aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/apps
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/apps')
-rw-r--r--framework/src/onos/apps/aaa/features.xml1
-rw-r--r--framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaConfig.java239
-rw-r--r--framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaManager.java562
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaIntegrationTest.java151
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaManagerTest.java258
-rw-r--r--framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaTestBase.java224
-rw-r--r--framework/src/onos/apps/bgprouter/features.xml1
-rw-r--r--framework/src/onos/apps/cordvtn/pom.xml9
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java287
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java133
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java231
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DestinationInfo.java190
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java64
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java57
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java57
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java74
-rw-r--r--framework/src/onos/apps/dhcp/app/features.xml1
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java169
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGet.json26
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetAvailable.json16
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetMappings.json16
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigPut.json17
-rw-r--r--framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java2
-rw-r--r--framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/Olt.java359
-rw-r--r--framework/src/onos/apps/openstackswitching/api/pom.xml50
-rw-r--r--framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java)5
-rw-r--r--framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java)14
-rw-r--r--framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java)16
-rw-r--r--framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java)43
-rw-r--r--framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/package-info.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java)0
-rw-r--r--framework/src/onos/apps/openstackswitching/app/app.xml24
-rw-r--r--framework/src/onos/apps/openstackswitching/app/features.xml28
-rw-r--r--framework/src/onos/apps/openstackswitching/app/pom.xml137
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java)20
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackRestHandler.java179
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingConfig.java127
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java374
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java307
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/package-info.java20
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java)3
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java)42
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java)5
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java)46
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java)19
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java)47
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/package-info.java (renamed from framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java)0
-rw-r--r--framework/src/onos/apps/openstackswitching/app/src/main/webapp/WEB-INF/web.xml (renamed from framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml)0
-rw-r--r--framework/src/onos/apps/openstackswitching/network-cfg.json55
-rw-r--r--framework/src/onos/apps/openstackswitching/pom.xml97
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java471
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java227
-rw-r--r--framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java2
-rw-r--r--framework/src/onos/apps/routing-api/src/main/java/org/onosproject/routing/RouteEntry.java10
-rw-r--r--framework/src/onos/apps/routing-api/src/test/java/org/onosproject/routing/RouteEntryTest.java22
-rw-r--r--framework/src/onos/apps/sdnip/features.xml1
-rw-r--r--framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIpFib.java19
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java11
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java174
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java18
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java2
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java4
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java117
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java4
-rw-r--r--framework/src/onos/apps/virtualbng/features.xml1
-rw-r--r--framework/src/onos/apps/vtn/app/features.xml1
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/pom.xml67
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java43
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstaller.java46
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/DefaultFlowClassifierInstaller.java45
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java70
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java125
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java70
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java585
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java44
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java105
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/DnatService.java46
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java97
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L3ForwardService.java47
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/SnatService.java49
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java196
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/DnatServiceImpl.java88
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java211
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L3ForwardServiceImpl.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/SnatServiceImpl.java90
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/DataPathIdGenerator.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java123
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java97
-rw-r--r--framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFloatingIp.java140
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java146
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIp.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIpId.java85
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterInterface.java119
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpCreateCommand.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpQueryCommand.java92
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpRemoveCommand.java90
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpUpdateCommand.java103
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterCreateCommand.java97
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterQueryCommand.java76
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterRemoveCommand.java71
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterUpdateCommand.java99
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceCreateCommand.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceQueryCommand.java56
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceRemoveCommand.java50
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java77
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java123
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscListener.java26
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java60
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpListener.java25
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpService.java108
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java348
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java44
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java55
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterEvent.java59
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterListener.java25
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterService.java90
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/RouterManager.java269
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceEvent.java62
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceListener.java27
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceService.java80
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/RouterInterfaceManager.java235
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java94
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java472
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/subnet/impl/SubnetManager.java42
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/resources/OSGI-INF/blueprint/shell-config.xml33
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/AllowedAddressPairTest.java75
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultAllocationPoolTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultFlowClassifierTest.java143
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultHostRouteTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultNeutronNetworkTest.java77
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortChainTest.java134
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairGroupTest.java112
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairTest.java97
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultVirtualPortTest.java132
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FixedIpTest.java70
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FlowClassifierIdTest.java68
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PhysicalNetworkTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortChainIdTest.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairGroupIdTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterGatewayTest.java79
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterIdTest.java62
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SecurityGroupTest.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SegmentationIdTest.java63
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SubnetIdTest.java63
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantIdTest.java63
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantNetworkIdTest.java63
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/VirtualPortIdTest.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/DefaultFloatingIpTest.java125
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/FloatingIpIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManagerTest.java146
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/impl/PortChainManagerTest.java155
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/impl/PortPairManagerTest.java126
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManagerTest.java140
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/DefaultRouterTest.java114
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/RouterInterfaceTest.java97
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapAdapter.java114
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java242
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceTest.java25
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java285
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java38
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/RouterWebResource.java447
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java139
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java98
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterCodec.java91
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterGatewayInfoCodec.java39
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java296
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java232
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/VtnResourceTest.java54
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/FlowClassifierCodecTest.java98
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-FlowClassifier.json14
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPair.json9
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/flowClassifier.json11
-rw-r--r--framework/src/onos/apps/xos-integration/features.xml1
-rw-r--r--framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java545
198 files changed, 16962 insertions, 1232 deletions
diff --git a/framework/src/onos/apps/aaa/features.xml b/framework/src/onos/apps/aaa/features.xml
index 3825ec5c..e965d41a 100644
--- a/framework/src/onos/apps/aaa/features.xml
+++ b/framework/src/onos/apps/aaa/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaConfig.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaConfig.java
new file mode 100644
index 00000000..db821ca2
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaConfig.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.aaa;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.basics.BasicElementConfig;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Network config for the AAA app.
+ */
+public class AaaConfig extends Config<ApplicationId> {
+
+ private static final String RADIUS_IP = "radiusIp";
+ private static final String RADIUS_SERVER_PORT = "1812";
+ private static final String RADIUS_MAC = "radiusMac";
+ private static final String NAS_IP = "nasIp";
+ private static final String NAS_MAC = "nasMac";
+ private static final String RADIUS_SECRET = "radiusSecret";
+ private static final String RADIUS_SWITCH = "radiusSwitch";
+ private static final String RADIUS_PORT = "radiusPort";
+
+ // RADIUS server IP address
+ protected static final String DEFAULT_RADIUS_IP = "10.128.10.4";
+
+ // RADIUS MAC address
+ protected static final String DEFAULT_RADIUS_MAC = "00:00:00:00:01:10";
+
+ // NAS IP address
+ protected static final String DEFAULT_NAS_IP = "10.128.9.244";
+
+ // NAS MAC address
+ protected static final String DEFAULT_NAS_MAC = "00:00:00:00:10:01";
+
+ // RADIUS server shared secret
+ protected static final String DEFAULT_RADIUS_SECRET = "ONOSecret";
+
+ // Radius Switch Id
+ protected static final String DEFAULT_RADIUS_SWITCH = "of:90e2ba82f97791e9";
+
+ // Radius Port Number
+ protected static final String DEFAULT_RADIUS_PORT = "129";
+
+ // Radius Server UDP Port Number
+ protected static final String DEFAULT_RADIUS_SERVER_PORT = "1812";
+
+ /**
+ * Gets the value of a string property, protecting for an empty
+ * JSON object.
+ *
+ * @param name name of the property
+ * @param defaultValue default value if none has been specified
+ * @return String value if one os found, default value otherwise
+ */
+ private String getStringProperty(String name, String defaultValue) {
+ if (object == null) {
+ return defaultValue;
+ }
+ return get(name, defaultValue);
+ }
+
+ /**
+ * Returns the NAS ip.
+ *
+ * @return ip address or null if not set
+ */
+ public InetAddress nasIp() {
+ try {
+ return InetAddress.getByName(getStringProperty(NAS_IP, DEFAULT_NAS_IP));
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the NAS ip.
+ *
+ * @param ip new ip address; null to clear
+ * @return self
+ */
+ public BasicElementConfig nasIp(String ip) {
+ return (BasicElementConfig) setOrClear(NAS_IP, ip);
+ }
+
+ /**
+ * Returns the RADIUS server ip.
+ *
+ * @return ip address or null if not set
+ */
+ public InetAddress radiusIp() {
+ try {
+ return InetAddress.getByName(getStringProperty(RADIUS_IP, DEFAULT_RADIUS_IP));
+ } catch (UnknownHostException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the RADIUS server ip.
+ *
+ * @param ip new ip address; null to clear
+ * @return self
+ */
+ public BasicElementConfig radiusIp(String ip) {
+ return (BasicElementConfig) setOrClear(RADIUS_IP, ip);
+ }
+
+ /**
+ * Returns the RADIUS MAC address.
+ *
+ * @return mac address or null if not set
+ */
+ public String radiusMac() {
+ return getStringProperty(RADIUS_MAC, DEFAULT_RADIUS_MAC);
+ }
+
+ /**
+ * Sets the RADIUS MAC address.
+ *
+ * @param mac new MAC address; null to clear
+ * @return self
+ */
+ public BasicElementConfig radiusMac(String mac) {
+ return (BasicElementConfig) setOrClear(RADIUS_MAC, mac);
+ }
+
+ /**
+ * Returns the RADIUS MAC address.
+ *
+ * @return mac address or null if not set
+ */
+ public String nasMac() {
+ return getStringProperty(NAS_MAC, DEFAULT_NAS_MAC);
+ }
+
+ /**
+ * Sets the RADIUS MAC address.
+ *
+ * @param mac new MAC address; null to clear
+ * @return self
+ */
+ public BasicElementConfig nasMac(String mac) {
+ return (BasicElementConfig) setOrClear(NAS_MAC, mac);
+ }
+
+ /**
+ * Returns the RADIUS secret.
+ *
+ * @return radius secret or null if not set
+ */
+ public String radiusSecret() {
+ return getStringProperty(RADIUS_SECRET, DEFAULT_RADIUS_SECRET);
+ }
+
+ /**
+ * Sets the RADIUS secret.
+ *
+ * @param secret new MAC address; null to clear
+ * @return self
+ */
+ public BasicElementConfig radiusSecret(String secret) {
+ return (BasicElementConfig) setOrClear(RADIUS_SECRET, secret);
+ }
+
+ /**
+ * Returns the ID of the RADIUS switch.
+ *
+ * @return radius switch ID or null if not set
+ */
+ public String radiusSwitch() {
+ return getStringProperty(RADIUS_SWITCH, DEFAULT_RADIUS_SWITCH);
+ }
+
+ /**
+ * Sets the ID of the RADIUS switch.
+ *
+ * @param switchId new RADIUS switch ID; null to clear
+ * @return self
+ */
+ public BasicElementConfig radiusSwitch(String switchId) {
+ return (BasicElementConfig) setOrClear(RADIUS_SWITCH, switchId);
+ }
+
+ /**
+ * Returns the RADIUS port.
+ *
+ * @return radius port or null if not set
+ */
+ public long radiusPort() {
+ return Integer.parseInt(getStringProperty(RADIUS_PORT, DEFAULT_RADIUS_PORT));
+ }
+
+ /**
+ * Sets the RADIUS port.
+ *
+ * @param port new RADIUS port; null to clear
+ * @return self
+ */
+ public BasicElementConfig radiusPort(long port) {
+ return (BasicElementConfig) setOrClear(RADIUS_PORT, port);
+ }
+
+ /**
+ * Returns the RADIUS server UDP port.
+ *
+ * @return radius server UDP port.
+ */
+ public short radiusServerUdpPort() {
+ return Short.parseShort(getStringProperty(RADIUS_SERVER_PORT,
+ DEFAULT_RADIUS_SERVER_PORT));
+ }
+
+ /**
+ * Sets the RADIUS port.
+ *
+ * @param port new RADIUS UDP port; -1 to clear
+ * @return self
+ */
+ public BasicElementConfig radiusServerUdpPort(short port) {
+ return (BasicElementConfig) setOrClear(RADIUS_SERVER_PORT, (long) port);
+ }
+
+}
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaManager.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaManager.java
new file mode 100644
index 00000000..dd324eee
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AaaManager.java
@@ -0,0 +1,562 @@
+/*
+ * Copyright 2015 AT&T Foundry
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.aaa;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.onlab.packet.DeserializationException;
+import org.onlab.packet.EAP;
+import org.onlab.packet.EAPOL;
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.RADIUS;
+import org.onlab.packet.RADIUSAttribute;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.xosintegration.VoltTenantService;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.nio.ByteBuffer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+import static org.onosproject.net.packet.PacketPriority.CONTROL;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * AAA application for ONOS.
+ */
+@Component(immediate = true)
+public class AaaManager {
+
+ // for verbose output
+ private final Logger log = getLogger(getClass());
+
+ // a list of our dependencies :
+ // to register with ONOS as an application - described next
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ // to receive Packet-in events that we'll respond to
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VoltTenantService voltTenantService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry netCfgService;
+
+ // Parsed RADIUS server addresses
+ protected InetAddress radiusIpAddress;
+ protected String radiusMacAddress;
+
+ // NAS IP address
+ protected InetAddress nasIpAddress;
+ protected String nasMacAddress;
+
+ // RADIUS server secret
+ protected String radiusSecret;
+
+ // ID of RADIUS switch
+ protected String radiusSwitch;
+
+ // RADIUS port number
+ protected long radiusPort;
+
+ // RADIUS server TCP port number
+ protected short radiusServerPort;
+
+ // our application-specific event handler
+ private ReactivePacketProcessor processor = new ReactivePacketProcessor();
+
+ // our unique identifier
+ private ApplicationId appId;
+
+ // Socket used for UDP communications with RADIUS server
+ private DatagramSocket radiusSocket;
+
+ // Executor for RADIUS communication thread
+ private ExecutorService executor;
+
+ // Configuration properties factory
+ private final ConfigFactory factory =
+ new ConfigFactory<ApplicationId, AaaConfig>(APP_SUBJECT_FACTORY,
+ AaaConfig.class,
+ "AAA") {
+ @Override
+ public AaaConfig createConfig() {
+ return new AaaConfig();
+ }
+ };
+
+ // Listener for config changes
+ private final InternalConfigListener cfgListener = new InternalConfigListener();
+
+ /**
+ * Builds an EAPOL packet based on the given parameters.
+ *
+ * @param dstMac destination MAC address
+ * @param srcMac source MAC address
+ * @param vlan vlan identifier
+ * @param eapolType EAPOL type
+ * @param eap EAP payload
+ * @return Ethernet frame
+ */
+ private static Ethernet buildEapolResponse(MacAddress dstMac, MacAddress srcMac,
+ short vlan, byte eapolType, EAP eap) {
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(dstMac.toBytes());
+ eth.setSourceMACAddress(srcMac.toBytes());
+ eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
+ if (vlan != Ethernet.VLAN_UNTAGGED) {
+ eth.setVlanID(vlan);
+ }
+ //eapol header
+ EAPOL eapol = new EAPOL();
+ eapol.setEapolType(eapolType);
+ eapol.setPacketLength(eap.getLength());
+
+ //eap part
+ eapol.setPayload(eap);
+
+ eth.setPayload(eapol);
+ eth.setPad(true);
+ return eth;
+ }
+
+ @Activate
+ public void activate() {
+ netCfgService.addListener(cfgListener);
+ netCfgService.registerConfigFactory(factory);
+
+ // "org.onosproject.aaa" is the FQDN of our app
+ appId = coreService.registerApplication("org.onosproject.aaa");
+
+ cfgListener.reconfigureNetwork(netCfgService.getConfig(appId, AaaConfig.class));
+
+ // register our event handler
+ packetService.addProcessor(processor, PacketProcessor.director(2));
+ requestIntercepts();
+
+ StateMachine.initializeMaps();
+
+ try {
+ radiusSocket = new DatagramSocket(radiusServerPort);
+ } catch (Exception ex) {
+ log.error("Can't open RADIUS socket", ex);
+ }
+
+ executor = Executors.newSingleThreadExecutor(
+ new ThreadFactoryBuilder()
+ .setNameFormat("AAA-radius-%d").build());
+ executor.execute(radiusListener);
+ }
+
+ @Deactivate
+ public void deactivate() {
+ appId = coreService.registerApplication("org.onosproject.aaa");
+ withdrawIntercepts();
+ // de-register and null our handler
+ packetService.removeProcessor(processor);
+ processor = null;
+ StateMachine.destroyMaps();
+ radiusSocket.close();
+ executor.shutdownNow();
+ }
+
+ protected void sendRadiusPacket(RADIUS radiusPacket) {
+
+ try {
+ final byte[] data = radiusPacket.serialize();
+ final DatagramSocket socket = radiusSocket;
+
+ DatagramPacket packet =
+ new DatagramPacket(data, data.length,
+ radiusIpAddress, radiusServerPort);
+
+ socket.send(packet);
+ } catch (IOException e) {
+ log.info("Cannot send packet to RADIUS server", e);
+ }
+ }
+
+ /**
+ * Request packet in via PacketService.
+ */
+ private void requestIntercepts() {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
+ packetService.requestPackets(selector.build(),
+ CONTROL, appId);
+ }
+
+ /**
+ * Cancel request for packet in via PacketService.
+ */
+ private void withdrawIntercepts() {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.matchEthType(EthType.EtherType.EAPOL.ethType().toShort());
+ packetService.cancelPackets(selector.build(), CONTROL, appId);
+ }
+
+ /**
+ * Send the ethernet packet to the supplicant.
+ *
+ * @param ethernetPkt the ethernet packet
+ * @param connectPoint the connect point to send out
+ */
+ private void sendPacketToSupplicant(Ethernet ethernetPkt, ConnectPoint connectPoint) {
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(connectPoint.port()).build();
+ OutboundPacket packet = new DefaultOutboundPacket(connectPoint.deviceId(),
+ treatment, ByteBuffer.wrap(ethernetPkt.serialize()));
+ packetService.emit(packet);
+ }
+
+ // our handler defined as a private inner class
+
+ /**
+ * Packet processor responsible for forwarding packets along their paths.
+ */
+ private class ReactivePacketProcessor implements PacketProcessor {
+ @Override
+ public void process(PacketContext context) {
+
+ // Extract the original Ethernet frame from the packet information
+ InboundPacket pkt = context.inPacket();
+ Ethernet ethPkt = pkt.parsed();
+ if (ethPkt == null) {
+ return;
+ }
+ try {
+ // identify if incoming packet comes from supplicant (EAP) or RADIUS
+ switch (EthType.EtherType.lookup(ethPkt.getEtherType())) {
+ case EAPOL:
+ handleSupplicantPacket(context.inPacket());
+ break;
+ default:
+ log.trace("Skipping Ethernet packet type {}",
+ EthType.EtherType.lookup(ethPkt.getEtherType()));
+ }
+ } catch (StateMachineException e) {
+ log.warn("Unable to process RADIUS packet:", e);
+ }
+ }
+
+ /**
+ * Creates and initializes common fields of a RADIUS packet.
+ *
+ * @param stateMachine state machine for the request
+ * @param eapPacket EAP packet
+ * @return RADIUS packet
+ */
+ private RADIUS getRadiusPayload(StateMachine stateMachine, byte identifier, EAP eapPacket) {
+ RADIUS radiusPayload =
+ new RADIUS(RADIUS.RADIUS_CODE_ACCESS_REQUEST,
+ eapPacket.getIdentifier());
+
+ // set Request Authenticator in StateMachine
+ stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
+
+ radiusPayload.setIdentifier(identifier);
+ radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME,
+ stateMachine.username());
+
+ radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP,
+ AaaManager.this.nasIpAddress.getAddress());
+
+ radiusPayload.encapsulateMessage(eapPacket);
+
+ return radiusPayload;
+ }
+
+ /**
+ * Handles PAE packets (supplicant).
+ *
+ * @param inPacket Ethernet packet coming from the supplicant
+ */
+ private void handleSupplicantPacket(InboundPacket inPacket) throws StateMachineException {
+ Ethernet ethPkt = inPacket.parsed();
+ // Where does it come from?
+ MacAddress srcMac = ethPkt.getSourceMAC();
+
+ DeviceId deviceId = inPacket.receivedFrom().deviceId();
+ PortNumber portNumber = inPacket.receivedFrom().port();
+ String sessionId = deviceId.toString() + portNumber.toString();
+ StateMachine stateMachine = StateMachine.lookupStateMachineBySessionId(sessionId);
+ if (stateMachine == null) {
+ stateMachine = new StateMachine(sessionId, voltTenantService);
+ }
+
+
+ EAPOL eapol = (EAPOL) ethPkt.getPayload();
+
+ switch (eapol.getEapolType()) {
+ case EAPOL.EAPOL_START:
+ stateMachine.start();
+ stateMachine.setSupplicantConnectpoint(inPacket.receivedFrom());
+
+ //send an EAP Request/Identify to the supplicant
+ EAP eapPayload = new EAP(EAP.REQUEST, stateMachine.identifier(), EAP.ATTR_IDENTITY, null);
+ Ethernet eth = buildEapolResponse(srcMac, MacAddress.valueOf(nasMacAddress),
+ ethPkt.getVlanID(), EAPOL.EAPOL_PACKET,
+ eapPayload);
+ stateMachine.setSupplicantAddress(srcMac);
+ stateMachine.setVlanId(ethPkt.getVlanID());
+
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+
+ break;
+ case EAPOL.EAPOL_PACKET:
+ RADIUS radiusPayload;
+ // check if this is a Response/Identify or a Response/TLS
+ EAP eapPacket = (EAP) eapol.getPayload();
+
+ byte dataType = eapPacket.getDataType();
+ switch (dataType) {
+
+ case EAP.ATTR_IDENTITY:
+ // request id access to RADIUS
+ stateMachine.setUsername(eapPacket.getData());
+
+ radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
+ radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
+
+ sendRadiusPacket(radiusPayload);
+
+ // change the state to "PENDING"
+ stateMachine.requestAccess();
+ break;
+ case EAP.ATTR_MD5:
+ // verify if the EAP identifier corresponds to the
+ // challenge identifier from the client state
+ // machine.
+ if (eapPacket.getIdentifier() == stateMachine.challengeIdentifier()) {
+ //send the RADIUS challenge response
+ radiusPayload =
+ getRadiusPayload(stateMachine,
+ stateMachine.identifier(),
+ eapPacket);
+
+ radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
+ stateMachine.challengeState());
+ radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
+ sendRadiusPacket(radiusPayload);
+ }
+ break;
+ case EAP.ATTR_TLS:
+ // request id access to RADIUS
+ radiusPayload = getRadiusPayload(stateMachine, stateMachine.identifier(), eapPacket);
+
+ radiusPayload.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
+ stateMachine.challengeState());
+ stateMachine.setRequestAuthenticator(radiusPayload.generateAuthCode());
+
+ radiusPayload.addMessageAuthenticator(AaaManager.this.radiusSecret);
+ sendRadiusPacket(radiusPayload);
+
+ if (stateMachine.state() != StateMachine.STATE_PENDING) {
+ stateMachine.requestAccess();
+ }
+
+ break;
+ default:
+ return;
+ }
+ break;
+ default:
+ log.trace("Skipping EAPOL message {}", eapol.getEapolType());
+ }
+
+ }
+ }
+
+ class RadiusListener implements Runnable {
+
+ /**
+ * Handles RADIUS packets.
+ *
+ * @param radiusPacket RADIUS packet coming from the RADIUS server.
+ * @throws StateMachineException if an illegal state transition is triggered
+ */
+ protected void handleRadiusPacket(RADIUS radiusPacket) throws StateMachineException {
+ StateMachine stateMachine = StateMachine.lookupStateMachineById(radiusPacket.getIdentifier());
+ if (stateMachine == null) {
+ log.error("Invalid session identifier, exiting...");
+ return;
+ }
+
+ EAP eapPayload;
+ Ethernet eth;
+ switch (radiusPacket.getCode()) {
+ case RADIUS.RADIUS_CODE_ACCESS_CHALLENGE:
+ byte[] challengeState =
+ radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_STATE).getValue();
+ eapPayload = radiusPacket.decapsulateMessage();
+ stateMachine.setChallengeInfo(eapPayload.getIdentifier(), challengeState);
+ eth = buildEapolResponse(stateMachine.supplicantAddress(),
+ MacAddress.valueOf(nasMacAddress),
+ stateMachine.vlanId(),
+ EAPOL.EAPOL_PACKET,
+ eapPayload);
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+ break;
+ case RADIUS.RADIUS_CODE_ACCESS_ACCEPT:
+ //send an EAPOL - Success to the supplicant.
+ byte[] eapMessage =
+ radiusPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE).getValue();
+ eapPayload = new EAP();
+ eapPayload = (EAP) eapPayload.deserialize(eapMessage, 0, eapMessage.length);
+ eth = buildEapolResponse(stateMachine.supplicantAddress(),
+ MacAddress.valueOf(nasMacAddress),
+ stateMachine.vlanId(),
+ EAPOL.EAPOL_PACKET,
+ eapPayload);
+ sendPacketToSupplicant(eth, stateMachine.supplicantConnectpoint());
+
+ stateMachine.authorizeAccess();
+ break;
+ case RADIUS.RADIUS_CODE_ACCESS_REJECT:
+ stateMachine.denyAccess();
+ break;
+ default:
+ log.warn("Unknown RADIUS message received with code: {}", radiusPacket.getCode());
+ }
+ }
+
+
+ @Override
+ public void run() {
+ boolean done = false;
+ int packetNumber = 1;
+
+ log.info("UDP listener thread starting up");
+ RADIUS inboundRadiusPacket;
+ while (!done) {
+ try {
+ byte[] packetBuffer = new byte[RADIUS.RADIUS_MAX_LENGTH];
+ DatagramPacket inboundBasePacket =
+ new DatagramPacket(packetBuffer, packetBuffer.length);
+ DatagramSocket socket = radiusSocket;
+ socket.receive(inboundBasePacket);
+ log.info("Packet #{} received", packetNumber++);
+ try {
+ inboundRadiusPacket =
+ RADIUS.deserializer()
+ .deserialize(inboundBasePacket.getData(),
+ 0,
+ inboundBasePacket.getLength());
+ handleRadiusPacket(inboundRadiusPacket);
+ } catch (DeserializationException dex) {
+ log.error("Cannot deserialize packet", dex);
+ } catch (StateMachineException sme) {
+ log.error("Illegal state machine operation", sme);
+ }
+
+ } catch (IOException e) {
+ log.info("Socket was closed, exiting listener thread");
+ done = true;
+ }
+ }
+ }
+ }
+
+ RadiusListener radiusListener = new RadiusListener();
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ /**
+ * Reconfigures the DHCP Server according to the configuration parameters passed.
+ *
+ * @param cfg configuration object
+ */
+ private void reconfigureNetwork(AaaConfig cfg) {
+ AaaConfig newCfg;
+ if (cfg == null) {
+ newCfg = new AaaConfig();
+ } else {
+ newCfg = cfg;
+ }
+ if (newCfg.nasIp() != null) {
+ nasIpAddress = newCfg.nasIp();
+ }
+ if (newCfg.radiusIp() != null) {
+ radiusIpAddress = newCfg.radiusIp();
+ }
+ if (newCfg.radiusMac() != null) {
+ radiusMacAddress = newCfg.radiusMac();
+ }
+ if (newCfg.nasMac() != null) {
+ nasMacAddress = newCfg.nasMac();
+ }
+ if (newCfg.radiusSecret() != null) {
+ radiusSecret = newCfg.radiusSecret();
+ }
+ if (newCfg.radiusSwitch() != null) {
+ radiusSwitch = newCfg.radiusSwitch();
+ }
+ if (newCfg.radiusPort() != -1) {
+ radiusPort = newCfg.radiusPort();
+ }
+ if (newCfg.radiusServerUdpPort() != -1) {
+ radiusServerPort = newCfg.radiusServerUdpPort();
+ }
+ }
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+
+ if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
+ event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
+ event.configClass().equals(AaaConfig.class)) {
+
+ AaaConfig cfg = netCfgService.getConfig(appId, AaaConfig.class);
+ reconfigureNetwork(cfg);
+ log.info("Reconfigured");
+ }
+ }
+ }
+
+
+}
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaIntegrationTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaIntegrationTest.java
new file mode 100644
index 00000000..6d708fef
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaIntegrationTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.aaa;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.onlab.packet.EAP;
+import org.onlab.packet.EAPOL;
+import org.onlab.packet.Ethernet;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Set of tests of the ONOS application component. These use an existing RADIUS
+ * server and sends live packets over the network to it.
+ */
+@Ignore ("This should not be run as part of the standard build")
+public class AaaIntegrationTest extends AaaTestBase {
+
+ private AaaManager aaa;
+
+ /**
+ * Mocks the network config registry.
+ */
+ @SuppressWarnings("unchecked")
+ static final class TestNetworkConfigRegistry
+ extends NetworkConfigRegistryAdapter {
+ @Override
+ public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+ return (C) new AaaConfig();
+ }
+ }
+
+ /**
+ * Sets up the services required by the AAA application.
+ */
+ @Before
+ public void setUp() {
+ aaa = new AaaManager();
+ aaa.netCfgService = new TestNetworkConfigRegistry();
+ aaa.coreService = new CoreServiceAdapter();
+ aaa.packetService = new MockPacketService();
+ aaa.activate();
+ }
+
+ /**
+ * Fetches the sent packet at the given index. The requested packet
+ * must be the last packet on the list.
+ *
+ * @param index index into sent packets array
+ * @return packet
+ */
+ private Ethernet fetchPacket(int index) {
+ for (int iteration = 0; iteration < 20; iteration++) {
+ if (savedPackets.size() > index) {
+ return (Ethernet) savedPackets.get(index);
+ } else {
+ try {
+ Thread.sleep(250);
+ } catch (Exception ex) {
+ return null;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Tests the authentication path through the AAA application by sending
+ * packets to the RADIUS server and checking the state machine
+ * transitions.
+ *
+ * @throws Exception when an unhandled error occurs
+ */
+ @Test
+ public void testAuthentication() throws Exception {
+
+ // (1) Supplicant start up
+
+ Ethernet startPacket = constructSupplicantStartPacket();
+ sendPacket(startPacket);
+
+ Ethernet responsePacket = fetchPacket(0);
+ assertThat(responsePacket, notNullValue());
+ checkRadiusPacket(aaa, responsePacket, EAP.REQUEST);
+
+ // (2) Supplicant identify
+
+ Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
+ sendPacket(identifyPacket);
+
+ // State machine should have been created by now
+
+ StateMachine stateMachine =
+ StateMachine.lookupStateMachineBySessionId(SESSION_ID);
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
+
+ // (3) RADIUS MD5 challenge
+
+ Ethernet radiusChallengeMD5Packet = fetchPacket(1);
+ assertThat(radiusChallengeMD5Packet, notNullValue());
+ checkRadiusPacket(aaa, radiusChallengeMD5Packet, EAP.REQUEST);
+
+
+ // (4) Supplicant MD5 response
+
+ Ethernet md5RadiusPacket =
+ constructSupplicantIdentifyPacket(stateMachine,
+ EAP.ATTR_MD5,
+ stateMachine.challengeIdentifier(),
+ radiusChallengeMD5Packet);
+ sendPacket(md5RadiusPacket);
+
+
+ // (5) RADIUS Success
+
+ Ethernet successRadiusPacket = fetchPacket(2);
+ assertThat(successRadiusPacket, notNullValue());
+ EAPOL successEapol = (EAPOL) successRadiusPacket.getPayload();
+ EAP successEap = (EAP) successEapol.getPayload();
+ assertThat(successEap.getCode(), is(EAP.SUCCESS));
+
+ // State machine should be in authorized state
+
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
+
+ }
+
+}
+
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaManagerTest.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaManagerTest.java
new file mode 100644
index 00000000..e3bcd9e4
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaManagerTest.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.aaa;
+
+import com.google.common.base.Charsets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.DeserializationException;
+import org.onlab.packet.EAP;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.RADIUS;
+import org.onlab.packet.RADIUSAttribute;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.NetworkConfigRegistryAdapter;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+
+/**
+ * Set of tests of the ONOS application component.
+ */
+public class AaaManagerTest extends AaaTestBase {
+
+ static final String BAD_IP_ADDRESS = "198.51.100.0";
+
+ private AaaManager aaaManager;
+
+ class AaaManagerWithoutRadiusServer extends AaaManager {
+ protected void sendRadiusPacket(RADIUS radiusPacket) {
+ savePacket(radiusPacket);
+ }
+ }
+
+ /**
+ * Mocks the AAAConfig class to force usage of an unroutable address for the
+ * RADIUS server.
+ */
+ static class MockAaaConfig extends AaaConfig {
+ @Override
+ public InetAddress radiusIp() {
+ try {
+ return InetAddress.getByName(BAD_IP_ADDRESS);
+ } catch (UnknownHostException ex) {
+ // can't happen
+ throw new IllegalStateException(ex);
+ }
+ }
+ }
+
+ /**
+ * Mocks the network config registry.
+ */
+ @SuppressWarnings("unchecked")
+ private static final class TestNetworkConfigRegistry
+ extends NetworkConfigRegistryAdapter {
+ @Override
+ public <S, C extends Config<S>> C getConfig(S subject, Class<C> configClass) {
+ AaaConfig aaaConfig = new MockAaaConfig();
+ return (C) aaaConfig;
+ }
+ }
+
+ /**
+ * Constructs an Ethernet packet containing a RADIUS challenge
+ * packet.
+ *
+ * @param challengeCode code to use in challenge packet
+ * @param challengeType type to use in challenge packet
+ * @return Ethernet packet
+ */
+ private RADIUS constructRadiusCodeAccessChallengePacket(byte challengeCode, byte challengeType) {
+
+ String challenge = "12345678901234567";
+
+ EAP eap = new EAP(challengeType, (byte) 1, challengeType,
+ challenge.getBytes(Charsets.US_ASCII));
+ eap.setIdentifier((byte) 1);
+
+ RADIUS radius = new RADIUS();
+ radius.setCode(challengeCode);
+
+ radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_STATE,
+ challenge.getBytes(Charsets.US_ASCII));
+
+ radius.setPayload(eap);
+ radius.setAttribute(RADIUSAttribute.RADIUS_ATTR_EAP_MESSAGE,
+ eap.serialize());
+
+ return radius;
+ }
+
+ /**
+ * Sets up the services required by the AAA application.
+ */
+ @Before
+ public void setUp() {
+ aaaManager = new AaaManagerWithoutRadiusServer();
+ aaaManager.netCfgService = new TestNetworkConfigRegistry();
+ aaaManager.coreService = new CoreServiceAdapter();
+ aaaManager.packetService = new MockPacketService();
+ aaaManager.activate();
+ }
+
+ /**
+ * Tears down the AAA application.
+ */
+ @After
+ public void tearDown() {
+ aaaManager.deactivate();
+ }
+
+ /**
+ * Extracts the RADIUS packet from a packet sent by the supplicant.
+ *
+ * @param radius RADIUS packet sent by the supplicant
+ * @throws DeserializationException if deserialization of the packet contents
+ * fails.
+ */
+ private void checkRadiusPacketFromSupplicant(RADIUS radius)
+ throws DeserializationException {
+ assertThat(radius, notNullValue());
+
+ EAP eap = radius.decapsulateMessage();
+ assertThat(eap, notNullValue());
+ }
+
+ /**
+ * Fetches the sent packet at the given index. The requested packet
+ * must be the last packet on the list.
+ *
+ * @param index index into sent packets array
+ * @return packet
+ */
+ private BasePacket fetchPacket(int index) {
+ BasePacket packet = savedPackets.get(index);
+ assertThat(packet, notNullValue());
+ return packet;
+ }
+
+ /**
+ * Tests the authentication path through the AAA application.
+ *
+ * @throws DeserializationException if packed deserialization fails.
+ */
+ @Test
+ public void testAuthentication() throws Exception {
+
+ // (1) Supplicant start up
+
+ Ethernet startPacket = constructSupplicantStartPacket();
+ sendPacket(startPacket);
+
+ Ethernet responsePacket = (Ethernet) fetchPacket(0);
+ checkRadiusPacket(aaaManager, responsePacket, EAP.ATTR_IDENTITY);
+
+ // (2) Supplicant identify
+
+ Ethernet identifyPacket = constructSupplicantIdentifyPacket(null, EAP.ATTR_IDENTITY, (byte) 1, null);
+ sendPacket(identifyPacket);
+
+ RADIUS radiusIdentifyPacket = (RADIUS) fetchPacket(1);
+
+ checkRadiusPacketFromSupplicant(radiusIdentifyPacket);
+
+ assertThat(radiusIdentifyPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
+ assertThat(new String(radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_USERNAME).getValue()),
+ is("testuser"));
+
+ IpAddress nasIp =
+ IpAddress.valueOf(IpAddress.Version.INET,
+ radiusIdentifyPacket.getAttribute(RADIUSAttribute.RADIUS_ATTR_NAS_IP)
+ .getValue());
+ assertThat(nasIp.toString(), is(aaaManager.nasIpAddress.getHostAddress()));
+
+ // State machine should have been created by now
+
+ StateMachine stateMachine =
+ StateMachine.lookupStateMachineBySessionId(SESSION_ID);
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
+
+ // (3) RADIUS MD5 challenge
+
+ RADIUS radiusCodeAccessChallengePacket =
+ constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_CHALLENGE, EAP.ATTR_MD5);
+ aaaManager.radiusListener.handleRadiusPacket(radiusCodeAccessChallengePacket);
+
+ Ethernet radiusChallengeMD5Packet = (Ethernet) fetchPacket(2);
+ checkRadiusPacket(aaaManager, radiusChallengeMD5Packet, EAP.ATTR_MD5);
+
+ // (4) Supplicant MD5 response
+
+ Ethernet md5RadiusPacket =
+ constructSupplicantIdentifyPacket(stateMachine,
+ EAP.ATTR_MD5,
+ stateMachine.challengeIdentifier(),
+ radiusChallengeMD5Packet);
+ sendPacket(md5RadiusPacket);
+
+ RADIUS responseMd5RadiusPacket = (RADIUS) fetchPacket(3);
+
+ checkRadiusPacketFromSupplicant(responseMd5RadiusPacket);
+ assertThat(responseMd5RadiusPacket.getIdentifier(), is((byte) 0));
+ assertThat(responseMd5RadiusPacket.getCode(), is(RADIUS.RADIUS_CODE_ACCESS_REQUEST));
+
+ // State machine should be in pending state
+
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_PENDING));
+
+ // (5) RADIUS Success
+
+ RADIUS successPacket =
+ constructRadiusCodeAccessChallengePacket(RADIUS.RADIUS_CODE_ACCESS_ACCEPT, EAP.SUCCESS);
+ aaaManager.radiusListener.handleRadiusPacket((successPacket));
+ Ethernet supplicantSuccessPacket = (Ethernet) fetchPacket(4);
+
+ checkRadiusPacket(aaaManager, supplicantSuccessPacket, EAP.SUCCESS);
+
+ // State machine should be in authorized state
+
+ assertThat(stateMachine, notNullValue());
+ assertThat(stateMachine.state(), is(StateMachine.STATE_AUTHORIZED));
+
+ }
+
+ /**
+ * Tests the default configuration.
+ */
+ @Test
+ public void testConfig() {
+ assertThat(aaaManager.nasIpAddress.getHostAddress(), is(AaaConfig.DEFAULT_NAS_IP));
+ assertThat(aaaManager.nasMacAddress, is(AaaConfig.DEFAULT_NAS_MAC));
+ assertThat(aaaManager.radiusIpAddress.getHostAddress(), is(BAD_IP_ADDRESS));
+ assertThat(aaaManager.radiusMacAddress, is(AaaConfig.DEFAULT_RADIUS_MAC));
+ }
+}
diff --git a/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaTestBase.java b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaTestBase.java
new file mode 100644
index 00000000..b076a2e3
--- /dev/null
+++ b/framework/src/onos/apps/aaa/src/test/java/org/onosproject/aaa/AaaTestBase.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.aaa;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.EAP;
+import org.onlab.packet.EAPOL;
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.packet.DefaultInboundPacket;
+import org.onosproject.net.packet.DefaultPacketContext;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.OutboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketServiceAdapter;
+
+import java.nio.ByteBuffer;
+import java.security.MessageDigest;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.onosproject.net.NetTestTools.connectPoint;
+
+/**
+ * Common methods for AAA app testing.
+ */
+public class AaaTestBase {
+
+ MacAddress clientMac = MacAddress.valueOf("1a:1a:1a:1a:1a:1a");
+ MacAddress serverMac = MacAddress.valueOf("2a:2a:2a:2a:2a:2a");
+
+ // Our session id will be the device ID ("of:1") with the port ("1") concatenated
+ static final String SESSION_ID = "of:11";
+
+ List<BasePacket> savedPackets = new LinkedList<>();
+ PacketProcessor packetProcessor;
+
+ /**
+ * Saves the given packet onto the saved packets list.
+ *
+ * @param packet packet to save
+ */
+ void savePacket(BasePacket packet) {
+ savedPackets.add(packet);
+ }
+
+ /**
+ * Keeps a reference to the PacketProcessor and saves the OutboundPackets.
+ */
+ class MockPacketService extends PacketServiceAdapter {
+
+ @Override
+ public void addProcessor(PacketProcessor processor, int priority) {
+ packetProcessor = processor;
+ }
+
+ @Override
+ public void emit(OutboundPacket packet) {
+ try {
+ Ethernet eth = Ethernet.deserializer().deserialize(packet.data().array(),
+ 0, packet.data().array().length);
+ savePacket(eth);
+ } catch (Exception e) {
+ fail(e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Mocks the DefaultPacketContext.
+ */
+ final class TestPacketContext extends DefaultPacketContext {
+
+ private TestPacketContext(long time, InboundPacket inPkt,
+ OutboundPacket outPkt, boolean block) {
+ super(time, inPkt, outPkt, block);
+ }
+
+ @Override
+ public void send() {
+ // We don't send anything out.
+ }
+ }
+
+ /**
+ * Sends an Ethernet packet to the process method of the Packet Processor.
+ *
+ * @param reply Ethernet packet
+ */
+ void sendPacket(Ethernet reply) {
+ final ByteBuffer byteBuffer = ByteBuffer.wrap(reply.serialize());
+ InboundPacket inPacket = new DefaultInboundPacket(connectPoint("1", 1),
+ reply,
+ byteBuffer);
+
+ PacketContext context = new TestPacketContext(127L, inPacket, null, false);
+ packetProcessor.process(context);
+ }
+
+ /**
+ * Constructs an Ethernet packet containing identification payload.
+ *
+ * @return Ethernet packet
+ */
+ Ethernet constructSupplicantIdentifyPacket(StateMachine stateMachine,
+ byte type,
+ byte id,
+ Ethernet radiusChallenge)
+ throws Exception {
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(clientMac.toBytes());
+ eth.setSourceMACAddress(serverMac.toBytes());
+ eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
+ eth.setVlanID((short) 2);
+
+ String username = "testuser";
+ byte[] data = username.getBytes();
+
+
+ if (type == EAP.ATTR_MD5) {
+ String password = "testpassword";
+ EAPOL eapol = (EAPOL) radiusChallenge.getPayload();
+ EAP eap = (EAP) eapol.getPayload();
+
+ byte[] identifier = new byte[password.length() + eap.getData().length];
+
+ identifier[0] = stateMachine.challengeIdentifier();
+ System.arraycopy(password.getBytes(), 0, identifier, 1, password.length());
+ System.arraycopy(eap.getData(), 1, identifier, 1 + password.length(), 16);
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] hash = md.digest(identifier);
+ data = new byte[17];
+ data[0] = (byte) 16;
+ System.arraycopy(hash, 0, data, 1, 16);
+ }
+ EAP eap = new EAP(EAP.RESPONSE, (byte) 1, type,
+ data);
+ eap.setIdentifier(id);
+
+ // eapol header
+ EAPOL eapol = new EAPOL();
+ eapol.setEapolType(EAPOL.EAPOL_PACKET);
+ eapol.setPacketLength(eap.getLength());
+
+ // eap part
+ eapol.setPayload(eap);
+
+ eth.setPayload(eapol);
+ eth.setPad(true);
+ return eth;
+ }
+
+ /**
+ * Constructs an Ethernet packet containing a EAPOL_START Payload.
+ *
+ * @return Ethernet packet
+ */
+ Ethernet constructSupplicantStartPacket() {
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(clientMac.toBytes());
+ eth.setSourceMACAddress(serverMac.toBytes());
+ eth.setEtherType(EthType.EtherType.EAPOL.ethType().toShort());
+ eth.setVlanID((short) 2);
+
+ EAP eap = new EAP(EAPOL.EAPOL_START, (byte) 2, EAPOL.EAPOL_START, null);
+
+ // eapol header
+ EAPOL eapol = new EAPOL();
+ eapol.setEapolType(EAPOL.EAPOL_START);
+ eapol.setPacketLength(eap.getLength());
+
+ // eap part
+ eapol.setPayload(eap);
+
+ eth.setPayload(eapol);
+ eth.setPad(true);
+ return eth;
+ }
+
+ /**
+ * Checks the contents of a RADIUS packet being sent to the RADIUS server.
+ *
+ * @param radiusPacket packet to check
+ * @param code expected code
+ */
+ void checkRadiusPacket(AaaManager aaaManager, Ethernet radiusPacket, byte code) {
+
+ assertThat(radiusPacket.getSourceMAC(),
+ is(MacAddress.valueOf(aaaManager.nasMacAddress)));
+ assertThat(radiusPacket.getDestinationMAC(), is(serverMac));
+
+ assertThat(radiusPacket.getPayload(), instanceOf(EAPOL.class));
+ EAPOL eapol = (EAPOL) radiusPacket.getPayload();
+ assertThat(eapol, notNullValue());
+
+ assertThat(eapol.getEapolType(), is(EAPOL.EAPOL_PACKET));
+ assertThat(eapol.getPayload(), instanceOf(EAP.class));
+ EAP eap = (EAP) eapol.getPayload();
+ assertThat(eap, notNullValue());
+
+ assertThat(eap.getCode(), is(code));
+ }
+}
diff --git a/framework/src/onos/apps/bgprouter/features.xml b/framework/src/onos/apps/bgprouter/features.xml
index c91a7f10..7153ac91 100644
--- a/framework/src/onos/apps/bgprouter/features.xml
+++ b/framework/src/onos/apps/bgprouter/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
diff --git a/framework/src/onos/apps/cordvtn/pom.xml b/framework/src/onos/apps/cordvtn/pom.xml
index 1d96108b..3f3ec23b 100644
--- a/framework/src/onos/apps/cordvtn/pom.xml
+++ b/framework/src/onos/apps/cordvtn/pom.xml
@@ -33,6 +33,10 @@
<properties>
<onos.app.name>org.onosproject.cordvtn</onos.app.name>
+ <onos.app.requires>
+ org.onosproject.ovsdb,
+ org.onosproject.openstackswitching
+ </onos.app.requires>
</properties>
<dependencies>
@@ -64,6 +68,11 @@
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>3.0.3</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-openstackswitching-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
index c3bf77c5..67297741 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.cordvtn;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -23,6 +25,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.ItemNotFoundException;
+import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.ApplicationId;
@@ -31,9 +34,11 @@ import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
import org.onosproject.net.Port;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeName;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.behaviour.DefaultTunnelDescription;
import org.onosproject.net.behaviour.TunnelConfig;
@@ -45,9 +50,13 @@ import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
+import org.onosproject.openstackswitching.OpenstackNetwork;
+import org.onosproject.openstackswitching.OpenstackPort;
+import org.onosproject.openstackswitching.OpenstackSwitchingService;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
@@ -62,8 +71,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
+import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.groupedThreads;
@@ -72,8 +83,8 @@ import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
import static org.slf4j.LoggerFactory.getLogger;
/**
- * Provides initial setup or cleanup for provisioning virtual tenant networks
- * on ovsdb, integration bridge and vm when they are added or deleted.
+ * Provisions virtual tenant networks with service chaining capability
+ * in OpenStack environment.
*/
@Component(immediate = true)
@Service
@@ -86,7 +97,8 @@ public class CordVtn implements CordVtnService {
.register(KryoNamespaces.API)
.register(CordVtnNode.class)
.register(NodeState.class);
- private static final String DEFAULT_BRIDGE_NAME = "br-int";
+ private static final String DEFAULT_BRIDGE = "br-int";
+ private static final String VPORT_PREFIX = "tap";
private static final String DEFAULT_TUNNEL = "vxlan";
private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
{
@@ -116,11 +128,17 @@ public class CordVtn implements CordVtnService {
protected DeviceAdminService adminService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OvsdbController controller;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected OpenstackSwitchingService openstackService;
+
private final ExecutorService eventExecutor = Executors
.newFixedThreadPool(NUM_THREADS, groupedThreads("onos/cordvtn", "event-handler"));
@@ -132,6 +150,8 @@ public class CordVtn implements CordVtnService {
private final VmHandler vmHandler = new VmHandler();
private ConsistentMap<CordVtnNode, NodeState> nodeStore;
+ private Map<HostId, String> hostNetworkMap = Maps.newHashMap();
+ private CordVtnRuleInstaller ruleInstaller;
private enum NodeState {
@@ -185,6 +205,8 @@ public class CordVtn implements CordVtnService {
.withApplicationId(appId)
.build();
+ ruleInstaller = new CordVtnRuleInstaller(appId, flowObjectiveService,
+ driverService, DEFAULT_TUNNEL);
deviceService.addListener(deviceListener);
hostService.addListener(hostListener);
@@ -314,11 +336,27 @@ public class CordVtn implements CordVtnService {
/**
* Performs tasks after node initialization.
+ * First disconnect unnecessary OVSDB connection and then installs flow rules
+ * for existing VMs if there are any.
*
* @param node cordvtn node
*/
private void postInit(CordVtnNode node) {
disconnect(node);
+
+ Set<OpenstackNetwork> vNets = Sets.newHashSet();
+ hostService.getConnectedHosts(node.intBrId())
+ .stream()
+ .forEach(host -> {
+ OpenstackNetwork vNet = getOpenstackNetworkByHost(host);
+ if (vNet != null) {
+ log.info("VM {} is detected", host.id());
+
+ hostNetworkMap.put(host.id(), vNet.id());
+ vNets.add(vNet);
+ }
+ });
+ vNets.stream().forEach(this::installFlowRules);
}
/**
@@ -443,7 +481,7 @@ public class CordVtn implements CordVtnService {
}
List<ControllerInfo> controllers = new ArrayList<>();
- Sets.newHashSet(clusterService.getNodes())
+ Sets.newHashSet(clusterService.getNodes()).stream()
.forEach(controller -> {
ControllerInfo ctrlInfo = new ControllerInfo(controller.ip(), OFPORT, "tcp");
controllers.add(ctrlInfo);
@@ -453,7 +491,7 @@ public class CordVtn implements CordVtnService {
try {
DriverHandler handler = driverService.createHandler(node.ovsdbId());
BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
- bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, controllers);
+ bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE), dpid, controllers);
} catch (ItemNotFoundException e) {
log.warn("Failed to create integration bridge on {}", node.ovsdbId());
}
@@ -474,13 +512,12 @@ public class CordVtn implements CordVtnService {
optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
}
TunnelDescription description =
- new DefaultTunnelDescription(null, null, VXLAN,
- TunnelName.tunnelName(DEFAULT_TUNNEL),
+ new DefaultTunnelDescription(null, null, VXLAN, TunnelName.tunnelName(DEFAULT_TUNNEL),
optionBuilder.build());
try {
DriverHandler handler = driverService.createHandler(node.ovsdbId());
TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
- tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), description);
+ tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE), description);
} catch (ItemNotFoundException e) {
log.warn("Failed to create tunnel interface on {}", node.ovsdbId());
}
@@ -516,6 +553,212 @@ public class CordVtn implements CordVtnService {
}
}
+ /**
+ * Returns tunnel port of the device.
+ *
+ * @param bridgeId device id
+ * @return port, null if no tunnel port exists on a given device
+ */
+ private Port getTunnelPort(DeviceId bridgeId) {
+ try {
+ return deviceService.getPorts(bridgeId).stream()
+ .filter(p -> p.annotations().value("portName").contains(DEFAULT_TUNNEL)
+ && p.isEnabled())
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns remote ip address for tunneling.
+ *
+ * @param bridgeId device id
+ * @return ip address, null if no such device exists
+ */
+ private IpAddress getRemoteIp(DeviceId bridgeId) {
+ CordVtnNode node = getNodeByBridgeId(bridgeId);
+ if (node != null) {
+ // TODO get data plane IP for tunneling
+ return node.ovsdbIp();
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns destination information of all ports associated with a given
+ * OpenStack network. Output of the destination information is set to local
+ * port or tunnel port according to a given device id.
+ *
+ * @param deviceId device id to install flow rules
+ * @param vNet OpenStack network
+ * @return list of flow information, empty list if no flow information exists
+ */
+ private List<DestinationInfo> getSameNetworkPortsInfo(DeviceId deviceId, OpenstackNetwork vNet) {
+ List<DestinationInfo> dstInfos = Lists.newArrayList();
+ long tunnelId = Long.valueOf(vNet.segmentId());
+
+ for (OpenstackPort vPort : openstackService.ports(vNet.id())) {
+ ConnectPoint cp = getConnectPoint(vPort);
+ if (cp == null) {
+ log.debug("Couldn't find connection point for OpenStack port {}", vPort.id());
+ continue;
+ }
+
+ DestinationInfo.Builder dBuilder = cp.deviceId().equals(deviceId) ?
+ DestinationInfo.builder(deviceService.getPort(cp.deviceId(), cp.port())) :
+ DestinationInfo.builder(getTunnelPort(deviceId))
+ .setRemoteIp(getRemoteIp(cp.deviceId()));
+
+ dBuilder.setMac(vPort.macAddress())
+ .setTunnelId(tunnelId);
+ dstInfos.add(dBuilder.build());
+ }
+ return dstInfos;
+ }
+
+ /**
+ * Returns local ports associated with a given OpenStack network.
+ *
+ * @param bridgeId device id
+ * @param vNet OpenStack network
+ * @return port list, empty list if no port exists
+ */
+ private List<Port> getLocalSameNetworkPorts(DeviceId bridgeId, OpenstackNetwork vNet) {
+ List<Port> ports = new ArrayList<>();
+ openstackService.ports(vNet.id()).stream().forEach(port -> {
+ ConnectPoint cp = getConnectPoint(port);
+ if (cp != null && cp.deviceId().equals(bridgeId)) {
+ ports.add(deviceService.getPort(cp.deviceId(), cp.port()));
+ }
+ });
+ return ports;
+ }
+
+ /**
+ * Returns OpenStack port associated with a given host.
+ *
+ * @param host host
+ * @return OpenStack port, or null if no port has been found
+ */
+ private OpenstackPort getOpenstackPortByHost(Host host) {
+ Port port = deviceService.getPort(host.location().deviceId(),
+ host.location().port());
+ return openstackService.port(port);
+ }
+
+ /**
+ * Returns OpenStack network associated with a given host.
+ *
+ * @param host host
+ * @return OpenStack network, or null if no network has been found
+ */
+ private OpenstackNetwork getOpenstackNetworkByHost(Host host) {
+ OpenstackPort vPort = getOpenstackPortByHost(host);
+ if (vPort != null) {
+ return openstackService.network(vPort.networkId());
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Returns port name with OpenStack port information.
+ *
+ * @param vPort OpenStack port
+ * @return port name
+ */
+ private String getPortName(OpenstackPort vPort) {
+ checkNotNull(vPort);
+ return VPORT_PREFIX + vPort.id().substring(0, 10);
+ }
+
+ /**
+ * Returns connect point of a given OpenStack port.
+ * It assumes there's only one physical port associated with an OpenStack port.
+ *
+ * @param vPort openstack port
+ * @return connect point, null if no such port exists
+ */
+ private ConnectPoint getConnectPoint(OpenstackPort vPort) {
+ try {
+ Host host = hostService.getHostsByMac(vPort.macAddress())
+ .stream()
+ .findFirst()
+ .get();
+ return new ConnectPoint(host.location().deviceId(), host.location().port());
+ } catch (NoSuchElementException e) {
+ log.debug("Not a valid host with {}", vPort.macAddress());
+ return null;
+ }
+ }
+
+ /**
+ * Installs flow rules for a given OpenStack network.
+ *
+ * @param vNet OpenStack network
+ */
+ private void installFlowRules(OpenstackNetwork vNet) {
+ checkNotNull(vNet, "Tenant network should not be null");
+
+ for (Device device : deviceService.getAvailableDevices(SWITCH)) {
+ List<DestinationInfo> dstInfos = getSameNetworkPortsInfo(device.id(), vNet);
+
+ for (Port inPort : getLocalSameNetworkPorts(device.id(), vNet)) {
+ List<DestinationInfo> localInInfos = dstInfos.stream()
+ .filter(info -> !info.output().equals(inPort))
+ .collect(Collectors.toList());
+ ruleInstaller.installFlowRulesLocalIn(device.id(), inPort, localInInfos);
+ }
+
+ Port tunPort = getTunnelPort(device.id());
+ List<DestinationInfo> tunnelInInfos = dstInfos.stream()
+ .filter(info -> !info.output().equals(tunPort))
+ .collect(Collectors.toList());
+ ruleInstaller.installFlowRulesTunnelIn(device.id(), tunPort, tunnelInInfos);
+ }
+ }
+
+ /**
+ * Uninstalls flow rules associated with a given host for a given OpenStack network.
+ *
+ * @param vNet OpenStack network
+ * @param host removed host
+ */
+ private void uninstallFlowRules(OpenstackNetwork vNet, Host host) {
+ checkNotNull(vNet, "Tenant network should not be null");
+
+ Port removedPort = deviceService.getPort(host.location().deviceId(),
+ host.location().port());
+
+ for (Device device : deviceService.getAvailableDevices(SWITCH)) {
+ List<DestinationInfo> dstInfos = getSameNetworkPortsInfo(device.id(), vNet);
+
+ for (Port inPort : getLocalSameNetworkPorts(device.id(), vNet)) {
+ List<DestinationInfo> localInInfos = Lists.newArrayList(
+ DestinationInfo.builder(getTunnelPort(device.id()))
+ .setTunnelId(Long.valueOf(vNet.segmentId()))
+ .setMac(host.mac())
+ .setRemoteIp(getRemoteIp(host.location().deviceId()))
+ .build());
+ ruleInstaller.uninstallFlowRules(device.id(), inPort, localInInfos);
+ }
+
+ if (device.id().equals(host.location().deviceId())) {
+ Port tunPort = getTunnelPort(device.id());
+ List<DestinationInfo> tunnelInInfo = Lists.newArrayList(
+ DestinationInfo.builder(removedPort)
+ .setTunnelId(Long.valueOf(vNet.segmentId()))
+ .setMac(host.mac())
+ .build());
+
+ ruleInstaller.uninstallFlowRules(device.id(), tunPort, tunnelInInfo);
+ ruleInstaller.uninstallFlowRules(device.id(), removedPort, dstInfos);
+ }
+ }
+ }
+
private class InternalDeviceListener implements DeviceListener {
@Override
@@ -644,12 +887,40 @@ public class CordVtn implements CordVtnService {
@Override
public void connected(Host host) {
+ CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
+ if (node == null || !getNodeState(node).equals(NodeState.COMPLETE)) {
+ // do nothing for the host on unregistered or unprepared device
+ return;
+ }
+
+ OpenstackNetwork vNet = getOpenstackNetworkByHost(host);
+ if (vNet == null) {
+ return;
+ }
+
log.info("VM {} is detected", host.id());
+
+ hostNetworkMap.put(host.id(), vNet.id());
+ installFlowRules(vNet);
}
@Override
public void disconnected(Host host) {
+ CordVtnNode node = getNodeByBridgeId(host.location().deviceId());
+ if (node == null || !getNodeState(node).equals(NodeState.COMPLETE)) {
+ // do nothing for the host on unregistered or unprepared device
+ return;
+ }
+
+ OpenstackNetwork vNet = openstackService.network(hostNetworkMap.get(host.id()));
+ if (vNet == null) {
+ return;
+ }
+
log.info("VM {} is vanished", host.id());
+
+ uninstallFlowRules(vNet, host);
+ hostNetworkMap.remove(host.id());
}
}
}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java
new file mode 100644
index 00000000..439d16e1
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnNode.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cordvtn;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.net.DeviceId;
+
+import java.util.Comparator;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a compute infrastructure node for CORD VTN service.
+ */
+public final class CordVtnNode {
+
+ private final String hostname;
+ private final IpAddress ovsdbIp;
+ private final TpPort ovsdbPort;
+ private final DeviceId bridgeId;
+
+ public static final Comparator<CordVtnNode> CORDVTN_NODE_COMPARATOR =
+ (node1, node2) -> node1.hostname().compareTo(node2.hostname());
+
+ /**
+ * Creates a new node.
+ *
+ * @param hostname hostname
+ * @param ovsdbIp OVSDB server IP address
+ * @param ovsdbPort OVSDB server port number
+ * @param bridgeId integration bridge identifier
+ */
+ public CordVtnNode(String hostname, IpAddress ovsdbIp, TpPort ovsdbPort, DeviceId bridgeId) {
+ this.hostname = checkNotNull(hostname);
+ this.ovsdbIp = checkNotNull(ovsdbIp);
+ this.ovsdbPort = checkNotNull(ovsdbPort);
+ this.bridgeId = checkNotNull(bridgeId);
+ }
+
+ /**
+ * Returns the OVSDB server IP address.
+ *
+ * @return ip address
+ */
+ public IpAddress ovsdbIp() {
+ return this.ovsdbIp;
+ }
+
+ /**
+ * Returns the OVSDB server port number.
+ *
+ * @return port number
+ */
+ public TpPort ovsdbPort() {
+ return this.ovsdbPort;
+ }
+
+ /**
+ * Returns the hostname.
+ *
+ * @return hostname
+ */
+ public String hostname() {
+ return this.hostname;
+ }
+
+ /**
+ * Returns the identifier of the integration bridge.
+ *
+ * @return device id
+ */
+ public DeviceId intBrId() {
+ return this.bridgeId;
+ }
+
+ /**
+ * Returns the identifier of the OVSDB device.
+ *
+ * @return device id
+ */
+ public DeviceId ovsdbId() {
+ return DeviceId.deviceId("ovsdb:" + this.ovsdbIp.toString());
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof CordVtnNode) {
+ CordVtnNode that = (CordVtnNode) obj;
+ if (Objects.equals(hostname, that.hostname) &&
+ Objects.equals(ovsdbIp, that.ovsdbIp) &&
+ Objects.equals(ovsdbPort, that.ovsdbPort) &&
+ Objects.equals(bridgeId, that.bridgeId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(hostname, ovsdbIp, ovsdbPort);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("host", hostname)
+ .add("ip", ovsdbIp)
+ .add("port", ovsdbPort)
+ .add("bridgeId", bridgeId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java
new file mode 100644
index 00000000..9e22997c
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnRuleInstaller.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cordvtn;
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.slf4j.Logger;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Populates rules for virtual tenant network.
+ */
+public final class CordVtnRuleInstaller {
+ protected final Logger log = getLogger(getClass());
+
+ private static final int DEFAULT_PRIORITY = 5000;
+
+ private final ApplicationId appId;
+ private final FlowObjectiveService flowObjectiveService;
+ private final DriverService driverService;
+ private final String tunnelType;
+
+ /**
+ * Creates a new rule installer.
+ *
+ * @param appId application id
+ * @param flowObjectiveService flow objective service
+ * @param driverService driver service
+ * @param tunnelType tunnel type
+ */
+ public CordVtnRuleInstaller(ApplicationId appId,
+ FlowObjectiveService flowObjectiveService,
+ DriverService driverService,
+ String tunnelType) {
+ this.appId = appId;
+ this.flowObjectiveService = flowObjectiveService;
+ this.driverService = driverService;
+ this.tunnelType = checkNotNull(tunnelType);
+ }
+
+ /**
+ * Installs flow rules for tunnel in traffic.
+ *
+ * @param deviceId device id to install flow rules
+ * @param inPort in port
+ * @param dstInfos list of destination info
+ */
+ public void installFlowRulesTunnelIn(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
+ dstInfos.stream().forEach(dstInfo -> {
+ ForwardingObjective.Builder fBuilder = vtnRulesSameNode(inPort, dstInfo);
+ if (fBuilder != null) {
+ flowObjectiveService.forward(deviceId, fBuilder.add());
+ }
+ });
+ }
+
+ /**
+ * Installs flow rules for local in traffic.
+ *
+ * @param deviceId device id to install flow rules
+ * @param inPort in port
+ * @param dstInfos list of destination info
+ */
+ public void installFlowRulesLocalIn(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
+ dstInfos.stream().forEach(dstInfo -> {
+ ForwardingObjective.Builder fBuilder = isTunnelPort(dstInfo.output()) ?
+ vtnRulesRemoteNode(deviceId, inPort, dstInfo) : vtnRulesSameNode(inPort, dstInfo);
+
+ if (fBuilder != null) {
+ flowObjectiveService.forward(deviceId, fBuilder.add());
+ }
+ });
+ }
+
+ /**
+ * Uninstalls flow rules associated with a given port from a given device.
+ *
+ * @param deviceId device id
+ * @param inPort port associated with removed host
+ * @param dstInfos list of destination info
+ */
+ public void uninstallFlowRules(DeviceId deviceId, Port inPort, List<DestinationInfo> dstInfos) {
+ dstInfos.stream().forEach(dstInfo -> {
+ ForwardingObjective.Builder fBuilder = isTunnelPort(dstInfo.output()) ?
+ vtnRulesRemoteNode(deviceId, inPort, dstInfo) : vtnRulesSameNode(inPort, dstInfo);
+
+ if (fBuilder != null) {
+ flowObjectiveService.forward(deviceId, fBuilder.remove());
+ }
+ });
+ }
+
+ /**
+ * Returns forwarding objective builder to provision basic virtual tenant network.
+ * This method cares for the traffics whose source and destination device is the same.
+ *
+ * @param inPort in port
+ * @param dstInfo destination information
+ * @return forwarding objective builder
+ */
+ private ForwardingObjective.Builder vtnRulesSameNode(Port inPort, DestinationInfo dstInfo) {
+ checkArgument(inPort.element().id().equals(dstInfo.output().element().id()));
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchInPort(inPort.number())
+ .matchEthDst(dstInfo.mac());
+ if (isTunnelPort(inPort)) {
+ sBuilder.matchTunnelId(dstInfo.tunnelId());
+ }
+
+ tBuilder.setOutput(dstInfo.output().number());
+
+ return DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+ }
+
+ /**
+ * Returns forwarding objective builder to provision basic virtual tenant network.
+ * This method cares for the traffics whose source and destination is not the same.
+ *
+ * @param deviceId device id to install flow rules
+ * @param inPort in port
+ * @param dstInfo destination information
+ * @return forwarding objective, or null if it fails to build it
+ */
+ private ForwardingObjective.Builder vtnRulesRemoteNode(DeviceId deviceId, Port inPort, DestinationInfo dstInfo) {
+ checkArgument(isTunnelPort(dstInfo.output()));
+
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ ExtensionTreatment extTreatment =
+ getTunnelDstInstruction(deviceId, dstInfo.remoteIp().getIp4Address());
+ if (extTreatment == null) {
+ return null;
+ }
+
+ sBuilder.matchInPort(inPort.number())
+ .matchEthDst(dstInfo.mac());
+
+ tBuilder.extension(extTreatment, deviceId)
+ .setTunnelId(dstInfo.tunnelId())
+ .setOutput(dstInfo.output().number());
+
+ return DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .makePermanent();
+ }
+
+ /**
+ * Checks if a given port is tunnel interface or not.
+ * It assumes the tunnel interface contains tunnelType string in its name.
+ *
+ * @param port port
+ * @return true if the port is tunnel interface, false otherwise.
+ */
+ private boolean isTunnelPort(Port port) {
+ return port.annotations().value("portName").contains(tunnelType);
+ }
+
+ /**
+ * Returns extension instruction to set tunnel destination.
+ *
+ * @param deviceId device id
+ * @param remoteIp tunnel destination address
+ * @return extension treatment or null if it fails to get instruction
+ */
+ private ExtensionTreatment getTunnelDstInstruction(DeviceId deviceId, Ip4Address remoteIp) {
+ try {
+ Driver driver = driverService.getDriver(deviceId);
+ DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+
+ ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ treatment.setPropertyValue("tunnelDst", remoteIp);
+
+ return treatment;
+ } catch (ItemNotFoundException | UnsupportedOperationException | ExtensionPropertyException e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ return null;
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DestinationInfo.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DestinationInfo.java
new file mode 100644
index 00000000..290cc170
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DestinationInfo.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.cordvtn;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.Port;
+
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Contains destination information.
+ */
+public final class DestinationInfo {
+
+ private final Port output;
+ private final List<IpAddress> ip;
+ private final MacAddress mac;
+ private final IpAddress remoteIp;
+ private final long tunnelId;
+
+ /**
+ * Creates a new destination information.
+ *
+ * @param output output port
+ * @param ip destination ip address
+ * @param mac destination mac address
+ * @param remoteIp tunnel remote ip address
+ * @param tunnelId segment id
+ */
+ public DestinationInfo(Port output, List<IpAddress> ip, MacAddress mac,
+ IpAddress remoteIp, long tunnelId) {
+ this.output = checkNotNull(output);
+ this.ip = ip;
+ this.mac = mac;
+ this.remoteIp = remoteIp;
+ this.tunnelId = tunnelId;
+ }
+
+ /**
+ * Returns output port.
+ *
+ * @return port
+ */
+ public Port output() {
+ return output;
+ }
+
+ /**
+ * Returns destination ip addresses.
+ *
+ * @return list of ip address
+ */
+ public List<IpAddress> ip() {
+ return ip;
+ }
+
+ /**
+ * Returns destination mac address.
+ *
+ * @return mac address
+ */
+ public MacAddress mac() {
+ return mac;
+ }
+
+ /**
+ * Returns tunnel remote ip address.
+ *
+ * @return ip address
+ */
+ public IpAddress remoteIp() {
+ return remoteIp;
+ }
+
+ /**
+ * Returns tunnel id.
+ *
+ * @return tunnel id
+ */
+ public long tunnelId() {
+ return tunnelId;
+ }
+
+ /**
+ * Returns a new destination info builder.
+ *
+ * @return destination info builder
+ */
+ public static DestinationInfo.Builder builder(Port output) {
+ return new Builder(output);
+ }
+
+ /**
+ * DestinationInfo builder class.
+ */
+ public static final class Builder {
+
+ private final Port output;
+ private List<IpAddress> ip;
+ private MacAddress mac;
+ private IpAddress remoteIp;
+ private long tunnelId;
+
+ /**
+ * Creates a new destination information builder.
+ *
+ * @param output output port
+ */
+ public Builder(Port output) {
+ this.output = checkNotNull(output, "Output port cannot be null");
+ }
+
+ /**
+ * Sets the destination ip address.
+ *
+ * @param ip ip address
+ * @return destination info builder
+ */
+ public Builder setIp(List<IpAddress> ip) {
+ this.ip = checkNotNull(ip, "IP cannot be null");
+ return this;
+ }
+
+ /**
+ * Sets the destination mac address.
+ *
+ * @param mac mac address
+ * @return destination info builder
+ */
+ public Builder setMac(MacAddress mac) {
+ this.mac = checkNotNull(mac, "MAC address cannot be null");
+ return this;
+ }
+
+ /**
+ * Sets the tunnel remote ip address.
+ *
+ * @param remoteIp ip address
+ * @return destination info builder
+ */
+ public Builder setRemoteIp(IpAddress remoteIp) {
+ this.remoteIp = checkNotNull(remoteIp, "Remote IP address cannot be null");
+ return this;
+ }
+
+ /**
+ * Sets the tunnel id.
+ *
+ * @param tunnelId tunnel id
+ * @return destination info builder
+ */
+ public Builder setTunnelId(long tunnelId) {
+ this.tunnelId = checkNotNull(tunnelId, "Tunnel ID cannot be null");
+ return this;
+ }
+
+ /**
+ * Build a destination information.
+ *
+ * @return destination info object
+ */
+ public DestinationInfo build() {
+ return new DestinationInfo(this);
+ }
+ }
+
+ private DestinationInfo(Builder builder) {
+ output = builder.output;
+ ip = builder.ip;
+ mac = builder.mac;
+ remoteIp = builder.remoteIp;
+ tunnelId = builder.tunnelId;
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java
new file mode 100644
index 00000000..1b7d9866
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeAddCommand.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.TpPort;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.CordVtnNode;
+import org.onosproject.net.DeviceId;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Adds a new node to the service.
+ */
+@Command(scope = "onos", name = "cordvtn-node-add",
+ description = "Adds a new node to CORD VTN service")
+public class CordVtnNodeAddCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hostname", description = "Hostname",
+ required = true, multiValued = false)
+ private String hostname = null;
+
+ @Argument(index = 1, name = "ovsdb",
+ description = "OVSDB server listening address (ip:port)",
+ required = true, multiValued = false)
+ private String ovsdb = null;
+
+ @Argument(index = 2, name = "bridgeId",
+ description = "Device ID of integration bridge",
+ required = true, multiValued = false)
+ private String bridgeId = null;
+
+ @Override
+ protected void execute() {
+ checkArgument(ovsdb.contains(":"), "OVSDB address should be ip:port format");
+ checkArgument(bridgeId.startsWith("of:"), "bridgeId should be of:dpid format");
+
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+ String[] ipPort = ovsdb.split(":");
+ CordVtnNode node = new CordVtnNode(hostname,
+ IpAddress.valueOf(ipPort[0]),
+ TpPort.tpPort(Integer.parseInt(ipPort[1])),
+ DeviceId.deviceId(bridgeId));
+ service.addNode(node);
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java
new file mode 100644
index 00000000..0446fc6a
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeDeleteCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.CordVtnNode;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Deletes nodes from the service.
+ */
+@Command(scope = "onos", name = "cordvtn-node-delete",
+ description = "Deletes nodes from CORD VTN service")
+public class CordVtnNodeDeleteCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
+ required = true, multiValued = true)
+ private String[] hostnames = null;
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+
+ for (String hostname : hostnames) {
+ CordVtnNode node;
+ try {
+ node = service.getNodes()
+ .stream()
+ .filter(n -> n.hostname().equals(hostname))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ print("Unable to find %s", hostname);
+ continue;
+ }
+
+ service.deleteNode(node);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java
new file mode 100644
index 00000000..dd77a9c3
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeInitCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cordvtn.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.CordVtnNode;
+
+import java.util.NoSuchElementException;
+
+/**
+ * Initializes nodes for CordVtn service.
+ */
+@Command(scope = "onos", name = "cordvtn-node-init",
+ description = "Initializes nodes for CORD VTN service")
+public class CordVtnNodeInitCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "hostnames", description = "Hostname(s)",
+ required = true, multiValued = true)
+ private String[] hostnames = null;
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+
+ for (String hostname : hostnames) {
+ CordVtnNode node;
+ try {
+ node = service.getNodes()
+ .stream()
+ .filter(n -> n.hostname().equals(hostname))
+ .findFirst().get();
+ } catch (NoSuchElementException e) {
+ print("Unable to find %s", hostname);
+ continue;
+ }
+
+ service.initNode(node);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java
new file mode 100644
index 00000000..83e58598
--- /dev/null
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/cli/CordVtnNodeListCommand.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.cordvtn.cli;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.cordvtn.CordVtnService;
+import org.onosproject.cordvtn.CordVtnNode;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Lists all nodes registered to the service.
+ */
+@Command(scope = "onos", name = "cordvtn-nodes",
+ description = "Lists all nodes registered in CORD VTN service")
+public class CordVtnNodeListCommand extends AbstractShellCommand {
+
+ @Override
+ protected void execute() {
+ CordVtnService service = AbstractShellCommand.get(CordVtnService.class);
+ List<CordVtnNode> nodes = service.getNodes();
+ Collections.sort(nodes, CordVtnNode.CORDVTN_NODE_COMPARATOR);
+
+ if (outputJson()) {
+ print("%s", json(service, nodes));
+ } else {
+ for (CordVtnNode node : nodes) {
+ print("hostname=%s, ovsdb=%s, br-int=%s, init=%s",
+ node.hostname(),
+ node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString(),
+ node.intBrId().toString(),
+ getState(service, node));
+ }
+ print("Total %s nodes", service.getNodeCount());
+ }
+ }
+
+ private JsonNode json(CordVtnService service, List<CordVtnNode> nodes) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode result = mapper.createArrayNode();
+ for (CordVtnNode node : nodes) {
+ String ipPort = node.ovsdbIp().toString() + ":" + node.ovsdbPort().toString();
+ result.add(mapper.createObjectNode()
+ .put("hostname", node.hostname())
+ .put("ovsdb", ipPort)
+ .put("brInt", node.intBrId().toString())
+ .put("init", getState(service, node)));
+ }
+ return result;
+ }
+
+ private String getState(CordVtnService service, CordVtnNode node) {
+ return service.getNodeInitState(node) ? "COMPLETE" : "INCOMPLETE";
+ }
+}
diff --git a/framework/src/onos/apps/dhcp/app/features.xml b/framework/src/onos/apps/dhcp/app/features.xml
index 0b277dea..496cf80f 100644
--- a/framework/src/onos/apps/dhcp/app/features.xml
+++ b/framework/src/onos/apps/dhcp/app/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
diff --git a/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java
new file mode 100644
index 00000000..cd8149ea
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DhcpWebResource.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.dhcp.rest;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onosproject.dhcp.DhcpService;
+import org.onosproject.dhcp.IpAssignment;
+import org.onosproject.net.HostId;
+import org.onosproject.rest.AbstractWebResource;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Manage DHCP address assignments.
+ */
+@Path("dhcp")
+public class DhcpWebResource extends AbstractWebResource {
+
+ final DhcpService service = get(DhcpService.class);
+
+ /**
+ * Get DHCP server configuration data.
+ * Shows lease, renewal and rebinding times in seconds.
+ *
+ * @return 200 OK
+ * @rsModel DhcpConfigGet
+ */
+ @GET
+ @Path("config")
+ public Response getConfigs() {
+ DhcpService service = get(DhcpService.class);
+ ObjectNode node = mapper().createObjectNode()
+ .put("leaseTime", service.getLeaseTime())
+ .put("renewalTime", service.getRenewalTime())
+ .put("rebindingTime", service.getRebindingTime());
+ return ok(node.toString()).build();
+ }
+
+ /**
+ * Get all MAC/IP mappings.
+ * Shows all MAC/IP mappings held by the DHCP server.
+ *
+ * @rsModel DhcpConfigGetMappings
+ * @return 200 OK
+ */
+ @GET
+ @Path("mappings")
+ public Response listMappings() {
+ ObjectNode root = mapper().createObjectNode();
+
+ final Map<HostId, IpAssignment> intents = service.listMapping();
+ ArrayNode arrayNode = root.putArray("mappings");
+ intents.entrySet().forEach(i -> arrayNode.add(mapper().createObjectNode()
+ .put("host", i.getKey().toString())
+ .put("ip", i.getValue().ipAddress().toString())));
+
+ return ok(root.toString()).build();
+ }
+
+
+ /**
+ * Get all available IPs.
+ * Shows all the IPs in the free pool of the DHCP Server.
+ *
+ * @rsModel DhcpConfigGetAvailable
+ * @return 200 OK
+ */
+ @GET
+ @Path("available")
+ public Response listAvailableIPs() {
+ final Iterable<Ip4Address> availableIPList = service.getAvailableIPs();
+
+ final ObjectNode root = mapper().createObjectNode();
+ ArrayNode arrayNode = root.putArray("availableIP");
+ availableIPList.forEach(i -> arrayNode.add(i.toString()));
+ return ok(root.toString()).build();
+ }
+
+ /**
+ * Post a new static MAC/IP binding.
+ * Registers a static binding to the DHCP server, and displays the current set of bindings.
+ *
+ * @rsModel DhcpConfigPut
+ * @param stream JSON stream
+ * @return 200 OK
+ */
+ @POST
+ @Path("mappings")
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response setMapping(InputStream stream) {
+ ObjectNode root = mapper().createObjectNode();
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ JsonNode macID = jsonTree.get("mac");
+ JsonNode ip = jsonTree.get("ip");
+ if (macID != null && ip != null) {
+
+ if (!service.setStaticMapping(MacAddress.valueOf(macID.asText()),
+ Ip4Address.valueOf(ip.asText()),
+ false, Lists.newArrayList())) {
+ throw new IllegalArgumentException("Static Mapping Failed. " +
+ "The IP maybe unavailable.");
+ }
+ }
+
+ final Map<HostId, IpAssignment> intents = service.listMapping();
+ ArrayNode arrayNode = root.putArray("mappings");
+ intents.entrySet().forEach(i -> arrayNode.add(mapper().createObjectNode()
+ .put("host", i.getKey().toString())
+ .put("ip", i.getValue().ipAddress().toString())));
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ return ok(root.toString()).build();
+ }
+
+ /**
+ * Delete a static MAC/IP binding.
+ * Removes a static binding from the DHCP Server, and displays the current set of bindings.
+ *
+ * @param macID mac address identifier
+ * @return 200 OK
+ */
+ @DELETE
+ @Path("mappings/{macID}")
+ public Response deleteMapping(@PathParam("macID") String macID) {
+
+ ObjectNode root = mapper().createObjectNode();
+
+ if (!service.removeStaticMapping(MacAddress.valueOf(macID))) {
+ throw new IllegalArgumentException("Static Mapping Removal Failed.");
+ }
+ final Map<HostId, IpAssignment> intents = service.listMapping();
+ ArrayNode arrayNode = root.putArray("mappings");
+ intents.entrySet().forEach(i -> arrayNode.add(mapper().createObjectNode()
+ .put("host", i.getKey().toString())
+ .put("ip", i.getValue().ipAddress().toString())));
+
+ return ok(root.toString()).build();
+ }
+}
diff --git a/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGet.json b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGet.json
new file mode 100644
index 00000000..9e451b30
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGet.json
@@ -0,0 +1,26 @@
+{
+ "type": "object",
+ "required": [
+ "leaseTime",
+ "renewalTime",
+ "rebindingTime"
+ ],
+ "properties": {
+ "leaseTime": {
+ "type": "integer",
+ "format": "int64",
+ "example": "250"
+ },
+ "renewalTime": {
+ "type": "integer",
+ "format": "int64",
+ "example": "250"
+ },
+ "rebindingTime": {
+ "type": "integer",
+ "format": "int64",
+ "example": "250"
+ }
+ }
+}
+
diff --git a/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetAvailable.json b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetAvailable.json
new file mode 100644
index 00000000..2dcb91d5
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetAvailable.json
@@ -0,0 +1,16 @@
+{
+ "type": "object",
+ "required": [
+ "availableIp"
+ ],
+ "properties": {
+ "availableIp": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": "[127.0.0.1]"
+ }
+ }
+}
+
diff --git a/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetMappings.json b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetMappings.json
new file mode 100644
index 00000000..c4d17f66
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigGetMappings.json
@@ -0,0 +1,16 @@
+{
+ "type": "object",
+ "required": [
+ "mappings"
+ ],
+ "properties": {
+ "mappings": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "example": "[]"
+ }
+ }
+}
+
diff --git a/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigPut.json b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigPut.json
new file mode 100644
index 00000000..a8eb5378
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/definitions/DhcpConfigPut.json
@@ -0,0 +1,17 @@
+{
+ "type": "object",
+ "required": [
+ "mac",
+ "ip"],
+ "properties": {
+ "mac": {
+ "type": "String",
+ "example": "be:48:89:d5:75:59"
+ },
+ "ip": {
+ "type": "String",
+ "example": "10.128.12.4"
+ }
+ }
+}
+
diff --git a/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java b/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
index f5bd1e01..2b9a2a54 100644
--- a/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
+++ b/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/impl/McastForwarding.java
@@ -168,7 +168,7 @@ public class McastForwarding {
* ingress port would be a specific device.
*/
McastRoute entry = mrib.findBestMatch(spfx, gpfx);
- if (entry == null || entry.getSaddr().equals(IPv4.fromIPv4Address(0))) {
+ if (entry == null || entry.getSaddr().address().isZero()) {
/*
* Create an entry that we can fast drop.
diff --git a/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/Olt.java b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/Olt.java
new file mode 100644
index 00000000..ffc4705a
--- /dev/null
+++ b/framework/src/onos/apps/olt/src/main/java/org/onosproject/olt/Olt.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.olt;
+
+import com.google.common.base.Strings;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Tools;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+
+import java.util.Dictionary;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Provisions rules on access devices.
+ */
+@Service
+@Component(immediate = true)
+public class Olt implements AccessDeviceService {
+ private final Logger log = getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry networkConfig;
+
+ private final DeviceListener deviceListener = new InternalDeviceListener();
+
+ private ApplicationId appId;
+
+ private static final VlanId DEFAULT_VLAN = VlanId.vlanId((short) 0);
+ public static final int OFFSET = 200;
+
+ public static final int UPLINK_PORT = 129;
+ public static final int GFAST_UPLINK_PORT = 100;
+
+ public static final String OLT_DEVICE = "of:90e2ba82f97791e9";
+ public static final String GFAST_DEVICE = "of:0011223344551357";
+
+ @Property(name = "uplinkPort", intValue = UPLINK_PORT,
+ label = "The OLT's uplink port number")
+ private int uplinkPort = UPLINK_PORT;
+
+ @Property(name = "gfastUplink", intValue = GFAST_UPLINK_PORT,
+ label = "The OLT's uplink port number")
+ private int gfastUplink = GFAST_UPLINK_PORT;
+
+ //TODO: replace this with an annotation lookup
+ @Property(name = "oltDevice", value = OLT_DEVICE,
+ label = "The OLT device id")
+ private String oltDevice = OLT_DEVICE;
+
+ @Property(name = "gfastDevice", value = GFAST_DEVICE,
+ label = "The gfast device id")
+ private String gfastDevice = GFAST_DEVICE;
+
+ private Map<DeviceId, AccessDeviceData> oltData = new ConcurrentHashMap<>();
+
+ private InternalNetworkConfigListener configListener =
+ new InternalNetworkConfigListener();
+ private static final Class<AccessDeviceConfig> CONFIG_CLASS =
+ AccessDeviceConfig.class;
+
+ private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
+ new ConfigFactory<DeviceId, AccessDeviceConfig>(
+ SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
+ @Override
+ public AccessDeviceConfig createConfig() {
+ return new AccessDeviceConfig();
+ }
+ };
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication("org.onosproject.olt");
+
+ networkConfig.registerConfigFactory(configFactory);
+ networkConfig.addListener(configListener);
+
+ networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
+ subject -> {
+ AccessDeviceConfig config = networkConfig.getConfig(subject, AccessDeviceConfig.class);
+ if (config != null) {
+ AccessDeviceData data = config.getOlt();
+ oltData.put(data.deviceId(), data);
+ }
+ }
+ );
+
+ /*deviceService.addListener(deviceListener);
+
+ deviceService.getPorts(DeviceId.deviceId(oltDevice)).stream().forEach(
+ port -> {
+ if (!port.number().isLogical() && port.isEnabled()) {
+ short vlanId = fetchVlanId(port.number());
+ if (vlanId > 0) {
+ provisionVlanOnPort(oltDevice, uplinkPort, port.number(), (short) 7);
+ provisionVlanOnPort(oltDevice, uplinkPort, port.number(), vlanId);
+ }
+ }
+ }
+ );*/
+
+
+ deviceService.getPorts(DeviceId.deviceId(gfastDevice)).stream()
+ .filter(port -> !port.number().isLogical())
+ .filter(Port::isEnabled)
+ .forEach(port -> {
+ short vlanId = (short) (fetchVlanId(port.number()) + OFFSET);
+ if (vlanId > 0) {
+ provisionVlanOnPort(gfastDevice, gfastUplink, port.number(), vlanId);
+ }
+ }
+ );
+ log.info("Started with Application ID {}", appId.id());
+ }
+
+ @Deactivate
+ public void deactivate() {
+ networkConfig.removeListener(configListener);
+ networkConfig.unregisterConfigFactory(configFactory);
+ log.info("Stopped");
+ }
+
+ @Modified
+ public void modified(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+
+ String s = Tools.get(properties, "uplinkPort");
+ uplinkPort = Strings.isNullOrEmpty(s) ? UPLINK_PORT : Integer.parseInt(s);
+
+ s = Tools.get(properties, "oltDevice");
+ oltDevice = Strings.isNullOrEmpty(s) ? OLT_DEVICE : s;
+ }
+
+ private short fetchVlanId(PortNumber port) {
+ long p = port.toLong() + OFFSET;
+ if (p > 4095) {
+ log.warn("Port Number {} exceeds vlan max", port);
+ return -1;
+ }
+ return (short) p;
+ }
+
+ private void provisionVlanOnPort(String deviceId, int uplinkPort, PortNumber p, short vlanId) {
+ DeviceId did = DeviceId.deviceId(deviceId);
+
+ TrafficSelector upstream = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId(vlanId))
+ .matchInPort(p)
+ .build();
+
+ TrafficSelector downStream = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId(vlanId))
+ .matchInPort(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment downStreamTreatment = DefaultTrafficTreatment.builder()
+ .setOutput(p)
+ .build();
+
+
+ ForwardingObjective upFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(upstream)
+ .fromApp(appId)
+ .withTreatment(upstreamTreatment)
+ .add();
+
+ ForwardingObjective downFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(downStream)
+ .fromApp(appId)
+ .withTreatment(downStreamTreatment)
+ .add();
+
+ flowObjectiveService.forward(did, upFwd);
+ flowObjectiveService.forward(did, downFwd);
+ }
+
+ @Override
+ public void provisionSubscriber(ConnectPoint port, VlanId vlan) {
+ AccessDeviceData olt = oltData.get(port.deviceId());
+
+ if (olt == null) {
+ log.warn("No data found for OLT device {}", port.deviceId());
+ return;
+ }
+
+ provisionVlans(olt.deviceId(), olt.uplink(), port.port(), vlan, olt.vlan(),
+ olt.defaultVlan());
+ }
+
+ private void provisionVlans(DeviceId deviceId, PortNumber uplinkPort,
+ PortNumber subscriberPort,
+ VlanId subscriberVlan, VlanId deviceVlan,
+ Optional<VlanId> defaultVlan) {
+
+ TrafficSelector upstream = DefaultTrafficSelector.builder()
+ .matchVlanId((defaultVlan.isPresent()) ? defaultVlan.get() : DEFAULT_VLAN)
+ .matchInPort(subscriberPort)
+ .build();
+
+ TrafficSelector downstream = DefaultTrafficSelector.builder()
+ .matchVlanId(deviceVlan)
+ .matchInPort(uplinkPort)
+ .build();
+
+ TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
+ .setVlanId(subscriberVlan)
+ .pushVlan()
+ .setVlanId(deviceVlan)
+ .setOutput(uplinkPort)
+ .build();
+
+ TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
+ .popVlan()
+ .setVlanId((defaultVlan.isPresent()) ? defaultVlan.get() : DEFAULT_VLAN)
+ .setOutput(subscriberPort)
+ .build();
+
+
+ ForwardingObjective upFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(upstream)
+ .fromApp(appId)
+ .withTreatment(upstreamTreatment)
+ .add();
+
+ ForwardingObjective downFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(downstream)
+ .fromApp(appId)
+ .withTreatment(downstreamTreatment)
+ .add();
+
+ flowObjectiveService.forward(deviceId, upFwd);
+ flowObjectiveService.forward(deviceId, downFwd);
+ }
+
+ @Override
+ public void removeSubscriber(ConnectPoint port) {
+ throw new UnsupportedOperationException("Not yet implemented");
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+ @Override
+ public void event(DeviceEvent event) {
+ DeviceId devId = DeviceId.deviceId(oltDevice);
+ switch (event.type()) {
+ case PORT_ADDED:
+ case PORT_UPDATED:
+ if (devId.equals(event.subject().id()) && event.port().isEnabled()) {
+ short vlanId = fetchVlanId(event.port().number());
+ provisionVlanOnPort(gfastDevice, uplinkPort, event.port().number(), vlanId);
+ }
+ break;
+ case DEVICE_ADDED:
+ case DEVICE_UPDATED:
+ case DEVICE_REMOVED:
+ case DEVICE_SUSPENDED:
+ case DEVICE_AVAILABILITY_CHANGED:
+ case PORT_REMOVED:
+ case PORT_STATS_UPDATED:
+ default:
+ return;
+ }
+ }
+ }
+
+ private class InternalNetworkConfigListener implements NetworkConfigListener {
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ if (event.configClass().equals(CONFIG_CLASS)) {
+ AccessDeviceConfig config =
+ networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
+ if (config != null) {
+ oltData.put(config.getOlt().deviceId(), config.getOlt());
+ }
+ }
+ break;
+ case CONFIG_UNREGISTERED:
+ case CONFIG_REMOVED:
+ default:
+ break;
+ }
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/openstackswitching/api/pom.xml b/framework/src/onos/apps/openstackswitching/api/pom.xml
new file mode 100644
index 00000000..f5e6f94f
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/api/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-openstackswitching</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-openstackswitching-api</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>SONA Openstack Switching application API</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
index 7bfdf290..1b28d0c4 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
+++ b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
@@ -77,6 +77,11 @@ public final class OpenstackNetwork {
return this.networkType;
}
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+
public static final class Builder {
private String name;
private String tenantId;
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java
index 4326b4fc..1613b597 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java
+++ b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java
@@ -19,6 +19,7 @@ import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.MacAddress;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@@ -31,7 +32,8 @@ public final class OpenstackPort {
public enum PortStatus {
UP,
- DOWN
+ DOWN,
+ ACTIVE
}
private PortStatus status;
@@ -179,6 +181,16 @@ public final class OpenstackPort {
//
//}
+ @Override
+ public Object clone() {
+ OpenstackPort op = new OpenstackPort(this.status, this.name, this.adminStateUp,
+ this.networkId, this.tenantId, this.deviceOwner, this.macAddress,
+ (HashMap) this.fixedIps.clone(), this.id,
+ Collections.unmodifiableList(this.securityGroups), this.deviceId);
+
+ return op;
+ }
+
/**
* OpenstackPort Builder class.
*/
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java
index 39d783e3..bc536e88 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java
+++ b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSubnet.java
@@ -15,6 +15,10 @@
*/
package org.onosproject.openstackswitching;
+import org.onlab.packet.Ip4Address;
+
+import java.util.List;
+
import static com.google.common.base.Preconditions.checkNotNull;
/**
@@ -26,13 +30,13 @@ public final class OpenstackSubnet {
private boolean enableHhcp;
private String networkId;
private String tenantId;
- private String dnsNameservers;
+ private List<Ip4Address> dnsNameservers;
private String gatewayIp;
private String cidr;
private String id;
private OpenstackSubnet(String name, boolean enableHhcp, String networkId,
- String tenantId, String dnsNameservers, String gatewayIp,
+ String tenantId, List<Ip4Address> dnsNameservers, String gatewayIp,
String cidr, String id) {
this.name = name;
this.enableHhcp = enableHhcp;
@@ -69,7 +73,7 @@ public final class OpenstackSubnet {
return tenantId;
}
- public String dnsNameservers() {
+ public List<Ip4Address> dnsNameservers() {
return dnsNameservers;
}
@@ -85,8 +89,6 @@ public final class OpenstackSubnet {
return id;
}
- // TODO : Implement the following functions when necessary
-
/**
* OpenstackSubnet Builder class.
*
@@ -96,7 +98,7 @@ public final class OpenstackSubnet {
private boolean enableDhcp;
private String networkId;
private String tenantId;
- private String dnsNameservers;
+ private List<Ip4Address> dnsNameservers;
private String gatewayIp;
private String cidr;
private String id;
@@ -127,7 +129,7 @@ public final class OpenstackSubnet {
return this;
}
- public Builder setDnsNameservers(String dnsNameservers) {
+ public Builder setDnsNameservers(List<Ip4Address> dnsNameservers) {
this.dnsNameservers = dnsNameservers;
return this;
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
index 3d40d51d..59b8db0c 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
+++ b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
@@ -15,8 +15,12 @@
*/
package org.onosproject.openstackswitching;
+import org.onosproject.net.Port;
+
+import java.util.Collection;
+
/**
- * It handles port management REST API from Openstack for VMs.
+ * Handles port management REST API from Openstack for VMs.
*/
public interface OpenstackSwitchingService {
@@ -40,16 +44,49 @@ public interface OpenstackSwitchingService {
void updatePorts();
/**
- * Store the network information created by openstack.
+ * Stores the network information created by openstack.
*
* @param openstackNetwork network information
*/
void createNetwork(OpenstackNetwork openstackNetwork);
/**
- * Store the subnet information created by openstack.
+ * Stores the subnet information created by openstack.
*
* @param openstackSubnet subnet information
*/
void createSubnet(OpenstackSubnet openstackSubnet);
+
+ /**
+ * Returns port information list for the network ID given.
+ *
+ * @param networkId Network ID of the ports
+ * @return port information list
+ */
+ Collection<OpenstackPort> ports(String networkId);
+
+ /**
+ * Returns port information for the port given.
+ *
+ * @param port port reference
+ * @return port information
+ */
+ OpenstackPort port(Port port);
+
+ /**
+ * Returns port information for the port ID given.
+ *
+ * @param portId Port ID
+ * @return port information
+ */
+ OpenstackPort port(String portId);
+
+ /**
+ * Returns network information list for the network ID given.
+ *
+ * @param networkId Network ID
+ * @return network information list
+ */
+ OpenstackNetwork network(String networkId);
+
}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/package-info.java
index cd50f912..cd50f912 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java
+++ b/framework/src/onos/apps/openstackswitching/api/src/main/java/org/onosproject/openstackswitching/package-info.java
diff --git a/framework/src/onos/apps/openstackswitching/app/app.xml b/framework/src/onos/apps/openstackswitching/app/app.xml
new file mode 100644
index 00000000..e982b90d
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/app.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<app name="org.onosproject.openstackswitching" origin="ON.Lab" version="${project.version}"
+ featuresRepo="mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features"
+ features="${project.artifactId}">
+ <description>${project.description}</description>
+ <artifact>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-app-dhcp/${project.version}</artifact>
+</app>
diff --git a/framework/src/onos/apps/openstackswitching/app/features.xml b/framework/src/onos/apps/openstackswitching/app/features.xml
new file mode 100644
index 00000000..acb07b62
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/features.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <bundle>mvn:${project.groupId}/onos-app-openstackswitching/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-dhcp/${project.version}</bundle>
+ <bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle>
+ <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/framework/src/onos/apps/openstackswitching/app/pom.xml b/framework/src/onos/apps/openstackswitching/app/pom.xml
new file mode 100644
index 00000000..5460faef
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/pom.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<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/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-openstackswitching</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-openstackswitching</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>SONA Openstack Switching applications</description>
+ <properties>
+ <onos.version>1.4.0-SNAPSHOT</onos.version>
+ <onos.app.name>org.onosproject.openstackswitching</onos.app.name>
+ <web.context>/onos/openstackswitching</web.context>
+ <api.version>1.0.0</api.version>
+ <api.title>ONOS OpenStack Switching REST API</api.title>
+ <api.description>
+ APIs for receiving Neutron information.
+ </api.description>
+ <api.package>org.onosproject.openstackswitching.web</api.package>
+ <onos.app.origin>SKT, Inc.</onos.app.origin>
+ </properties>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-openstackswitching-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-rest</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-servlet</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-dhcp-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.19</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <_wab>src/main/webapp/</_wab>
+ <Bundle-SymbolicName>
+ ${project.groupId}.${project.artifactId}
+ </Bundle-SymbolicName>
+ <Import-Package>
+ org.slf4j,
+ org.osgi.framework,
+ javax.ws.rs,
+ javax.ws.rs.core,
+ com.sun.jersey.api.core,
+ com.sun.jersey.api.client,
+ com.sun.jersey.spi.container.servlet,
+ com.sun.jersey.server.impl.container.servlet,
+ com.fasterxml.jackson.databind,
+ com.fasterxml.jackson.databind.node,
+ com.fasterxml.jackson.core,
+ org.apache.karaf.shell.commands,
+ com.google.common.*,
+ org.onlab.packet.*,
+ org.onosproject.*
+ </Import-Package>
+ <Web-ContextPath>${web.context}</Web-ContextPath>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+
+</project>
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
index 0c139d8d..944d12a1 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
@@ -28,26 +28,27 @@ import org.onosproject.net.packet.PacketService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
-import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
/**
- * It handles ARP packet from VMs.
+ * Handles ARP packet from VMs.
*/
public class OpenstackArpHandler {
private static Logger log = LoggerFactory
.getLogger(OpenstackArpHandler.class);
private PacketService packetService;
- private Map<String, OpenstackPort> openstackPortMap;
+ private OpenstackRestHandler restHandler;
/**
* Returns OpenstackArpHandler reference.
*
- * @param openstackPortMap
- * @param packetService
+ * @param restHandler rest API handler reference
+ * @param packetService PacketService reference
*/
- public OpenstackArpHandler(Map<String, OpenstackPort> openstackPortMap, PacketService packetService) {
- this.openstackPortMap = openstackPortMap;
+ public OpenstackArpHandler(OpenstackRestHandler restHandler, PacketService packetService) {
+ this.restHandler = checkNotNull(restHandler);
this.packetService = packetService;
}
@@ -68,8 +69,9 @@ public class OpenstackArpHandler {
//Searches the Dst MAC Address based on openstackPortMap
MacAddress macAddress = null;
- OpenstackPort openstackPort = openstackPortMap.values().stream().filter(e -> e.fixedIps().
- containsValue(Ip4Address.valueOf(dstIPAddress))).findAny().orElse(null);
+ OpenstackPort openstackPort = restHandler.getPorts().stream().
+ filter(e -> e.fixedIps().containsValue(Ip4Address.valueOf(
+ dstIPAddress))).findAny().orElse(null);
if (openstackPort != null) {
macAddress = openstackPort.macAddress();
diff --git a/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackRestHandler.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackRestHandler.java
new file mode 100644
index 00000000..9065bc52
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackRestHandler.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstackswitching;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.WebResource;
+import org.onosproject.openstackswitching.web.OpenstackNetworkCodec;
+import org.onosproject.openstackswitching.web.OpenstackPortCodec;
+import org.onosproject.openstackswitching.web.OpenstackSubnetCodec;
+import org.slf4j.Logger;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.net.MediaType.JSON_UTF_8;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Handles REST Calls to Openstack Neutron.
+ *
+ */
+public class OpenstackRestHandler {
+
+ private final Logger log = getLogger(getClass());
+ private String neutronUrl;
+ private String keystoneUrl;
+ private String tokenId;
+ private String userName;
+ private String pass;
+
+ /**
+ * Creates OpenstackRestHandler instance.
+ *
+ * @param cfg OpenstackSwitchingConfig reference
+ */
+ public OpenstackRestHandler(OpenstackSwitchingConfig cfg) {
+ this.neutronUrl = checkNotNull(cfg.neutronServer());
+ this.keystoneUrl = checkNotNull(cfg.keystoneServer());
+ this.userName = checkNotNull(cfg.userName());
+ this.pass = checkNotNull(cfg.password());
+ }
+
+ /**
+ * Returns network information stored in Neutron.
+ *
+ * @return List of OpenstackNetwork
+ */
+ public Collection<OpenstackNetwork> getNetworks() {
+
+ WebResource.Builder builder = getClientBuilder(neutronUrl + "networks");
+ String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
+ header("X-Auth-Token", getToken()).get(String.class);
+
+ ObjectMapper mapper = new ObjectMapper();
+ List<OpenstackNetwork> openstackNetworks = Lists.newArrayList();
+ try {
+ ObjectNode node = (ObjectNode) mapper.readTree(response);
+ ArrayNode networkList = (ArrayNode) node.path("networks");
+ OpenstackNetworkCodec networkCodec = new OpenstackNetworkCodec();
+ networkList.forEach(n -> openstackNetworks.add(networkCodec.decode((ObjectNode) n, null)));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ log.debug("networks response:" + response);
+ openstackNetworks.forEach(n -> log.debug("network ID: {}", n.id()));
+
+ return openstackNetworks;
+ }
+
+ /**
+ * Returns port information stored in Neutron.
+ *
+ * @return List of OpenstackPort
+ */
+ public Collection<OpenstackPort> getPorts() {
+
+ WebResource.Builder builder = getClientBuilder(neutronUrl + "ports");
+ String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
+ header("X-Auth-Token", getToken()).get(String.class);
+
+ ObjectMapper mapper = new ObjectMapper();
+ List<OpenstackPort> openstackPorts = Lists.newArrayList();
+ try {
+ ObjectNode node = (ObjectNode) mapper.readTree(response);
+ ArrayNode portList = (ArrayNode) node.path("ports");
+ OpenstackPortCodec portCodec = new OpenstackPortCodec();
+ portList.forEach(p -> openstackPorts.add(portCodec.decode((ObjectNode) p, null)));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ log.debug("port response:" + response);
+ openstackPorts.forEach(n -> log.debug("port ID: {}", n.id()));
+
+ return openstackPorts;
+ }
+
+ /**
+ * Returns Subnet information in Neutron.
+ *
+ * @return List of OpenstackSubnet
+ */
+ public Collection<OpenstackSubnet> getSubnets() {
+
+ WebResource.Builder builder = getClientBuilder(neutronUrl + "subnets");
+ String response = builder.accept(MediaType.APPLICATION_JSON_TYPE).
+ header("X-Auth-Token", getToken()).get(String.class);
+
+ ObjectMapper mapper = new ObjectMapper();
+ List<OpenstackSubnet> subnets = Lists.newArrayList();
+ try {
+ ObjectNode node = (ObjectNode) mapper.readTree(response);
+ ArrayNode subnetList = (ArrayNode) node.path("subnets");
+ OpenstackSubnetCodec subnetCodec = new OpenstackSubnetCodec();
+ subnetList.forEach(s -> subnets.add(subnetCodec.decode((ObjectNode) s, null)));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ log.debug("subnets response:" + response);
+ subnets.forEach(s -> log.debug("subnet ID: {}", s.id()));
+
+ return subnets;
+ }
+
+ private WebResource.Builder getClientBuilder(String uri) {
+ Client client = Client.create();
+ WebResource resource = client.resource(uri);
+ return resource.accept(JSON_UTF_8.toString())
+ .type(JSON_UTF_8.toString());
+ }
+
+ private String getToken() {
+ if (isTokenInvalid()) {
+ String request = "{\"auth\": {\"tenantName\": \"admin\", " +
+ "\"passwordCredentials\": {\"username\": \"" +
+ userName + "\",\"password\": \"" + pass + "\"}}}";
+ WebResource.Builder builder = getClientBuilder(keystoneUrl + "tokens");
+ String response = builder.accept(MediaType.APPLICATION_JSON).post(String.class, request);
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ ObjectNode node = (ObjectNode) mapper.readTree(response);
+ tokenId = node.path("access").path("token").path("id").asText();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ log.debug("token response:" + response);
+ }
+
+ return tokenId;
+ }
+
+ private boolean isTokenInvalid() {
+ //TODO: validation check for the existing token
+ return true;
+ }
+
+}
diff --git a/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingConfig.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingConfig.java
new file mode 100644
index 00000000..ba39ff66
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingConfig.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2014 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstackswitching;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+import org.onosproject.net.config.basics.BasicElementConfig;
+
+/**
+ * Handles configuration for OpenstackSwitching app.
+ */
+public class OpenstackSwitchingConfig extends Config<ApplicationId> {
+ public static final String DONOTPUSH = "do_not_push_flows";
+ public static final String NEUTRON_SERVER = "neutron_server";
+ public static final String KEYSTONE_SERVER = "keystone_server";
+ public static final String USER_NAME = "user_name";
+ public static final String PASSWORD = "password";
+
+ /**
+ * Returns the flag whether the app pushes flows or not.
+ *
+ * @return the flag or false if not set
+ */
+ public boolean doNotPushFlows() {
+ String flag = get(DONOTPUSH, "false");
+ return Boolean.valueOf(flag);
+ }
+
+ /**
+ * Returns the Neutron server IP address.
+ *
+ * @return Neutron server IP
+ */
+ public String neutronServer() {
+ return get(NEUTRON_SERVER, "");
+ }
+
+ /**
+ * Returns the Keystone server IP address.
+ *
+ * @return Keystone server IP
+ */
+ public String keystoneServer() {
+ return get(KEYSTONE_SERVER, "");
+ }
+
+ /**
+ * Returns the username for openstack.
+ *
+ * @return username for openstack
+ */
+ public String userName() {
+ return get(USER_NAME, "");
+ }
+
+ /**
+ * Returns the password for openstack.
+ *
+ * @return password for openstack
+ */
+ public String password() {
+ return get(PASSWORD, "");
+ }
+
+ /**
+ * Sets the flag whether the app pushes flows or not.
+ *
+ * @param flag the flag whether the app pushes flows or not
+ * @return self
+ */
+ public BasicElementConfig doNotPushFlows(boolean flag) {
+ return (BasicElementConfig) setOrClear(DONOTPUSH, flag);
+ }
+
+ /**
+ * Sets the neutron server IP address.
+ *
+ * @param url neutron server IP address
+ * @return itself
+ */
+ public BasicElementConfig neutronServer(String url) {
+ return (BasicElementConfig) setOrClear(NEUTRON_SERVER, url);
+ }
+
+ /**
+ * Sets the keystone server IP address.
+ *
+ * @param url keystone server IP address
+ * @return itself
+ */
+ public BasicElementConfig keystoneServer(String url) {
+ return (BasicElementConfig) setOrClear(KEYSTONE_SERVER, url);
+ }
+
+ /**
+ * Sets the username for openstack.
+ *
+ * @param username user name for openstack
+ * @return itself
+ */
+ public BasicElementConfig userName(String username) {
+ return (BasicElementConfig) setOrClear(USER_NAME, username);
+ }
+
+ /**
+ * Sets the password for openstack.
+ *
+ * @param password password for openstack
+ * @return itself
+ */
+ public BasicElementConfig password(String password) {
+ return (BasicElementConfig) setOrClear(PASSWORD, password);
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
new file mode 100644
index 00000000..d881d81c
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
@@ -0,0 +1,374 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.openstackswitching;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.dhcp.DhcpService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.config.ConfigFactory;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
+import org.onosproject.net.config.NetworkConfigRegistry;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.packet.InboundPacket;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.packet.PacketProcessor;
+import org.onosproject.net.packet.PacketService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.List;
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.stream.Collectors;
+
+import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
+
+@SuppressWarnings("ALL")
+@Service
+@Component(immediate = true)
+/**
+ * Populates forwarding rules for VMs created by Openstack.
+ */
+public class OpenstackSwitchingManager implements OpenstackSwitchingService {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackSwitchingManager.class);
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected PacketService packetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DhcpService dhcpService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry cfgService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ private ApplicationId appId;
+ private boolean doNotPushFlows;
+ private Ip4Address neutronServer;
+ private Ip4Address keystoneServer;
+ private String userName;
+ private String password;
+ private OpenstackArpHandler arpHandler;
+ private OpenstackRestHandler restHandler;
+
+ private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);
+
+ private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
+ private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
+ private InternalConfigListener internalConfigListener = new InternalConfigListener();
+ private final Set<ConfigFactory> factories = ImmutableSet.of(
+ new ConfigFactory<ApplicationId, OpenstackSwitchingConfig>(APP_SUBJECT_FACTORY,
+ OpenstackSwitchingConfig.class,
+ "openstackswitching") {
+ @Override
+ public OpenstackSwitchingConfig createConfig() {
+ return new OpenstackSwitchingConfig();
+ }
+ }
+ );
+
+ @Activate
+ protected void activate() {
+ appId = coreService
+ .registerApplication("org.onosproject.openstackswitching");
+
+ factories.forEach(cfgService::registerConfigFactory);
+ packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
+ deviceService.addListener(internalDeviceListener);
+ cfgService.addListener(internalConfigListener);
+
+ internalConfigListener.configureNetwork();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ packetService.removeProcessor(internalPacketProcessor);
+ deviceService.removeListener(internalDeviceListener);
+ cfgService.removeListener(internalConfigListener);
+
+ deviceEventExcutorService.shutdown();
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public void createPorts(OpenstackPort openstackPort) {
+ registerDhcpInfo(openstackPort);
+ }
+
+ @Override
+ public void deletePorts() {
+
+ }
+
+ @Override
+ public void updatePorts() {
+
+ }
+
+ @Override
+ public void createNetwork(OpenstackNetwork openstackNetwork) {
+ }
+
+ @Override
+ public void createSubnet(OpenstackSubnet openstackSubnet) {
+ }
+
+ @Override
+ public Collection<OpenstackPort> ports(String networkId) {
+ Collection<OpenstackPort> ports = restHandler.getPorts();
+ List<OpenstackPort> portList = ports.stream()
+ .filter(p -> p.networkId().equals(networkId))
+ .collect(Collectors.toList());
+
+ return portList;
+ }
+
+ @Override
+ public OpenstackPort port(Port port) {
+ Collection<OpenstackPort> ports = restHandler.getPorts();
+ String uuid = port.annotations().value("portName").substring(3);
+ return ports.stream()
+ .filter(p -> p.id().startsWith(uuid))
+ .findFirst().orElse(null);
+ }
+
+ @Override
+ public OpenstackPort port(String portId) {
+ Collection<OpenstackPort> ports = restHandler.getPorts();
+ return ports.stream()
+ .filter(p -> p.id().equals(portId))
+ .findFirst().orElse(null);
+ }
+
+ @Override
+ public OpenstackNetwork network(String networkId) {
+ Collection<OpenstackNetwork> networks = restHandler.getNetworks();
+ return networks.stream()
+ .filter(n -> n.id().equals(networkId))
+ .findFirst().orElse(null);
+ }
+
+ private void processDeviceAdded(Device device) {
+ log.debug("device {} is added", device.id());
+ }
+
+ private void processPortAdded(Device device, Port port) {
+ if (!port.annotations().value("portName").equals("vxlan")) {
+ OpenstackSwitchingRulePopulator rulePopulator =
+ new OpenstackSwitchingRulePopulator(appId, flowObjectiveService,
+ deviceService, restHandler, driverService);
+ rulePopulator.populateSwitchingRules(device, port);
+ }
+ }
+
+ private void processPortRemoved(Device device, Port port) {
+ // TODO: Remove flow rules for the VM removed
+ log.debug("port {} is removed", port.toString());
+ }
+
+ private void registerDhcpInfo(OpenstackPort openstackPort) {
+ Ip4Address ip4Address;
+ Ip4Address subnetMask;
+ Ip4Address dhcpServer;
+ Ip4Address gatewayIPAddress;
+ Ip4Address domainServer;
+ OpenstackSubnet openstackSubnet;
+
+ ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
+
+ openstackSubnet = restHandler.getSubnets().stream()
+ .filter(n -> n.networkId().equals(openstackPort.networkId()))
+ .findFirst().get();
+
+ subnetMask = Ip4Address.valueOf(buildSubnetMask(openstackSubnet.cidr()));
+ gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
+ dhcpServer = gatewayIPAddress;
+ // TODO: supports multiple DNS servers
+ if (openstackSubnet.dnsNameservers().isEmpty()) {
+ domainServer = Ip4Address.valueOf("8.8.8.8");
+ } else {
+ domainServer = openstackSubnet.dnsNameservers().get(0);
+ }
+ List<Ip4Address> options = Lists.newArrayList();
+ options.add(subnetMask);
+ options.add(dhcpServer);
+ options.add(gatewayIPAddress);
+ options.add(domainServer);
+
+ dhcpService.setStaticMapping(openstackPort.macAddress(), ip4Address, true, options);
+ }
+
+ private byte[] buildSubnetMask(String cidr) {
+ int prefix;
+ String[] parts = cidr.split("/");
+ prefix = Integer.parseInt(parts[1]);
+ int mask = 0xffffffff << (32 - prefix);
+ byte[] bytes = new byte[]{(byte) (mask >>> 24),
+ (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
+
+ return bytes;
+ }
+
+
+
+ private class InternalPacketProcessor implements PacketProcessor {
+
+ @Override
+ public void process(PacketContext context) {
+
+ if (context.isHandled()) {
+ return;
+ }
+
+ InboundPacket pkt = context.inPacket();
+ Ethernet ethernet = pkt.parsed();
+
+ if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
+ arpHandler.processPacketIn(pkt);
+ }
+ }
+ }
+
+ private class InternalDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent deviceEvent) {
+ deviceEventExcutorService.execute(new InternalEventHandler(deviceEvent));
+ }
+ }
+
+ private class InternalEventHandler implements Runnable {
+
+ volatile DeviceEvent deviceEvent;
+
+ InternalEventHandler(DeviceEvent deviceEvent) {
+ this.deviceEvent = deviceEvent;
+ }
+
+ @Override
+ public void run() {
+
+ if (doNotPushFlows) {
+ return;
+ }
+
+ switch (deviceEvent.type()) {
+ case DEVICE_ADDED:
+ processDeviceAdded((Device) deviceEvent.subject());
+ break;
+ case DEVICE_UPDATED:
+ Port port = (Port) deviceEvent.subject();
+ if (port.isEnabled()) {
+ processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ }
+ break;
+ case DEVICE_AVAILABILITY_CHANGED:
+ Device device = (Device) deviceEvent.subject();
+ if (deviceService.isAvailable(device.id())) {
+ processDeviceAdded(device);
+ }
+ break;
+ case PORT_ADDED:
+ processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ break;
+ case PORT_UPDATED:
+ processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
+ break;
+ case PORT_REMOVED:
+ processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private class InternalConfigListener implements NetworkConfigListener {
+
+ public void configureNetwork() {
+ OpenstackSwitchingConfig cfg =
+ cfgService.getConfig(appId, OpenstackSwitchingConfig.class);
+ if (cfg == null) {
+ log.error("There is no openstack server information in config.");
+ return;
+ }
+ doNotPushFlows = cfg.doNotPushFlows();
+ restHandler = new OpenstackRestHandler(cfg);
+ arpHandler = new OpenstackArpHandler(restHandler, packetService);
+ }
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ if (((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
+ event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED)) &&
+ event.configClass().equals(OpenstackSwitchingConfig.class)) {
+ configureNetwork();
+ }
+ }
+
+ }
+
+ private final class PortInfo {
+ DeviceId deviceId;
+ String portName;
+ Ip4Address fixedIp;
+ Ip4Address hostIp;
+
+ private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
+ Ip4Address hostIp) {
+ this.deviceId = deviceId;
+ this.portName = portName;
+ this.fixedIp = fixedIp;
+ this.hostIp = hostIp;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
new file mode 100644
index 00000000..38c03638
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
@@ -0,0 +1,307 @@
+/*
+* Copyright 2015 Open Networking Laboratory
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package org.onosproject.openstackswitching;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionPropertyException;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+
+/**
+ * Populates switching flow rules.
+ */
+public class OpenstackSwitchingRulePopulator {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackSwitchingRulePopulator.class);
+ private static final int SWITCHING_RULE_PRIORITY = 50000;
+
+ private FlowObjectiveService flowObjectiveService;
+ private DriverService driverService;
+ private DeviceService deviceService;
+ private OpenstackRestHandler restHandler;
+ private ApplicationId appId;
+
+ private Collection<OpenstackNetwork> openstackNetworkList;
+ private Collection<OpenstackPort> openstackPortList;
+
+ /**
+ * Creates OpenstackSwitchingRulPopulator.
+ *
+ * @param appId application id
+ * @param flowObjectiveService FlowObjectiveService reference
+ * @param deviceService DeviceService reference
+ * @param driverService DriverService reference
+ */
+ public OpenstackSwitchingRulePopulator(ApplicationId appId,
+ FlowObjectiveService flowObjectiveService,
+ DeviceService deviceService,
+ OpenstackRestHandler restHandler,
+ DriverService driverService) {
+ this.flowObjectiveService = flowObjectiveService;
+ this.deviceService = deviceService;
+ this.driverService = driverService;
+ this.restHandler = restHandler;
+ this.appId = appId;
+
+ openstackNetworkList = restHandler.getNetworks();
+ openstackPortList = restHandler.getPorts();
+ }
+
+ /**
+ * Populates flow rules for the VM created.
+ *
+ * @param device device to populate rules to
+ * @param port port for the VM created
+ */
+ public void populateSwitchingRules(Device device, Port port) {
+ populateFlowRulesForTrafficToSameCnode(device, port);
+ populateFlowRulesForTrafficToDifferentCnode(device, port);
+ }
+
+ /**
+ * Populates the flow rules for traffic to VMs in the same Cnode as the sender.
+ *
+ * @param device device to put the rules
+ * @param port port info of the VM
+ */
+ private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) {
+ Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName"));
+ if (vmIp != null) {
+ setFlowRuleForVMsInSameCnode(vmIp, device.id(), port);
+ }
+ }
+
+ /**
+ * Populates the flow rules for traffic to VMs in different Cnode using
+ * Nicira extention.
+ *
+ * @param device device to put rules
+ * @param port port information of the VM
+ */
+ private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) {
+ String portName = port.annotations().value("portName");
+ String channelId = device.annotations().value("channelId");
+ Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
+ Ip4Address fixedIp = getFixedIpAddressForPort(portName);
+ MacAddress vmMac = getVmMacAddressForPort(portName);
+ String vni = getVniForPort(portName);
+ deviceService.getAvailableDevices().forEach(d -> {
+ if (!d.equals(device)) {
+ deviceService.getPorts(d.id()).forEach(p -> {
+ String pName = p.annotations().value("portName");
+ if (!p.equals(port) && vni.equals(getVniForPort(pName))) {
+ String cidx = d.annotations().value("channelId");
+ Ip4Address hostIpx = Ip4Address.valueOf(cidx.split(":")[0]);
+ MacAddress vmMacx = getVmMacAddressForPort(pName);
+ Ip4Address fixedIpx = getFixedIpAddressForPort(pName);
+
+ setVxLanFlowRule(vni, device.id(), hostIpx, fixedIpx, vmMacx);
+ setVxLanFlowRule(vni, d.id(), hostIpAddress, fixedIp, vmMac);
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Returns the VNI of the VM of the port.
+ *
+ * @param portName VM port
+ * @return VNI
+ */
+ private String getVniForPort(String portName) {
+ String uuid = portName.substring(3);
+ OpenstackPort port = openstackPortList.stream()
+ .filter(p -> p.id().startsWith(uuid))
+ .findAny().orElse(null);
+ if (port == null) {
+ log.warn("No port information for port {}", portName);
+ return null;
+ }
+
+ OpenstackNetwork network = openstackNetworkList.stream()
+ .filter(n -> n.id().equals(port.networkId()))
+ .findAny().orElse(null);
+ if (network == null) {
+ log.warn("No VNI information for network {}", port.networkId());
+ return null;
+ }
+
+ return network.segmentId();
+ }
+
+ /**
+ * Returns the Fixed IP address of the VM.
+ *
+ * @param portName VM port info
+ * @return IP address of the VM
+ */
+ private Ip4Address getFixedIpAddressForPort(String portName) {
+
+ String uuid = portName.substring(3);
+ OpenstackPort port = openstackPortList.stream()
+ .filter(p -> p.id().startsWith(uuid))
+ .findFirst().orElse(null);
+
+ if (port == null) {
+ log.error("There is no port information for port name {}", portName);
+ return null;
+ }
+
+ if (port.fixedIps().isEmpty()) {
+ log.error("There is no fixed IP info in the port information");
+ return null;
+ }
+
+ return (Ip4Address) port.fixedIps().values().toArray()[0];
+ }
+
+ /**
+ * Returns the MAC address of the VM of the port.
+ *
+ * @param portName VM port
+ * @return MAC address of the VM
+ */
+ private MacAddress getVmMacAddressForPort(String portName) {
+
+ String uuid = portName.substring(3);
+ OpenstackPort port = openstackPortList.stream()
+ .filter(p -> p.id().startsWith(uuid))
+ .findFirst().orElse(null);
+
+ if (port == null) {
+ log.error("There is port information for port name {}", portName);
+ return null;
+ }
+
+ return port.macAddress();
+ }
+
+ /**
+ * Sets the flow rules for traffic between VMs in the same Cnode.
+ *
+ * @param ip4Address VM IP address
+ * @param id device ID to put rules
+ * @param port VM port
+ */
+ private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id,
+ Port port) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(ip4Address.toIpPrefix());
+ tBuilder.setOutput(port.number());
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .add();
+
+ flowObjectiveService.forward(id, fo);
+ }
+
+ /**
+ * Sets the flow rules between traffic from VMs in different Cnode.
+ *
+ * @param vni VNI
+ * @param id device ID
+ * @param hostIp host IP of the VM
+ * @param vmIp fixed IP of the VM
+ * @param vmMac MAC address of the VM
+ */
+ private void setVxLanFlowRule(String vni, DeviceId id, Ip4Address hostIp,
+ Ip4Address vmIp, MacAddress vmMac) {
+ TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+
+ sBuilder.matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(vmIp.toIpPrefix());
+ tBuilder.setTunnelId(Long.parseLong(vni))
+ .extension(buildNiciraExtenstion(id, hostIp), id)
+ .setOutput(getTunnelPort(id));
+
+ ForwardingObjective fo = DefaultForwardingObjective.builder()
+ .withSelector(sBuilder.build())
+ .withTreatment(tBuilder.build())
+ .withPriority(SWITCHING_RULE_PRIORITY)
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .fromApp(appId)
+ .add();
+
+ flowObjectiveService.forward(id, fo);
+ }
+
+ private ExtensionTreatment buildNiciraExtenstion(DeviceId id, Ip4Address hostIp) {
+ Driver driver = driverService.getDriver(id);
+ DriverHandler driverHandler = new DefaultDriverHandler(new DefaultDriverData(driver, id));
+ ExtensionTreatmentResolver resolver = driverHandler.behaviour(ExtensionTreatmentResolver.class);
+
+ ExtensionTreatment extensionInstruction =
+ resolver.getExtensionInstruction(
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type());
+
+ try {
+ extensionInstruction.setPropertyValue("tunnelDst", hostIp);
+ } catch (ExtensionPropertyException e) {
+ log.error("Error setting Nicira extension setting {}", e);
+ }
+
+ return extensionInstruction;
+ }
+
+ private PortNumber getTunnelPort(DeviceId id) {
+ Port port = deviceService.getPorts(id).stream()
+ .filter(p -> p.annotations().value("portName").equals("vxlan"))
+ .findAny().orElse(null);
+
+ if (port == null) {
+ log.error("No TunnelPort was created.");
+ return null;
+ }
+ return port.number();
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/package-info.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/package-info.java
new file mode 100644
index 00000000..cd50f912
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * OpenStack switch interface.
+ */
+package org.onosproject.openstackswitching;
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
index fc1509d4..0a0b5dce 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
@@ -43,6 +43,9 @@ public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> {
public OpenstackNetwork decode(ObjectNode json, CodecContext context) {
JsonNode networkInfo = json.get(NETWORK);
+ if (networkInfo == null) {
+ networkInfo = json;
+ }
String name = networkInfo.path(NAME).asText();
String tenantId = networkInfo.path(TENANT_ID).asText();
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java
index f4c401fb..bf04cc4d 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java
@@ -15,48 +15,52 @@
*/
package org.onosproject.openstackswitching.web;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.openstackswitching.OpenstackNetwork;
-import org.onosproject.openstackswitching.OpenstackSwitchingService;
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
+/**
+ * Handles REST API call of Neutron ML2 plugin.
+ */
@Path("networks")
public class OpenstackNetworkWebResource extends AbstractWebResource {
protected static final Logger log = LoggerFactory
.getLogger(OpenstackNetworkWebResource.class);
- private static final OpenstackNetworkCodec NETWORK_CODEC = new OpenstackNetworkCodec();
-
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createNetwork(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode networkNode = (ObjectNode) mapper.readTree(input);
+ log.debug("REST API networks is called {}", input.toString());
+ return Response.status(Response.Status.OK).build();
+ }
- OpenstackNetwork openstackNetwork = NETWORK_CODEC.decode(networkNode, this);
+ @PUT
+ @Path("{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response updateNetwork(InputStream input) {
+ log.debug("REST API networks is called {}", input.toString());
+ return Response.status(Response.Status.OK).build();
+ }
- OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
- switchingService.createNetwork(openstackNetwork);
- return Response.status(Response.Status.OK).build();
- } catch (Exception e) {
- log.error("Creates VirtualPort failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ @DELETE
+ @Path("{id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response deleteNetwork(InputStream input) {
+ log.debug("REST API networks is called {}", input.toString());
+ return Response.status(Response.Status.OK).build();
}
}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
index 765b6901..63e6d2ea 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
@@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory;
import java.util.HashMap;
/**
- * It encodes and decodes the OpenstackPort.
+ * Encodes and decodes the OpenstackPort.
*/
public class OpenstackPortCodec extends JsonCodec<OpenstackPort> {
@@ -58,6 +58,9 @@ public class OpenstackPortCodec extends JsonCodec<OpenstackPort> {
HashMap<String, Ip4Address> fixedIpMap = new HashMap<>();
JsonNode portInfo = json.get(PORT);
+ if (portInfo == null) {
+ portInfo = json;
+ }
String status = portInfo.path(STATUS).asText();
String name = portInfo.path(NAME).asText();
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
index 67a9cebb..faffa732 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
@@ -33,6 +33,9 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.InputStream;
+/**
+ * Handles Rest API call from Neutron ML2 plugin.
+ */
@Path("ports")
public class OpenstackPortWebResource extends AbstractWebResource {
@@ -50,13 +53,15 @@ public class OpenstackPortWebResource extends AbstractWebResource {
ObjectNode portNode = (ObjectNode) mapper.readTree(input);
OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
-
- OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
+ OpenstackSwitchingService switchingService =
+ getService(OpenstackSwitchingService.class);
switchingService.createPorts(openstackPort);
- log.info("REST API ports is called with {}", portNode.toString());
+
+ log.debug("REST API ports is called with {}", portNode.toString());
return Response.status(Response.Status.OK).build();
+
} catch (Exception e) {
- log.error("Creates VirtualPort failed because of exception {}",
+ log.error("Creates Port failed because of exception {}",
e.toString());
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
.build();
@@ -64,23 +69,12 @@ public class OpenstackPortWebResource extends AbstractWebResource {
}
@DELETE
+ @Path("{id}")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response deletesPorts(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode portNode = (ObjectNode) mapper.readTree(input);
-
- OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
- switchingService.deletePorts();
- log.info("REST API ports is called with {}", portNode.toString());
- return Response.status(Response.Status.OK).build();
- } catch (Exception e) {
- log.error("Delete VirtualPort failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ log.debug("REST API ports is called with {}", input.toString());
+ return Response.status(Response.Status.OK).build();
}
@PUT
@@ -88,19 +82,7 @@ public class OpenstackPortWebResource extends AbstractWebResource {
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response updatePorts(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode portNode = (ObjectNode) mapper.readTree(input);
-
- OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
- switchingService.updatePorts();
- log.info("REST API ports is called with {}", portNode.toString());
- return Response.status(Response.Status.OK).build();
- } catch (Exception e) {
- log.error("Update VirtualPort failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ log.info("REST API ports is called with {}", input.toString());
+ return Response.status(Response.Status.OK).build();
}
}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java
index a643057a..2a7af82a 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetCodec.java
@@ -18,17 +18,21 @@ package org.onosproject.openstackswitching.web;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+import org.onlab.packet.Ip4Address;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.openstackswitching.OpenstackSubnet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.List;
+
/**
- * It encodes and decodes the OpenstackSubnet.
+ * Encodes and decodes the OpenstackSubnet.
*/
-
public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
private static Logger log = LoggerFactory
.getLogger(OpenstackSubnetCodec.class);
@@ -47,12 +51,19 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
@Override
public OpenstackSubnet decode(ObjectNode json, CodecContext context) {
JsonNode subnetInfo = json.get(SUBNET);
+ if (subnetInfo == null) {
+ subnetInfo = json;
+ }
String name = subnetInfo.path(NAME).asText();
boolean enableDhcp = subnetInfo.path(ENABLE_DHCP).asBoolean();
String networkId = subnetInfo.path(NETWORK_ID).asText();
String tenantId = subnetInfo.path(TENANT_ID).asText();
- String dnsNameservsers = subnetInfo.path(DNS_NAMESERVERS).asText();
+ ArrayNode dnsNameservsers = (ArrayNode) subnetInfo.path(DNS_NAMESERVERS);
+ List<Ip4Address> dnsList = Lists.newArrayList();
+ if (dnsNameservsers != null && !dnsNameservsers.isMissingNode()) {
+ dnsNameservsers.forEach(dns -> dnsList.add(Ip4Address.valueOf(dns.asText())));
+ }
String gatewayIp = subnetInfo.path(GATEWAY_IP).asText();
String cidr = subnetInfo.path(CIDR).asText();
String id = subnetInfo.path(ID).asText();
@@ -62,7 +73,7 @@ public class OpenstackSubnetCodec extends JsonCodec<OpenstackSubnet> {
.setEnableDhcp(enableDhcp)
.setNetworkId(networkId)
.setTenantId(tenantId)
- .setDnsNameservers(dnsNameservsers)
+ .setDnsNameservers(dnsList)
.setGatewayIp(gatewayIp)
.setCidr(cidr)
.setId(id)
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java
index af1ae9dd..43205eac 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/OpenstackSubnetWebResource.java
@@ -15,18 +15,19 @@
*/
package org.onosproject.openstackswitching.web;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.onosproject.openstackswitching.OpenstackSubnet;
-import org.onosproject.openstackswitching.OpenstackSwitchingService;
+/**
+ * Handles Rest API call from Neutron ML2 plugin.
+ */
import org.onosproject.rest.AbstractWebResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -37,28 +38,32 @@ public class OpenstackSubnetWebResource extends AbstractWebResource {
protected static final Logger log = LoggerFactory
.getLogger(OpenstackSubnetWebResource.class);
- private static final OpenstackSubnetCodec SUBNET_CODEC = new OpenstackSubnetCodec();
-
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response createSubnet(InputStream input) {
- try {
- ObjectMapper mapper = new ObjectMapper();
- ObjectNode subnetNode = (ObjectNode) mapper.readTree(input);
+ return Response.status(Response.Status.OK).build();
+ }
+
+
+ @PUT
+ @Path("{subnetUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateSubnet(@PathParam("id") String id,
+ final InputStream input) {
+ return Response.status(Response.Status.OK).build();
- OpenstackSubnet openstackSubnet = SUBNET_CODEC.decode(subnetNode, this);
+ }
- OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
- switchingService.createSubnet(openstackSubnet);
- log.info("REST API subnets is called with {}", subnetNode.toString());
- return Response.status(Response.Status.OK).build();
- } catch (Exception e) {
- log.error("Creates VirtualSubnet failed because of exception {}",
- e.toString());
- return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
- .build();
- }
+ @DELETE
+ @Path("{subnetUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response deleteSubnet(@PathParam("id") String id,
+ final InputStream input) {
+ return Response.status(Response.Status.OK).build();
}
+
}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/package-info.java
index 91e19c62..91e19c62 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/java/org/onosproject/openstackswitching/web/package-info.java
diff --git a/framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/openstackswitching/app/src/main/webapp/WEB-INF/web.xml
index 4f50ef72..4f50ef72 100644
--- a/framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
+++ b/framework/src/onos/apps/openstackswitching/app/src/main/webapp/WEB-INF/web.xml
diff --git a/framework/src/onos/apps/openstackswitching/network-cfg.json b/framework/src/onos/apps/openstackswitching/network-cfg.json
new file mode 100644
index 00000000..62c3a515
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/network-cfg.json
@@ -0,0 +1,55 @@
+{
+ "apps" : {
+ "org.onosproject.openstackswitching" : {
+ "openstackswitching" : {
+ "do_not_push_flows" : "false",
+ "neutron_server" : "http://127.0.0.1:9696/v2.0/",
+ "keystone_server" : "http://127.0.0.1:5000/v2.0/",
+ "user_name" : "admin",
+ "password" : "nova"
+ }
+ },
+ "org.onosproject.dhcp" : {
+ "dhcp" : {
+ "ip": "10.0.0.1",
+ "mac": "1a:2b:3c:4e:5e:6f",
+ "subnet": "255.0.0.0",
+ "broadcast": "10.255.255.255",
+ "router": "10.0.0.1",
+ "domain": "10.0.0.1",
+ "ttl": "63",
+ "lease": "300",
+ "renew": "150",
+ "rebind": "200",
+ "delay": "3",
+ "timeout": "150",
+ "startip": "10.0.0.110",
+ "endip": "10.0.0.130"
+ }
+ },
+ "org.onosproject.cordvtn" : {
+ "cordvtn" : {
+ "ovsdbNodes" : [
+ {
+ "host" : "compute-01",
+ "ip" : "128.199.162.106",
+ "port" : "6640",
+ "bridgeId" : "of:0000000000000001"
+ },
+ {
+ "host" : "compute-02",
+ "ip" : "103.253.145.133",
+ "port" : "6640",
+ "bridgeId" : "of:0000000000000002"
+ },
+ {
+ "host" : "network",
+ "ip" : "128.199.125.11",
+ "port" : "6640",
+ "bridgeId" : "of:0000000000000003"
+ }
+ ]
+ }
+ }
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/pom.xml b/framework/src/onos/apps/openstackswitching/pom.xml
index 52129b6f..9dbdcf5f 100644
--- a/framework/src/onos/apps/openstackswitching/pom.xml
+++ b/framework/src/onos/apps/openstackswitching/pom.xml
@@ -26,101 +26,18 @@
<relativePath>../pom.xml</relativePath>
</parent>
- <artifactId>onos-app-openstackswitching</artifactId>
- <packaging>bundle</packaging>
+ <artifactId>onos-openstackswitching</artifactId>
+ <packaging>pom</packaging>
- <description>SONA Openstack Switching applications</description>
- <properties>
- <onos.version>1.4.0-SNAPSHOT</onos.version>
- <onos.app.name>org.onosproject.openstackswitching</onos.app.name>
- <web.context>/onos/openstackswitching</web.context>
- <api.version>1.0.0</api.version>
- <api.title>ONOS OpenStack Switching REST API</api.title>
- <api.description>
- APIs for receiving Neutron information.
- </api.description>
- <api.package>org.onosproject.openstackswitching.web</api.package>
- <onos.app.origin>SKT, Inc.</onos.app.origin>
- </properties>
+ <description>SONA Openstack Switching application</description>
+ <modules>
+ <module>api</module>
+ <module>app</module>
+ </modules>
<dependencies>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-rest</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onlab-rest</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>javax.ws.rs</groupId>
- <artifactId>jsr311-api</artifactId>
- <version>1.1.1</version>
- </dependency>
- <dependency>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-servlet</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-app-dhcp-api</artifactId>
- <version>${project.version}</version>
- </dependency>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <_wab>src/main/webapp/</_wab>
- <Bundle-SymbolicName>
- ${project.groupId}.${project.artifactId}
- </Bundle-SymbolicName>
- <Import-Package>
- org.slf4j,
- org.osgi.framework,
- javax.ws.rs,
- javax.ws.rs.core,
- com.sun.jersey.api.core,
- com.sun.jersey.spi.container.servlet,
- com.sun.jersey.server.impl.container.servlet,
- com.fasterxml.jackson.databind,
- com.fasterxml.jackson.databind.node,
- com.fasterxml.jackson.core,
- org.apache.karaf.shell.commands,
- com.google.common.*,
- org.onlab.packet.*,
- org.onosproject.*
- </Import-Package>
- <Web-ContextPath>${web.context}</Web-ContextPath>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
</project>
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
deleted file mode 100644
index 4be8a50d..00000000
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- * Copyright 2015 Open Networking Laboratory
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.onosproject.openstackswitching;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Deactivate;
-import org.apache.felix.scr.annotations.Reference;
-import org.apache.felix.scr.annotations.ReferenceCardinality;
-import org.apache.felix.scr.annotations.Service;
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.MacAddress;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
-import org.onosproject.dhcp.DhcpService;
-import org.onosproject.net.Device;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.device.DeviceEvent;
-import org.onosproject.net.device.DeviceListener;
-import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.packet.InboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
-import org.onosproject.net.packet.PacketService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-
-@SuppressWarnings("ALL")
-@Service
-@Component(immediate = true)
-/**
- * It populates forwarding rules for VMs created by Openstack.
- */
-public class OpenstackSwitchingManager implements OpenstackSwitchingService {
-
- private static Logger log = LoggerFactory
- .getLogger(OpenstackSwitchingManager.class);
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected CoreService coreService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected PacketService packetService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DeviceService deviceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected FlowObjectiveService flowObjectiveService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected DhcpService dhcpService;
-
- public static final int DHCP_PORT = 67;
-
- private ApplicationId appId;
- private OpenstackArpHandler arpHandler;
-
- private OpenstackSwitchingRulePopulator rulePopulator;
- private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);
-
- private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
- private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
-
- // Map <port_id, OpenstackPort>
- private Map<String, OpenstackPort> openstackPortMap;
- // Map <network_id, OpenstackNetwork>
- private Map<String, OpenstackNetwork> openstackNetworkMap;
- // Map <subnet_id, OpenstackSubner>
- private Map<String, OpenstackSubnet> openstackSubnetMap;
- // Map <vni, List <Entry <portName, host ip>>
- private Map<String, List<PortInfo>> vniPortMap;
- private Map<Ip4Address, Port> tunnelPortMap;
-
-
- @Activate
- protected void activate() {
- appId = coreService
- .registerApplication("org.onosproject.openstackswitching");
- rulePopulator = new OpenstackSwitchingRulePopulator(appId, flowObjectiveService);
- packetService.addProcessor(internalPacketProcessor, PacketProcessor.director(1));
- deviceService.addListener(internalDeviceListener);
-
- openstackPortMap = Maps.newHashMap();
- openstackNetworkMap = Maps.newHashMap();
- openstackSubnetMap = Maps.newHashMap();
-
- vniPortMap = Maps.newHashMap();
- tunnelPortMap = Maps.newHashMap();
- arpHandler = new OpenstackArpHandler(openstackPortMap, packetService);
- log.info("Started");
- }
-
- @Deactivate
- protected void deactivate() {
- packetService.removeProcessor(internalPacketProcessor);
- deviceService.removeListener(internalDeviceListener);
-
- deviceEventExcutorService.shutdown();
-
- log.info("Stopped");
- }
-
- @Override
- public void createPorts(OpenstackPort openstackPort) {
- //For DHCP purpose
- //registerDhcpInfo(openstackPort);
- openstackPortMap.put(openstackPort.id(), openstackPort);
- }
-
- /*
- private void registerDhcpInfo(OpenstackPort openstackPort) {
- Ip4Address ip4Address;
- Ip4Address subnetMask;
- Ip4Address dhcpServer;
- Ip4Address gatewayIPAddress;
- Ip4Address domainServer;
- OpenstackSubnet openstackSubnet;
-
- ip4Address = (Ip4Address) openstackPort.fixedIps().values().toArray()[0];
-
- openstackSubnet = openstackSubnetMap.values().stream()
- .filter(n -> n.networkId().equals(openstackPort.networkId()))
- .findFirst().get();
-
- int prefix;
- String[] parts = openstackSubnet.cidr().split("/");
- prefix = Integer.parseInt(parts[1]);
- int mask = 0xffffffff << (32 - prefix);
- byte[] bytes = new byte[]{(byte) (mask >>> 24),
- (byte) (mask >> 16 & 0xff), (byte) (mask >> 8 & 0xff), (byte) (mask & 0xff)};
-
- subnetMask = Ip4Address.valueOf(bytes);
- gatewayIPAddress = Ip4Address.valueOf(openstackSubnet.gatewayIp());
- dhcpServer = gatewayIPAddress;
- domainServer = Ip4Address.valueOf("8.8.8.8");
-
- dhcpService.setStaticMappingOpenstack(openstackPort.macAddress(),
- ip4Address, subnetMask, dhcpServer, gatewayIPAddress, domainServer);
- }
- */
-
- @Override
- public void deletePorts() {
-
- }
-
- @Override
- public void updatePorts() {
-
- }
-
- @Override
- public void createNetwork(OpenstackNetwork openstackNetwork) {
- openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
- }
-
-
- @Override
- public void createSubnet(OpenstackSubnet openstackSubnet) {
- openstackSubnetMap.put(openstackSubnet.id(), openstackSubnet);
- log.debug("Added Subnet Info {}", openstackNetworkMap.get(openstackSubnet.id()));
- }
-
- private void processDeviceAdded(Device device) {
- log.debug("device {} is added", device.id());
- rulePopulator.populateDefaultRules(device.id());
- }
-
- private void processPortAdded(Device device, Port port) {
- // TODO: Simplify the data structure to store the network info
- // TODO: Make it stateless
- // TODO: All the logics need to be processed inside of the rulePopulator class
- synchronized (vniPortMap) {
- log.debug("port {} is updated", port.toString());
-
- updatePortMaps(device, port);
- if (!port.annotations().value("portName").equals("vxlan")) {
- populateFlowRulesForTrafficToSameCnode(device, port);
- populateFlowRulesForTrafficToDifferentCnode(device, port);
- }
- }
- }
-
- private void processPortRemoved(Device device, Port port) {
- log.debug("port {} is removed", port.toString());
- // TODO: need to update the vniPortMap
- }
-
- /**
- * Populates the flow rules for traffic to VMs in different Cnode using
- * Nicira extention.
- *
- * @param device device to put rules
- * @param port port information of the VM
- */
- private void populateFlowRulesForTrafficToDifferentCnode(Device device, Port port) {
- String portName = port.annotations().value("portName");
- String channelId = device.annotations().value("channelId");
- Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
- Ip4Address fixedIp = getFixedIpAddressForPort(portName);
- // TODO: Avoid duplicate flow rule set up for VMs in other Cnode
- // (possibly avoided by flowrule subsystem?)
- if (tunnelPortMap.get(hostIpAddress) == null) {
- log.debug("There is no tunnel port information");
- return;
- }
- String vni = getVniForPort(portName);
- MacAddress vmMac = getVmMacAddressForPort(portName);
- if (!vniPortMap.isEmpty() && vniPortMap.get(vni) != null) {
- for (PortInfo portInfo : vniPortMap.get(vni)) {
- if (!portInfo.portName.equals(portName) &&
- !portInfo.hostIp.equals(hostIpAddress)) {
- MacAddress vmMacx = getVmMacAddressForPort(portInfo.portName);
- rulePopulator.populateForwardingRuleForOtherCnode(vni,
- device.id(), portInfo.hostIp, portInfo.fixedIp, vmMacx,
- tunnelPortMap.get(hostIpAddress).number(),
- portInfo.deviceId, hostIpAddress, fixedIp, vmMac,
- tunnelPortMap.get(portInfo.hostIp).number());
- }
- }
- }
- }
-
- /**
- * Populates the flow rules for traffic to VMs in the same Cnode as the sender.
- *
- * @param device device to put the rules
- * @param port port info of the VM
- */
- private void populateFlowRulesForTrafficToSameCnode(Device device, Port port) {
- Ip4Prefix cidr = getCidrForPort(port.annotations().value("portName"));
- Ip4Address vmIp = getFixedIpAddressForPort(port.annotations().value("portName"));
- if (vmIp != null) {
- rulePopulator.populateForwardingRule(vmIp, device.id(), port, cidr);
- }
- }
-
- /**
- * Updates the port maps using the port information.
- *
- * @param device device info
- * @param port port of the VM
- */
- private void updatePortMaps(Device device, Port port) {
- String portName = port.annotations().value("portName");
- String channelId = device.annotations().value("channelId");
- Ip4Address hostIpAddress = Ip4Address.valueOf(channelId.split(":")[0]);
- if (portName.startsWith("vxlan")) {
- tunnelPortMap.put(hostIpAddress, port);
- } else {
- String vni = getVniForPort(portName);
- Ip4Address fixedIp = getFixedIpAddressForPort(portName);
- if (vniPortMap.get(vni) == null) {
- vniPortMap.put(vni, Lists.newArrayList());
- }
- vniPortMap.get(vni).add(new PortInfo(device.id(), portName, fixedIp, hostIpAddress));
- }
- }
-
- /**
- * Returns CIDR information from the subnet map for the port.
- *
- * @param portName port name of the port of the VM
- * @return CIDR of the VNI of the VM
- */
- private Ip4Prefix getCidrForPort(String portName) {
- String networkId = null;
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortMap.values().stream()
- .filter(p -> p.id().startsWith(uuid))
- .findFirst().get();
- if (port == null) {
- log.debug("No port information for port {}", portName);
- return null;
- }
-
- OpenstackSubnet subnet = openstackSubnetMap.values().stream()
- .filter(s -> s.networkId().equals(port.networkId()))
- .findFirst().get();
- if (subnet == null) {
- log.debug("No subnet information for network {}", subnet.id());
- return null;
- }
-
- return Ip4Prefix.valueOf(subnet.cidr());
- }
-
- /**
- * Returns the VNI of the VM of the port.
- *
- * @param portName VM port
- * @return VNI
- */
- private String getVniForPort(String portName) {
- String networkId = null;
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortMap.values().stream()
- .filter(p -> p.id().startsWith(uuid))
- .findFirst().get();
- if (port == null) {
- log.debug("No port information for port {}", portName);
- return null;
- }
- OpenstackNetwork network = openstackNetworkMap.values().stream()
- .filter(n -> n.id().equals(port.networkId()))
- .findFirst().get();
- if (network == null) {
- log.debug("No VNI information for network {}", network.id());
- return null;
- }
-
- return network.segmentId();
- }
-
- /**
- * Returns the Fixed IP address of the VM.
- *
- * @param portName VM port info
- * @return IP address of the VM
- */
- private Ip4Address getFixedIpAddressForPort(String portName) {
-
- // FIXME - For now we use the information stored from neutron Rest API call.
- // TODO - Later, the information needs to be extracted from Neutron on-demand.
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortMap.values().stream()
- .filter(p -> p.id().startsWith(uuid))
- .findFirst().get();
-
- if (port == null) {
- log.error("There is no port information for port name {}", portName);
- return null;
- }
-
- if (port.fixedIps().isEmpty()) {
- log.error("There is no fixed IP info in the port information");
- return null;
- }
-
- return (Ip4Address) port.fixedIps().values().toArray()[0];
- }
-
- /**
- * Returns the MAC address of the VM of the port.
- *
- * @param portName VM port
- * @return MAC address of the VM
- */
- private MacAddress getVmMacAddressForPort(String portName) {
-
- String uuid = portName.substring(3);
- OpenstackPort port = openstackPortMap.values().stream()
- .filter(p -> p.id().startsWith(uuid))
- .findFirst().get();
-
- if (port == null) {
- log.error("There is no mac information for port name {}", portName);
- return null;
- }
-
- return port.macAddress();
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
-
- @Override
- public void process(PacketContext context) {
-
- if (context.isHandled()) {
- return;
- }
-
- InboundPacket pkt = context.inPacket();
- Ethernet ethernet = pkt.parsed();
-
- if (ethernet.getEtherType() == Ethernet.TYPE_ARP) {
- arpHandler.processPacketIn(pkt);
- }
- }
- }
-
- private class InternalDeviceListener implements DeviceListener {
-
- @Override
- public void event(DeviceEvent event) {
- deviceEventExcutorService.execute(new InternalEventHandler(event));
- }
- }
-
- private class InternalEventHandler implements Runnable {
-
- volatile DeviceEvent deviceEvent;
-
- InternalEventHandler(DeviceEvent deviceEvent) {
- this.deviceEvent = deviceEvent;
- }
-
- @Override
- public void run() {
- switch (deviceEvent.type()) {
- case DEVICE_ADDED:
- processDeviceAdded((Device) deviceEvent.subject());
- break;
- case DEVICE_UPDATED:
- Port port = (Port) deviceEvent.subject();
- if (port.isEnabled()) {
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
- }
- break;
- case DEVICE_AVAILABILITY_CHANGED:
- Device device = (Device) deviceEvent.subject();
- if (deviceService.isAvailable(device.id())) {
- processDeviceAdded(device);
- }
- break;
- case PORT_ADDED:
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
- break;
- case PORT_UPDATED:
- processPortAdded((Device) deviceEvent.subject(), deviceEvent.port());
- break;
- case PORT_REMOVED:
- processPortRemoved((Device) deviceEvent.subject(), deviceEvent.port());
- break;
- default:
- break;
- }
- }
- }
-
- private final class PortInfo {
- DeviceId deviceId;
- String portName;
- Ip4Address fixedIp;
- Ip4Address hostIp;
-
- private PortInfo(DeviceId deviceId, String portName, Ip4Address fixedIp,
- Ip4Address hostIp) {
- this.deviceId = deviceId;
- this.portName = portName;
- this.fixedIp = fixedIp;
- this.hostIp = hostIp;
- }
- }
-
-} \ No newline at end of file
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
deleted file mode 100644
index f6e98060..00000000
--- a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
-* Copyright 2015 Open Networking Laboratory
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-package org.onosproject.openstackswitching;
-
-import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
-import org.onlab.packet.MacAddress;
-import org.onlab.packet.TpPort;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
-import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
-import org.onosproject.net.flowobjective.DefaultForwardingObjective;
-import org.onosproject.net.flowobjective.FlowObjectiveService;
-import org.onosproject.net.flowobjective.ForwardingObjective;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * It populates switching flow rules.
- *
- */
-public class OpenstackSwitchingRulePopulator {
-
- private static Logger log = LoggerFactory
- .getLogger(OpenstackSwitchingRulePopulator.class);
-
- private FlowObjectiveService flowObjectiveService;
- private ApplicationId appId;
-
- /**
- * Creates OpenstackSwitchingRulPopulator.
- *
- * @param appId application id
- * @param flowObjectiveService FlowObjectiveService reference
- */
- public OpenstackSwitchingRulePopulator(ApplicationId appId,
- FlowObjectiveService flowObjectiveService) {
- this.flowObjectiveService = flowObjectiveService;
- this.appId = appId;
- }
-
- /**
- * Populates flows rules for forwarding packets to and from VMs.
- *
- * @param ip v4 IP Address
- * @param id device ID
- * @param port port
- * @param cidr v4 IP prefix
- * @return true if it succeeds to populate rules, false otherwise.
- */
- public boolean populateForwardingRule(Ip4Address ip, DeviceId id, Port port, Ip4Prefix cidr) {
-
-
- setFlowRuleForVMsInSameCnode(ip, id, port, cidr);
-
- return true;
- }
-
- /**
- * Populates the common flows rules for all VMs.
- *
- * - Send ARP packets to the controller
- * - Send DHCP packets to the controller
- *
- * @param id Device ID to populates rules to
- */
- public void populateDefaultRules(DeviceId id) {
-
- setFlowRuleForArp(id);
-
- log.warn("Default rule has been set");
- }
-
- /**
- * Populates the forwarding rules for VMs with the same VNI but in other Code.
- *
- * @param vni VNI for the networks
- * @param id device ID to populates the flow rules
- * @param hostIp host IP address of the VM
- * @param vmIp fixed IP address for the VM
- * @param vmMac MAC address for the VM
- * @param tunnelPort tunnel port number for the VM
- * @param idx device ID for OVS of the other VM
- * @param hostIpx host IP address of the other VM
- * @param vmIpx fixed IP address of the other VM
- * @param vmMacx MAC address for the other VM
- * @param tunnelPortx x tunnel port number for other VM
- */
- public void populateForwardingRuleForOtherCnode(String vni, DeviceId id, Ip4Address hostIp,
- Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort,
- DeviceId idx, Ip4Address hostIpx,
- Ip4Address vmIpx, MacAddress vmMacx, PortNumber tunnelPortx) {
- setVxLanFlowRule(vni, id, hostIp, vmIp, vmMac, tunnelPort);
- setVxLanFlowRule(vni, idx, hostIpx, vmIpx, vmMacx, tunnelPortx);
- }
-
- /**
- * Populates the flow rules for DHCP packets from VMs.
- *
- * @param id device ID to set the rules
- */
- private void setFlowRuleForDhcp(DeviceId id) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPProtocol(IPv4.PROTOCOL_UDP)
- .matchUdpDst(TpPort.tpPort(OpenstackSwitchingManager.DHCP_PORT));
- tBuilder.setOutput(PortNumber.CONTROLLER);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(5000)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(id, fo);
- }
-
- /**
- * Populates the flow rules for ARP packets from VMs.
- *
- * @param id device ID to put rules.
- */
- private void setFlowRuleForArp(DeviceId id) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_ARP);
- tBuilder.setOutput(PortNumber.CONTROLLER);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(5000)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(id, fo);
- }
-
- /**
- * Sets the flow rules for traffic between VMs in the same Cnode.
- *
- * @param ip4Address VM IP address
- * @param id device ID to put rules
- * @param port VM port
- * @param cidr subnet info of the VMs
- */
- private void setFlowRuleForVMsInSameCnode(Ip4Address ip4Address, DeviceId id,
- Port port, Ip4Prefix cidr) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(ip4Address.toIpPrefix())
- .matchIPSrc(cidr);
- tBuilder.setOutput(port.number());
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(5000)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(id, fo);
- }
-
- /**
- * Sets the flow rules between traffic from VMs in different Cnode.
- *
- * @param vni VNI
- * @param id device ID
- * @param hostIp host IP of the VM
- * @param vmIp fixed IP of the VM
- * @param vmMac MAC address of the VM
- * @param tunnelPort tunnel port to forward traffic to
- */
- private void setVxLanFlowRule(String vni, DeviceId id, Ip4Address hostIp,
- Ip4Address vmIp, MacAddress vmMac, PortNumber tunnelPort) {
- TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
-
- sBuilder.matchEthType(Ethernet.TYPE_IPV4)
- .matchIPDst(vmIp.toIpPrefix());
- tBuilder.setTunnelId(Long.parseLong(vni))
- //.setTunnelDst() <- for Nicira ext
- //.setEthDst(vmMac)
- .setOutput(tunnelPort);
-
- ForwardingObjective fo = DefaultForwardingObjective.builder()
- .withSelector(sBuilder.build())
- .withTreatment(tBuilder.build())
- .withPriority(5000)
- .withFlag(ForwardingObjective.Flag.VERSATILE)
- .fromApp(appId)
- .add();
-
- flowObjectiveService.forward(id, fo);
- }
-}
diff --git a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java
index e33d5aa1..70ade23a 100644
--- a/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java
+++ b/framework/src/onos/apps/pim/src/main/java/org/onosproject/pim/impl/PIMInterfaces.java
@@ -117,7 +117,7 @@ public final class PIMInterfaces {
* @param cp The connectPoint representing the PIMInterface to be removed.
*/
private void removeInterface(ConnectPoint cp) {
- removeInterface(cp);
+ PIMInterfaces.this.removeInterface(cp);
}
@Override
diff --git a/framework/src/onos/apps/routing-api/src/main/java/org/onosproject/routing/RouteEntry.java b/framework/src/onos/apps/routing-api/src/main/java/org/onosproject/routing/RouteEntry.java
index 2b0ef989..8204a109 100644
--- a/framework/src/onos/apps/routing-api/src/main/java/org/onosproject/routing/RouteEntry.java
+++ b/framework/src/onos/apps/routing-api/src/main/java/org/onosproject/routing/RouteEntry.java
@@ -89,14 +89,17 @@ public class RouteEntry {
/**
* Creates the binary string representation of an IP prefix.
* The prefix can be either IPv4 or IPv6.
- * The string length is equal to the prefix length.
+ * The string length is equal to the prefix length + 1.
+ *
+ * For each string, we put a extra "0" in the front. The purpose of
+ * doing this is to store the default route inside InvertedRadixTree.
*
* @param ipPrefix the IP prefix to use
* @return the binary string representation
*/
public static String createBinaryString(IpPrefix ipPrefix) {
if (ipPrefix.prefixLength() == 0) {
- return "";
+ return "0";
}
byte[] octets = ipPrefix.address().toOctets();
@@ -109,7 +112,8 @@ public class RouteEntry {
boolean isSet = ((value & mask) != 0);
result.append(isSet ? "1" : "0");
}
- return result.toString();
+
+ return "0" + result.toString();
}
@Override
diff --git a/framework/src/onos/apps/routing-api/src/test/java/org/onosproject/routing/RouteEntryTest.java b/framework/src/onos/apps/routing-api/src/test/java/org/onosproject/routing/RouteEntryTest.java
index b89eb2d1..981d6a09 100644
--- a/framework/src/onos/apps/routing-api/src/test/java/org/onosproject/routing/RouteEntryTest.java
+++ b/framework/src/onos/apps/routing-api/src/test/java/org/onosproject/routing/RouteEntryTest.java
@@ -121,52 +121,52 @@ public class RouteEntryTest {
Ip4Prefix prefix;
prefix = Ip4Prefix.valueOf("0.0.0.0/0");
- assertThat(RouteEntry.createBinaryString(prefix), is(""));
+ assertThat(RouteEntry.createBinaryString(prefix), is("0"));
prefix = Ip4Prefix.valueOf("192.168.166.0/22");
assertThat(RouteEntry.createBinaryString(prefix),
- is("1100000010101000101001"));
+ is("0" + "1100000010101000101001"));
prefix = Ip4Prefix.valueOf("192.168.166.0/23");
assertThat(RouteEntry.createBinaryString(prefix),
- is("11000000101010001010011"));
+ is("0" + "11000000101010001010011"));
prefix = Ip4Prefix.valueOf("192.168.166.0/24");
assertThat(RouteEntry.createBinaryString(prefix),
- is("110000001010100010100110"));
+ is("0" + "110000001010100010100110"));
prefix = Ip4Prefix.valueOf("130.162.10.1/25");
assertThat(RouteEntry.createBinaryString(prefix),
- is("1000001010100010000010100"));
+ is("0" + "1000001010100010000010100"));
prefix = Ip4Prefix.valueOf("255.255.255.255/32");
assertThat(RouteEntry.createBinaryString(prefix),
- is("11111111111111111111111111111111"));
+ is("0" + "11111111111111111111111111111111"));
Ip6Prefix prefix6;
Pattern pattern;
Matcher matcher;
prefix6 = Ip6Prefix.valueOf("::/0");
- assertThat(RouteEntry.createBinaryString(prefix6), is(""));
+ assertThat(RouteEntry.createBinaryString(prefix6), is("0"));
prefix6 = Ip6Prefix.valueOf("2000::1000/112");
- pattern = Pattern.compile("00100{108}");
+ pattern = Pattern.compile("0" + "00100{108}");
matcher = pattern.matcher(RouteEntry.createBinaryString(prefix6));
assertTrue(matcher.matches());
prefix6 = Ip6Prefix.valueOf("2000::1000/116");
- pattern = Pattern.compile("00100{108}0001");
+ pattern = Pattern.compile("0" + "00100{108}0001");
matcher = pattern.matcher(RouteEntry.createBinaryString(prefix6));
assertTrue(matcher.matches());
prefix6 = Ip6Prefix.valueOf("2000::2000/116");
- pattern = Pattern.compile("00100{108}0010");
+ pattern = Pattern.compile("0" + "00100{108}0010");
matcher = pattern.matcher(RouteEntry.createBinaryString(prefix6));
assertTrue(matcher.matches());
prefix6 = Ip6Prefix.valueOf("2000::1234/128");
- pattern = Pattern.compile("00100{108}0001001000110100");
+ pattern = Pattern.compile("0" + "00100{108}0001001000110100");
matcher = pattern.matcher(RouteEntry.createBinaryString(prefix6));
assertTrue(matcher.matches());
}
diff --git a/framework/src/onos/apps/sdnip/features.xml b/framework/src/onos/apps/sdnip/features.xml
index 21ae89d3..5bd0dbc4 100644
--- a/framework/src/onos/apps/sdnip/features.xml
+++ b/framework/src/onos/apps/sdnip/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="onos-app-sdnip" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIpFib.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIpFib.java
index c0001bdc..9113e013 100644
--- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIpFib.java
+++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/SdnIpFib.java
@@ -83,7 +83,8 @@ public class SdnIpFib implements FibListener {
@Override
- public void update(Collection<FibUpdate> updates, Collection<FibUpdate> withdraws) {
+ public void update(Collection<FibUpdate> updates,
+ Collection<FibUpdate> withdraws) {
int submitCount = 0, withdrawCount = 0;
//
// NOTE: Semantically, we MUST withdraw existing intents before
@@ -157,7 +158,8 @@ public class SdnIpFib implements FibListener {
MacAddress nextHopMacAddress) {
// Find the attachment point (egress interface) of the next hop
- Interface egressInterface = interfaceService.getMatchingInterface(nextHopIpAddress);
+ Interface egressInterface =
+ interfaceService.getMatchingInterface(nextHopIpAddress);
if (egressInterface == null) {
log.warn("No outgoing interface found for {}",
nextHopIpAddress);
@@ -182,10 +184,19 @@ public class SdnIpFib implements FibListener {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
if (prefix.isIp4()) {
selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(prefix);
+ // if it is default route, then we do not need match destination
+ // IP address
+ if (prefix.prefixLength() != 0) {
+ selector.matchIPDst(prefix);
+ }
} else {
selector.matchEthType(Ethernet.TYPE_IPV6);
- selector.matchIPv6Dst(prefix);
+ // if it is default route, then we do not need match destination
+ // IP address
+ if (prefix.prefixLength() != 0) {
+ selector.matchIPv6Dst(prefix);
+ }
+
}
// Rewrite the destination MAC address
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index a737339f..99225874 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -448,7 +448,6 @@ public class DefaultRoutingHandler {
if (nextHops.isEmpty()) {
nextHops.add(destSw);
}
-
// If both target switch and dest switch are edge routers, then set IP
// rule for both subnet and router IP.
boolean targetIsEdge;
@@ -467,7 +466,7 @@ public class DefaultRoutingHandler {
if (targetIsEdge && destIsEdge) {
Set<Ip4Prefix> subnets = config.getSubnets(destSw);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
- targetSw, destSw, subnets);
+ targetSw, destSw, subnets);
result = rulePopulator.populateIpRuleForSubnet(targetSw,
subnets,
destSw,
@@ -479,24 +478,23 @@ public class DefaultRoutingHandler {
Ip4Address routerIp = destRouterIp;
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
- targetSw, destSw, routerIpPrefix);
+ targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
- // If the target switch is an edge router, then set IP rules for the router IP.
} else if (targetIsEdge) {
+ // If the target switch is an edge router, then set IP rules for the router IP.
Ip4Address routerIp = destRouterIp;
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for router IP {}",
- targetSw, destSw, routerIpPrefix);
+ targetSw, destSw, routerIpPrefix);
result = rulePopulator.populateIpRuleForRouter(targetSw, routerIpPrefix, destSw, nextHops);
if (!result) {
return false;
}
}
-
// Populates MPLS rules to all routers
log.debug("* populateEcmpRoutingRulePartial in device{} towards {} for all MPLS rules",
targetSw, destSw);
@@ -504,7 +502,6 @@ public class DefaultRoutingHandler {
if (!result) {
return false;
}
-
return true;
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
index bc3ce8c6..a07a15d2 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting;
+import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
@@ -26,7 +27,6 @@ import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.DeviceConfiguration;
import org.onosproject.segmentrouting.grouphandler.NeighborSet;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.Link;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -227,7 +227,15 @@ public class RoutingRulePopulator {
treatment = null;
}
- if (srManager.getNextObjectiveId(deviceId, ns) <= 0) {
+ // setup metadata to pass to nextObjective - indicate the vlan on egress
+ // if needed by the switch pipeline. Since neighbor sets are always to
+ // other neighboring routers, there is no subnet assigned on those ports.
+ TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
+ metabuilder.matchVlanId(
+ VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
+
+ int nextId = srManager.getNextObjectiveId(deviceId, ns, metabuilder.build());
+ if (nextId <= 0) {
log.warn("No next objective in {} for ns: {}", deviceId, ns);
return false;
}
@@ -236,7 +244,7 @@ public class RoutingRulePopulator {
.builder()
.fromApp(srManager.appId)
.makePermanent()
- .nextStep(srManager.getNextObjectiveId(deviceId, ns))
+ .nextStep(nextId)
.withSelector(selector)
.withPriority(100)
.withFlag(ForwardingObjective.Flag.SPECIFIC);
@@ -279,63 +287,70 @@ public class RoutingRulePopulator {
List<ForwardingObjective.Builder> fwdObjBuilders = new ArrayList<>();
// TODO Handle the case of Bos == false
- sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
sbuilder.matchEthType(Ethernet.MPLS_UNICAST);
+ sbuilder.matchMplsLabel(MplsLabel.mplsLabel(segmentId));
+ TrafficSelector selector = sbuilder.build();
+
+ // setup metadata to pass to nextObjective - indicate the vlan on egress
+ // if needed by the switch pipeline. Since mpls next-hops are always to
+ // other neighboring routers, there is no subnet assigned on those ports.
+ TrafficSelector.Builder metabuilder = DefaultTrafficSelector.builder(selector);
+ metabuilder.matchVlanId(
+ VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET));
- // If the next hop is the destination router, do PHP
+ // If the next hop is the destination router for the segment, do pop
if (nextHops.size() == 1 && destSwId.equals(nextHops.toArray()[0])) {
log.debug("populateMplsRule: Installing MPLS forwarding objective for "
- + "label {} in switch {} with PHP",
- segmentId,
- deviceId);
+ + "label {} in switch {} with pop", segmentId, deviceId);
+ // bos pop case (php)
ForwardingObjective.Builder fwdObjBosBuilder =
getMplsForwardingObjective(deviceId,
- destSwId,
nextHops,
true,
- true);
- // TODO: Check with Sangho on why we need this
- ForwardingObjective.Builder fwdObjNoBosBuilder =
- getMplsForwardingObjective(deviceId,
- destSwId,
- nextHops,
true,
- false);
- if (fwdObjBosBuilder != null) {
- fwdObjBuilders.add(fwdObjBosBuilder);
- } else {
- log.warn("Failed to set MPLS rules.");
+ metabuilder.build());
+ if (fwdObjBosBuilder == null) {
return false;
}
+ fwdObjBuilders.add(fwdObjBosBuilder);
+
+ // XXX not-bos pop case, SR app multi-label not implemented yet
+ /*ForwardingObjective.Builder fwdObjNoBosBuilder =
+ getMplsForwardingObjective(deviceId,
+ nextHops,
+ true,
+ false);*/
+
} else {
+ // next hop is not destination, SR CONTINUE case (swap with self)
log.debug("Installing MPLS forwarding objective for "
- + "label {} in switch {} without PHP",
- segmentId,
- deviceId);
+ + "label {} in switch {} without pop", segmentId, deviceId);
+ // continue case with bos - this does get triggered in edge routers
+ // and in core routers - driver can handle depending on availability
+ // of MPLS ECMP or not
ForwardingObjective.Builder fwdObjBosBuilder =
getMplsForwardingObjective(deviceId,
- destSwId,
nextHops,
false,
- true);
- // TODO: Check with Sangho on why we need this
- ForwardingObjective.Builder fwdObjNoBosBuilder =
+ true,
+ metabuilder.build());
+ if (fwdObjBosBuilder == null) {
+ return false;
+ }
+ fwdObjBuilders.add(fwdObjBosBuilder);
+
+ // XXX continue case with not-bos - SR app multi label not implemented yet
+ // also requires MPLS ECMP
+ /*ForwardingObjective.Builder fwdObjNoBosBuilder =
getMplsForwardingObjective(deviceId,
- destSwId,
nextHops,
false,
- false);
- if (fwdObjBosBuilder != null) {
- fwdObjBuilders.add(fwdObjBosBuilder);
- } else {
- log.warn("Failed to set MPLS rules.");
- return false;
- }
+ false); */
+
}
- TrafficSelector selector = sbuilder.build();
for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
.makePermanent()).withSelector(selector)
@@ -345,76 +360,61 @@ public class RoutingRulePopulator {
forward(deviceId,
fwdObjBuilder.
add(new SRObjectiveContext(deviceId,
- SRObjectiveContext.ObjectiveType.FORWARDING)));
+ SRObjectiveContext.ObjectiveType.FORWARDING)));
rulePopulationCounter.incrementAndGet();
}
return true;
}
- private ForwardingObjective.Builder getMplsForwardingObjective(DeviceId deviceId,
- DeviceId destSw,
- Set<DeviceId> nextHops,
- boolean phpRequired,
- boolean isBos) {
+ private ForwardingObjective.Builder getMplsForwardingObjective(
+ DeviceId deviceId,
+ Set<DeviceId> nextHops,
+ boolean phpRequired,
+ boolean isBos,
+ TrafficSelector meta) {
+
ForwardingObjective.Builder fwdBuilder = DefaultForwardingObjective
.builder().withFlag(ForwardingObjective.Flag.SPECIFIC);
- DeviceId nextHop = (DeviceId) nextHops.toArray()[0];
-
- boolean isEdge;
- MacAddress srcMac;
- MacAddress dstMac;
- try {
- isEdge = config.isEdgeDevice(deviceId);
- srcMac = config.getDeviceMac(deviceId);
- dstMac = config.getDeviceMac(nextHop);
- } catch (DeviceConfigNotFoundException e) {
- log.warn(e.getMessage() + " Aborting getMplsForwardingObjective");
- return null;
- }
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
if (phpRequired) {
+ // php case - pop should always be flow-action
log.debug("getMplsForwardingObjective: php required");
tbuilder.deferred().copyTtlIn();
if (isBos) {
- tbuilder.deferred().popMpls(Ethernet.TYPE_IPV4).decNwTtl();
+ tbuilder.deferred().popMpls(EthType.EtherType.IPV4.ethType())
+ .decNwTtl();
} else {
- tbuilder.deferred().popMpls(Ethernet.MPLS_UNICAST).decMplsTtl();
+ tbuilder.deferred().popMpls(EthType.EtherType.MPLS_UNICAST.ethType())
+ .decMplsTtl();
}
} else {
+ // swap with self case - SR CONTINUE
log.debug("getMplsForwardingObjective: php not required");
tbuilder.deferred().decMplsTtl();
}
- if (!isECMPSupportedInTransitRouter() && !isEdge) {
- PortNumber port = selectOnePort(deviceId, nextHops);
- if (port == null) {
- log.warn("No link from {} to {}", deviceId, nextHops);
- return null;
- }
- tbuilder.deferred()
- .setEthSrc(srcMac)
- .setEthDst(dstMac)
- .setOutput(port);
- fwdBuilder.withTreatment(tbuilder.build());
- } else {
- NeighborSet ns = new NeighborSet(nextHops);
- fwdBuilder.withTreatment(tbuilder.build());
- fwdBuilder.nextStep(srManager
- .getNextObjectiveId(deviceId, ns));
+ // All forwarding is via ECMP group, the metadata informs the driver
+ // that the next-Objective will be used by MPLS flows. In other words,
+ // MPLS ECMP is requested. It is up to the driver to decide if these
+ // packets will be hashed or not.
+ fwdBuilder.withTreatment(tbuilder.build());
+ NeighborSet ns = new NeighborSet(nextHops);
+ log.debug("Trying to get a nextObjid for mpls rule on device:{} to ns:{}",
+ deviceId, ns);
+
+ int nextId = srManager.getNextObjectiveId(deviceId, ns, meta);
+ if (nextId <= 0) {
+ log.warn("No next objective in {} for ns: {}", deviceId, ns);
+ return null;
}
+ fwdBuilder.nextStep(nextId);
return fwdBuilder;
}
- private boolean isECMPSupportedInTransitRouter() {
-
- // TODO: remove this function when objectives subsystem is supported.
- return false;
- }
-
/**
* Creates a filtering objective to permit all untagged packets with a
* dstMac corresponding to the router's MAC address. For those pipelines
@@ -552,22 +552,6 @@ public class RoutingRulePopulator {
}
- private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
-
- Set<Link> links = srManager.linkService.getDeviceLinks(srcId);
- for (DeviceId destId: destIds) {
- for (Link link : links) {
- if (link.dst().deviceId().equals(destId)) {
- return link.src().port();
- } else if (link.src().deviceId().equals(destId)) {
- return link.dst().port();
- }
- }
- }
-
- return null;
- }
-
private static class SRObjectiveContext implements ObjectiveContext {
enum ObjectiveType {
FILTER,
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 84fe5168..f6bf649c 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -424,17 +424,22 @@ public class SegmentRoutingManager implements SegmentRoutingService {
/**
* Returns the next objective ID for the given NeighborSet.
- * If the nextObjectiveID does not exist, a new one is created and returned.
+ * If the nextObjective does not exist, a new one is created and
+ * it's id is returned.
+ * TODO move the side-effect creation of a Next Objective into a new method
*
* @param deviceId Device ID
* @param ns NegighborSet
- * @return next objective ID
+ * @param meta metadata passed into the creation of a Next Objective
+ * @return next objective ID or -1 if an error was encountered during the
+ * creation of the nextObjective
*/
- public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns) {
+ public int getNextObjectiveId(DeviceId deviceId, NeighborSet ns,
+ TrafficSelector meta) {
if (groupHandlerMap.get(deviceId) != null) {
log.trace("getNextObjectiveId query in device {}", deviceId);
return groupHandlerMap
- .get(deviceId).getNextObjectiveId(ns);
+ .get(deviceId).getNextObjectiveId(ns, meta);
} else {
log.warn("getNextObjectiveId query in device {} not found", deviceId);
return -1;
@@ -586,7 +591,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
.deviceId());
if (groupHandler != null) {
- groupHandler.linkUp(link);
+ groupHandler.linkUp(link, mastershipService.isLocalMaster(
+ link.src().deviceId()));
} else {
Device device = deviceService.getDevice(link.src().deviceId());
if (device != null) {
@@ -596,7 +602,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
processDeviceAdded(device);
groupHandler = groupHandlerMap.get(link.src()
.deviceId());
- groupHandler.linkUp(link);
+ groupHandler.linkUp(link, mastershipService.isLocalMaster(device.id()));
}
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
index 7d025c72..b86adada 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/TunnelHandler.java
@@ -194,7 +194,7 @@ public class TunnelHandler {
tunnel.allowToRemoveGroup(true);
}
- return groupHandlerMap.get(deviceId).getNextObjectiveId(ns);
+ return groupHandlerMap.get(deviceId).getNextObjectiveId(ns, null);
}
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
index 33496bd7..6b6d960a 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java
@@ -93,7 +93,7 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
+ "with label for sw {} is {}",
deviceId, nsSet);
- createGroupsFromNeighborsets(nsSet);
+ //createGroupsFromNeighborsets(nsSet);
}
@Override
@@ -107,7 +107,7 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
newNeighborLink.dst().deviceId(),
devicePortMap.keySet());
- createGroupsFromNeighborsets(nsSet);
+ //createGroupsFromNeighborsets(nsSet);
}
@Override
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index b394db5e..e792bf66 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -21,11 +21,11 @@ import static org.slf4j.LoggerFactory.getLogger;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import org.onlab.packet.Ip4Prefix;
@@ -38,6 +38,7 @@ import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
@@ -71,10 +72,10 @@ public class DefaultGroupHandler {
protected LinkService linkService;
protected FlowObjectiveService flowObjectiveService;
- protected HashMap<DeviceId, Set<PortNumber>> devicePortMap = new HashMap<>();
- protected HashMap<PortNumber, DeviceId> portDeviceMap = new HashMap<>();
- //protected HashMap<NeighborSet, Integer> deviceNextObjectiveIds =
- // new HashMap<NeighborSet, Integer>();
+ protected ConcurrentHashMap<DeviceId, Set<PortNumber>> devicePortMap =
+ new ConcurrentHashMap<>();
+ protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
+ new ConcurrentHashMap<>();
protected EventuallyConsistentMap<
NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null;
protected EventuallyConsistentMap<
@@ -173,7 +174,7 @@ public class DefaultGroupHandler {
*
* @param newLink new neighbor link
*/
- public void linkUp(Link newLink) {
+ public void linkUp(Link newLink, boolean isMaster) {
if (newLink.type() != Link.Type.DIRECT) {
log.warn("linkUp: unknown link type");
@@ -186,6 +187,8 @@ public class DefaultGroupHandler {
return;
}
+ log.info("* LinkUP: Device {} linkUp at local port {} to neighbor {}", deviceId,
+ newLink.src().port(), newLink.dst().deviceId());
MacAddress dstMac;
try {
dstMac = deviceConfig.getDeviceMac(newLink.dst().deviceId());
@@ -194,8 +197,6 @@ public class DefaultGroupHandler {
return;
}
- log.debug("Device {} linkUp at local port {} to neighbor {}", deviceId,
- newLink.src().port(), newLink.dst().deviceId());
addNeighborAtPort(newLink.dst().deviceId(),
newLink.src().port());
/*if (devicePortMap.get(newLink.dst().deviceId()) == null) {
@@ -237,14 +238,20 @@ public class DefaultGroupHandler {
nextObjBuilder.addTreatment(tBuilder.build());
- log.debug("linkUp in device {}: Adding Bucket "
- + "with Port {} to next object id {}",
+ log.info("**linkUp in device {}: Adding Bucket "
+ + "with Port {} to next object id {} and amIMaster:{}",
deviceId,
newLink.src().port(),
- nextId);
- NextObjective nextObjective = nextObjBuilder.
- add(new SRNextObjectiveContext(deviceId));
- flowObjectiveService.next(deviceId, nextObjective);
+ nextId, isMaster);
+
+ if (isMaster) {
+ NextObjective nextObjective = nextObjBuilder.
+ addToExisting(new SRNextObjectiveContext(deviceId));
+ flowObjectiveService.next(deviceId, nextObjective);
+ }
+ } else {
+ log.warn("linkUp in device {}, but global store has no record "
+ + "for neighbor-set {}", deviceId, ns);
}
}
}
@@ -305,15 +312,16 @@ public class DefaultGroupHandler {
nextObjBuilder.addTreatment(tBuilder.build());
- log.debug("portDown in device {}: Removing Bucket "
+ log.info("**portDown in device {}: Removing Bucket "
+ "with Port {} to next object id {}",
deviceId,
port,
nextId);
- NextObjective nextObjective = nextObjBuilder.
+ // should do removefromexisting and only if master
+ /*NextObjective nextObjective = nextObjBuilder.
remove(new SRNextObjectiveContext(deviceId));
- flowObjectiveService.next(deviceId, nextObjective);
+ flowObjectiveService.next(deviceId, nextObjective);*/
}
}
@@ -325,12 +333,15 @@ public class DefaultGroupHandler {
/**
* Returns the next objective associated with the neighborset.
* If there is no next objective for this neighborset, this API
- * would create a next objective and return.
+ * would create a next objective and return. Optionally metadata can be
+ * passed in for the creation of the next objective.
*
* @param ns neighborset
- * @return int if found or -1
+ * @param meta metadata passed into the creation of a Next Objective
+ * @return int if found or -1 if there are errors in the creation of the
+ * neighbor set.
*/
- public int getNextObjectiveId(NeighborSet ns) {
+ public int getNextObjectiveId(NeighborSet ns, TrafficSelector meta) {
Integer nextId = nsNextObjStore.
get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
if (nextId == null) {
@@ -343,7 +354,7 @@ public class DefaultGroupHandler {
.filter((nsStoreEntry) ->
(nsStoreEntry.getKey().deviceId().equals(deviceId)))
.collect(Collectors.toList()));
- createGroupsFromNeighborsets(Collections.singleton(ns));
+ createGroupsFromNeighborsets(Collections.singleton(ns), meta);
nextId = nsNextObjStore.
get(new NeighborSetNextObjectiveStoreKey(deviceId, ns));
if (nextId == null) {
@@ -421,17 +432,19 @@ public class DefaultGroupHandler {
// Update DeviceToPort database
log.debug("Device {} addNeighborAtPort: neighbor {} at port {}",
deviceId, neighborId, portToNeighbor);
- if (devicePortMap.get(neighborId) != null) {
- devicePortMap.get(neighborId).add(portToNeighbor);
- } else {
- Set<PortNumber> ports = new HashSet<>();
- ports.add(portToNeighbor);
- devicePortMap.put(neighborId, ports);
+ Set<PortNumber> ports = Collections
+ .newSetFromMap(new ConcurrentHashMap<PortNumber, Boolean>());
+ ports.add(portToNeighbor);
+ Set<PortNumber> portnums = devicePortMap.putIfAbsent(neighborId, ports);
+ if (portnums != null) {
+ portnums.add(portToNeighbor);
}
// Update portToDevice database
- if (portDeviceMap.get(portToNeighbor) == null) {
- portDeviceMap.put(portToNeighbor, neighborId);
+ DeviceId prev = portDeviceMap.putIfAbsent(portToNeighbor, neighborId);
+ if (prev != null) {
+ log.warn("Device: {} port: {} has neighbor: {}. NOT updating "
+ + "to neighbor: {}", deviceId, portToNeighbor, prev, neighborId);
}
}
@@ -505,61 +518,66 @@ public class DefaultGroupHandler {
* Creates Groups from a set of NeighborSet given.
*
* @param nsSet a set of NeighborSet
+ * @param meta metadata passed into the creation of a Next Objective
*/
- public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet) {
+ public void createGroupsFromNeighborsets(Set<NeighborSet> nsSet,
+ TrafficSelector meta) {
for (NeighborSet ns : nsSet) {
int nextId = flowObjectiveService.allocateNextId();
NextObjective.Builder nextObjBuilder = DefaultNextObjective
.builder().withId(nextId)
.withType(NextObjective.Type.HASHED).fromApp(appId);
- for (DeviceId d : ns.getDeviceIds()) {
- if (devicePortMap.get(d) == null) {
- log.warn("Device {} is not in the port map yet", d);
+ for (DeviceId neighborId : ns.getDeviceIds()) {
+ if (devicePortMap.get(neighborId) == null) {
+ log.warn("Neighbor {} is not in the port map yet for dev:{}",
+ neighborId, deviceId);
return;
- } else if (devicePortMap.get(d).size() == 0) {
+ } else if (devicePortMap.get(neighborId).size() == 0) {
log.warn("There are no ports for "
- + "the Device {} in the port map yet", d);
+ + "the Device {} in the port map yet", neighborId);
return;
}
- MacAddress deviceMac;
+ MacAddress neighborMac;
try {
- deviceMac = deviceConfig.getDeviceMac(d);
+ neighborMac = deviceConfig.getDeviceMac(neighborId);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting createGroupsFromNeighborsets.");
return;
}
- for (PortNumber sp : devicePortMap.get(d)) {
+ for (PortNumber sp : devicePortMap.get(neighborId)) {
TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment
.builder();
- tBuilder.setOutput(sp)
- .setEthDst(deviceMac)
+ tBuilder.setEthDst(neighborMac)
.setEthSrc(nodeMacAddr);
if (ns.getEdgeLabel() != NeighborSet.NO_EDGE_LABEL) {
tBuilder.pushMpls()
.copyTtlOut()
.setMpls(MplsLabel.mplsLabel(ns.getEdgeLabel()));
}
+ tBuilder.setOutput(sp);
nextObjBuilder.addTreatment(tBuilder.build());
}
}
-
+ if (meta != null) {
+ nextObjBuilder.setMeta(meta);
+ }
NextObjective nextObj = nextObjBuilder.
add(new SRNextObjectiveContext(deviceId));
- flowObjectiveService.next(deviceId, nextObj);
- log.debug("createGroupsFromNeighborsets: Submited "
- + "next objective {} in device {}",
+ log.info("**createGroupsFromNeighborsets: Submited "
+ + "next objective {} in device {}",
nextId, deviceId);
+ flowObjectiveService.next(deviceId, nextObj);
nsNextObjStore.put(new NeighborSetNextObjectiveStoreKey(deviceId, ns),
nextId);
}
}
+
public void createGroupsFromSubnetConfig() {
Map<Ip4Prefix, List<PortNumber>> subnetPortMap =
this.deviceConfig.getSubnetPortsMap(this.deviceId);
-
// Construct a broadcast group for each subnet
subnetPortMap.forEach((subnet, ports) -> {
SubnetNextObjectiveStoreKey key =
@@ -612,6 +630,9 @@ public class DefaultGroupHandler {
.withType(NextObjective.Type.HASHED).fromApp(appId);
NextObjective nextObjective = nextObjBuilder.
remove(new SRNextObjectiveContext(deviceId));
+ log.info("**removeGroup: Submited "
+ + "next objective {} in device {}",
+ objectiveId, deviceId);
flowObjectiveService.next(deviceId, nextObjective);
for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: nsNextObjStore.entrySet()) {
@@ -634,14 +655,14 @@ public class DefaultGroupHandler {
}
@Override
public void onSuccess(Objective objective) {
- log.debug("Next objective operation successful in device {}",
- deviceId);
+ log.info("Next objective {} operation successful in device {}",
+ objective.id(), deviceId);
}
@Override
public void onError(Objective objective, ObjectiveError error) {
log.warn("Next objective {} operation failed with error: {} in device {}",
- objective, error, deviceId);
+ objective.id(), error, deviceId);
}
}
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
index 8e1b6a8f..14d77ba6 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java
@@ -81,7 +81,7 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
log.debug("createGroupsAtTransitRouter: The neighborset with label "
+ "for sw {} is {}", deviceId, nsSet);
- createGroupsFromNeighborsets(nsSet);
+ //createGroupsFromNeighborsets(nsSet);
}
@Override
@@ -95,7 +95,7 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
Set<NeighborSet> nsSet = computeImpactedNeighborsetForPortEvent(
newNeighborLink.dst().deviceId(),
devicePortMap.keySet());
- createGroupsFromNeighborsets(nsSet);
+ //createGroupsFromNeighborsets(nsSet);
}
@Override
diff --git a/framework/src/onos/apps/virtualbng/features.xml b/framework/src/onos/apps/virtualbng/features.xml
index 2b48bec3..c997d4c6 100644
--- a/framework/src/onos/apps/virtualbng/features.xml
+++ b/framework/src/onos/apps/virtualbng/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle>
diff --git a/framework/src/onos/apps/vtn/app/features.xml b/framework/src/onos/apps/vtn/app/features.xml
index c82b41d5..8ee882c4 100644
--- a/framework/src/onos/apps/vtn/app/features.xml
+++ b/framework/src/onos/apps/vtn/app/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<feature>onos-api</feature>
diff --git a/framework/src/onos/apps/vtn/sfcmgr/pom.xml b/framework/src/onos/apps/vtn/sfcmgr/pom.xml
new file mode 100644
index 00000000..8b5f1983
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!--
+ ~ Copyright 2015 Open Networking Laboratory
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<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.onosproject</groupId>
+ <artifactId>onos-app-vtn</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-sfc-mgr</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.scr.annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-vtn-rsc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.onosproject.openflow.*,org.projectfloodlight.openflow.*
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java
new file mode 100644
index 00000000..e91e6b69
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/ServiceFunctionForwarder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sfc.forwarder;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.PortChain;
+
+/**
+ * Abstraction of an entity which provides Service function forwarder.
+ */
+public interface ServiceFunctionForwarder {
+
+ /**
+ * Install Service function chain.
+ *
+ * @param portChain Port chain
+ */
+ void install(PortChain portChain);
+
+ /**
+ * Programs forwarding object for Service Function.
+ *
+ * @param portChain port chain
+ * @param appid application id
+ * @param type forwarding objective operation type
+ */
+ void programServiceFunctionForwarder(PortChain portChain, ApplicationId appid,
+ Objective.Operation type);
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java
new file mode 100644
index 00000000..08021f3c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/forwarder/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service function forwarder for SFC.
+ */
+package org.onosproject.sfc.forwarder;
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstaller.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstaller.java
new file mode 100644
index 00000000..f05a21dc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/FlowClassifierInstaller.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sfc.installer;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.PortPair;
+
+/**
+ * Abstraction of an entity which installs flow classification rules in ovs.
+ */
+public interface FlowClassifierInstaller {
+
+ /**
+ * Install flow classifier rules.
+ *
+ * @param flowClassifier Flow Classifier
+ * @param portPair Port pair
+ */
+ void install(FlowClassifier flowClassifier, PortPair portPair);
+
+ /**
+ * Programs forwarding object for flow classifier.
+ *
+ * @param flowClassifier flow classifier
+ * @param portPair port pair
+ * @param appid application id
+ * @param type forwarding objective operation type
+ */
+ void programFlowClassification(FlowClassifier flowClassifier, PortPair portPair, ApplicationId appid,
+ Objective.Operation type);
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/DefaultFlowClassifierInstaller.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/DefaultFlowClassifierInstaller.java
new file mode 100644
index 00000000..e1a80932
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/DefaultFlowClassifierInstaller.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sfc.installer.impl;
+
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flowobjective.Objective.Operation;
+import org.onosproject.sfc.installer.FlowClassifierInstaller;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.PortPair;
+
+/**
+ * Provides flow classifier installer.
+ */
+public class DefaultFlowClassifierInstaller implements FlowClassifierInstaller {
+
+ /**
+ * Default constructor.
+ */
+ public DefaultFlowClassifierInstaller() {
+ }
+
+ @Override
+ public void install(FlowClassifier flowClassifier, PortPair portPair) {
+ // TODO: Process flow-classifier for installation.
+ }
+
+ @Override
+ public void programFlowClassification(FlowClassifier flowClassifier, PortPair portPair, ApplicationId appid,
+ Operation type) {
+ // TODO: program forwarding objective for flow-classifier installation.
+ }
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/package-info.java
new file mode 100644
index 00000000..d9796d80
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Implementation of Service for installing flow classifier rules in OVS.
+ */
+package org.onosproject.sfc.installer.impl;
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/package-info.java
new file mode 100644
index 00000000..77c0ab30
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/installer/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for installing flow classifier rules in OVS.
+ */
+package org.onosproject.sfc.installer;
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java
new file mode 100644
index 00000000..ef5fc529
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/SfcService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sfc.manager;
+
+/**
+ * SFC application that applies flows to the device.
+ */
+public interface SfcService {
+
+ /**
+ * When port-pair is created, check whether Forwarding Rule needs to be
+ * updated in OVS.
+ */
+ public void onPortPairCreated();
+
+ /**
+ * When port-pair is deleted, check whether Forwarding Rule needs to be
+ * updated in OVS.
+ */
+ public void onPortPairDeleted();
+
+ /**
+ * When port-pair-group is created, check whether Forwarding Rule needs to
+ * be updated in OVS.
+ */
+ public void onPortPairGroupCreated();
+
+ /**
+ * When port-pair-group is deleted, check whether Forwarding Rule needs to
+ * be updated in OVS.
+ */
+ public void onPortPairGroupDeleted();
+
+ /**
+ * When flow-classifier is created, check whether Forwarding Rule needs to
+ * be updated in OVS.
+ */
+ public void onFlowClassifierCreated();
+
+ /**
+ * When flow-classifier is deleted, check whether Forwarding Rule needs to
+ * be updated in OVS.
+ */
+ public void onFlowClassifierDeleted();
+
+ /**
+ * When port-chain is created, check whether Forwarding Rule needs to be
+ * updated in OVS.
+ */
+ public void onPortChainCreated();
+
+ /**
+ * When port-chain is deleted, check whether Forwarding Rule needs to be
+ * updated in OVS.
+ */
+ public void onPortChainDeleted();
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java
new file mode 100644
index 00000000..12d27c87
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/SfcManager.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.sfc.manager.impl;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Service;
+import org.onosproject.sfc.manager.SfcService;
+import org.onosproject.vtnrsc.PortChain;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of SFC Service.
+ */
+@Component(immediate = true)
+@Service
+public class SfcManager implements SfcService {
+
+ private final Logger log = getLogger(getClass());
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void onPortPairCreated() {
+ log.debug("onPortPairCreated");
+ // TODO: Process port-pair on creation.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onPortPairDeleted() {
+ log.debug("onPortPairDeleted");
+ // TODO: Process port-pair on deletion.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onPortPairGroupCreated() {
+ log.debug("onPortPairGroupCreated");
+ // TODO: Process port-pair-group on creation.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onPortPairGroupDeleted() {
+ log.debug("onPortPairGroupDeleted");
+ // TODO: Process port-pair-group on deletion.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onFlowClassifierCreated() {
+ log.debug("onFlowClassifierCreated");
+ // TODO: Process flow-classifier on creation.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onFlowClassifierDeleted() {
+ log.debug("onFlowClassifierDeleted");
+ // TODO: Process flow-classifier on deletion.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ @Override
+ public void onPortChainCreated() {
+ log.debug("onPortChainCreated");
+ // TODO: Process port-chain on creation.
+ // TODO: Parameter also needs to be modified.
+
+ }
+
+ @Override
+ public void onPortChainDeleted() {
+ log.debug("onPortChainDeleted");
+ // TODO: Process port-chain on deletion.
+ // TODO: Parameter also needs to be modified.
+ }
+
+ /**
+ * Install SF Forwarding rule into OVS.
+ *
+ * @param portChain
+ * port chain
+ */
+ public void installForwardingRule(PortChain portChain) {
+ log.debug("installForwardingRule");
+ // TODO: Installation of SF Forwarding rule into OVS.
+ }
+
+ /**
+ * Uninstall SF Forwarding rule from OVS.
+ *
+ * @param portChain
+ * port chain
+ */
+ public void unInstallForwardingRule(PortChain portChain) {
+ log.debug("unInstallForwardingRule");
+ // TODO: Uninstallation of SF Forwarding rule from OVS.
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/package-info.java
new file mode 100644
index 00000000..7161380a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * SFC Service manager for interacting with SFC.
+ */
+package org.onosproject.sfc.manager.impl;
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/package-info.java
new file mode 100644
index 00000000..1dd0f5a0
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/manager/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with SFC.
+ */
+package org.onosproject.sfc.manager;
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java
new file mode 100644
index 00000000..a104e529
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/VTNService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.manager;
+
+import org.onosproject.net.Device;
+import org.onosproject.net.Host;
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+public interface VTNService {
+
+ /**
+ * Creates a vxlan tunnel and creates the ovs when a ovs controller node is
+ * detected.
+ *
+ * @param device controller-type device
+ */
+ void onControllerDetected(Device device);
+
+ /**
+ * Drops a vxlan tunnel and drops the ovs when a ovs controller node is
+ * vanished.
+ *
+ * @param device controller-type device
+ */
+ void onControllerVanished(Device device);
+
+ /**
+ * Applies default forwarding flows when a ovs is detected.
+ *
+ * @param device switch-type device
+ */
+ void onOvsDetected(Device device);
+
+ /**
+ * Remove default forwarding flows when a ovs is vanished.
+ *
+ * @param device switch-type device
+ */
+ void onOvsVanished(Device device);
+
+ /**
+ * Applies multicast flows and tunnel flows when a VM is detected.
+ *
+ * @param host a VM
+ */
+ void onHostDetected(Host host);
+
+ /**
+ * Remove multicast flows and tunnel flows when a VM is vanished.
+ *
+ * @param host a VM
+ */
+ void onHostVanished(Host host);
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
new file mode 100644
index 00000000..be6b9364
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VTNManager.java
@@ -0,0 +1,585 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.manager.impl;
+
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeDescription;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.device.DeviceEvent;
+import org.onosproject.net.device.DeviceListener;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment.Builder;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupService;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.LogicalClockService;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.vtn.manager.VTNService;
+import org.onosproject.vtn.table.ClassifierService;
+import org.onosproject.vtn.table.L2ForwardService;
+import org.onosproject.vtn.table.impl.ClassifierServiceImpl;
+import org.onosproject.vtn.table.impl.L2ForwardServiceImpl;
+import org.onosproject.vtn.util.DataPathIdGenerator;
+import org.onosproject.vtn.util.VtnConfig;
+import org.onosproject.vtn.util.VtnData;
+import org.onosproject.vtnrsc.AllowedAddressPair;
+import org.onosproject.vtnrsc.BindingHostId;
+import org.onosproject.vtnrsc.DefaultVirtualPort;
+import org.onosproject.vtnrsc.FixedIp;
+import org.onosproject.vtnrsc.SecurityGroup;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetwork;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPort;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of VTNService.
+ */
+@Component(immediate = true)
+@Service
+public class VTNManager implements VTNService {
+ private final Logger log = getLogger(getClass());
+ private static final String APP_ID = "org.onosproject.app.vtn";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TenantNetworkService tenantNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualPortService virtualPortService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LogicalClockService clockService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MastershipService mastershipService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected GroupService groupService;
+
+ private ApplicationId appId;
+ private ClassifierService classifierService;
+ private L2ForwardService l2ForwardService;
+
+ private final HostListener hostListener = new InnerHostListener();
+ private final DeviceListener deviceListener = new InnerDeviceListener();
+
+ private static final String IFACEID = "ifaceid";
+ private static final String CONTROLLER_IP_KEY = "ipaddress";
+ public static final String DRIVER_NAME = "onosfw";
+ private static final String EX_PORT_NAME = "eth0";
+ private static final String VIRTUALPORT = "vtn-virtual-port";
+ private static final String SWITCHES_OF_CONTROLLER = "switchesOfController";
+ private static final String SWITCH_OF_LOCAL_HOST_PORTS = "switchOfLocalHostPorts";
+ private static final String DEFAULT_IP = "0.0.0.0";
+
+ private EventuallyConsistentMap<VirtualPortId, VirtualPort> vPortStore;
+ private EventuallyConsistentMap<IpAddress, Boolean> switchesOfController;
+ private EventuallyConsistentMap<DeviceId, NetworkOfLocalHostPorts> switchOfLocalHostPorts;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(APP_ID);
+ classifierService = new ClassifierServiceImpl(appId);
+ l2ForwardService = new L2ForwardServiceImpl(appId);
+
+ deviceService.addListener(deviceListener);
+ hostService.addListener(hostListener);
+
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(NetworkOfLocalHostPorts.class)
+ .register(TenantNetworkId.class)
+ .register(Host.class)
+ .register(TenantNetwork.class)
+ .register(TenantId.class)
+ .register(SubnetId.class)
+ .register(VirtualPortId.class)
+ .register(VirtualPort.State.class)
+ .register(AllowedAddressPair.class)
+ .register(FixedIp.class)
+ .register(BindingHostId.class)
+ .register(SecurityGroup.class)
+ .register(IpAddress.class)
+ .register(DefaultVirtualPort.class);
+
+ vPortStore = storageService
+ .<VirtualPortId, VirtualPort>eventuallyConsistentMapBuilder()
+ .withName(VIRTUALPORT).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+
+ switchesOfController = storageService
+ .<IpAddress, Boolean>eventuallyConsistentMapBuilder()
+ .withName(SWITCHES_OF_CONTROLLER).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+
+ switchOfLocalHostPorts = storageService
+ .<DeviceId, NetworkOfLocalHostPorts>eventuallyConsistentMapBuilder()
+ .withName(SWITCH_OF_LOCAL_HOST_PORTS).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ deviceService.removeListener(deviceListener);
+ hostService.removeListener(hostListener);
+ log.info("Stopped");
+ }
+
+ @Override
+ public void onControllerDetected(Device controllerDevice) {
+ if (controllerDevice == null) {
+ log.error("The controller device is null");
+ return;
+ }
+ String localIpAddress = controllerDevice.annotations()
+ .value(CONTROLLER_IP_KEY);
+ IpAddress localIp = IpAddress.valueOf(localIpAddress);
+ DeviceId controllerDeviceId = controllerDevice.id();
+ DriverHandler handler = driverService.createHandler(controllerDeviceId);
+ if (mastershipService.isLocalMaster(controllerDeviceId)) {
+ // Get DataPathIdGenerator
+ String ipaddress = controllerDevice.annotations().value("ipaddress");
+ DataPathIdGenerator dpidGenerator = DataPathIdGenerator.builder()
+ .addIpAddress(ipaddress).build();
+ DeviceId deviceId = dpidGenerator.getDeviceId();
+ String dpid = dpidGenerator.getDpId();
+ // Inject pipeline driver name
+ BasicDeviceConfig config = configService.addConfig(deviceId,
+ BasicDeviceConfig.class);
+ config.driver(DRIVER_NAME);
+ configService.applyConfig(deviceId, BasicDeviceConfig.class, config.node());
+ // Add Bridge
+ VtnConfig.applyBridgeConfig(handler, dpid, EX_PORT_NAME);
+ log.info("A new ovs is created in node {}", localIp.toString());
+ switchesOfController.put(localIp, true);
+ }
+ // Create tunnel in br-int on all controllers
+ programTunnelConfig(controllerDeviceId, localIp, handler);
+ }
+
+ @Override
+ public void onControllerVanished(Device controllerDevice) {
+ if (controllerDevice == null) {
+ log.error("The device is null");
+ return;
+ }
+ String dstIp = controllerDevice.annotations().value(CONTROLLER_IP_KEY);
+ IpAddress dstIpAddress = IpAddress.valueOf(dstIp);
+ DeviceId controllerDeviceId = controllerDevice.id();
+ if (mastershipService.isLocalMaster(controllerDeviceId)) {
+ switchesOfController.remove(dstIpAddress);
+ }
+ // remove tunnel in br-int on other controllers
+ programTunnelConfig(controllerDeviceId, dstIpAddress, null);
+ }
+
+ @Override
+ public void onOvsDetected(Device device) {
+ // Create tunnel out flow rules
+ applyTunnelOut(device, Objective.Operation.ADD);
+ }
+
+ @Override
+ public void onOvsVanished(Device device) {
+ // Remove Tunnel out flow rules
+ applyTunnelOut(device, Objective.Operation.REMOVE);
+ }
+
+ @Override
+ public void onHostDetected(Host host) {
+ // apply L2 openflow rules
+ applyHostMonitoredL2Rules(host, Objective.Operation.ADD);
+ }
+
+ @Override
+ public void onHostVanished(Host host) {
+ // apply L2 openflow rules
+ applyHostMonitoredL2Rules(host, Objective.Operation.REMOVE);
+ }
+
+ private void programTunnelConfig(DeviceId localDeviceId, IpAddress localIp,
+ DriverHandler localHandler) {
+ if (mastershipService.isLocalMaster(localDeviceId)) {
+ VtnConfig.applyTunnelConfig(localHandler, localIp, IpAddress.valueOf(DEFAULT_IP));
+ log.info("Add tunnel on {}", localIp);
+ }
+ }
+
+ private void applyTunnelOut(Device device, Objective.Operation type) {
+ if (device == null) {
+ log.error("The device is null");
+ return;
+ }
+ if (!mastershipService.isLocalMaster(device.id())) {
+ return;
+ }
+ String controllerIp = VtnData.getControllerIpOfSwitch(device);
+ if (controllerIp == null) {
+ log.error("Can't find controller of device: {}",
+ device.id().toString());
+ return;
+ }
+ IpAddress ipAddress = IpAddress.valueOf(controllerIp);
+ if (!switchesOfController.containsKey(ipAddress)) {
+ log.error("Can't find controller of device: {}",
+ device.id().toString());
+ return;
+ }
+ if (type == Objective.Operation.ADD) {
+ switchOfLocalHostPorts.put(device.id(), new NetworkOfLocalHostPorts());
+ } else if (type == Objective.Operation.REMOVE) {
+ switchOfLocalHostPorts.remove(device.id());
+ }
+ Iterable<Device> devices = deviceService.getAvailableDevices();
+ DeviceId localControllerId = VtnData.getControllerId(device, devices);
+ DriverHandler handler = driverService.createHandler(localControllerId);
+ Set<PortNumber> ports = VtnConfig.getPortNumbers(handler);
+ Iterable<Host> allHosts = hostService.getHosts();
+ String tunnelName = "vxlan-" + DEFAULT_IP;
+ if (allHosts != null) {
+ Sets.newHashSet(allHosts).stream().forEach(host -> {
+ MacAddress hostMac = host.mac();
+ String ifaceId = host.annotations().value(IFACEID);
+ if (ifaceId == null) {
+ log.error("The ifaceId of Host is null");
+ return;
+ }
+ VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
+ VirtualPort virtualPort = virtualPortService
+ .getPort(virtualPortId);
+ TenantNetwork network = tenantNetworkService
+ .getNetwork(virtualPort.networkId());
+ SegmentationId segmentationId = network.segmentationId();
+ DeviceId remoteDeviceId = host.location().deviceId();
+ Device remoteDevice = deviceService.getDevice(remoteDeviceId);
+ String remoteControllerIp = VtnData
+ .getControllerIpOfSwitch(remoteDevice);
+ if (remoteControllerIp == null) {
+ log.error("Can't find remote controller of device: {}",
+ remoteDeviceId.toString());
+ return;
+ }
+ IpAddress remoteIpAddress = IpAddress
+ .valueOf(remoteControllerIp);
+ ports.stream()
+ .filter(p -> p.name().equalsIgnoreCase(tunnelName))
+ .forEach(p -> {
+ l2ForwardService
+ .programTunnelOut(device.id(), segmentationId, p,
+ hostMac, type, remoteIpAddress);
+ });
+ });
+ }
+ }
+
+ private void applyHostMonitoredL2Rules(Host host, Objective.Operation type) {
+ DeviceId deviceId = host.location().deviceId();
+ if (!mastershipService.isLocalMaster(deviceId)) {
+ return;
+ }
+ String ifaceId = host.annotations().value(IFACEID);
+ if (ifaceId == null) {
+ log.error("The ifaceId of Host is null");
+ return;
+ }
+ VirtualPortId virtualPortId = VirtualPortId.portId(ifaceId);
+ VirtualPort virtualPort = virtualPortService.getPort(virtualPortId);
+ if (virtualPort == null) {
+ virtualPort = vPortStore.get(virtualPortId);
+ }
+
+ Iterable<Device> devices = deviceService.getAvailableDevices();
+ PortNumber inPort = host.location().port();
+ MacAddress mac = host.mac();
+ Device device = deviceService.getDevice(deviceId);
+ String controllerIp = VtnData.getControllerIpOfSwitch(device);
+ IpAddress ipAddress = IpAddress.valueOf(controllerIp);
+ TenantNetwork network = tenantNetworkService.getNetwork(virtualPort.networkId());
+ if (network == null) {
+ log.error("Can't find network of the host");
+ return;
+ }
+ SegmentationId segmentationId = network.segmentationId();
+ // Get all the tunnel PortNumber in the current node
+ Iterable<Port> ports = deviceService.getPorts(deviceId);
+ Collection<PortNumber> localTunnelPorts = VtnData.getLocalTunnelPorts(ports);
+ // Get all the local vm's PortNumber in the current node
+ Map<TenantNetworkId, Set<PortNumber>> localHostPorts = switchOfLocalHostPorts
+ .get(deviceId).getNetworkOfLocalHostPorts();
+ Set<PortNumber> networkOflocalHostPorts = localHostPorts.get(network.id());
+ for (PortNumber p : localTunnelPorts) {
+ programGroupTable(deviceId, appId, p, devices, type);
+ }
+
+ if (type == Objective.Operation.ADD) {
+ vPortStore.put(virtualPortId, virtualPort);
+ if (networkOflocalHostPorts == null) {
+ networkOflocalHostPorts = new HashSet<PortNumber>();
+ localHostPorts.putIfAbsent(network.id(), networkOflocalHostPorts);
+ }
+ networkOflocalHostPorts.add(inPort);
+ l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
+ inPort, networkOflocalHostPorts,
+ localTunnelPorts,
+ type);
+ classifierService.programTunnelIn(deviceId, segmentationId,
+ localTunnelPorts,
+ type);
+ } else if (type == Objective.Operation.REMOVE) {
+ vPortStore.remove(virtualPortId);
+ if (networkOflocalHostPorts != null) {
+ l2ForwardService.programLocalBcastRules(deviceId, segmentationId,
+ inPort, networkOflocalHostPorts,
+ localTunnelPorts,
+ type);
+ networkOflocalHostPorts.remove(inPort);
+ if (networkOflocalHostPorts.isEmpty()) {
+ classifierService.programTunnelIn(deviceId, segmentationId,
+ localTunnelPorts,
+ type);
+ switchOfLocalHostPorts.get(deviceId).getNetworkOfLocalHostPorts()
+ .remove(virtualPort.networkId());
+ }
+ }
+ }
+
+ l2ForwardService.programLocalOut(deviceId, segmentationId, inPort, mac,
+ type);
+
+ l2ForwardService.programTunnelBcastRules(deviceId, segmentationId,
+ networkOflocalHostPorts,
+ localTunnelPorts,
+ type);
+
+ programTunnelOuts(devices, ipAddress, segmentationId, mac,
+ type);
+
+ classifierService.programLocalIn(deviceId, segmentationId, inPort, mac,
+ appId, type);
+ }
+
+ private void programTunnelOuts(Iterable<Device> devices,
+ IpAddress ipAddress,
+ SegmentationId segmentationId,
+ MacAddress dstMac,
+ Objective.Operation type) {
+ String tunnelName = "vxlan-" + DEFAULT_IP;
+ Sets.newHashSet(devices).stream()
+ .filter(d -> d.type() == Device.Type.CONTROLLER)
+ .filter(d -> !("ovsdb:" + ipAddress).equals(d.id().toString()))
+ .forEach(d -> {
+ DriverHandler handler = driverService.createHandler(d.id());
+ BridgeConfig bridgeConfig = handler
+ .behaviour(BridgeConfig.class);
+ Collection<BridgeDescription> bridgeDescriptions = bridgeConfig
+ .getBridges();
+ Set<PortNumber> ports = bridgeConfig.getPortNumbers();
+ Iterator<BridgeDescription> it = bridgeDescriptions
+ .iterator();
+ if (it.hasNext()) {
+ BridgeDescription sw = it.next();
+ ports.stream()
+ .filter(p -> p.name()
+ .equalsIgnoreCase(tunnelName))
+ .forEach(p -> {
+ l2ForwardService.programTunnelOut(sw.deviceId(),
+ segmentationId, p,
+ dstMac, type, ipAddress);
+ });
+ }
+ });
+ }
+
+ private class InnerDeviceListener implements DeviceListener {
+
+ @Override
+ public void event(DeviceEvent event) {
+ Device device = event.subject();
+ if (Device.Type.CONTROLLER == device.type()) {
+ if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
+ onControllerDetected(device);
+ }
+ if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
+ if (deviceService.isAvailable(device.id())) {
+ onControllerDetected(device);
+ } else {
+ onControllerVanished(device);
+ }
+ }
+ } else if (Device.Type.SWITCH == device.type()) {
+ if (DeviceEvent.Type.DEVICE_ADDED == event.type()) {
+ onOvsDetected(device);
+ }
+ if (DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED == event.type()) {
+ if (deviceService.isAvailable(device.id())) {
+ onOvsDetected(device);
+ } else {
+ onOvsVanished(device);
+ }
+ }
+ } else {
+ log.info("Do nothing for this device type");
+ }
+ }
+ }
+
+ private class InnerHostListener implements HostListener {
+
+ @Override
+ public void event(HostEvent event) {
+ Host host = event.subject();
+ if (HostEvent.Type.HOST_ADDED == event.type()) {
+ onHostDetected(host);
+ } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
+ onHostVanished(host);
+ } else if (HostEvent.Type.HOST_UPDATED == event.type()) {
+ onHostVanished(host);
+ onHostDetected(host);
+ }
+ }
+
+ }
+
+ // Local Host Ports of Network.
+ private class NetworkOfLocalHostPorts {
+ private final Map<TenantNetworkId, Set<PortNumber>> networkOfLocalHostPorts =
+ new HashMap<TenantNetworkId, Set<PortNumber>>();
+
+ public Map<TenantNetworkId, Set<PortNumber>> getNetworkOfLocalHostPorts() {
+ return networkOfLocalHostPorts;
+ }
+ }
+
+ private void programGroupTable(DeviceId deviceId, ApplicationId appid,
+ PortNumber portNumber, Iterable<Device> devices, Objective.Operation type) {
+ if (type.equals(Objective.Operation.REMOVE)) {
+ return;
+ }
+
+ List<GroupBucket> buckets = Lists.newArrayList();
+ Sets.newHashSet(devices)
+ .stream()
+ .filter(d -> d.type() == Device.Type.CONTROLLER)
+ .filter(d -> !deviceId.equals(d.id()))
+ .forEach(d -> {
+ String ipAddress = d.annotations()
+ .value(CONTROLLER_IP_KEY);
+ Ip4Address dst = Ip4Address.valueOf(ipAddress);
+ Builder builder = DefaultTrafficTreatment.builder();
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ try {
+ treatment.setPropertyValue("tunnelDst", dst);
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ }
+
+ builder.extension(treatment, deviceId);
+ builder.setOutput(portNumber);
+ GroupBucket bucket = DefaultGroupBucket
+ .createAllGroupBucket(builder.build());
+ buckets.add(bucket);
+ });
+ final GroupKey key = new DefaultGroupKey(APP_ID.getBytes());
+ GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.ALL,
+ new GroupBuckets(buckets),
+ key,
+ L2ForwardServiceImpl.GROUP_ID,
+ appid);
+ groupService.addGroup(groupDescription);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/package-info.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/package-info.java
new file mode 100644
index 00000000..4c9a58cc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.manager.impl;
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/package-info.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/package-info.java
new file mode 100644
index 00000000..09bd80f8
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.manager;
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java
new file mode 100644
index 00000000..b548938b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ArpService.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * ArpService interface providing the rules in ARP table which is Table(10).
+ */
+public interface ArpService {
+
+ /**
+ * Assemble the arp rules.
+ * Match: arp type, vnid and destination ip.
+ * Action: set arp_operation, move arp_eth_src to arp_eth_dst, set arp_eth_src,
+ * move arp_ip_src to arp_ip_dst, set arp_ip_src, set output port.
+ *
+ * @param deviceId Device Id
+ * @param dstIP destination ip
+ * @param matchVni the vni of the source network (l2vni)
+ * @param dstMac destination mac
+ * @param type the operation type of the flow rules
+ */
+ void programArpRules(DeviceId deviceId, IpAddress dstIP,
+ SegmentationId matchVni, MacAddress dstMac,
+ Objective.Operation type);
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java
new file mode 100644
index 00000000..69e951a2
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/ClassifierService.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * Applies classifier flows to the device. Classifier table is Table(0).
+ */
+public interface ClassifierService {
+
+ /**
+ * The port rule that message from host matches Table(0) Match: host mac and
+ * ingress port Action: set vnid and go to L2Forward Table(50).
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param inPort the ingress port of the host
+ * @param srcMac the mac of the host
+ * @param appId the application ID of the vtn
+ * @param type the operation of the flow
+ */
+ void programLocalIn(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber inPort, MacAddress srcMac,
+ ApplicationId appId, Objective.Operation type);
+
+ /**
+ * The port rule that message from tunnel Table(0) Match: tunnel port and
+ * vnid Action: go to L2Forward Table(50).
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programTunnelIn(DeviceId deviceId, SegmentationId segmentationId,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+ /**
+ * Assemble the L3 Classifier table rules which are sended from external port.
+ * Match: ipv4 type, ingress port and destination ip.
+ * Action: go to DNAT Table(20).
+ *
+ * @param deviceId Device Id
+ * @param inPort external port
+ * @param dstIp floating ip
+ * @param type the operation type of the flow rules
+ */
+ void programL3ExPortClassifierRules(DeviceId deviceId, PortNumber inPort,
+ IpAddress dstIp,
+ Objective.Operation type);
+
+ /**
+ * Assemble the L3 Classifier table rules which are sended from internal port.
+ * Match: ingress port, source mac and destination mac.
+ * Action: set vnid and go to L3Forward Table(30).
+ *
+ * @param deviceId Device Id
+ * @param inPort the ingress port of the host
+ * @param srcMac source mac
+ * @param dstMac destination vm gateway mac
+ * @param actionVni the vni of L3 network
+ * @param type the operation type of the flow rules
+ */
+ void programL3InPortClassifierRules(DeviceId deviceId,
+ PortNumber inPort, MacAddress srcMac,
+ MacAddress dstMac,
+ SegmentationId actionVni,
+ Objective.Operation type);
+
+ /**
+ * Assemble the Arp Classifier table rules.
+ * Match: arp type and destination ip.
+ * Action: set vnid and go to ARP Table(10).
+ *
+ * @param deviceId Device Id
+ * @param dstIp source gateway ip
+ * @param actionVni the vni of the source network (l2vni)
+ * @param type the operation type of the flow rules
+ */
+ void programArpClassifierRules(DeviceId deviceId, IpAddress dstIp,
+ SegmentationId actionVni,
+ Objective.Operation type);
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/DnatService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/DnatService.java
new file mode 100644
index 00000000..88c56288
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/DnatService.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * DnatService interface provides the rules in DNAT table which is Table(20) for ovs pipeline.
+ * DNAT means Destination Network Address Translation, it is acronym for network terminology.
+ * Handle the downward flows.
+ */
+public interface DnatService {
+
+ /**
+ * Assemble the DNAT table rules.
+ * Match: ipv4 type and destination ip.
+ * Action: set eth_src, set ip_dst, set vnid and goto L3Forward Table(30).
+ *
+ * @param deviceId Device Id
+ * @param dstIp floating ip
+ * @param ethSrc floating ip gateway mac
+ * @param ipDst destination vm ip
+ * @param actionVni the vni of L3 network
+ * @param type the operation type of the flow rules
+ */
+ void programRules(DeviceId deviceId, IpAddress dstIp,
+ MacAddress ethSrc, IpAddress ipDst,
+ SegmentationId actionVni, Objective.Operation type);
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java
new file mode 100644
index 00000000..cb661f8b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L2ForwardService.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * Applies L2 flows to the device. L2Forward table is Table(50).
+ */
+public interface L2ForwardService {
+
+ /**
+ * The local broadcast rule that message matches Table(50).
+ * Match: broadcast mac and vnid.
+ * Action: set output port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param inPort the ingress port of the host
+ * @param localVmPorts the local ports of the network which connect host
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programLocalBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber inPort,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+ /**
+ * The tunnel broadcast rule that message matches Table(50).
+ * Match: broadcast mac and vnid.
+ * Action: output port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param localVmPorts the local ports of the network which connect host
+ * @param localTunnelPorts the tunnel pors of the device
+ * @param type the operation of the flow
+ */
+ void programTunnelBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type);
+
+ /**
+ * The local out rule that message matches Table(50).
+ * Match: local host mac and vnid.
+ * Action: output local host port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param outPort the ingress port of the host
+ * @param sourceMac the mac of the host
+ * @param type the operation of the flow
+ */
+ void programLocalOut(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber outPort, MacAddress sourceMac,
+ Objective.Operation type);
+
+ /**
+ * The tunnel out rule that message matches Table(50).
+ * Match: host mac and vnid.
+ * Action: output tunnel port.
+ *
+ * @param deviceId Device Id
+ * @param segmentationId the vnid of the host belong to
+ * @param tunnelOutPort the port of the tunnel
+ * @param dstMac the mac of the host
+ * @param type the operation of the flow
+ * @param ipAddress the ipAddress of the node
+ */
+ void programTunnelOut(DeviceId deviceId, SegmentationId segmentationId,
+ PortNumber tunnelOutPort, MacAddress dstMac,
+ Objective.Operation type, IpAddress ipAddress);
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L3ForwardService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L3ForwardService.java
new file mode 100644
index 00000000..718253a4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/L3ForwardService.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * L3ForwardService interface provide the rules in L3Forward table which is Table(30).
+ */
+public interface L3ForwardService {
+
+ /**
+ * Assemble the L3Forward table rules.
+ * Match: ipv4 type, vnid and destination ip.
+ * Action: set eth_src, set eth_dst, set vnid and goto L2Forward Table(50).
+ *
+ * @param deviceId Device Id
+ * @param l3Vni the vni of L3 network
+ * @param dstVmIP destination vm ip
+ * @param dstVni the vni of the destination network (l2vni)
+ * @param dstVmGwMac destination VM gateway mac
+ * @param dstVmMac destination VM mac
+ * @param type the operation type of the flow rules
+ */
+ void programRouteRules(DeviceId deviceId, SegmentationId l3Vni,
+ IpAddress dstVmIP, SegmentationId dstVni,
+ MacAddress dstVmGwMac, MacAddress dstVmMac,
+ Objective.Operation type);
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/SnatService.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/SnatService.java
new file mode 100644
index 00000000..e57596ed
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/SnatService.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtnrsc.SegmentationId;
+
+/**
+ * SnatService interface provides the rules in SNAT table which is Table(40) for ovs pipeline.
+ * SNAT means Source Network Address Translation, it is acronym for network terminology.
+ * Handle the upward flows.
+ */
+public interface SnatService {
+
+ /**
+ * Assemble the SNAT table rules.
+ * Match: ipv4 type, vnid and source ip.
+ * Action: set eth_src, set eth_dst, set ip_src, set vnid and goto L2Forward Table(50).
+ *
+ * @param deviceId Device Id
+ * @param matchVni the vni of L3 network
+ * @param srcIP source ip
+ * @param ethDst external gateway mac
+ * @param ethSrc external port mac
+ * @param ipSrc floating ip
+ * @param actionVni external network VNI
+ * @param type the operation type of the flow rules
+ */
+ void programRules(DeviceId deviceId, SegmentationId matchVni,
+ IpAddress srcIP, MacAddress ethDst,
+ MacAddress ethSrc, IpAddress ipSrc,
+ SegmentationId actionVni, Objective.Operation type);
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java
new file mode 100644
index 00000000..512a1559
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/ClassifierServiceImpl.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.ClassifierService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of ClassifierService.
+ */
+public class ClassifierServiceImpl implements ClassifierService {
+ private final Logger log = getLogger(getClass());
+
+ private static final EtherType ETH_TYPE = EtherType.ARP;
+ private static final int ARP_CLASSIFIER_PRIORITY = 60000;
+ private static final int L3_CLASSIFIER_PRIORITY = 0xffff;
+ private static final int L2_CLASSIFIER_PRIORITY = 50000;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Constructor.
+ *
+ * @param appId the application id of vtn
+ */
+ public ClassifierServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programLocalIn(DeviceId deviceId,
+ SegmentationId segmentationId, PortNumber inPort,
+ MacAddress srcMac, ApplicationId appid,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(inPort).matchEthSrc(srcMac).build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.add(Instructions
+ .modTunnelId(Long.parseLong(segmentationId.toString())));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(L2_CLASSIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("programLocalIn-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("programLocalIn-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+ @Override
+ public void programTunnelIn(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localTunnelPorts == null) {
+ log.info("No tunnel port in device");
+ return;
+ }
+ Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(tp).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).makePermanent().withFlag(Flag.SPECIFIC)
+ .withPriority(L2_CLASSIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("programTunnelIn-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("programTunnelIn-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+ @Override
+ public void programL3ExPortClassifierRules(DeviceId deviceId, PortNumber inPort,
+ IpAddress dstIp,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4).matchInPort(inPort)
+ .matchIPDst(IpPrefix.valueOf(dstIp, 32)).build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(L3_CLASSIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("L3ExToInClassifierRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("L3ExToInClassifierRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+ @Override
+ public void programL3InPortClassifierRules(DeviceId deviceId, PortNumber inPort,
+ MacAddress srcMac, MacAddress dstMac,
+ SegmentationId actionVni,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(inPort).matchEthSrc(srcMac).matchEthDst(dstMac)
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setTunnelId(Long.parseLong(actionVni.segmentationId())).build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(L3_CLASSIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("L3InternalClassifierRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("L3InternalClassifierRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+ @Override
+ public void programArpClassifierRules(DeviceId deviceId, IpAddress dstIp,
+ SegmentationId actionVni,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(ETH_TYPE.ethType().toShort())
+ .matchArpTpa(Ip4Address.valueOf(dstIp.toString()))
+ .build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setTunnelId(Long.parseLong(actionVni.segmentationId()))
+ .build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(ARP_CLASSIFIER_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("ArpClassifierRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("ArpClassifierRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/DnatServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/DnatServiceImpl.java
new file mode 100644
index 00000000..7b8d42fa
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/DnatServiceImpl.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.DnatService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of DnatService.
+ */
+public class DnatServiceImpl implements DnatService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int DNAT_PRIORITY = 0xffff;
+ private static final int PREFIX_LENGTH = 32;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Construct a DnatServiceImpl object.
+ *
+ * @param appId the application id of vtn
+ */
+ public DnatServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programRules(DeviceId deviceId, IpAddress dstIp,
+ MacAddress ethSrc, IpAddress ipDst,
+ SegmentationId actionVni, Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchIPDst(IpPrefix.valueOf(dstIp, PREFIX_LENGTH)).build();
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.setEthSrc(ethSrc).setIpDst(ipDst)
+ .setTunnelId(Long.parseLong(actionVni.segmentationId()));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(DNAT_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("RouteRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("RouteRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java
new file mode 100644
index 00000000..3581cf6e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L2ForwardServiceImpl.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.flow.instructions.ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.ExtensionTreatmentResolver;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.TrafficTreatment.Builder;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.L2ForwardService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of L2ForwardService.
+ */
+public final class L2ForwardServiceImpl implements L2ForwardService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int MAC_PRIORITY = 0xffff;
+ public static final Integer GROUP_ID = 1;
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+ private final DriverService driverService;
+ /**
+ * Constructor.
+ *
+ * @param appId the application id of vtn
+ */
+ public L2ForwardServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ this.driverService = serviceDirectory.get(DriverService.class);
+ }
+
+ @Override
+ public void programLocalBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber inPort,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localVmPorts == null || localTunnelPorts == null) {
+ log.info("No other host port and tunnel in the device");
+ return;
+ }
+ Sets.newHashSet(localVmPorts).stream().forEach(lp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(lp).matchEthDst(MacAddress.BROADCAST)
+ .add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+ .builder();
+ boolean flag = false;
+ for (PortNumber outPort : localVmPorts) {
+ flag = true;
+ if (outPort != lp) {
+ treatment.setOutput(outPort);
+ }
+ }
+ if (type.equals(Objective.Operation.REMOVE) && inPort == lp) {
+ flag = false;
+ }
+ treatment.group(new DefaultGroupId(GROUP_ID));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
+ if (flag) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+ @Override
+ public void programTunnelBcastRules(DeviceId deviceId,
+ SegmentationId segmentationId,
+ Iterable<PortNumber> localVmPorts,
+ Iterable<PortNumber> localTunnelPorts,
+ Objective.Operation type) {
+ if (localVmPorts == null || localTunnelPorts == null) {
+ log.info("No other host port or tunnel ports in the device");
+ return;
+ }
+ Sets.newHashSet(localTunnelPorts).stream().forEach(tp -> {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchInPort(tp)
+ .add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .matchEthDst(MacAddress.BROADCAST).build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment
+ .builder();
+
+ for (PortNumber outPort : localVmPorts) {
+ treatment.setOutput(outPort);
+ }
+
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).makePermanent()
+ .withFlag(Flag.SPECIFIC).withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ if (Sets.newHashSet(localVmPorts).size() == 0) {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.add());
+ }
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ });
+ }
+
+ @Override
+ public void programLocalOut(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber outPort, MacAddress sourceMac,
+ Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchTunnelId(Long.parseLong(segmentationId.toString()))
+ .matchEthDst(sourceMac).build();
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(outPort).build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+
+ }
+
+ @Override
+ public void programTunnelOut(DeviceId deviceId,
+ SegmentationId segmentationId,
+ PortNumber tunnelOutPort, MacAddress dstMac,
+ Objective.Operation type, IpAddress ipAddress) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthDst(dstMac).add(Criteria.matchTunnelId(Long
+ .parseLong(segmentationId.toString())))
+ .build();
+
+ DriverHandler handler = driverService.createHandler(deviceId);
+ ExtensionTreatmentResolver resolver = handler.behaviour(ExtensionTreatmentResolver.class);
+ ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
+ try {
+ treatment.setPropertyValue("tunnelDst", Ip4Address.valueOf(ipAddress.toString()));
+ } catch (Exception e) {
+ log.error("Failed to get extension instruction to set tunnel dst {}", deviceId);
+ }
+
+ Builder builder = DefaultTrafficTreatment.builder();
+ builder.extension(treatment, deviceId)
+ .setOutput(tunnelOutPort).build();
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(builder.build()).withSelector(selector)
+ .fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(MAC_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L3ForwardServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L3ForwardServiceImpl.java
new file mode 100644
index 00000000..cf97e76d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/L3ForwardServiceImpl.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.Objective.Operation;
+import org.onosproject.vtn.table.L3ForwardService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of L3ForwardService.
+ */
+public class L3ForwardServiceImpl implements L3ForwardService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int L3FWD_PRIORITY = 0xffff;
+ private static final short IP_TYPE = Ethernet.TYPE_IPV4;
+ private static final int PREFIX_LENGTH = 32;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Construct a L3ForwardServiceImpl object.
+ *
+ * @param appId the application id of vtn
+ */
+ public L3ForwardServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programRouteRules(DeviceId deviceId, SegmentationId l3Vni,
+ IpAddress dstVmIP, SegmentationId dstVni,
+ MacAddress dstVmGwMac, MacAddress dstVmMac,
+ Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(IP_TYPE)
+ .matchTunnelId(Long.parseLong(l3Vni.segmentationId()))
+ .matchIPDst(IpPrefix.valueOf(dstVmIP, PREFIX_LENGTH)).build();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.setEthSrc(dstVmGwMac)
+ .setEthDst(dstVmMac)
+ .add(Instructions.modTunnelId(Long.parseLong(dstVni
+ .segmentationId())));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(L3FWD_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("RouteRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("RouteRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/SnatServiceImpl.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/SnatServiceImpl.java
new file mode 100644
index 00000000..0f090954
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/SnatServiceImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.table.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.vtn.table.SnatService;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of SnatService.
+ */
+public class SnatServiceImpl implements SnatService {
+ private final Logger log = getLogger(getClass());
+
+ private static final int SNAT_PRIORITY = 0xffff;
+ private static final int PREFIC_LENGTH = 32;
+
+ private final FlowObjectiveService flowObjectiveService;
+ private final ApplicationId appId;
+
+ /**
+ * Construct a SnatServiceImpl object.
+ *
+ * @param appId the application id of vtn
+ */
+ public SnatServiceImpl(ApplicationId appId) {
+ this.appId = checkNotNull(appId, "ApplicationId can not be null");
+ ServiceDirectory serviceDirectory = new DefaultServiceDirectory();
+ this.flowObjectiveService = serviceDirectory.get(FlowObjectiveService.class);
+ }
+
+ @Override
+ public void programRules(DeviceId deviceId, SegmentationId matchVni,
+ IpAddress srcIP, MacAddress ethDst,
+ MacAddress ethSrc, IpAddress ipSrc,
+ SegmentationId actionVni, Objective.Operation type) {
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthType(Ethernet.TYPE_IPV4)
+ .matchTunnelId(Long.parseLong(matchVni.segmentationId()))
+ .matchIPSrc(IpPrefix.valueOf(srcIP, PREFIC_LENGTH)).build();
+
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.setEthDst(ethDst).setEthSrc(ethSrc).setIpSrc(ipSrc)
+ .setTunnelId(Long.parseLong(actionVni.segmentationId()));
+ ForwardingObjective.Builder objective = DefaultForwardingObjective
+ .builder().withTreatment(treatment.build())
+ .withSelector(selector).fromApp(appId).withFlag(Flag.SPECIFIC)
+ .withPriority(SNAT_PRIORITY);
+ if (type.equals(Objective.Operation.ADD)) {
+ log.debug("RouteRules-->ADD");
+ flowObjectiveService.forward(deviceId, objective.add());
+ } else {
+ log.debug("RouteRules-->REMOVE");
+ flowObjectiveService.forward(deviceId, objective.remove());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java
new file mode 100644
index 00000000..fd2e18e5
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.table.impl;
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java
new file mode 100644
index 00000000..cf53c966
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/table/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.table;
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/DataPathIdGenerator.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/DataPathIdGenerator.java
new file mode 100644
index 00000000..c2413475
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/DataPathIdGenerator.java
@@ -0,0 +1,64 @@
+package org.onosproject.vtn.util;
+
+import static org.onlab.util.Tools.toHex;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Calendar;
+
+import org.onosproject.core.IdGenerator;
+import org.onosproject.net.DeviceId;
+
+public final class DataPathIdGenerator implements IdGenerator {
+ private static final String SCHEME = "of";
+ private String ipAddress;
+ private String timeStamp;
+
+ private DataPathIdGenerator(Builder builder) {
+ this.ipAddress = builder.ipAddress;
+ Calendar cal = Calendar.getInstance();
+ this.timeStamp = String.valueOf(cal.get(Calendar.SECOND))
+ + String.valueOf(cal.get(Calendar.MILLISECOND));
+ }
+
+ @Override
+ public long getNewId() {
+ String dpid = ipAddress.replace(".", "") + timeStamp;
+ return Long.parseLong(dpid);
+ }
+
+ public String getDpId() {
+ return toHex(getNewId());
+ }
+
+ public DeviceId getDeviceId() {
+ try {
+ URI uri = new URI(SCHEME, toHex(getNewId()), null);
+ return DeviceId.deviceId(uri);
+ } catch (URISyntaxException e) {
+ return null;
+ }
+ }
+
+ /**
+ * Returns a new builder.
+ *
+ * @return new builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ public static final class Builder {
+ private String ipAddress;
+
+ public Builder addIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ return this;
+ }
+
+ public DataPathIdGenerator build() {
+ return new DataPathIdGenerator(this);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
new file mode 100644
index 00000000..5ac04661
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnConfig.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.util;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeName;
+import org.onosproject.net.behaviour.DefaultTunnelDescription;
+import org.onosproject.net.behaviour.IpTunnelEndPoint;
+import org.onosproject.net.behaviour.TunnelConfig;
+import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.net.behaviour.TunnelEndPoint;
+import org.onosproject.net.behaviour.TunnelName;
+import org.onosproject.net.driver.DriverHandler;
+
+/**
+ * Applies configuration to the device.
+ */
+public final class VtnConfig {
+
+ private static final String DEFAULT_BRIDGE_NAME = "br-int";
+ private static final String DEFAULT_TUNNEL = "vxlan-0.0.0.0";
+ private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
+ {
+ put("key", "flow");
+ put("remote_ip", "flow");
+ }
+ };
+ /**
+ * Constructs a vtn config object. Utility classes should not have a
+ * public or default constructor, otherwise IDE will compile unsuccessfully. This
+ * class should not be instantiated.
+ */
+ private VtnConfig() {
+ }
+
+ /**
+ * Creates or update bridge in the controller device.
+ *
+ * @param handler DriverHandler
+ * @param dpid datapath id
+ * @param exPortName external port name
+ */
+ public static void applyBridgeConfig(DriverHandler handler, String dpid, String exPortName) {
+ BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+ bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, exPortName);
+ }
+
+ /**
+ * Creates or update tunnel in the controller device.
+ *
+ * @param handler DriverHandler
+ * @param srcIp the ipAddress of the local controller device
+ * @param dstIp the ipAddress of the remote controller device
+ */
+ public static void applyTunnelConfig(DriverHandler handler, IpAddress srcIp,
+ IpAddress dstIp) {
+ DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
+ for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
+ optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
+ }
+ TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
+ TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
+ TunnelDescription tunnel = new DefaultTunnelDescription(
+ tunnelAsSrc,
+ null,
+ TunnelDescription.Type.VXLAN,
+ TunnelName.tunnelName(DEFAULT_TUNNEL),
+ optionBuilder.build());
+ tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), tunnel);
+ }
+
+ /**
+ * Creates or update tunnel in the controller device.
+ *
+ * @param handler DriverHandler
+ * @param srcIp the ipAddress of the local controller device
+ * @param dstIp the ipAddress of the remote controller device
+ */
+ public static void removeTunnelConfig(DriverHandler handler, IpAddress srcIp,
+ IpAddress dstIp) {
+ TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
+ TunnelEndPoint tunnelAsSrc = IpTunnelEndPoint.ipTunnelPoint(srcIp);
+ TunnelEndPoint tunnelAsDst = IpTunnelEndPoint.ipTunnelPoint(dstIp);
+ TunnelDescription tunnel = new DefaultTunnelDescription(
+ tunnelAsSrc,
+ tunnelAsDst,
+ TunnelDescription.Type.VXLAN,
+ null);
+ tunnelConfig.removeTunnel(tunnel);
+ }
+
+ /**
+ * Gets ports in the controller device.
+ *
+ * @param handler DriverHandler
+ * @return set of port numbers
+ */
+ public static Set<PortNumber> getPortNumbers(DriverHandler handler) {
+ BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+ return bridgeConfig.getPortNumbers();
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java
new file mode 100644
index 00000000..a8562e7f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/VtnData.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtn.util;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+import org.onosproject.net.AnnotationKeys;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+/**
+ * VtnData utility class.
+ */
+public final class VtnData {
+
+ private static final Logger log = LoggerFactory.getLogger(VtnData.class);
+ private static final String SWITCH_CHANNEL_ID = "channelId";
+ private static final String PORT_HEAD = "vxlan";
+
+ /**
+ * Constructs a VtnData object. Utility classes should not have a public or
+ * default constructor, otherwise IDE will compile unsuccessfully. This
+ * class should not be instantiated.
+ */
+ private VtnData() {
+ }
+
+ /**
+ * Get the ControllerIp from the device .
+ *
+ * @param device Device
+ * @return Controller Ip
+ */
+ public static String getControllerIpOfSwitch(Device device) {
+ String url = device.annotations().value(SWITCH_CHANNEL_ID);
+ return url.substring(0, url.lastIndexOf(":"));
+ }
+
+ /**
+ * Get the ControllerId from the device .
+ *
+ * @param device Device
+ * @param devices Devices
+ * @return Controller Id
+ */
+ public static DeviceId getControllerId(Device device,
+ Iterable<Device> devices) {
+ for (Device d : devices) {
+ if (d.type() == Device.Type.CONTROLLER && d.id().toString()
+ .contains(getControllerIpOfSwitch(device))) {
+ return d.id();
+ }
+ }
+ log.info("Can not find controller for device : {}", device.id());
+ return null;
+ }
+
+ /**
+ * Get local tunnel ports.
+ *
+ * @param ports Iterable of Port
+ * @return Collection of PortNumber
+ */
+ public static Collection<PortNumber> getLocalTunnelPorts(Iterable<Port> ports) {
+ Collection<PortNumber> localTunnelPorts = new ArrayList<>();
+ Sets.newHashSet(ports).stream()
+ .filter(p -> !p.number().equals(PortNumber.LOCAL))
+ .forEach(p -> {
+ if (p.annotations().value(AnnotationKeys.PORT_NAME)
+ .startsWith(PORT_HEAD)) {
+ localTunnelPorts.add(p.number());
+ }
+ });
+ return localTunnelPorts;
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/package-info.java b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/package-info.java
new file mode 100644
index 00000000..213b9e28
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/util/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * VTN application that applies configuration and flows to the device.
+ */
+package org.onosproject.vtn.util;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFloatingIp.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFloatingIp.java
new file mode 100644
index 00000000..7a297d90
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFloatingIp.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Default implementation of FloatingIp interface.
+ */
+public final class DefaultFloatingIp implements FloatingIp {
+
+ private final FloatingIpId id;
+ private final TenantId tenantId;
+ private final TenantNetworkId networkId;
+ private final VirtualPortId portId;
+ private final RouterId routerId;
+ private final IpAddress floatingIp;
+ private final IpAddress fixedIp;
+ private final Status status;
+
+ /**
+ *
+ * Creates a floating Ip object.
+ *
+ * @param id floatingIp identifier
+ * @param tenantId tenant identifier
+ * @param networkId the identifier of network associated with the floating Ip
+ * @param portId port identifier
+ * @param routerId router identifier
+ * @param floatingIp floatingIp address
+ * @param fixedIp the fixed Ip associated with the floating Ip
+ * @param status the floating Ip status
+ */
+ public DefaultFloatingIp(FloatingIpId id, TenantId tenantId,
+ TenantNetworkId networkId, VirtualPortId portId,
+ RouterId routerId, IpAddress floatingIp,
+ IpAddress fixedIp, Status status) {
+ this.id = checkNotNull(id, "id cannot be null");
+ this.tenantId = checkNotNull(tenantId, "tenantId cannot be null");
+ this.networkId = checkNotNull(networkId, "networkId cannot be null");
+ this.portId = portId;
+ this.routerId = routerId;
+ this.floatingIp = checkNotNull(floatingIp, "floatingIp cannot be null");
+ this.fixedIp = fixedIp;
+ this.status = checkNotNull(status, "status cannot be null");
+ }
+
+ @Override
+ public FloatingIpId id() {
+ return id;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public TenantNetworkId networkId() {
+ return networkId;
+ }
+
+ @Override
+ public VirtualPortId portId() {
+ return portId;
+ }
+
+ @Override
+ public RouterId routerId() {
+ return routerId;
+ }
+
+ @Override
+ public IpAddress floatingIp() {
+ return floatingIp;
+ }
+
+ @Override
+ public IpAddress fixedIp() {
+ return fixedIp;
+ }
+
+ @Override
+ public Status status() {
+ return status;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, tenantId, networkId, portId, routerId,
+ floatingIp, fixedIp, status);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultFloatingIp) {
+ final DefaultFloatingIp that = (DefaultFloatingIp) obj;
+ return Objects.equals(this.id, that.id)
+ && Objects.equals(this.tenantId, that.tenantId)
+ && Objects.equals(this.networkId, that.networkId)
+ && Objects.equals(this.portId, that.portId)
+ && Objects.equals(this.routerId, that.routerId)
+ && Objects.equals(this.floatingIp, that.floatingIp)
+ && Objects.equals(this.fixedIp, that.fixedIp)
+ && Objects.equals(this.status, that.status);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("id", id).add("tenantId", tenantId)
+ .add("networkId", networkId).add("portId", portId)
+ .add("routerId", routerId).add("floatingIp", floatingIp)
+ .add("fixedIp", fixedIp).add("floatingIpStatus", status)
+ .toString();
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java
new file mode 100644
index 00000000..a2404f56
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Default implementation of router interface.
+ */
+public final class DefaultRouter implements Router {
+ private final RouterId id;
+ private final String name;
+ private final boolean adminStateUp;
+ private final Status status;
+ private final boolean distributed;
+ private final RouterGateway externalGatewayInfo;
+ private final VirtualPortId gatewayPortId;
+ private final TenantId tenantId;
+ private final List<String> routes;
+
+ /**
+ * Creates router object.
+ *
+ * @param id router identifier
+ * @param routerName the name of router
+ * @param adminStateUp the status of admin state
+ * @param status the status of router
+ * @param distributed the status of router distributed
+ * @param externalGatewayInfo the gateway info of router
+ * @param gatewayPortId the port identifier of router gateway
+ * @param tenantId the tenant identifier
+ * @param routes the routes configure
+ */
+ public DefaultRouter(RouterId id, String routerName, boolean adminStateUp,
+ Status status, boolean distributed,
+ RouterGateway externalGatewayInfo,
+ VirtualPortId gatewayPortId, TenantId tenantId,
+ List<String> routes) {
+ this.id = checkNotNull(id, "id cannot be null");
+ this.name = routerName;
+ this.adminStateUp = checkNotNull(adminStateUp, "adminStateUp cannot be null");
+ this.status = checkNotNull(status, "status cannot be null");
+ this.distributed = checkNotNull(distributed, "distributed cannot be null");
+ this.externalGatewayInfo = externalGatewayInfo;
+ this.gatewayPortId = gatewayPortId;
+ this.tenantId = checkNotNull(tenantId, "tenantId cannot be null");
+ this.routes = routes;
+ }
+
+ @Override
+ public RouterId id() {
+ return id;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public boolean adminStateUp() {
+ return adminStateUp;
+ }
+
+ @Override
+ public Status status() {
+ return status;
+ }
+
+ @Override
+ public boolean distributed() {
+ return distributed;
+ }
+
+ @Override
+ public RouterGateway externalGatewayInfo() {
+ return externalGatewayInfo;
+ }
+
+ @Override
+ public VirtualPortId gatewayPortid() {
+ return gatewayPortId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public List<String> routes() {
+ return routes;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, name, adminStateUp, status, distributed,
+ externalGatewayInfo, gatewayPortId, routes);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultRouter) {
+ final DefaultRouter that = (DefaultRouter) obj;
+ return Objects.equals(this.id, that.id)
+ && Objects.equals(this.name, that.name)
+ && Objects.equals(this.adminStateUp, that.adminStateUp)
+ && Objects.equals(this.status, that.status)
+ && Objects.equals(this.distributed, that.distributed)
+ && Objects.equals(this.externalGatewayInfo,
+ that.externalGatewayInfo)
+ && Objects.equals(this.gatewayPortId, that.gatewayPortId)
+ && Objects.equals(this.routes, that.routes);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("id", id).add("routerName", name)
+ .add("adminStateUp", adminStateUp).add("status", status)
+ .add("distributed", distributed)
+ .add("externalGatewayInfo", externalGatewayInfo)
+ .add("gatewayPortid", gatewayPortId).add("routes", routes).toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIp.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIp.java
new file mode 100644
index 00000000..0933d9ef
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIp.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.onlab.packet.IpAddress;
+
+/**
+ * Representation of a floatingIp.
+ */
+public interface FloatingIp {
+
+ /**
+ * Coarse classification of the type of the FloatingIp.
+ */
+ public enum Status {
+ /**
+ * Signifies that a floating Ip is currently active.
+ */
+ ACTIVE,
+ /**
+ * Signifies that a floating Ip is currently inactive.
+ */
+ INACTIVE
+ }
+
+ /**
+ * Returns the floatingIp identifier.
+ *
+ * @return identifier
+ */
+ FloatingIpId id();
+
+ /**
+ * Returns the tenant identifier.
+ *
+ * @return the tenant identifier
+ */
+ TenantId tenantId();
+
+ /**
+ * Returns the network identifier.
+ *
+ * @return the network identifier
+ */
+ TenantNetworkId networkId();
+
+ /**
+ * Returns the port identifier.
+ *
+ * @return the port identifier
+ */
+ VirtualPortId portId();
+
+ /**
+ * Returns the router identifier.
+ *
+ * @return the router identifier
+ */
+ RouterId routerId();
+
+ /**
+ * Returns the floating ip address.
+ *
+ * @return floatingIp
+ */
+ IpAddress floatingIp();
+
+ /**
+ * Returns the fixed ip address.
+ *
+ * @return fixedIp
+ */
+ IpAddress fixedIp();
+
+ /**
+ * Returns the status of floating ip.
+ *
+ * @return floatingIpStatus
+ */
+ Status status();
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIpId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIpId.java
new file mode 100644
index 00000000..1b48c7d6
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FloatingIpId.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+import java.util.UUID;
+
+/**
+ * Immutable representation of a floating IP identifier.
+ */
+public final class FloatingIpId {
+ private final UUID floatingIpId;
+
+ // Public construction is prohibited
+ private FloatingIpId(UUID floatingIpId) {
+ this.floatingIpId = checkNotNull(floatingIpId, "floatingIpId cannot be null");
+ }
+
+ /**
+ * Creates a floating IP identifier.
+ *
+ * @param floatingIpId the UUID id of floating IP identifier
+ * @return object of floating IP identifier
+ */
+ public static FloatingIpId of(UUID floatingIpId) {
+ return new FloatingIpId(floatingIpId);
+ }
+
+ /**
+ * Creates a floating IP identifier.
+ *
+ * @param floatingIpId the floating IP identifier in string
+ * @return object of floating IP identifier
+ */
+ public static FloatingIpId of(String floatingIpId) {
+ return new FloatingIpId(UUID.fromString(floatingIpId));
+ }
+
+ /**
+ * Returns the floating IP identifier.
+ *
+ * @return the floating IP identifier
+ */
+ public UUID floatingIpId() {
+ return floatingIpId;
+ }
+
+ @Override
+ public int hashCode() {
+ return floatingIpId.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof FloatingIpId) {
+ final FloatingIpId that = (FloatingIpId) obj;
+ return Objects.equals(this.floatingIpId, that.floatingIpId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("floatingIpId", floatingIpId).toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterInterface.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterInterface.java
new file mode 100644
index 00000000..5c37c30b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterInterface.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Objects;
+
+/**
+ * Representation of a Router interface.
+ */
+public final class RouterInterface {
+ private final SubnetId subnetId;
+ private final VirtualPortId portId;
+ private final RouterId routerId;
+ private final TenantId tenantId;
+
+ // Public construction is prohibited
+ private RouterInterface(SubnetId subnetId, VirtualPortId portId,
+ RouterId routerId, TenantId tenantId) {
+ this.subnetId = checkNotNull(subnetId, "subnetId cannot be null");
+ this.portId = checkNotNull(portId, "portId cannot be null");
+ this.routerId = checkNotNull(routerId, "routerId cannot be null");
+ this.tenantId = checkNotNull(tenantId, "tenantId cannot be null");
+ }
+
+ /**
+ * Creates router interface object.
+ *
+ * @param subnetId subnet identifier
+ * @param portId port identifier
+ * @param routerId router identifier
+ * @param tenantId tenant identifier
+ * @return RouterInterface
+ */
+ public static RouterInterface routerInterface(SubnetId subnetId,
+ VirtualPortId portId,
+ RouterId routerId,
+ TenantId tenantId) {
+ return new RouterInterface(subnetId, portId, routerId, tenantId);
+ }
+
+ /**
+ * Returns subnet identifier.
+ *
+ * @return subnetId the subnet identifier
+ */
+ public SubnetId subnetId() {
+ return subnetId;
+ }
+
+ /**
+ * Returns port identifier.
+ *
+ * @return portId the port identifier
+ */
+ public VirtualPortId portId() {
+ return portId;
+ }
+
+ /**
+ * Returns router identifier.
+ *
+ * @return routerId the router identifier
+ */
+ public RouterId routerId() {
+ return routerId;
+ }
+
+ /**
+ * Returns tenant identifier.
+ *
+ * @return tenantId the tenant identifier
+ */
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(subnetId, portId, routerId, tenantId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof RouterInterface) {
+ final RouterInterface that = (RouterInterface) obj;
+ return Objects.equals(this.subnetId, that.subnetId)
+ && Objects.equals(this.portId, that.portId)
+ && Objects.equals(this.routerId, that.routerId)
+ && Objects.equals(this.tenantId, that.tenantId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this).add("subnetId", subnetId)
+ .add("portId", portId).add("routerId", routerId)
+ .add("tenantId", tenantId).toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpCreateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpCreateCommand.java
new file mode 100644
index 00000000..00758dd2
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpCreateCommand.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.floatingip;
+
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.DefaultFloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIp.Status;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for create a floating IP.
+ */
+@Command(scope = "onos", name = "floatingip-create",
+ description = "Supports for creating a floating IP")
+public class FloatingIpCreateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "id", description = "The floating IP identifier",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Argument(index = 1, name = "networkId", description = "The network identifier of floating IP",
+ required = true, multiValued = false)
+ String networkId = null;
+
+ @Argument(index = 2, name = "tenantId", description = "The tenant identifier of floating IP",
+ required = true, multiValued = false)
+ String tenantId = null;
+
+ @Argument(index = 3, name = "routerId", description = "The router identifier of floating IP",
+ required = true, multiValued = false)
+ String routerId = null;
+
+ @Argument(index = 4, name = "fixedIp", description = "The fixed IP of floating IP",
+ required = true, multiValued = false)
+ String fixedIp = null;
+
+ @Argument(index = 5, name = "floatingIp", description = "The floating IP of floating IP",
+ required = true, multiValued = false)
+ String floatingIp = null;
+
+ @Option(name = "-p", aliases = "--portId", description = "The port identifier of floating IP",
+ required = false, multiValued = false)
+ String portId = null;
+
+ @Option(name = "-s", aliases = "--status", description = "The status of floating IP",
+ required = false, multiValued = false)
+ String status = null;
+
+ @Override
+ protected void execute() {
+ FloatingIpService service = get(FloatingIpService.class);
+ try {
+ FloatingIp floatingIpObj = new DefaultFloatingIp(
+ FloatingIpId.of(id),
+ TenantId.tenantId(tenantId),
+ TenantNetworkId.networkId(networkId),
+ VirtualPortId.portId(portId),
+ RouterId.valueOf(routerId),
+ floatingIp == null ? null : IpAddress.valueOf(floatingIp),
+ fixedIp == null ? null : IpAddress.valueOf(fixedIp),
+ status == null ? Status.ACTIVE
+ : Status.valueOf(status));
+ Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIpObj);
+ service.createFloatingIps(floatingIpSet);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpQueryCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpQueryCommand.java
new file mode 100644
index 00000000..c441d535
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpQueryCommand.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.floatingip;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+
+/**
+ * Supports for query a floating IP.
+ */
+@Command(scope = "onos", name = "floatingips", description = "Supports for querying a floating IP")
+public class FloatingIpQueryCommand extends AbstractShellCommand {
+ @Option(name = "-I", aliases = "--id", description = "The floating IP identifier",
+ required = false, multiValued = false)
+ String id = null;
+
+ @Option(name = "-i", aliases = "--fixedIp", description = "The fixed IP of floating IP",
+ required = false, multiValued = false)
+ String fixedIp = null;
+
+ @Option(name = "-l", aliases = "--floatingIp", description = "The floating IP of floating IP",
+ required = false, multiValued = false)
+ String floatingIp = null;
+
+ private static final String FMT = "floatingIpId=%s, networkId=%s, tenantId=%s, portId=%s,"
+ + "routerId=%s, fixedIp=%s, floatingIp=%s, status=%s";
+
+ @Override
+ protected void execute() {
+ FloatingIpService service = get(FloatingIpService.class);
+ if (id != null) {
+ FloatingIp floatingIp = service.getFloatingIp(FloatingIpId
+ .of(id));
+ printFloatingIp(floatingIp);
+ } else if (fixedIp != null || floatingIp != null) {
+ Iterable<FloatingIp> floatingIps = service.getFloatingIps();
+ if (floatingIps == null) {
+ return;
+ }
+ if (fixedIp != null) {
+ for (FloatingIp floatingIp : floatingIps) {
+ if (floatingIp.fixedIp().toString().equals(fixedIp)) {
+ printFloatingIp(floatingIp);
+ return;
+ }
+ }
+ print(null, "The fixedIp is not existed");
+ }
+ if (floatingIp != null) {
+ for (FloatingIp floatingIpObj : floatingIps) {
+ if (floatingIpObj.fixedIp().toString().equals(floatingIp)) {
+ printFloatingIp(floatingIpObj);
+ return;
+ }
+ }
+ print(null, "The floatingIp is not existed");
+ }
+ } else {
+ Iterable<FloatingIp> floatingIps = service.getFloatingIps();
+ if (floatingIps == null) {
+ return;
+ }
+ for (FloatingIp floatingIp : floatingIps) {
+ printFloatingIp(floatingIp);
+ }
+ }
+ }
+
+ private void printFloatingIp(FloatingIp floatingIp) {
+ print(FMT, floatingIp.id(), floatingIp.networkId(),
+ floatingIp.tenantId(), floatingIp.portId(),
+ floatingIp.routerId(), floatingIp.fixedIp(),
+ floatingIp.floatingIp(), floatingIp.status());
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpRemoveCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpRemoveCommand.java
new file mode 100644
index 00000000..a413503a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpRemoveCommand.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.floatingip;
+
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for remove a floating IP.
+ */
+@Command(scope = "onos", name = "floatingip-remove", description = "Supports for removing a floating IP")
+public class FloatingIpRemoveCommand extends AbstractShellCommand {
+ @Option(name = "-I", aliases = "--id", description = "The floating IP identifier",
+ required = false, multiValued = false)
+ String id = null;
+
+ @Option(name = "-i", aliases = "--fixedIp", description = "The fixed IP of floating IP",
+ required = false, multiValued = false)
+ String fixedIp = null;
+
+ @Option(name = "-l", aliases = "--floatingIp", description = "The floating IP of floating IP",
+ required = false, multiValued = false)
+ String floatingIp = null;
+
+ @Override
+ protected void execute() {
+ FloatingIpService service = get(FloatingIpService.class);
+ if (id == null && fixedIp == null && floatingIp == null) {
+ print(null, "one of id, fixedIp, floatingIp should not be null");
+ }
+ try {
+ Set<FloatingIpId> floatingIpSet = Sets.newHashSet();
+ if (id != null) {
+ floatingIpSet.add(FloatingIpId.of(id));
+ service.removeFloatingIps(floatingIpSet);
+ } else {
+ Iterable<FloatingIp> floatingIps = service.getFloatingIps();
+ if (floatingIps == null) {
+ return;
+ }
+ if (fixedIp != null) {
+ for (FloatingIp floatingIp : floatingIps) {
+ if (floatingIp.fixedIp().toString().equals(fixedIp)) {
+ floatingIpSet.add(floatingIp.id());
+ service.removeFloatingIps(floatingIpSet);
+ return;
+ }
+ }
+ print(null, "The fixedIp is not existed");
+ return;
+ }
+ if (floatingIp != null) {
+ for (FloatingIp floatingIpObj : floatingIps) {
+ if (floatingIpObj.fixedIp().toString()
+ .equals(floatingIp)) {
+ floatingIpSet.add(floatingIpObj.id());
+ service.removeFloatingIps(floatingIpSet);
+ return;
+ }
+ }
+ print(null, "The floatingIp is not existed");
+ return;
+ }
+ }
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpUpdateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpUpdateCommand.java
new file mode 100644
index 00000000..413b3bdb
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/FloatingIpUpdateCommand.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.floatingip;
+
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.DefaultFloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIp.Status;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for update a floating IP.
+ */
+@Command(scope = "onos", name = "floatingip-update",
+ description = "Supports for updating a floating IP")
+public class FloatingIpUpdateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "id", description = "The floating IP identifier",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Option(name = "-n", aliases = "--networkId", description = "The network identifier of floating IP",
+ required = false, multiValued = false)
+ String networkId = null;
+
+ @Option(name = "-t", aliases = "--tenantId", description = "The tenant identifier of floating IP",
+ required = false, multiValued = false)
+ String tenantId = null;
+
+ @Option(name = "-r", aliases = "--routerId", description = "The router identifier of floating IP",
+ required = false, multiValued = false)
+ String routerId = null;
+
+ @Option(name = "-p", aliases = "--portId", description = "The port identifier of floating IP",
+ required = false, multiValued = false)
+ String portId = null;
+
+ @Option(name = "-s", aliases = "--status", description = "The status of floating IP",
+ required = false, multiValued = false)
+ String status = null;
+
+ @Option(name = "-i", aliases = "--fixedIp", description = "The fixed IP of floating IP",
+ required = false, multiValued = false)
+ String fixedIp = null;
+
+ @Option(name = "-l", aliases = "--floatingIp", description = "The floating IP of floating IP",
+ required = false, multiValued = false)
+ String floatingIp = null;
+
+ @Override
+ protected void execute() {
+ FloatingIpService service = get(FloatingIpService.class);
+ FloatingIpId floatingIpId = FloatingIpId.of(id);
+ FloatingIp floatingIpStore = get(FloatingIpService.class).getFloatingIp(floatingIpId);
+ try {
+ FloatingIp floatingIpObj = new DefaultFloatingIp(
+ floatingIpId,
+ tenantId == null ? floatingIpStore.tenantId()
+ : TenantId.tenantId(tenantId),
+ networkId == null ? floatingIpStore.networkId()
+ : TenantNetworkId.networkId(networkId),
+ portId == null ? floatingIpStore.portId()
+ : VirtualPortId.portId(portId),
+ routerId == null ? floatingIpStore.routerId()
+ : RouterId.valueOf(routerId),
+ floatingIp == null ? floatingIpStore.floatingIp()
+ : IpAddress.valueOf(floatingIp),
+ fixedIp == null ? floatingIpStore.fixedIp()
+ : IpAddress.valueOf(fixedIp),
+ status == null ? floatingIpStore.status()
+ : Status.valueOf(status));
+ Set<FloatingIp> floatingIpSet = Sets.newHashSet(floatingIpObj);
+ service.updateFloatingIps(floatingIpSet);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/package-info.java
new file mode 100644
index 00000000..ac560771
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/floatingip/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Command line interface for floatingIP.
+ */
+package org.onosproject.vtnrsc.cli.floatingip;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterCreateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterCreateCommand.java
new file mode 100644
index 00000000..3a736deb
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterCreateCommand.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.router;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.DefaultRouter;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.Router.Status;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.router.RouterService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for create a router.
+ */
+@Command(scope = "onos", name = "router-create",
+ description = "Supports for creating a router")
+public class RouterCreateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "id", description = "The router identifier",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Argument(index = 1, name = "routerName", description = "The name of router",
+ required = true, multiValued = false)
+ String routerName = null;
+
+ @Argument(index = 2, name = "tenantId", description = "The tenant identifier of router",
+ required = true, multiValued = false)
+ String tenantId = null;
+
+ @Option(name = "-g", aliases = "--gatewayPortId", description = "The gatewayPort identifier of router",
+ required = false, multiValued = false)
+ String gatewayPortId = null;
+
+ @Option(name = "-e", aliases = "--externalGatewayInfo", description = "The external gateway info of router",
+ required = false, multiValued = false)
+ String externalGatewayInfo = null;
+
+ @Option(name = "-s", aliases = "--status", description = "The status of router",
+ required = false, multiValued = false)
+ String status = null;
+
+ @Option(name = "-a", aliases = "--adminStateUp", description = "The boolean adminStateUp of router",
+ required = false, multiValued = false)
+ boolean adminStateUp = true;
+
+ @Option(name = "-d", aliases = "--distributed", description = "The boolean distributed of router",
+ required = false, multiValued = false)
+ boolean distributed = false;
+
+ @Override
+ protected void execute() {
+ RouterService service = get(RouterService.class);
+ try {
+ List<String> routes = new ArrayList<String>();
+ Router router = new DefaultRouter(
+ RouterId.valueOf(id),
+ routerName,
+ adminStateUp,
+ status == null ? Status.ACTIVE
+ : Status.valueOf(status),
+ distributed,
+ null,
+ VirtualPortId.portId(gatewayPortId),
+ TenantId.tenantId(tenantId),
+ routes);
+ Set<Router> routerSet = Sets.newHashSet(router);
+ service.createRouters(routerSet);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterQueryCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterQueryCommand.java
new file mode 100644
index 00000000..a8a4b585
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterQueryCommand.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.router;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.router.RouterService;
+
+/**
+ * Supports for query a list of router.
+ */
+@Command(scope = "onos", name = "routers", description = "Supports for creating a router")
+public class RouterQueryCommand extends AbstractShellCommand {
+ @Option(name = "-i", aliases = "--id", description = "The router identifier",
+ required = false, multiValued = false)
+ String id = null;
+
+ @Option(name = "-n", aliases = "--routerName", description = "The name of router",
+ required = false, multiValued = false)
+ String routerName = null;
+
+ private static final String FMT = "routerId=%s, routerName=%s, tenantId=%s, gatewayPortId=%s,"
+ + "externalGatewayInfo=%s, status=%s, adminStateUp=%s, distributed=%s, routers=%s";
+
+ @Override
+ protected void execute() {
+ RouterService service = get(RouterService.class);
+ if (id != null) {
+ Router router = service.getRouter(RouterId.valueOf(id));
+ printFloatingIp(router);
+ } else if (routerName != null) {
+ Iterable<Router> routers = service.getRouters();
+ if (routers == null) {
+ return;
+ }
+ for (Router router : routers) {
+ if (router.name().equals(routerName)) {
+ printFloatingIp(router);
+ return;
+ }
+ }
+ print(null, "The routerName is not existed");
+ } else {
+ Iterable<Router> routers = service.getRouters();
+ if (routers == null) {
+ return;
+ }
+ for (Router router : routers) {
+ printFloatingIp(router);
+ }
+ }
+ }
+
+ private void printFloatingIp(Router router) {
+ print(FMT, router.id(), router.name(), router.tenantId(),
+ router.gatewayPortid(), router.externalGatewayInfo(),
+ router.status(), router.adminStateUp(), router.distributed(),
+ router.routes());
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterRemoveCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterRemoveCommand.java
new file mode 100644
index 00000000..b48434a1
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterRemoveCommand.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.router;
+
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.router.RouterService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for remove a router.
+ */
+@Command(scope = "onos", name = "router-remove", description = "Supports for removing a router")
+public class RouterRemoveCommand extends AbstractShellCommand {
+ @Option(name = "-i", aliases = "--id", description = "The router identifier",
+ required = false, multiValued = false)
+ String id = null;
+
+ @Option(name = "-n", aliases = "--routerName", description = "The name of router",
+ required = false, multiValued = false)
+ String routerName = null;
+
+ @Override
+ protected void execute() {
+ RouterService service = get(RouterService.class);
+ if (id == null && routerName == null) {
+ print(null, "one of id, routerName should not be null");
+ }
+ try {
+ Set<RouterId> routerSet = Sets.newHashSet();
+ if (id != null) {
+ routerSet.add(RouterId.valueOf(id));
+ service.removeRouters(routerSet);
+ } else {
+ Iterable<Router> routers = service.getRouters();
+ if (routers == null) {
+ return;
+ }
+ for (Router router : routers) {
+ if (router.name().equals(routerName)) {
+ routerSet.add(router.id());
+ service.removeRouters(routerSet);
+ return;
+ }
+ }
+ }
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterUpdateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterUpdateCommand.java
new file mode 100644
index 00000000..699874b3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/RouterUpdateCommand.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.router;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.DefaultRouter;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.Router.Status;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.router.RouterService;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Supports for update a router.
+ */
+@Command(scope = "onos", name = "router-update", description = "Supports for updating a router")
+public class RouterUpdateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "id", description = "The router identifier",
+ required = true, multiValued = false)
+ String id = null;
+
+ @Option(name = "-r", aliases = "--routerName", description = "The name of router",
+ required = false, multiValued = false)
+ String routerName = null;
+
+ @Option(name = "-t", aliases = "--tenantId", description = "The tenant identifier of router",
+ required = false, multiValued = false)
+ String tenantId = null;
+
+ @Option(name = "-g", aliases = "--gatewayPortId", description = "The gatewayPort identifier of router",
+ required = false, multiValued = false)
+ String gatewayPortId = null;
+
+ @Option(name = "-e", aliases = "--externalGatewayInfo", description = "The externalGatewayInfo of router",
+ required = false, multiValued = false)
+ String externalGatewayInfo = null;
+
+ @Option(name = "-s", aliases = "--status", description = "The status of router",
+ required = false, multiValued = false)
+ String status = null;
+
+ @Option(name = "-a", aliases = "--adminStateUp", description = "The boolean adminStateUp of router",
+ required = false, multiValued = false)
+ boolean adminStateUp = true;
+
+ @Option(name = "-d", aliases = "--distributed", description = "The boolean distributed of router",
+ required = false, multiValued = false)
+ boolean distributed = false;
+
+ @Override
+ protected void execute() {
+ RouterService service = get(RouterService.class);
+ RouterId routerId = RouterId.valueOf(id);
+ Router router = get(RouterService.class).getRouter(routerId);
+ try {
+ List<String> routes = new ArrayList<String>();
+ Router routerObj = new DefaultRouter(
+ RouterId.valueOf(id),
+ routerName == null ? router.name() : routerName,
+ adminStateUp,
+ status == null ? Status.ACTIVE
+ : Status.valueOf(status),
+ distributed,
+ null,
+ gatewayPortId == null ? router.gatewayPortid()
+ : VirtualPortId.portId(gatewayPortId),
+ tenantId == null ? router.tenantId()
+ : TenantId.tenantId(tenantId),
+ routes);
+ Set<Router> routerSet = Sets.newHashSet(routerObj);
+ service.createRouters(routerSet);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/package-info.java
new file mode 100644
index 00000000..4f1768ac
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/router/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Command line interface for router.
+ */
+package org.onosproject.vtnrsc.cli.router;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceCreateCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceCreateCommand.java
new file mode 100644
index 00000000..a3a174c9
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceCreateCommand.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.routerinterface;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+
+/**
+ * Supports for create a router interface.
+ */
+@Command(scope = "onos", name = "routerinterface-create", description = "Supports for creating a router interface")
+public class RouterInterfaceCreateCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "routerId", description = "The router identifier of router interface",
+ required = true, multiValued = false)
+ String routerId = null;
+
+ @Argument(index = 1, name = "tenantId", description = "The tenant identifier of router interface",
+ required = true, multiValued = false)
+ String tenantId = null;
+
+ @Argument(index = 2, name = "portId", description = "The port identifier of router interface",
+ required = true, multiValued = false)
+ String portId = null;
+
+ @Argument(index = 3, name = "subnetId", description = "The subnet identifier of router interface",
+ required = true, multiValued = false)
+ String subnetId = null;
+
+ @Override
+ protected void execute() {
+ RouterInterfaceService service = get(RouterInterfaceService.class);
+ try {
+ RouterInterface routerInterface = RouterInterface.routerInterface(
+ SubnetId.subnetId(subnetId),
+ VirtualPortId.portId(portId),
+ RouterId.valueOf(routerId),
+ TenantId.tenantId(tenantId));
+ service.addRouterInterface(routerInterface);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceQueryCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceQueryCommand.java
new file mode 100644
index 00000000..5de35aee
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceQueryCommand.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.routerinterface;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+
+/**
+ * Supports for query a router interface.
+ */
+@Command(scope = "onos", name = "routerinterfaces", description = "Supports for querying a router interface")
+public class RouterInterfaceQueryCommand extends AbstractShellCommand {
+ @Option(name = "-s", aliases = "--subnetId", description = "The subnet identifier of router interface",
+ required = false, multiValued = false)
+ String subnetId = null;
+
+ private static final String FMT = "subnetId=%s, tenantId=%s, portId=%s, routerId=%s";
+
+ @Override
+ protected void execute() {
+ RouterInterfaceService service = get(RouterInterfaceService.class);
+ if (subnetId != null) {
+ RouterInterface routerInterface = service
+ .getRouterInterface(SubnetId.subnetId(subnetId));
+ printRouterInterface(routerInterface);
+ } else {
+ Iterable<RouterInterface> routerInterfaces = service
+ .getRouterInterfaces();
+ for (RouterInterface routerInterface : routerInterfaces) {
+ printRouterInterface(routerInterface);
+ }
+ }
+ }
+
+ private void printRouterInterface(RouterInterface routerInterface) {
+ print(FMT, routerInterface.subnetId(), routerInterface.tenantId(),
+ routerInterface.portId(), routerInterface.routerId());
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceRemoveCommand.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceRemoveCommand.java
new file mode 100644
index 00000000..4e838e26
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/RouterInterfaceRemoveCommand.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.cli.routerinterface;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+
+/**
+ * Supports for remove a router interface.
+ */
+@Command(scope = "onos", name = "routerinterface-remove", description = "Supports for removing a router interface")
+public class RouterInterfaceRemoveCommand extends AbstractShellCommand {
+ @Option(name = "-s", aliases = "--subnetId", description = "The subnet identifier of router interface",
+ required = true, multiValued = false)
+ String subnetId = null;
+
+ @Override
+ protected void execute() {
+ RouterInterfaceService service = get(RouterInterfaceService.class);
+ try {
+ RouterInterface routerInterface = service
+ .getRouterInterface(SubnetId.subnetId(subnetId));
+ if (routerInterface == null) {
+ print(null, "subnet ID of interface doesn't exist");
+ return;
+ }
+ service.removeRouterInterface(routerInterface);
+ } catch (Exception e) {
+ print(null, e.getMessage());
+ }
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/package-info.java
new file mode 100644
index 00000000..7b82004e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/cli/routerinterface/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Command line interface for router interface.
+ */
+package org.onosproject.vtnrsc.cli.routerinterface;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java
new file mode 100644
index 00000000..3bac158b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEvent.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.event;
+
+import org.onosproject.event.AbstractEvent;
+
+
+/**
+ * Describes network vtnrsc event.
+ */
+public class VtnRscEvent
+ extends AbstractEvent<VtnRscEvent.Type, VtnRscEventFeedback> {
+
+ /**
+ * Type of vtnrsc events.
+ */
+ public enum Type {
+ /**
+ * Signifies that floating IP has create.
+ */
+ FLOATINGIP_PUT,
+ /**
+ * Signifies that floating IP has delete.
+ */
+ FLOATINGIP_DELETE,
+ /**
+ * Signifies that router has create.
+ */
+ ROUTER_PUT,
+ /**
+ * Signifies that router has delete.
+ */
+ ROUTER_DELETE,
+ /**
+ * Signifies that router interface has add.
+ */
+ ROUTER_INTERFACE_PUT,
+ /**
+ * Signifies that router interface has remove.
+ */
+ ROUTER_INTERFACE_DELETE
+ }
+
+ /**
+ * Creates an event of a given type and for the specified vtn event feedback.
+ *
+ * @param type Vtnrsc event type
+ * @param vtnFeedback event VtnrscEventFeedback subject
+ */
+ public VtnRscEvent(Type type, VtnRscEventFeedback vtnFeedback) {
+ super(type, vtnFeedback);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified vtn event feedback.
+ *
+ * @param type Vtnrsc event type
+ * @param vtnFeedback event VtnrscEventFeedback subject
+ * @param time occurrence time
+ */
+ public VtnRscEvent(Type type, VtnRscEventFeedback vtnFeedback, long time) {
+ super(type, vtnFeedback, time);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java
new file mode 100644
index 00000000..63dcaeee
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscEventFeedback.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.event;
+
+import java.util.Objects;
+
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterInterface;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Representation of a VtnRsc event feedback.
+ */
+public class VtnRscEventFeedback {
+ private final FloatingIp floaingtIp;
+ private final Router router;
+ private final RouterInterface routerInterface;
+
+ /**
+ * Creates VtnRscEventFeedback object.
+ *
+ * @param floatingIp the floating Ip
+ */
+ public VtnRscEventFeedback(FloatingIp floatingIp) {
+ this.floaingtIp = checkNotNull(floatingIp, "floaintIp cannot be null");
+ this.router = null;
+ this.routerInterface = null;
+ }
+
+ /**
+ * Creates VtnRscEventFeedback object.
+ *
+ * @param router the router
+ */
+ public VtnRscEventFeedback(Router router) {
+ this.floaingtIp = null;
+ this.router = checkNotNull(router, "router cannot be null");
+ this.routerInterface = null;
+ }
+
+ /**
+ * Creates VtnRscEventFeedback object.
+ *
+ * @param routerInterface the router interface
+ */
+ public VtnRscEventFeedback(RouterInterface routerInterface) {
+ this.floaingtIp = null;
+ this.router = null;
+ this.routerInterface = checkNotNull(routerInterface,
+ "routerInterface cannot be null");
+ }
+
+ /**
+ * Returns floating IP.
+ *
+ * @return floaingtIp the floating IP
+ */
+ public FloatingIp floatingIp() {
+ return floaingtIp;
+ }
+
+ /**
+ * Returns router.
+ *
+ * @return router the router
+ */
+ public Router router() {
+ return router;
+ }
+
+ /**
+ * Returns router interface.
+ *
+ * @return routerInterface the router interface
+ */
+ public RouterInterface routerInterface() {
+ return routerInterface;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(floaingtIp, router, routerInterface);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VtnRscEventFeedback) {
+ final VtnRscEventFeedback that = (VtnRscEventFeedback) obj;
+ return Objects.equals(this.floaingtIp, that.floaingtIp)
+ && Objects.equals(this.router, that.router)
+ && Objects.equals(this.routerInterface, that.routerInterface);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("router", router)
+ .add("floaingtIp", floaingtIp)
+ .add("routerInterface", routerInterface)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscListener.java
new file mode 100644
index 00000000..fdd67552
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/VtnRscListener.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc.event;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of VtnRsc related events.
+ */
+public interface VtnRscListener extends EventListener<VtnRscEvent> {
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/package-info.java
new file mode 100644
index 00000000..c1575ad3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/event/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Event of VtnRsc for VtnRsc service.
+ */
+package org.onosproject.vtnrsc.event;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java
new file mode 100644
index 00000000..f76007f7
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpEvent.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.vtnrsc.FloatingIp;
+
+/**
+ * Describes network Floating IP event.
+ */
+public class FloatingIpEvent
+ extends AbstractEvent<FloatingIpEvent.Type, FloatingIp> {
+ /**
+ * Type of Floating IP events.
+ */
+ public enum Type {
+ /**
+ * Signifies that Floating IP has been created.
+ */
+ FLOATINGIP_PUT,
+ /**
+ * Signifies that Floating IP has been deleted.
+ */
+ FLOATINGIP_DELETE
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Floating IP.
+ *
+ * @param type Floating IP event type
+ * @param floagingIp Floating IP subject
+ */
+ public FloatingIpEvent(Type type, FloatingIp floagingIp) {
+ super(type, floagingIp);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Floating IP.
+ *
+ * @param type Floating IP event type
+ * @param floagingIp Floating IP subject
+ * @param time occurrence time
+ */
+ public FloatingIpEvent(Type type, FloatingIp floagingIp, long time) {
+ super(type, floagingIp, time);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpListener.java
new file mode 100644
index 00000000..a42af136
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of Floating IP related events.
+ */
+public interface FloatingIpListener extends EventListener<FloatingIpEvent> {
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpService.java
new file mode 100644
index 00000000..3f6f2515
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/FloatingIpService.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip;
+
+import java.util.Collection;
+
+import org.onlab.packet.IpAddress;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.TenantId;
+
+/**
+ * Service for interacting with the inventory of floating IP.
+ */
+public interface FloatingIpService {
+ /**
+ * Returns exists or not of specific floatingIp identifier.
+ *
+ * @param floatingIpId floatingIp identifier
+ * @return true or false
+ */
+ boolean exists(FloatingIpId floatingIpId);
+
+ /**
+ * Returns is used or not of specific floating IP address.
+ *
+ * @param floatingIpAddr floatingIp address
+ * @param floatingIpId floatingIp identifier
+ * @return true or false
+ */
+ boolean floatingIpIsUsed(IpAddress floatingIpAddr, FloatingIpId floatingIpId);
+
+ /**
+ * Returns is used or not of specific fixed IP address.
+ *
+ * @param fixedIpAddr fixedIp address
+ * @param tenantId the tenant identifier of floating IP
+ * @param floatingIpId floatingIp identifier
+ * @return true or false
+ */
+ boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId, FloatingIpId floatingIpId);
+
+ /**
+ * Returns a collection of the currently known floating IP.
+ *
+ * @return collection of floating IP
+ */
+ Collection<FloatingIp> getFloatingIps();
+
+ /**
+ * Returns the floatingIp with the specified identifier.
+ *
+ * @param floatingIpId floatingIp identifier
+ * @return floatingIp or null if one with the given identifier is not known
+ */
+ FloatingIp getFloatingIp(FloatingIpId floatingIpId);
+
+ /**
+ * Creates new floatingIps.
+ *
+ * @param floatingIps the collection of floatingIp
+ * @return true if the identifier floatingIp has been created right
+ */
+ boolean createFloatingIps(Collection<FloatingIp> floatingIps);
+
+ /**
+ * Updates existing floatingIps.
+ *
+ * @param floatingIps the collection of floatingIp
+ * @return true if all floatingIp were updated successfully
+ */
+ boolean updateFloatingIps(Collection<FloatingIp> floatingIps);
+
+ /**
+ * Removes the specified floatingIp from the store.
+ *
+ * @param floatingIpIds the collection of floatingIp identifier
+ * @return true if remove identifier floatingIp successfully
+ */
+ boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds);
+
+ /**
+ * Adds the specified listener to floating Ip manager.
+ *
+ * @param listener floating Ip listener
+ */
+ void addListener(FloatingIpListener listener);
+
+ /**
+ * Removes the specified listener to floating Ip manager.
+ *
+ * @param listener floating Ip listener
+ */
+ void removeListener(FloatingIpListener listener);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java
new file mode 100644
index 00000000..9f944da1
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/FloatingIpManager.java
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultFloatingIp;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
+import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+import org.onosproject.vtnrsc.router.RouterService;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of the FloatingIp service.
+ */
+@Component(immediate = true)
+@Service
+public class FloatingIpManager implements FloatingIpService {
+ private static final String FLOATINGIP_ID_NOT_NULL = "Floatingip ID cannot be null";
+ private static final String FLOATINGIP_NOT_NULL = "Floatingip cannot be null";
+ private static final String FLOATINGIP = "vtn-floatingip-store";
+ private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
+ private static final String LISTENER_NOT_NULL = "Listener cannot be null";
+ private static final String EVENT_NOT_NULL = "event cannot be null";
+
+ private final Logger log = getLogger(getClass());
+ private final Set<FloatingIpListener> listeners = Sets
+ .newCopyOnWriteArraySet();
+ private EventuallyConsistentMapListener<FloatingIpId, FloatingIp> floatingIpListener =
+ new InnerFloatingIpStoreListener();
+ protected EventuallyConsistentMap<FloatingIpId, FloatingIp> floatingIpStore;
+ protected ApplicationId appId;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TenantNetworkService tenantNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualPortService virtualPortService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RouterService routerService;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(VTNRSC_APP);
+ KryoNamespace.Builder serializer = KryoNamespace
+ .newBuilder()
+ .register(KryoNamespaces.API)
+ .register(FloatingIp.class, FloatingIpId.class,
+ TenantNetworkId.class, TenantId.class,
+ FloatingIp.Status.class, RouterId.class,
+ VirtualPortId.class, DefaultFloatingIp.class);
+ floatingIpStore = storageService
+ .<FloatingIpId, FloatingIp>eventuallyConsistentMapBuilder()
+ .withName(FLOATINGIP).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+ floatingIpStore.addListener(floatingIpListener);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ floatingIpStore.removeListener(floatingIpListener);
+ floatingIpStore.destroy();
+ listeners.clear();
+ log.info("Stopped");
+ }
+
+ @Override
+ public Collection<FloatingIp> getFloatingIps() {
+ return Collections.unmodifiableCollection(floatingIpStore.values());
+ }
+
+ @Override
+ public FloatingIp getFloatingIp(FloatingIpId floatingIpId) {
+ checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
+ return floatingIpStore.get(floatingIpId);
+ }
+
+ @Override
+ public boolean exists(FloatingIpId floatingIpId) {
+ checkNotNull(floatingIpId, FLOATINGIP_ID_NOT_NULL);
+ return floatingIpStore.containsKey(floatingIpId);
+ }
+
+ @Override
+ public boolean floatingIpIsUsed(IpAddress floatingIpAddr,
+ FloatingIpId floatingIpId) {
+ checkNotNull(floatingIpAddr, "Floating IP address cannot be null");
+ checkNotNull(floatingIpId, "Floating IP Id cannot be null");
+ Collection<FloatingIp> floatingIps = getFloatingIps();
+ for (FloatingIp floatingIp : floatingIps) {
+ if (floatingIp.floatingIp().equals(floatingIpAddr)
+ && !floatingIp.id().equals(floatingIpId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean fixedIpIsUsed(IpAddress fixedIpAddr, TenantId tenantId,
+ FloatingIpId floatingIpId) {
+ checkNotNull(fixedIpAddr, "Fixed IP address cannot be null");
+ checkNotNull(tenantId, "Tenant Id cannot be null");
+ checkNotNull(floatingIpId, "Floating IP Id cannot be null");
+ Collection<FloatingIp> floatingIps = getFloatingIps();
+ for (FloatingIp floatingIp : floatingIps) {
+ IpAddress fixedIp = floatingIp.fixedIp();
+ if (fixedIp != null) {
+ if (fixedIp.equals(fixedIpAddr)
+ && floatingIp.tenantId().equals(tenantId)
+ && !floatingIp.id().equals(floatingIpId)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean createFloatingIps(Collection<FloatingIp> floatingIps) {
+ checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
+ boolean result = true;
+ for (FloatingIp floatingIp : floatingIps) {
+ verifyFloatingIpData(floatingIp);
+ if (floatingIp.portId() != null) {
+ floatingIpStore.put(floatingIp.id(), floatingIp);
+ if (!floatingIpStore.containsKey(floatingIp.id())) {
+ log.debug("The floating Ip is created failed whose identifier is {}",
+ floatingIp.id().toString());
+ result = false;
+ }
+ } else {
+ FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp.id());
+ if (oldFloatingIp != null) {
+ floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
+ if (floatingIpStore.containsKey(floatingIp.id())) {
+ log.debug("The floating Ip is created failed whose identifier is {}",
+ floatingIp.id().toString());
+ result = false;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean updateFloatingIps(Collection<FloatingIp> floatingIps) {
+ checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
+ boolean result = true;
+ if (floatingIps != null) {
+ for (FloatingIp floatingIp : floatingIps) {
+ verifyFloatingIpData(floatingIp);
+ if (floatingIp.portId() != null) {
+ floatingIpStore.put(floatingIp.id(), floatingIp);
+ if (!floatingIpStore.containsKey(floatingIp.id())) {
+ log.debug("The floating Ip is updated failed whose identifier is {}",
+ floatingIp.id().toString());
+ result = false;
+ }
+ } else {
+ FloatingIp oldFloatingIp = floatingIpStore.get(floatingIp
+ .id());
+ if (oldFloatingIp != null) {
+ floatingIpStore.remove(floatingIp.id(), oldFloatingIp);
+ if (floatingIpStore.containsKey(floatingIp.id())) {
+ log.debug("The floating Ip is updated failed whose identifier is {}",
+ floatingIp.id().toString());
+ result = false;
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public boolean removeFloatingIps(Collection<FloatingIpId> floatingIpIds) {
+ checkNotNull(floatingIpIds, FLOATINGIP_ID_NOT_NULL);
+ boolean result = true;
+ if (floatingIpIds != null) {
+ for (FloatingIpId floatingIpId : floatingIpIds) {
+ if (!floatingIpStore.containsKey(floatingIpId)) {
+ log.debug("The floatingIp is not exist whose identifier is {}",
+ floatingIpId.toString());
+ throw new IllegalArgumentException(
+ "FloatingIP ID doesn't exist");
+ }
+ FloatingIp floatingIp = floatingIpStore.get(floatingIpId);
+ floatingIpStore.remove(floatingIpId, floatingIp);
+ if (floatingIpStore.containsKey(floatingIpId)) {
+ log.debug("The floating Ip is deleted failed whose identifier is {}",
+ floatingIpId.toString());
+ result = false;
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public void addListener(FloatingIpListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(FloatingIpListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ /**
+ * Verifies validity of FloatingIp data.
+ *
+ * @param floatingIps floatingIp instance
+ */
+ private void verifyFloatingIpData(FloatingIp floatingIps) {
+ checkNotNull(floatingIps, FLOATINGIP_NOT_NULL);
+ if (!tenantNetworkService.exists(floatingIps.networkId())) {
+ log.debug("The network identifier {} that the floating Ip {} create for is not exist",
+ floatingIps.networkId().toString(), floatingIps.id()
+ .toString());
+ throw new IllegalArgumentException(
+ "Floating network ID doesn't exist");
+ }
+
+ VirtualPortId portId = floatingIps.portId();
+ if (portId != null && !virtualPortService.exists(portId)) {
+ log.debug("The port identifier {} that the floating Ip {} create for is not exist",
+ floatingIps.portId().toString(), floatingIps.id()
+ .toString());
+ throw new IllegalArgumentException("Port ID doesn't exist");
+ }
+
+ RouterId routerId = floatingIps.routerId();
+ if (routerId != null && !routerService.exists(routerId)) {
+ log.debug("The router identifier {} that the floating Ip {} create for is not exist",
+ floatingIps.routerId().toString(), floatingIps.id()
+ .toString());
+ throw new IllegalArgumentException("Router ID doesn't exist");
+ }
+
+ if (floatingIpIsUsed(floatingIps.floatingIp(), floatingIps.id())) {
+ log.debug("The floaing Ip {} that the floating Ip {} create for is used",
+ floatingIps.floatingIp().toString(), floatingIps.id()
+ .toString());
+ throw new IllegalArgumentException(
+ "The floating IP address is used");
+ }
+
+ IpAddress fixedIp = floatingIps.fixedIp();
+ if (fixedIp != null
+ && fixedIpIsUsed(fixedIp, floatingIps.tenantId(),
+ floatingIps.id())) {
+ log.debug("The fixed Ip {} that the floating Ip {} create for is used",
+ floatingIps.fixedIp().toString(), floatingIps.id()
+ .toString());
+ throw new IllegalArgumentException("The fixed IP address is used");
+ }
+ }
+
+ private class InnerFloatingIpStoreListener
+ implements
+ EventuallyConsistentMapListener<FloatingIpId, FloatingIp> {
+
+ @Override
+ public void event(EventuallyConsistentMapEvent<FloatingIpId, FloatingIp> event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ FloatingIp floatingIp = event.value();
+ if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
+ notifyListeners(new FloatingIpEvent(
+ FloatingIpEvent.Type.FLOATINGIP_PUT,
+ floatingIp));
+ }
+ if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
+ notifyListeners(new FloatingIpEvent(
+ FloatingIpEvent.Type.FLOATINGIP_DELETE,
+ floatingIp));
+ }
+ }
+ }
+
+ /**
+ * Notifies specify event to all listeners.
+ *
+ * @param event Floating IP event
+ */
+ private void notifyListeners(FloatingIpEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ listeners.forEach(listener -> listener.event(event));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/package-info.java
new file mode 100644
index 00000000..c638eba0
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides implementation of the FloatingIp service.
+ */
+package org.onosproject.vtnrsc.floatingip.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/package-info.java
new file mode 100644
index 00000000..274cbdd0
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/floatingip/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with the inventory of FloatingIp.
+ */
+package org.onosproject.vtnrsc.floatingip;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java
index c160d221..c5911ff2 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierService.java
@@ -24,49 +24,59 @@ import org.onosproject.vtnrsc.FlowClassifierId;
public interface FlowClassifierService {
/**
- * Store Flow Classifier.
+ * Check whether Flow Classifier is present based on given Flow Classifier
+ * Id.
*
- * @param flowClassifier Flow Classifier
- * @return true if adding Flow Classifier into store is success otherwise return false.
+ * @param id flow classifier identifier
+ * @return true if flow classifier is present otherwise return false
*/
- boolean createFlowClassifier(FlowClassifier flowClassifier);
+ boolean exists(FlowClassifierId id);
/**
- * Return the existing collection of Flow Classifier.
+ * Returns the number of flow classifiers known to the system.
*
- * @return Flow Classifier collections.
+ * @return number of flow classifiers
*/
- Iterable<FlowClassifier> getFlowClassifiers();
+ int getFlowClassifierCount();
+
+ /**
+ * Store Flow Classifier.
+ *
+ * @param flowClassifier flow classifier
+ * @return true if adding flow classifier into store is success otherwise
+ * return false
+ */
+ boolean createFlowClassifier(FlowClassifier flowClassifier);
/**
- * Check whether Flow Classifier is present based on given Flow Classifier Id.
+ * Return the existing collection of Flow Classifier.
*
- * @param id Flow Classifier.
- * @return true if Flow Classifier is present otherwise return false.
+ * @return flow classifier collections
*/
- boolean hasFlowClassifier(FlowClassifierId id);
+ Iterable<FlowClassifier> getFlowClassifiers();
/**
* Retrieve the Flow Classifier based on given Flow Classifier id.
*
- * @param id Flow Classifier Id.
- * @return Flow Classifier if present otherwise returns null.
+ * @param id flow classifier identifier
+ * @return flow classifier if present otherwise returns null
*/
FlowClassifier getFlowClassifier(FlowClassifierId id);
/**
* Update Flow Classifier based on given Flow Classifier Id.
*
- * @param flowClassifier Flow Classifier.
- * @return true if update is success otherwise return false.
+ * @param flowClassifier flow classifier
+ * @return true if flow classifier update is success otherwise return false
*/
boolean updateFlowClassifier(FlowClassifier flowClassifier);
/**
* Remove Flow Classifier from store based on given Flow Classifier Id.
*
- * @param id Flow Classifier Id.
- * @return true if Flow Classifier removal is success otherwise return false.
+ * @param id flow classifier identifier
+ * @return true if flow classifier removal is success otherwise return
+ * false
*/
boolean removeFlowClassifier(FlowClassifierId id);
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
index ee5873d6..4a60cd34 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManager.java
@@ -54,7 +54,7 @@ public class FlowClassifierManager implements FlowClassifierService {
protected StorageService storageService;
@Activate
- private void activate() {
+ protected void activate() {
KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
.register(KryoNamespaces.API)
.register(MultiValuedTimestamp.class)
@@ -67,34 +67,25 @@ public class FlowClassifierManager implements FlowClassifierService {
}
@Deactivate
- private void deactivate() {
+ protected void deactivate() {
flowClassifierStore.destroy();
log.info("Flow Classifier service deactivated");
}
@Override
- public boolean createFlowClassifier(FlowClassifier flowClassifier) {
- log.debug("createFlowClassifier");
- checkNotNull(flowClassifier, FLOW_CLASSIFIER_NOT_NULL);
- FlowClassifierId id = flowClassifier.flowClassifierId();
-
- flowClassifierStore.put(id, flowClassifier);
- if (!flowClassifierStore.containsKey(id)) {
- log.debug("Flow Classifier creation is failed whose identifier is {}.", id.toString());
- return false;
- }
- return true;
+ public boolean exists(FlowClassifierId id) {
+ checkNotNull(id, FLOW_CLASSIFIER_ID_NOT_NULL);
+ return flowClassifierStore.containsKey(id);
}
@Override
- public Iterable<FlowClassifier> getFlowClassifiers() {
- return ImmutableList.copyOf(flowClassifierStore.values());
+ public int getFlowClassifierCount() {
+ return flowClassifierStore.size();
}
@Override
- public boolean hasFlowClassifier(FlowClassifierId id) {
- checkNotNull(id, FLOW_CLASSIFIER_ID_NOT_NULL);
- return flowClassifierStore.containsKey(id);
+ public Iterable<FlowClassifier> getFlowClassifiers() {
+ return ImmutableList.copyOf(flowClassifierStore.values());
}
@Override
@@ -104,10 +95,36 @@ public class FlowClassifierManager implements FlowClassifierService {
}
@Override
- public boolean updateFlowClassifier(FlowClassifier flowClassifier) {
+ public boolean createFlowClassifier(FlowClassifier flowClassifier) {
+ log.debug("createFlowClassifier");
checkNotNull(flowClassifier, FLOW_CLASSIFIER_NOT_NULL);
FlowClassifierId id = flowClassifier.flowClassifierId();
+
flowClassifierStore.put(id, flowClassifier);
+ if (!flowClassifierStore.containsKey(id)) {
+ log.debug("Flow Classifier creation is failed whose identifier is {}.", id.toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updateFlowClassifier(FlowClassifier flowClassifier) {
+ checkNotNull(flowClassifier, FLOW_CLASSIFIER_NOT_NULL);
+
+ if (!flowClassifierStore.containsKey(flowClassifier.flowClassifierId())) {
+ log.debug("The flowClassifier is not exist whose identifier was {} ", flowClassifier.flowClassifierId()
+ .toString());
+ return false;
+ }
+
+ flowClassifierStore.put(flowClassifier.flowClassifierId(), flowClassifier);
+
+ if (!flowClassifier.equals(flowClassifierStore.get(flowClassifier.flowClassifierId()))) {
+ log.debug("Updation of flowClassifier is failed whose identifier was {} ", flowClassifier
+ .flowClassifierId().toString());
+ return false;
+ }
return true;
}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterEvent.java
new file mode 100644
index 00000000..25bd7b31
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterEvent.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.vtnrsc.Router;
+
+/**
+ * Describes network Router event.
+ */
+public class RouterEvent extends AbstractEvent<RouterEvent.Type, Router> {
+ /**
+ * Type of Router events.
+ */
+ public enum Type {
+ /**
+ * Signifies that router has been created.
+ */
+ ROUTER_PUT,
+ /**
+ * Signifies that router has been deleted.
+ */
+ ROUTER_DELETE
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Router.
+ *
+ * @param type Router event type
+ * @param router Router subject
+ */
+ public RouterEvent(Type type, Router router) {
+ super(type, router);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Router.
+ *
+ * @param type Router event type
+ * @param router Router subject
+ * @param time occurrence time
+ */
+ public RouterEvent(Type type, Router router, long time) {
+ super(type, router, time);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterListener.java
new file mode 100644
index 00000000..dc772981
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterListener.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of Router related events.
+ */
+public interface RouterListener extends EventListener<RouterEvent> {
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterService.java
new file mode 100644
index 00000000..362fa02b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/RouterService.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router;
+
+import java.util.Collection;
+
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterId;
+
+/**
+ * Service for interacting with the inventory of Routers.
+ */
+public interface RouterService {
+ /**
+ * Returns exists or not of specific router identifier.
+ *
+ * @param routerId router identifier
+ * @return true or false
+ */
+ boolean exists(RouterId routerId);
+
+ /**
+ * Returns a collection of the currently known Routers.
+ *
+ * @return collection of Routers
+ */
+ Collection<Router> getRouters();
+
+ /**
+ * Returns the Router with the specified identifier.
+ *
+ * @param routerId Router identifier
+ * @return Router or null if one with the given identifier is not known
+ */
+ Router getRouter(RouterId routerId);
+
+ /**
+ * Creates new Routers.
+ *
+ * @param routers the collection of Routers
+ * @return true if the identifier Router has been created right.
+ * false if the identifier Router is failed to store
+ */
+ boolean createRouters(Collection<Router> routers);
+
+ /**
+ * Updates existing Routers.
+ *
+ * @param routers the collection of Routers
+ * @return true if Routers were updated successfully.
+ * false if Routers were updated failed
+ */
+ boolean updateRouters(Collection<Router> routers);
+
+ /**
+ * Removes the specified Routers from the store.
+ *
+ * @param routerIds the collection of Routers identifier
+ * @return true if remove identifier Routers successfully. false if remove
+ * identifier Routers failed
+ */
+ boolean removeRouters(Collection<RouterId> routerIds);
+
+ /**
+ * Adds the specified listener to Router manager.
+ *
+ * @param listener Router listener
+ */
+ void addListener(RouterListener listener);
+
+ /**
+ * Removes the specified listener to Router manager.
+ *
+ * @param listener Router listener
+ */
+ void removeListener(RouterListener listener);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/RouterManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/RouterManager.java
new file mode 100644
index 00000000..b796fd7b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/RouterManager.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.DefaultRouter;
+import org.onosproject.vtnrsc.FixedIp;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterGateway;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.router.RouterEvent;
+import org.onosproject.vtnrsc.router.RouterListener;
+import org.onosproject.vtnrsc.router.RouterService;
+import org.onosproject.vtnrsc.subnet.SubnetService;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of the Router service.
+ */
+@Component(immediate = true)
+@Service
+public class RouterManager implements RouterService {
+
+ private static final String ROUTER_ID_NULL = "Router ID cannot be null";
+ private static final String ROUTER_NOT_NULL = "Router cannot be null";
+ private static final String ROUTER = "vtn-router-store";
+ private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
+ private static final String LISTENER_NOT_NULL = "Listener cannot be null";
+ private static final String EVENT_NOT_NULL = "event cannot be null";
+
+ private final Logger log = getLogger(getClass());
+ private final Set<RouterListener> listeners = Sets.newCopyOnWriteArraySet();
+ private EventuallyConsistentMapListener<RouterId, Router> routerListener = new InnerRouterStoreListener();
+ protected EventuallyConsistentMap<RouterId, Router> routerStore;
+ protected ApplicationId appId;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TenantNetworkService tenantNetworkService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualPortService virtualPortService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected SubnetService subnetService;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(VTNRSC_APP);
+ KryoNamespace.Builder serializer = KryoNamespace
+ .newBuilder()
+ .register(KryoNamespaces.API)
+ .register(Router.class, RouterId.class, DefaultRouter.class,
+ TenantNetworkId.class, TenantId.class,
+ VirtualPortId.class, DefaultRouter.class,
+ RouterGateway.class, Router.Status.class,
+ SubnetId.class);
+ routerStore = storageService
+ .<RouterId, Router>eventuallyConsistentMapBuilder()
+ .withName(ROUTER).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+ routerStore.addListener(routerListener);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ routerStore.removeListener(routerListener);
+ routerStore.destroy();
+ listeners.clear();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean exists(RouterId routerId) {
+ checkNotNull(routerId, ROUTER_ID_NULL);
+ return routerStore.containsKey(routerId);
+ }
+
+ @Override
+ public Collection<Router> getRouters() {
+ return Collections.unmodifiableCollection(routerStore.values());
+ }
+
+ @Override
+ public Router getRouter(RouterId routerId) {
+ checkNotNull(routerId, ROUTER_ID_NULL);
+ return routerStore.get(routerId);
+ }
+
+ @Override
+ public boolean createRouters(Collection<Router> routers) {
+ checkNotNull(routers, ROUTER_NOT_NULL);
+ for (Router router : routers) {
+ verifyRouterData(router);
+ routerStore.put(router.id(), router);
+ if (!routerStore.containsKey(router.id())) {
+ log.debug("The router is created failed whose identifier is {}",
+ router.id().toString());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean updateRouters(Collection<Router> routers) {
+ checkNotNull(routers, ROUTER_NOT_NULL);
+ for (Router router : routers) {
+ if (!routerStore.containsKey(router.id())) {
+ log.debug("The routers is not exist whose identifier is {}",
+ router.id().toString());
+ throw new IllegalArgumentException(
+ "routers ID doesn't exist");
+ }
+ verifyRouterData(router);
+ routerStore.put(router.id(), router);
+ if (!router.equals(routerStore.get(router.id()))) {
+ log.debug("The router is updated failed whose identifier is {}",
+ router.id().toString());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeRouters(Collection<RouterId> routerIds) {
+ checkNotNull(routerIds, ROUTER_ID_NULL);
+ for (RouterId routerId : routerIds) {
+ if (!routerStore.containsKey(routerId)) {
+ log.debug("The router is not exist whose identifier is {}",
+ routerId.toString());
+ throw new IllegalArgumentException(
+ "router ID doesn't exist");
+ }
+ Router router = routerStore.get(routerId);
+ routerStore.remove(routerId, router);
+ if (routerStore.containsKey(routerId)) {
+ log.debug("The router deleted is failed whose identifier is {}",
+ routerId.toString());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void addListener(RouterListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(RouterListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.remove(listener);
+ }
+
+ /**
+ * Verifies validity of Router data.
+ *
+ * @param routers router instance
+ */
+ private void verifyRouterData(Router routers) {
+ checkNotNull(routers, ROUTER_NOT_NULL);
+ if (routers.gatewayPortid() != null
+ && !virtualPortService.exists(routers.gatewayPortid())) {
+ log.debug("The gateway port ID is not exist whose identifier is {}",
+ routers.gatewayPortid().toString());
+ throw new IllegalArgumentException("gateway port ID doesn't exist");
+ }
+
+ if (routers.externalGatewayInfo() != null) {
+ RouterGateway routerGateway = routers.externalGatewayInfo();
+ if (!tenantNetworkService.exists(routerGateway.networkId())) {
+ log.debug("The network ID of gateway info is not exist whose identifier is {}",
+ routers.id().toString());
+ throw new IllegalArgumentException(
+ "network ID of gateway info doesn't exist");
+ }
+ Iterable<FixedIp> fixedIps = routerGateway.externalFixedIps();
+ for (FixedIp fixedIp : fixedIps) {
+ if (!subnetService.exists(fixedIp.subnetId())) {
+ log.debug("The subnet ID of gateway info is not exist whose identifier is {}",
+ routers.id().toString());
+ throw new IllegalArgumentException(
+ "subnet ID of gateway info doesn't exist");
+ }
+ }
+ }
+ }
+
+ private class InnerRouterStoreListener
+ implements EventuallyConsistentMapListener<RouterId, Router> {
+
+ @Override
+ public void event(EventuallyConsistentMapEvent<RouterId, Router> event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ Router router = event.value();
+ if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
+ notifyListeners(new RouterEvent(RouterEvent.Type.ROUTER_PUT,
+ router));
+ }
+ if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
+ notifyListeners(new RouterEvent(RouterEvent.Type.ROUTER_DELETE,
+ router));
+ }
+ }
+ }
+
+ /**
+ * Notifies specify event to all listeners.
+ *
+ * @param event Floating IP event
+ */
+ private void notifyListeners(RouterEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ listeners.forEach(listener -> listener.event(event));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/package-info.java
new file mode 100644
index 00000000..1254f982
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides implementation of the Router service.
+ */
+package org.onosproject.vtnrsc.router.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/package-info.java
new file mode 100644
index 00000000..fb6834aa
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/router/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with the inventory of Router.
+ */
+package org.onosproject.vtnrsc.router;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceEvent.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceEvent.java
new file mode 100644
index 00000000..7f5cfa13
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceEvent.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.routerinterface;
+
+import org.onosproject.event.AbstractEvent;
+import org.onosproject.vtnrsc.RouterInterface;
+
+/**
+ * Describes network Router Interface event.
+ */
+public class RouterInterfaceEvent
+ extends AbstractEvent<RouterInterfaceEvent.Type, RouterInterface> {
+
+ /**
+ * Type of Router Interface events.
+ */
+ public enum Type {
+ /**
+ * Signifies that router interface has been added.
+ */
+ ROUTER_INTERFACE_PUT,
+ /**
+ * Signifies that router interface has been removed.
+ */
+ ROUTER_INTERFACE_DELETE
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Router Interface.
+ *
+ * @param type Router Interface event type
+ * @param routerInterface Router Interface subject
+ */
+ public RouterInterfaceEvent(Type type, RouterInterface routerInterface) {
+ super(type, routerInterface);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified Router Interface.
+ *
+ * @param type Router Interface event type.
+ * @param routerInterface Router Interface subject
+ * @param time occurrence time
+ */
+ public RouterInterfaceEvent(Type type, RouterInterface routerInterface,
+ long time) {
+ super(type, routerInterface, time);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceListener.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceListener.java
new file mode 100644
index 00000000..1d0dab6f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceListener.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc.routerinterface;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of Router Interface related events.
+ */
+public interface RouterInterfaceListener
+ extends EventListener<RouterInterfaceEvent> {
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceService.java
new file mode 100644
index 00000000..8cf147a5
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/RouterInterfaceService.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.routerinterface;
+
+import java.util.Collection;
+
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+
+/**
+ * Service for interacting with the inventory of Router interface.
+ */
+public interface RouterInterfaceService {
+ /**
+ * Returns exists or not of specific subnet identifier.
+ *
+ * @param subnetId subnet identifier
+ * @return true or false
+ */
+ boolean exists(SubnetId subnetId);
+
+ /**
+ * Returns a collection of the currently known Router interface.
+ *
+ * @return collection of RouterInterface
+ */
+ Collection<RouterInterface> getRouterInterfaces();
+
+ /**
+ * Returns the Router interface with the specified subnet identifier.
+ *
+ * @param subnetId subnet identifier
+ * @return RouterInterface or null if one with the given identifier is not
+ * known
+ */
+ RouterInterface getRouterInterface(SubnetId subnetId);
+
+ /**
+ * Adds the specified RouterInterface.
+ *
+ * @param routerInterface the interface add to router
+ * @return true if add router interface successfully
+ */
+ boolean addRouterInterface(RouterInterface routerInterface);
+
+ /**
+ * Removes the specified RouterInterface.
+ *
+ * @param routerInterface the interface remove from router
+ * @return true if remove router interface successfully
+ */
+ boolean removeRouterInterface(RouterInterface routerInterface);
+
+ /**
+ * Adds the specified listener to Router Interface manager.
+ *
+ * @param listener Router Interface listener
+ */
+ void addListener(RouterInterfaceListener listener);
+
+ /**
+ * Removes the specified listener to RouterInterface manager.
+ *
+ * @param listener Router Interface listener
+ */
+ void removeListener(RouterInterfaceListener listener);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/RouterInterfaceManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/RouterInterfaceManager.java
new file mode 100644
index 00000000..244a5c03
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/RouterInterfaceManager.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.routerinterface.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.router.RouterService;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceEvent;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceListener;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+import org.onosproject.vtnrsc.subnet.SubnetService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of the Router interface service.
+ */
+@Component(immediate = true)
+@Service
+public class RouterInterfaceManager implements RouterInterfaceService {
+ private static final String SUBNET_ID_NULL = "Subnet ID cannot be null";
+ private static final String ROUTER_INTERFACE_NULL = "Router Interface cannot be null";
+ private static final String ROUTER_INTERFACE = "vtn-router-interface-store";
+ private static final String VTNRSC_APP = "org.onosproject.vtnrsc";
+ private static final String LISTENER_NOT_NULL = "Listener cannot be null";
+ private static final String EVENT_NOT_NULL = "event cannot be null";
+
+ private final Logger log = getLogger(getClass());
+ private final Set<RouterInterfaceListener> listeners = Sets
+ .newCopyOnWriteArraySet();
+ private EventuallyConsistentMapListener<SubnetId, RouterInterface> routerInterfaceListener =
+ new InnerRouterInterfaceStoreListener();
+ protected EventuallyConsistentMap<SubnetId, RouterInterface> routerInterfaceStore;
+ protected ApplicationId appId;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualPortService virtualPortService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected SubnetService subnetService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RouterService routerService;
+
+ @Activate
+ public void activate() {
+ appId = coreService.registerApplication(VTNRSC_APP);
+ KryoNamespace.Builder serializer = KryoNamespace
+ .newBuilder()
+ .register(KryoNamespaces.API)
+ .register(RouterId.class, TenantId.class, VirtualPortId.class,
+ RouterInterface.class, SubnetId.class);
+ routerInterfaceStore = storageService
+ .<SubnetId, RouterInterface>eventuallyConsistentMapBuilder()
+ .withName(ROUTER_INTERFACE).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+ routerInterfaceStore.addListener(routerInterfaceListener);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ routerInterfaceStore.removeListener(routerInterfaceListener);
+ routerInterfaceStore.destroy();
+ listeners.clear();
+ log.info("Stopped");
+ }
+
+ @Override
+ public boolean exists(SubnetId subnetId) {
+ checkNotNull(subnetId, SUBNET_ID_NULL);
+ return routerInterfaceStore.containsKey(subnetId);
+ }
+
+ @Override
+ public Collection<RouterInterface> getRouterInterfaces() {
+ return Collections
+ .unmodifiableCollection(routerInterfaceStore.values());
+ }
+
+ @Override
+ public RouterInterface getRouterInterface(SubnetId subnetId) {
+ checkNotNull(subnetId, SUBNET_ID_NULL);
+ return routerInterfaceStore.get(subnetId);
+ }
+
+ @Override
+ public boolean addRouterInterface(RouterInterface routerInterface) {
+ checkNotNull(routerInterface, ROUTER_INTERFACE_NULL);
+ verifyRouterInterfaceData(routerInterface);
+ routerInterfaceStore.put(routerInterface.subnetId(), routerInterface);
+ if (!routerInterfaceStore.containsKey(routerInterface.subnetId())) {
+ log.debug("The router interface is created failed whose identifier is {}",
+ routerInterface.subnetId().toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean removeRouterInterface(RouterInterface routerInterface) {
+ checkNotNull(routerInterface, ROUTER_INTERFACE_NULL);
+ if (!routerInterfaceStore.containsKey(routerInterface.subnetId())) {
+ log.debug("The router interface is not exist whose identifier is {}",
+ routerInterface.subnetId().toString());
+ throw new IllegalArgumentException("subnet ID doesn't exist");
+ }
+ verifyRouterInterfaceData(routerInterface);
+ routerInterfaceStore
+ .remove(routerInterface.subnetId(), routerInterface);
+ if (routerInterfaceStore.containsKey(routerInterface.subnetId())) {
+ log.debug("The router interface deleted is failed whose identifier is {}",
+ routerInterface.subnetId().toString());
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void addListener(RouterInterfaceListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(RouterInterfaceListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.remove(listener);
+ }
+
+ /**
+ * Verifies validity of Router interface data.
+ *
+ * @param routers router instance
+ */
+ private void verifyRouterInterfaceData(RouterInterface routerInterface) {
+ checkNotNull(routerInterface, ROUTER_INTERFACE_NULL);
+ if (!subnetService.exists(routerInterface.subnetId())) {
+ log.debug("The subnet ID of interface is not exist whose identifier is {}",
+ routerInterface.subnetId().toString());
+ throw new IllegalArgumentException(
+ "subnet ID of interface doesn't exist");
+ }
+ if (!virtualPortService.exists(routerInterface.portId())) {
+ log.debug("The port ID of interface is not exist whose identifier is {}",
+ routerInterface.portId().toString());
+ throw new IllegalArgumentException(
+ "port ID of interface doesn't exist");
+ }
+ if (!routerService.exists(routerInterface.routerId())) {
+ log.debug("The router ID of interface is not exist whose identifier is {}",
+ routerInterface.routerId().toString());
+ throw new IllegalArgumentException(
+ "router ID of interface doesn't exist");
+ }
+ }
+
+ private class InnerRouterInterfaceStoreListener
+ implements
+ EventuallyConsistentMapListener<SubnetId, RouterInterface> {
+
+ @Override
+ public void event(EventuallyConsistentMapEvent<SubnetId, RouterInterface> event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ RouterInterface routerInterface = event.value();
+ if (EventuallyConsistentMapEvent.Type.PUT == event.type()) {
+ notifyListeners(new RouterInterfaceEvent(
+ RouterInterfaceEvent.Type.ROUTER_INTERFACE_PUT,
+ routerInterface));
+ }
+ if (EventuallyConsistentMapEvent.Type.REMOVE == event.type()) {
+ notifyListeners(new RouterInterfaceEvent(
+ RouterInterfaceEvent.Type.ROUTER_INTERFACE_DELETE,
+ routerInterface));
+ }
+ }
+ }
+
+ /**
+ * Notifies specify event to all listeners.
+ *
+ * @param event Floating IP event
+ */
+ private void notifyListeners(RouterInterfaceEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ listeners.forEach(listener -> listener.event(event));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/package-info.java
new file mode 100644
index 00000000..71db9dc5
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides implementation of the RouterInterface service.
+ */
+package org.onosproject.vtnrsc.routerinterface.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/package-info.java
new file mode 100644
index 00000000..3804089a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/routerinterface/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with the inventory of RouterInterface.
+ */
+package org.onosproject.vtnrsc.routerinterface;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java
new file mode 100644
index 00000000..21161ba5
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/VtnRscService.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.service;
+
+import java.util.Iterator;
+
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.event.VtnRscListener;
+
+/**
+ * Service for interacting with the inventory of Vtn resource.
+ */
+public interface VtnRscService {
+ /**
+ * Adds the specified listener.
+ *
+ * @param listener VtnRsc listener
+ */
+ void addListener(VtnRscListener listener);
+
+ /**
+ * Removes the specified listener.
+ *
+ * @param listener VtnRsc listener
+ */
+ void removeListener(VtnRscListener listener);
+
+ /**
+ * Returns the SegmentationId of tenant.
+ *
+ * @param tenantId tenant identifier
+ * @return SegmentationId the SegmentationId of tenant
+ */
+ SegmentationId getL3vni(TenantId tenantId);
+
+ /**
+ * Returns Classifier Ovs list of the specific tenant.
+ *
+ * @param tenantId tenant identifier
+ * @return iterable collection of Device
+ */
+ Iterator<Device> getClassifierOfTenant(TenantId tenantId);
+
+ /**
+ * Returns Service function forwarders Ovs list of the specific tenant.
+ *
+ * @param tenantId tenant identifier
+ * @return iterable collection of Device
+ */
+ Iterator<Device> getSFFOfTenant(TenantId tenantId);
+
+ /**
+ * Returns gateway mac address of the specific host.
+ *
+ * @param hostId host identifier
+ * @return MacAddress of host
+ */
+ MacAddress getGatewayMac(HostId hostId);
+
+ /**
+ * Checks if a specific port is a service function.
+ *
+ * @param portId port identifier
+ * @return true or false
+ */
+ boolean isServiceFunction(VirtualPortId portId);
+
+ /**
+ * Returns device identifier mapping to the specific port.
+ *
+ * @param portId port identifier
+ * @return device identifier
+ */
+ DeviceId getSFToSFFMaping(VirtualPortId portId);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java
new file mode 100644
index 00000000..ec9ca3ef
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/VtnRscManager.java
@@ -0,0 +1,472 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.service.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.host.HostEvent;
+import org.onosproject.net.host.HostListener;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.LogicalClockService;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.vtnrsc.FixedIp;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.onosproject.vtnrsc.Subnet;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPort;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.event.VtnRscEvent;
+import org.onosproject.vtnrsc.event.VtnRscEventFeedback;
+import org.onosproject.vtnrsc.event.VtnRscListener;
+import org.onosproject.vtnrsc.floatingip.FloatingIpEvent;
+import org.onosproject.vtnrsc.floatingip.FloatingIpListener;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+import org.onosproject.vtnrsc.router.RouterEvent;
+import org.onosproject.vtnrsc.router.RouterListener;
+import org.onosproject.vtnrsc.router.RouterService;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceEvent;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceListener;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+import org.onosproject.vtnrsc.service.VtnRscService;
+import org.onosproject.vtnrsc.subnet.SubnetService;
+import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
+import org.onosproject.vtnrsc.virtualport.VirtualPortService;
+import org.slf4j.Logger;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Provides implementation of the VtnRsc service.
+ */
+@Component(immediate = true)
+@Service
+public class VtnRscManager implements VtnRscService {
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LogicalClockService clockService;
+
+ private final Logger log = getLogger(getClass());
+ private final Set<VtnRscListener> listeners = Sets.newCopyOnWriteArraySet();
+ private HostListener hostListener = new InnerHostListener();
+ private FloatingIpListener floatingIpListener = new InnerFloatingIpListener();
+ private RouterListener routerListener = new InnerRouterListener();
+ private RouterInterfaceListener routerInterfaceListener = new InnerRouterInterfaceListener();
+
+ private EventuallyConsistentMap<TenantId, SegmentationId> l3vniMap;
+ private EventuallyConsistentMap<TenantId, Set<DeviceId>> classifierOvsMap;
+ private EventuallyConsistentMap<TenantId, Set<DeviceId>> sffOvsMap;
+
+ private static final String IFACEID = "ifaceid";
+ private static final String RUNNELOPTOPOIC = "tunnel-ops-ids";
+ private static final String LISTENER_NOT_NULL = "listener cannot be null";
+ private static final String EVENT_NOT_NULL = "event cannot be null";
+ private static final String TENANTID_NOT_NULL = "tenantId cannot be null";
+ private static final String DEVICEID_NOT_NULL = "deviceId cannot be null";
+ private static final String OVSMAP_NOT_NULL = "ovsMap cannot be null";
+ private static final String L3VNIMAP = "l3vniMap";
+ private static final String CLASSIFIEROVSMAP = "classifierOvsMap";
+ private static final String SFFOVSMAP = "sffOvsMap";
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RouterService routerService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FloatingIpService floatingIpService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected RouterInterfaceService routerInterfaceService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected VirtualPortService virtualPortService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected SubnetService subnetService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected TenantNetworkService tenantNetworkService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
+
+ @Activate
+ public void activate() {
+ hostService.addListener(hostListener);
+ floatingIpService.addListener(floatingIpListener);
+ routerService.addListener(routerListener);
+ routerInterfaceService.addListener(routerInterfaceListener);
+
+ KryoNamespace.Builder serializer = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(TenantId.class, DeviceId.class);
+ l3vniMap = storageService
+ .<TenantId, SegmentationId>eventuallyConsistentMapBuilder()
+ .withName(L3VNIMAP).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+
+ classifierOvsMap = storageService
+ .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
+ .withName(CLASSIFIEROVSMAP).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+
+ sffOvsMap = storageService
+ .<TenantId, Set<DeviceId>>eventuallyConsistentMapBuilder()
+ .withName(SFFOVSMAP).withSerializer(serializer)
+ .withTimestampProvider((k, v) -> clockService.getTimestamp())
+ .build();
+ }
+
+ @Deactivate
+ public void deactivate() {
+ hostService.removeListener(hostListener);
+ floatingIpService.removeListener(floatingIpListener);
+ routerService.removeListener(routerListener);
+ routerInterfaceService.removeListener(routerInterfaceListener);
+ l3vniMap.destroy();
+ classifierOvsMap.destroy();
+ sffOvsMap.destroy();
+ listeners.clear();
+ log.info("Stopped");
+ }
+
+ @Override
+ public void addListener(VtnRscListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(VtnRscListener listener) {
+ checkNotNull(listener, LISTENER_NOT_NULL);
+ listeners.add(listener);
+ }
+
+ @Override
+ public SegmentationId getL3vni(TenantId tenantId) {
+ checkNotNull(tenantId, "tenantId cannot be null");
+ SegmentationId l3vni = l3vniMap.get(tenantId);
+ if (l3vni == null) {
+ long segmentationId = coreService.getIdGenerator(RUNNELOPTOPOIC)
+ .getNewId();
+ l3vni = SegmentationId.segmentationId(String
+ .valueOf(segmentationId));
+ l3vniMap.put(tenantId, l3vni);
+ }
+ return l3vni;
+ }
+
+ private class InnerHostListener implements HostListener {
+
+ @Override
+ public void event(HostEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ Host host = event.subject();
+ String ifaceId = host.annotations().value(IFACEID);
+ VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
+ TenantId tenantId = virtualPortService.getPort(hPortId).tenantId();
+ DeviceId deviceId = host.location().deviceId();
+ if (HostEvent.Type.HOST_ADDED == event.type()) {
+ if (isServiceFunction(hPortId)) {
+ addDeviceIdOfOvsMap(tenantId, deviceId, sffOvsMap);
+ } else {
+ addDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
+ }
+ } else if (HostEvent.Type.HOST_REMOVED == event.type()) {
+ if (isLastSFHostOfTenant(host, deviceId, tenantId)) {
+ removeDeviceIdOfOvsMap(tenantId, deviceId, sffOvsMap);
+ }
+ if (isLastClassifierHostOfTenant(host, deviceId, tenantId)) {
+ removeDeviceIdOfOvsMap(tenantId, deviceId, classifierOvsMap);
+ }
+ }
+ }
+ }
+
+ private class InnerFloatingIpListener implements FloatingIpListener {
+
+ @Override
+ public void event(FloatingIpEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ FloatingIp floatingIp = event.subject();
+ if (FloatingIpEvent.Type.FLOATINGIP_PUT == event.type()) {
+ notifyListeners(new VtnRscEvent(
+ VtnRscEvent.Type.FLOATINGIP_PUT,
+ new VtnRscEventFeedback(
+ floatingIp)));
+ }
+ if (FloatingIpEvent.Type.FLOATINGIP_DELETE == event.type()) {
+ notifyListeners(new VtnRscEvent(
+ VtnRscEvent.Type.FLOATINGIP_DELETE,
+ new VtnRscEventFeedback(
+ floatingIp)));
+ }
+ }
+ }
+
+ private class InnerRouterListener implements RouterListener {
+
+ @Override
+ public void event(RouterEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ Router router = event.subject();
+ if (RouterEvent.Type.ROUTER_PUT == event.type()) {
+ notifyListeners(new VtnRscEvent(VtnRscEvent.Type.ROUTER_PUT,
+ new VtnRscEventFeedback(router)));
+ }
+ if (RouterEvent.Type.ROUTER_DELETE == event.type()) {
+ notifyListeners(new VtnRscEvent(VtnRscEvent.Type.ROUTER_DELETE,
+ new VtnRscEventFeedback(router)));
+ }
+ }
+ }
+
+ private class InnerRouterInterfaceListener
+ implements RouterInterfaceListener {
+
+ @Override
+ public void event(RouterInterfaceEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ RouterInterface routerInterface = event.subject();
+ if (RouterInterfaceEvent.Type.ROUTER_INTERFACE_PUT == event.type()) {
+ notifyListeners(new VtnRscEvent(
+ VtnRscEvent.Type.ROUTER_INTERFACE_PUT,
+ new VtnRscEventFeedback(
+ routerInterface)));
+ }
+ if (RouterInterfaceEvent.Type.ROUTER_INTERFACE_DELETE == event
+ .type()) {
+ notifyListeners(new VtnRscEvent(
+ VtnRscEvent.Type.ROUTER_INTERFACE_DELETE,
+ new VtnRscEventFeedback(
+ routerInterface)));
+ }
+ }
+ }
+
+ @Override
+ public Iterator<Device> getClassifierOfTenant(TenantId tenantId) {
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ Set<DeviceId> deviceIdSet = classifierOvsMap.get(tenantId);
+ Set<Device> deviceSet = new HashSet<>();
+ if (deviceIdSet != null) {
+ for (DeviceId deviceId : deviceIdSet) {
+ deviceSet.add(deviceService.getDevice(deviceId));
+ }
+ }
+ return deviceSet.iterator();
+ }
+
+ @Override
+ public Iterator<Device> getSFFOfTenant(TenantId tenantId) {
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ Set<DeviceId> deviceIdSet = sffOvsMap.get(tenantId);
+ Set<Device> deviceSet = new HashSet<>();
+ if (deviceIdSet != null) {
+ for (DeviceId deviceId : deviceIdSet) {
+ deviceSet.add(deviceService.getDevice(deviceId));
+ }
+ }
+ return deviceSet.iterator();
+ }
+
+ @Override
+ public MacAddress getGatewayMac(HostId hostId) {
+ checkNotNull(hostId, "hostId cannot be null");
+ Host host = hostService.getHost(hostId);
+ String ifaceId = host.annotations().value(IFACEID);
+ VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
+ VirtualPort hPort = virtualPortService.getPort(hPortId);
+ SubnetId subnetId = hPort.fixedIps().iterator().next().subnetId();
+ Subnet subnet = subnetService.getSubnet(subnetId);
+ IpAddress gatewayIp = subnet.gatewayIp();
+ Iterable<VirtualPort> virtualPorts = virtualPortService.getPorts();
+ MacAddress macAddress = null;
+ for (VirtualPort port : virtualPorts) {
+ Set<FixedIp> fixedIpSet = port.fixedIps();
+ for (FixedIp fixedIp : fixedIpSet) {
+ if (fixedIp.ip().equals(gatewayIp)) {
+ macAddress = port.macAddress();
+ }
+ }
+ }
+ return macAddress;
+ }
+
+ @Override
+ public boolean isServiceFunction(VirtualPortId portId) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public DeviceId getSFToSFFMaping(VirtualPortId portId) {
+ checkNotNull(portId, "portId cannot be null");
+ VirtualPort vmPort = virtualPortService.getPort(portId);
+ Set<Host> hostSet = hostService.getHostsByMac(vmPort.macAddress());
+ for (Host host : hostSet) {
+ if (host.annotations().value(IFACEID).equals(vmPort.portId())) {
+ return host.location().deviceId();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Checks whether the last Service Function host of a specific tenant in
+ * this device.
+ *
+ * @param host the host on device
+ * @param deviceId the device identifier
+ * @param tenantId the tenant identifier
+ * @return true or false
+ */
+ private boolean isLastSFHostOfTenant(Host host, DeviceId deviceId,
+ TenantId tenantId) {
+ checkNotNull(host, "host cannot be null");
+ checkNotNull(deviceId, DEVICEID_NOT_NULL);
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ Set<Host> hostSet = hostService.getConnectedHosts(deviceId);
+ for (Host h : hostSet) {
+ String ifaceId = h.annotations().value(IFACEID);
+ VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
+ if (virtualPortService.getPort(hPortId).tenantId() != tenantId) {
+ hostSet.remove(h);
+ } else {
+ if (!isServiceFunction(hPortId)) {
+ hostSet.remove(h);
+ }
+ }
+ }
+ if (hostSet.size() == 1 && hostSet.contains(host)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks whether the last Classifier host of a specific tenant in this
+ * device.
+ *
+ * @param host the host on device
+ * @param deviceId the device identifier
+ * @param tenantId the tenant identifier
+ * @return true or false
+ */
+ private boolean isLastClassifierHostOfTenant(Host host, DeviceId deviceId,
+ TenantId tenantId) {
+ checkNotNull(host, "host cannot be null");
+ checkNotNull(deviceId, DEVICEID_NOT_NULL);
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ Set<Host> hostSet = hostService.getConnectedHosts(deviceId);
+ for (Host h : hostSet) {
+ String ifaceId = h.annotations().value(IFACEID);
+ VirtualPortId hPortId = VirtualPortId.portId(ifaceId);
+ if (virtualPortService.getPort(hPortId).tenantId() != tenantId) {
+ hostSet.remove(h);
+ } else {
+ if (isServiceFunction(hPortId)) {
+ hostSet.remove(h);
+ }
+ }
+ }
+ if (hostSet.size() == 1 && hostSet.contains(host)) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Adds specify Device identifier to OvsMap.
+ *
+ * @param tenantId the tenant identifier
+ * @param deviceId the device identifier
+ * @param ovsMap the instance of map to store device identifier
+ */
+ private void addDeviceIdOfOvsMap(TenantId tenantId,
+ DeviceId deviceId,
+ EventuallyConsistentMap<TenantId, Set<DeviceId>> ovsMap) {
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ checkNotNull(deviceId, DEVICEID_NOT_NULL);
+ checkNotNull(ovsMap, OVSMAP_NOT_NULL);
+ if (ovsMap.containsKey(tenantId)) {
+ Set<DeviceId> deviceIdSet = ovsMap.get(tenantId);
+ deviceIdSet.add(deviceId);
+ ovsMap.put(tenantId, deviceIdSet);
+ } else {
+ Set<DeviceId> deviceIdSet = new HashSet<>();
+ deviceIdSet.add(deviceId);
+ ovsMap.put(tenantId, deviceIdSet);
+ }
+ }
+
+ /**
+ * Removes specify Device identifier from OvsMap.
+ *
+ * @param tenantId the tenant identifier
+ * @param deviceId the device identifier
+ * @param ovsMap the instance of map to store device identifier
+ */
+ private void removeDeviceIdOfOvsMap(TenantId tenantId,
+ DeviceId deviceId,
+ EventuallyConsistentMap<TenantId, Set<DeviceId>> ovsMap) {
+ checkNotNull(tenantId, TENANTID_NOT_NULL);
+ checkNotNull(deviceId, DEVICEID_NOT_NULL);
+ checkNotNull(ovsMap, OVSMAP_NOT_NULL);
+ Set<DeviceId> deviceIdSet = ovsMap.get(tenantId);
+ if (deviceIdSet.size() > 1) {
+ deviceIdSet.remove(deviceId);
+ ovsMap.put(tenantId, deviceIdSet);
+ } else {
+ ovsMap.remove(tenantId);
+ }
+ }
+
+ /**
+ * Notifies specify event to all listeners.
+ *
+ * @param event VtnRsc event
+ */
+ private void notifyListeners(VtnRscEvent event) {
+ checkNotNull(event, EVENT_NOT_NULL);
+ listeners.forEach(listener -> listener.event(event));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/package-info.java
new file mode 100644
index 00000000..aaea08b3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/impl/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Provides implementation of the VtnRsc service.
+ */
+package org.onosproject.vtnrsc.service.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/package-info.java
new file mode 100644
index 00000000..37af604a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/service/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Service for interacting with the inventory of Vtn resource.
+ */
+package org.onosproject.vtnrsc.service;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/subnet/impl/SubnetManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/subnet/impl/SubnetManager.java
index 890beb29..94430389 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/subnet/impl/SubnetManager.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/subnet/impl/SubnetManager.java
@@ -144,21 +144,19 @@ public class SubnetManager implements SubnetService {
@Override
public boolean updateSubnets(Iterable<Subnet> subnets) {
checkNotNull(subnets, SUBNET_NOT_NULL);
- if (subnets != null) {
- for (Subnet subnet : subnets) {
- if (!subnetStore.containsKey(subnet.id())) {
- log.debug("The subnet is not exist whose identifier is {}",
- subnet.id().toString());
- return false;
- }
-
- subnetStore.put(subnet.id(), subnet);
-
- if (!subnet.equals(subnetStore.get(subnet.id()))) {
- log.debug("The subnet is updated failed whose identifier is {}",
- subnet.id().toString());
- return false;
- }
+ for (Subnet subnet : subnets) {
+ if (!subnetStore.containsKey(subnet.id())) {
+ log.debug("The subnet is not exist whose identifier is {}",
+ subnet.id().toString());
+ return false;
+ }
+
+ subnetStore.put(subnet.id(), subnet);
+
+ if (!subnet.equals(subnetStore.get(subnet.id()))) {
+ log.debug("The subnet is updated failed whose identifier is {}",
+ subnet.id().toString());
+ return false;
}
}
return true;
@@ -167,14 +165,12 @@ public class SubnetManager implements SubnetService {
@Override
public boolean removeSubnets(Iterable<SubnetId> subnetIds) {
checkNotNull(subnetIds, SUBNET_ID_NULL);
- if (subnetIds != null) {
- for (SubnetId subnetId : subnetIds) {
- subnetStore.remove(subnetId);
- if (subnetStore.containsKey(subnetId)) {
- log.debug("The subnet created is failed whose identifier is {}",
- subnetId.toString());
- return false;
- }
+ for (SubnetId subnetId : subnetIds) {
+ subnetStore.remove(subnetId);
+ if (subnetStore.containsKey(subnetId)) {
+ log.debug("The subnet created is failed whose identifier is {}",
+ subnetId.toString());
+ return false;
}
}
return true;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/apps/vtn/vtnrsc/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index c6a9c81b..f7a1bf44 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -52,5 +52,38 @@
<command>
<action class="org.onosproject.vtnrsc.cli.virtualport.VirtualPortUpdateCommand"/>
</command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.floatingip.FloatingIpCreateCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.floatingip.FloatingIpQueryCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.floatingip.FloatingIpRemoveCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.floatingip.FloatingIpUpdateCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.router.RouterCreateCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.router.RouterQueryCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.router.RouterRemoveCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.router.RouterUpdateCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.routerinterface.RouterInterfaceCreateCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.routerinterface.RouterInterfaceRemoveCommand"/>
+ </command>
+ <command>
+ <action class="org.onosproject.vtnrsc.cli.routerinterface.RouterInterfaceQueryCommand"/>
+ </command>
</command-bundle>
</blueprint>
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/AllowedAddressPairTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/AllowedAddressPairTest.java
new file mode 100644
index 00000000..05152359
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/AllowedAddressPairTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for AllowedAddressPair class.
+ */
+public class AllowedAddressPairTest {
+
+ final IpAddress ip1 = IpAddress.valueOf("192.168.0.1");
+ final IpAddress ip2 = IpAddress.valueOf("192.168.0.2");
+ final MacAddress mac1 = MacAddress.valueOf("fa:16:3e:76:83:88");
+ final MacAddress mac2 = MacAddress.valueOf("aa:16:3e:76:83:88");
+
+ /**
+ * Checks that the AllowedAddressPair class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(AllowedAddressPair.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ AllowedAddressPair p1 = AllowedAddressPair
+ .allowedAddressPair(ip1, mac1);
+ AllowedAddressPair p2 = AllowedAddressPair
+ .allowedAddressPair(ip1, mac1);
+ AllowedAddressPair p3 = AllowedAddressPair
+ .allowedAddressPair(ip2, mac2);
+ new EqualsTester().addEqualityGroup(p1, p2).addEqualityGroup(p3)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a AllowedAddressPair object.
+ */
+ @Test
+ public void testConstruction() {
+ AllowedAddressPair allowedAddressPair = AllowedAddressPair
+ .allowedAddressPair(ip1, mac1);
+ assertThat(ip1, is(notNullValue()));
+ assertThat(ip1, is(allowedAddressPair.ip()));
+ assertThat(mac1, is(notNullValue()));
+ assertThat(mac1, is(allowedAddressPair.mac()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultAllocationPoolTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultAllocationPoolTest.java
new file mode 100644
index 00000000..9e7d3c1c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultAllocationPoolTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultAllocationPool class.
+ */
+public class DefaultAllocationPoolTest {
+
+ final IpAddress startIP1 = IpAddress.valueOf("192.168.1.1");
+ final IpAddress startIP2 = IpAddress.valueOf("192.168.1.2");
+ final IpAddress endIP1 = IpAddress.valueOf("192.168.1.1");
+ final IpAddress endIP2 = IpAddress.valueOf("192.168.1.2");
+
+ /**
+ * Checks that the DefaultAllocationPool class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultAllocationPool.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ AllocationPool pool1 = new DefaultAllocationPool(startIP1, endIP1);
+ AllocationPool pool2 = new DefaultAllocationPool(startIP1, endIP1);
+ AllocationPool pool3 = new DefaultAllocationPool(startIP2, endIP2);
+ new EqualsTester().addEqualityGroup(pool1, pool2)
+ .addEqualityGroup(pool3).testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultAllocationPool object.
+ */
+ @Test
+ public void testConstruction() {
+ final AllocationPool apool = new DefaultAllocationPool(startIP1, endIP1);
+ assertThat(startIP1, is(apool.startIp()));
+ assertThat(endIP1, is(apool.endIp()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultFlowClassifierTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultFlowClassifierTest.java
new file mode 100644
index 00000000..7032c216
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultFlowClassifierTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultFlowClassifier class.
+ */
+public class DefaultFlowClassifierTest {
+ /**
+ * Checks that the DefaultFlowClassifier class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultFlowClassifier.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ // Create same two flow classifier objects.
+ final String name = "FlowClassifier1";
+ final String description = "FlowClassifier1";
+ final String ethType = "IPv4";
+ final String protocol = "tcp";
+ final int minSrcPortRange = 5;
+ final int maxSrcPortRange = 10;
+ final int minDstPortRange = 5;
+ final int maxDstPortRange = 10;
+ final FlowClassifierId flowClassifierId = FlowClassifierId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final IpPrefix srcIpPrefix = IpPrefix.valueOf("0.0.0.0/0");
+ final IpPrefix dstIpPrefix = IpPrefix.valueOf("10.10.10.10/0");
+ final VirtualPortId virtualSrcPort = VirtualPortId.portId("1");
+ final VirtualPortId virtualDstPort = VirtualPortId.portId("2");
+
+ DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder();
+ final FlowClassifier flowClassifier1 = flowClassifierBuilder.setFlowClassifierId(flowClassifierId)
+ .setTenantId(tenantId).setName(name).setDescription(description).setEtherType(ethType)
+ .setProtocol(protocol).setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange)
+ .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix)
+ .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build();
+
+ flowClassifierBuilder = new DefaultFlowClassifier.Builder();
+ final FlowClassifier sameAsFlowClassifier1 = flowClassifierBuilder.setFlowClassifierId(flowClassifierId)
+ .setTenantId(tenantId).setName(name).setDescription(description).setEtherType(ethType)
+ .setProtocol(protocol).setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange)
+ .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix)
+ .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build();
+
+ // Create different classifier object.
+ final String name2 = "FlowClassifier2";
+ final String description2 = "FlowClassifier2";
+ final String ethType2 = "IPv6";
+ final String protocol2 = "udp";
+ final int minSrcPortRange2 = 5;
+ final int maxSrcPortRange2 = 10;
+ final int minDstPortRange2 = 5;
+ final int maxDstPortRange2 = 10;
+ final FlowClassifierId flowClassifierId2 = FlowClassifierId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final IpPrefix srcIpPrefix2 = IpPrefix.valueOf("0.0.0.0/0");
+ final IpPrefix dstIpPrefix2 = IpPrefix.valueOf("10.10.10.10/0");
+ final VirtualPortId virtualSrcPort2 = VirtualPortId.portId("3");
+ final VirtualPortId virtualDstPort2 = VirtualPortId.portId("4");
+
+ DefaultFlowClassifier.Builder flowClassifierBuilder3 = new DefaultFlowClassifier.Builder();
+ final FlowClassifier flowClassifier2 = flowClassifierBuilder3.setFlowClassifierId(flowClassifierId2)
+ .setTenantId(tenantId2).setName(name2).setDescription(description2).setEtherType(ethType2)
+ .setProtocol(protocol2).setMinSrcPortRange(minSrcPortRange2).setMaxSrcPortRange(maxSrcPortRange2)
+ .setMinDstPortRange(minDstPortRange2).setMaxDstPortRange(maxDstPortRange2).setSrcIpPrefix(srcIpPrefix2)
+ .setDstIpPrefix(dstIpPrefix2).setSrcPort(virtualSrcPort2).setDstPort(virtualDstPort2).build();
+
+ new EqualsTester().addEqualityGroup(flowClassifier1, sameAsFlowClassifier1).addEqualityGroup(flowClassifier2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultFlowClassifier object.
+ */
+ @Test
+ public void testConstruction() {
+ final String name = "FlowClassifier";
+ final String description = "FlowClassifier";
+ final String ethType = "IPv4";
+ final String protocol = "tcp";
+ final int minSrcPortRange = 5;
+ final int maxSrcPortRange = 10;
+ final int minDstPortRange = 5;
+ final int maxDstPortRange = 10;
+ final FlowClassifierId flowClassifierId = FlowClassifierId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final IpPrefix srcIpPrefix = IpPrefix.valueOf("0.0.0.0/0");
+ final IpPrefix dstIpPrefix = IpPrefix.valueOf("10.10.10.10/0");
+ final VirtualPortId virtualSrcPort = VirtualPortId.portId("1");
+ final VirtualPortId virtualDstPort = VirtualPortId.portId("2");
+
+ DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder();
+ final FlowClassifier flowClassifier = flowClassifierBuilder.setFlowClassifierId(flowClassifierId)
+ .setTenantId(tenantId).setName(name).setDescription(description).setEtherType(ethType)
+ .setProtocol(protocol).setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange)
+ .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix)
+ .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build();
+
+ assertThat(flowClassifierId, is(flowClassifier.flowClassifierId()));
+ assertThat(tenantId, is(flowClassifier.tenantId()));
+ assertThat(name, is(flowClassifier.name()));
+ assertThat(description, is(flowClassifier.description()));
+ assertThat(ethType, is(flowClassifier.etherType()));
+ assertThat(protocol, is(flowClassifier.protocol()));
+ assertThat(minSrcPortRange, is(flowClassifier.minSrcPortRange()));
+ assertThat(maxSrcPortRange, is(flowClassifier.maxSrcPortRange()));
+ assertThat(minDstPortRange, is(flowClassifier.minDstPortRange()));
+ assertThat(maxDstPortRange, is(flowClassifier.maxDstPortRange()));
+ assertThat(srcIpPrefix, is(flowClassifier.srcIpPrefix()));
+ assertThat(dstIpPrefix, is(flowClassifier.dstIpPrefix()));
+ assertThat(virtualSrcPort, is(flowClassifier.srcPort()));
+ assertThat(virtualDstPort, is(flowClassifier.dstPort()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultHostRouteTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultHostRouteTest.java
new file mode 100644
index 00000000..53ead67f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultHostRouteTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultHostRoute class.
+ */
+public class DefaultHostRouteTest {
+ final IpAddress nexthop1 = IpAddress.valueOf("192.168.1.1");
+ final IpAddress nexthop2 = IpAddress.valueOf("192.168.1.2");
+ final IpPrefix destination1 = IpPrefix.valueOf("1.1.1.1/1");
+ final IpPrefix destination2 = IpPrefix.valueOf("1.1.1.1/2");
+
+ /**
+ * Checks that the DefaultHostRoute class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultHostRoute.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ HostRoute route1 = new DefaultHostRoute(nexthop1, destination1);
+ HostRoute route2 = new DefaultHostRoute(nexthop1, destination1);
+ HostRoute route3 = new DefaultHostRoute(nexthop2, destination2);
+ new EqualsTester().addEqualityGroup(route1, route2)
+ .addEqualityGroup(route3).testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultHostRoute object.
+ */
+ @Test
+ public void testConstruction() {
+ final HostRoute host = new DefaultHostRoute(nexthop1, destination1);
+ assertThat(nexthop1, is(host.nexthop()));
+ assertThat(destination1, is(host.destination()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultNeutronNetworkTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultNeutronNetworkTest.java
new file mode 100644
index 00000000..7f186a1d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultNeutronNetworkTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultNeutronNetwork class.
+ */
+public class DefaultNeutronNetworkTest {
+
+ private String networkIdStr1 = "123";
+ private String networkIdStr2 = "234";
+ private String physicalNetworkStr = "1234";
+ private String tenantIdStr = "345";
+ private String segmentationIdStr = "1";
+ private String name = "456";
+
+ /**
+ * Checks that the DefaultNeutronNetwork class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultTenantNetwork.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquality() {
+ TenantNetworkId networkid1 = TenantNetworkId.networkId(networkIdStr1);
+ TenantNetworkId networkid2 = TenantNetworkId.networkId(networkIdStr2);
+ PhysicalNetwork physicalNetwork = PhysicalNetwork
+ .physicalNetwork(physicalNetworkStr);
+ TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ SegmentationId segmentationID = SegmentationId
+ .segmentationId(segmentationIdStr);
+ TenantNetwork p1 = new DefaultTenantNetwork(networkid1, name, false,
+ TenantNetwork.State.ACTIVE,
+ false, tenantId, false,
+ TenantNetwork.Type.LOCAL,
+ physicalNetwork,
+ segmentationID);
+ TenantNetwork p2 = new DefaultTenantNetwork(networkid1, name, false,
+ TenantNetwork.State.ACTIVE,
+ false, tenantId, false,
+ TenantNetwork.Type.LOCAL,
+ physicalNetwork,
+ segmentationID);
+ TenantNetwork p3 = new DefaultTenantNetwork(networkid2, name, false,
+ TenantNetwork.State.ACTIVE,
+ false, tenantId, false,
+ TenantNetwork.Type.LOCAL,
+ physicalNetwork,
+ segmentationID);
+ new EqualsTester().addEqualityGroup(p1, p2).addEqualityGroup(p3)
+ .testEquals();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortChainTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortChainTest.java
new file mode 100644
index 00000000..27234ac3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortChainTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultPortChain class.
+ */
+public class DefaultPortChainTest {
+ /**
+ * Checks that the DefaultPortChain class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPortChain.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ // Create same two port chain objects.
+ final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortChain1";
+ final String description = "PortChain1";
+ // create list of Port Pair Groups.
+ final List<PortPairGroupId> portPairGroups = new LinkedList<PortPairGroupId>();
+ PortPairGroupId portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairGroups.add(portPairGroupId);
+ portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3af");
+ portPairGroups.add(portPairGroupId);
+ // create list of Flow classifiers.
+ final List<FlowClassifierId> flowClassifiers = new LinkedList<FlowClassifierId>();
+ FlowClassifierId flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ flowClassifiers.add(flowClassifierId);
+ flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3af");
+ flowClassifiers.add(flowClassifierId);
+
+ DefaultPortChain.Builder portChainBuilder = new DefaultPortChain.Builder();
+ final PortChain portChain1 = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setPortPairGroups(portPairGroups).setFlowClassifiers(flowClassifiers)
+ .build();
+
+ portChainBuilder = new DefaultPortChain.Builder();
+ final PortChain samePortChain1 = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setPortPairGroups(portPairGroups).setFlowClassifiers(flowClassifiers)
+ .build();
+
+ // Create different port chain object.
+ final PortChainId portChainId2 = PortChainId.of("79999999-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortChain2";
+ final String description2 = "PortChain2";
+ // create list of Port Pair Groups.
+ final List<PortPairGroupId> portPairGroups2 = new LinkedList<PortPairGroupId>();
+ portPairGroupId = PortPairGroupId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairGroups2.add(portPairGroupId);
+ portPairGroupId = PortPairGroupId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3af");
+ portPairGroups2.add(portPairGroupId);
+ // create list of Flow classifiers.
+ final List<FlowClassifierId> flowClassifiers2 = new LinkedList<FlowClassifierId>();
+ flowClassifierId = FlowClassifierId.of("76666666-fc23-aeb6-f44b-56dc5e2fb3ae");
+ flowClassifiers2.add(flowClassifierId);
+ flowClassifierId = FlowClassifierId.of("76666666-fc23-aeb6-f44b-56dc5e2fb3af");
+ flowClassifiers2.add(flowClassifierId);
+
+ portChainBuilder = new DefaultPortChain.Builder();
+ final PortChain portChain2 = portChainBuilder.setId(portChainId2).setTenantId(tenantId2).setName(name2)
+ .setDescription(description2).setPortPairGroups(portPairGroups2).setFlowClassifiers(flowClassifiers2)
+ .build();
+
+ new EqualsTester().addEqualityGroup(portChain1, samePortChain1).addEqualityGroup(portChain2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultPortChain object.
+ */
+ @Test
+ public void testConstruction() {
+ final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortChain";
+ final String description = "PortChain";
+ // create list of Port Pair Groups.
+ final List<PortPairGroupId> portPairGroups = new LinkedList<PortPairGroupId>();
+ PortPairGroupId portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairGroups.add(portPairGroupId);
+ portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3af");
+ portPairGroups.add(portPairGroupId);
+ // create list of Flow classifiers.
+ final List<FlowClassifierId> flowClassifiers = new LinkedList<FlowClassifierId>();
+ FlowClassifierId flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ flowClassifiers.add(flowClassifierId);
+ flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3af");
+ flowClassifiers.add(flowClassifierId);
+
+ DefaultPortChain.Builder portChainBuilder = new DefaultPortChain.Builder();
+ final PortChain portChain = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setPortPairGroups(portPairGroups).setFlowClassifiers(flowClassifiers)
+ .build();
+
+ assertThat(portChainId, is(portChain.portChainId()));
+ assertThat(tenantId, is(portChain.tenantId()));
+ assertThat(name, is(portChain.name()));
+ assertThat(description, is(portChain.description()));
+ assertThat(portPairGroups, is(portChain.portPairGroups()));
+ assertThat(flowClassifiers, is(portChain.flowClassifiers()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairGroupTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairGroupTest.java
new file mode 100644
index 00000000..1b484e94
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairGroupTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultPortPairGroup class.
+ */
+public class DefaultPortPairGroupTest {
+ /**
+ * Checks that the DefaultPortPairGroup class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPortPairGroup.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ // Create same two port-pair-group objects.
+ final PortPairGroupId portPairGroupId = PortPairGroupId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPairGroup1";
+ final String description = "PortPairGroup1";
+ // create port-pair-id list
+ final List<PortPairId> portPairList = new LinkedList<PortPairId>();
+ PortPairId portPairId = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList.add(portPairId);
+ portPairId = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList.add(portPairId);
+
+ DefaultPortPairGroup.Builder portPairGroupBuilder = new DefaultPortPairGroup.Builder();
+ final PortPairGroup portPairGroup1 = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId)
+ .setName(name).setDescription(description).setPortPairs(portPairList).build();
+
+ portPairGroupBuilder = new DefaultPortPairGroup.Builder();
+ final PortPairGroup samePortPairGroup1 = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId)
+ .setName(name).setDescription(description).setPortPairs(portPairList).build();
+
+ // Create different port-pair-group object.
+ final PortPairGroupId portPairGroupId2 = PortPairGroupId.of("79999999-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortPairGroup2";
+ final String description2 = "PortPairGroup2";
+ // create port-pair-id list
+ final List<PortPairId> portPairList2 = new LinkedList<PortPairId>();
+ portPairId = PortPairId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList2.add(portPairId);
+ portPairId = PortPairId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList2.add(portPairId);
+
+ portPairGroupBuilder = new DefaultPortPairGroup.Builder();
+ final PortPairGroup portPairGroup2 = portPairGroupBuilder.setId(portPairGroupId2).setTenantId(tenantId2)
+ .setName(name2).setDescription(description2).setPortPairs(portPairList2).build();
+
+ new EqualsTester().addEqualityGroup(portPairGroup1, samePortPairGroup1).addEqualityGroup(portPairGroup2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultPortPairGroup object.
+ */
+ @Test
+ public void testConstruction() {
+ final PortPairGroupId portPairGroupId = PortPairGroupId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPairGroup";
+ final String description = "PortPairGroup";
+ // create port-pair-id list
+ final List<PortPairId> portPairList = new LinkedList<PortPairId>();
+ PortPairId portPairId = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList.add(portPairId);
+ portPairId = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairList.add(portPairId);
+
+ DefaultPortPairGroup.Builder portPairGroupBuilder = new DefaultPortPairGroup.Builder();
+ final PortPairGroup portPairGroup = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId)
+ .setName(name).setDescription(description).setPortPairs(portPairList).build();
+
+ assertThat(portPairGroupId, is(portPairGroup.portPairGroupId()));
+ assertThat(tenantId, is(portPairGroup.tenantId()));
+ assertThat(name, is(portPairGroup.name()));
+ assertThat(description, is(portPairGroup.description()));
+ assertThat(portPairList, is(portPairGroup.portPairs()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairTest.java
new file mode 100644
index 00000000..c8004ce6
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultPortPairTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultPortPair class.
+ */
+public class DefaultPortPairTest {
+ /**
+ * Checks that the DefaultPortPair class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPortPair.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ // Create same two port pair objects.
+ final PortPairId portPairId = PortPairId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPair1";
+ final String description = "PortPair1";
+ final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
+
+ DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
+ final PortPair portPair1 = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setIngress(ingress).setEgress(egress).build();
+
+ portPairBuilder = new DefaultPortPair.Builder();
+ final PortPair samePortPair1 = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setIngress(ingress).setEgress(egress).build();
+
+ // Create different port pair object.
+ final PortPairId portPairId2 = PortPairId.of("79999999-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortPair2";
+ final String description2 = "PortPair2";
+ final String ingress2 = "d5555555-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress2 = "a6666666-4a56-2a6e-cd3a-9dee4e2ec345";
+
+ portPairBuilder = new DefaultPortPair.Builder();
+ final PortPair portPair2 = portPairBuilder.setId(portPairId2).setTenantId(tenantId2).setName(name2)
+ .setDescription(description2).setIngress(ingress2).setEgress(egress2).build();
+
+ new EqualsTester().addEqualityGroup(portPair1, samePortPair1).addEqualityGroup(portPair2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultPortPair object.
+ */
+ @Test
+ public void testConstruction() {
+ final PortPairId portPairId = PortPairId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPair";
+ final String description = "PortPair";
+ final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
+
+ DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
+ final PortPair portPair = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setIngress(ingress).setEgress(egress).build();
+
+ assertThat(portPairId, is(portPair.portPairId()));
+ assertThat(tenantId, is(portPair.tenantId()));
+ assertThat(name, is(portPair.name()));
+ assertThat(description, is(portPair.description()));
+ assertThat(ingress, is(portPair.ingress()));
+ assertThat(egress, is(portPair.egress()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultVirtualPortTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultVirtualPortTest.java
new file mode 100644
index 00000000..81d8b14d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/DefaultVirtualPortTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.testing.EqualsTester;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for DefaultVirtualPort class.
+ */
+public class DefaultVirtualPortTest {
+
+ private Set<FixedIp> fixedIps;
+ private Map<String, String> propertyMap;
+ private Set<AllowedAddressPair> allowedAddressPairs;
+ private Set<SecurityGroup> securityGroups;
+ private VirtualPortId id1;
+ private VirtualPortId id2;
+ private String macAddressStr = "fa:12:3e:56:ee:a2";
+ private String ipAddress = "10.1.1.1";
+ private String deviceStr = "of:000000000000001";
+ private String tenantIdStr = "123";
+ private String portId1 = "1241";
+ private String portId2 = "1242";
+ private String tenantNetworkId = "1234567";
+ private String subnet = "1212";
+ private String hostIdStr = "fa:e2:3e:56:ee:a2";
+
+ private void initVirtualPortId() {
+ id1 = VirtualPortId.portId(portId1);
+ id2 = VirtualPortId.portId(portId2);
+ }
+
+ private void initFixedIpSet() {
+ FixedIp fixedIp = FixedIp.fixedIp(SubnetId.subnetId(subnet),
+ IpAddress.valueOf(ipAddress));
+ fixedIps = Sets.newHashSet();
+ fixedIps.add(fixedIp);
+ }
+
+ private void initPropertyMap() {
+ String deviceOwner = "james";
+ propertyMap = Maps.newHashMap();
+ propertyMap.putIfAbsent("deviceOwner", deviceOwner);
+ }
+
+ private void initAddressPairSet() {
+ allowedAddressPairs = Sets.newHashSet();
+ AllowedAddressPair allowedAddressPair = AllowedAddressPair
+ .allowedAddressPair(IpAddress.valueOf(ipAddress),
+ MacAddress.valueOf(macAddressStr));
+ allowedAddressPairs.add(allowedAddressPair);
+ }
+
+ private void initSecurityGroupSet() {
+ securityGroups = Sets.newHashSet();
+ }
+
+ /**
+ * Checks that the DefaultVirtualPort class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(SecurityGroup.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ initVirtualPortId();
+ initFixedIpSet();
+ initPropertyMap();
+ initAddressPairSet();
+ initSecurityGroupSet();
+ TenantNetworkId networkId = TenantNetworkId.networkId(tenantNetworkId);
+ MacAddress macAddress = MacAddress.valueOf(macAddressStr);
+ TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ DeviceId deviceId = DeviceId.deviceId(deviceStr);
+ BindingHostId bindingHostId = BindingHostId.bindingHostId(hostIdStr);
+
+ VirtualPort d1 = new DefaultVirtualPort(id1, networkId, true,
+ propertyMap,
+ VirtualPort.State.ACTIVE,
+ macAddress, tenantId, deviceId,
+ fixedIps, bindingHostId,
+ allowedAddressPairs,
+ securityGroups);
+ VirtualPort d2 = new DefaultVirtualPort(id1, networkId, true,
+ propertyMap,
+ VirtualPort.State.ACTIVE,
+ macAddress, tenantId, deviceId,
+ fixedIps, bindingHostId,
+ allowedAddressPairs,
+ securityGroups);
+ VirtualPort d3 = new DefaultVirtualPort(id2, networkId, true,
+ propertyMap,
+ VirtualPort.State.ACTIVE,
+ macAddress, tenantId, deviceId,
+ fixedIps, bindingHostId,
+ allowedAddressPairs,
+ securityGroups);
+ new EqualsTester().addEqualityGroup(d1, d2).addEqualityGroup(d3)
+ .testEquals();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FixedIpTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FixedIpTest.java
new file mode 100644
index 00000000..d77532a7
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FixedIpTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for FixedIp class.
+ */
+public class FixedIpTest {
+
+ final SubnetId subnetId1 = SubnetId.subnetId("lef11-95w-4er-9c9c");
+ final SubnetId subnetId2 = SubnetId.subnetId("lefaa-95w-4er-9c9c");
+ final IpAddress ip1 = IpAddress.valueOf("192.168.0.1");
+ final IpAddress ip2 = IpAddress.valueOf("192.168.1.1");
+
+ /**
+ * Checks that the FixedIp class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(FixedIp.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ FixedIp fixedIp1 = FixedIp.fixedIp(subnetId1, ip1);
+ FixedIp fixedIp2 = FixedIp.fixedIp(subnetId1, ip1);
+ FixedIp fixedIp3 = FixedIp.fixedIp(subnetId2, ip2);
+ new EqualsTester().addEqualityGroup(fixedIp1, fixedIp2)
+ .addEqualityGroup(fixedIp3).testEquals();
+ }
+
+ /**
+ * Checks the construction of a FixedIp object.
+ */
+ @Test
+ public void testConstruction() {
+ FixedIp fixedIp = FixedIp.fixedIp(subnetId1, ip1);
+ assertThat(ip1, is(notNullValue()));
+ assertThat(ip1, is(fixedIp.ip()));
+ assertThat(subnetId1, is(notNullValue()));
+ assertThat(subnetId1, is(fixedIp.subnetId()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FlowClassifierIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FlowClassifierIdTest.java
new file mode 100644
index 00000000..0bef00fc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/FlowClassifierIdTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.UUID;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for FlowClassifierId class.
+ */
+public class FlowClassifierIdTest {
+
+ final FlowClassifierId flowClassifierId1 = FlowClassifierId
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final FlowClassifierId sameAsFlowClassifierId1 = FlowClassifierId
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final FlowClassifierId flowClassifierId2 = FlowClassifierId
+ .of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the FlowClassifierId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(FlowClassifierId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(flowClassifierId1, sameAsFlowClassifierId1)
+ .addEqualityGroup(flowClassifierId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a FlowClassifierId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String flowClassifierIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final FlowClassifierId flowClassifierId = FlowClassifierId.of(flowClassifierIdValue);
+ assertThat(flowClassifierId, is(notNullValue()));
+ assertThat(flowClassifierId.value(), is(UUID.fromString(flowClassifierIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PhysicalNetworkTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PhysicalNetworkTest.java
new file mode 100644
index 00000000..c4f591e7
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PhysicalNetworkTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for PhysicalNetwork class.
+ */
+public class PhysicalNetworkTest {
+
+ final PhysicalNetwork physicalNetwork1 = PhysicalNetwork.physicalNetwork("1");
+ final PhysicalNetwork sameAsPhysicalNetwork1 = PhysicalNetwork.physicalNetwork("1");
+ final PhysicalNetwork physicalNetwork2 = PhysicalNetwork.physicalNetwork("2");
+
+ /**
+ * Checks that the PhysicalNetwork class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PhysicalNetwork.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(physicalNetwork1, sameAsPhysicalNetwork1)
+ .addEqualityGroup(physicalNetwork2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a PhysicalNetwork object.
+ */
+ @Test
+ public void testConstruction() {
+ final String physicalNetworkValue = "s";
+ final PhysicalNetwork physicalNetwork = PhysicalNetwork
+ .physicalNetwork(physicalNetworkValue);
+ assertThat(physicalNetwork, is(notNullValue()));
+ assertThat(physicalNetwork.physicalNetwork(), is(physicalNetworkValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortChainIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortChainIdTest.java
new file mode 100644
index 00000000..1e84fc5d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortChainIdTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.UUID;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for PortChainId class.
+ */
+public class PortChainIdTest {
+
+ final PortChainId portChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortChainId sameAsPortChainId1 = PortChainId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortChainId portChainId2 = PortChainId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortChainId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortChainId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portChainId1, sameAsPortChainId1).addEqualityGroup(portChainId2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortChainId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portChainIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortChainId portChainId = PortChainId.of(portChainIdValue);
+ assertThat(portChainId, is(notNullValue()));
+ assertThat(portChainId.value(), is(UUID.fromString(portChainIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairGroupIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairGroupIdTest.java
new file mode 100644
index 00000000..20eb24a5
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairGroupIdTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.UUID;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for PortPairGroupId class.
+ */
+public class PortPairGroupIdTest {
+
+ final PortPairGroupId portPairGroupId1 = PortPairGroupId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairGroupId sameAsPortPairGroupId1 = PortPairGroupId
+ .of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairGroupId portPairGroupId2 = PortPairGroupId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortPairGroupId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortPairGroupId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portPairGroupId1, sameAsPortPairGroupId1)
+ .addEqualityGroup(portPairGroupId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortPairGroupId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portPairGroupIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortPairGroupId portPairGroupId = PortPairGroupId.of(portPairGroupIdValue);
+ assertThat(portPairGroupId, is(notNullValue()));
+ assertThat(portPairGroupId.value(), is(UUID.fromString(portPairGroupIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairIdTest.java
new file mode 100644
index 00000000..757d3a69
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/PortPairIdTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.UUID;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for PortPairId class.
+ */
+public class PortPairIdTest {
+
+ final PortPairId portPairId1 = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairId sameAsPortPairId1 = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final PortPairId portPairId2 = PortPairId.of("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+
+ /**
+ * Checks that the PortPairId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(PortPairId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(portPairId1, sameAsPortPairId1).addEqualityGroup(portPairId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a PortPairId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String portPairIdValue = "dace4513-24fc-4fae-af4b-321c5e2eb3d1";
+ final PortPairId portPairId = PortPairId.of(portPairIdValue);
+ assertThat(portPairId, is(notNullValue()));
+ assertThat(portPairId.value(), is(UUID.fromString(portPairIdValue)));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterGatewayTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterGatewayTest.java
new file mode 100644
index 00000000..9f60de8f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterGatewayTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for RouterGateway class.
+ */
+public class RouterGatewayTest {
+ final TenantNetworkId networkId1 = TenantNetworkId.networkId("1");
+ final TenantNetworkId networkId2 = TenantNetworkId.networkId("2");
+ final Set<FixedIp> fixedIpSet1 = new HashSet<>();
+ final Set<FixedIp> fixedIpSet2 = new HashSet<>();
+
+ /**
+ * Checks that the RouterGateway class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(RouterGateway.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ RouterGateway routerGateway1 = RouterGateway.routerGateway(networkId1,
+ true,
+ fixedIpSet1);
+ RouterGateway routerGateway2 = RouterGateway.routerGateway(networkId1,
+ true,
+ fixedIpSet1);
+ RouterGateway routerGateway3 = RouterGateway.routerGateway(networkId2,
+ true,
+ fixedIpSet2);
+ new EqualsTester().addEqualityGroup(routerGateway1, routerGateway2)
+ .addEqualityGroup(routerGateway3).testEquals();
+ }
+
+ /**
+ * Checks the construction of a RouterGateway object.
+ */
+ @Test
+ public void testConstruction() {
+ RouterGateway routerGateway = RouterGateway.routerGateway(networkId1,
+ true,
+ fixedIpSet1);
+ assertThat(fixedIpSet1, is(notNullValue()));
+ assertThat(fixedIpSet1, is(routerGateway.externalFixedIps()));
+ assertThat(networkId1, is(notNullValue()));
+ assertThat(networkId1, is(routerGateway.networkId()));
+ assertThat(routerGateway.enableSnat(), is(true));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterIdTest.java
new file mode 100644
index 00000000..225211b9
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/RouterIdTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for RouterId class.
+ */
+public class RouterIdTest {
+ final RouterId routerId1 = RouterId.valueOf("1");
+ final RouterId sameAsRouterId1 = RouterId.valueOf("1");
+ final RouterId routerId2 = RouterId.valueOf("2");
+
+ /**
+ * Checks that the RouterId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(RouterId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(routerId1, sameAsRouterId1).addEqualityGroup(routerId2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a RouterId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String routerIdValue = "s";
+ final RouterId routerId = RouterId.valueOf(routerIdValue);
+ assertThat(routerId, is(notNullValue()));
+ assertThat(routerId.routerId(), is(routerIdValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SecurityGroupTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SecurityGroupTest.java
new file mode 100644
index 00000000..20871c02
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SecurityGroupTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for SecurityGroup class.
+ */
+public class SecurityGroupTest {
+
+ final SecurityGroup securityGroup1 = SecurityGroup.securityGroup("1");
+ final SecurityGroup sameAssecurityGroup = SecurityGroup.securityGroup("1");
+ final SecurityGroup securityGroup2 = SecurityGroup.securityGroup("2");
+
+ /**
+ * Checks that the SecurityGroup class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(SecurityGroup.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(securityGroup1, sameAssecurityGroup)
+ .addEqualityGroup(securityGroup2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a SecurityGroup object.
+ */
+ @Test
+ public void testConstruction() {
+ final String securityGroupValue = "1";
+ final SecurityGroup securityGroup = SecurityGroup.securityGroup(securityGroupValue);
+ assertThat(securityGroup, is(notNullValue()));
+ assertThat(securityGroup.securityGroup(), is(securityGroupValue));
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SegmentationIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SegmentationIdTest.java
new file mode 100644
index 00000000..dfb3dcf8
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SegmentationIdTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for SegmentationId class.
+ */
+public class SegmentationIdTest {
+
+ final SegmentationId segmentationID1 = SegmentationId.segmentationId("1");
+ final SegmentationId sameAsSegmentationID1 = SegmentationId.segmentationId("1");
+ final SegmentationId segmentationID2 = SegmentationId.segmentationId("2");
+
+ /**
+ * Checks that the SegmentationId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(SegmentationId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(segmentationID1, sameAsSegmentationID1)
+ .addEqualityGroup(segmentationID2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a segmentationId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String segmentationIdValue = "s";
+ final SegmentationId segmentationId = SegmentationId.segmentationId(segmentationIdValue);
+ assertThat(segmentationId, is(notNullValue()));
+ assertThat(segmentationId.segmentationId(), is(segmentationIdValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SubnetIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SubnetIdTest.java
new file mode 100644
index 00000000..5a1809ce
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/SubnetIdTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for SubnetId class.
+ */
+public class SubnetIdTest {
+
+ final SubnetId subnetId1 = SubnetId.subnetId("1");
+ final SubnetId sameAsSubnetId1 = SubnetId.subnetId("1");
+ final SubnetId subnetId2 = SubnetId.subnetId("2");
+
+ /**
+ * Checks that the SubnetId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(SubnetId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(subnetId1, sameAsSubnetId1).addEqualityGroup(subnetId2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a SubnetId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String subnetIdValue = "s";
+ final SubnetId subnetId = SubnetId.subnetId(subnetIdValue);
+ assertThat(subnetId, is(notNullValue()));
+ assertThat(subnetId.subnetId(), is(subnetIdValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantIdTest.java
new file mode 100644
index 00000000..f601d427
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantIdTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for TenantId class.
+ */
+public class TenantIdTest {
+
+ final TenantId tenantId1 = TenantId.tenantId("1");
+ final TenantId sameAsTenantId1 = TenantId.tenantId("1");
+ final TenantId tenantId2 = TenantId.tenantId("2");
+
+ /**
+ * Checks that the TenantId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(TenantId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(tenantId1, sameAsTenantId1).addEqualityGroup(tenantId2)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a TenantId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String tenantIdValue = "s";
+ final TenantId tenantId = TenantId.tenantId(tenantIdValue);
+ assertThat(tenantId, is(notNullValue()));
+ assertThat(tenantId.tenantId(), is(tenantIdValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantNetworkIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantNetworkIdTest.java
new file mode 100644
index 00000000..3bd72026
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/TenantNetworkIdTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for TenantNetworkId class.
+ */
+public class TenantNetworkIdTest {
+
+ final TenantNetworkId networkId1 = TenantNetworkId.networkId("1");
+ final TenantNetworkId sameAsnetworkId1 = TenantNetworkId.networkId("1");
+ final TenantNetworkId networkId2 = TenantNetworkId.networkId("2");
+
+ /**
+ * Checks that the TenantNetworkId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(TenantNetworkId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(networkId1, sameAsnetworkId1)
+ .addEqualityGroup(networkId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a TenantNetworkId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String networkIdValue = "s";
+ final TenantNetworkId networkId = TenantNetworkId.networkId(networkIdValue);
+ assertThat(networkId, is(notNullValue()));
+ assertThat(networkId.networkId(), is(networkIdValue));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/VirtualPortIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/VirtualPortIdTest.java
new file mode 100644
index 00000000..70966118
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/VirtualPortIdTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.vtnrsc;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for VirtualPortId class.
+ */
+public class VirtualPortIdTest {
+
+ final VirtualPortId virtualPortId1 = VirtualPortId.portId("1");
+ final VirtualPortId sameAsVirtualPortId1 = VirtualPortId.portId("1");
+ final VirtualPortId virtualPortId2 = VirtualPortId.portId("2");
+
+ /**
+ * Checks that the VirtualPortId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(VirtualPortId.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(virtualPortId1, sameAsVirtualPortId1)
+ .addEqualityGroup(virtualPortId2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a VirtualPortId object.
+ */
+ @Test
+ public void testConstruction() {
+ final String vPortIdValue = "aaa";
+ final VirtualPortId virtualPortId = VirtualPortId.portId(vPortIdValue);
+ assertThat(virtualPortId, is(notNullValue()));
+ assertThat(virtualPortId.portId(), is(vPortIdValue));
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/DefaultFloatingIpTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/DefaultFloatingIpTest.java
new file mode 100644
index 00000000..d6826f5d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/DefaultFloatingIpTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.vtnrsc.DefaultFloatingIp;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for DefaultFloatingIp class.
+ */
+public class DefaultFloatingIpTest {
+
+ private String floatingIpIdStr1 = "5fb63824-4d5c-4b85-9f2f-ebb93c9ce3df";
+ private String floatingIpIdStr2 = "fa44f585-fe02-40d3-afe7-d1d7e5782c99";
+ private String floatingIpStr = "10.1.1.2";
+ private String fixedIpStr = "192.168.1.2";
+ private String tenantIdStr = "123";
+ private String tenantNetworkId = "1234567";
+ private String virtualPortId = "1212";
+ private String routerIdStr = "123";
+
+ /**
+ * Checks that the DefaultFloatingIp class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultFloatingIp.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final TenantNetworkId networkId = TenantNetworkId
+ .networkId(tenantNetworkId);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId = RouterId.valueOf(routerIdStr);
+ final FloatingIpId id1 = FloatingIpId.of(floatingIpIdStr1);
+ final FloatingIpId id2 = FloatingIpId.of(floatingIpIdStr2);
+ final IpAddress floatingIpAddress = IpAddress.valueOf(floatingIpStr);
+ final IpAddress fixedIpAddress = IpAddress.valueOf(fixedIpStr);
+
+ FloatingIp fip1 = new DefaultFloatingIp(id1, tenantId, networkId,
+ portId, routerId,
+ floatingIpAddress,
+ fixedIpAddress,
+ FloatingIp.Status.ACTIVE);
+ FloatingIp fip2 = new DefaultFloatingIp(id1, tenantId, networkId,
+ portId, routerId,
+ floatingIpAddress,
+ fixedIpAddress,
+ FloatingIp.Status.ACTIVE);
+ FloatingIp fip3 = new DefaultFloatingIp(id2, tenantId, networkId,
+ portId, routerId,
+ floatingIpAddress,
+ fixedIpAddress,
+ FloatingIp.Status.ACTIVE);
+
+ new EqualsTester().addEqualityGroup(fip1, fip2).addEqualityGroup(fip3)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultFloatingIp object.
+ */
+ @Test
+ public void testConstruction() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final TenantNetworkId networkId = TenantNetworkId
+ .networkId(tenantNetworkId);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId = RouterId.valueOf(routerIdStr);
+ final FloatingIpId id = FloatingIpId.of(floatingIpIdStr1);
+ final IpAddress floatingIpAddress = IpAddress.valueOf(floatingIpStr);
+ final IpAddress fixedIpAddress = IpAddress.valueOf(fixedIpStr);
+
+ FloatingIp fip = new DefaultFloatingIp(id, tenantId, networkId, portId,
+ routerId, floatingIpAddress,
+ fixedIpAddress,
+ FloatingIp.Status.ACTIVE);
+ assertThat(id, is(notNullValue()));
+ assertThat(id, is(fip.id()));
+ assertThat(tenantId, is(notNullValue()));
+ assertThat(tenantId, is(fip.tenantId()));
+ assertThat(networkId, is(notNullValue()));
+ assertThat(networkId, is(fip.networkId()));
+ assertThat(portId, is(notNullValue()));
+ assertThat(portId, is(fip.portId()));
+ assertThat(routerId, is(notNullValue()));
+ assertThat(routerId, is(fip.routerId()));
+ assertThat(floatingIpAddress, is(notNullValue()));
+ assertThat(floatingIpAddress, is(fip.floatingIp()));
+ assertThat(fixedIpAddress, is(notNullValue()));
+ assertThat(fixedIpAddress, is(fip.fixedIp()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/FloatingIpIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/FloatingIpIdTest.java
new file mode 100644
index 00000000..6ae27e9e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/floatingip/FloatingIpIdTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.floatingip;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.FloatingIpId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for FloatingIpId class.
+ */
+public class FloatingIpIdTest {
+ private String floatingIpIdStr1 = "5fb63824-4d5c-4b85-9f2f-ebb93c9ce3df";
+ private String floatingIpIdStr2 = "fa44f585-fe02-40d3-afe7-d1d7e5782c99";
+
+ /**
+ * Checks that the FloatingIpId class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(FloatingIpId.class);
+ }
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ FloatingIpId id1 = FloatingIpId.of(floatingIpIdStr1);
+ FloatingIpId id2 = FloatingIpId.of(floatingIpIdStr1);
+ FloatingIpId id3 = FloatingIpId.of(floatingIpIdStr2);
+ new EqualsTester().addEqualityGroup(id1, id2).addEqualityGroup(id3)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a FloatingIpId object.
+ */
+ @Test
+ public void testConstruction() {
+ final FloatingIpId id = FloatingIpId.of(floatingIpIdStr1);
+ assertThat(id, is(notNullValue()));
+ assertThat(id.floatingIpId().toString(), is(floatingIpIdStr1));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManagerTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManagerTest.java
new file mode 100644
index 00000000..8283a52b
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/impl/FlowClassifierManagerTest.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.flowclassifier.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import org.onlab.packet.IpPrefix;
+
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.util.VtnStorageServiceTest;
+
+/**
+ * Unit tests for FlowClassifierManager class.
+ */
+public class FlowClassifierManagerTest {
+
+ final String name = "FlowClassifier";
+ final String description = "FlowClassifier";
+ final String ethType = "IPv4";
+ final String protocol = "udp";
+ final int minSrcPortRange = 1024;
+ final int maxSrcPortRange = 5000;
+ final int minDstPortRange = 1024;
+ final int maxDstPortRange = 5000;
+ final FlowClassifierId flowClassifierId = FlowClassifierId.of("71111111-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("8");
+ final IpPrefix srcIpPrefix = IpPrefix.valueOf("0.0.0.0/0");
+ final IpPrefix dstIpPrefix = IpPrefix.valueOf("100.100.100.100/0");
+ final VirtualPortId virtualSrcPort = VirtualPortId.portId("100");
+ final VirtualPortId virtualDstPort = VirtualPortId.portId("200");
+ DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder();
+ FlowClassifierManager flowClassifierMgr = new FlowClassifierManager();
+ FlowClassifier flowClassifier = null;
+ private final VtnStorageServiceTest storageService = new VtnStorageServiceTest();
+
+ /**
+ * Checks the operation of createFlowClassifier() method.
+ */
+ @Test
+ public void testCreateFlowClassifier() {
+ // initialize flow classifier manager
+ flowClassifierMgr.storageService = storageService;
+ flowClassifierMgr.activate();
+
+ // create flow classifier
+ flowClassifier = flowClassifierBuilder.setFlowClassifierId(flowClassifierId).setTenantId(tenantId)
+ .setName(name).setDescription(description).setEtherType(ethType).setProtocol(protocol)
+ .setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange)
+ .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix)
+ .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort).setDstPort(virtualDstPort).build();
+ assertThat(flowClassifierMgr.createFlowClassifier(flowClassifier), is(true));
+ }
+
+ /**
+ * Checks the operation of exists() method.
+ */
+ @Test
+ public void testExists() {
+ testCreateFlowClassifier();
+ assertThat(flowClassifierMgr.exists(flowClassifierId), is(true));
+ }
+
+ /**
+ * Checks the operation of getFlowClassifierCount() method.
+ */
+ @Test
+ public void testGetFlowClassifierCount() {
+ testCreateFlowClassifier();
+ assertThat(flowClassifierMgr.getFlowClassifierCount(), is(1));
+ }
+
+ /**
+ * Checks the operation of getFlowClassifiers() method.
+ */
+ @Test
+ public void testGetFlowClassifiers() {
+ testCreateFlowClassifier();
+ final Iterable<FlowClassifier> flowClassifierList = flowClassifierMgr.getFlowClassifiers();
+ assertThat(flowClassifierList, is(notNullValue()));
+ assertThat(flowClassifierList.iterator().hasNext(), is(true));
+ }
+
+ /**
+ * Checks the operation of getFlowClassifier() method.
+ */
+ @Test
+ public void testGetFlowClassifier() {
+ testCreateFlowClassifier();
+ assertThat(flowClassifier, is(notNullValue()));
+ assertThat(flowClassifierMgr.getFlowClassifier(flowClassifierId), is(flowClassifier));
+ }
+
+ /**
+ * Checks the operation of updateFlowClassifier() method.
+ */
+ @Test
+ public void testUpdateFlowClassifier() {
+ // create a flow classifier
+ testCreateFlowClassifier();
+
+ // new updates
+ final String name2 = "FlowClassifier2";
+ final String description2 = "FlowClassifier2";
+ final String ethType2 = "IPv6";
+ final String protocol2 = "tcp";
+ final TenantId tenantId2 = TenantId.tenantId("10");
+ final VirtualPortId virtualSrcPort2 = VirtualPortId.portId("300");
+ final VirtualPortId virtualDstPort2 = VirtualPortId.portId("400");
+ flowClassifier = flowClassifierBuilder.setFlowClassifierId(flowClassifierId)
+ .setTenantId(tenantId2).setName(name2).setDescription(description2).setEtherType(ethType2)
+ .setProtocol(protocol2).setMinSrcPortRange(minSrcPortRange).setMaxSrcPortRange(maxSrcPortRange)
+ .setMinDstPortRange(minDstPortRange).setMaxDstPortRange(maxDstPortRange).setSrcIpPrefix(srcIpPrefix)
+ .setDstIpPrefix(dstIpPrefix).setSrcPort(virtualSrcPort2).setDstPort(virtualDstPort2).build();
+ assertThat(flowClassifierMgr.updateFlowClassifier(flowClassifier), is(true));
+ }
+
+ /**
+ * Checks the operation of removeFlowClassifier() method.
+ */
+ @Test
+ public void testRemoveFlowClassifier() {
+ testCreateFlowClassifier();
+ assertThat(flowClassifierMgr.removeFlowClassifier(flowClassifierId), is(true));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/impl/PortChainManagerTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/impl/PortChainManagerTest.java
new file mode 100644
index 00000000..0831ec9c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portchain/impl/PortChainManagerTest.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.portchain.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.DefaultPortChain;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
+import org.onosproject.vtnrsc.util.VtnStorageServiceTest;
+
+/**
+ * Unit tests for PortChainManager class.
+ */
+public class PortChainManagerTest {
+ final PortChainId portChainId = PortChainId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortChain";
+ final String description = "PortChain";
+ final List<PortPairGroupId> portPairGroupList = new LinkedList<PortPairGroupId>();
+ final List<FlowClassifierId> flowClassifierList = new LinkedList<FlowClassifierId>();
+ DefaultPortChain.Builder portChainBuilder = new DefaultPortChain.Builder();
+ DefaultFlowClassifier.Builder flowClassifierBuilder = new DefaultFlowClassifier.Builder();
+ PortChainManager portChainMgr = new PortChainManager();
+ PortChain portChain = null;
+ private final VtnStorageServiceTest storageService = new VtnStorageServiceTest();
+
+ /**
+ * Checks the operation of createPortChain() method.
+ */
+ @Test
+ public void testCreatePortChain() {
+ // initialize port chain manager
+ portChainMgr.storageService = storageService;
+ portChainMgr.activate();
+
+ // create list of Port Pair Groups.
+ PortPairGroupId portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairGroupList.add(portPairGroupId);
+ portPairGroupId = PortPairGroupId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3af");
+ portPairGroupList.add(portPairGroupId);
+
+ // create list of Flow classifiers.
+ FlowClassifierId flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ flowClassifierList.add(flowClassifierId);
+ flowClassifierId = FlowClassifierId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3af");
+ flowClassifierList.add(flowClassifierId);
+
+ // create port chain
+ portChain = portChainBuilder.setId(portChainId).setTenantId(tenantId).setName(name).setDescription(description)
+ .setPortPairGroups(portPairGroupList).setFlowClassifiers(flowClassifierList).build();
+ assertThat(portChainMgr.createPortChain(portChain), is(true));
+ }
+
+ /**
+ * Checks the operation of exists() method.
+ */
+ @Test
+ public void testExists() {
+ testCreatePortChain();
+ assertThat(portChainMgr.exists(portChainId), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortChainCount() method.
+ */
+ @Test
+ public void testGetPortChainCount() {
+ testCreatePortChain();
+ assertThat(portChainMgr.getPortChainCount(), is(1));
+ }
+
+ /**
+ * Checks the operation of getPortChains() method.
+ */
+ @Test
+ public void testGetPortChains() {
+ testCreatePortChain();
+ final Iterable<PortChain> portChainList = portChainMgr.getPortChains();
+ assertThat(portChainList, is(notNullValue()));
+ assertThat(portChainList.iterator().hasNext(), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortChain() method.
+ */
+ @Test
+ public void testGetPortChain() {
+ testCreatePortChain();
+ assertThat(portChain, is(notNullValue()));
+ assertThat(portChainMgr.getPortChain(portChainId), is(portChain));
+ }
+
+ /**
+ * Checks the operation of updatePortChain() method.
+ */
+ @Test
+ public void testUpdatePortChain() {
+ // create a port chain
+ testCreatePortChain();
+
+ // new updates
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortChain2";
+ final String description2 = "PortChain2";
+ // create list of Port Pair Groups.
+ final List<PortPairGroupId> portPairGroupList = new LinkedList<PortPairGroupId>();
+ PortPairGroupId portPairGroupId = PortPairGroupId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairGroupList.add(portPairGroupId);
+ portPairGroupId = PortPairGroupId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3af");
+ portPairGroupList.add(portPairGroupId);
+ // create list of Flow classifiers.
+ final List<FlowClassifierId> flowClassifierList = new LinkedList<FlowClassifierId>();
+ FlowClassifierId flowClassifierId = FlowClassifierId.of("76666666-fc23-aeb6-f44b-56dc5e2fb3ae");
+ flowClassifierList.add(flowClassifierId);
+ flowClassifierId = FlowClassifierId.of("76666666-fc23-aeb6-f44b-56dc5e2fb3af");
+ flowClassifierList.add(flowClassifierId);
+ portChain = portChainBuilder.setId(portChainId).setTenantId(tenantId2).setName(name2)
+ .setDescription(description2).setPortPairGroups(portPairGroupList)
+ .setFlowClassifiers(flowClassifierList).build();
+ assertThat(portChainMgr.updatePortChain(portChain), is(true));
+ }
+
+ /**
+ * Checks the operation of removePortChain() method.
+ */
+ @Test
+ public void testRemovePortChain() {
+ testCreatePortChain();
+ assertThat(portChainMgr.removePortChain(portChainId), is(true));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/impl/PortPairManagerTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/impl/PortPairManagerTest.java
new file mode 100644
index 00000000..c936d7cc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpair/impl/PortPairManagerTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.portpair.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.DefaultPortPair;
+import org.onosproject.vtnrsc.util.VtnStorageServiceTest;
+
+/**
+ * Unit tests for PortPairManager class.
+ */
+public class PortPairManagerTest {
+ final PortPairId portPairId = PortPairId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPair";
+ final String description = "PortPair";
+ final String ingress = "d3333333-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress = "a4444444-4a56-2a6e-cd3a-9dee4e2ec345";
+ DefaultPortPair.Builder portPairBuilder = new DefaultPortPair.Builder();
+ PortPairManager portPairMgr = new PortPairManager();
+ PortPair portPair = null;
+ private final VtnStorageServiceTest storageService = new VtnStorageServiceTest();
+
+ /**
+ * Checks the operation of createPortPair() method.
+ */
+ @Test
+ public void testCreatePortPair() {
+ // initialize port pair manager
+ portPairMgr.storageService = storageService;
+ portPairMgr.activate();
+
+ // create port pair
+ portPair = portPairBuilder.setId(portPairId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setIngress(ingress).setEgress(egress).build();
+ assertThat(portPairMgr.createPortPair(portPair), is(true));
+ }
+
+ /**
+ * Checks the operation of exists() method.
+ */
+ @Test
+ public void testExists() {
+ testCreatePortPair();
+ assertThat(portPairMgr.exists(portPairId), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortPairCount() method.
+ */
+ @Test
+ public void testGetPortPairCount() {
+ testCreatePortPair();
+ assertThat(portPairMgr.getPortPairCount(), is(1));
+ }
+
+ /**
+ * Checks the operation of getPortPairs() method.
+ */
+ @Test
+ public void testGetPortPairs() {
+ testCreatePortPair();
+ final Iterable<PortPair> portPairList = portPairMgr.getPortPairs();
+ assertThat(portPairList, is(notNullValue()));
+ assertThat(portPairList.iterator().hasNext(), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortPair() method.
+ */
+ @Test
+ public void testGetPortPair() {
+ testCreatePortPair();
+ assertThat(portPair, is(notNullValue()));
+ assertThat(portPairMgr.getPortPair(portPairId), is(portPair));
+ }
+
+ /**
+ * Checks the operation of updatePortPair() method.
+ */
+ @Test
+ public void testUpdatePortPair() {
+ // create a port pair
+ testCreatePortPair();
+
+ // new updates
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortPair2";
+ final String description2 = "PortPair2";
+ final String ingress2 = "d5555555-24fc-4fae-af4b-321c5e2eb3d1";
+ final String egress2 = "a6666666-4a56-2a6e-cd3a-9dee4e2ec345";
+ portPair = portPairBuilder.setId(portPairId).setTenantId(tenantId2).setName(name2)
+ .setDescription(description2).setIngress(ingress2).setEgress(egress2).build();
+ assertThat(portPairMgr.updatePortPair(portPair), is(true));
+ }
+
+ /**
+ * Checks the operation of removePortPair() method.
+ */
+ @Test
+ public void testRemovePortPair() {
+ testCreatePortPair();
+ assertThat(portPairMgr.removePortPair(portPairId), is(true));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManagerTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManagerTest.java
new file mode 100644
index 00000000..95bcd09a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/portpairgroup/impl/PortPairGroupManagerTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.portpairgroup.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+import java.util.List;
+import java.util.LinkedList;
+
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.DefaultPortPairGroup;
+import org.onosproject.vtnrsc.util.VtnStorageServiceTest;
+
+/**
+ * Unit tests for PortPairGroupManager class.
+ */
+public class PortPairGroupManagerTest {
+ final PortPairGroupId portPairGroupId = PortPairGroupId.of("78888888-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final TenantId tenantId = TenantId.tenantId("1");
+ final String name = "PortPairGroup";
+ final String description = "PortPairGroup";
+ final List<PortPairId> portPairIdList = new LinkedList<PortPairId>();
+ DefaultPortPairGroup.Builder portPairGroupBuilder = new DefaultPortPairGroup.Builder();
+ PortPairGroupManager portPairGroupMgr = new PortPairGroupManager();
+ PortPairGroup portPairGroup = null;
+ private final VtnStorageServiceTest storageService = new VtnStorageServiceTest();
+
+ /**
+ * Checks the operation of createPortPairGroup() method.
+ */
+ @Test
+ public void testCreatePortPairGroup() {
+ // initialize port pair group manager
+ portPairGroupMgr.storageService = storageService;
+ portPairGroupMgr.activate();
+
+ // create port-pair-id list
+ PortPairId portPairId = PortPairId.of("73333333-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairIdList.add(portPairId);
+ portPairId = PortPairId.of("74444444-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairIdList.add(portPairId);
+
+ // create port pair
+ portPairGroup = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId).setName(name)
+ .setDescription(description).setPortPairs(portPairIdList).build();
+ assertThat(portPairGroupMgr.createPortPairGroup(portPairGroup), is(true));
+ }
+
+ /**
+ * Checks the operation of exists() method.
+ */
+ @Test
+ public void testExists() {
+ testCreatePortPairGroup();
+ assertThat(portPairGroupMgr.exists(portPairGroupId), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortPairGroupCount() method.
+ */
+ @Test
+ public void testGetPortPairGroupCount() {
+ testCreatePortPairGroup();
+ assertThat(portPairGroupMgr.getPortPairGroupCount(), is(1));
+ }
+
+ /**
+ * Checks the operation of getPortPairGroups() method.
+ */
+ @Test
+ public void testGetPortPairGroups() {
+ testCreatePortPairGroup();
+ final Iterable<PortPairGroup> portPairGroupList = portPairGroupMgr.getPortPairGroups();
+ assertThat(portPairGroupList, is(notNullValue()));
+ assertThat(portPairGroupList.iterator().hasNext(), is(true));
+ }
+
+ /**
+ * Checks the operation of getPortPairGroup() method.
+ */
+ @Test
+ public void testGetPortPairGroup() {
+ testCreatePortPairGroup();
+ assertThat(portPairGroup, is(notNullValue()));
+ assertThat(portPairGroupMgr.getPortPairGroup(portPairGroupId), is(portPairGroup));
+ }
+
+ /**
+ * Checks the operation of updatePortPairGroup() method.
+ */
+ @Test
+ public void testUpdatePortPairGroup() {
+ // create a port pair group
+ testCreatePortPairGroup();
+
+ // new updates
+ // create port-pair-id list
+ final TenantId tenantId2 = TenantId.tenantId("2");
+ final String name2 = "PortPairGroup2";
+ final String description2 = "PortPairGroup2";
+ final List<PortPairId> portPairIdList = new LinkedList<PortPairId>();
+ PortPairId portPairId = PortPairId.of("75555555-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairIdList.add(portPairId);
+ portPairId = PortPairId.of("76666666-fc23-aeb6-f44b-56dc5e2fb3ae");
+ portPairIdList.add(portPairId);
+
+ // create port pair
+ portPairGroup = portPairGroupBuilder.setId(portPairGroupId).setTenantId(tenantId2).setName(name2)
+ .setDescription(description2).setPortPairs(portPairIdList).build();
+ assertThat(portPairGroupMgr.updatePortPairGroup(portPairGroup), is(true));
+ }
+
+ /**
+ * Checks the operation of removePortPairGroup() method.
+ */
+ @Test
+ public void testRemovePortPairGroup() {
+ testCreatePortPairGroup();
+ assertThat(portPairGroupMgr.removePortPairGroup(portPairGroupId), is(true));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/DefaultRouterTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/DefaultRouterTest.java
new file mode 100644
index 00000000..ecc80658
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/DefaultRouterTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import java.util.Collections;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.DefaultRouter;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.RouterGateway;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for DefaultRouter class.
+ */
+public class DefaultRouterTest {
+
+ private String tenantIdStr = "123";
+ private String virtualPortId = "1212";
+ private String routeIdStr1 = "1";
+ private String routeIdStr2 = "2";
+ private String routerName = "router";
+ private String tenantNetworkId = "1234567";
+
+ /**
+ * Checks that the DefaultRouter class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultRouter.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId1 = RouterId.valueOf(routeIdStr1);
+ final RouterId routerId2 = RouterId.valueOf(routeIdStr2);
+ final TenantNetworkId networkId = TenantNetworkId
+ .networkId(tenantNetworkId);
+ final RouterGateway routerGateway = RouterGateway.routerGateway(
+ networkId,
+ true,
+ Collections
+ .emptySet());
+
+ Router r1 = new DefaultRouter(routerId1, routerName, false,
+ Router.Status.ACTIVE, false,
+ routerGateway, portId, tenantId, null);
+ Router r2 = new DefaultRouter(routerId1, routerName, false,
+ Router.Status.ACTIVE, false,
+ routerGateway, portId, tenantId, null);
+ Router r3 = new DefaultRouter(routerId2, routerName, false,
+ Router.Status.ACTIVE, false,
+ routerGateway, portId, tenantId, null);
+
+ new EqualsTester().addEqualityGroup(r1, r2).addEqualityGroup(r3)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a DefaultRouter object.
+ */
+ @Test
+ public void testConstruction() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId = RouterId.valueOf(routeIdStr1);
+ final TenantNetworkId networkId = TenantNetworkId
+ .networkId(tenantNetworkId);
+ final RouterGateway routerGateway = RouterGateway.routerGateway(
+ networkId,
+ true,
+ Collections
+ .emptySet());
+
+ Router r1 = new DefaultRouter(routerId, routerName, false,
+ Router.Status.ACTIVE, false,
+ routerGateway, portId, tenantId, null);
+ assertThat(routerId, is(notNullValue()));
+ assertThat(routerId, is(r1.id()));
+ assertThat(tenantId, is(notNullValue()));
+ assertThat(tenantId, is(r1.tenantId()));
+ assertThat(routerGateway, is(notNullValue()));
+ assertThat(routerGateway, is(r1.externalGatewayInfo()));
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/RouterInterfaceTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/RouterInterfaceTest.java
new file mode 100644
index 00000000..53ea037d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/router/RouterInterfaceTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.router;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for RouterInterface class.
+ */
+public class RouterInterfaceTest {
+ private String tenantIdStr = "123";
+ private String virtualPortId = "1212";
+ private String routeIdStr1 = "1";
+ private String routeIdStr2 = "2";
+ private String subnetIdStr = "1234567";
+
+ /**
+ * Checks that the RouterInterface class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(RouterInterface.class);
+ }
+
+ /**
+ * Checks the operation of equals().
+ */
+ @Test
+ public void testEquals() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId1 = RouterId.valueOf(routeIdStr1);
+ final RouterId routerId2 = RouterId.valueOf(routeIdStr2);
+ final SubnetId subnet = SubnetId.subnetId(subnetIdStr);
+
+ RouterInterface ri1 = RouterInterface.routerInterface(subnet, portId,
+ routerId1,
+ tenantId);
+ RouterInterface ri2 = RouterInterface.routerInterface(subnet, portId,
+ routerId1,
+ tenantId);
+ RouterInterface ri3 = RouterInterface.routerInterface(subnet, portId,
+ routerId2,
+ tenantId);
+
+ new EqualsTester().addEqualityGroup(ri1, ri2).addEqualityGroup(ri3)
+ .testEquals();
+ }
+
+ /**
+ * Checks the construction of a RouterInterface object.
+ */
+ @Test
+ public void testConstruction() {
+ final TenantId tenantId = TenantId.tenantId(tenantIdStr);
+ final VirtualPortId portId = VirtualPortId.portId(virtualPortId);
+ final RouterId routerId1 = RouterId.valueOf(routeIdStr1);
+ final SubnetId subnet = SubnetId.subnetId(subnetIdStr);
+
+ RouterInterface ri1 = RouterInterface.routerInterface(subnet, portId,
+ routerId1,
+ tenantId);
+ assertThat(portId, is(notNullValue()));
+ assertThat(portId, is(ri1.portId()));
+ assertThat(tenantId, is(notNullValue()));
+ assertThat(tenantId, is(ri1.tenantId()));
+ assertThat(routerId1, is(notNullValue()));
+ assertThat(routerId1, is(ri1.routerId()));
+ assertThat(subnet, is(notNullValue()));
+ assertThat(subnet, is(ri1.subnetId()));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapAdapter.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapAdapter.java
new file mode 100644
index 00000000..0631f865
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapAdapter.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.util;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+
+/**
+ * Testing adapter for EventuallyConsistentMap.
+ */
+public class VtnEventuallyConsistentMapAdapter<K, V> implements EventuallyConsistentMap<K, V> {
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return false;
+ }
+
+ @Override
+ public boolean containsValue(V value) {
+ return false;
+ }
+
+ @Override
+ public V get(K key) {
+ return null;
+ }
+
+ @Override
+ public void put(K key, V value) {
+
+ }
+
+ @Override
+ public V remove(K key) {
+ return null;
+ }
+
+ @Override
+ public void remove(K key, V value) {
+
+ }
+
+ @Override
+ public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
+ return null;
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+
+ }
+
+ @Override
+ public void clear() {
+
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return null;
+ }
+
+ @Override
+ public Collection<V> values() {
+ return null;
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return null;
+ }
+
+ @Override
+ public void addListener(EventuallyConsistentMapListener<K, V> listener) {
+
+ }
+
+ @Override
+ public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
+
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java
new file mode 100644
index 00000000..68b7d689
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.util;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiFunction;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.store.Timestamp;
+
+import static org.onosproject.store.service.EventuallyConsistentMapEvent.Type.*;
+import org.onosproject.store.service.EventuallyConsistentMapListener;
+import org.onosproject.store.service.EventuallyConsistentMapEvent;
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.EventuallyConsistentMap;
+
+/**
+ * Testing version of an Eventually Consistent Map.
+ */
+
+public final class VtnEventuallyConsistentMapTest<K, V> extends VtnEventuallyConsistentMapAdapter<K, V> {
+
+ private final HashMap<K, V> map;
+ private final String mapName;
+ private final List<EventuallyConsistentMapListener<K, V>> listeners;
+ private final BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
+
+ private VtnEventuallyConsistentMapTest(String mapName,
+ BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
+ map = new HashMap<>();
+ listeners = new LinkedList<>();
+ this.mapName = mapName;
+ this.peerUpdateFunction = peerUpdateFunction;
+ }
+
+ /**
+ * Notify all listeners of an event.
+ */
+ private void notifyListeners(EventuallyConsistentMapEvent<K, V> event) {
+ listeners.forEach(
+ listener -> listener.event(event)
+ );
+ }
+
+ @Override
+ public int size() {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(K key) {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(V value) {
+ return map.containsValue(value);
+ }
+
+ @Override
+ public V get(K key) {
+ return map.get(key);
+ }
+
+ @Override
+ public void put(K key, V value) {
+ map.put(key, value);
+ EventuallyConsistentMapEvent<K, V> addEvent =
+ new EventuallyConsistentMapEvent<>(mapName, PUT, key, value);
+ notifyListeners(addEvent);
+ if (peerUpdateFunction != null) {
+ peerUpdateFunction.apply(key, value);
+ }
+ }
+
+ @Override
+ public V remove(K key) {
+ V result = map.remove(key);
+ if (result != null) {
+ EventuallyConsistentMapEvent<K, V> removeEvent =
+ new EventuallyConsistentMapEvent<>(mapName, REMOVE,
+ key, map.get(key));
+ notifyListeners(removeEvent);
+ }
+ return result;
+ }
+
+ @Override
+ public void remove(K key, V value) {
+ boolean removed = map.remove(key, value);
+ if (removed) {
+ EventuallyConsistentMapEvent<K, V> removeEvent =
+ new EventuallyConsistentMapEvent<>(mapName, REMOVE, key, value);
+ notifyListeners(removeEvent);
+ }
+ }
+
+ @Override
+ public V compute(K key, BiFunction<K, V, V> recomputeFunction) {
+ return map.compute(key, recomputeFunction);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ map.putAll(m);
+ }
+
+ @Override
+ public void clear() {
+ map.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ return map.keySet();
+ }
+
+ @Override
+ public Collection<V> values() {
+ return map.values();
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ return map.entrySet();
+ }
+
+ public static <K, V> Builder<K, V> builder() {
+ return new Builder<>();
+ }
+
+ @Override
+ public void addListener(EventuallyConsistentMapListener<K, V> listener) {
+ listeners.add(listener);
+ }
+
+ @Override
+ public void removeListener(EventuallyConsistentMapListener<K, V> listener) {
+ listeners.remove(listener);
+ }
+
+ public static class Builder<K, V> implements EventuallyConsistentMapBuilder<K, V> {
+ private String name;
+ private BiFunction<K, V, Collection<NodeId>> peerUpdateFunction;
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withSerializer(KryoNamespace.Builder serializerBuilder) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V>
+ withTimestampProvider(BiFunction<K, V, Timestamp> timestampProvider) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withEventExecutor(ExecutorService executor) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withCommunicationExecutor(ExecutorService executor) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withBackgroundExecutor(ScheduledExecutorService executor) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V>
+ withPeerUpdateFunction(BiFunction<K, V, Collection<NodeId>> peerUpdateFunction) {
+ this.peerUpdateFunction = peerUpdateFunction;
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withTombstonesDisabled() {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withAntiEntropyPeriod(long period, TimeUnit unit) {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withFasterConvergence() {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMapBuilder<K, V> withPersistence() {
+ return this;
+ }
+
+ @Override
+ public EventuallyConsistentMap<K, V> build() {
+ if (name == null) {
+ name = "test";
+ }
+ return new VtnEventuallyConsistentMapTest<>(name, peerUpdateFunction);
+ }
+ }
+
+}
+
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java
new file mode 100644
index 00000000..efb1a791
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceAdapter.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.util;
+
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.ConsistentMapBuilder;
+import org.onosproject.store.service.DistributedSetBuilder;
+import org.onosproject.store.service.DistributedQueueBuilder;
+import org.onosproject.store.service.AtomicCounterBuilder;
+import org.onosproject.store.service.AtomicValueBuilder;
+import org.onosproject.store.service.TransactionContextBuilder;
+import org.onosproject.store.service.StorageService;
+
+/**
+ * Adapter for the storage service.
+ */
+public class VtnStorageServiceAdapter implements StorageService {
+ @Override
+ public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
+ return null;
+ }
+
+ @Override
+ public <K, V> ConsistentMapBuilder<K, V> consistentMapBuilder() {
+ return null;
+ }
+
+ @Override
+ public <E> DistributedSetBuilder<E> setBuilder() {
+ return null;
+ }
+
+ @Override
+ public <E> DistributedQueueBuilder<E> queueBuilder() {
+ return null;
+ }
+
+ @Override
+ public AtomicCounterBuilder atomicCounterBuilder() {
+ return null;
+ }
+
+ @Override
+ public <V> AtomicValueBuilder<V> atomicValueBuilder() {
+ return null;
+ }
+
+ @Override
+ public TransactionContextBuilder transactionContextBuilder() {
+ return null;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceTest.java
new file mode 100644
index 00000000..1f0f1835
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnStorageServiceTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnrsc.util;
+
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+
+public class VtnStorageServiceTest extends VtnStorageServiceAdapter {
+ @Override
+ public <K, V> EventuallyConsistentMapBuilder<K, V> eventuallyConsistentMapBuilder() {
+ return VtnEventuallyConsistentMapTest.builder();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java
new file mode 100644
index 00000000..f7e97d5d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FloatingIpWebResource.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.CREATED;
+import static javax.ws.rs.core.Response.Status.CONFLICT;
+import static javax.ws.rs.core.Response.Status.NO_CONTENT;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.DefaultFloatingIp;
+import org.onosproject.vtnrsc.FloatingIp;
+import org.onosproject.vtnrsc.FloatingIpId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.FloatingIp.Status;
+import org.onosproject.vtnrsc.floatingip.FloatingIpService;
+import org.onosproject.vtnweb.web.FloatingIpCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Sets;
+
+@Path("floatingips")
+public class FloatingIpWebResource extends AbstractWebResource {
+ private final Logger log = LoggerFactory
+ .getLogger(FloatingIpWebResource.class);
+ public static final String CREATE_FAIL = "Floating IP is failed to create!";
+ public static final String UPDATE_FAIL = "Floating IP is failed to update!";
+ public static final String GET_FAIL = "Floating IP is failed to get!";
+ public static final String NOT_EXIST = "Floating IP does not exist!";
+ public static final String DELETE_SUCCESS = "Floating IP delete success!";
+ public static final String JSON_NOT_NULL = "JsonNode can not be null";
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response listFloatingIps() {
+ Collection<FloatingIp> floatingIps = get(FloatingIpService.class)
+ .getFloatingIps();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("floatingips",
+ new FloatingIpCodec().encode(floatingIps, this));
+ return ok(result.toString()).build();
+ }
+
+ @GET
+ @Path("{floatingIpUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getFloatingIp(@PathParam("floatingIpUUID") String id,
+ @QueryParam("fields") List<String> fields) {
+
+ if (!get(FloatingIpService.class).exists(FloatingIpId.of(id))) {
+ return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
+ }
+ FloatingIp sub = nullIsNotFound(get(FloatingIpService.class)
+ .getFloatingIp(FloatingIpId.of(id)), GET_FAIL);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ if (fields.size() > 0) {
+ result.set("floatingip",
+ new FloatingIpCodec().extracFields(sub, this, fields));
+ } else {
+ result.set("floatingip", new FloatingIpCodec().encode(sub, this));
+ }
+ return ok(result.toString()).build();
+ }
+
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response createFloatingIp(final InputStream input) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ Collection<FloatingIp> floatingIps = createOrUpdateByInputStream(subnode);
+ Boolean result = nullIsNotFound((get(FloatingIpService.class)
+ .createFloatingIps(floatingIps)),
+ CREATE_FAIL);
+ if (!result) {
+ return Response.status(CONFLICT).entity(CREATE_FAIL).build();
+ }
+ return Response.status(CREATED).entity(result.toString()).build();
+
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @PUT
+ @Path("{floatingIpUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateFloatingIp(@PathParam("floatingIpUUID") String id,
+ final InputStream input) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ Collection<FloatingIp> floatingIps = createOrUpdateByInputStream(subnode);
+ Boolean result = nullIsNotFound(get(FloatingIpService.class)
+ .updateFloatingIps(floatingIps), UPDATE_FAIL);
+ if (!result) {
+ return Response.status(CONFLICT).entity(UPDATE_FAIL).build();
+ }
+ return ok(result.toString()).build();
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @Path("{floatingIpUUID}")
+ @DELETE
+ public Response deleteSingleFloatingIp(@PathParam("floatingIpUUID") String id)
+ throws IOException {
+ try {
+ FloatingIpId floatingIpId = FloatingIpId.of(id);
+ Set<FloatingIpId> floatingIpIds = Sets.newHashSet(floatingIpId);
+ get(FloatingIpService.class).removeFloatingIps(floatingIpIds);
+ return Response.status(NO_CONTENT).entity(DELETE_SUCCESS).build();
+ } catch (Exception e) {
+ return Response.status(NOT_FOUND).entity(e.getMessage()).build();
+ }
+ }
+
+ private Collection<FloatingIp> createOrUpdateByInputStream(JsonNode subnode)
+ throws Exception {
+ checkNotNull(subnode, JSON_NOT_NULL);
+ Collection<FloatingIp> floatingIps = null;
+ JsonNode floatingIpNodes = subnode.get("floatingips");
+ if (floatingIpNodes == null) {
+ floatingIpNodes = subnode.get("floatingip");
+ }
+ log.debug("floatingNodes is {}", floatingIpNodes.toString());
+
+ if (floatingIpNodes.isArray()) {
+ throw new IllegalArgumentException("only singleton requests allowed");
+ } else {
+ floatingIps = changeJsonToSub(floatingIpNodes);
+ }
+ return floatingIps;
+ }
+
+ /**
+ * Returns a collection of floatingIps from floatingIpNodes.
+ *
+ * @param floatingIpNodes the floatingIp json node
+ * @return floatingIps a collection of floatingIp
+ * @throws Exception when any argument is illegal
+ */
+ public Collection<FloatingIp> changeJsonToSub(JsonNode floatingIpNodes)
+ throws Exception {
+ checkNotNull(floatingIpNodes, JSON_NOT_NULL);
+ Map<FloatingIpId, FloatingIp> subMap = new HashMap<FloatingIpId, FloatingIp>();
+ if (!floatingIpNodes.hasNonNull("id")) {
+ throw new IllegalArgumentException("id should not be null");
+ } else if (floatingIpNodes.get("id").asText().isEmpty()) {
+ throw new IllegalArgumentException("id should not be empty");
+ }
+ FloatingIpId id = FloatingIpId.of(floatingIpNodes.get("id")
+ .asText());
+
+ if (!floatingIpNodes.hasNonNull("tenant_id")) {
+ throw new IllegalArgumentException("tenant_id should not be null");
+ } else if (floatingIpNodes.get("tenant_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("tenant_id should not be empty");
+ }
+ TenantId tenantId = TenantId.tenantId(floatingIpNodes.get("tenant_id")
+ .asText());
+
+ if (!floatingIpNodes.hasNonNull("floating_network_id")) {
+ throw new IllegalArgumentException(
+ "floating_network_id should not be null");
+ } else if (floatingIpNodes.get("floating_network_id").asText()
+ .isEmpty()) {
+ throw new IllegalArgumentException(
+ "floating_network_id should not be empty");
+ }
+ TenantNetworkId networkId = TenantNetworkId.networkId(floatingIpNodes
+ .get("floating_network_id").asText());
+
+ VirtualPortId portId = null;
+ if (floatingIpNodes.hasNonNull("port_id")) {
+ portId = VirtualPortId.portId(floatingIpNodes.get("port_id")
+ .asText());
+ }
+
+ RouterId routerId = null;
+ if (floatingIpNodes.hasNonNull("router_id")) {
+ routerId = RouterId.valueOf(floatingIpNodes.get("router_id")
+ .asText());
+ }
+
+ IpAddress fixedIp = null;
+ if (floatingIpNodes.hasNonNull("fixed_ip_address")) {
+ fixedIp = IpAddress.valueOf(floatingIpNodes.get("fixed_ip_address")
+ .asText());
+ }
+
+ if (!floatingIpNodes.hasNonNull("floating_ip_address")) {
+ throw new IllegalArgumentException(
+ "floating_ip_address should not be null");
+ } else if (floatingIpNodes.get("floating_ip_address").asText()
+ .isEmpty()) {
+ throw new IllegalArgumentException(
+ "floating_ip_address should not be empty");
+ }
+ IpAddress floatingIp = IpAddress.valueOf(floatingIpNodes
+ .get("floating_ip_address").asText());
+
+ if (!floatingIpNodes.hasNonNull("status")) {
+ throw new IllegalArgumentException("status should not be null");
+ } else if (floatingIpNodes.get("status").asText().isEmpty()) {
+ throw new IllegalArgumentException("status should not be empty");
+ }
+ Status status = Status.valueOf(floatingIpNodes.get("status").asText());
+
+ DefaultFloatingIp floatingIpObj = new DefaultFloatingIp(id, tenantId,
+ networkId,
+ portId,
+ routerId,
+ floatingIp,
+ fixedIp, status);
+ subMap.put(id, floatingIpObj);
+ return Collections.unmodifiableCollection(subMap.values());
+ }
+
+ /**
+ * Returns the specified item if that items is null; otherwise throws not
+ * found exception.
+ *
+ * @param item item to check
+ * @param <T> item type
+ * @param message not found message
+ * @return item if not null
+ * @throws org.onlab.util.ItemNotFoundException if item is null
+ */
+ protected <T> T nullIsNotFound(T item, String message) {
+ if (item == null) {
+ throw new ItemNotFoundException(message);
+ }
+ return item;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
index b0e2f38d..08e37f96 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
@@ -15,7 +15,6 @@
*/
package org.onosproject.vtnweb.resources;
-import static javax.ws.rs.core.Response.Status.NOT_FOUND;
import static javax.ws.rs.core.Response.Status.OK;
import static org.onlab.util.Tools.nullIsNotFound;
@@ -54,7 +53,6 @@ public class FlowClassifierWebResource extends AbstractWebResource {
private final Logger log = LoggerFactory.getLogger(FlowClassifierWebResource.class);
- final FlowClassifierService service = get(FlowClassifierService.class);
public static final String FLOW_CLASSIFIER_NOT_FOUND = "Flow classifier not found";
/**
@@ -65,7 +63,7 @@ public class FlowClassifierWebResource extends AbstractWebResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getFlowClassifiers() {
- final Iterable<FlowClassifier> flowClassifiers = service.getFlowClassifiers();
+ Iterable<FlowClassifier> flowClassifiers = get(FlowClassifierService.class).getFlowClassifiers();
ObjectNode result = new ObjectMapper().createObjectNode();
ArrayNode flowClassifierEntry = result.putArray("flow_classifiers");
if (flowClassifiers != null) {
@@ -79,19 +77,16 @@ public class FlowClassifierWebResource extends AbstractWebResource {
/**
* Get details of a flow classifier.
*
- * @param id flow classifier id
+ * @param id
+ * flow classifier id
* @return 200 OK , 404 if given identifier does not exist
*/
@GET
@Path("{flow_id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getFlowClassifier(@PathParam("flow_id") String id) {
-
- if (!service.hasFlowClassifier(FlowClassifierId.of(id))) {
- return Response.status(NOT_FOUND).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
- }
- FlowClassifier flowClassifier = nullIsNotFound(service.getFlowClassifier(FlowClassifierId.of(id)),
- FLOW_CLASSIFIER_NOT_FOUND);
+ FlowClassifier flowClassifier = nullIsNotFound(
+ get(FlowClassifierService.class).getFlowClassifier(FlowClassifierId.of(id)), FLOW_CLASSIFIER_NOT_FOUND);
ObjectNode result = new ObjectMapper().createObjectNode();
result.set("flow_classifier", new FlowClassifierCodec().encode(flowClassifier, this));
@@ -102,9 +97,10 @@ public class FlowClassifierWebResource extends AbstractWebResource {
/**
* Creates and stores a new flow classifier.
*
- * @param stream flow classifier from JSON
+ * @param stream
+ * flow classifier from JSON
* @return status of the request - CREATED if the JSON is correct,
- * BAD_REQUEST if the JSON is invalid
+ * BAD_REQUEST if the JSON is invalid
*/
@POST
@Consumes(MediaType.APPLICATION_JSON)
@@ -116,7 +112,8 @@ public class FlowClassifierWebResource extends AbstractWebResource {
JsonNode flow = jsonTree.get("flow_classifier");
FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this);
- Boolean issuccess = nullIsNotFound(service.createFlowClassifier(flowClassifier), FLOW_CLASSIFIER_NOT_FOUND);
+ Boolean issuccess = nullIsNotFound(get(FlowClassifierService.class).createFlowClassifier(flowClassifier),
+ FLOW_CLASSIFIER_NOT_FOUND);
return Response.status(OK).entity(issuccess.toString()).build();
} catch (IOException ex) {
log.error("Exception while creating flow classifier {}.", ex.toString());
@@ -127,8 +124,10 @@ public class FlowClassifierWebResource extends AbstractWebResource {
/**
* Update details of a flow classifier.
*
- * @param id flow classifier id
- * @param stream InputStream
+ * @param id
+ * flow classifier id
+ * @param stream
+ * InputStream
* @return 200 OK, 404 if given identifier does not exist
*/
@PUT
@@ -141,7 +140,8 @@ public class FlowClassifierWebResource extends AbstractWebResource {
JsonNode jsonTree = mapper().readTree(stream);
JsonNode flow = jsonTree.get("flow_classifier");
FlowClassifier flowClassifier = new FlowClassifierCodec().decode((ObjectNode) flow, this);
- Boolean result = nullIsNotFound(service.updateFlowClassifier(flowClassifier), FLOW_CLASSIFIER_NOT_FOUND);
+ Boolean result = nullIsNotFound(get(FlowClassifierService.class).updateFlowClassifier(flowClassifier),
+ FLOW_CLASSIFIER_NOT_FOUND);
return Response.status(OK).entity(result.toString()).build();
} catch (IOException e) {
log.error("Update flow classifier failed because of exception {}.", e.toString());
@@ -152,14 +152,16 @@ public class FlowClassifierWebResource extends AbstractWebResource {
/**
* Delete details of a flow classifier.
*
- * @param id flow classifier id
+ * @param id
+ * flow classifier id
*/
@Path("{flow_id}")
@DELETE
public void deleteFlowClassifier(@PathParam("flow_id") String id) {
log.debug("Deletes flow classifier by identifier {}.", id);
FlowClassifierId flowClassifierId = FlowClassifierId.of(id);
- Boolean issuccess = nullIsNotFound(service.removeFlowClassifier(flowClassifierId), FLOW_CLASSIFIER_NOT_FOUND);
+ Boolean issuccess = nullIsNotFound(get(FlowClassifierService.class).removeFlowClassifier(flowClassifierId),
+ FLOW_CLASSIFIER_NOT_FOUND);
}
}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/RouterWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/RouterWebResource.java
new file mode 100644
index 00000000..6f80dd15
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/RouterWebResource.java
@@ -0,0 +1,447 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
+import static javax.ws.rs.core.Response.Status.CONFLICT;
+import static javax.ws.rs.core.Response.Status.CREATED;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+import static javax.ws.rs.core.Response.Status.NO_CONTENT;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onlab.packet.IpAddress;
+import org.onlab.util.ItemNotFoundException;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.DefaultRouter;
+import org.onosproject.vtnrsc.FixedIp;
+import org.onosproject.vtnrsc.Router;
+import org.onosproject.vtnrsc.Router.Status;
+import org.onosproject.vtnrsc.RouterGateway;
+import org.onosproject.vtnrsc.RouterId;
+import org.onosproject.vtnrsc.RouterInterface;
+import org.onosproject.vtnrsc.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.router.RouterService;
+import org.onosproject.vtnrsc.routerinterface.RouterInterfaceService;
+import org.onosproject.vtnweb.web.RouterCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+@Path("routers")
+public class RouterWebResource extends AbstractWebResource {
+ private final Logger log = LoggerFactory.getLogger(RouterWebResource.class);
+ public static final String CREATE_FAIL = "Router is failed to create!";
+ public static final String UPDATE_FAIL = "Router is failed to update!";
+ public static final String GET_FAIL = "Router is failed to get!";
+ public static final String NOT_EXIST = "Router does not exist!";
+ public static final String DELETE_SUCCESS = "Router delete success!";
+ public static final String JSON_NOT_NULL = "JsonNode can not be null";
+ public static final String INTFACR_ADD_SUCCESS = "Interface add success";
+ public static final String INTFACR_DEL_SUCCESS = "Interface delete success";
+
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response listRouters() {
+ Collection<Router> routers = get(RouterService.class).getRouters();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("routers", new RouterCodec().encode(routers, this));
+ return ok(result.toString()).build();
+ }
+
+ @GET
+ @Path("{routerUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getRouter(@PathParam("routerUUID") String id,
+ @QueryParam("fields") List<String> fields) {
+
+ if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
+ return Response.status(NOT_FOUND)
+ .entity("The Router does not exists").build();
+ }
+ Router sub = nullIsNotFound(get(RouterService.class)
+ .getRouter(RouterId.valueOf(id)),
+ NOT_EXIST);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ if (fields.size() > 0) {
+ result.set("router",
+ new RouterCodec().extracFields(sub, this, fields));
+ } else {
+ result.set("router", new RouterCodec().encode(sub, this));
+ }
+ return ok(result.toString()).build();
+ }
+
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response createRouter(final InputStream input) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ Collection<Router> routers = createOrUpdateByInputStream(subnode);
+
+ Boolean result = nullIsNotFound((get(RouterService.class)
+ .createRouters(routers)),
+ CREATE_FAIL);
+ if (!result) {
+ return Response.status(CONFLICT).entity(CREATE_FAIL).build();
+ }
+ return Response.status(CREATED).entity(result.toString()).build();
+
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @PUT
+ @Path("{routerUUID}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateRouter(@PathParam("routerUUID") String id,
+ final InputStream input) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ Collection<Router> routers = createOrUpdateByInputStream(subnode);
+ Boolean result = nullIsNotFound(get(RouterService.class)
+ .updateRouters(routers), UPDATE_FAIL);
+ if (!result) {
+ return Response.status(CONFLICT).entity(UPDATE_FAIL).build();
+ }
+ return ok(result.toString()).build();
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @Path("{routerUUID}")
+ @DELETE
+ public Response deleteSingleRouter(@PathParam("routerUUID") String id)
+ throws IOException {
+ try {
+ RouterId routerId = RouterId.valueOf(id);
+ Set<RouterId> routerIds = Sets.newHashSet(routerId);
+ get(RouterService.class).removeRouters(routerIds);
+ return Response.status(NO_CONTENT).entity(DELETE_SUCCESS).build();
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @PUT
+ @Path("{routerUUID}/add_router_interface")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response addRouterInterface(@PathParam("routerUUID") String id,
+ final InputStream input) {
+ if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
+ return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
+ }
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ if (!subnode.hasNonNull("id")) {
+ throw new IllegalArgumentException("id should not be null");
+ } else if (subnode.get("id").asText().isEmpty()) {
+ throw new IllegalArgumentException("id should not be empty");
+ }
+ RouterId routerId = RouterId.valueOf(id);
+ if (!subnode.hasNonNull("subnet_id")) {
+ throw new IllegalArgumentException("subnet_id should not be null");
+ } else if (subnode.get("subnet_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("subnet_id should not be empty");
+ }
+ SubnetId subnetId = SubnetId.subnetId(subnode.get("subnet_id")
+ .asText());
+ if (!subnode.hasNonNull("tenant_id")) {
+ throw new IllegalArgumentException("tenant_id should not be null");
+ } else if (subnode.get("tenant_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("tenant_id should not be empty");
+ }
+ TenantId tenentId = TenantId.tenantId(subnode.get("tenant_id")
+ .asText());
+ if (!subnode.hasNonNull("port_id")) {
+ throw new IllegalArgumentException("port_id should not be null");
+ } else if (subnode.get("port_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("port_id should not be empty");
+ }
+ VirtualPortId portId = VirtualPortId.portId(subnode.get("port_id")
+ .asText());
+ RouterInterface routerInterface = RouterInterface
+ .routerInterface(subnetId, portId, routerId, tenentId);
+ get(RouterInterfaceService.class)
+ .addRouterInterface(routerInterface);
+ return ok(INTFACR_ADD_SUCCESS).build();
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ @PUT
+ @Path("{routerUUID}/remove_router_interface")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response removeRouterInterface(@PathParam("routerUUID") String id,
+ final InputStream input) {
+ if (!get(RouterService.class).exists(RouterId.valueOf(id))) {
+ return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
+ }
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode subnode = mapper.readTree(input);
+ if (!subnode.hasNonNull("id")) {
+ throw new IllegalArgumentException("id should not be null");
+ } else if (subnode.get("id").asText().isEmpty()) {
+ throw new IllegalArgumentException("id should not be empty");
+ }
+ RouterId routerId = RouterId.valueOf(id);
+ if (!subnode.hasNonNull("subnet_id")) {
+ throw new IllegalArgumentException("subnet_id should not be null");
+ } else if (subnode.get("subnet_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("subnet_id should not be empty");
+ }
+ SubnetId subnetId = SubnetId.subnetId(subnode.get("subnet_id")
+ .asText());
+ if (!subnode.hasNonNull("port_id")) {
+ throw new IllegalArgumentException("port_id should not be null");
+ } else if (subnode.get("port_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("port_id should not be empty");
+ }
+ VirtualPortId portId = VirtualPortId.portId(subnode.get("port_id")
+ .asText());
+ if (!subnode.hasNonNull("tenant_id")) {
+ throw new IllegalArgumentException("tenant_id should not be null");
+ } else if (subnode.get("tenant_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("tenant_id should not be empty");
+ }
+ TenantId tenentId = TenantId.tenantId(subnode.get("tenant_id")
+ .asText());
+ RouterInterface routerInterface = RouterInterface
+ .routerInterface(subnetId, portId, routerId, tenentId);
+ get(RouterInterfaceService.class)
+ .removeRouterInterface(routerInterface);
+ return ok(INTFACR_DEL_SUCCESS).build();
+ } catch (Exception e) {
+ return Response.status(BAD_REQUEST).entity(e.getMessage()).build();
+ }
+ }
+
+ private Collection<Router> createOrUpdateByInputStream(JsonNode subnode)
+ throws Exception {
+ checkNotNull(subnode, JSON_NOT_NULL);
+ JsonNode routerNode = subnode.get("routers");
+ if (routerNode == null) {
+ routerNode = subnode.get("router");
+ }
+ log.debug("routerNode is {}", routerNode.toString());
+
+ if (routerNode.isArray()) {
+ throw new Exception("only singleton requests allowed");
+ } else {
+ return changeJsonToSub(routerNode);
+ }
+ }
+
+ /**
+ * Returns a collection of floatingIps from floatingIpNodes.
+ *
+ * @param routerNode the router json node
+ * @return routers a collection of router
+ * @throws Exception when any argument is illegal
+ */
+ public Collection<Router> changeJsonToSub(JsonNode routerNode)
+ throws Exception {
+ checkNotNull(routerNode, JSON_NOT_NULL);
+ Map<RouterId, Router> subMap = new HashMap<RouterId, Router>();
+ if (!routerNode.hasNonNull("id")) {
+ new IllegalArgumentException("id should not be null");
+ } else if (routerNode.get("id").asText().isEmpty()) {
+ throw new IllegalArgumentException("id should not be empty");
+ }
+ RouterId id = RouterId.valueOf(routerNode.get("id").asText());
+
+ if (!routerNode.hasNonNull("tenant_id")) {
+ throw new IllegalArgumentException("tenant_id should not be null");
+ } else if (routerNode.get("tenant_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("tenant_id should not be empty");
+ }
+ TenantId tenantId = TenantId.tenantId(routerNode.get("tenant_id")
+ .asText());
+
+ VirtualPortId gwPortId = null;
+ if (routerNode.hasNonNull("gw_port_id")) {
+ gwPortId = VirtualPortId.portId(routerNode.get("gw_port_id")
+ .asText());
+ }
+
+ if (!routerNode.hasNonNull("status")) {
+ throw new IllegalArgumentException("status should not be null");
+ } else if (routerNode.get("status").asText().isEmpty()) {
+ throw new IllegalArgumentException("status should not be empty");
+ }
+ Status status = Status.valueOf(routerNode.get("status").asText());
+
+ String routerName = null;
+ if (routerNode.hasNonNull("name")) {
+ routerName = routerNode.get("name").asText();
+ }
+
+ boolean adminStateUp = true;
+ checkArgument(routerNode.get("admin_state_up").isBoolean(),
+ "admin_state_up should be boolean");
+ if (routerNode.hasNonNull("admin_state_up")) {
+ adminStateUp = routerNode.get("admin_state_up").asBoolean();
+ }
+ boolean distributed = false;
+ if (routerNode.hasNonNull("distributed")) {
+ distributed = routerNode.get("distributed").asBoolean();
+ }
+ RouterGateway gateway = null;
+ if (routerNode.hasNonNull("external_gateway_info")) {
+ gateway = jsonNodeToGateway(routerNode.get("external_gateway_info"));
+ }
+ List<String> routes = new ArrayList<String>();
+ DefaultRouter routerObj = new DefaultRouter(id, routerName,
+ adminStateUp, status,
+ distributed, gateway,
+ gwPortId, tenantId, routes);
+ subMap.put(id, routerObj);
+ return Collections.unmodifiableCollection(subMap.values());
+ }
+
+ /**
+ * Changes JsonNode Gateway to the Gateway.
+ *
+ * @param gateway the gateway JsonNode
+ * @return gateway
+ */
+ private RouterGateway jsonNodeToGateway(JsonNode gateway) {
+ checkNotNull(gateway, JSON_NOT_NULL);
+ if (!gateway.hasNonNull("network_id")) {
+ throw new IllegalArgumentException("network_id should not be null");
+ } else if (gateway.get("network_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("network_id should not be empty");
+ }
+ TenantNetworkId networkId = TenantNetworkId.networkId(gateway
+ .get("network_id").asText());
+
+ if (!gateway.hasNonNull("enable_snat")) {
+ throw new IllegalArgumentException("enable_snat should not be null");
+ } else if (gateway.get("enable_snat").asText().isEmpty()) {
+ throw new IllegalArgumentException("enable_snat should not be empty");
+ }
+ checkArgument(gateway.get("enable_snat").isBoolean(),
+ "enable_snat should be boolean");
+ boolean enableSnat = gateway.get("enable_snat").asBoolean();
+
+ if (!gateway.hasNonNull("external_fixed_ips")) {
+ throw new IllegalArgumentException(
+ "external_fixed_ips should not be null");
+ } else if (gateway.get("external_fixed_ips").isNull()) {
+ throw new IllegalArgumentException(
+ "external_fixed_ips should not be empty");
+ }
+ Collection<FixedIp> fixedIpList = jsonNodeToFixedIp(gateway
+ .get("external_fixed_ips"));
+ RouterGateway gatewayObj = RouterGateway.routerGateway(networkId,
+ enableSnat,
+ fixedIpList);
+ return gatewayObj;
+ }
+
+ /**
+ * Changes JsonNode fixedIp to a collection of the fixedIp.
+ *
+ * @param fixedIp the allocationPools JsonNode
+ * @return a collection of fixedIp
+ */
+ private Collection<FixedIp> jsonNodeToFixedIp(JsonNode fixedIp) {
+ checkNotNull(fixedIp, JSON_NOT_NULL);
+ ConcurrentMap<Integer, FixedIp> fixedIpMaps = Maps.newConcurrentMap();
+ Integer i = 0;
+ for (JsonNode node : fixedIp) {
+ if (!node.hasNonNull("subnet_id")) {
+ throw new IllegalArgumentException("subnet_id should not be null");
+ } else if (node.get("subnet_id").asText().isEmpty()) {
+ throw new IllegalArgumentException("subnet_id should not be empty");
+ }
+ SubnetId subnetId = SubnetId.subnetId(node.get("subnet_id")
+ .asText());
+ if (!node.hasNonNull("ip_address")) {
+ throw new IllegalArgumentException("ip_address should not be null");
+ } else if (node.get("ip_address").asText().isEmpty()) {
+ throw new IllegalArgumentException("ip_address should not be empty");
+ }
+ IpAddress ipAddress = IpAddress.valueOf(node.get("ip_address")
+ .asText());
+ FixedIp fixedIpObj = FixedIp.fixedIp(subnetId, ipAddress);
+
+ fixedIpMaps.putIfAbsent(i, fixedIpObj);
+ i++;
+ }
+ return Collections.unmodifiableCollection(fixedIpMaps.values());
+ }
+
+ /**
+ * Returns the specified item if that items is null; otherwise throws not
+ * found exception.
+ *
+ * @param item item to check
+ * @param <T> item type
+ * @param message not found message
+ * @return item if not null
+ * @throws org.onlab.util.ItemNotFoundException if item is null
+ */
+ protected <T> T nullIsNotFound(T item, String message) {
+ if (item == null) {
+ throw new ItemNotFoundException(message);
+ }
+ return item;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java
index 2dd931ea..fd2c4790 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java
@@ -98,20 +98,20 @@ public class TenantNetworkWebResource extends AbstractWebResource {
if ((queryId == null || queryId.equals(network.id().toString()))
&& (queryName == null || queryName.equals(network.name()))
&& (queryadminStateUp == null || queryadminStateUp
- .equals(network.adminStateUp()))
+ .equals(Boolean.toString(network.adminStateUp())))
&& (querystate == null || querystate.equals(network.state()
.toString()))
- && (queryshared == null || queryshared.equals(network
- .shared()))
+ && (queryshared == null || queryshared.equals(Boolean.toString(network
+ .shared())))
&& (querytenantId == null || querytenantId.equals(network
.tenantId().toString()))
- && (routerExternal == null || routerExternal.equals(network
- .routerExternal()))
- && (type == null || type.equals(network.type()))
+ && (routerExternal == null || routerExternal.equals(Boolean.toString(network
+ .routerExternal())))
+ && (type == null || type.equals(network.type().toString()))
&& (physicalNetwork == null || physicalNetwork
- .equals(network.physicalNetwork()))
+ .equals(network.physicalNetwork().toString()))
&& (segmentationId == null || segmentationId.equals(network
- .segmentationId()))) {
+ .segmentationId().toString()))) {
networksMap.putIfAbsent(network.id(), network);
}
}
@@ -269,42 +269,39 @@ public class TenantNetworkWebResource extends AbstractWebResource {
TenantNetwork network = null;
ConcurrentMap<TenantNetworkId, TenantNetwork> networksMap = Maps
.newConcurrentMap();
- if (node != null) {
- checkArgument(node.get("admin_state_up").isBoolean(), "admin_state_up should be boolean");
- checkArgument(node.get("shared").isBoolean(), "shared should be boolean");
- checkArgument(node.get("router:external").isBoolean(), "router:external should be boolean");
- String name = node.get("name").asText();
- boolean adminStateUp = node.get("admin_state_up").asBoolean();
- String state = node.get("status").asText();
- boolean shared = node.get("shared").asBoolean();
- String tenantId = node.get("tenant_id").asText();
- boolean routerExternal = node.get("router:external").asBoolean();
- String type = node.get("provider:network_type").asText();
- String physicalNetwork = node.get("provider:physical_network")
- .asText();
- String segmentationId = node.get("provider:segmentation_id")
- .asText();
- TenantNetworkId id = null;
- if (flag == CREATE_NETWORK) {
- id = TenantNetworkId.networkId(node.get("id").asText());
- } else if (flag == UPDATE_NETWORK) {
- id = networkId;
- }
- network = new DefaultTenantNetwork(
- id,
- name,
- adminStateUp,
- isState(state),
- shared,
- TenantId.tenantId(tenantId),
- routerExternal,
- isType(type),
- PhysicalNetwork
- .physicalNetwork(physicalNetwork),
- SegmentationId
- .segmentationId(segmentationId));
- networksMap.putIfAbsent(id, network);
+ checkArgument(node.get("admin_state_up").isBoolean(), "admin_state_up should be boolean");
+ checkArgument(node.get("shared").isBoolean(), "shared should be boolean");
+ checkArgument(node.get("router:external").isBoolean(), "router:external should be boolean");
+ String name = node.get("name").asText();
+ boolean adminStateUp = node.get("admin_state_up").asBoolean();
+ String state = node.get("status").asText();
+ boolean shared = node.get("shared").asBoolean();
+ String tenantId = node.get("tenant_id").asText();
+ boolean routerExternal = node.get("router:external").asBoolean();
+ String type = node.get("provider:network_type").asText();
+ String physicalNetwork = node.get("provider:physical_network").asText();
+ String segmentationId = node.get("provider:segmentation_id").asText();
+ TenantNetworkId id = null;
+ if (flag.equals(CREATE_NETWORK)) {
+ id = TenantNetworkId.networkId(node.get("id").asText());
+ } else if (flag.equals(UPDATE_NETWORK)) {
+ id = networkId;
}
+ network = new DefaultTenantNetwork(
+ id,
+ name,
+ adminStateUp,
+ isState(state),
+ shared,
+ TenantId.tenantId(tenantId),
+ routerExternal,
+ isType(type),
+ PhysicalNetwork
+ .physicalNetwork(physicalNetwork),
+ SegmentationId
+ .segmentationId(segmentationId));
+ networksMap.putIfAbsent(id, network);
+
return Collections.unmodifiableCollection(networksMap.values());
}
@@ -319,38 +316,32 @@ public class TenantNetworkWebResource extends AbstractWebResource {
TenantNetwork network = null;
ConcurrentMap<TenantNetworkId, TenantNetwork> networksMap = Maps
.newConcurrentMap();
- if (nodes != null) {
- for (JsonNode node : nodes) {
- String id = node.get("id").asText();
- String name = node.get("name").asText();
- boolean adminStateUp = node.get("admin_state_up").asBoolean();
- String state = node.get("status").asText();
- boolean shared = node.get("shared").asBoolean();
- String tenantId = node.get("tenant_id").asText();
- boolean routerExternal = node.get("router:external")
- .asBoolean();
- String type = node.get("provider:network_type").asText();
- String physicalNetwork = node.get("provider:physical_network")
- .asText();
- String segmentationId = node.get("provider:segmentation_id")
- .asText();
- network = new DefaultTenantNetwork(
- TenantNetworkId
- .networkId(id),
- name,
- adminStateUp,
- isState(state),
- shared,
- TenantId.tenantId(tenantId),
- routerExternal,
- isType(type),
- PhysicalNetwork
- .physicalNetwork(physicalNetwork),
- SegmentationId
- .segmentationId(segmentationId));
- networksMap.putIfAbsent(TenantNetworkId.networkId(id), network);
- }
+ for (JsonNode node : nodes) {
+ String id = node.get("id").asText();
+ String name = node.get("name").asText();
+ boolean adminStateUp = node.get("admin_state_up").asBoolean();
+ String state = node.get("status").asText();
+ boolean shared = node.get("shared").asBoolean();
+ String tenantId = node.get("tenant_id").asText();
+ boolean routerExternal = node.get("router:external")
+ .asBoolean();
+ String type = node.get("provider:network_type").asText();
+ String physicalNetwork = node.get("provider:physical_network").asText();
+ String segmentationId = node.get("provider:segmentation_id").asText();
+ network = new DefaultTenantNetwork(
+ TenantNetworkId.networkId(id),
+ name,
+ adminStateUp,
+ isState(state),
+ shared,
+ TenantId.tenantId(tenantId),
+ routerExternal,
+ isType(type),
+ PhysicalNetwork.physicalNetwork(physicalNetwork),
+ SegmentationId.segmentationId(segmentationId));
+ networksMap.putIfAbsent(TenantNetworkId.networkId(id), network);
}
+
return Collections.unmodifiableCollection(networksMap.values());
}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java
new file mode 100644
index 00000000..ff5aebb4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FloatingIpCodec.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.FloatingIp;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * FloatingIp JSON codec.
+ */
+public final class FloatingIpCodec extends JsonCodec<FloatingIp> {
+ @Override
+ public ObjectNode encode(FloatingIp floatingIp, CodecContext context) {
+ checkNotNull(floatingIp, "floatingIp cannot be null");
+ ObjectNode result = context
+ .mapper()
+ .createObjectNode()
+ .put("id", floatingIp.id().floatingIpId().toString())
+ .put("floating_network_id", floatingIp.networkId().toString())
+ .put("router_id",
+ floatingIp.routerId() == null ? null : floatingIp
+ .routerId().routerId())
+ .put("tenant_id", floatingIp.tenantId().toString())
+ .put("port_id",
+ floatingIp.portId() == null ? null : floatingIp.portId()
+ .toString())
+ .put("fixed_ip_address",
+ floatingIp.fixedIp() == null ? null : floatingIp.fixedIp()
+ .toString())
+ .put("floating_ip_address", floatingIp.floatingIp().toString())
+ .put("status", floatingIp.status().toString());
+ return result;
+ }
+
+ public ObjectNode extracFields(FloatingIp floatingIp, CodecContext context,
+ List<String> fields) {
+ checkNotNull(floatingIp, "floatingIp cannot be null");
+ ObjectNode result = context.mapper().createObjectNode();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("floating_network_id")) {
+ result.put("floating_network_id", floatingIp.networkId()
+ .toString());
+ }
+ if (s.equals("router_id")) {
+ result.put("router_id",
+ floatingIp.routerId() == null ? null : floatingIp
+ .routerId().routerId());
+ }
+ if (s.equals("tenant_id")) {
+ result.put("tenant_id", floatingIp.tenantId().toString());
+ }
+ if (s.equals("port_id")) {
+ result.put("port_id",
+ floatingIp.portId() == null ? null : floatingIp
+ .portId().toString());
+ }
+ if (s.equals("id")) {
+ result.put("id", floatingIp.id().floatingIpId().toString());
+ }
+ if (s.equals("fixed_ip_address")) {
+ result.put("fixed_ip_address",
+ floatingIp.fixedIp() == null ? null : floatingIp
+ .fixedIp().toString());
+ }
+ if (s.equals("floating_ip_address")) {
+ result.put("floating_ip_address", floatingIp.floatingIp()
+ .toString());
+ }
+ if (s.equals("status")) {
+ result.put("status", floatingIp.status().toString());
+ }
+ }
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterCodec.java
new file mode 100644
index 00000000..61f7e955
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterCodec.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.Router;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Router JSON codec.
+ */
+public class RouterCodec extends JsonCodec<Router> {
+ @Override
+ public ObjectNode encode(Router router, CodecContext context) {
+ checkNotNull(router, "router cannot be null");
+ ObjectNode result = context
+ .mapper()
+ .createObjectNode()
+ .put("id", router.id().routerId())
+ .put("status", router.status().toString())
+ .put("name", router.name().toString())
+ .put("admin_state_up", router.adminStateUp())
+ .put("tenant_id", router.tenantId().toString())
+ .put("routes",
+ router.routes() == null ? null : router.routes()
+ .toString());
+ result.set("external_gateway_info",
+ router.externalGatewayInfo() == null ? null
+ : new RouterGatewayInfoCodec()
+ .encode(router.externalGatewayInfo(), context));
+
+ return result;
+ }
+
+ public ObjectNode extracFields(Router router, CodecContext context,
+ List<String> fields) {
+ checkNotNull(router, "router cannot be null");
+ ObjectNode result = context.mapper().createObjectNode();
+ Iterator<String> i = fields.iterator();
+ while (i.hasNext()) {
+ String s = i.next();
+ if (s.equals("id")) {
+ result.put("id", router.id().routerId());
+ }
+ if (s.equals("status")) {
+ result.put("status", router.status().toString());
+ }
+ if (s.equals("name")) {
+ result.put("name", router.name().toString());
+ }
+ if (s.equals("admin_state_up")) {
+ result.put("admin_state_up", router.adminStateUp());
+ }
+ if (s.equals("tenant_id")) {
+ result.put("tenant_id", router.tenantId().toString());
+ }
+ if (s.equals("routes")) {
+ result.put("routes", router.routes() == null ? null : router
+ .routes().toString());
+ }
+ if (s.equals("external_gateway_info")) {
+ result.set("external_gateway_info",
+ router.externalGatewayInfo() == null ? null
+ : new RouterGatewayInfoCodec()
+ .encode(router.externalGatewayInfo(),
+ context));
+ }
+ }
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterGatewayInfoCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterGatewayInfoCodec.java
new file mode 100644
index 00000000..cb9fb67d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/RouterGatewayInfoCodec.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.RouterGateway;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Subnet Router Gateway Info codec.
+ */
+public class RouterGatewayInfoCodec extends JsonCodec<RouterGateway> {
+ @Override
+ public ObjectNode encode(RouterGateway routerGateway, CodecContext context) {
+ checkNotNull(routerGateway, "routerGateway cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("network_id", routerGateway.networkId().toString());
+ result.set("external_fixed_ips", new FixedIpCodec()
+ .encode(routerGateway.externalFixedIps(), context));
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
index 97337960..13b377bf 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/webapp/WEB-INF/web.xml
@@ -37,6 +37,8 @@
org.onosproject.vtnweb.resources.PortChainWebResource
org.onosproject.vtnweb.resources.PortPairGroupWebResource
org.onosproject.vtnweb.resources.PortPairWebResource
+ org.onosproject.vtnweb.resources.FloatingIpWebResource
+ org.onosproject.vtnweb.resources.RouterWebResource
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java
new file mode 100644
index 00000000..be645be0
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.packet.IpPrefix;
+import org.onlab.rest.BaseResource;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.flowclassifier.FlowClassifierService;
+
+import com.eclipsesource.json.JsonObject;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+/**
+ * Unit tests for flow classifier REST APIs.
+ */
+public class FlowClassifierResourceTest extends VtnResourceTest {
+
+ final FlowClassifierService flowClassifierService = createMock(FlowClassifierService.class);
+
+ FlowClassifierId flowClassifierId1 = FlowClassifierId.of("4a334cd4-fe9c-4fae-af4b-321c5e2eb051");
+ TenantId tenantId1 = TenantId.tenantId("1814726e2d22407b8ca76db5e567dcf1");
+ VirtualPortId srcPortId1 = VirtualPortId.portId("dace4513-24fc-4fae-af4b-321c5e2eb3d1");
+ VirtualPortId dstPortId1 = VirtualPortId.portId("aef3478a-4a56-2a6e-cd3a-9dee4e2ec345");
+
+ final MockFlowClassifier flowClassifier1 = new MockFlowClassifier(flowClassifierId1, tenantId1, "flowClassifier1",
+ "Mock flow classifier", "IPv4", "IP", 1001, 1500,
+ 5001, 6000, IpPrefix.valueOf("1.1.1.1/16"),
+ IpPrefix.valueOf("22.12.34.45/16"),
+ srcPortId1, dstPortId1);
+
+ /**
+ * Mock class for a flow classifier.
+ */
+ private static class MockFlowClassifier implements FlowClassifier {
+
+ private final FlowClassifierId flowClassifierId;
+ private final TenantId tenantId;
+ private final String name;
+ private final String description;
+ private final String etherType;
+ private final String protocol;
+ private final int minSrcPortRange;
+ private final int maxSrcPortRange;
+ private final int minDstPortRange;
+ private final int maxDstPortRange;
+ private final IpPrefix srcIpPrefix;
+ private final IpPrefix dstIpPrefix;
+ private final VirtualPortId srcPort;
+ private final VirtualPortId dstPort;
+
+ public MockFlowClassifier(FlowClassifierId flowClassifierId, TenantId tenantId, String name,
+ String description, String etherType, String protocol, int minSrcPortRange,
+ int maxSrcPortRange, int minDstPortRange, int maxDstPortRange, IpPrefix srcIpPrefix,
+ IpPrefix dstIpPrefix, VirtualPortId srcPort, VirtualPortId dstPort) {
+ this.flowClassifierId = flowClassifierId;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.etherType = etherType;
+ this.protocol = protocol;
+ this.minSrcPortRange = minSrcPortRange;
+ this.maxSrcPortRange = maxSrcPortRange;
+ this.minDstPortRange = minDstPortRange;
+ this.maxDstPortRange = maxDstPortRange;
+ this.srcIpPrefix = srcIpPrefix;
+ this.dstIpPrefix = dstIpPrefix;
+ this.srcPort = srcPort;
+ this.dstPort = dstPort;
+ }
+
+
+ @Override
+ public FlowClassifierId flowClassifierId() {
+ return flowClassifierId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String etherType() {
+ return etherType;
+ }
+
+ @Override
+ public String protocol() {
+ return protocol;
+ }
+
+ @Override
+ public int minSrcPortRange() {
+ return minSrcPortRange;
+ }
+
+ @Override
+ public int maxSrcPortRange() {
+ return maxSrcPortRange;
+ }
+
+ @Override
+ public int minDstPortRange() {
+ return minDstPortRange;
+ }
+
+ @Override
+ public int maxDstPortRange() {
+ return maxDstPortRange;
+ }
+
+ @Override
+ public IpPrefix srcIpPrefix() {
+ return srcIpPrefix;
+ }
+
+ @Override
+ public IpPrefix dstIpPrefix() {
+ return dstIpPrefix;
+ }
+
+ @Override
+ public VirtualPortId srcPort() {
+ return srcPort;
+ }
+
+ @Override
+ public VirtualPortId dstPort() {
+ return dstPort;
+ }
+
+ @Override
+ public boolean exactMatch(FlowClassifier flowClassifier) {
+ return this.equals(flowClassifier) &&
+ Objects.equals(this.flowClassifierId, flowClassifier.flowClassifierId()) &&
+ Objects.equals(this.tenantId, flowClassifier.tenantId());
+ }
+ }
+
+ /**
+ * Sets up the global values for all the tests.
+ */
+ @Before
+ public void setUpTest() {
+ ServiceDirectory testDirectory = new TestServiceDirectory().add(FlowClassifierService.class,
+ flowClassifierService);
+ BaseResource.setServiceDirectory(testDirectory);
+
+ }
+
+ /**
+ * Cleans up.
+ */
+ @After
+ public void tearDownTest() {
+ }
+
+ /**
+ * Tests the result of the rest api GET when there are no flow classifiers.
+ */
+ @Test
+ public void testFlowClassifiersEmpty() {
+
+ expect(flowClassifierService.getFlowClassifiers()).andReturn(null).anyTimes();
+ replay(flowClassifierService);
+ final WebResource rs = resource();
+ final String response = rs.path("flow_classifiers").get(String.class);
+ assertThat(response, is("{\"flow_classifiers\":[]}"));
+ }
+
+ /**
+ * Tests the result of a rest api GET for flow classifier id.
+ */
+ @Test
+ public void testGetFlowClassifierId() {
+
+ final Set<FlowClassifier> flowClassifiers = new HashSet<>();
+ flowClassifiers.add(flowClassifier1);
+
+ expect(flowClassifierService.exists(anyObject())).andReturn(true).anyTimes();
+ expect(flowClassifierService.getFlowClassifier(anyObject())).andReturn(flowClassifier1).anyTimes();
+ replay(flowClassifierService);
+
+ final WebResource rs = resource();
+ final String response = rs.path("flow_classifiers/4a334cd4-fe9c-4fae-af4b-321c5e2eb051").get(String.class);
+ final JsonObject result = JsonObject.readFrom(response);
+ assertThat(result, notNullValue());
+ }
+
+ /**
+ * Tests that a fetch of a non-existent flow classifier object throws an exception.
+ */
+ @Test
+ public void testBadGet() {
+ expect(flowClassifierService.getFlowClassifier(anyObject()))
+ .andReturn(null).anyTimes();
+ replay(flowClassifierService);
+ WebResource rs = resource();
+ try {
+ rs.path("flow_classifiers/78dcd363-fc23-aeb6-f44b-56dc5aafb3ae").get(String.class);
+ fail("Fetch of non-existent flow classifier did not throw an exception");
+ } catch (UniformInterfaceException ex) {
+ assertThat(ex.getMessage(),
+ containsString("returned a response status of"));
+ }
+ }
+
+ /**
+ * Tests creating a flow classifier with POST.
+ */
+ @Test
+ public void testPost() {
+
+ expect(flowClassifierService.createFlowClassifier(anyObject()))
+ .andReturn(true).anyTimes();
+ replay(flowClassifierService);
+
+ WebResource rs = resource();
+ InputStream jsonStream = FlowClassifierResourceTest.class.getResourceAsStream("post-FlowClassifier.json");
+
+ ClientResponse response = rs.path("flow_classifiers")
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .post(ClientResponse.class, jsonStream);
+ assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+ }
+
+ /**
+ * Tests deleting a flow classifier.
+ */
+ @Test
+ public void testDelete() {
+ expect(flowClassifierService.removeFlowClassifier(anyObject()))
+ .andReturn(true).anyTimes();
+ replay(flowClassifierService);
+
+ WebResource rs = resource();
+
+ String location = "flow_classifiers/4a334cd4-fe9c-4fae-af4b-321c5e2eb051";
+
+ ClientResponse deleteResponse = rs.path(location)
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .delete(ClientResponse.class);
+ assertThat(deleteResponse.getStatus(),
+ is(HttpURLConnection.HTTP_NO_CONTENT));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java
new file mode 100644
index 00000000..271904cc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.ws.rs.core.MediaType;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onlab.rest.BaseResource;
+import org.onosproject.vtnrsc.PortPair;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.portpair.PortPairService;
+
+import com.eclipsesource.json.JsonObject;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.UniformInterfaceException;
+import com.sun.jersey.api.client.WebResource;
+/**
+ * Unit tests for port pair REST APIs.
+ */
+public class PortPairResourceTest extends VtnResourceTest {
+
+ final PortPairService portPairService = createMock(PortPairService.class);
+
+ PortPairId portPairId1 = PortPairId.of("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ TenantId tenantId1 = TenantId.tenantId("d382007aa9904763a801f68ecf065cf5");
+
+ final MockPortPair portPair1 = new MockPortPair(portPairId1, tenantId1, "portPair1",
+ "Mock port pair", "dace4513-24fc-4fae-af4b-321c5e2eb3d1",
+ "aef3478a-4a56-2a6e-cd3a-9dee4e2ec345");
+
+ /**
+ * Mock class for a port pair.
+ */
+ private static class MockPortPair implements PortPair {
+
+ private final PortPairId portPairId;
+ private final TenantId tenantId;
+ private final String name;
+ private final String description;
+ private final String ingress;
+ private final String egress;
+
+ public MockPortPair(PortPairId portPairId, TenantId tenantId,
+ String name, String description,
+ String ingress, String egress) {
+
+ this.portPairId = portPairId;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.ingress = ingress;
+ this.egress = egress;
+ }
+
+ @Override
+ public PortPairId portPairId() {
+ return portPairId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public String ingress() {
+ return ingress;
+ }
+
+ @Override
+ public String egress() {
+ return egress;
+ }
+
+ @Override
+ public boolean exactMatch(PortPair portPair) {
+ return this.equals(portPair) &&
+ Objects.equals(this.portPairId, portPair.portPairId()) &&
+ Objects.equals(this.tenantId, portPair.tenantId());
+ }
+ }
+
+ /**
+ * Sets up the global values for all the tests.
+ */
+ @Before
+ public void setUpTest() {
+ ServiceDirectory testDirectory = new TestServiceDirectory().add(PortPairService.class, portPairService);
+ BaseResource.setServiceDirectory(testDirectory);
+
+ }
+
+ /**
+ * Cleans up.
+ */
+ @After
+ public void tearDownTest() {
+ }
+
+ /**
+ * Tests the result of the rest api GET when there are no port pairs.
+ */
+ @Test
+ public void testPortPairsEmpty() {
+
+ expect(portPairService.getPortPairs()).andReturn(null).anyTimes();
+ replay(portPairService);
+ final WebResource rs = resource();
+ final String response = rs.path("port_pairs").get(String.class);
+ assertThat(response, is("{\"port_pairs\":[]}"));
+ }
+
+ /**
+ * Tests the result of a rest api GET for port pair id.
+ */
+ @Test
+ public void testGetPortPairId() {
+
+ final Set<PortPair> portPairs = new HashSet<>();
+ portPairs.add(portPair1);
+
+ expect(portPairService.exists(anyObject())).andReturn(true).anyTimes();
+ expect(portPairService.getPortPair(anyObject())).andReturn(portPair1).anyTimes();
+ replay(portPairService);
+
+ final WebResource rs = resource();
+ final String response = rs.path("port_pairs/78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae").get(String.class);
+ final JsonObject result = JsonObject.readFrom(response);
+ assertThat(result, notNullValue());
+ }
+
+ /**
+ * Tests that a fetch of a non-existent port pair object throws an exception.
+ */
+ @Test
+ public void testBadGet() {
+ expect(portPairService.getPortPair(anyObject()))
+ .andReturn(null).anyTimes();
+ replay(portPairService);
+ WebResource rs = resource();
+ try {
+ rs.path("port_pairs/78dcd363-fc23-aeb6-f44b-56dc5aafb3ae").get(String.class);
+ fail("Fetch of non-existent port pair did not throw an exception");
+ } catch (UniformInterfaceException ex) {
+ assertThat(ex.getMessage(),
+ containsString("returned a response status of"));
+ }
+ }
+
+ /**
+ * Tests creating a port pair with POST.
+ */
+ @Test
+ public void testPost() {
+
+ expect(portPairService.createPortPair(anyObject()))
+ .andReturn(true).anyTimes();
+ replay(portPairService);
+
+ WebResource rs = resource();
+ InputStream jsonStream = PortPairResourceTest.class.getResourceAsStream("post-PortPair.json");
+
+ ClientResponse response = rs.path("port_pairs")
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .post(ClientResponse.class, jsonStream);
+ assertThat(response.getStatus(), is(HttpURLConnection.HTTP_OK));
+ }
+
+ /**
+ * Tests deleting a port pair.
+ */
+ @Test
+ public void testDelete() {
+ expect(portPairService.removePortPair(anyObject()))
+ .andReturn(true).anyTimes();
+ replay(portPairService);
+
+ WebResource rs = resource();
+
+ String location = "port_pairs/78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae";
+
+ ClientResponse deleteResponse = rs.path(location)
+ .type(MediaType.APPLICATION_JSON_TYPE)
+ .delete(ClientResponse.class);
+ assertThat(deleteResponse.getStatus(),
+ is(HttpURLConnection.HTTP_NO_CONTENT));
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/VtnResourceTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/VtnResourceTest.java
new file mode 100644
index 00000000..4b95844d
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/VtnResourceTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.resources;
+
+import java.io.IOException;
+import java.net.ServerSocket;
+
+import com.sun.jersey.test.framework.AppDescriptor;
+import com.sun.jersey.test.framework.JerseyTest;
+import com.sun.jersey.test.framework.WebAppDescriptor;
+
+/**
+ * Base class for VTN REST API tests. Performs common configuration operations.
+ */
+public class VtnResourceTest extends JerseyTest {
+
+ /**
+ * Assigns an available port for the test.
+ *
+ * @param defaultPort If a port cannot be determined, this one is used.
+ * @return free port
+ */
+ @Override
+ public int getPort(int defaultPort) {
+ try {
+ ServerSocket socket = new ServerSocket(0);
+ socket.setReuseAddress(true);
+ int port = socket.getLocalPort();
+ socket.close();
+ return port;
+ } catch (IOException ioe) {
+ return defaultPort;
+ }
+ }
+
+ @Override
+ public AppDescriptor configure() {
+ return new WebAppDescriptor.Builder("org.onosproject.vtnweb.resources").build();
+ }
+
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/FlowClassifierCodecTest.java b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/FlowClassifierCodecTest.java
new file mode 100644
index 00000000..be36aa83
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/web/FlowClassifierCodecTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.vtnweb.web;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Flow classifier codec unit tests.
+ */
+public class FlowClassifierCodecTest {
+
+ SfcCodecContext context;
+ JsonCodec<FlowClassifier> flowClassifierCodec;
+ /**
+ * Sets up for each test. Creates a context and fetches the flow classifier
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new SfcCodecContext();
+ flowClassifierCodec = context.codec(FlowClassifier.class);
+ assertThat(flowClassifierCodec, notNullValue());
+ }
+
+ /**
+ * Reads in a flow classifier from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the flow classifier
+ * @return decoded flow classifier
+ * @throws IOException if processing the resource fails
+ */
+ private FlowClassifier getFlowClassifier(String resourceName) throws IOException {
+ InputStream jsonStream = FlowClassifierCodecTest.class
+ .getResourceAsStream(resourceName);
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode json = mapper.readTree(jsonStream);
+ assertThat(json, notNullValue());
+ FlowClassifier flowClassifier = flowClassifierCodec.decode((ObjectNode) json, context);
+ assertThat(flowClassifier, notNullValue());
+ return flowClassifier;
+ }
+
+ /**
+ * Checks that a simple flow classifier decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecFlowClassifierTest() throws IOException {
+
+ FlowClassifier flowClassifier = getFlowClassifier("flowClassifier.json");
+
+ assertThat(flowClassifier, notNullValue());
+
+ FlowClassifierId flowClassifierId = FlowClassifierId.of("4a334cd4-fe9c-4fae-af4b-321c5e2eb051");
+ TenantId tenantId = TenantId.tenantId("1814726e2d22407b8ca76db5e567dcf1");
+
+ assertThat(flowClassifier.flowClassifierId().toString(), is(flowClassifierId.toString()));
+ assertThat(flowClassifier.name(), is("flow1"));
+ assertThat(flowClassifier.tenantId().toString(), is(tenantId.toString()));
+ assertThat(flowClassifier.description(), is("flow classifier"));
+ assertThat(flowClassifier.protocol(), is("tcp"));
+ assertThat(flowClassifier.minSrcPortRange(), is(22));
+ assertThat(flowClassifier.maxSrcPortRange(), is(4000));
+ assertThat(flowClassifier.minDstPortRange(), is(80));
+ assertThat(flowClassifier.maxDstPortRange(), is(80));
+
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-FlowClassifier.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-FlowClassifier.json
new file mode 100644
index 00000000..6e72e8fd
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-FlowClassifier.json
@@ -0,0 +1,14 @@
+{"flow_classifier": {
+ "id": "4a334cd4-fe9c-4fae-af4b-321c5e2eb051",
+ "name": "flow1",
+ "tenant_id": "1814726e2d22407b8ca76db5e567dcf1",
+ "description": "flow classifier",
+ "ethertype": "IPv4",
+ "protocol": "tcp",
+ "source_port_range_min": 22, "source_port_range_max": 4000,
+ "destination_port_range_min": 80, "destination_port_range_max": 80,
+ "source_ip_prefix": "1.1.1.1/16" , "destination_ip_prefix": "22.12.34.45/16",
+ "logical_destination_port": "dace4513-24fc-4fae-af4b-321c5e2eb3d1",
+ "logical_source_port": "aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPair.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPair.json
new file mode 100644
index 00000000..2a774e31
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/resources/post-PortPair.json
@@ -0,0 +1,9 @@
+{"port_pair": {
+ "id": "78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae",
+ "name": "PP1",
+ "tenant_id": "d382007aa9904763a801f68ecf065cf5",
+ "description": "SF-A",
+ "ingress": "dace4513-24fc-4fae-af4b-321c5e2eb3d1",
+ "egress": "aef3478a-4a56-2a6e-cd3a-9dee4e2ec345"
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/flowClassifier.json b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/flowClassifier.json
new file mode 100644
index 00000000..0fc0b74e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/test/resources/org/onosproject/vtnweb/web/flowClassifier.json
@@ -0,0 +1,11 @@
+{
+ "id": "4a334cd4-fe9c-4fae-af4b-321c5e2eb051",
+ "name": "flow1",
+ "tenant_id": "1814726e2d22407b8ca76db5e567dcf1",
+ "description": "flow classifier",
+ "ethertype": "IPv4",
+ "protocol": "tcp",
+ "source_port_range_min": 22, "source_port_range_max": 4000,
+ "destination_port_range_min": 80, "destination_port_range_max": 80,
+ "source_ip_prefix": "1.1.1.1/16" , "destination_ip_prefix": "22.12.34.45/16"
+ }
diff --git a/framework/src/onos/apps/xos-integration/features.xml b/framework/src/onos/apps/xos-integration/features.xml
index a7b14569..6b08b637 100644
--- a/framework/src/onos/apps/xos-integration/features.xml
+++ b/framework/src/onos/apps/xos-integration/features.xml
@@ -15,7 +15,6 @@
~ limitations under the License.
-->
<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
- <repository>mvn:${project.groupId}/${project.artifactId}/${project.version}/xml/features</repository>
<feature name="${project.artifactId}" version="${project.version}"
description="${project.description}">
<bundle>mvn:com.sun.jersey/jersey-client/1.19</bundle>
diff --git a/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java b/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java
new file mode 100644
index 00000000..32f2a680
--- /dev/null
+++ b/framework/src/onos/apps/xos-integration/src/main/java/org/onosproject/xosintegration/OnosXosIntegrationManager.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2014-2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.xosintegration;
+
+import com.eclipsesource.json.JsonArray;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.Maps;
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientHandlerException;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Modified;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.Service;
+import org.onlab.packet.VlanId;
+import org.onlab.util.Tools;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flowobjective.DefaultForwardingObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+
+import java.util.Dictionary;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static com.google.common.base.Strings.isNullOrEmpty;
+import static com.google.common.net.MediaType.JSON_UTF_8;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.slf4j.LoggerFactory.getLogger;
+
+
+/**
+ * XOS interface application.
+ */
+@Component(immediate = true)
+@Service
+public class OnosXosIntegrationManager implements VoltTenantService {
+ private static final String XOS_SERVER_ADDRESS_PROPERTY_NAME =
+ "xosServerAddress";
+ private static final String XOS_SERVER_PORT_PROPERTY_NAME =
+ "xosServerPort";
+ private static final String XOS_PROVIDER_SERVICE_PROPERTY_NAME =
+ "xosProviderService";
+
+ private static final String TEST_XOS_SERVER_ADDRESS = "10.254.1.22";
+ private static final int TEST_XOS_SERVER_PORT = 8000;
+ private static final String XOS_TENANT_BASE_URI = "/xoslib/volttenant/";
+ private static final int TEST_XOS_PROVIDER_SERVICE = 1;
+
+ private static final int PRIORITY = 50000;
+ private static final DeviceId FABRIC_DEVICE_ID = DeviceId.deviceId("of:5e3e486e73000187");
+ private static final PortNumber FABRIC_OLT_CONNECT_POINT = PortNumber.portNumber(2);
+ private static final PortNumber FABRIC_VCPE_CONNECT_POINT = PortNumber.portNumber(3);
+ private static final String FABRIC_CONTROLLER_ADDRESS = "10.0.3.136";
+ private static final int FABRIC_SERVER_PORT = 8181;
+ private static final String FABRIC_BASE_URI = "/onos/cordfabric/vlans/add";
+
+ private static final DeviceId OLT_DEVICE_ID = DeviceId.deviceId("of:90e2ba82f97791e9");
+ private static final int OLT_UPLINK_PORT = 129;
+
+ private static final ConnectPoint FABRIC_PORT = new ConnectPoint(
+ DeviceId.deviceId("of:000090e2ba82f974"),
+ PortNumber.portNumber(2));
+
+ private final Logger log = getLogger(getClass());
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ComponentConfigService cfgService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected FlowObjectiveService flowObjectiveService;
+
+ @Property(name = XOS_SERVER_ADDRESS_PROPERTY_NAME,
+ value = TEST_XOS_SERVER_ADDRESS,
+ label = "XOS Server address")
+ protected String xosServerAddress = TEST_XOS_SERVER_ADDRESS;
+
+ @Property(name = XOS_SERVER_PORT_PROPERTY_NAME,
+ intValue = TEST_XOS_SERVER_PORT,
+ label = "XOS Server port")
+ protected int xosServerPort = TEST_XOS_SERVER_PORT;
+
+ @Property(name = XOS_PROVIDER_SERVICE_PROPERTY_NAME,
+ intValue = TEST_XOS_PROVIDER_SERVICE,
+ label = "XOS Provider Service")
+ protected int xosProviderService = TEST_XOS_PROVIDER_SERVICE;
+
+ private ApplicationId appId;
+ private Map<String, ConnectPoint> nodeToPort;
+ private Map<Long, Short> portToVlan;
+ private Map<ConnectPoint, String> portToSsid;
+
+ @Activate
+ public void activate(ComponentContext context) {
+ log.info("XOS app is starting");
+ cfgService.registerProperties(getClass());
+ appId = coreService.registerApplication("org.onosproject.xosintegration");
+
+ setupMap();
+
+ readComponentConfiguration(context);
+
+ log.info("XOS({}) started", appId.id());
+ }
+
+ @Deactivate
+ public void deactivate() {
+ cfgService.unregisterProperties(getClass(), false);
+ log.info("XOS({}) stopped", appId.id());
+ }
+
+ @Modified
+ public void modified(ComponentContext context) {
+ readComponentConfiguration(context);
+ }
+
+ private void setupMap() {
+ nodeToPort = Maps.newHashMap();
+
+ nodeToPort.put("cordcompute01.onlab.us", new ConnectPoint(FABRIC_DEVICE_ID,
+ PortNumber.portNumber(4)));
+
+ nodeToPort.put("cordcompute02.onlab.us", new ConnectPoint(FABRIC_DEVICE_ID,
+ PortNumber.portNumber(3)));
+
+ portToVlan = Maps.newHashMap();
+ portToVlan.putIfAbsent(1L, (short) 201);
+ portToVlan.putIfAbsent(6L, (short) 401);
+
+ portToSsid = Maps.newHashMap();
+ portToSsid.put(new ConnectPoint(OLT_DEVICE_ID, PortNumber.portNumber(1)), "0");
+ portToSsid.put(new ConnectPoint(FABRIC_DEVICE_ID, PortNumber.portNumber(6)), "1");
+ }
+
+ /**
+ * Converts a JSON representation of a tenant into a tenant object.
+ *
+ * @param jsonTenant JSON object representing the tenant
+ * @return volt tenant object
+ */
+ private VoltTenant jsonToTenant(JsonObject jsonTenant) {
+ return VoltTenant.builder()
+ .withHumanReadableName(jsonTenant.get("humanReadableName").asString())
+ .withId(jsonTenant.get("id").asInt())
+ .withProviderService(jsonTenant.get("provider_service").asInt())
+ .withServiceSpecificId(jsonTenant.get("service_specific_id").asString())
+ .withVlanId(jsonTenant.get("vlan_id").asString())
+ .build();
+ }
+
+ /**
+ * Converts a tenant object into a JSON string.
+ *
+ * @param tenant volt tenant object to convert
+ * @return JSON string for the tenant
+ */
+ private String tenantToJson(VoltTenant tenant) {
+ return "{"
+ + "\"humanReadableName\": \"" + tenant.humanReadableName() + "\","
+ + "\"id\": \"" + tenant.id() + "\","
+ + "\"provider_service\": \"" + tenant.providerService() + "\","
+ + "\"service_specific_id\": \"" + tenant.serviceSpecificId() + "\","
+ + "\"vlan_id\": \"" + tenant.vlanId() + "\""
+ + "}";
+ }
+
+ /**
+ * Gets a client web resource builder for the base XOS REST API
+ * with no additional URI.
+ *
+ * @return web resource builder
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private WebResource.Builder getClientBuilder() {
+ return getClientBuilder("");
+ }
+
+ /**
+ * Gets a client web resource builder for the base XOS REST API
+ * with an optional additional URI.
+ *
+ * @return web resource builder
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private WebResource.Builder getClientBuilder(String uri) {
+ String baseUrl = "http://" + xosServerAddress + ":"
+ + Integer.toString(xosServerPort);
+ Client client = Client.create();
+ client.addFilter(new HTTPBasicAuthFilter("padmin@vicci.org", "letmein"));
+ WebResource resource = client.resource(baseUrl
+ + XOS_TENANT_BASE_URI + uri);
+ return resource.accept(JSON_UTF_8.toString())
+ .type(JSON_UTF_8.toString());
+ }
+
+ /**
+ * Performs a REST GET operation on the base XOS REST URI.
+ *
+ * @return JSON string fetched by the GET operation
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private String getRest() {
+ return getRest("");
+ }
+
+ /**
+ * Performs a REST GET operation on the base XOS REST URI with
+ * an optional additional URI.
+ *
+ * @return JSON string fetched by the GET operation
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private String getRest(String uri) {
+ WebResource.Builder builder = getClientBuilder(uri);
+ ClientResponse response = builder.get(ClientResponse.class);
+
+ if (response.getStatus() != HTTP_OK) {
+ log.info("REST GET request returned error code {}",
+ response.getStatus());
+ }
+ String jsonString = response.getEntity(String.class);
+ log.info("JSON read:\n{}", jsonString);
+
+ return jsonString;
+ }
+
+ /**
+ * Performs a REST POST operation of a json string on the base
+ * XOS REST URI with an optional additional URI.
+ *
+ * @param json JSON string to post
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private String postRest(String json) {
+ WebResource.Builder builder = getClientBuilder();
+ ClientResponse response;
+
+ try {
+ response = builder.post(ClientResponse.class, json);
+ } catch (ClientHandlerException e) {
+ log.warn("Unable to contact REST server: {}", e.getMessage());
+ return "{ 'error' : 'oops no one home' }";
+ }
+
+ if (response.getStatus() != HTTP_CREATED) {
+ log.info("REST POST request returned error code {}",
+ response.getStatus());
+ }
+ return response.getEntity(String.class);
+ }
+
+ /**
+ * Performs a REST DELETE operation on the base
+ * XOS REST URI with an optional additional URI.
+ *
+ * @param uri optional additional URI
+ * @deprecated in Cardinal Release
+ */
+ @Deprecated
+ private void deleteRest(String uri) {
+ WebResource.Builder builder = getClientBuilder(uri);
+ ClientResponse response = builder.delete(ClientResponse.class);
+
+ if (response.getStatus() != HTTP_NO_CONTENT) {
+ log.info("REST DELETE request returned error code {}",
+ response.getStatus());
+ }
+ }
+
+ /**
+ * Deletes the tenant with the given ID.
+ *
+ * @param tenantId ID of tenant to delete
+ */
+ private void deleteTenant(long tenantId) {
+ deleteRest(Long.toString(tenantId));
+ }
+
+ @Override
+ public Set<VoltTenant> getAllTenants() {
+ String jsonString = getRest();
+
+ JsonArray voltTenantItems = JsonArray.readFrom(jsonString);
+
+ return IntStream.range(0, voltTenantItems.size())
+ .mapToObj(index -> jsonToTenant(voltTenantItems.get(index).asObject()))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public void removeTenant(long id) {
+ deleteTenant(id);
+ }
+
+ @Override
+ public VoltTenant addTenant(VoltTenant newTenant) {
+ long providerServiceId = newTenant.providerService();
+ if (providerServiceId == -1) {
+ providerServiceId = xosProviderService;
+ }
+
+ PortNumber onuPort = newTenant.port().port();
+ VlanId subscriberVlan = VlanId.vlanId(portToVlan.get(onuPort.toLong()));
+
+ VoltTenant tenantToCreate = VoltTenant.builder()
+ .withProviderService(providerServiceId)
+ .withServiceSpecificId(portToSsid.get(newTenant.port()))
+ .withVlanId(String.valueOf(subscriberVlan.toShort()))
+ .withPort(newTenant.port())
+ .build();
+ String json = tenantToJson(tenantToCreate);
+
+
+ provisionVlanOnPort(OLT_DEVICE_ID, OLT_UPLINK_PORT, onuPort, subscriberVlan.toShort());
+
+ String retJson = postRest(json);
+
+ fetchCpeLocation(tenantToCreate, retJson);
+
+ return newTenant;
+ }
+
+ private void fetchCpeLocation(VoltTenant newTenant, String jsonString) {
+ JsonObject json = JsonObject.readFrom(jsonString);
+
+ if (json.get("computeNodeName") != null) {
+ ConnectPoint point = nodeToPort.get(json.get("computeNodeName").asString());
+ //ConnectPoint fromPoint = newTenant.port();
+ ConnectPoint oltPort = new ConnectPoint(FABRIC_DEVICE_ID, FABRIC_OLT_CONNECT_POINT);
+
+ provisionFabric(VlanId.vlanId(Short.parseShort(newTenant.vlanId())),
+ point, oltPort);
+ }
+
+ }
+
+ @Override
+ public VoltTenant getTenant(long id) {
+ String jsonString = getRest(Long.toString(id));
+ JsonObject jsonTenant = JsonObject.readFrom(jsonString);
+ if (jsonTenant.get("id") != null) {
+ return jsonToTenant(jsonTenant);
+ } else {
+ return null;
+ }
+ }
+
+ private void provisionVlanOnPort(DeviceId deviceId, int uplinkPort, PortNumber p, short vlanId) {
+
+ TrafficSelector upstream = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.ANY)
+ .matchInPort(p)
+ .build();
+
+ TrafficSelector downstream = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId(vlanId))
+ .matchInPort(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment upstreamTreatment = DefaultTrafficTreatment.builder()
+ .setVlanId(VlanId.vlanId(vlanId))
+ .setOutput(PortNumber.portNumber(uplinkPort))
+ .build();
+
+ TrafficTreatment downstreamTreatment = DefaultTrafficTreatment.builder()
+ .popVlan()
+ .setOutput(p)
+ .build();
+
+
+ ForwardingObjective upFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(upstream)
+ .fromApp(appId)
+ .withTreatment(upstreamTreatment)
+ .add();
+
+ ForwardingObjective downFwd = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(1000)
+ .makePermanent()
+ .withSelector(downstream)
+ .fromApp(appId)
+ .withTreatment(downstreamTreatment)
+ .add();
+
+ flowObjectiveService.forward(deviceId, upFwd);
+ flowObjectiveService.forward(deviceId, downFwd);
+
+ }
+
+ private void provisionDataPlane(VoltTenant tenant) {
+ VlanId vlan = VlanId.vlanId(Short.parseShort(tenant.vlanId()));
+
+ TrafficSelector fromGateway = DefaultTrafficSelector.builder()
+ .matchInPhyPort(tenant.port().port())
+ .build();
+
+ TrafficSelector fromFabric = DefaultTrafficSelector.builder()
+ .matchInPhyPort(FABRIC_PORT.port())
+ .matchVlanId(vlan)
+ .build();
+
+ TrafficTreatment toFabric = DefaultTrafficTreatment.builder()
+ .pushVlan()
+ .setVlanId(vlan)
+ .setOutput(FABRIC_PORT.port())
+ .build();
+
+ TrafficTreatment toGateway = DefaultTrafficTreatment.builder()
+ .popVlan()
+ .setOutput(tenant.port().port())
+ .build();
+
+ ForwardingObjective forwardToFabric = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(PRIORITY)
+ .makePermanent()
+ .fromApp(appId)
+ .withSelector(fromGateway)
+ .withTreatment(toFabric)
+ .add();
+
+ ForwardingObjective forwardToGateway = DefaultForwardingObjective.builder()
+ .withFlag(ForwardingObjective.Flag.VERSATILE)
+ .withPriority(PRIORITY)
+ .makePermanent()
+ .fromApp(appId)
+ .withSelector(fromFabric)
+ .withTreatment(toGateway)
+ .add();
+
+ flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToFabric);
+ flowObjectiveService.forward(FABRIC_PORT.deviceId(), forwardToGateway);
+ }
+
+ private void provisionFabric(VlanId vlanId, ConnectPoint point, ConnectPoint fromPoint) {
+
+ long vlan = vlanId.toShort();
+
+ JsonObject node = new JsonObject();
+ node.add("vlan", vlan);
+ if (vlan == 201) {
+ node.add("iptv", true);
+ } else {
+ node.add("iptv", false);
+ }
+ JsonArray array = new JsonArray();
+ JsonObject cp1 = new JsonObject();
+ JsonObject cp2 = new JsonObject();
+ cp1.add("device", point.deviceId().toString());
+ cp1.add("port", point.port().toLong());
+ cp2.add("device", fromPoint.deviceId().toString());
+ cp2.add("port", fromPoint.port().toLong());
+ array.add(cp1);
+ array.add(cp2);
+ node.add("ports", array);
+
+
+ String baseUrl = "http://" + FABRIC_CONTROLLER_ADDRESS + ":"
+ + Integer.toString(FABRIC_SERVER_PORT);
+ Client client = Client.create();
+ WebResource resource = client.resource(baseUrl + FABRIC_BASE_URI);
+ WebResource.Builder builder = resource.accept(JSON_UTF_8.toString())
+ .type(JSON_UTF_8.toString());
+
+ try {
+ builder.post(ClientResponse.class, node.toString());
+ } catch (ClientHandlerException e) {
+ log.warn("Unable to contact fabric REST server: {}", e.getMessage());
+ return;
+ }
+ }
+
+ /**
+ * Extracts properties from the component configuration context.
+ *
+ * @param context the component context
+ */
+ private void readComponentConfiguration(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+
+ String newXosServerAddress =
+ Tools.get(properties, XOS_SERVER_ADDRESS_PROPERTY_NAME);
+ if (!isNullOrEmpty(newXosServerAddress)) {
+ xosServerAddress = newXosServerAddress;
+ }
+
+ String newXosServerPortString =
+ Tools.get(properties, XOS_SERVER_PORT_PROPERTY_NAME);
+ if (!isNullOrEmpty(newXosServerPortString)) {
+ xosServerPort = Integer.parseInt(newXosServerPortString);
+ }
+
+ String newXosProviderServiceString =
+ Tools.get(properties, XOS_PROVIDER_SERVICE_PROPERTY_NAME);
+ if (!isNullOrEmpty(newXosProviderServiceString)) {
+ xosProviderService = Integer.parseInt(newXosProviderServiceString);
+ }
+ }
+}
+
+