OpenDaylight Controller functional modules. 68/68/1
authorMadhu Venugopal <vmadhu@cisco.com>
Fri, 22 Mar 2013 22:47:35 +0000 (15:47 -0700)
committerMadhu Venugopal <vmadhu@cisco.com>
Fri, 22 Mar 2013 22:47:35 +0000 (15:47 -0700)
Change-Id: I1cd6668738099e8db3cfe83f812a92c922ced38c
Signed-off-by: Madhu Venugopal <vmadhu@cisco.com>
380 files changed:
opendaylight/arphandler/pom.xml [new file with mode: 0644]
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java [new file with mode: 0644]
opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java [new file with mode: 0644]
opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java [new file with mode: 0644]
opendaylight/configuration/api/pom.xml [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAware.java [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAwareCommon.java [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerAware.java [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationService.java [new file with mode: 0644]
opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationServiceCommon.java [new file with mode: 0644]
opendaylight/configuration/implementation/pom.xml [new file with mode: 0644]
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/Activator.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java [new file with mode: 0644]
opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java [new file with mode: 0644]
opendaylight/containermanager/api/pom.xml [new file with mode: 0644]
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerAuthorization.java [new file with mode: 0644]
opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java [new file with mode: 0644]
opendaylight/containermanager/implementation/pom.xml [new file with mode: 0644]
opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/Activator.java [new file with mode: 0644]
opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerImpl.java [new file with mode: 0644]
opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java [new file with mode: 0644]
opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java [new file with mode: 0644]
opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java [new file with mode: 0644]
opendaylight/distribution/opendaylight/pom.xml
opendaylight/distribution/sdk/pom.xml
opendaylight/forwarding/staticrouting/pom.xml [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IStaticRoutingAware.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRoute.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/Activator.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java [new file with mode: 0644]
opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/pom.xml [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntryInstall.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManager.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/IForwardingRulesManagerAware.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroup.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupChangeListener.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupConfig.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/PortGroupProvider.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/Activator.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/internal/ForwardingRulesManagerImpl.java [new file with mode: 0644]
opendaylight/forwardingrulesmanager/src/test/java/org/opendaylight/controller/forwardingrulesmanager/frmTest.java [new file with mode: 0644]
opendaylight/hosttracker/pom.xml [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/HostTracker.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/HostTrackerCallable.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/IfHostListener.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/IfIptoHost.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/IfNewHostNotify.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnector.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/hostAware/IHostFinder.java [new file with mode: 0644]
opendaylight/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/internal/Activator.java [new file with mode: 0644]
opendaylight/hosttracker/src/test/java/org/opendaylight/controller/hosttracker/HostTrackerTest.java [new file with mode: 0644]
opendaylight/hosttracker/src/test/java/org/opendaylight/controller/hosttracker/hostAware/HostNodeConnectorTest.java [new file with mode: 0644]
opendaylight/northbound/commons/pom.xml [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/AuthenticationProviderWrapper.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/RestMessages.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/WebSecurityContextRepository.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/InternalServerErrorException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/MethodNotAllowed.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/MethodNotAllowedException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/NotAcceptableException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/ResourceConflictException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/ResourceForbiddenException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/ResourceGoneException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/ResourceNotFoundException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/ServiceUnavailableException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/UnauthorizedException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/UnsupportedMediaTypeException.java [new file with mode: 0644]
opendaylight/northbound/commons/src/main/java/org/opendaylight/controller/northbound/commons/exception/package-info.java [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/pom.xml [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowConfigs.java [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthbound.java [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/java/org/opendaylight/controller/flowprogrammer/northbound/FlowProgrammerNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/flowprogrammer/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/hosttracker/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/hosttracker/pom.xml [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthbound.java [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/HostTrackerNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/java/org/opendaylight/controller/hosttracker/northbound/Hosts.java [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/hosttracker/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/integrationtest/pom.xml [new file with mode: 0644]
opendaylight/northbound/integrationtest/src/test/resources/exam.properties [new file with mode: 0644]
opendaylight/northbound/integrationtest/src/test/resources/logback.xml [new file with mode: 0644]
opendaylight/northbound/staticrouting/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/staticrouting/pom.xml [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoute.java [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutes.java [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthbound.java [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/northbound/StaticRoutingNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/staticrouting/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/statistics/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/statistics/pom.xml [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/AllFlowStatistics.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/AllPortStatistics.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/FlowStatistics.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/PortStatistics.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthbound.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/java/org/opendaylight/controller/statistics/northbound/StatisticsNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/statistics/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/subnets/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/subnets/pom.xml [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetConfigs.java [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundJAXRS.java [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/java/org/opendaylight/controller/subnets/northbound/SubnetsNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/subnets/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/switchmanager/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/switchmanager/pom.xml [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectorProperties.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeConnectors.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/NodeProperties.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/Nodes.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthbound.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/northbound/SwitchNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/switchmanager/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northbound/topology/enunciate.xml [new file with mode: 0644]
opendaylight/northbound/topology/pom.xml [new file with mode: 0644]
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/EdgeProperties.java [new file with mode: 0644]
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/Topology.java [new file with mode: 0644]
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundJAXRS.java [new file with mode: 0644]
opendaylight/northbound/topology/src/main/java/org/opendaylight/controller/topology/northbound/TopologyNorthboundRSApplication.java [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/northbound/topology/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/northboundtest/unit_test_suite/pom.xml [new file with mode: 0644]
opendaylight/northboundtest/unit_test_suite/src/main/java/org/opendaylight/controller/northboundtest/unittestsuite/internal/API3UnitTest.java [new file with mode: 0644]
opendaylight/northboundtest/unit_test_suite/src/main/java/org/opendaylight/controller/northboundtest/unittestsuite/internal/Activator.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/pom.xml [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IDataPacketListen.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IDataPacketMux.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IInventoryShimExternalListener.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IInventoryShimInternalListener.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IOFInventoryService.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IOFStatisticsManager.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IPluginReadServiceFilter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/IRefreshInternalProvider.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/ITopologyServiceShimListener.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/IController.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/IMessageListener.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitch.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/ISwitchStateListener.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/Controller.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/ControllerIO.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/StatisticsCollector.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchEvent.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SwitchHandler.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/core/internal/SynchronousMessage.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Activator.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketMuxDemux.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DataPacketServices.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DescStatisticsConverter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/DiscoveryService.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowConverter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerService.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowStatisticsConverter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryService.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceHelper.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/InventoryServiceShim.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/OFStatisticsManager.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortConverter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/PortStatisticsConverter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadService.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/ReadServiceFilter.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServiceShim.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/TopologyServices.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/internal/Utils.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6FlowMod.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6Match.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6StatsReply.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/main/java/org/opendaylight/controller/protocol_plugin/openflow/vendorextension/v6extension/V6StatsRequest.java [new file with mode: 0644]
opendaylight/protocol_plugins/openflow/src/test/java/org/opendaylight/controller/protocol_plugin/openflow/internal/FlowProgrammerServiceTest.java [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/pom.xml [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/Activator.java [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/main/java/org/opendaylight/controller/routing/dijkstra_implementation/internal/DijkstraImplementation.java [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/main/resources/OSGI-INF/component-factory.xml [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/main/resources/OSGI-INF/component.xml [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/test/java/org/opendaylight/controller/routing/dijkstra_implementation/DijkstraTest.java [new file with mode: 0644]
opendaylight/routing/dijkstra_implementation/src/test/java/org/opendaylight/controller/routing/dijkstra_implementation/MaxThruputTest.java [new file with mode: 0644]
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/Match.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchField.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/match/MatchType.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/LLDPTLV.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/packet/address/EthernetAddress.java
opendaylight/sal/api/src/main/java/org/opendaylight/controller/sal/utils/HexEncode.java
opendaylight/samples/simpleforwarding/pom.xml [new file with mode: 0644]
opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/Activator.java [new file with mode: 0644]
opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/HostNodePair.java [new file with mode: 0644]
opendaylight/samples/simpleforwarding/src/main/java/org/opendaylight/controller/samples/simpleforwarding/internal/SimpleForwardingImpl.java [new file with mode: 0644]
opendaylight/samples/simpleforwarding/src/test/java/org/opendaylight/controller/samples/simpleforwarding/internal/HostSwitchTest.java [new file with mode: 0644]
opendaylight/statisticsmanager/pom.xml [new file with mode: 0644]
opendaylight/statisticsmanager/src/main/java/org/opendaylight/controller/statisticsmanager/IStatisticsManager.java [new file with mode: 0644]
opendaylight/statisticsmanager/src/main/java/org/opendaylight/controller/statisticsmanager/StatisticsManager.java [new file with mode: 0644]
opendaylight/statisticsmanager/src/main/java/org/opendaylight/controller/statisticsmanager/internal/Activator.java [new file with mode: 0644]
opendaylight/statisticsmanager/src/test/java/org/opendaylight/controller/statisticsmanager/StatisticsManagerTest.java [new file with mode: 0644]
opendaylight/switchmanager/pom.xml [new file with mode: 0755]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/IInventoryListener.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/ISpanAware.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManager.java [new file with mode: 0755]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/ISwitchManagerAware.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/SpanConfig.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/Subnet.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/SubnetConfig.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/Switch.java [new file with mode: 0755]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/SwitchConfig.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/Activator.java [new file with mode: 0644]
opendaylight/switchmanager/src/main/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImpl.java [new file with mode: 0755]
opendaylight/switchmanager/src/test/java/org/opendaylight/controller/switchmanager/SubnetTest.java [new file with mode: 0644]
opendaylight/switchmanager/src/test/java/org/opendaylight/controller/switchmanager/SwitchTest.java [new file with mode: 0644]
opendaylight/switchmanager/src/test/java/org/opendaylight/controller/switchmanager/internal/SwitchManagerImplTest.java [new file with mode: 0644]
opendaylight/topologymanager/pom.xml [new file with mode: 0755]
opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManager.java [new file with mode: 0644]
opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/ITopologyManagerAware.java [new file with mode: 0644]
opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/TopologyUserLinkConfig.java [new file with mode: 0644]
opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/Activator.java [new file with mode: 0644]
opendaylight/topologymanager/src/main/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImpl.java [new file with mode: 0644]
opendaylight/topologymanager/src/test/java/org/opendaylight/controller/topologymanager/internal/TopologyManagerImplTest.java [new file with mode: 0644]
opendaylight/usermanager/pom.xml [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/AuthResponse.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IAAAProvider.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ISessionManager.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/IUserManager.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/ODLUserLevel.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/Activator.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUser.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/AuthorizationConfig.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/ServerConfig.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserConfig.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/internal/UserManagerImpl.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/SessionManager.java [new file with mode: 0644]
opendaylight/usermanager/src/main/java/org/opendaylight/controller/usermanager/security/UserSecurityContextRepository.java [new file with mode: 0644]
opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/AuthResponseTest.java [new file with mode: 0644]
opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthenticatedUserTest.java [new file with mode: 0644]
opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/AuthorizationUserConfigTest.java [new file with mode: 0644]
opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/ServerConfigTest.java [new file with mode: 0644]
opendaylight/usermanager/src/test/java/org/opendaylight/controller/usermanager/internal/UserManagerImplTest.java [new file with mode: 0644]
opendaylight/web/devices/pom.xml [new file with mode: 0644]
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/Devices.java [new file with mode: 0644]
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/DevicesJsonBean.java [new file with mode: 0644]
opendaylight/web/devices/src/main/java/org/opendaylight/controller/devices/web/StatusJsonBean.java [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/WEB-INF/Devices-servlet.xml [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/web/devices/src/main/resources/js/page.js [new file with mode: 0644]
opendaylight/web/flows/pom.xml [new file with mode: 0644]
opendaylight/web/flows/src/main/java/org/opendaylight/controller/flows/web/Flows.java [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/WEB-INF/Flows-servlet.xml [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/web/flows/src/main/resources/js/page.js [new file with mode: 0644]
opendaylight/web/root/pom.xml [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/AuthenticationProviderWrapper.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerAuthenticationSuccessHandler.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerCustomFilter.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerLoginUrlAuthEntryPoint.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerLogoutHandler.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerUISessionManager.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerUserDetailsService.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/ControllerWebSecurityContextRepository.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/IOneWeb.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/OneWeb.java [new file with mode: 0644]
opendaylight/web/root/src/main/java/org/opendaylight/controller/web/OneWebAdmin.java [new file with mode: 0644]
opendaylight/web/root/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/web/root/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/web/root/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/web/root/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/RootGUI-servlet.xml [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/jsp/login.jsp [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/jsp/main.jsp [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/web/root/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/web/root/src/main/resources/css/bootstrap.min.css [new file with mode: 0644]
opendaylight/web/root/src/main/resources/css/login.less [new file with mode: 0644]
opendaylight/web/root/src/main/resources/css/one.less [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/Device_pc_3045_default_64.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/Device_switch_3062_unknown_64.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/Expand16T.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/Key_0024_16.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/alert_unreachable_2008_128.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/logo.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/open_1054_16.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/open_1054_24.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/save_as_0106_16.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/save_as_0106_24.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/topology_view_1033_128.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/user_0020_16.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/user_0020_24.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/user_group_0107_16.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/img/user_group_0107_24.png [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/bootstrap.min.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/jit.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/jquery-1.9.1.min.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/less-1.3.3.min.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/one-topology.js [new file with mode: 0644]
opendaylight/web/root/src/main/resources/js/one.js [new file with mode: 0644]
opendaylight/web/topology/pom.xml [new file with mode: 0644]
opendaylight/web/topology/src/main/java/org/opendaylight/controller/topology/web/Topology.java [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/WEB-INF/Topology-servlet.xml [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/web/topology/src/main/resources/js/page.js [new file with mode: 0644]
opendaylight/web/topology/src/test/java/org/opendaylight/controller/topology/web/TopologyTest.java [new file with mode: 0644]
opendaylight/web/troubleshoot/pom.xml [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/Troubleshoot.java [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/java/org/opendaylight/controller/troubleshoot/web/TroubleshootingJsonBean.java [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/META-INF/spring.factories [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/META-INF/spring.handlers [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/META-INF/spring.schemas [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/META-INF/spring.tooling [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/WEB-INF/Troubleshoot-servlet.xml [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/WEB-INF/spring/context.xml [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/WEB-INF/spring/servlet/security.xml [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/WEB-INF/web.xml [new file with mode: 0644]
opendaylight/web/troubleshoot/src/main/resources/js/page.js [new file with mode: 0644]

diff --git a/opendaylight/arphandler/pom.xml b/opendaylight/arphandler/pom.xml
new file mode 100644 (file)
index 0000000..cf3aff7
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>arphandler</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+       <groupId>org.apache.felix</groupId>
+       <artifactId>maven-bundle-plugin</artifactId>
+       <version>2.3.6</version>
+       <extensions>true</extensions>
+       <configuration>
+         <instructions>
+           <Import-Package>
+                 org.opendaylight.controller.sal.core,
+             org.opendaylight.controller.sal.utils,
+             org.opendaylight.controller.sal.packet,
+          org.opendaylight.controller.switchmanager,
+          org.opendaylight.controller.hosttracker,
+             org.opendaylight.controller.hosttracker.hostAware,
+          org.apache.felix.dm,
+          org.osgi.service.component,
+             org.slf4j
+           </Import-Package>
+        <Bundle-Activator>
+          org.opendaylight.controller.arphandler.internal.Activator
+               </Bundle-Activator>
+         </instructions>
+       </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/Activator.java
new file mode 100644 (file)
index 0000000..e886813
--- /dev/null
@@ -0,0 +1,104 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.arphandler.internal;
+
+import java.util.Hashtable;
+import java.util.Dictionary;
+import org.apache.felix.dm.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.hosttracker.IfHostListener;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.hostAware.IHostFinder;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { ArpHandler.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(ArpHandler.class)) {
+            // export the service
+            Dictionary<String, String> props = new Hashtable<String, String>();
+            props.put("salListenerName", "arphandler");
+            c.setInterface(new String[] { IHostFinder.class.getName(),
+                    IListenDataPacket.class.getName() }, props);
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    ISwitchManager.class).setCallbacks("setSwitchManager",
+                    "unsetSwitchManager").setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IDataPacketService.class).setCallbacks(
+                    "setDataPacketService", "unsetDataPacketService")
+                    .setRequired(true));
+
+            // the Host Listener is optional
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IfHostListener.class).setCallbacks("setHostListener",
+                    "unsetHostListener").setRequired(false));
+
+            // the IfIptoHost is a required dependency
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IfIptoHost.class).setCallbacks("setHostTracker",
+                    "unsetHostTracker").setRequired(true));
+        }
+    }
+}
diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java
new file mode 100644 (file)
index 0000000..a9667d8
--- /dev/null
@@ -0,0 +1,506 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+/*
+ *
+ */
+package org.opendaylight.controller.arphandler.internal;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.hosttracker.IfHostListener;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.hosttracker.hostAware.IHostFinder;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.packet.ARP;
+import org.opendaylight.controller.sal.packet.BitBufferHelper;
+import org.opendaylight.controller.sal.packet.Ethernet;
+import org.opendaylight.controller.sal.packet.IDataPacketService;
+import org.opendaylight.controller.sal.packet.IListenDataPacket;
+import org.opendaylight.controller.sal.packet.IPv4;
+import org.opendaylight.controller.sal.packet.Packet;
+import org.opendaylight.controller.sal.packet.PacketResult;
+import org.opendaylight.controller.sal.packet.RawPacket;
+import org.opendaylight.controller.sal.utils.EtherTypes;
+import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.NetUtils;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.Subnet;
+
+public class ArpHandler implements IHostFinder, IListenDataPacket {
+    private static final Logger logger = LoggerFactory
+            .getLogger(ArpHandler.class);
+    private IfIptoHost hostTracker = null;
+    private ISwitchManager switchManager = null;
+    private IDataPacketService dataPacketService = null;
+    private Set<IfHostListener> hostListener = Collections
+            .synchronizedSet(new HashSet<IfHostListener>());
+
+    void setHostListener(IfHostListener s) {
+        if (this.hostListener != null) {
+            this.hostListener.add(s);
+        }
+    }
+
+    void unsetHostListener(IfHostListener s) {
+        if (this.hostListener != null) {
+            this.hostListener.remove(s);
+        }
+    }
+
+    void setDataPacketService(IDataPacketService s) {
+        this.dataPacketService = s;
+    }
+
+    void unsetDataPacketService(IDataPacketService s) {
+        if (this.dataPacketService == s) {
+            this.dataPacketService = s;
+        }
+    }
+
+    public IfIptoHost getHostTracker() {
+        return hostTracker;
+    }
+
+    public void setHostTracker(IfIptoHost hostTracker) {
+        logger.debug("Setting HostTracker");
+        this.hostTracker = hostTracker;
+    }
+
+    public void unsetHostTracker(IfIptoHost s) {
+        logger.debug("UNSetting HostTracker");
+        if (this.hostTracker == s) {
+            this.hostTracker = null;
+        }
+    }
+
+    protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP,
+            byte[] tMAC, InetAddress tIP) {
+        byte[] senderIP = sIP.getAddress();
+        byte[] targetIP = tIP.getAddress();
+        ARP arp = new ARP();
+        arp.setHardwareType(ARP.HW_TYPE_ETHERNET).setProtocolType(
+                EtherTypes.IPv4.shortValue())
+                .setHardwareAddressLength((byte) 6).setProtocolAddressLength(
+                        (byte) 4).setOpCode(ARP.REPLY)
+                .setSenderHardwareAddress(sMAC).setSenderProtocolAddress(
+                        senderIP).setTargetHardwareAddress(tMAC)
+                .setTargetProtocolAddress(targetIP);
+
+        Ethernet ethernet = new Ethernet();
+        ethernet.setSourceMACAddress(sMAC).setDestinationMACAddress(tMAC)
+                .setEtherType(EtherTypes.ARP.shortValue()).setPayload(arp);
+
+        RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
+        destPkt.setOutgoingNodeConnector(p);
+
+        this.dataPacketService.transmitDataPacket(destPkt);
+    }
+
+    private boolean isBroadcastMAC(byte[] mac) {
+        if (BitBufferHelper.toNumber(mac) == 0xffffffffffffL) { //TODO: implement this in our Ethernet
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isUnicastMAC(byte[] mac) {
+        if ((BitBufferHelper.toNumber(mac) & 0x010000000000L) == 0) {
+            return true;
+        }
+        return false;
+    }
+
+    protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p) {
+        if (pkt.getOpCode() == 0x1) {
+            logger.debug("Received ARP REQUEST Packet from NodeConnector:" + p);
+        } else {
+            logger.debug("Received ARP REPLY Packet from NodeConnector:" + p);
+        }
+        InetAddress targetIP = null;
+        try {
+            targetIP = InetAddress.getByAddress(pkt.getTargetProtocolAddress());
+        } catch (UnknownHostException e1) {
+            return;
+        }
+        InetAddress sourceIP = null;
+        try {
+            sourceIP = InetAddress.getByAddress(pkt.getSenderProtocolAddress());
+        } catch (UnknownHostException e1) {
+            return;
+        }
+        byte[] targetMAC = eHeader.getDestinationMACAddress();
+        byte[] sourceMAC = eHeader.getSourceMACAddress();
+
+        /*
+         * Sanity Check; drop ARP packets originated by the controller itself.
+         * This is to avoid continuous flooding
+         */
+        if (Arrays.equals(sourceMAC, getControllerMAC())) {
+            logger.debug(
+                    "Receive the self originated packet (srcMAC {}) --> DROP",
+                    HexEncode.bytesToHexString(sourceMAC));
+            return;
+        }
+
+        Subnet subnet = null;
+        if (switchManager != null) {
+            subnet = switchManager.getSubnetByNetworkAddress(sourceIP);
+        }
+        if (subnet == null) {
+            logger.debug("can't find subnet matching {}, drop packet", sourceIP
+                    .toString());
+            return;
+        }
+        logger.debug("Found {} matching {}", subnet.toString(), sourceIP
+                .toString());
+        /*
+         * Make sure that the host is a legitimate member of this subnet
+         */
+        if (!subnet.hasNodeConnector(p)) {
+            logger.debug("{} showing up on {} does not belong to {}",
+                    new Object[] { sourceIP.toString(), p, subnet.toString() });
+            return;
+        }
+
+        if (isUnicastMAC(sourceMAC)) {
+            // TODO For not this is only OPENFLOW but we need to fix this
+            if (p.getType().equals(
+                    NodeConnector.NodeConnectorIDType.OPENFLOW)) {
+                HostNodeConnector host = null;
+                try {
+                    host = new HostNodeConnector(sourceMAC, sourceIP, p, subnet
+                            .getVlan());
+                } catch (ConstructionException e) {
+                    return;
+                }
+                /*
+                 * Learn host from the received ARP REQ/REPLY, inform
+                 * Host Tracker
+                 */
+                logger.debug("Inform Host tracker of new host {}", host);
+                synchronized (this.hostListener) {
+                    for (IfHostListener listener : this.hostListener) {
+                        listener.hostListener(host);
+                    }
+                }
+            }
+        }
+        /*
+         * No further action is needed if this is a gratuitous ARP
+         */
+        if (sourceIP.equals(targetIP)) {
+            return;
+        }
+
+        /*
+         * No further action is needed if this is a ARP Reply
+         */
+        if (pkt.getOpCode() != ARP.REQUEST) {
+            return;
+        }
+        /*
+         * ARP Request Handling:
+         * If targetIP is the IP of the subnet, reply with ARP REPLY
+         * If targetIP is a known host, PROXY ARP (by sending ARP REPLY) on behalf of known target hosts.
+         * For unknown target hosts, generate and send an ARP request to ALL switches/ports using
+         * the IP address defined in the subnet as source address
+         */
+        /*
+         * Send ARP reply if target IP is gateway IP
+         */
+        if ((targetIP.equals(subnet.getNetworkAddress()))
+                && (isBroadcastMAC(targetMAC) || Arrays.equals(targetMAC,
+                        getControllerMAC()))) {
+            sendARPReply(p, getControllerMAC(), targetIP, pkt
+                    .getSenderHardwareAddress(), sourceIP);
+            return;
+        }
+
+        /*
+         * unknown host, initiate ARP request
+         */
+        HostNodeConnector host = hostTracker.hostQuery(targetIP);
+        if (host == null) {
+            sendBcastARPRequest(targetIP, subnet);
+            return;
+        }
+        /*
+         * Known target host, send ARP REPLY
+         * make sure that targetMAC matches the host's MAC if it is not broadcastMAC
+         */
+        if (isBroadcastMAC(targetMAC)
+                || Arrays.equals(host.getDataLayerAddressBytes(), targetMAC)) {
+            sendARPReply(p, host.getDataLayerAddressBytes(), host
+                    .getNetworkAddress(), pkt.getSenderHardwareAddress(),
+                    sourceIP);
+            return;
+        } else {
+            /*
+             * target target MAC has been changed. For now, discard it.
+             * TODO: We may need to send unicast ARP REQUEST on behalf of the
+             * target back to the sender to trigger the sender to
+             * update its table
+             */
+            return;
+        }
+    }
+
+    /*
+     *  Send a broadcast ARP Request to the switch/ ports  using
+     *  the networkAddress of the subnet as sender IP
+     *  the controller's MAC as sender MAC
+     *  the targetIP as the target Network Address
+     */
+    protected void sendBcastARPRequest(InetAddress targetIP, Subnet subnet) {
+        Set<NodeConnector> nodeConnectors;
+        if (subnet.isFlatLayer2()) {
+            nodeConnectors = new HashSet<NodeConnector>();
+            for (Node n : this.switchManager.getNodes()) {
+                nodeConnectors.addAll(this.switchManager
+                        .getUpNodeConnectors(n));
+            }
+        } else {
+            nodeConnectors = subnet.getNodeConnectors();
+        }
+        for (NodeConnector p : nodeConnectors) {
+            ARP arp = new ARP();
+            byte[] senderIP = subnet.getNetworkAddress().getAddress();
+            byte[] targetIPB = targetIP.getAddress();
+            arp.setHardwareType(ARP.HW_TYPE_ETHERNET).setProtocolType(
+                    EtherTypes.IPv4.shortValue()).setHardwareAddressLength(
+                    (byte) 6).setProtocolAddressLength((byte) 4).setOpCode(
+                    ARP.REQUEST).setSenderHardwareAddress(getControllerMAC())
+                    .setSenderProtocolAddress(senderIP)
+                    .setTargetHardwareAddress(
+                            new byte[] { (byte) 0, (byte) 0, (byte) 0,
+                                    (byte) 0, (byte) 0, (byte) 0 })
+                    .setTargetProtocolAddress(targetIPB);
+
+            Ethernet ethernet = new Ethernet();
+            ethernet.setSourceMACAddress(getControllerMAC())
+                    .setDestinationMACAddress(
+                            new byte[] { (byte) -1, (byte) -1, (byte) -1,
+                                    (byte) -1, (byte) -1, (byte) -1 })
+                    .setEtherType(EtherTypes.ARP.shortValue()).setPayload(arp);
+
+            // TODO For now send port-by-port, see how to optimize to
+            // send to a bunch of port on the same node in a shoot
+            RawPacket destPkt = this.dataPacketService
+                    .encodeDataPacket(ethernet);
+            destPkt.setOutgoingNodeConnector(p);
+
+            this.dataPacketService.transmitDataPacket(destPkt);
+        }
+    }
+
+    /*
+     * Send a unicast ARP Request to the known host on a specific switch/port as
+     * defined in the host.
+     * The sender IP is the networkAddress of the subnet
+     * The sender MAC is the controller's MAC
+     */
+    protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) {
+        //Long swID = host.getnodeconnectornodeId();
+        //Short portID = host.getnodeconnectorportId();
+        //Node n = NodeCreator.createOFNode(swID);
+        Node n = host.getnodeconnectorNode();
+        if (n == null) {
+            logger.error("cannot send UcastARP because cannot extract node "
+                    + "from HostNodeConnector:" + host);
+            return;
+        }
+        NodeConnector outPort = host.getnodeConnector();
+        if (outPort == null) {
+            logger.error("cannot send UcastARP because cannot extract "
+                    + "outPort from HostNodeConnector:" + host);
+            return;
+        }
+
+        byte[] senderIP = subnet.getNetworkAddress().getAddress();
+        byte[] targetIP = host.getNetworkAddress().getAddress();
+        byte[] targetMAC = host.getDataLayerAddressBytes();
+        ARP arp = new ARP();
+        arp.setHardwareType(ARP.HW_TYPE_ETHERNET).setProtocolType(
+                EtherTypes.IPv4.shortValue())
+                .setHardwareAddressLength((byte) 6).setProtocolAddressLength(
+                        (byte) 4).setOpCode(ARP.REQUEST)
+                .setSenderHardwareAddress(getControllerMAC())
+                .setSenderProtocolAddress(senderIP).setTargetHardwareAddress(
+                        targetMAC).setTargetProtocolAddress(targetIP);
+
+        Ethernet ethernet = new Ethernet();
+        ethernet.setSourceMACAddress(getControllerMAC())
+                .setDestinationMACAddress(targetMAC).setEtherType(
+                        EtherTypes.ARP.shortValue()).setPayload(arp);
+
+        RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet);
+        destPkt.setOutgoingNodeConnector(outPort);
+
+        this.dataPacketService.transmitDataPacket(destPkt);
+    }
+
+    public void find(InetAddress networkAddress) {
+        logger.debug("Received find IP {}", networkAddress.toString());
+
+        Subnet subnet = null;
+        if (switchManager != null) {
+            subnet = switchManager.getSubnetByNetworkAddress(networkAddress);
+        }
+        if (subnet == null) {
+            logger.debug("can't find subnet matching IP {}", networkAddress
+                    .toString());
+            return;
+        }
+        logger.debug("found subnet {}", subnet.toString());
+
+        // send a broadcast ARP Request to this interface
+        sendBcastARPRequest(networkAddress, subnet);
+    }
+
+    /*
+     * Probe the host by sending a unicast ARP Request to the host
+     */
+    public void probe(HostNodeConnector host) {
+        logger.debug("Received probe host {}", host);
+
+        Subnet subnet = null;
+        if (switchManager != null) {
+            subnet = switchManager.getSubnetByNetworkAddress(host
+                    .getNetworkAddress());
+        }
+        if (subnet == null) {
+            logger.debug("can't find subnet matching {}", host
+                    .getNetworkAddress().toString());
+            return;
+        }
+        sendUcastARPRequest(host, subnet);
+    }
+
+    /*
+     * An IP packet is punted to the controller, this means that the
+     * destination host is not known to the controller.
+     * Need to discover it by sending a Broadcast ARP Request
+     */
+    protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p) {
+        InetAddress dIP = null;
+        try {
+            dIP = InetAddress.getByAddress(NetUtils.intToByteArray4(pkt
+                    .getDestinationAddress()));
+        } catch (UnknownHostException e1) {
+            return;
+        }
+
+        Subnet subnet = null;
+        if (switchManager != null) {
+            subnet = switchManager.getSubnetByNetworkAddress(dIP);
+        }
+        if (subnet == null) {
+            logger.debug("can't find subnet matching {}, drop packet", dIP
+                    .toString());
+            return;
+        }
+        logger.debug("Found {} matching {}", subnet.toString(), dIP.toString());
+        /*
+         * unknown destination host, initiate ARP request
+         */
+        sendBcastARPRequest(dIP, subnet);
+        return;
+    }
+
+    public byte[] getControllerMAC() {
+        if (switchManager == null) {
+            return null;
+        }
+        return switchManager.getControllerMAC();
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init() {
+    }
+
+    /**
+     * Function called by the dependency manager when at least one
+     * dependency become unsatisfied or when the component is shutting
+     * down because for example bundle is being stopped.
+     *
+     */
+    void destroy() {
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called
+     * and after the services provided by the class are registered in
+     * the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services
+     * exported by the component are unregistered, this will be
+     * followed by a "destroy ()" calls
+     *
+     */
+    void stop() {
+    }
+
+    void setSwitchManager(ISwitchManager s) {
+        logger.debug("SwitchManager set");
+        this.switchManager = s;
+    }
+
+    void unsetSwitchManager(ISwitchManager s) {
+        if (this.switchManager == s) {
+            logger.debug("SwitchManager removed!");
+            this.switchManager = null;
+        }
+    }
+
+    @Override
+    public PacketResult receiveDataPacket(RawPacket inPkt) {
+        if (inPkt == null) {
+            return PacketResult.IGNORED;
+        }
+        logger
+                .trace("Received a frame of size:"
+                        + inPkt.getPacketData().length);
+        Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt);
+        if (formattedPak instanceof Ethernet) {
+            Object nextPak = formattedPak.getPayload();
+            if (nextPak instanceof IPv4) {
+                handlePuntedIPPacket((IPv4) nextPak, inPkt
+                        .getIncomingNodeConnector());
+                logger.trace("Handled IP packet");
+            }
+            if (nextPak instanceof ARP) {
+                handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt
+                        .getIncomingNodeConnector());
+                logger.trace("Handled ARP packet");
+            }
+        }
+        return PacketResult.IGNORED;
+    }
+}
diff --git a/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java b/opendaylight/arphandler/src/test/java/org/opendaylight/controller/arphandler/internal/ArphandlerTest.java
new file mode 100644 (file)
index 0000000..b863d2b
--- /dev/null
@@ -0,0 +1,52 @@
+\r
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.arphandler.internal;\r
+\r
+\r
+import org.junit.Assert;\r
+import org.junit.Test;\r
+import junit.framework.TestCase;\r
+\r
+import org.opendaylight.controller.hosttracker.IfIptoHost;\r
+import org.opendaylight.controller.hosttracker.HostTracker;\r
+\r
+import org.opendaylight.controller.switchmanager.ISwitchManager;\r
+import org.opendaylight.controller.switchmanager.internal.SwitchManagerImpl;\r
+\r
+\r
+public class ArphandlerTest extends TestCase {\r
+        \r
+       @Test\r
+       public void testArphandlerCreation() {\r
+                       \r
+               ArpHandler ah = null;\r
+               ah = new ArpHandler();\r
+               Assert.assertTrue(ah != null);\r
+                       \r
+               HostTracker hostTracker = null;\r
+               hostTracker = new HostTracker();\r
+               ah.setHostTracker(hostTracker);\r
+               IfIptoHost ht= ah.getHostTracker();\r
+               Assert.assertTrue(ht.equals(hostTracker));\r
+               ah.unsetHostTracker(hostTracker);\r
+               ht= ah.getHostTracker();\r
+               Assert.assertTrue(ht == null);\r
+               \r
+               ah.setHostListener(hostTracker);\r
+               ah.unsetHostListener(hostTracker);\r
+               \r
+               ISwitchManager swManager = new SwitchManagerImpl();\r
+               ah.setSwitchManager(swManager);\r
+               ah.unsetSwitchManager(swManager);\r
+               \r
+       }\r
+\r
+\r
+}\r
diff --git a/opendaylight/configuration/api/pom.xml b/opendaylight/configuration/api/pom.xml
new file mode 100644 (file)
index 0000000..0af960d
--- /dev/null
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>configuration</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+       <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+       <configuration>
+         <instructions>
+           <Import-Package>
+              org.opendaylight.controller.sal.utils,
+              org.apache.commons.lang3.builder
+           </Import-Package>
+           <Export-Package>
+              org.opendaylight.controller.configuration
+           </Export-Package>
+         </instructions>
+       </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+       <dependency>
+               <groupId>org.opendaylight.controller</groupId>
+               <artifactId>sal</artifactId>
+               <version>0.4.0-SNAPSHOT</version>
+       </dependency> 
+  </dependencies>
+</project>
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAware.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAware.java
new file mode 100644 (file)
index 0000000..69c2594
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+
+/**
+ * Listener Interface for receiving Configuration events.
+ *
+ *
+ */
+public interface IConfigurationAware extends IConfigurationAwareCommon {
+}
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAwareCommon.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationAwareCommon.java
new file mode 100644 (file)
index 0000000..57a648b
--- /dev/null
@@ -0,0 +1,26 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+import org.opendaylight.controller.sal.utils.Status;
+
+
+/**
+ * Listener Interface for receiving Configuration events.
+ *
+ *
+ */
+public interface IConfigurationAwareCommon {
+
+    /**
+     * Trigger from configuration component to persist the configuration state.
+     */
+    public Status saveConfiguration();
+}
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerAware.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerAware.java
new file mode 100644 (file)
index 0000000..ac1aabe
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+
+/**
+ * Listener Interface for receiving Configuration events.
+ *
+ *
+ */
+public interface IConfigurationContainerAware extends IConfigurationAwareCommon {
+}
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationContainerService.java
new file mode 100644 (file)
index 0000000..fb5be35
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+/**
+ * Container Manager interface
+ *
+ *
+ */
+public interface IConfigurationContainerService extends
+        IConfigurationServiceCommon {
+}
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationService.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationService.java
new file mode 100644 (file)
index 0000000..c6a0183
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+
+/**
+ * Container Manager interface
+ *
+ *
+ */
+public interface IConfigurationService extends IConfigurationServiceCommon {
+}
diff --git a/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationServiceCommon.java b/opendaylight/configuration/api/src/main/java/org/opendaylight/controller/configuration/IConfigurationServiceCommon.java
new file mode 100644 (file)
index 0000000..fc9c5ac
--- /dev/null
@@ -0,0 +1,21 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration;
+
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * Container Manager interface
+ *
+ *
+ */
+public interface IConfigurationServiceCommon {
+    public Status saveConfigurations();
+}
diff --git a/opendaylight/configuration/implementation/pom.xml b/opendaylight/configuration/implementation/pom.xml
new file mode 100644 (file)
index 0000000..bac0184
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>configuration.implementation</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.configuration,
+              org.opendaylight.controller.clustering.services,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.controller.sal.core,
+              org.osgi.framework,
+              org.slf4j,
+              org.apache.felix.dm
+            </Import-Package>
+            <Export-Package>
+            </Export-Package>
+            <Bundle-Activator>
+              org.opendaylight.controller.configuration.internal.Activator
+            </Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+       <dependency>
+               <groupId>org.opendaylight.controller</groupId>
+               <artifactId>sal</artifactId>
+               <version>0.4.0-SNAPSHOT</version>
+       </dependency> 
+  </dependencies>
+</project>
diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/Activator.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/Activator.java
new file mode 100644 (file)
index 0000000..9fb5b15
--- /dev/null
@@ -0,0 +1,137 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.configuration.IConfigurationService;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @file Activator.java
+ *
+ * @brief Component Activator for Configuration Management.
+ *
+ *
+ *
+ */
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { ConfigurationContainerImpl.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(ConfigurationContainerImpl.class)) {
+            // export the service
+            c.setInterface(new String[] {
+                    IConfigurationContainerService.class.getName(),
+                    IConfigurationAware.class.getName() }, null);
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IConfigurationContainerAware.class).setCallbacks(
+                    "addConfigurationContainerAware",
+                    "removeConfigurationContainerAware").setRequired(false));
+        }
+    }
+
+    /**
+     * Method which tells how many Global implementations are
+     * supported by the bundle. This way we can tune the number of
+     * components created. This components will be created ONLY at the
+     * time of bundle startup and will be destroyed only at time of
+     * bundle destruction, this is the major difference with the
+     * implementation retrieved via getImplementations where all of
+     * them are assumed to be in a container!
+     *
+     *
+     * @return The list of implementations the bundle will support,
+     * in Global version
+     */
+    protected Object[] getGlobalImplementations() {
+        Object[] res = { ConfigurationImpl.class };
+        return res;
+    }
+
+    /**
+     * Configure the dependency for a given instance Global
+     *
+     * @param c Component assigned for this instance, this will be
+     * what will be used for configuration
+     * @param imp implementation to be configured
+     * @param containerName container on which the configuration happens
+     */
+    protected void configureGlobalInstance(Component c, Object imp) {
+        if (imp.equals(ConfigurationImpl.class)) {
+
+            // export the service
+            c.setInterface(
+                    new String[] { IConfigurationService.class.getName() },
+                    null);
+
+            c.add(createServiceDependency().setService(
+                    IClusterGlobalServices.class).setCallbacks(
+                    "setClusterServices", "unsetClusterServices").setRequired(
+                    true));
+
+            c.add(createServiceDependency().setService(
+                    IConfigurationAware.class).setCallbacks(
+                    "addConfigurationAware", "removeConfigurationAware")
+                    .setRequired(false));
+        }
+    }
+}
diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImpl.java
new file mode 100644 (file)
index 0000000..efe966b
--- /dev/null
@@ -0,0 +1,108 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.configuration.IConfigurationContainerService;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @file   ConfigurationImpl.java
+ *
+ * @brief  Backend functionality for all Configuration related tasks.
+ *
+ *
+ */
+
+public class ConfigurationContainerImpl implements
+        IConfigurationContainerService, IConfigurationAware {
+    private static final Logger logger = LoggerFactory
+            .getLogger(ConfigurationContainerImpl.class);
+    private IClusterGlobalServices clusterServices;
+    /*
+     * Collection containing the configuration objects.
+     * This is configuration world: container names (also the map key)
+     * are maintained as they were configured by user, same case
+     */
+    private Set<IConfigurationContainerAware> configurationAwareList = (Set<IConfigurationContainerAware>) Collections
+            .synchronizedSet(new HashSet<IConfigurationContainerAware>());
+
+    public void addConfigurationContainerAware(
+            IConfigurationContainerAware configurationAware) {
+        if (!this.configurationAwareList.contains(configurationAware)) {
+            this.configurationAwareList.add(configurationAware);
+        }
+    }
+
+    public int getConfigurationAwareListSize() {
+       return this.configurationAwareList.size();
+    }
+    
+    public void removeConfigurationContainerAware(
+            IConfigurationContainerAware configurationAware) {
+        this.configurationAwareList.remove(configurationAware);
+    }
+
+    public void setClusterServices(IClusterGlobalServices i) {
+        this.clusterServices = i;
+        logger.debug("IClusterServices set");
+    }
+
+    public void unsetClusterServices(IClusterGlobalServices i) {
+        if (this.clusterServices == i) {
+            this.clusterServices = null;
+            logger.debug("IClusterServices Unset");
+        }
+    }
+
+    public void init() {
+    }
+
+    public void destroy() {
+        // Clear local states
+        this.configurationAwareList.clear();
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        boolean success = true;
+        for (IConfigurationContainerAware configurationAware : configurationAwareList) {
+            logger.info("Save Config triggered for "
+                    + configurationAware.getClass().getSimpleName());
+
+            Status status = configurationAware.saveConfiguration();
+            if (!status.isSuccess()) {
+               success = false;
+               logger.info("Failed to save config for "
+                               + configurationAware.getClass().getSimpleName());
+            }
+        }
+        if (success) {
+            return new Status(StatusCode.SUCCESS, null);
+        } else {
+            return new Status(StatusCode.INTERNALERROR,
+                       "Failed to Save All Configurations");
+        }
+    }
+
+    @Override
+    public Status saveConfigurations() {
+        return saveConfiguration();
+    }
+}
diff --git a/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java b/opendaylight/configuration/implementation/src/main/java/org/opendaylight/controller/configuration/internal/ConfigurationImpl.java
new file mode 100644 (file)
index 0000000..a8f7da6
--- /dev/null
@@ -0,0 +1,99 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.configuration.IConfigurationService;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @file   ConfigurationImpl.java
+ *
+ * @brief  Backend functionality for all Configuration related tasks.
+ *
+ *
+ */
+
+public class ConfigurationImpl implements IConfigurationService {
+    private static final Logger logger = LoggerFactory
+            .getLogger(ConfigurationImpl.class);
+    private IClusterGlobalServices clusterServices;
+    /*
+     * Collection containing the configuration objects.
+     * This is configuration world: container names (also the map key)
+     * are maintained as they were configured by user, same case
+     */
+    private Set<IConfigurationAware> configurationAwareList = (Set<IConfigurationAware>) Collections
+            .synchronizedSet(new HashSet<IConfigurationAware>());
+
+    
+    public int getConfigurationAwareListSize() {
+       return this.configurationAwareList.size();
+    }
+    
+    public void addConfigurationAware(IConfigurationAware configurationAware) {
+        if (!this.configurationAwareList.contains(configurationAware)) {
+            this.configurationAwareList.add(configurationAware);
+        }
+    }
+
+    public void removeConfigurationAware(IConfigurationAware configurationAware) {
+        this.configurationAwareList.remove(configurationAware);
+    }
+
+    public void setClusterServices(IClusterGlobalServices i) {
+        this.clusterServices = i;
+        logger.debug("IClusterServices set");
+    }
+
+    public void unsetClusterServices(IClusterGlobalServices i) {
+        if (this.clusterServices == i) {
+            this.clusterServices = null;
+            logger.debug("IClusterServices Unset");
+        }
+    }
+
+    public void init() {
+        logger.info("ContainerManager startup....");
+    }
+
+    public void destroy() {
+        // Clear local states
+        this.configurationAwareList.clear();
+    }
+
+    @Override
+    public Status saveConfigurations() {
+        boolean success = true;
+        for (IConfigurationAware configurationAware : configurationAwareList) {
+               Status status = configurationAware.saveConfiguration();
+            if (!status.isSuccess()) {
+               success = false;
+               logger.info("Failed to save config for "
+                               + configurationAware.getClass().getName());
+            }
+        }
+        if (success) {
+            return new Status(StatusCode.SUCCESS, null);
+        } else {
+            return new Status(StatusCode.INTERNALERROR,
+                       "Failed to Save All Configurations");
+        }
+    }
+
+}
diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationAwareTest.java
new file mode 100644 (file)
index 0000000..e93b467
--- /dev/null
@@ -0,0 +1,32 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import org.opendaylight.controller.configuration.IConfigurationAware;
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * @file   TestConfigurationAware.java
+ *
+ * @brief  Test Class to create for jUnit test cases for Configuration Implementation
+ *
+ *
+ */
+
+public class ConfigurationAwareTest implements
+IConfigurationAware {
+       
+       @Override
+       public Status saveConfiguration() {
+               return null;
+       }
+
+
+}
diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerAwareTest.java
new file mode 100644 (file)
index 0000000..52f3776
--- /dev/null
@@ -0,0 +1,35 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * @file   TestConfigurationAware.java
+ *
+ * @brief  Test Class to create for jUnit test cases for Configuration Implementation
+ *
+ *
+ */
+
+public class ConfigurationContainerAwareTest implements
+         IConfigurationContainerAware {
+
+       
+       
+       
+       @Override
+       public Status saveConfiguration() {
+               return null;
+       }
+       
+       
+}
diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationContainerImplTest.java
new file mode 100644 (file)
index 0000000..1d704a1
--- /dev/null
@@ -0,0 +1,65 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import org.junit.*;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+
+
+
+public class ConfigurationContainerImplTest { 
+       
+
+       @Test
+       public void testAddRemoveSaveConfiguration() {
+               
+               ConfigurationContainerImpl configurationContainerImpl = new ConfigurationContainerImpl();
+               IConfigurationContainerAware testConfigurationContainerAware = new ConfigurationContainerAwareTest();
+               
+               configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware);
+               configurationContainerImpl.addConfigurationContainerAware(testConfigurationContainerAware);
+               
+               Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               IConfigurationContainerAware testConfigurationAware1 = new ConfigurationContainerAwareTest();
+               configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware1);
+               
+               Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               IConfigurationContainerAware testConfigurationAware2 = new ConfigurationContainerAwareTest();
+               configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware2);
+               
+               Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               IConfigurationContainerAware testConfigurationAware3 = new ConfigurationContainerAwareTest();
+               configurationContainerImpl.addConfigurationContainerAware(testConfigurationAware3);
+               
+               Assert.assertEquals(4, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware);
+               Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               configurationContainerImpl.removeConfigurationContainerAware(testConfigurationContainerAware);
+               Assert.assertEquals(3, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware3);
+               Assert.assertEquals(2, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware2);
+               Assert.assertEquals(1, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               configurationContainerImpl.removeConfigurationContainerAware(testConfigurationAware1);
+               Assert.assertEquals(0, configurationContainerImpl.getConfigurationAwareListSize());
+               
+               
+       }
+       
+}
+
diff --git a/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java b/opendaylight/configuration/implementation/src/test/java/org/opendaylight/controller/configuration/internal/ConfigurationImplTest.java
new file mode 100644 (file)
index 0000000..71d768d
--- /dev/null
@@ -0,0 +1,63 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.configuration.internal;
+
+import org.junit.*;
+import org.opendaylight.controller.configuration.IConfigurationAware;
+
+public class ConfigurationImplTest { 
+       
+
+       @Test
+       public void testAddRemoveSaveConfiguration() {
+               
+               ConfigurationImpl configurationImpl = new ConfigurationImpl();
+               IConfigurationAware testConfigurationAware = new ConfigurationAwareTest();
+               
+               configurationImpl.addConfigurationAware(testConfigurationAware);
+               configurationImpl.addConfigurationAware(testConfigurationAware);
+               
+               Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize());
+               
+               ConfigurationAwareTest testConfigurationAware1 = new ConfigurationAwareTest();
+               configurationImpl.addConfigurationAware(testConfigurationAware1);
+               
+               Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize());
+               
+               ConfigurationAwareTest testConfigurationAware2 = new ConfigurationAwareTest();
+               configurationImpl.addConfigurationAware(testConfigurationAware2);
+               
+               Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize());
+               
+               ConfigurationAwareTest testConfigurationAware3 = new ConfigurationAwareTest();
+               configurationImpl.addConfigurationAware(testConfigurationAware3);
+               
+               Assert.assertEquals(4, configurationImpl.getConfigurationAwareListSize());
+               
+               
+               configurationImpl.removeConfigurationAware(testConfigurationAware);
+               Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize());
+               
+               configurationImpl.removeConfigurationAware(testConfigurationAware);
+               Assert.assertEquals(3, configurationImpl.getConfigurationAwareListSize());
+               
+               configurationImpl.removeConfigurationAware(testConfigurationAware3);
+               Assert.assertEquals(2, configurationImpl.getConfigurationAwareListSize());
+               
+               configurationImpl.removeConfigurationAware(testConfigurationAware1);
+               Assert.assertEquals(1, configurationImpl.getConfigurationAwareListSize());
+               
+               configurationImpl.removeConfigurationAware(testConfigurationAware2);
+               Assert.assertEquals(0, configurationImpl.getConfigurationAwareListSize());
+               
+       }
+       
+}
+
diff --git a/opendaylight/containermanager/api/pom.xml b/opendaylight/containermanager/api/pom.xml
new file mode 100644 (file)
index 0000000..8b5ccdf
--- /dev/null
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>containermanager</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+       <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+       <configuration>
+         <instructions>
+           <Import-Package>
+                 org.opendaylight.controller.sal.action,
+                 org.opendaylight.controller.sal.authorization,
+                 org.opendaylight.controller.sal.core,
+                 org.opendaylight.controller.sal.flowprogrammer,
+                 org.opendaylight.controller.sal.match,
+              org.opendaylight.controller.sal.reader,
+              org.opendaylight.controller.sal.utils,
+              org.apache.commons.lang3.builder
+           </Import-Package>
+           <Export-Package>
+              org.opendaylight.controller.containermanager
+           </Export-Package>
+         </instructions>
+       </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+       <dependency>
+               <groupId>org.opendaylight.controller</groupId>
+               <artifactId>sal</artifactId>
+               <version>0.4.0-SNAPSHOT</version>
+       </dependency> 
+  </dependencies>
+</project>
diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerAuthorization.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerAuthorization.java
new file mode 100644 (file)
index 0000000..6d3d9f8
--- /dev/null
@@ -0,0 +1,19 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.containermanager;
+
+import org.opendaylight.controller.sal.authorization.IResourceAuthorization;
+
+/**
+ * Container groups and container users authorizations
+ */
+public interface IContainerAuthorization extends IResourceAuthorization {
+
+}
diff --git a/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java b/opendaylight/containermanager/api/src/main/java/org/opendaylight/controller/containermanager/IContainerManager.java
new file mode 100644 (file)
index 0000000..f057959
--- /dev/null
@@ -0,0 +1,45 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.containermanager;
+
+import java.util.List;
+
+import org.opendaylight.controller.sal.utils.Status;
+
+/**
+ * Container Manager interface
+ *
+ *
+ */
+public interface IContainerManager {
+
+    /**
+     * Returns a list of Containers that currently exist.
+     *
+     * @return array of String Container names
+     */
+    public boolean hasNonDefaultContainer();
+
+    /**
+     * Returns a list of Containers that currently exist.
+     *
+     * @return array of String Container names
+     */
+    public List<String> getContainerNames();
+
+    /**
+     * Save the current container configuration to disk.
+     * TODO : REMOVE THIS FUNCTION and make Save as a service rather than the
+     * current hack of calling individual save routines.
+     *
+     * @return status code
+     */
+    public Status saveContainerConfig();
+}
diff --git a/opendaylight/containermanager/implementation/pom.xml b/opendaylight/containermanager/implementation/pom.xml
new file mode 100644 (file)
index 0000000..1ead516
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>containermanager.implementation</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <version>2.3.6</version>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Import-Package>
+              org.opendaylight.controller.containermanager,
+              org.opendaylight.controller.clustering.services,
+              org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.utils,
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.sal.action,
+              org.opendaylight.controller.sal.flowprogrammer,
+              org.opendaylight.controller.sal.match,
+              org.opendaylight.controller.sal.reader,
+              org.eclipse.osgi.framework.console,
+              org.osgi.framework,
+              org.slf4j,
+              org.apache.felix.dm
+            </Import-Package>
+            <Export-Package>
+            </Export-Package>
+            <Bundle-Activator>
+              org.opendaylight.controller.containermanager.internal.Activator
+            </Bundle-Activator>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>containermanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+       <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>sal</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+       </dependency> 
+  </dependencies>
+</project>
diff --git a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/Activator.java b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/Activator.java
new file mode 100644 (file)
index 0000000..9caa620
--- /dev/null
@@ -0,0 +1,129 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.containermanager.internal;
+
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.sal.core.IContainerAware;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.IContainerListener;
+import org.apache.felix.dm.Component;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { ContainerImpl.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(ContainerImpl.class)) {
+            // export the service
+            c.setInterface(new String[] { IContainer.class.getName() }, null);
+        }
+    }
+
+    /**
+     * Method which tells how many Global implementations are
+     * supported by the bundle. This way we can tune the number of
+     * components created. This components will be created ONLY at the
+     * time of bundle startup and will be destroyed only at time of
+     * bundle destruction, this is the major difference with the
+     * implementation retrieved via getImplementations where all of
+     * them are assumed to be in a container!
+     *
+     *
+     * @return The list of implementations the bundle will support,
+     * in Global version
+     */
+    protected Object[] getGlobalImplementations() {
+        Object[] res = { ContainerManager.class };
+        return res;
+    }
+
+    /**
+     * Configure the dependency for a given instance Global
+     *
+     * @param c Component assigned for this instance, this will be
+     * what will be used for configuration
+     * @param imp implementation to be configured
+     * @param containerName container on which the configuration happens
+     */
+    protected void configureGlobalInstance(Component c, Object imp) {
+        if (imp.equals(ContainerManager.class)) {
+
+            // export the service
+            c.setInterface(new String[] { IContainerManager.class.getName() },
+                    null);
+
+            c.add(createServiceDependency().setService(
+                    IClusterGlobalServices.class).setCallbacks(
+                    "setClusterServices", "unsetClusterServices").setRequired(
+                    true));
+
+            // Key kick-starter for container creation in each component
+            c.add(createServiceDependency().setService(IContainerAware.class)
+                    .setCallbacks("setIContainerAware", "unsetIContainerAware")
+                    .setRequired(false));
+
+            // Optional interface expected to be exported by the
+            // protocol plugins to setup proper filtering based on
+            // slicing events
+            c.add(createServiceDependency()
+                    .setService(IContainerListener.class).setCallbacks(
+                            "setIContainerListener", "unsetIContainerListener")
+                    .setRequired(false));
+        }
+    }
+}
diff --git a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerImpl.java b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerImpl.java
new file mode 100644 (file)
index 0000000..15f939d
--- /dev/null
@@ -0,0 +1,68 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+/**
+ * @file   ContainerImpl.java
+ *
+ * @brief  Class that instantiated per-container implements the
+ * interface IContainer
+ *
+ *
+ */
+package org.opendaylight.controller.containermanager.internal;
+
+import java.util.Dictionary;
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import java.util.Set;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.ContainerFlow;
+import java.util.List;
+import org.opendaylight.controller.sal.core.IContainer;
+
+public class ContainerImpl implements IContainer {
+    private String containerName = null;
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        Dictionary<?, ?> props = c.getServiceProperties();
+        if (props != null) {
+            this.containerName = (String) props.get("containerName");
+        }
+    }
+
+    @Override
+    public String getName() {
+        return this.containerName;
+    }
+
+    @Override
+    public List<ContainerFlow> getContainerFlows() {
+        return null;
+    }
+
+    @Override
+    public short getTag(Node n) {
+        return (short) 0;
+    }
+
+    @Override
+    public Set<NodeConnector> getNodeConnectors() {
+        return null;
+    }
+
+    @Override
+    public Set<Node> getNodes() {
+        return null;
+    }
+}
diff --git a/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java b/opendaylight/containermanager/implementation/src/main/java/org/opendaylight/controller/containermanager/internal/ContainerManager.java
new file mode 100644 (file)
index 0000000..d47aca8
--- /dev/null
@@ -0,0 +1,126 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+/**
+ * @file   ContainerManager.java
+ *
+ * @brief  Manage one or many Containers
+ *
+ *
+ */
+package org.opendaylight.controller.containermanager.internal;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.clustering.services.IClusterGlobalServices;
+import org.opendaylight.controller.containermanager.IContainerManager;
+import org.opendaylight.controller.sal.core.IContainerAware;
+import org.opendaylight.controller.sal.core.IContainerListener;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.Status;
+
+public class ContainerManager implements IContainerManager {
+    private static final Logger logger = LoggerFactory
+            .getLogger(ContainerManager.class);
+    private IClusterGlobalServices clusterServices;
+    /*
+     * Collection containing the configuration objects.
+     * This is configuration world: container names (also the map key)
+     * are maintained as they were configured by user, same case
+     */
+    private Set<IContainerAware> iContainerAware = (Set<IContainerAware>) Collections
+            .synchronizedSet(new HashSet<IContainerAware>());
+    private Set<IContainerListener> iContainerListener = Collections
+            .synchronizedSet(new HashSet<IContainerListener>());
+
+    void setIContainerListener(IContainerListener s) {
+        if (this.iContainerListener != null) {
+            this.iContainerListener.add(s);
+        }
+    }
+
+    void unsetIContainerListener(IContainerListener s) {
+        if (this.iContainerListener != null) {
+            this.iContainerListener.remove(s);
+        }
+    }
+
+    public void setIContainerAware(IContainerAware iContainerAware) {
+        if (!this.iContainerAware.contains(iContainerAware)) {
+            this.iContainerAware.add(iContainerAware);
+            // Now call the container creation for all the known containers so
+            // far
+            List<String> containerDB = getContainerNames();
+            if (containerDB != null) {
+                for (int i = 0; i < containerDB.size(); i++) {
+                    iContainerAware.containerCreate(containerDB.get(i));
+                }
+            }
+        }
+    }
+
+    public void unsetIContainerAware(IContainerAware iContainerAware) {
+        this.iContainerAware.remove(iContainerAware);
+        // There is no need to do cleanup of the component when
+        // unregister because it will be taken care by the Containerd
+        // component itself
+    }
+
+    public void setClusterServices(IClusterGlobalServices i) {
+        this.clusterServices = i;
+        logger.debug("IClusterServices set");
+    }
+
+    public void unsetClusterServices(IClusterGlobalServices i) {
+        if (this.clusterServices == i) {
+            this.clusterServices = null;
+            logger.debug("IClusterServices Unset");
+        }
+    }
+
+    public void init() {
+        logger.info("ContainerManager startup....");
+    }
+
+    public void destroy() {
+        // Clear local states
+        this.iContainerAware.clear();
+        this.iContainerListener.clear();
+
+        logger.info("ContainerManager Shutdown....");
+    }
+
+    @Override
+    public List<String> getContainerNames() {
+        /*
+         * Return container names as they were configured by user (case sensitive)
+         * along with the default container
+         */
+        List<String> containerNameList = new ArrayList<String>();
+        containerNameList.add(GlobalConstants.DEFAULT.toString());
+        return containerNameList;
+    }
+
+    @Override
+    public boolean hasNonDefaultContainer() {
+        return false;
+    }
+
+    @Override
+    public Status saveContainerConfig() {
+        return null;
+    }
+
+}
diff --git a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerImplTest.java
new file mode 100644 (file)
index 0000000..4bdd679
--- /dev/null
@@ -0,0 +1,60 @@
+\r
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.containermanager.internal;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+import java.util.Hashtable;\r
+\r
+import org.apache.felix.dm.impl.ComponentImpl;\r
+import org.junit.Test;\r
+import org.opendaylight.controller.sal.core.Node;\r
+import org.opendaylight.controller.sal.utils.NodeCreator;\r
+\r
+public class ContainerImplTest {\r
+\r
+       @Test\r
+       public void test() {\r
+               \r
+               ContainerImpl container1 = new ContainerImpl();\r
+                               \r
+               //Create Component for init\r
+               ComponentImpl component1 = new ComponentImpl(null, null, null);\r
+               component1.setInterface("serviceTestName", null);\r
+\r
+               //container1 does not have name yet\r
+               container1.init(component1);\r
+               assertNull(container1.getName());\r
+               \r
+               //Sets container1 name to TestName\r
+               Hashtable<String, String> properties = new Hashtable<String, String>();\r
+               properties.put("dummyKey", "dummyValue");\r
+               properties.put("containerName", "TestName");\r
+               component1.setInterface("serviceTestName", properties);\r
+\r
+               container1.init(component1);\r
+               assertEquals("TestName", container1.getName());\r
+               \r
+               //getContainerFlows always returns null for now\r
+               assertNull(container1.getContainerFlows());\r
+               \r
+               //getTag always returns 0 for now\r
+               Node n = NodeCreator.createOFNode(1L);\r
+               assertEquals(0, container1.getTag(n));\r
+               \r
+               //getNodeConnectors always returns null for now\r
+               assertNull(container1.getNodeConnectors());\r
+               \r
+               //getNodes always returns null for now\r
+               assertNull(container1.getNodes());\r
+               \r
+       }\r
+\r
+}\r
diff --git a/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java b/opendaylight/containermanager/implementation/src/test/java/org/opendaylight/controller/containermanager/internal/ContainerManagerTest.java
new file mode 100644 (file)
index 0000000..b5e7a11
--- /dev/null
@@ -0,0 +1,38 @@
+\r
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.controller.containermanager.internal;\r
+\r
+import static org.junit.Assert.*;\r
+\r
+import java.util.ArrayList;\r
+\r
+import org.junit.Test;\r
+import org.opendaylight.controller.sal.utils.GlobalConstants;\r
+\r
+public class ContainerManagerTest {\r
+\r
+       @Test\r
+       public void test() {\r
+               ContainerManager cm = new ContainerManager();\r
+               \r
+               cm.init();\r
+               \r
+               ArrayList<String> names = (ArrayList<String>) cm.getContainerNames();\r
+               assertEquals(1, names.size());\r
+               assertEquals(GlobalConstants.DEFAULT.toString(), names.get(0));\r
+               \r
+               assertFalse(cm.hasNonDefaultContainer());\r
+               assertNull(cm.saveContainerConfig());\r
+               \r
+               cm.destroy();\r
+\r
+       }\r
+\r
+}\r
index 3ec92d3..6984fd6 100644 (file)
   <version>0.1.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <modules>
+    <module>../../forwarding/staticrouting</module>
     <module>../../clustering/services</module>
     <module>../../clustering/services_implementation</module>
     <module>../../clustering/stub</module>
     <module>../../clustering/test</module>
+    <module>../../configuration/api</module>
+    <module>../../configuration/implementation</module>
+    <module>../../routing/dijkstra_implementation</module>
+    <module>../../arphandler</module>
+    <module>../../forwardingrulesmanager</module>
+    <module>../../hosttracker</module>
+    <module>../../containermanager/api</module>
+    <module>../../containermanager/implementation</module>
+    <module>../../switchmanager</module>
+    <module>../../statisticsmanager</module>
+    <module>../../topologymanager</module>
+    <module>../../usermanager</module>
     <module>../../../third-party/openflowj</module>
     <module>../../../third-party/net.sf.jung2</module>
     <module>../../../third-party/jersey-servlet</module>
     <!-- SAL bundles -->
     <module>../../sal/api</module>
     <module>../../sal/implementation</module>
+    
+    <!--  Web bundles -->
+    <module>../../web/root</module>
+    <module>../../web/flows</module>
+    <module>../../web/devices</module>
+    <module>../../web/troubleshoot</module>
+    <module>../../web/topology</module>
+    
+    <!-- Northbound bundles -->
+    <module>../../northbound/commons</module>
+    <module>../../northbound/topology</module>
+    <module>../../northbound/staticrouting</module>
+    <module>../../northbound/statistics</module>
+    <module>../../northbound/flowprogrammer</module>
+    <module>../../northbound/hosttracker</module>
+    <module>../../northbound/subnets</module>
+    <module>../../northbound/switchmanager</module>
 
     <!-- Debug and logging -->
     <module>../../logging/bridge</module>
+
+       <!-- Southbound bundles -->
+    <module>../../protocol_plugins/openflow</module>
+       
+    <!-- Samples -->
+    <module>../../samples/simpleforwarding</module>
   </modules>
   
   <build>
index 51152c9..b4afa61 100644 (file)
   <packaging>pom</packaging>
   <modules>
     <module>../../clustering/services</module>
+    <module>../../containermanager/api</module>
     <module>../../sal/api</module>
+
+    <!-- Northbound common hooks -->
+    <module>../../northbound/commons</module>
   </modules>
   
   <build>
diff --git a/opendaylight/forwarding/staticrouting/pom.xml b/opendaylight/forwarding/staticrouting/pom.xml
new file mode 100644 (file)
index 0000000..38f18bf
--- /dev/null
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>forwarding.staticrouting</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+       <groupId>org.apache.felix</groupId>
+       <artifactId>maven-bundle-plugin</artifactId>
+       <version>2.3.6</version>
+       <extensions>true</extensions>
+       <configuration>
+         <instructions>
+           <Import-Package>
+                         org.opendaylight.controller.sal.utils,
+                         org.opendaylight.controller.sal.core,
+                         org.opendaylight.controller.configuration,
+              org.opendaylight.controller.forwardingrulesmanager,
+              org.opendaylight.controller.hosttracker,
+              org.opendaylight.controller.hosttracker.hostAware,
+              org.opendaylight.controller.clustering.services,
+              org.opendaylight.controller.sal.packet,
+              org.opendaylight.controller.sal.routing,
+              org.opendaylight.controller.topologymanager,
+              org.eclipse.osgi.framework.console,
+              org.osgi.framework,
+              org.slf4j,
+              org.apache.felix.dm,
+              org.apache.commons.lang3.builder
+            </Import-Package>
+           <Export-Package>
+              org.opendaylight.controller.forwarding.staticrouting
+            </Export-Package>
+               <Bundle-Activator>
+                 org.opendaylight.controller.forwarding.staticrouting.internal.Activator
+               </Bundle-Activator>
+         </instructions>
+       </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>topologymanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>forwardingrulesmanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>    
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+       <dependency>
+               <groupId>org.opendaylight.controller</groupId>
+               <artifactId>sal</artifactId>
+               <version>0.4.0-SNAPSHOT</version>
+       </dependency>    
+  </dependencies>
+</project>
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IForwardingStaticRouting.java
new file mode 100644 (file)
index 0000000..9b9c0b0
--- /dev/null
@@ -0,0 +1,58 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+import java.net.InetAddress;
+import java.util.concurrent.ConcurrentMap;
+/**
+ * 
+ * This interface provides APIs to configure and manage static routes.
+ *
+ */
+import org.opendaylight.controller.sal.utils.Status;
+
+public interface IForwardingStaticRouting {
+
+    /**
+     * Retrieves the StaticRoute that has the longest prefix matching the ipAddress.
+     * @param ipAddress (InetAddress) the IP address
+     * @return StaticRoute
+     */
+    public StaticRoute getBestMatchStaticRoute(InetAddress ipAddress);
+
+    /**
+     * Returns all the StaticRouteConfig
+     * @return all the StaticRouteConfig
+     */
+    public ConcurrentMap<String, StaticRouteConfig> getStaticRouteConfigs();
+
+    /**
+     * Adds a StaticRouteConfig
+     * @param config: the StaticRouteConfig to be added
+     * @return a text string indicating the result of the operation..
+     * If the operation is successful, the return string will be "SUCCESS"
+     */
+    public Status addStaticRoute(StaticRouteConfig config);
+
+    /**
+     * Removes  the named StaticRouteConfig
+     * @param name: the name of the StaticRouteConfig to be removed
+     * @return a text string indicating the result of the operation.
+     * If the operation is successful, the return string will be "SUCCESS"
+     */
+    public Status removeStaticRoute(String name);
+
+    /**
+     * Saves the config
+     * @return a text string indicating the result of the operation.
+     * If the operation is successful, the return string will be "Success"
+     */
+    Status saveConfig();
+}
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IStaticRoutingAware.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/IStaticRoutingAware.java
new file mode 100644 (file)
index 0000000..f650ee9
--- /dev/null
@@ -0,0 +1,25 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+/**
+ * Interface that will be implemented by the modules that want to
+ * know when a Static Route is added or deleted.
+ *
+ */
+public interface IStaticRoutingAware {
+
+    /**
+     * This method  is called when a StaticRoute has added or deleted.
+     * @param s: StaticRoute
+     * @param added: boolean true if the static route is added,
+     */
+    public void staticRouteUpdate(StaticRoute s, boolean added);
+}
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRoute.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRoute.java
new file mode 100644 (file)
index 0000000..beec70e
--- /dev/null
@@ -0,0 +1,316 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.Map;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.packet.BitBufferHelper;
+import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.opendaylight.controller.sal.utils.NodeCreator;
+
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+
+/**
+ * This class defines a static route object.
+ */
+public class StaticRoute {
+    /**
+     * This Enum defines the possible types for the next hop address.
+     */
+    public enum NextHopType {
+        IPADDRESS("nexthop-ip"), SWITCHPORT("nexthop-interface");
+        private NextHopType(String name) {
+            this.name = name;
+        }
+
+        private String name;
+
+        public String toString() {
+            return name;
+        }
+
+        public static NextHopType fromString(String str) {
+            if (str == null)
+                return IPADDRESS;
+            if (str.equals(IPADDRESS.toString()))
+                return IPADDRESS;
+            if (str.equals(SWITCHPORT.toString()))
+                return SWITCHPORT;
+            return IPADDRESS;
+        }
+    }
+
+    InetAddress networkAddress;
+    InetAddress mask;
+    NextHopType type;
+    InetAddress nextHopAddress;
+    Node node;
+    NodeConnector port;
+    HostNodeConnector host;
+
+    /**
+     * Create a static route object with no specific information.
+     */
+    public StaticRoute() {
+
+    }
+
+    /**
+     * Create a static route object from the StaticRouteConfig.
+     * @param: config: StaticRouteConfig
+     */
+    public StaticRoute(StaticRouteConfig config) {
+        networkAddress = config.getStaticRouteIP();
+        mask = StaticRoute.getV4AddressMaskFromDecimal(config
+                .getStaticRouteMask());
+        type = NextHopType.fromString(config.getNextHopType());
+        nextHopAddress = config.getNextHopIP();
+        Map<Long, Short> switchPort = config.getNextHopSwitchPorts();
+        if ((switchPort != null) && (switchPort.size() == 1)) {
+            node = NodeCreator.createOFNode((Long) switchPort.keySet()
+                    .toArray()[0]);
+            port = NodeConnectorCreator.createOFNodeConnector(
+                    (Short) switchPort.values().toArray()[0], node);
+        }
+    }
+
+    /**
+     * Get the IP address portion of the sub-network of the static route.
+     * @return InetAddress: the IP address portion of the sub-network of the static route
+     */
+    public InetAddress getNetworkAddress() {
+        return networkAddress;
+    }
+
+    /**
+     * Set the IP address portion of the sub-network of the static route.
+     * @param networkAddress The IP address (InetAddress) to be set
+     */
+    public void setNetworkAddress(InetAddress networkAddress) {
+        this.networkAddress = networkAddress;
+    }
+
+    /**
+     * Get the mask of the sub-network of the static route.
+     * @return mask: the mask  (InetAddress) of the sub-network of the static route
+     */
+    public InetAddress getMask() {
+        return mask;
+    }
+
+    /**
+     * Set the sub-network's mask of the static route.
+     * @param mask The mask (InetAddress) to be set
+     */
+    public void setMask(InetAddress mask) {
+        this.mask = mask;
+    }
+
+    /**
+     * Get the NextHopeType of the static route.
+     * @return type: NextHopeType
+     */
+    public NextHopType getType() {
+        return type;
+    }
+
+    /**
+     * Set the nextHopType.
+     * @param type The NextHopType to be set
+     */
+    public void setType(NextHopType type) {
+        this.type = type;
+    }
+
+    /**
+     * Get the next hop IP address.
+     * @return: nextHopAddress (InetAddress)
+     */
+    public InetAddress getNextHopAddress() {
+        return nextHopAddress;
+    }
+
+    /**
+     * Set the next hop IP address.
+     * @param nextHopAddress The IP address (InetAddress) to be set
+     */
+    public void setNextHopAddress(InetAddress nextHopAddress) {
+        this.nextHopAddress = nextHopAddress;
+    }
+
+    /**
+     * Get the Node associated with the static route.
+     * @return: Node
+     */
+    public Node getNode() {
+        return node;
+    }
+
+    /**
+     * Set the node associated to the static route.
+     * @param node: The node to be set
+     */
+    public void setNode(Node node) {
+        this.node = node;
+    }
+
+    /**
+     * Set the port associated to the static route.
+     * @param port The port (NodeConnector) to be set
+     */
+    public void setPort(NodeConnector port) {
+        this.port = port;
+    }
+
+    /**
+     * Get the port associated to the static route.
+     * @return port: The port (NodeConnector)
+     */
+    public NodeConnector getPort() {
+        return port;
+    }
+
+    /**
+     * Get the Host associated to static route.
+     * @return host:  The host (HostNodeConnector)
+     */
+    public HostNodeConnector getHost() {
+        return host;
+    }
+
+    /**
+     * Set the host associated to the static route.
+     * @param host: (HostNodeConnector) to be set
+     */
+    public void setHost(HostNodeConnector host) {
+        this.host = host;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((host == null) ? 0 : host.hashCode());
+        result = prime * result + ((mask == null) ? 0 : mask.hashCode());
+        result = prime * result
+                + ((networkAddress == null) ? 0 : networkAddress.hashCode());
+        result = prime * result
+                + ((nextHopAddress == null) ? 0 : nextHopAddress.hashCode());
+        result = prime * result + ((port == null) ? 0 : port.hashCode());
+        result = prime * result + ((node == null) ? 0 : node.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "StaticRoute [networkAddress=" + networkAddress + ", mask="
+                + mask + ", type=" + type.toString() + ", nextHopAddress="
+                + nextHopAddress + ", swid=" + node + ", port=" + port
+                + ", host=" + host + "]";
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        StaticRoute other = (StaticRoute) obj;
+        if (!networkAddress.equals(other.networkAddress))
+            return false;
+        if (!mask.equals(other.mask))
+            return false;
+        return true;
+    }
+
+    private static InetAddress getV4AddressMaskFromDecimal(int mask) {
+        int netmask = 0;
+        for (int i = 0; i < mask; i++) {
+            netmask |= (1 << 31 - i);
+        }
+
+        try {
+            return InetAddress.getByAddress(BitBufferHelper
+                    .toByteArray(netmask));
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    private void applyV4MaskOnByteBuffer(ByteBuffer bb, ByteBuffer bbMask) {
+        for (int i = 0; i < bb.array().length; i++) {
+            bb.put(i, (byte) (bb.get(i) & bbMask.get(i)));
+        }
+    }
+
+    /**
+     * Compute and return the IP address  with longest prefix match from the static route based on the
+     *  destNetworkAddress. Currently it only take IPv4 address format (Inet4Address)
+     * @param destNetworkAddress: the IP address to be based on
+     * @return: InetAddress: the IPv4 address with the longest prefix matching the static route.
+     * If the destNetworkkAddress is not IPv4 format, it will return null.
+     */
+    public InetAddress longestPrefixMatch(InetAddress destNetworkAddress) {
+        if (destNetworkAddress instanceof Inet4Address) {
+            ByteBuffer bbdest = ByteBuffer
+                    .wrap(destNetworkAddress.getAddress());
+            ByteBuffer bbself = ByteBuffer.wrap(networkAddress.getAddress());
+
+            ByteBuffer bbMask = ByteBuffer.wrap(mask.getAddress());
+
+            applyV4MaskOnByteBuffer(bbdest, bbMask);
+            applyV4MaskOnByteBuffer(bbself, bbMask);
+
+            if (bbdest.equals(bbself)) {
+                try {
+                    return InetAddress.getByAddress(bbself.array());
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Compare the static route with another static route. It only handles(for now) IPv4Address.
+     * @param s: the other StaticRoute
+     * @return: 0 if they are the same
+     */
+    public int compareTo(StaticRoute s) {
+        if (s == null)
+            return 1;
+        if ((networkAddress instanceof Inet6Address)
+                || (s.getNetworkAddress() instanceof Inet6Address)) {
+            // HANDLE IPv6 Later
+            return 1;
+        }
+
+        ByteBuffer bbchallenger = ByteBuffer.wrap(s.getNetworkAddress()
+                .getAddress());
+        ByteBuffer bbself = ByteBuffer.wrap(networkAddress.getAddress());
+        ByteBuffer bbChallengerMask = ByteBuffer.wrap(s.getMask().getAddress());
+        ByteBuffer bbSelfMask = ByteBuffer.wrap(getMask().getAddress());
+
+        applyV4MaskOnByteBuffer(bbchallenger, bbChallengerMask);
+        applyV4MaskOnByteBuffer(bbself, bbSelfMask);
+        return bbself.compareTo(bbchallenger);
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfig.java
new file mode 100644 (file)
index 0000000..706c29e
--- /dev/null
@@ -0,0 +1,345 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.opendaylight.controller.sal.utils.GUIField;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+/**
+ * This class defines all the necessary configuration information for a static route.
+ */
+public class StaticRouteConfig implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private static final String regexSubnet = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])[/](\\d|[12]\\d|3[0-2])$";
+    private static final String regexIP = "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\."
+            + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
+    private static final String regexDatapathID = "^([0-9a-fA-F]{1,2}[:-]){7}[0-9a-fA-F]{1,2}$";
+    private static final String regexDatapathIDLong = "^[0-9a-fA-F]{1,16}$";
+    private static final String prettyFields[] = { GUIField.NAME.toString(),
+            GUIField.STATICROUTE.toString(), GUIField.NEXTHOP.toString() };
+    private transient String nextHopType; // Ignoring NextHopType for now. Supporting just the next-hop IP-Address feature for now.
+    // Order matters: JSP file expects following fields in the following order
+    private String name;
+    private String staticRoute; // A.B.C.D/MM  Where A.B.C.D is the Default Gateway IP (L3) or ARP Querier IP (L2)
+    private String nextHop; // NextHop IP-Address (or) datapath ID/port list: xx:xx:xx:xx:xx:xx:xx:xx/a,b,c-m,r-t,y
+
+    /**
+     * Create a static route configuration  with no specific information.
+     */
+    public StaticRouteConfig() {
+        super();
+        nextHopType = StaticRoute.NextHopType.IPADDRESS.toString();
+    }
+
+    /**
+     * Create a static route configuration with all the information.
+     * @param name The name (String) of the static route config
+     * @param staticRoute The string representation of the route. e.g. 192.168.1.1/24
+     * @param nextHop The string representation of the next hop IP address. e.g. 10.10.1.1
+     */
+    public StaticRouteConfig(String name, String staticRoute, String nextHop) {
+        super();
+        this.name = name;
+        this.staticRoute = staticRoute;
+        this.nextHop = nextHop;
+    }
+
+    /**
+     * Get the name of the StaticRouteConfig.
+     * @return: The name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Set the name of the StaticRouteConfig.
+     * @param name The name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * Get the string representation of the static route.
+     * @return The string representation of the static route
+     */
+    public String getStaticRoute() {
+        return staticRoute;
+    }
+
+    /**
+     * Set the static route of the StaticRouteConfig.
+     * @param staticRoute The string representation of the static route
+     */
+    public void setStaticRoute(String staticRoute) {
+        this.staticRoute = staticRoute;
+    }
+
+    /**
+     * Get the string representation of the next hop address type.
+     * @return The string representation of the next hop address type
+     */
+    public String getNextHopType() {
+        if (nextHopType == null)
+            return StaticRoute.NextHopType.IPADDRESS.toString();
+        return nextHopType;
+    }
+
+    /**
+     * Set the next hop address type.
+     * @param nextHopType The string representation of the next hop address type
+     */
+    public void setNextHopType(String nextHopType) {
+        this.nextHopType = nextHopType;
+    }
+
+    /**
+     * Get all the supported next hop address types.
+     * @return The list of supported next hop address types
+     */
+    public static List<String> getSupportedNextHopTypes() {
+        List<String> s = new ArrayList<String>();
+        for (StaticRoute.NextHopType nh : StaticRoute.NextHopType.values()) {
+            s.add(nh.toString());
+        }
+        return s;
+    }
+
+    /**
+     * Get the next hop address
+     * @return The string represenation of the next hop address
+     */
+    public String getNextHop() {
+        return nextHop;
+    }
+
+    /**
+     * Set the next hop address.
+     * @param nextHop: The string representation of the next hop address to be set
+     */
+    public void setNextHop(String nextHop) {
+        this.nextHop = nextHop;
+    }
+
+    /**
+     * Return a string with text indicating if the config is valid.
+     * @return SUCCESS if the config is valid
+     */
+    public Status isValid() {
+        if ((name == null) || (name.trim().length() < 1)) {
+            return new Status(StatusCode.BADREQUEST,
+                       "Invalid Static Route name");
+        }
+        if (!isValidStaticRouteEntry()) {
+            return new Status(StatusCode.BADREQUEST,
+                       "Invalid Static Route entry. Please use the " +
+                       "IPAddress/mask format. Default gateway " +
+                       "(0.0.0.0/0) is NOT supported.");
+        }
+        if (!isValidNextHop()) {
+            return new Status(StatusCode.BADREQUEST,
+                       "Invalid NextHop IP Address configuration. " +
+                                       "Please use the X.X.X.X format.");
+        }
+
+        return new Status(StatusCode.SUCCESS, null);
+    }
+
+    private boolean isValidAddress(String address) {
+        if ((address != null) && address.matches(regexIP)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isValidStaticRouteEntry() {
+        if ((staticRoute != null) && staticRoute.matches(regexSubnet)) {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isValidNextHop() {
+        if (getNextHopType().equalsIgnoreCase(
+                StaticRoute.NextHopType.IPADDRESS.toString())) {
+            return isValidNextHopIP();
+        } else if (getNextHopType().equalsIgnoreCase(
+                StaticRoute.NextHopType.SWITCHPORT.toString())) {
+            return isValidSwitchId();
+        }
+        return false;
+    }
+
+    private boolean isValidNextHopIP() {
+        return isValidAddress(nextHop);
+    }
+
+    private boolean isValidSwitchId(String switchId) {
+        return (switchId != null && (switchId.matches(regexDatapathID) || switchId
+                .matches(regexDatapathIDLong)));
+    }
+
+    private boolean isValidSwitchId() {
+        if (getNextHopType().equalsIgnoreCase(
+                StaticRoute.NextHopType.SWITCHPORT.toString())) {
+            String pieces[] = nextHop.split("/");
+            if (pieces.length < 2)
+                return false;
+            return isValidSwitchId(pieces[0]);
+        }
+        return false;
+    }
+
+    /**
+     * Return the IP address of the static route.
+     * @return The IP address
+     */
+    public InetAddress getStaticRouteIP() {
+        if (!isValidStaticRouteEntry())
+            return null;
+        InetAddress ip = null;
+        try {
+            ip = InetAddress.getByName(staticRoute.split("/")[0]);
+        } catch (UnknownHostException e1) {
+            return null;
+        }
+        return ip;
+    }
+
+    /**
+     * Return the bit-mask length of the static route.
+     * @return The bit-mask length
+     */
+    public Short getStaticRouteMask() {
+        Short maskLen = 0;
+        if (isValidStaticRouteEntry()) {
+            String[] s = staticRoute.split("/");
+            maskLen = (s.length == 2) ? Short.valueOf(s[1]) : 32;
+        }
+        return maskLen;
+    }
+
+    /**
+     * Return the IP address of the next hop.
+     * @return the IP address
+     */
+    public InetAddress getNextHopIP() {
+        if ((getNextHopType()
+                .equalsIgnoreCase(StaticRoute.NextHopType.IPADDRESS.toString()))
+                && isValidNextHopIP()) {
+            InetAddress ip = null;
+            try {
+                ip = InetAddress.getByName(nextHop);
+            } catch (UnknownHostException e1) {
+                return null;
+            }
+            return ip;
+        }
+        return null;
+    }
+
+/**
+ * Return the switch ID and the port ID of the next hop address.
+ * @return The switchID (Long) and PortID (Short) in the map
+ */
+    public Map<Long, Short> getNextHopSwitchPorts() {
+        // codedSwitchPorts = xx:xx:xx:xx:xx:xx:xx:xx/port-number
+        if (getNextHopType().equalsIgnoreCase(
+                StaticRoute.NextHopType.SWITCHPORT.toString())) {
+            Map<Long, Short> sp = new HashMap<Long, Short>(1);
+            String pieces[] = nextHop.split("/");
+            sp.put(getSwitchIDLong(pieces[0]), Short.valueOf(pieces[1]));
+            return sp;
+        }
+        return null;
+    }
+
+    private long getSwitchIDLong(String switchId) {
+        int radix = 16;
+        String switchString = "0";
+
+        if (isValidSwitchId(switchId)) {
+            if (switchId.contains(":")) {
+                // Handle the 00:00:AA:BB:CC:DD:EE:FF notation
+                switchString = switchId.replace(":", "");
+            } else if (switchId.contains("-")) {
+                // Handle the 00-00-AA-BB-CC-DD-EE-FF notation
+                switchString = switchId.replace("-", "");
+            } else {
+                // Handle the 0123456789ABCDEF notation
+                switchString = switchId;
+            }
+        }
+        return Long.parseLong(switchString, radix);
+    }
+
+    /**
+     * Return all the field names of the config.
+     * @return The list containing all the field names
+     */
+    public static List<String> getFieldsNames() {
+        List<String> fieldList = new ArrayList<String>();
+        for (Field fld : StaticRouteConfig.class.getDeclaredFields()) {
+            fieldList.add(fld.getName());
+        }
+        //remove the 6 static fields + NextHopType
+        for (short i = 0; i < 7; i++) {
+            fieldList.remove(0);
+        }
+        return fieldList;
+    }
+
+    /**
+     * Return all the GUI field names of the config.
+     * @return The list containing all the GUI field names
+     */
+    public static List<String> getGuiFieldsNames() {
+        List<String> fieldList = new ArrayList<String>();
+        for (String str : prettyFields) {
+            fieldList.add(str);
+        }
+        return fieldList;
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return "StaticRouteConfig [name=" + name + ", staticRoute="
+                + staticRoute + ", nextHopType=" + nextHopType + ", nextHop="
+                + nextHop + "]";
+    }
+}
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/Activator.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/Activator.java
new file mode 100644 (file)
index 0000000..37f3873
--- /dev/null
@@ -0,0 +1,109 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting.internal;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
+import org.opendaylight.controller.forwarding.staticrouting.IStaticRoutingAware;
+import org.opendaylight.controller.sal.core.ComponentActivatorAbstractBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.IfNewHostNotify;
+
+public class Activator extends ComponentActivatorAbstractBase {
+    protected static final Logger logger = LoggerFactory
+            .getLogger(Activator.class);
+
+    /**
+     * Function called when the activator starts just after some
+     * initializations are done by the
+     * ComponentActivatorAbstractBase.
+     *
+     */
+    public void init() {
+
+    }
+
+    /**
+     * Function called when the activator stops just before the
+     * cleanup done by ComponentActivatorAbstractBase
+     *
+     */
+    public void destroy() {
+
+    }
+
+    /**
+     * Function that is used to communicate to dependency manager the
+     * list of known implementations for services inside a container
+     *
+     *
+     * @return An array containing all the CLASS objects that will be
+     * instantiated in order to get an fully working implementation
+     * Object
+     */
+    public Object[] getImplementations() {
+        Object[] res = { StaticRoutingImplementation.class };
+        return res;
+    }
+
+    /**
+     * Function that is called when configuration of the dependencies
+     * is required.
+     *
+     * @param c dependency manager Component object, used for
+     * configuring the dependencies exported and imported
+     * @param imp Implementation class that is being configured,
+     * needed as long as the same routine can configure multiple
+     * implementations
+     * @param containerName The containerName being configured, this allow
+     * also optional per-container different behavior if needed, usually
+     * should not be the case though.
+     */
+    public void configureInstance(Component c, Object imp, String containerName) {
+        if (imp.equals(StaticRoutingImplementation.class)) {
+            Dictionary<String, Set<String>> props = new Hashtable<String, Set<String>>();
+            Set<String> propSet = new HashSet<String>();
+            propSet.add("forwarding.staticrouting.configSaveEvent");
+            props.put("cachenames", propSet);
+            // export the service
+
+            c.setInterface(new String[] { ICacheUpdateAware.class.getName(),
+                    IForwardingStaticRouting.class.getName(),
+                    IfNewHostNotify.class.getName(),
+                    IConfigurationContainerAware.class.getName() }, props);
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IClusterContainerServices.class).setCallbacks(
+                    "setClusterContainerService",
+                    "unsetClusterContainerService").setRequired(true));
+
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IfIptoHost.class).setCallbacks("setHostTracker",
+                    "unsetHostTracker").setRequired(true));
+
+            // Static routing aware there could be many
+            c.add(createContainerServiceDependency(containerName).setService(
+                    IStaticRoutingAware.class).setCallbacks(
+                    "setStaticRoutingAware", "unsetStaticRoutingAware")
+                    .setRequired(false));
+        }
+    }
+}
diff --git a/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java b/opendaylight/forwarding/staticrouting/src/main/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementation.java
new file mode 100644 (file)
index 0000000..fd043fd
--- /dev/null
@@ -0,0 +1,520 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting.internal;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.dm.Component;
+import org.opendaylight.controller.clustering.services.CacheConfigException;
+import org.opendaylight.controller.clustering.services.CacheExistException;
+import org.opendaylight.controller.clustering.services.ICacheUpdateAware;
+import org.opendaylight.controller.clustering.services.IClusterContainerServices;
+import org.opendaylight.controller.clustering.services.IClusterServices;
+import org.opendaylight.controller.configuration.IConfigurationContainerAware;
+import org.opendaylight.controller.forwarding.staticrouting.IForwardingStaticRouting;
+import org.opendaylight.controller.forwarding.staticrouting.IStaticRoutingAware;
+import org.opendaylight.controller.forwarding.staticrouting.StaticRoute;
+import org.opendaylight.controller.forwarding.staticrouting.StaticRouteConfig;
+import org.opendaylight.controller.hosttracker.IfIptoHost;
+import org.opendaylight.controller.hosttracker.IfNewHostNotify;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.IObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectReader;
+import org.opendaylight.controller.sal.utils.ObjectWriter;
+import org.opendaylight.controller.sal.utils.Status;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Static Routing feature provides the bridge between SDN and Non-SDN networks.
+ *
+ *
+ *
+ */
+public class StaticRoutingImplementation implements IfNewHostNotify,
+        IForwardingStaticRouting, IObjectReader, IConfigurationContainerAware,
+        ICacheUpdateAware<Long, String> {
+    private static Logger log = LoggerFactory
+            .getLogger(StaticRoutingImplementation.class);
+    private static String ROOT = GlobalConstants.STARTUPHOME.toString();
+    private static final String SAVE = "Save";
+    ConcurrentMap<String, StaticRoute> staticRoutes;
+    ConcurrentMap<String, StaticRouteConfig> staticRouteConfigs;
+    private IfIptoHost hostTracker;
+    private Timer gatewayProbeTimer;
+    private String staticRoutesFileName = null;
+    private Map<Long, String> configSaveEvent;
+    private IClusterContainerServices clusterContainerService = null;
+    private Set<IStaticRoutingAware> staticRoutingAware = Collections
+            .synchronizedSet(new HashSet<IStaticRoutingAware>());
+
+    void setStaticRoutingAware(IStaticRoutingAware s) {
+        if (this.staticRoutingAware != null) {
+            this.staticRoutingAware.add(s);
+        }
+    }
+
+    void unsetStaticRoutingAware(IStaticRoutingAware s) {
+        if (this.staticRoutingAware != null) {
+            this.staticRoutingAware.remove(s);
+        }
+    }
+
+    public void setHostTracker(IfIptoHost hostTracker) {
+        log.debug("Setting HostTracker");
+        this.hostTracker = hostTracker;
+    }
+
+    public void unsetHostTracker(IfIptoHost hostTracker) {
+        if (this.hostTracker == hostTracker) {
+            this.hostTracker = null;
+        }
+    }
+
+    public ConcurrentMap<String, StaticRouteConfig> getStaticRouteConfigs() {
+        return staticRouteConfigs;
+    }
+
+    public void setStaticRouteConfigs(
+            ConcurrentMap<String, StaticRouteConfig> staticRouteConfigs) {
+        this.staticRouteConfigs = staticRouteConfigs;
+    }
+
+    @Override
+    public Object readObject(ObjectInputStream ois)
+            throws FileNotFoundException, IOException, ClassNotFoundException {
+        // Perform the class deserialization locally, from inside the package
+        // where the class is defined
+        return ois.readObject();
+    }
+
+    @SuppressWarnings("unchecked")
+    private void loadConfiguration() {
+        ObjectReader objReader = new ObjectReader();
+        ConcurrentMap<String, StaticRouteConfig> confList = (ConcurrentMap<String, StaticRouteConfig>) objReader
+                .read(this, staticRoutesFileName);
+
+        if (confList == null) {
+            return;
+        }
+
+        for (StaticRouteConfig conf : confList.values()) {
+            addStaticRoute(conf);
+        }
+    }
+
+    @Override
+    public Status saveConfig() {
+        // Publish the save config event to the cluster nodes
+        configSaveEvent.put(new Date().getTime(), SAVE);
+        return saveConfigInternal();
+    }
+
+    public Status saveConfigInternal() {
+        Status status;
+        ObjectWriter objWriter = new ObjectWriter();
+
+        status = objWriter.write(
+                new ConcurrentHashMap<String, StaticRouteConfig>(
+                        staticRouteConfigs), staticRoutesFileName);
+
+        if (status.isSuccess()) {
+            return status;
+        } else {
+            return new Status(StatusCode.INTERNALERROR, "Save failed");
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+       private void allocateCaches() {
+        if (this.clusterContainerService == null) {
+            log
+                    .info("un-initialized clusterContainerService, can't create cache");
+            return;
+        }
+
+        try {
+            clusterContainerService.createCache(
+                    "forwarding.staticrouting.routes", EnumSet
+                            .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+            clusterContainerService.createCache(
+                    "forwarding.staticrouting.configs", EnumSet
+                            .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+            clusterContainerService.createCache(
+                    "forwarding.staticrouting.configSaveEvent", EnumSet
+                            .of(IClusterServices.cacheMode.NON_TRANSACTIONAL));
+
+        } catch (CacheExistException cee) {
+            log
+                    .error("\nCache already exists - destroy and recreate if needed");
+        } catch (CacheConfigException cce) {
+            log.error("\nCache configuration invalid - check cache mode");
+        }
+    }
+
+    @SuppressWarnings({ "unchecked", "deprecation" })
+    private void retrieveCaches() {
+        if (this.clusterContainerService == null) {
+            log
+                    .info("un-initialized clusterContainerService, can't retrieve cache");
+            return;
+        }
+
+        staticRoutes = (ConcurrentMap<String, StaticRoute>) clusterContainerService
+                .getCache("forwarding.staticrouting.routes");
+        if (staticRoutes == null) {
+            log.error("\nFailed to get rulesDB handle");
+        }
+
+        staticRouteConfigs = (ConcurrentMap<String, StaticRouteConfig>) clusterContainerService
+                .getCache("forwarding.staticrouting.configs");
+        if (staticRouteConfigs == null) {
+            log.error("\nFailed to get rulesDB handle");
+        }
+        configSaveEvent = (ConcurrentMap<Long, String>) clusterContainerService
+                .getCache("forwarding.staticrouting.configSaveEvent");
+        if (configSaveEvent == null) {
+            log.error("\nFailed to get cache for configSaveEvent");
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+       private void destroyCaches() {
+        if (this.clusterContainerService == null) {
+            log
+                    .info("un-initialized clusterContainerService, can't destroy cache");
+            return;
+        }
+
+        clusterContainerService.destroyCache("forwarding.staticrouting.routes");
+        clusterContainerService
+                .destroyCache("forwarding.staticrouting.configs");
+        clusterContainerService
+                .destroyCache("forwarding.staticrouting.configSaveEvent");
+
+    }
+
+    @Override
+    public void entryCreated(Long key, String cacheName, boolean local) {
+    }
+
+    @Override
+    public void entryUpdated(Long key, String new_value, String cacheName,
+            boolean originLocal) {
+        saveConfigInternal();
+    }
+
+    @Override
+    public void entryDeleted(Long key, String cacheName, boolean originLocal) {
+    }
+
+    private void notifyStaticRouteUpdate(StaticRoute s, boolean update) {
+        if (this.staticRoutingAware != null) {
+            log.info("Invoking StaticRoutingAware listeners");
+            synchronized (this.staticRoutingAware) {
+                for (IStaticRoutingAware ra : this.staticRoutingAware) {
+                    try {
+                        ra.staticRouteUpdate(s, update);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+
+    private class NotifyStaticRouteThread extends Thread {
+        private StaticRoute staticRoute;
+        private boolean added;
+
+        public NotifyStaticRouteThread(StaticRoute s, boolean update) {
+            this.staticRoute = s;
+            this.added = update;
+        }
+
+        public void run() {
+            if (!added
+                    || (staticRoute.getType() == StaticRoute.NextHopType.SWITCHPORT)) {
+                notifyStaticRouteUpdate(staticRoute, added);
+            } else {
+                HostNodeConnector host = hostTracker.hostQuery(staticRoute
+                        .getNextHopAddress());
+                if (host == null) {
+                    Future<HostNodeConnector> future = hostTracker
+                            .discoverHost(staticRoute.getNextHopAddress());
+                    if (future != null) {
+                        try {
+                            host = future.get();
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+                }
+                if (host != null) {
+                    staticRoute.setHost(host);
+                    notifyStaticRouteUpdate(staticRoute, added);
+                }
+            }
+        }
+    }
+
+    private void checkAndUpdateListeners(StaticRoute staticRoute, boolean added) {
+        new NotifyStaticRouteThread(staticRoute, added).start();
+    }
+
+    private void notifyHostUpdate(HostNodeConnector host, boolean added) {
+        if (host == null)
+            return;
+        for (StaticRoute s : staticRoutes.values()) {
+            if (s.getType() == StaticRoute.NextHopType.SWITCHPORT)
+                continue;
+            if (s.getNextHopAddress().equals(host.getNetworkAddress())) {
+                if (added) {
+                    s.setHost(host);
+                } else {
+                    s.setHost(null);
+                }
+                notifyStaticRouteUpdate(s, added);
+            }
+        }
+    }
+
+    @Override
+    public void notifyHTClient(HostNodeConnector host) {
+        notifyHostUpdate(host, true);
+    }
+
+    @Override
+    public void notifyHTClientHostRemoved(HostNodeConnector host) {
+        notifyHostUpdate(host, false);
+    }
+
+    public boolean isIPv4AddressValid(String cidr) {
+        if (cidr == null)
+            return false;
+
+        String values[] = cidr.split("/");
+        Pattern ipv4Pattern = Pattern
+                .compile("(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])");
+        Matcher mm = ipv4Pattern.matcher(values[0]);
+        if (!mm.matches()) {
+            log.debug("IPv4 source address {} is not valid", cidr);
+            return false;
+        }
+        if (values.length >= 2) {
+            int prefix = Integer.valueOf(values[1]);
+            if ((prefix < 0) || (prefix > 32)) {
+                log.debug("prefix {} is not valid", prefix);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public static short getUnsignedByte(ByteBuffer bb, int position) {
+        return ((short) (bb.get(position) & (short) 0xff));
+    }
+
+    public static int compareByteBuffers(ByteBuffer buf1, ByteBuffer buf2) {
+        for (int i = 0; i < buf1.array().length; i++) {
+            if (getUnsignedByte(buf1, i) > getUnsignedByte(buf2, i)) {
+                return 1;
+            } else if (getUnsignedByte(buf1, i) < getUnsignedByte(buf2, i)) {
+                return -1;
+            }
+        }
+
+        return 0;
+    }
+
+    public StaticRoute getBestMatchStaticRoute(InetAddress ipAddress) {
+        ByteBuffer bblongestPrefix = null;
+        try {
+            bblongestPrefix = ByteBuffer.wrap(InetAddress.getByName("0.0.0.0")
+                    .getAddress());
+        } catch (Exception e) {
+            return null;
+        }
+
+        if (staticRoutes == null) {
+            return null;
+        }
+
+        StaticRoute longestPrefixRoute = null;
+        for (StaticRoute s : staticRoutes.values()) {
+            InetAddress prefix = s.longestPrefixMatch(ipAddress);
+            if ((prefix != null) && (prefix instanceof Inet4Address)) {
+                ByteBuffer bbtmp = ByteBuffer.wrap(prefix.getAddress());
+                if (compareByteBuffers(bbtmp, bblongestPrefix) > 0) {
+                    bblongestPrefix = bbtmp;
+                    longestPrefixRoute = s;
+                }
+            }
+        }
+        return longestPrefixRoute;
+    }
+
+    public Status addStaticRoute(StaticRouteConfig config) {
+        Status status;
+
+        status = config.isValid();
+        if (!status.isSuccess()) {
+            return status;
+        }
+        if (staticRouteConfigs.get(config.getName()) != null) {
+               return new Status(StatusCode.CONFLICT,
+                               "A valid Static Route configuration with this name " +
+                                               "already exists. Please use a different name");
+        }
+        for (StaticRouteConfig s : staticRouteConfigs.values()) {
+            if (s.equals(config)) {
+               return new Status(StatusCode.CONFLICT,
+                               "This conflicts with an existing Static Route " +
+                                       "Configuration. Please check the configuration " +
+                                               "and try again");
+            }
+        }
+
+        staticRouteConfigs.put(config.getName(), config);
+        StaticRoute sRoute = new StaticRoute(config);
+        staticRoutes.put(config.getName(), sRoute);
+        checkAndUpdateListeners(sRoute, true);
+        return status; 
+    }
+
+    public Status removeStaticRoute(String name) {
+        staticRouteConfigs.remove(name);
+        StaticRoute sRoute = staticRoutes.remove(name);
+        if (sRoute != null) {
+            checkAndUpdateListeners(sRoute, false);
+            return new Status(StatusCode.SUCCESS, null);
+        }
+        return new Status(StatusCode.NOTFOUND, 
+                       "Static Route with name " + name + " is not found");
+    }
+
+    void setClusterContainerService(IClusterContainerServices s) {
+        log.debug("Cluster Service set");
+        this.clusterContainerService = s;
+    }
+
+    void unsetClusterContainerService(IClusterContainerServices s) {
+        if (this.clusterContainerService == s) {
+            log.debug("Cluster Service removed!");
+            this.clusterContainerService = null;
+        }
+    }
+
+    /**
+     * Function called by the dependency manager when all the required
+     * dependencies are satisfied
+     *
+     */
+    void init(Component c) {
+        String containerName = null;
+        Dictionary props = c.getServiceProperties();
+        if (props != null) {
+            containerName = (String) props.get("containerName");
+        } else {
+            // In the Global instance case the containerName is empty
+            containerName = "";
+        }
+
+        staticRoutesFileName = ROOT + "staticRouting_" + containerName
+                + ".conf";
+
+        log.debug("forwarding.staticrouting starting on container "
+                + containerName);
+        //staticRoutes = new ConcurrentHashMap<String, StaticRoute>();
+        allocateCaches();
+        retrieveCaches();
+
+        if (staticRouteConfigs.isEmpty())
+            loadConfiguration();
+
+        /*
+         *  Slow probe to identify any gateway that might have silently appeared
+         *  after the Static Routing Configuration.
+         */
+        gatewayProbeTimer = new Timer();
+        gatewayProbeTimer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                for (StaticRoute s : staticRoutes.values()) {
+                    if ((s.getType() == StaticRoute.NextHopType.IPADDRESS)
+                            && s.getHost() == null) {
+                        checkAndUpdateListeners(s, true);
+                    }
+                }
+            }
+        }, 60 * 1000, 60 * 1000);
+    }
+
+    /**
+     * Function called by the dependency manager when at least one
+     * dependency become unsatisfied or when the component is shutting
+     * down because for example bundle is being stopped.
+     *
+     */
+    void destroy() {
+        log.debug("Destroy all the Static Routing Rules given we are "
+                + "shutting down");
+
+        destroyCaches();
+        gatewayProbeTimer.cancel();
+
+        // Clear the listener so to be ready in next life
+        this.staticRoutingAware.clear();
+    }
+
+    /**
+     * Function called by dependency manager after "init ()" is called
+     * and after the services provided by the class are registered in
+     * the service registry
+     *
+     */
+    void start() {
+    }
+
+    /**
+     * Function called by the dependency manager before the services
+     * exported by the component are unregistered, this will be
+     * followed by a "destroy ()" calls
+     *
+     */
+    void stop() {
+    }
+
+    @Override
+    public Status saveConfiguration() {
+        return this.saveConfig();
+    }
+}
diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteConfigTest.java
new file mode 100644 (file)
index 0000000..84ec54b
--- /dev/null
@@ -0,0 +1,111 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+
+import java.net.InetAddress;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.forwarding.staticrouting.StaticRoute.NextHopType;
+import org.opendaylight.controller.sal.utils.Status;
+import org.opendaylight.controller.sal.utils.StatusCode;
+
+public class StaticRouteConfigTest {
+       
+       @Test
+       public void testStaticRouteSetGet() {
+               StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig();
+               staticRouteConfig1.setName("route");
+               staticRouteConfig1.setStaticRoute("10.1.1.2/32");
+               staticRouteConfig1.setNextHop("200.2.2.2");
+               staticRouteConfig1.setNextHopType(NextHopType.IPADDRESS.toString());
+               StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route", "10.1.1.2/32", "200.2.2.2");
+               
+               Assert.assertEquals(staticRouteConfig2.getName(), staticRouteConfig1.getName());
+               Assert.assertEquals(staticRouteConfig2.getStaticRoute(), staticRouteConfig1.getStaticRoute());
+               Assert.assertEquals(staticRouteConfig2.getNextHop(), staticRouteConfig1.getNextHop());
+               Assert.assertEquals("nexthop-ip", staticRouteConfig1.getNextHopType());
+       }
+               
+       @Test
+       public void testStaticRouteisValid() {  
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1");
+               Status receivedResponse1 = staticRouteConfig1.isValid();
+               Status expectedResponse1 = new Status(StatusCode.SUCCESS, null);
+               Assert.assertEquals(expectedResponse1.toString(), receivedResponse1.toString());
+               
+        StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("", "", "100.1.1.1");
+               Status receivedResponse2 = staticRouteConfig2.isValid();
+               Status expectedResponse2 = new Status(StatusCode.BADREQUEST,
+                       "Invalid Static Route name");
+               Assert.assertEquals(expectedResponse2.toString(), receivedResponse2.toString());
+
+        StaticRouteConfig staticRouteConfig3 = new StaticRouteConfig("route1", "10.1.1.254", "100.1.1.1");
+               Status receivedResponse3 = staticRouteConfig3.isValid();
+               Status expectedResponse3 = new Status(StatusCode.BADREQUEST,
+                       "Invalid Static Route entry. Please use the " +
+                       "IPAddress/mask format. Default gateway " +
+                       "(0.0.0.0/0) is NOT supported.");
+               Assert.assertEquals(expectedResponse3.toString(), receivedResponse3.toString());
+
+        StaticRouteConfig staticRouteConfig4 = new StaticRouteConfig("route1", "289.1.1.254/24", "100.1.1.1");
+               Status receivedResponse4 = staticRouteConfig4.isValid();
+               Status expectedResponse4 = new Status(StatusCode.BADREQUEST,
+                       "Invalid Static Route entry. Please use the " +
+                       "IPAddress/mask format. Default gateway " +
+                       "(0.0.0.0/0) is NOT supported.");
+               Assert.assertEquals(expectedResponse4.toString(), receivedResponse4.toString());
+               
+        StaticRouteConfig staticRouteConfig5 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1");
+               Status receivedResponse5 = staticRouteConfig5.isValid();
+               Status expectedResponse5 = new Status(StatusCode.BADREQUEST,
+                       "Invalid NextHop IP Address configuration. " +
+                               "Please use the X.X.X.X format.");
+               Assert.assertEquals(expectedResponse5.toString(), receivedResponse5.toString());
+       }
+       
+       @Test
+       public void testGetStaticRouteIP() {
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1");
+        InetAddress ip1 = staticRouteConfig1.getStaticRouteIP();
+               Assert.assertEquals("10.1.1.0", ip1.getHostAddress());        
+               
+        StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.0/80", "100.1.1.1");
+        InetAddress ip2 = staticRouteConfig2.getStaticRouteIP();
+               Assert.assertEquals(null, ip2);        
+
+       }
+       
+       @Test
+       public void testGetStaticRouteMask() {
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1");
+               Short receivedMaskLen1 = staticRouteConfig1.getStaticRouteMask();
+               Short expectedMaskLen1 = 24;
+               Assert.assertEquals(expectedMaskLen1, receivedMaskLen1);
+
+               StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.0/40", "100.1.1.1");
+               Short receivedMaskLen2 = staticRouteConfig2.getStaticRouteMask();
+               Short expectedMaskLen2 = 0;
+               Assert.assertEquals(expectedMaskLen2, receivedMaskLen2);
+       }
+       
+       @Test 
+       public void testGetNextHopIP() {
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1");
+        InetAddress ip1 = staticRouteConfig1.getNextHopIP();
+               Assert.assertEquals("100.1.1.1", ip1.getHostAddress());                
+
+               StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1");
+        InetAddress ip2 = staticRouteConfig2.getNextHopIP();
+               Assert.assertEquals(null, ip2);                
+       }
+       
+}
+
diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/StaticRouteTest.java
new file mode 100644 (file)
index 0000000..f05b10c
--- /dev/null
@@ -0,0 +1,109 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.controller.forwarding.staticrouting.StaticRoute.NextHopType;
+import org.opendaylight.controller.hosttracker.hostAware.HostNodeConnector;
+import org.opendaylight.controller.sal.core.ConstructionException;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.opendaylight.controller.sal.utils.NodeCreator;
+
+public class StaticRouteTest {
+       
+       @Test
+       public void testStaticRouteGetSet() {
+               StaticRoute staticRoute = new StaticRoute();
+               InetAddress networkAddress = null;
+               InetAddress mask = null;
+               InetAddress nextHopAddress = null;
+               try {
+                       networkAddress = InetAddress.getByName("10.1.1.0");
+                       mask = InetAddress.getByName("255.255.255.0");
+                       nextHopAddress = InetAddress.getByName("200.0.0.1");
+                       
+               } catch (UnknownHostException e) {
+                       Assert.assertTrue(false);
+               }
+               staticRoute.setNetworkAddress(networkAddress);
+               Assert.assertEquals(networkAddress.getHostAddress(), staticRoute.getNetworkAddress().getHostAddress());
+               staticRoute.setMask(mask);
+               Assert.assertEquals(mask.getHostAddress(), staticRoute.getMask().getHostAddress());
+               staticRoute.setType(NextHopType.IPADDRESS);
+               Assert.assertEquals("nexthop-ip", staticRoute.getType().toString());
+               staticRoute.setNextHopAddress(nextHopAddress);
+               Assert.assertEquals(nextHopAddress.getHostAddress(), staticRoute.getNextHopAddress().getHostAddress());
+               Node node = NodeCreator.createOFNode(((long)10));
+               staticRoute.setNode(node);
+               Assert.assertEquals(node, staticRoute.getNode());
+               NodeConnector nc0 = NodeConnectorCreator.createOFNodeConnector((short)20, node);
+               staticRoute.setPort(nc0);
+               Assert.assertEquals(nc0, staticRoute.getPort());
+        InetAddress ip1 = null;
+        HostNodeConnector h1 = null;
+        try {
+            ip1 = InetAddress.getByName("192.1.1.1");
+        } catch (UnknownHostException e) {
+            Assert.assertTrue(false);
+        }
+        try {
+            h1 = new HostNodeConnector(ip1);
+        } catch (ConstructionException e) {
+            Assert.assertTrue(false);
+        }
+        staticRoute.setHost(h1);
+        Assert.assertEquals(h1, staticRoute.getHost());
+       }
+       
+       @Test
+       public void testStaticRouteComparison() {
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.0/24", "100.1.1.1");
+        StaticRouteConfig staticRouteConfig2 = new StaticRouteConfig("route2", "10.1.1.0/24", "100.2.1.1");
+        StaticRouteConfig staticRouteConfig3 = new StaticRouteConfig("route3", "10.2.1.0/24", "100.3.1.1");
+        StaticRouteConfig staticRouteConfig4 = new StaticRouteConfig("route4", "10.1.1.0/31", "");
+        StaticRoute staticRoute1 = new StaticRoute(staticRouteConfig1);
+        StaticRoute staticRoute2 = new StaticRoute(staticRouteConfig2);
+        StaticRoute staticRoute3 = new StaticRoute(staticRouteConfig3);
+        StaticRoute staticRoute4 = new StaticRoute(staticRouteConfig4);
+
+        Assert.assertTrue(staticRoute1.equals(staticRoute2));
+        Assert.assertFalse(staticRoute1.equals(staticRoute3));
+        Assert.assertFalse(staticRoute1.equals(staticRoute4));
+        
+        Assert.assertTrue(staticRoute1.compareTo(staticRoute2) == 0 ? true : false);
+        Assert.assertFalse(staticRoute1.compareTo(staticRoute3) == 0 ? true : false);
+        Assert.assertTrue(staticRoute1.compareTo(staticRoute4) == 0 ? true : false);
+                       
+       }
+       
+       @Test
+       public void testLongestPrefixMatch() {
+        StaticRouteConfig staticRouteConfig1 = new StaticRouteConfig("route1", "10.1.1.254/24", "100.1.1.1");
+        StaticRoute staticRoute1 = new StaticRoute(staticRouteConfig1);
+               InetAddress ip1 = null;
+               InetAddress ip2 = null;
+               try {
+                       ip1 = InetAddress.getByName("10.1.0.2");
+                       ip2 = InetAddress.getByName("10.1.1.2");
+               } catch (UnknownHostException e) {
+                       Assert.assertTrue(false);
+               }
+        InetAddress rxdIp1 = staticRoute1.longestPrefixMatch(ip1);
+        InetAddress rxdIp2 = staticRoute1.longestPrefixMatch(ip2);
+               Assert.assertEquals(null, rxdIp1);
+               Assert.assertEquals("10.1.1.0", rxdIp2.getHostAddress());
+       }
+}
diff --git a/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java b/opendaylight/forwarding/staticrouting/src/test/java/org/opendaylight/controller/forwarding/staticrouting/internal/StaticRoutingImplementationTest.java
new file mode 100644 (file)
index 0000000..4df0590
--- /dev/null
@@ -0,0 +1,28 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwarding.staticrouting.internal;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StaticRoutingImplementationTest {
+       
+       @Test
+       public void isIPv4AddressValidTest() {
+               StaticRoutingImplementation staticRouteImpl = new StaticRoutingImplementation();
+        Assert.assertTrue(staticRouteImpl.isIPv4AddressValid("192.168.100.0/24"));             
+        Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.100.0/36"));            
+        Assert.assertFalse(staticRouteImpl.isIPv4AddressValid("192.168.300.0/32"));            
+       }
+}
+
+
+
+
diff --git a/opendaylight/forwardingrulesmanager/pom.xml b/opendaylight/forwardingrulesmanager/pom.xml
new file mode 100644 (file)
index 0000000..27c3b1e
--- /dev/null
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.opendaylight.controller</groupId>
+    <artifactId>commons.opendaylight</artifactId>
+    <version>1.4.0-SNAPSHOT</version>
+    <relativePath>../commons/opendaylight</relativePath>
+  </parent>
+
+  <groupId>org.opendaylight.controller</groupId>
+  <artifactId>forwardingrulesmanager</artifactId>
+  <version>0.4.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <build>
+    <plugins>
+      <plugin>
+       <groupId>org.apache.felix</groupId>
+       <artifactId>maven-bundle-plugin</artifactId>
+       <version>2.3.6</version>
+       <extensions>true</extensions>
+       <configuration>
+         <instructions>
+           <Include-Resource>
+           </Include-Resource>
+           <Export-Package>
+             org.opendaylight.controller.forwardingrulesmanager
+           </Export-Package>
+           <Import-Package>
+                     org.opendaylight.controller.clustering.services,
+                     org.opendaylight.controller.configuration,
+              org.opendaylight.controller.hosttracker,
+              org.opendaylight.controller.hosttracker.hostAware,
+              org.opendaylight.controller.switchmanager,
+              org.opendaylight.controller.sal.action,
+              org.opendaylight.controller.sal.core,
+              org.opendaylight.controller.sal.flowprogrammer,
+              org.opendaylight.controller.sal.match,
+                         org.opendaylight.controller.sal.utils,
+              org.opendaylight.controller.sal.packet,
+              javax.xml.bind.annotation,
+              javax.xml.bind,
+              org.apache.felix.dm,
+              org.apache.commons.lang3.builder,
+              org.osgi.service.component,
+              org.slf4j,
+              org.eclipse.osgi.framework.console,
+                         org.osgi.framework
+           </Import-Package>
+        <Bundle-Activator>
+             org.opendaylight.controller.forwardingrulesmanager.internal.Activator
+               </Bundle-Activator>
+            <Require-Bundle>
+              org.opendaylight.controller.hosttracker
+            </Require-Bundle>
+            <Service-Component>
+            </Service-Component>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>hosttracker</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>configuration</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>    
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>clustering.services</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.controller</groupId>
+      <artifactId>switchmanager</artifactId>
+      <version>0.4.0-SNAPSHOT</version>
+    </dependency>
+       <dependency>
+               <groupId>org.opendaylight.controller</groupId>
+               <artifactId>sal</artifactId>
+               <version>0.4.0-SNAPSHOT</version>
+       </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>4.8.1</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java b/opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowConfig.java
new file mode 100644 (file)
index 0000000..f1217b5
--- /dev/null
@@ -0,0 +1,1431 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwardingrulesmanager;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.opendaylight.controller.sal.action.Action;
+import org.opendaylight.controller.sal.action.ActionType;
+import org.opendaylight.controller.sal.action.Controller;
+import org.opendaylight.controller.sal.action.Drop;
+import org.opendaylight.controller.sal.action.Flood;
+import org.opendaylight.controller.sal.action.HwPath;
+import org.opendaylight.controller.sal.action.Loopback;
+import org.opendaylight.controller.sal.action.Output;
+import org.opendaylight.controller.sal.action.PopVlan;
+import org.opendaylight.controller.sal.action.SetDlDst;
+import org.opendaylight.controller.sal.action.SetDlSrc;
+import org.opendaylight.controller.sal.action.SetNwDst;
+import org.opendaylight.controller.sal.action.SetNwSrc;
+import org.opendaylight.controller.sal.action.SetNwTos;
+import org.opendaylight.controller.sal.action.SetTpDst;
+import org.opendaylight.controller.sal.action.SetTpSrc;
+import org.opendaylight.controller.sal.action.SetVlanId;
+import org.opendaylight.controller.sal.action.SetVlanPcp;
+import org.opendaylight.controller.sal.action.SwPath;
+import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.IContainer;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.core.NodeConnector;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.match.Match;
+import org.opendaylight.controller.sal.match.MatchType;
+import org.opendaylight.controller.sal.utils.GlobalConstants;
+import org.opendaylight.controller.sal.utils.HexEncode;
+import org.opendaylight.controller.sal.utils.IPProtocols;
+import org.opendaylight.controller.sal.utils.NetUtils;
+import org.opendaylight.controller.sal.utils.NodeConnectorCreator;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.controller.sal.utils.StatusCode;
+import org.opendaylight.controller.switchmanager.ISwitchManager;
+import org.opendaylight.controller.switchmanager.Switch;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Configuration Java Object which represents a flow configuration information
+ * for Forwarding Rrules Manager.
+ */
+
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.NONE)
+public class FlowConfig implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private static final Logger log = LoggerFactory.getLogger(FlowConfig.class);
+    private static final String staticFlowsGroup = "**StaticFlows";
+    private boolean dynamic;
+    private String status;
+
+    /*
+     * The order of the object data defined below is used directly in the UI built using JSP.
+     * Hence try to keep the order in a more logical way.
+     */
+    @XmlElement
+    private String installInHw;
+    @XmlElement
+    private String name;
+    @XmlElement
+    private Node node;
+    @XmlElement
+    private String ingressPort;
+    private String portGroup;
+    @XmlElement
+    private String priority;
+    @XmlElement
+    private String etherType;
+    @XmlElement
+    private String vlanId;
+    @XmlElement
+    private String vlanPriority;
+    @XmlElement
+    private String dlSrc;
+    @XmlElement
+    private String dlDst;
+    @XmlElement
+    private String nwSrc;
+    @XmlElement
+    private String nwDst;
+    @XmlElement
+    private String protocol;
+    @XmlElement
+    private String tosBits;
+    @XmlElement
+    private String tpSrc;
+    @XmlElement
+    private String tpDst;
+    @XmlElement
+    private String cookie;
+    @XmlElement
+    private String idleTimeout;
+    @XmlElement
+    private String hardTimeout;
+    @XmlElement
+    private List<String> actions;
+
+    private enum EtherIPType {
+        ANY, V4, V6;
+    };
+
+    private enum SetNextHopType {
+        CISCO_EXTENSION("Cisco NextHop Extension"), RESOLVE_L2RW(
+                "Resolve L2 Rewrite");
+
+        private SetNextHopType(String name) {
+            this.name = name;
+        }
+
+        private String name;
+
+        public String toString() {
+            return name;
+        }
+
+        public boolean equals(String type) {
+            if (type.trim().equalsIgnoreCase(name))
+                return true;
+            return false;
+        }
+    }
+
+    public FlowConfig() {
+    }
+
+    public FlowConfig(String installInHw, String name, Node node,
+            String priority, String cookie, String ingressPort,
+            String portGroup, String vlanId, String vlanPriority,
+            String etherType, String srcMac, String dstMac, String protocol,
+            String tosBits, String srcIP, String dstIP, String tpSrc,
+            String tpDst, String idleTimeout, String hardTimeout,
+            List<String> actions) {
+        super();
+        this.installInHw = installInHw;
+        this.name = name;
+        this.node = node;
+        this.priority = priority;
+        this.cookie = cookie;
+        this.ingressPort = ingressPort;
+        this.portGroup = portGroup;
+        this.vlanId = vlanId;
+        this.vlanPriority = vlanPriority;
+        this.etherType = etherType;
+        this.dlSrc = srcMac;
+        this.dlDst = dstMac;
+        this.protocol = protocol;
+        this.tosBits = tosBits;
+        this.nwSrc = srcIP;
+        this.nwDst = dstIP;
+        this.tpSrc = tpSrc;
+        this.tpDst = tpDst;
+        this.idleTimeout = idleTimeout;
+        this.hardTimeout = hardTimeout;
+        this.actions = actions;
+        this.status = StatusCode.SUCCESS.toString();
+    }
+
+    public FlowConfig(FlowConfig from) {
+        this.installInHw = from.installInHw;
+        this.name = from.name;
+        this.node = from.node;
+        this.priority = from.priority;
+        this.cookie = from.cookie;
+        this.ingressPort = from.ingressPort;
+        this.portGroup = from.portGroup;
+        this.vlanId = from.vlanId;
+        this.vlanPriority = from.vlanPriority;
+        this.etherType = from.etherType;
+        this.dlSrc = from.dlSrc;
+        this.dlDst = from.dlDst;
+        this.protocol = from.protocol;
+        this.tosBits = from.tosBits;
+        this.nwSrc = from.nwSrc;
+        this.nwDst = from.nwDst;
+        this.tpSrc = from.tpSrc;
+        this.tpDst = from.tpDst;
+        this.idleTimeout = from.idleTimeout;
+        this.hardTimeout = from.hardTimeout;
+        this.actions = new ArrayList<String>(from.actions);
+    }
+
+    public boolean installInHw() {
+        if (installInHw == null) {
+            // backward compatibility
+            installInHw = "true";
+        }
+        return installInHw.equals("true");
+    }
+
+    public void setInstallInHw(boolean inHw) {
+        installInHw = inHw ? "true" : "false";
+    }
+    
+    public String getInstallInHw() {
+       return installInHw;
+    }
+
+    public boolean isInternalFlow() {
+        // Controller generated static flows have name starting with "**"
+        if (this.name == null)
+            return false;
+        return this.name.startsWith("**");
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        if (name == null) {
+            return;
+        }
+        this.name = name;
+    }
+
+    public Node getNode() {
+        return this.node;
+    }
+
+    public void setNode(Node node) {
+        this.node = node;
+    }
+
+    public String getPriority() {
+        return priority;
+    }
+
+    public void setPriority(String priority) {
+        this.priority = priority;
+    }
+
+    public String getCookie() {
+        return cookie;
+    }
+
+    public void setCookie(String cookie) {
+        this.cookie = cookie;
+    }
+
+    public String getIngressPort() {
+        return ingressPort;
+    }
+
+    public void setIngressPort(String ingressPort) {
+        this.ingressPort = ingressPort;
+    }
+
+    public String getPortGroup() {
+        return portGroup;
+    }
+
+    @Override
+    public String toString() {
+        return "FlowConfig [dynamic=" + dynamic + ", status=" + status
+                + ", installInHw=" + installInHw + ", name=" + name
+                + ", switchId=" + node + ", ingressPort=" + ingressPort
+                + ", portGroup=" + portGroup + ", etherType=" + etherType
+                + ", priority=" + priority + ", vlanId=" + vlanId
+                + ", vlanPriority=" + vlanPriority + ", dlSrc=" + dlSrc
+                + ", dlDst=" + dlDst + ", nwSrc=" + nwSrc + ", nwDst=" + nwDst
+                + ", protocol=" + protocol + ", tosBits=" + tosBits
+                + ", tpSrc=" + tpSrc + ", tpDst=" + tpDst + ", cookie="
+                + cookie + ", idleTimeout=" + idleTimeout + ", hardTimeout="
+                + hardTimeout + ", actions=" + actions + "]";
+    }
+
+    public void setPortGroup(String portGroup) {
+        this.portGroup = portGroup;
+    }
+
+    public String getVlanId() {
+        return vlanId;
+    }
+
+    public void setVlanId(String vlanId) {
+        this.vlanId = vlanId;
+    }
+
+    public String getVlanPriority() {
+        return vlanPriority;
+    }
+
+    public void setVlanPriority(String vlanPriority) {
+        this.vlanPriority = vlanPriority;
+    }
+
+    public String getEtherType() {
+        return etherType;
+    }
+
+    public void setEtherType(String etherType) {
+        this.etherType = etherType;
+    }
+
+    public String getSrcMac() {
+        return dlSrc;
+    }
+
+    public void setSrcMac(String srcMac) {
+        this.dlSrc = srcMac;
+    }
+
+    public String getDstMac() {
+        return dlDst;
+    }
+
+    public void setDstMac(String dstMac) {
+        this.dlDst = dstMac;
+    }
+
+    public String getProtocol() {
+        return protocol;
+    }
+
+    public void setProtocol(String protocol) {
+        this.protocol = protocol;
+    }
+
+    public String getTosBits() {
+        return tosBits;
+    }
+
+    public void setTosBits(String tos_bits) {
+        this.tosBits = tos_bits;
+    }
+
+    public String getSrcIp() {
+        return nwSrc;
+    }
+
+    public void setSrcIp(String src_ip) {
+        this.nwSrc = src_ip;
+    }
+
+    public String getDstIp() {
+        return nwDst;
+    }
+
+    public void setDstIp(String dst_ip) {
+        this.nwDst = dst_ip;
+    }
+
+    public String getSrcPort() {
+        return tpSrc;
+    }
+
+    public void setSrcPort(String src_port) {
+        this.tpSrc = src_port;
+    }
+
+    public String getDstPort() {
+        return tpDst;
+    }
+
+    public void setDstPort(String dst_port) {
+        this.tpDst = dst_port;
+    }
+
+    public String getIdleTimeout() {
+        return idleTimeout;
+    }
+
+    public void setIdleTimeout(String idleTimeout) {
+        this.idleTimeout = idleTimeout;
+    }
+
+    public String getHardTimeout() {
+        return hardTimeout;
+    }
+
+    public void setHardTimeout(String hardTimeout) {
+        this.hardTimeout = hardTimeout;
+    }
+
+    public boolean isIPv6() {
+        if (NetUtils.isIPv6AddressValid(this.getSrcIp())
+                || NetUtils.isIPv6AddressValid(this.getDstIp())) {
+            return true;
+        }
+        return false;
+    }
+
+    public List<String> getActions() {
+        return actions;
+    }
+
+    public void setActions(List<String> actions) {
+        this.actions = actions;
+    }
+
+    public static List<String> getFieldsNames() {
+        List<String> fieldList = new ArrayList<String>();
+        for (Field fld : FlowConfig.class.getDeclaredFields()) {
+            fieldList.add(fld.getName());
+        }
+        // Remove 4 static fields + 2 internal field
+        for (int i = 0; i < 6; i++)
+            fieldList.remove(0);
+
+        return fieldList;
+    }
+
+    public boolean isPortGroupEnabled() {
+        return (portGroup != null);
+    }
+
+    public boolean isDynamic() {
+        return dynamic;
+    }
+
+    public void setDynamic(boolean dynamic) {
+        this.dynamic = dynamic;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public boolean isStatusSuccessful() {
+        return status.equals(StatusCode.SUCCESS.toString());
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((actions == null) ? 0 : actions.hashCode());
+        result = prime * result + ((cookie == null) ? 0 : cookie.hashCode());
+        result = prime * result + ((dlDst == null) ? 0 : dlDst.hashCode());
+        result = prime * result + ((dlSrc == null) ? 0 : dlSrc.hashCode());
+        result = prime * result + (dynamic ? 1231 : 1237);
+        result = prime * result
+                + ((etherType == null) ? 0 : etherType.hashCode());
+        result = prime * result
+                + ((ingressPort == null) ? 0 : ingressPort.hashCode());
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((nwDst == null) ? 0 : nwDst.hashCode());
+        result = prime * result + ((nwSrc == null) ? 0 : nwSrc.hashCode());
+        result = prime * result
+                + ((portGroup == null) ? 0 : portGroup.hashCode());
+        result = prime * result
+                + ((priority == null) ? 0 : priority.hashCode());
+        result = prime * result
+                + ((protocol == null) ? 0 : protocol.hashCode());
+        result = prime * result + ((node == null) ? 0 : node.hashCode());
+        result = prime * result + ((tosBits == null) ? 0 : tosBits.hashCode());
+        result = prime * result + ((tpDst == null) ? 0 : tpDst.hashCode());
+        result = prime * result + ((tpSrc == null) ? 0 : tpSrc.hashCode());
+        result = prime * result + ((vlanId == null) ? 0 : vlanId.hashCode());
+        result = prime * result
+                + ((vlanPriority == null) ? 0 : vlanPriority.hashCode());
+        result = prime * result
+                + ((idleTimeout == null) ? 0 : idleTimeout.hashCode());
+        result = prime * result
+                + ((hardTimeout == null) ? 0 : hardTimeout.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        FlowConfig other = (FlowConfig) obj;
+        if (actions == null) {
+            if (other.actions != null)
+                return false;
+        } else if (!actions.equals(other.actions))
+            return false;
+        if (cookie == null) {
+            if (other.cookie != null)
+                return false;
+        } else if (!cookie.equals(other.cookie))
+            return false;
+        if (dlDst == null) {
+            if (other.dlDst != null)
+                return false;
+        } else if (!dlDst.equals(other.dlDst))
+            return false;
+        if (dlSrc == null) {
+            if (other.dlSrc != null)
+                return false;
+        } else if (!dlSrc.equals(other.dlSrc))
+            return false;
+        if (dynamic != other.dynamic)
+            return false;
+        if (etherType == null) {
+            if (other.etherType != null)
+                return false;
+        } else if (!etherType.equals(other.etherType))
+            return false;
+        if (ingressPort == null) {
+            if (other.ingressPort != null)
+                return false;
+        } else if (!ingressPort.equals(other.ingressPort))
+            return false;
+        if (name == null) {
+            if (other.name != null)
+                return false;
+        } else if (!name.equals(other.name))
+            return false;
+        if (nwDst == null) {
+            if (other.nwDst != null)
+                return false;
+        } else if (!nwDst.equals(other.nwDst))
+            return false;
+        if (nwSrc == null) {
+            if (other.nwSrc != null)
+                return false;
+        } else if (!nwSrc.equals(other.nwSrc))
+            return false;
+        if (portGroup == null) {
+            if (other.portGroup != null)
+                return false;
+        } else if (!portGroup.equals(other.portGroup))
+            return false;
+        if (priority == null) {
+            if (other.priority != null)
+                return false;
+        } else if (!priority.equals(other.priority))
+            return false;
+        if (protocol == null) {
+            if (other.protocol != null)
+                return false;
+        } else if (!protocol.equals(other.protocol))
+            return false;
+        if (node == null) {
+            if (other.node != null)
+                return false;
+        } else if (!node.equals(other.node))
+            return false;
+        if (tosBits == null) {
+            if (other.tosBits != null)
+                return false;
+        } else if (!tosBits.equals(other.tosBits))
+            return false;
+        if (tpDst == null) {
+            if (other.tpDst != null)
+                return false;
+        } else if (!tpDst.equals(other.tpDst))
+            return false;
+        if (tpSrc == null) {
+            if (other.tpSrc != null)
+                return false;
+        } else if (!tpSrc.equals(other.tpSrc))
+            return false;
+        if (vlanId == null) {
+            if (other.vlanId != null)
+                return false;
+        } else if (!vlanId.equals(other.vlanId))
+            return false;
+        if (vlanPriority == null) {
+            if (other.vlanPriority != null)
+                return false;
+        } else if (!vlanPriority.equals(other.vlanPriority))
+            return false;
+        if (idleTimeout == null) {
+            if (other.idleTimeout != null)
+                return false;
+        } else if (!idleTimeout.equals(other.idleTimeout))
+            return false;
+        if (hardTimeout == null) {
+            if (other.hardTimeout != null)
+                return false;
+        } else if (!hardTimeout.equals(other.hardTimeout))
+            return false;
+        return true;
+    }
+
+    public InetAddress getNextHopAddressForL2RWAction() {
+        if (actions != null) {
+            Matcher sstr;
+            for (String actiongrp : actions) {
+                sstr = Pattern.compile("SET_NEXT_HOP=(.*)").matcher(actiongrp);
+                if (sstr.matches()) {
+                    SetNextHopType setNHType = SetNextHopType.CISCO_EXTENSION;
+                    String nextHopInfo = sstr.group(1);
+                    String values[] = nextHopInfo.split("//");
+                    String address = values[0].trim();
+                    String type = null;
+                    if (values.length > 1) {
+                        type = values[1].trim();
+                    }
+
+                    if (type != null) {
+                        for (SetNextHopType nh : SetNextHopType.values()) {
+                            if (nh.equals(type))
+                                setNHType = nh;
+                        }
+                    }
+
+                    log.debug("Get Nexthop address = " + address + " Type = "
+                            + setNHType.toString());
+                    if (setNHType == SetNextHopType.RESOLVE_L2RW) {
+                        try {
+                            return InetAddress.getByName(address);
+                        } catch (Exception e) {
+                            log
+                                    .debug("Exception during nextHopAddress resolution : "
+                                            + e.getMessage());
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    public String getNextHopL2RWUsageError() {
+        return "Could not resolve NextHop IP Address for the selected Switch.<br>"
+                + "Please Check the following configurations.<br>"
+                + "1. Is the NextHop IP address directly connected to the Selected Switch<br>"
+                + "2. If appropriate Subnet Configurations are done in the Switch Manager<br>"
+                + "3. If the Nexthop IP-Address is Correct";
+    }
+
+    public boolean isL2AddressValid(String mac) {
+        if (mac == null) {
+            return false;
+        }
+
+        Pattern macPattern = Pattern
+                .compile("([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}");
+        Matcher mm = macPattern.matcher(mac);
+        if (!mm.matches()) {
+            log
+                    .debug(
+                            "Ethernet address {} is not valid. Example: 00:05:b9:7c:81:5f",
+                            mac);
+            return false;
+        }
+        return true;
+    }
+
+    public boolean isPortValid(Switch sw, Short port) {
+        if (port < 1) {
+            log.debug("port {} is not valid", port);
+            return false;
+        }
+
+        if (sw == null) {
+            log
+                    .debug("switch info is not available. Skip checking if port is part of a switch or not.");
+            return true;
+        }
+
+        Set<NodeConnector> nodeConnectorSet = sw.getNodeConnectors();
+        for (NodeConnector nodeConnector : nodeConnectorSet) {
+            if (((Short) nodeConnector.getID()).equals(port)) {
+                return true;
+            }
+        }
+        log.debug("port {} is not a valid port of node {}", port, sw.getNode());
+        return false;
+    }
+
+    public boolean isVlanIdValid(String vlanId) {
+        int vlan = Integer.decode(vlanId);
+        return ((vlan >= 0) && (vlan < 4096));
+    }
+
+    public boolean isVlanPriorityValid(String vlanPriority) {
+        int pri = Integer.decode(vlanPriority);
+        return ((pri >= 0) && (pri < 8));
+    }
+
+    public boolean isTOSBitsValid(String tosBits) {
+        int tos = Integer.decode(tosBits);
+        return ((tos >= 0) && (tos < 64));
+    }
+
+    public boolean isTpPortValid(String tpPort) {
+        int port = Integer.decode(tpPort);
+        return ((port > 0) && (port <= 0xffff));
+    }
+
+    public boolean isTimeoutValid(String timeout) {
+        int to = Integer.decode(timeout);
+        return ((to >= 0) && (to <= 0xffff));
+    }
+
+    private boolean conflictWithContainerFlow(IContainer container,
+            StringBuffer resultStr) {
+        // Return true if it's default container
+        if (container.getName().equals(GlobalConstants.DEFAULT.toString())) {
+            return false;
+        }
+
+        // No container flow = no conflict
+        List<ContainerFlow> cFlowList = container.getContainerFlows();
+        if (((cFlowList == null)) || cFlowList.isEmpty()) {
+            return false;
+        }
+
+        // Check against each container's flow
+        Flow flow = this.getFlow();
+
+        // Configuration is rejected if it conflicts with _all_ the container flows
+        for (ContainerFlow cFlow : cFlowList) {
+            if (cFlow.allowsFlow(flow)) {
+                log
+                        .trace("Config is congruent with at least one container flow");
+                return false;
+            }
+        }
+        String msg = "Flow Config conflicts with all existing container flows";
+        resultStr.append(msg);
+        log.trace(msg);
+
+        return true;
+    }
+
+    public boolean isValid(IContainer container, StringBuffer resultStr) {
+        EtherIPType etype = EtherIPType.ANY;
+        EtherIPType ipsrctype = EtherIPType.ANY;
+        EtherIPType ipdsttype = EtherIPType.ANY;
+
+        String containerName = (container == null) ? GlobalConstants.DEFAULT
+                .toString() : container.getName();
+        ISwitchManager switchManager = (ISwitchManager) ServiceHelper
+                .getInstance(ISwitchManager.class, containerName, this);
+
+        Switch sw = null;
+        try {
+            if (name == null) {
+                resultStr.append(String.format("Name is null"));
+                return false;
+            }
+            if (node == null) {
+                resultStr.append(String.format("Node is null"));
+                return false;
+            }
+            if (switchManager != null) {
+                for (Switch device : switchManager.getNetworkDevices()) {
+                    if (device.getNode().equals(node)) {
+                        sw = device;
+                        break;
+                    }
+                }
+                if (sw == null) {
+                    resultStr
+                            .append(String.format("Node %s not found", node));
+                    return false;
+                }
+            } else {
+                log.debug("switchmanager is not set yet");
+            }
+
+            if (priority != null) {
+                if (Integer.decode(priority) < 0
+                        || (Integer.decode(priority) > 65535)) {
+                    resultStr.append(String.format(
+                            "priority %s is not in the range 0 - 65535",
+                            priority));
+                    return false;
+                }
+            }
+
+            // make sure it's a valid number
+            if (cookie != null)
+                Long.decode(cookie);
+
+            if (ingressPort != null) {
+                Short port = Short.decode(ingressPort);
+                if (isPortValid(sw, port) == false) {
+                    resultStr
+                            .append(String
+                                    .format(
+                                            "Ingress port %d is not valid for the Switch",
+                                            port));
+                    if ((container != null)
+                            && !container.getName().equals(
+                                    GlobalConstants.DEFAULT.toString())) {
+                        resultStr
+                                .append(" in Container " + container.getName());
+                    }
+                    return false;
+                }
+            }
+
+            if ((vlanId != null) && !isVlanIdValid(vlanId)) {
+                resultStr.append(String.format(
+                        "Vlan ID %s is not in the range 0 - 4095", vlanId));
+                return false;
+            }
+
+            if ((vlanPriority != null) && !isVlanPriorityValid(vlanPriority)) {
+                resultStr.append(String.format(
+                        "Vlan priority %s is not in the range 0 - 7",
+                        vlanPriority));
+                return false;
+            }
+
+            if (etherType != null) {
+                int type = Integer.decode(etherType);
+                if ((type < 0) || (type > 0xffff)) {
+                    resultStr.append(String.format(
+                            "Ethernet type %s is not valid", etherType));
+                    return false;
+                } else {
+                    if (type == 0x800)
+                        etype = EtherIPType.V4;
+                    else if (type == 0x86dd)
+                        etype = EtherIPType.V6;
+                }
+            }
+
+            if ((tosBits != null) && !isTOSBitsValid(tosBits)) {
+                resultStr.append(String.format(
+                        "IP ToS bits %s is not in the range 0 - 63", tosBits));
+                return false;
+            }
+
+            if ((tpSrc != null) && !isTpPortValid(tpSrc)) {
+                resultStr.append(String.format(
+                        "Transport source port %s is not valid", tpSrc));
+                return false;
+            }
+            if ((tpDst != null) && !isTpPortValid(tpDst)) {
+                resultStr.append(String.format(
+                        "Transport destination port %s is not valid", tpDst));
+                return false;
+            }
+
+            if ((dlSrc != null) && !isL2AddressValid(dlSrc)) {
+                resultStr
+                        .append(String
+                                .format(
+                                        "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                                        dlSrc));
+                return false;
+            }
+
+            if ((dlDst != null) && !isL2AddressValid(dlDst)) {
+                resultStr
+                        .append(String
+                                .format(
+                                        "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                                        dlDst));
+                return false;
+            }
+
+            if (nwSrc != null) {
+                if (NetUtils.isIPv4AddressValid(nwSrc)) {
+                    ipsrctype = EtherIPType.V4;
+                } else if (NetUtils.isIPv6AddressValid(nwSrc)) {
+                    ipsrctype = EtherIPType.V6;
+                } else {
+                    resultStr.append(String.format(
+                            "IP source address %s is not valid", nwSrc));
+                    return false;
+                }
+            }
+
+            if (nwDst != null) {
+                if (NetUtils.isIPv4AddressValid(nwDst)) {
+                    ipdsttype = EtherIPType.V4;
+                } else if (NetUtils.isIPv6AddressValid(nwDst)) {
+                    ipdsttype = EtherIPType.V6;
+                } else {
+                    resultStr.append(String.format(
+                            "IP destination address %s is not valid", nwDst));
+                    return false;
+                }
+            }
+
+            if (etype != EtherIPType.ANY) {
+                if ((ipsrctype != EtherIPType.ANY) && (ipsrctype != etype)) {
+                    resultStr.append(String
+                            .format("Type mismatch between Ethernet & Src IP"));
+                    return false;
+                }
+                if ((ipdsttype != EtherIPType.ANY) && (ipdsttype != etype)) {
+                    resultStr.append(String
+                            .format("Type mismatch between Ethernet & Dst IP"));
+                    return false;
+                }
+            }
+            if (ipsrctype != ipdsttype) {
+                if (!((ipsrctype == EtherIPType.ANY) || (ipdsttype == EtherIPType.ANY))) {
+                    resultStr
+                            .append(String.format("IP Src Dest Type mismatch"));
+                    return false;
+                }
+            }
+
+            if ((idleTimeout != null) && !isTimeoutValid(idleTimeout)) {
+                resultStr.append(String.format(
+                        "Idle Timeout value %s is not valid", idleTimeout));
+                return false;
+            }
+
+            if ((hardTimeout != null) && !isTimeoutValid(hardTimeout)) {
+                resultStr.append(String.format(
+                        "Hard Timeout value %s is not valid", hardTimeout));
+                return false;
+            }
+
+            Matcher sstr;
+            if (actions != null && !actions.isEmpty()) {
+                for (String actiongrp : actions) {
+                    // check output ports
+                    sstr = Pattern.compile("OUTPUT=(.*)").matcher(actiongrp);
+                    if (sstr.matches()) {
+                        for (String t : sstr.group(1).split(",")) {
+                            Matcher n = Pattern.compile("(?:(\\d+))")
+                                    .matcher(t);
+                            if (n.matches()) {
+                                if (n.group(1) != null) {
+                                    Short port = Short.parseShort(n.group(1));
+                                    if (isPortValid(sw, port) == false) {
+                                        resultStr
+                                                .append(String
+                                                        .format(
+                                                                "Output port %d is not valid for this switch",
+                                                                port));
+                                        if ((container != null)
+                                                && !container.getName().equals(
+                                                        GlobalConstants.DEFAULT
+                                                                .toString())) {
+                                            resultStr.append(" in Container "
+                                                    + container.getName());
+                                        }
+                                        return false;
+                                    }
+                                }
+                            }
+                        }
+                        continue;
+                    }
+                    // Check src IP
+                    sstr = Pattern.compile(ActionType.FLOOD.toString())
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if (container != null) {
+                            resultStr.append(String.format(
+                                    "flood is not allowed in container %s",
+                                    container.getName()));
+                            return false;
+                        }
+                        continue;
+                    }
+                    // Check src IP
+                    sstr = Pattern.compile(
+                            ActionType.SET_NW_SRC.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
+                            resultStr.append(String.format(
+                                    "IP source address %s is not valid", sstr
+                                            .group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+                    // Check dst IP
+                    sstr = Pattern.compile(
+                            ActionType.SET_NW_DST.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if (!NetUtils.isIPv4AddressValid(sstr.group(1))) {
+                            resultStr.append(String.format(
+                                    "IP destination address %s is not valid",
+                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_VLAN_ID.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isVlanIdValid(sstr.group(1))) {
+                            resultStr.append(String.format(
+                                    "Vlan ID %s is not in the range 0 - 4095",
+                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_VLAN_PCP.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isVlanPriorityValid(sstr.group(1))) {
+                            resultStr
+                                    .append(String
+                                            .format(
+                                                    "Vlan priority %s is not in the range 0 - 7",
+                                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_DL_SRC.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isL2AddressValid(sstr.group(1))) {
+                            resultStr
+                                    .append(String
+                                            .format(
+                                                    "Ethernet source address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_DL_DST.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isL2AddressValid(sstr.group(1))) {
+                            resultStr
+                                    .append(String
+                                            .format(
+                                                    "Ethernet destination address %s is not valid. Example: 00:05:b9:7c:81:5f",
+                                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_NW_TOS.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isTOSBitsValid(sstr.group(1))) {
+                            resultStr
+                                    .append(String
+                                            .format(
+                                                    "IP ToS bits %s is not in the range 0 - 63",
+                                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_TP_SRC.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isTpPortValid(sstr.group(1))) {
+                            resultStr.append(String.format(
+                                    "Transport source port %s is not valid",
+                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+
+                    sstr = Pattern.compile(
+                            ActionType.SET_TP_DST.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        if ((sstr.group(1) != null)
+                                && !isTpPortValid(sstr.group(1))) {
+                            resultStr
+                                    .append(String
+                                            .format(
+                                                    "Transport destination port %s is not valid",
+                                                    sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+                    sstr = Pattern.compile(
+                            ActionType.SET_NEXT_HOP.toString() + "=(.*)")
+                            .matcher(actiongrp);
+                    if (sstr.matches()) {
+                        String nextHopInfo = sstr.group(1);
+                        String values[] = nextHopInfo.split("//");
+                        String address = values[0].trim();
+
+                        if ((address == null) || !isOutputNextHopValid(address)) {
+                            resultStr.append(String.format(
+                                    "next hop %s is not valid", sstr.group(1)));
+                            return false;
+                        }
+                        continue;
+                    }
+                }
+            }
+            // Check against the container flow
+            if ((container != null)
+                    && conflictWithContainerFlow(container, resultStr)) {
+                return false;
+            }
+        } catch (NumberFormatException e) {
+            resultStr.append(String.format("Invalid number format %s", e
+                    .getMessage()));
+            return false;
+        }
+
+        return true;
+    }
+
+    public FlowEntry getFlowEntry() {
+        return new FlowEntry(FlowConfig.staticFlowsGroup, this.name, this
+                .getFlow(), this.getNode());
+    }
+
+    public Flow getFlow() {
+        Match match = new Match();
+
+        if (this.ingressPort != null) {
+            match.setField(MatchType.IN_PORT, NodeConnectorCreator
+                    .createOFNodeConnector(Short.parseShort(ingressPort),
+                            getNode()));
+        }
+        if (this.dlSrc != null) {
+            match.setField(MatchType.DL_SRC, HexEncode
+                    .bytesFromHexString(this.dlSrc));
+        }
+        if (this.dlDst != null) {
+            match.setField(MatchType.DL_DST, HexEncode
+                    .bytesFromHexString(this.dlDst));
+        }
+        if (this.etherType != null) {
+            match.setField(MatchType.DL_TYPE, Integer.decode(etherType)
+                    .shortValue());
+        }
+        if (this.vlanId != null) {
+            match.setField(MatchType.DL_VLAN, Short.parseShort(this.vlanId));
+        }
+        if (this.vlanPriority != null) {
+            match.setField(MatchType.DL_VLAN_PR, Byte
+                    .parseByte(this.vlanPriority));
+        }
+        if (this.nwSrc != null) {
+            String parts[] = this.nwSrc.split("/");
+            InetAddress ip = NetUtils.parseInetAddress(parts[0]);
+            InetAddress mask = null;
+            if (parts.length > 1) {
+                int maskLen = Integer.parseInt(parts[1]);
+                mask = NetUtils.getInetNetworkMask(maskLen,
+                        ip instanceof Inet6Address);
+            }
+            match.setField(MatchType.NW_SRC, ip, mask);
+        }
+        if (this.nwDst != null) {
+            String parts[] = this.nwDst.split("/");
+            InetAddress ip = NetUtils.parseInetAddress(parts[0]);
+            InetAddress mask = null;
+            if (parts.length > 1) {
+                int maskLen = Integer.parseInt(parts[1]);
+                mask = NetUtils.getInetNetworkMask(maskLen,
+                        ip instanceof Inet6Address);
+            }
+            match.setField(MatchType.NW_DST, ip, mask);
+        }
+        if (this.protocol != null) {
+            match.setField(MatchType.NW_PROTO, IPProtocols
+                    .getProtocolNumberByte(this.protocol));
+        }
+        if (this.tosBits != null) {
+            match.setField(MatchType.NW_TOS, Byte.parseByte(this.tosBits));
+        }
+        if (this.tpSrc != null) {
+            match.setField(MatchType.TP_SRC, Integer.valueOf(this.tpSrc)
+                    .shortValue());
+        }
+        if (this.tpDst != null) {
+            match.setField(MatchType.TP_DST, Integer.valueOf(this.tpDst)
+                    .shortValue());
+        }
+
+        Flow flow = new Flow(match, getActionList());
+        if (this.cookie != null) {
+            flow.setId(Long.parseLong(cookie));
+        }
+        if (this.hardTimeout != null) {
+            flow.setHardTimeout(Short.parseShort(this.hardTimeout));
+        }
+        if (this.idleTimeout != null) {
+            flow.setIdleTimeout(Short.parseShort(idleTimeout));
+        }
+        if (this.priority != null) {
+            flow.setPriority(Integer.decode(this.priority).shortValue());
+        }
+        return flow;
+    }
+
+    public boolean isOutputNextHopValid(String onh) {
+        if (onh == null) {
+            return false;
+        }
+        /*
+         * For now, only takes IPv4 or IPv6 address
+         */
+        return (NetUtils.isIPv4AddressValid(onh) || NetUtils
+                .isIPv6AddressValid(onh));
+    }
+
+    public boolean isByNameAndNodeIdEqual(FlowConfig that) {
+        return (this.name.equals(that.name) && this.node.equals(that.node));
+    }
+
+    public boolean isByNameAndNodeIdEqual(String name, Node node) {
+        return (this.name.equals(name) && this.node.equals(node));
+    }
+
+    public boolean onNode(Node node) {
+        return this.node.equals(node);
+    }
+
+    public static List<String> getSupportedNextHopTypes() {
+        List<String> s = new ArrayList<String>();
+        for (SetNextHopType nh : SetNextHopType.values()) {
+            s.add(nh.toString());
+        }
+        return s;
+    }
+
+    public void toggleStatus() {
+        installInHw = (installInHw == null) ? "true" : (installInHw
+                .equals("true")) ? "false" : "true";
+    }
+
+    /*
+     * Parses the actions string and return the List of SAL Action
+     * No syntax check run, as this function will be called when the
+     * config validation check has already been performed
+     */
+    private List<Action> getActionList() {
+        List<Action> actionList = new ArrayList<Action>();
+
+        if (actions != null) {
+            Matcher sstr;
+            for (String actiongrp : actions) {
+                sstr = Pattern.compile(ActionType.OUTPUT + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    for (String t : sstr.group(1).split(",")) {
+                        Matcher n = Pattern.compile("(?:(\\d+))").matcher(t);
+                        if (n.matches()) {
+                            if (n.group(1) != null) {
+                                short ofPort = Short.parseShort(n.group(1));
+                                actionList.add(new Output(NodeConnectorCreator
+                                        .createOFNodeConnector(ofPort, this
+                                                .getNode())));
+                            }
+                        }
+                    }
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.DROP.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new Drop());
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.LOOPBACK.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new Loopback());
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.FLOOD.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new Flood());
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.SW_PATH.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SwPath());
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.HW_PATH.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new HwPath());
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.CONTROLLER.toString())
+                        .matcher(actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new Controller());
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_VLAN_ID.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetVlanId(Short
+                            .parseShort(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_VLAN_PCP.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList
+                            .add(new SetVlanPcp(Byte.parseByte(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(ActionType.POP_VLAN.toString()).matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new PopVlan());
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_DL_SRC.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetDlSrc(HexEncode
+                            .bytesFromHexString(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_DL_DST.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetDlDst(HexEncode
+                            .bytesFromHexString(sstr.group(1))));
+                    continue;
+                }
+                sstr = Pattern.compile(
+                        ActionType.SET_NW_SRC.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetNwSrc(NetUtils.parseInetAddress(sstr
+                            .group(1))));
+                    continue;
+                }
+                sstr = Pattern.compile(
+                        ActionType.SET_NW_DST.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetNwDst(NetUtils.parseInetAddress(sstr
+                            .group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_NW_TOS.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList.add(new SetNwTos(Byte.parseByte(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_TP_SRC.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList
+                            .add(new SetTpSrc(Integer.valueOf(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_TP_DST.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    actionList
+                            .add(new SetTpDst(Integer.valueOf(sstr.group(1))));
+                    continue;
+                }
+
+                sstr = Pattern.compile(
+                        ActionType.SET_NEXT_HOP.toString() + "=(.*)").matcher(
+                        actiongrp);
+                if (sstr.matches()) {
+                    log.warn("We do not handle next hop action yet....");
+                    continue;
+                }
+            }
+        }
+        return actionList;
+    }
+
+}
diff --git a/opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java b/opendaylight/forwardingrulesmanager/src/main/java/org/opendaylight/controller/forwardingrulesmanager/FlowEntry.java
new file mode 100644 (file)
index 0000000..2ab1a05
--- /dev/null
@@ -0,0 +1,137 @@
+
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.forwardingrulesmanager;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.opendaylight.controller.sal.core.ContainerFlow;
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.flowprogrammer.Flow;
+import org.opendaylight.controller.sal.match.Match;
+
+/**
+ * Represents a flow applications request Forwarding Rules Manager to install
+ * on a network node. A FlowEntry is constituted of a flow (match + actions),
+ * the target network node, and the flow name. It also includes a group name. 
+ * For instance the flows constituting a policy all share the same group name.
+ */
+public class FlowEntry implements Cloneable, Serializable {
+    private static final long serialVersionUID = 1L;
+    private String groupName; // group name
+    private String flowName; // flow name (may be null)
+    private Node node; // network node where to install the flow
+    private Flow flow; // match + action
+
+    public FlowEntry(String groupName, String flowName, Flow flow, Node node) {
+        this.groupName = groupName;
+        this.flow = flow;
+        this.node = node;
+        this.flowName = (flowName != null) ? flowName : constructFlowName();
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public void setGroupName(String name) {
+        this.groupName = name;
+    }
+
+    /**
+     * Return the actual Flow contained in this entry
+     *
+     * @return the flow
+     */
+    public Flow getFlow() {
+        return flow;
+    }
+
+    public Node getNode() {
+        return node;
+    }
+
+    public void setNode(Node n) {
+        this.node = n;
+    }
+
+    public String getFlowName() {
+        return flowName;
+    }
+
+    public void setFlowName(String n) {
+        this.flowName = n;
+    }
+
+    @Override
+    public FlowEntry clone() {
+        FlowEntry cloned = null;
+        try {
+            cloned = (FlowEntry) super.clone();
+            cloned.flow = this.flow.clone();
+        } catch (CloneNotSupportedException e) {
+            e.printStackTrace();
+        }
+        return cloned;
+    }
+
+    @Override
+    public int hashCode() {
+        return HashCodeBuilder.reflectionHashCode(this);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        return EqualsBuilder.reflectionEquals(this, obj);
+    }
+
+    @Override
+    public String toString() {
+        return "FlowEntry[flowName = " + flowName + ", groupName = "
+                + groupName + ",node = " + node + ", flow = " + flow + "]";
+    }
+
+    private String constructFlowName() {
+        return this.groupName + "_" + new Date().toString();
+    }
+
+    public boolean equalsByNodeAndName(Node node, String flowName) {
+        return this.node.equals(node) && this.flowName.equals(flowName);