aboutsummaryrefslogtreecommitdiffstats
path: root/framework
diff options
context:
space:
mode:
Diffstat (limited to 'framework')
-rw-r--r--framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java1
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtn.java68
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java19
-rw-r--r--framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java2
-rw-r--r--framework/src/onos/apps/dhcp/api/pom.xml64
-rw-r--r--framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpService.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpService.java)0
-rw-r--r--framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpStore.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java)0
-rw-r--r--framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/IpAssignment.java)0
-rw-r--r--framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/package-info.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/package-info.java)0
-rw-r--r--framework/src/onos/apps/dhcp/api/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java (renamed from framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/app.xml23
-rw-r--r--framework/src/onos/apps/dhcp/app/features.xml25
-rw-r--r--framework/src/onos/apps/dhcp/app/pom.xml166
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/package-info.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/package-info.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/package-info.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/package-info.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/DHCPWebResource.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/rest/DHCPWebResource.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/package-info.java (renamed from framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/rest/package-info.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml (renamed from framework/src/onos/apps/dhcp/src/main/resources/OSGI-INF/blueprint/shell-config.xml)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.css (renamed from framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.css)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.html (renamed from framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.html)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.js (renamed from framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.js)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/gui/css.html (renamed from framework/src/onos/apps/dhcp/src/main/resources/gui/css.html)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/resources/gui/js.html (renamed from framework/src/onos/apps/dhcp/src/main/resources/gui/js.html)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/main/webapp/WEB-INF/web.xml (renamed from framework/src/onos/apps/dhcp/src/main/webapp/WEB-INF/web.xml)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java (renamed from framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java)0
-rw-r--r--framework/src/onos/apps/dhcp/app/src/test/resources/dhcp-cfg.json (renamed from framework/src/onos/apps/dhcp/src/test/resources/dhcp-cfg.json)0
-rw-r--r--framework/src/onos/apps/dhcp/pom.xml143
-rw-r--r--framework/src/onos/apps/igmp/src/main/java/org/onosproject/igmp/impl/package-info.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/package-info.java)4
-rw-r--r--framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/rest/package-info.java20
-rw-r--r--framework/src/onos/apps/mlb/src/main/java/org/onosproject/mlb/package-info.java20
-rw-r--r--framework/src/onos/apps/openstackswitching/pom.xml121
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java51
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java45
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java112
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java350
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java437
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java228
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java49
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java20
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java64
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java62
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java104
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java106
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java20
-rw-r--r--framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml44
-rw-r--r--framework/src/onos/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java18
-rw-r--r--framework/src/onos/apps/pom.xml6
-rw-r--r--framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java58
-rw-r--r--framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java5
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java5
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java24
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java164
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java4
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/RoutingRulePopulator.java104
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java190
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java66
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultEdgeGroupHandler.java9
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java81
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultTransitGroupHandler.java9
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java18
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java10
-rw-r--r--framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java78
-rw-r--r--framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestAddCommand.java12
-rw-r--r--framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestGetCommand.java12
-rw-r--r--framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestRemoveCommand.java23
-rw-r--r--framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/ConnectPointConfiguration.java55
-rw-r--r--framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfiguration.java27
-rw-r--r--framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java28
-rw-r--r--framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java12
-rw-r--r--framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java49
-rw-r--r--framework/src/onos/apps/vtn/pom.xml17
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/SfcService.java52
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/SfcManager.java69
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java413
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java201
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPair.java198
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java183
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifier.java259
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java91
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java148
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPair.java139
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java126
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java95
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/FlowClassifierService.java72
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.java108
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java80
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java80
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/package-info.java20
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/TunnelConfigService.java72
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java40
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java134
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java68
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultAllocationPoolTest.java68
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultHostRouteTest.java68
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/SubnetIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/DefaultNeutronNetworkTest.java83
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/PhysicalNetworkTest.java65
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/SegmentationIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantNetworkIdTest.java64
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/AllowedAddressPairTest.java76
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/DefaultVirtualPortTest.java142
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/FixedIpTest.java72
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/SecurityGroupTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/VirtualPortIdTest.java66
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java192
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/SubnetWebResource.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/TenantNetworkWebResource.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VirtualPortWebResource.java2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllocationPoolsCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllocationPoolsCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllowedAddressPairCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllowedAddressPairCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FixedIpCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FixedIpCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/HostRoutesCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/HostRoutesCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java105
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SecurityGroupCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SecurityGroupCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SubnetCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SubnetCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/TenantNetworkCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/TenantNetworkCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VirtualPortCodec.java (renamed from framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/VirtualPortCodec.java)2
-rw-r--r--framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/package-info.java20
-rwxr-xr-xframework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java54
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactories.java82
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactory.java60
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPNotificationMsg.java34
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPFactoryVer4.java58
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPMessageVer4.java109
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java17
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java190
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java170
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java209
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java120
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java119
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java138
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java166
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java78
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java40
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java29
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java172
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java152
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java240
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java131
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java187
-rw-r--r--framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java36
-rw-r--r--framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrNodeFlagBitTlvTest.java51
-rw-r--r--framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrRouterIdV6Test.java50
-rw-r--r--framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrIgpMetricTest.java44
-rw-r--r--framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrProtectionTypeTest.java57
-rw-r--r--framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOspfFwdAddrTest.java52
-rwxr-xr-xframework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/NextHopTest.java41
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java5
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java8
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java10
-rw-r--r--framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java4
-rw-r--r--framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml1
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java3
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java47
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java185
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java56
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java77
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java24
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java7
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java91
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java11
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java9
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java19
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java25
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java71
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java78
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java (renamed from framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java)26
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java92
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java7
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java68
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java16
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java66
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java14
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java17
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java15
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java13
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java104
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java54
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java19
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java36
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java40
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java49
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java48
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java20
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java4
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java8
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java1
-rw-r--r--framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java2
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java54
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java93
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java51
-rw-r--r--framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java59
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java42
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java35
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java14
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java37
-rw-r--r--framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java3
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java33
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java56
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java48
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java25
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java58
-rw-r--r--framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json5
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java48
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java116
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java2
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java24
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java110
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java3
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java108
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java13
-rw-r--r--framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java98
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java100
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java15
-rw-r--r--framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java395
-rw-r--r--framework/src/onos/core/store/dist/pom.xml2
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java58
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java194
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java63
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java11
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java221
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java6
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java7
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java108
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java74
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java52
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java9
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java20
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java2
-rw-r--r--framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java14
-rw-r--r--framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java6
-rw-r--r--framework/src/onos/core/store/persistence/pom.xml66
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java63
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java59
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java30
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java138
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java192
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java194
-rw-r--r--framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java20
-rw-r--r--framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java245
-rw-r--r--framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java274
-rw-r--r--framework/src/onos/core/store/pom.xml3
-rw-r--r--framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java73
-rw-r--r--framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java13
-rw-r--r--framework/src/onos/docs/internal-bgpls2
-rw-r--r--framework/src/onos/docs/internal-stores1
-rw-r--r--framework/src/onos/docs/internal.xml4
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java84
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java106
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java19
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java31
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java37
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java (renamed from framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java)10
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java (renamed from framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA1Pipeline.java)1120
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java75
-rw-r--r--framework/src/onos/drivers/src/main/resources/onos-drivers.xml11
-rw-r--r--framework/src/onos/features/features.xml1
-rw-r--r--framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/package-info.java20
-rw-r--r--framework/src/onos/netconf/api/src/main/java/org/onosproject/netconf/package-info.java20
-rw-r--r--framework/src/onos/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java20
-rw-r--r--framework/src/onos/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java20
-rw-r--r--framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionInterpreter.java58
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/EventSubject.java3
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridge.java11
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridgeName.java7
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java16
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbController.java4
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbDatapathId.java9
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbEventSubject.java2
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbIfaceId.java9
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbNodeId.java2
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPort.java10
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortName.java9
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortNumber.java9
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTableStore.java14
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java21
-rw-r--r--framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java9
-rw-r--r--framework/src/onos/pom.xml3
-rw-r--r--framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java196
-rw-r--r--framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java12
-rw-r--r--framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java144
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java65
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java22
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java6
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java36
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java26
-rw-r--r--framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java22
-rw-r--r--framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupBucketEntryBuilder.java4
-rw-r--r--framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java2
-rw-r--r--framework/src/onos/providers/ovsdb/host/src/main/java/org/onosproject/ovsdb/provider/host/OvsdbHostProvider.java4
-rw-r--r--framework/src/onos/tools/build/conf/pom.xml2
-rw-r--r--framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml4
-rw-r--r--framework/src/onos/tools/build/conf/src/main/resources/onos/suppressions.xml8
-rwxr-xr-xframework/src/onos/tools/dev/bin/onos-build-selective8
-rw-r--r--framework/src/onos/tools/dev/bin/onos-build-selective.exclude3
-rwxr-xr-xframework/src/onos/tools/dev/bin/onos-setup-karaf12
-rw-r--r--framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovMessageHandler.java20
-rw-r--r--framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovOverlay.java11
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-config19
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-execute-expect27
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-gen-partitions17
-rwxr-xr-xframework/src/onos/tools/test/bin/onos-secure-ssh3
-rwxr-xr-xframework/src/onos/tools/test/bin/stc4
-rw-r--r--framework/src/onos/tools/test/scenarios/dist-test-seq.xml67
-rw-r--r--framework/src/onos/tools/test/scenarios/dist-test.xml70
-rw-r--r--framework/src/onos/tools/test/topos/opticalUtils.py10
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/packet/Ethernet.java131
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/util/Bandwidth.java11
-rw-r--r--framework/src/onos/utils/misc/src/main/java/org/onlab/util/DataRateUnit.java64
-rw-r--r--framework/src/onos/utils/misc/src/test/java/org/onlab/util/AbstractAccumulatorTest.java27
-rw-r--r--framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimer.java26
-rw-r--r--framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimerTest.java4
-rw-r--r--framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Main.java24
-rw-r--r--framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java3
-rw-r--r--framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java58
-rw-r--r--framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java3
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css4
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js6
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js2
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css2
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js4
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css1
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html31
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js39
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css51
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js20
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js60
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js183
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js2
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js8
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js7
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js30
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js1
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js9
-rw-r--r--framework/src/onos/web/gui/src/main/webapp/index.html1
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json63
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json (renamed from framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json)0
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json30
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json18
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_8_addLink_1_2.json (renamed from framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json)0
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json (renamed from framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json)0
-rw-r--r--framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json2
372 files changed, 17306 insertions, 2349 deletions
diff --git a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
index 72a5b122..567944a6 100644
--- a/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
+++ b/framework/src/onos/apps/aaa/src/main/java/org/onosproject/aaa/AAA.java
@@ -419,6 +419,7 @@ public class AAA {
* 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());
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 4b28a14b..e15bc763 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
@@ -23,17 +23,27 @@ 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.ItemNotFoundException;
import org.onlab.util.KryoNamespace;
import org.onosproject.cluster.ClusterService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
+import org.onosproject.net.behaviour.BridgeConfig;
+import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.behaviour.DefaultTunnelDescription;
+import org.onosproject.net.behaviour.TunnelConfig;
+import org.onosproject.net.behaviour.TunnelDescription;
+import org.onosproject.net.behaviour.TunnelName;
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.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostService;
@@ -58,6 +68,7 @@ import java.util.concurrent.Executors;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.Device.Type.SWITCH;
+import static org.onosproject.net.behaviour.TunnelDescription.Type.VXLAN;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -79,7 +90,6 @@ public class CordVtn implements CordVtnService {
private static final Map<String, String> DEFAULT_TUNNEL_OPTIONS = new HashMap<String, String>() {
{
put("key", "flow");
- put("local_ip", "flow");
put("remote_ip", "flow");
}
};
@@ -99,6 +109,9 @@ public class CordVtn implements CordVtnService {
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected OvsdbController controller;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -213,8 +226,8 @@ public class CordVtn implements CordVtnService {
if (deviceService.getDevice(ovsdb.intBrId()) == null ||
!deviceService.isAvailable(ovsdb.intBrId())) {
createIntegrationBridge(ovsdb);
- } else if (!checkVxlanPort(ovsdb)) {
- createVxlanPort(ovsdb);
+ } else if (!checkVxlanInterface(ovsdb)) {
+ createVxlanInterface(ovsdb);
}
}
@@ -272,26 +285,41 @@ public class CordVtn implements CordVtnService {
});
String dpid = ovsdb.intBrId().toString().substring(DPID_BEGIN);
- // TODO change to use bridge config
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
- ovsdbClient.createBridge(DEFAULT_BRIDGE_NAME, dpid, controllers);
+ try {
+ DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
+ BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+ bridgeConfig.addBridge(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), dpid, controllers);
+ } catch (ItemNotFoundException e) {
+ log.warn("Failed to create integration bridge on {}", ovsdb.deviceId());
+ }
}
- private void createVxlanPort(OvsdbNode ovsdb) {
- // TODO change to use tunnel config and tunnel description
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
- ovsdbClient.createTunnel(DEFAULT_BRIDGE_NAME, DEFAULT_TUNNEL,
- DEFAULT_TUNNEL, DEFAULT_TUNNEL_OPTIONS);
+ private void createVxlanInterface(OvsdbNode ovsdb) {
+ DefaultAnnotations.Builder optionBuilder = DefaultAnnotations.builder();
+ for (String key : DEFAULT_TUNNEL_OPTIONS.keySet()) {
+ optionBuilder.set(key, DEFAULT_TUNNEL_OPTIONS.get(key));
+ }
+ TunnelDescription description =
+ new DefaultTunnelDescription(null, null, VXLAN,
+ TunnelName.tunnelName(DEFAULT_TUNNEL),
+ optionBuilder.build());
+ try {
+ DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
+ TunnelConfig tunnelConfig = handler.behaviour(TunnelConfig.class);
+ tunnelConfig.createTunnelInterface(BridgeName.bridgeName(DEFAULT_BRIDGE_NAME), description);
+ } catch (ItemNotFoundException e) {
+ log.warn("Failed to create VXLAN interface on {}", ovsdb.deviceId());
+ }
}
- private boolean checkVxlanPort(OvsdbNode ovsdb) {
- // TODO change to use tunnel config
- OvsdbClientService ovsdbClient = getOvsdbClient(ovsdb);
+ private boolean checkVxlanInterface(OvsdbNode ovsdb) {
try {
- ovsdbClient.getPorts().stream()
- .filter(p -> p.portName().value().equals(DEFAULT_TUNNEL))
- .findFirst().get();
- } catch (NoSuchElementException e) {
+ DriverHandler handler = driverService.createHandler(ovsdb.deviceId());
+ BridgeConfig bridgeConfig = handler.behaviour(BridgeConfig.class);
+ bridgeConfig.getPorts().stream()
+ .filter(p -> p.annotations().value("portName").equals(DEFAULT_TUNNEL))
+ .findAny().get();
+ } catch (ItemNotFoundException | NoSuchElementException e) {
return false;
}
return true;
@@ -374,8 +402,8 @@ public class CordVtn implements CordVtnService {
return;
}
- if (!checkVxlanPort(ovsdb)) {
- createVxlanPort(ovsdb);
+ if (!checkVxlanInterface(ovsdb)) {
+ createVxlanInterface(ovsdb);
}
}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
index 287f2a34..274ca9b4 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/CordVtnConfigManager.java
@@ -72,8 +72,6 @@ public class CordVtnConfigManager {
configService.addListener(configListener);
configRegistry.registerConfigFactory(configFactory);
-
- readConfiguration();
}
@Deactivate
@@ -101,7 +99,22 @@ public class CordVtnConfigManager {
@Override
public void event(NetworkConfigEvent event) {
- // TODO handle update event
+ if (!event.configClass().equals(CordVtnConfig.class)) {
+ return;
+ }
+
+ switch (event.type()) {
+ case CONFIG_ADDED:
+ log.info("Network configuration added");
+ readConfiguration();
+ break;
+ case CONFIG_UPDATED:
+ log.info("Network configuration updated");
+ readConfiguration();
+ break;
+ default:
+ break;
+ }
}
}
}
diff --git a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
index eba52108..46f6e29c 100644
--- a/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
+++ b/framework/src/onos/apps/cordvtn/src/main/java/org/onosproject/cordvtn/DefaultOvsdbNode.java
@@ -61,7 +61,7 @@ public class DefaultOvsdbNode implements OvsdbNode {
@Override
public DeviceId deviceId() {
- return DeviceId.deviceId("ovsdb:" + this.ip.toString() + ":" + this.port.toString());
+ return DeviceId.deviceId("ovsdb:" + this.ip.toString());
}
@Override
diff --git a/framework/src/onos/apps/dhcp/api/pom.xml b/framework/src/onos/apps/dhcp/api/pom.xml
new file mode 100644
index 00000000..fb5246f7
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/api/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-dhcp</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-dhcp-api</artifactId>
+ <packaging>bundle</packaging>
+
+ <url>http://onosproject.org</url>
+
+ <description>DHCP Server application API</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+
+</project>
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpService.java b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpService.java
index 7c2127f9..7c2127f9 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpService.java
+++ b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpService.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpStore.java
index e263b3a2..e263b3a2 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/DhcpStore.java
+++ b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/DhcpStore.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/IpAssignment.java b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java
index 9b3aa686..9b3aa686 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/IpAssignment.java
+++ b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/package-info.java b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/package-info.java
index 56778a35..56778a35 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/package-info.java
+++ b/framework/src/onos/apps/dhcp/api/src/main/java/org/onosproject/dhcp/package-info.java
diff --git a/framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java b/framework/src/onos/apps/dhcp/api/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java
index 3ecc5cfa..3ecc5cfa 100644
--- a/framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java
+++ b/framework/src/onos/apps/dhcp/api/src/test/java/org/onosproject/dhcp/IpAssignmentTest.java
diff --git a/framework/src/onos/apps/dhcp/app/app.xml b/framework/src/onos/apps/dhcp/app/app.xml
new file mode 100644
index 00000000..bf324b19
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/app.xml
@@ -0,0 +1,23 @@
+<?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.dhcp" 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}/${project.artifactId}/${project.version}</artifact>
+ <artifact>mvn:${project.groupId}/onos-app-dhcp-api/${project.version}</artifact>
+</app>
diff --git a/framework/src/onos/apps/dhcp/app/features.xml b/framework/src/onos/apps/dhcp/app/features.xml
new file mode 100644
index 00000000..0b277dea
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/features.xml
@@ -0,0 +1,25 @@
+<?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-dhcp-api/${project.version}</bundle>
+ <bundle>mvn:${project.groupId}/onos-app-dhcp/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/framework/src/onos/apps/dhcp/app/pom.xml b/framework/src/onos/apps/dhcp/app/pom.xml
new file mode 100644
index 00000000..6589402a
--- /dev/null
+++ b/framework/src/onos/apps/dhcp/app/pom.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ --><project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>onos-dhcp</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-app-dhcp</artifactId>
+ <packaging>bundle</packaging>
+
+ <url>http://onosproject.org</url>
+
+ <description>DHCP Server application</description>
+
+ <properties>
+ <onos.app.name>org.onosproject.dhcp</onos.app.name>
+ <web.context>/onos/dhcp</web.context>
+ <api.version>1.0.0</api.version>
+ <api.title>DHCP Server REST API</api.title>
+ <api.description>
+ APIs for interacting with the DHCP Server application.
+ </api.description>
+ <api.package>org.onosproject.dhcp.rest</api.package>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-app-dhcp-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-cli</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.console</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-serializers</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </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>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <_wab>src/main/webapp/</_wab>
+ <Include-Resource>
+ WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
+ {maven-resources}
+ </Include-Resource>
+ <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,
+ org.apache.karaf.shell.console,
+ com.google.common.*,
+ org.onlab.packet.*,
+ org.onlab.rest.*,
+ org.onosproject.*,
+ org.onlab.util.*,
+ org.jboss.netty.util.*
+ </Import-Package>
+ <Web-ContextPath>${web.context}</Web-ContextPath>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java
index 95f49e69..95f49e69 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpLeaseDetails.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java
index 209ba683..209ba683 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpListAllMappings.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java
index a92cd250..a92cd250 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpRemoveStaticMapping.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java
index 9f4f6580..9f4f6580 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/DhcpSetStaticMapping.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java
index 228d70fd..228d70fd 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/FreeIpCompleter.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java
index d6cd73a7..d6cd73a7 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/MacIdCompleter.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/package-info.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/package-info.java
index f8780195..f8780195 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/cli/package-info.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/cli/package-info.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java
index 4353d623..4353d623 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpConfig.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
index 96d94a2b..96d94a2b 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpManager.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java
index bb2bd2c2..bb2bd2c2 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpUi.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java
index 9ce65d5e..9ce65d5e 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DhcpViewMessageHandler.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
index 63f69d40..63f69d40 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/DistributedDhcpStore.java
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/package-info.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/package-info.java
index 12e14e48..12e14e48 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/impl/package-info.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/impl/package-info.java
diff --git a/framework/src/onos/apps/dhcp/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
index 646ab7ea..646ab7ea 100644
--- a/framework/src/onos/apps/dhcp/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
diff --git a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/rest/package-info.java b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/package-info.java
index 73173c55..73173c55 100644
--- a/framework/src/onos/apps/dhcp/src/main/java/org/onosproject/dhcp/rest/package-info.java
+++ b/framework/src/onos/apps/dhcp/app/src/main/java/org/onosproject/dhcp/rest/package-info.java
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/apps/dhcp/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index ce716315..ce716315 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/OSGI-INF/blueprint/shell-config.xml
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.css b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.css
index e0a29314..e0a29314 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.css
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.css
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.html b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.html
index 5782badf..5782badf 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.html
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.html
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.js b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.js
index 061d0de6..061d0de6 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/app/view/dhcp/dhcp.js
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/app/view/dhcp/dhcp.js
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/gui/css.html b/framework/src/onos/apps/dhcp/app/src/main/resources/gui/css.html
index d02ad44a..d02ad44a 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/gui/css.html
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/gui/css.html
diff --git a/framework/src/onos/apps/dhcp/src/main/resources/gui/js.html b/framework/src/onos/apps/dhcp/app/src/main/resources/gui/js.html
index d37b5768..d37b5768 100644
--- a/framework/src/onos/apps/dhcp/src/main/resources/gui/js.html
+++ b/framework/src/onos/apps/dhcp/app/src/main/resources/gui/js.html
diff --git a/framework/src/onos/apps/dhcp/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/dhcp/app/src/main/webapp/WEB-INF/web.xml
index 27504548..27504548 100644
--- a/framework/src/onos/apps/dhcp/src/main/webapp/WEB-INF/web.xml
+++ b/framework/src/onos/apps/dhcp/app/src/main/webapp/WEB-INF/web.xml
diff --git a/framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java b/framework/src/onos/apps/dhcp/app/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
index fd4701c6..fd4701c6 100644
--- a/framework/src/onos/apps/dhcp/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
+++ b/framework/src/onos/apps/dhcp/app/src/test/java/org/onosproject/dhcp/impl/DhcpManagerTest.java
diff --git a/framework/src/onos/apps/dhcp/src/test/resources/dhcp-cfg.json b/framework/src/onos/apps/dhcp/app/src/test/resources/dhcp-cfg.json
index abc48a83..abc48a83 100644
--- a/framework/src/onos/apps/dhcp/src/test/resources/dhcp-cfg.json
+++ b/framework/src/onos/apps/dhcp/app/src/test/resources/dhcp-cfg.json
diff --git a/framework/src/onos/apps/dhcp/pom.xml b/framework/src/onos/apps/dhcp/pom.xml
index 0daa4f7b..7a10776e 100644
--- a/framework/src/onos/apps/dhcp/pom.xml
+++ b/framework/src/onos/apps/dhcp/pom.xml
@@ -13,149 +13,30 @@
~ 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/xsd/maven-4.0.0.xsd">
+ -->
+<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>
- <artifactId>onos-apps</artifactId>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-apps</artifactId>
<version>1.4.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
- <artifactId>onos-app-dhcp</artifactId>
- <packaging>bundle</packaging>
-
- <url>http://onosproject.org</url>
+ <artifactId>onos-dhcp</artifactId>
+ <packaging>pom</packaging>
- <description>DHCP Server application</description>
+ <description>ONOS sample applications</description>
- <properties>
- <onos.app.name>org.onosproject.dhcp</onos.app.name>
- <web.context>/onos/dhcp</web.context>
- <api.version>1.0.0</api.version>
- <api.title>DHCP Server REST API</api.title>
- <api.description>
- APIs for interacting with the DHCP Server application.
- </api.description>
- <api.package>org.onosproject.dhcp.rest</api.package>
- </properties>
+ <modules>
+ <module>api</module>
+ <module>app</module>
+ </modules>
<dependencies>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-cli</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.apache.karaf.shell</groupId>
- <artifactId>org.apache.karaf.shell.console</artifactId>
- <scope>compile</scope>
- </dependency>
-
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onlab-junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-core-serializers</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-incubator-api</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.onosproject</groupId>
- <artifactId>onos-api</artifactId>
- <version>${project.version}</version>
- <classifier>tests</classifier>
- <scope>test</scope>
- </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>
</dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <extensions>true</extensions>
- <configuration>
- <instructions>
- <_wab>src/main/webapp/</_wab>
- <Include-Resource>
- WEB-INF/classes/apidoc/swagger.json=target/swagger.json,
- {maven-resources}
- </Include-Resource>
- <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,
- org.apache.karaf.shell.console,
- com.google.common.*,
- org.onlab.packet.*,
- org.onlab.rest.*,
- org.onosproject.*,
- org.onlab.util.*,
- org.jboss.netty.util.*
- </Import-Package>
- <Web-ContextPath>${web.context}</Web-ContextPath>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-
</project>
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/package-info.java b/framework/src/onos/apps/igmp/src/main/java/org/onosproject/igmp/impl/package-info.java
index 3a84e6e3..7d420198 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/package-info.java
+++ b/framework/src/onos/apps/igmp/src/main/java/org/onosproject/igmp/impl/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Service for interacting with the inventory of subnets.
+ * IGMP implementation.
*/
-package org.onosproject.vtnrsc.tunnel;
+package org.onosproject.igmp.impl;
diff --git a/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/rest/package-info.java b/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/rest/package-info.java
new file mode 100644
index 00000000..b42586fe
--- /dev/null
+++ b/framework/src/onos/apps/mfwd/src/main/java/org/onosproject/mfwd/rest/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.
+ */
+
+/**
+ * REST API for multicase forwarding.
+ */
+package org.onosproject.mfwd.rest;
diff --git a/framework/src/onos/apps/mlb/src/main/java/org/onosproject/mlb/package-info.java b/framework/src/onos/apps/mlb/src/main/java/org/onosproject/mlb/package-info.java
new file mode 100644
index 00000000..a7d83757
--- /dev/null
+++ b/framework/src/onos/apps/mlb/src/main/java/org/onosproject/mlb/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.
+ */
+
+/**
+ * Mastership load balancer.
+ */
+package org.onosproject.mlb;
diff --git a/framework/src/onos/apps/openstackswitching/pom.xml b/framework/src/onos/apps/openstackswitching/pom.xml
new file mode 100644
index 00000000..245b9e80
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/pom.xml
@@ -0,0 +1,121 @@
+<?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-apps</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-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>
+ </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/OpenstackArpHandler.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
new file mode 100644
index 00000000..afaf7a22
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackArpHandler.java
@@ -0,0 +1,51 @@
+/*
+* 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.onosproject.net.packet.InboundPacket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+
+/**
+ * It handles ARP packet from VMs.
+ */
+public class OpenstackArpHandler {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackArpHandler.class);
+
+ HashMap<String, OpenstackPort> openstackPortHashMap;
+
+ /**
+ * Constructs an OpenstackArpHandler.
+ *
+ * @param openstackPortMap port map
+ */
+ public OpenstackArpHandler(HashMap<String, OpenstackPort> openstackPortMap) {
+ this.openstackPortHashMap = openstackPortMap;
+ }
+
+ /**
+ * Processes ARP packets.
+ *
+ * @param pkt ARP request packet
+ */
+ public void processPacketIn(InboundPacket pkt) {
+ log.warn("Received an ARP packet");
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.java
new file mode 100644
index 00000000..9c3641c1
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackDhcpHandler.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.openstackswitching;
+
+import org.onosproject.net.packet.InboundPacket;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * It handles DHCP request packets.
+ */
+public class OpenstackDhcpHandler {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackDhcpHandler.class);
+
+ /**
+ * Returns OpenstackDhcpHandler reference.
+ */
+ public OpenstackDhcpHandler() {
+
+ }
+
+ /**
+ * Processes DHCP request packets.
+ *
+ * @param pkt DHCP request packet
+ */
+ public void processPacketIn(InboundPacket pkt) {
+ log.warn("Received a DHCP packet");
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.java
new file mode 100644
index 00000000..dc7c0263
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackNetwork.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.openstackswitching;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * Represents the network information given by Neutron.
+ */
+public final class OpenstackNetwork {
+
+ private String name;
+ private String tenantId;
+ private String segmentId;
+ private String networkType;
+ private String id;
+
+ /**
+ * Returns the builder object of the OpenstackNetwork class.
+ *
+ * @return OpenstackNetwork builder object
+ */
+ public static OpenstackNetwork.Builder builder() {
+ return new Builder();
+ }
+
+ private OpenstackNetwork(String name, String tenantId, String id, String sid,
+ String type) {
+ this.name = checkNotNull(name);
+ this.tenantId = checkNotNull(tenantId);
+ this.segmentId = checkNotNull(sid);
+ this.id = checkNotNull(id);
+ this.networkType = checkNotNull(type);
+ }
+
+ public String name() {
+ return this.name;
+ }
+
+ public String tenantId() {
+ return this.tenantId;
+ }
+
+ public String id() {
+ return this.id;
+ }
+
+ public String segmentId() {
+ return this.segmentId;
+ }
+
+ public String networkType() {
+ return this.networkType;
+ }
+
+ public static final class Builder {
+ private String name;
+ private String tenantId;
+ private String id;
+ private String sid;
+ private String networkType;
+
+ public Builder name(String name) {
+ this.name = name;
+
+ return this;
+ }
+
+ public Builder tenantId(String tenantId) {
+ this.tenantId = tenantId;
+
+ return this;
+ }
+
+ public Builder id(String id) {
+ this.id = id;
+
+ return this;
+ }
+
+ public Builder segmentId(String sid) {
+ this.sid = sid;
+
+ return this;
+ }
+
+ public Builder networkType(String type) {
+ this.networkType = type;
+
+ return this;
+ }
+
+ public OpenstackNetwork build() {
+ return new OpenstackNetwork(name, tenantId, id, sid, networkType);
+ }
+
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java
new file mode 100644
index 00000000..4326b4fc
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackPort.java
@@ -0,0 +1,350 @@
+/*
+ * 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 org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+
+import java.util.HashMap;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * It represents the Openstack Port information.
+ */
+public final class OpenstackPort {
+
+ public enum PortStatus {
+ UP,
+ DOWN
+ }
+
+ private PortStatus status;
+ private String name;
+ // FIX_ME
+ private String allowedAddressPairs;
+ private boolean adminStateUp;
+ private String networkId;
+ private String tenantId;
+ private String deviceOwner;
+ private MacAddress macAddress;
+ // <subnet id, ip address>
+ private HashMap<String, Ip4Address> fixedIps;
+ private String id;
+ private List<String> securityGroups;
+ private String deviceId;
+
+ private OpenstackPort(PortStatus status, String name, boolean adminStateUp,
+ String networkId, String tenantId, String deviceOwner,
+ MacAddress macAddress, HashMap fixedIps, String id,
+ List<String> securityGroups, String deviceId) {
+
+ this.status = status;
+ this.name = name;
+ this.adminStateUp = adminStateUp;
+ this.networkId = checkNotNull(networkId);
+ this.tenantId = checkNotNull(tenantId);
+ this.deviceOwner = deviceOwner;
+ this.macAddress = checkNotNull(macAddress);
+ this.fixedIps = checkNotNull(fixedIps);
+ this.id = checkNotNull(id);
+ this.securityGroups = securityGroups;
+ this.deviceId = deviceId;
+ }
+
+
+
+ /**
+ * Returns OpenstackPort builder object.
+ *
+ * @return OpenstackPort builder
+ */
+ public static OpenstackPort.Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns port status.
+ *
+ * @return port status
+ */
+ public PortStatus status() {
+ return status;
+ }
+
+ /**
+ * Returns port name.
+ *
+ * @return port name
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns whether admin state up or not.
+ *
+ * @return true if admin state up, false otherwise
+ */
+ public boolean isAdminStateUp() {
+ return adminStateUp;
+ }
+
+ /**
+ * Returns network ID.
+ *
+ * @return network ID
+ */
+ public String networkId() {
+ return networkId;
+ }
+
+ /**
+ * Returns device owner.
+ *
+ * @return device owner
+ */
+ public String deviceOwner() {
+ return deviceOwner;
+ }
+
+ /**
+ * Returns mac address.
+ *
+ * @return mac address
+ */
+ public MacAddress macAddress() {
+ return macAddress;
+ }
+
+ /**
+ * Returns the fixed IP information.
+ *
+ * @return fixed IP info
+ */
+ public HashMap fixedIps() {
+ return fixedIps;
+ }
+
+ /**
+ * Returns port ID.
+ *
+ * @return port ID
+ */
+ public String id() {
+ return id;
+ }
+
+ /**
+ * Returns security group information.
+ *
+ * @return security group info
+ */
+ public List<String> securityGroups() {
+ return securityGroups;
+ }
+
+ /**
+ * Returns device ID.
+ *
+ * @return device ID
+ */
+ public String deviceId() {
+ return deviceId;
+ }
+
+ // TODO : Implement the following functions when necessary
+ //@Override
+ //public void equals(Object that) {
+ //
+ //}
+ //
+ //@Override
+ //public int hashCode() {
+ //
+ //}
+
+ /**
+ * OpenstackPort Builder class.
+ */
+ public static final class Builder {
+
+ private PortStatus status;
+ private String name;
+ // FIX_ME
+ private String allowedAddressPairs;
+ private boolean adminStateUp;
+ private String networkId;
+ private String tenantId;
+ private String deviceOwner;
+ private MacAddress macAddress;
+ // list of hash map <subnet id, ip address>
+ private HashMap<String, Ip4Address> fixedIps;
+ private String id;
+ private List<String> securityGroups;
+ private String deviceId;
+
+ Builder() {
+ fixedIps = new HashMap<>();
+ securityGroups = Lists.newArrayList();
+ }
+
+ /**
+ * Sets port status.
+ *
+ * @param status port status
+ * @return Builder object
+ */
+ public Builder portStatus(PortStatus status) {
+ this.status = status;
+
+ return this;
+ }
+
+ /**
+ * Sets port name.
+ *
+ * @param name port name
+ * @return Builder object
+ */
+ public Builder name(String name) {
+ this.name = name;
+
+ return this;
+ }
+
+ /**
+ * Sets whether admin state up or not.
+ *
+ * @param isAdminStateUp true if admin state is up, false otherwise
+ * @return Builder object
+ */
+ public Builder adminState(boolean isAdminStateUp) {
+ this.adminStateUp = isAdminStateUp;
+
+ return this;
+ }
+
+ /**
+ * Sets network ID.
+ *
+ * @param networkId network ID
+ * @return Builder object
+ */
+ public Builder netwrokId(String networkId) {
+ this.networkId = networkId;
+
+ return this;
+ }
+
+ /**
+ * Sets tenant ID.
+ *
+ * @param tenantId tenant ID
+ * @return Builder object
+ */
+ public Builder tenantId(String tenantId) {
+ this.tenantId = tenantId;
+
+ return this;
+ }
+
+ /**
+ * Sets device owner.
+ *
+ * @param owner device owner
+ * @return Builder object
+ */
+ public Builder deviceOwner(String owner) {
+ this.deviceOwner = owner;
+
+ return this;
+ }
+
+ /**
+ * Sets MAC address of the port.
+ *
+ * @param mac MAC address
+ * @return Builder object
+ */
+ public Builder macAddress(MacAddress mac) {
+ this.macAddress = mac;
+
+ return this;
+ }
+
+ /**
+ * Sets Fixed IP address information.
+ *
+ * @param fixedIpList Fixed IP info
+ * @return Builder object
+ */
+ public Builder fixedIps(HashMap<String, Ip4Address> fixedIpList) {
+ fixedIps.putAll(fixedIpList);
+
+ return this;
+ }
+
+ /**
+ * Sets ID of the port.
+ *
+ * @param id ID of the port
+ * @return Builder object
+ */
+ public Builder id(String id) {
+ this.id = id;
+
+ return this;
+ }
+
+ /**
+ * Sets security group of the port.
+ *
+ * @param securityGroup security group of the port
+ * @return Builder object
+ */
+ public Builder securityGroup(String securityGroup) {
+ securityGroups.add(securityGroup);
+
+ return this;
+ }
+
+ /**
+ * Sets device ID of the port.
+ *
+ * @param deviceId device ID
+ * @return Builder object
+ */
+ public Builder deviceId(String deviceId) {
+ this.deviceId = deviceId;
+
+ return this;
+ }
+
+ /**
+ * Builds an OpenstackPort object.
+ *
+ * @return OpenstackPort objecet
+ */
+ public OpenstackPort build() {
+ return new OpenstackPort(status, name, adminStateUp, networkId, networkId,
+ deviceOwner, macAddress, fixedIps, id, securityGroups, deviceId);
+ }
+ }
+}
+
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
new file mode 100644
index 00000000..baae7f80
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingManager.java
@@ -0,0 +1,437 @@
+/*
+ * 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.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.UDP;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+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.HashMap;
+import java.util.List;
+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;
+
+
+ public static final int DHCP_PORT = 67;
+
+ private ApplicationId appId;
+ private OpenstackArpHandler arpHandler;
+ private OpenstackDhcpHandler dhcpHandler = new OpenstackDhcpHandler();
+ private OpenstackSwitchingRulePopulator rulePopulator;
+ private ExecutorService deviceEventExcutorService = Executors.newFixedThreadPool(10);
+
+ private InternalPacketProcessor internalPacketProcessor = new InternalPacketProcessor();
+ private InternalDeviceListener internalDeviceListener = new InternalDeviceListener();
+
+ // Map <port_id, OpenstackPort>
+ private HashMap<String, OpenstackPort> openstackPortMap;
+ // Map <network_id, OpenstackNetwork>
+ private HashMap<String, OpenstackNetwork> openstackNetworkMap;
+ // Map <vni, List <Entry <portName, host ip>>
+ private HashMap<String, List<PortInfo>> vniPortMap;
+ private HashMap<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();
+ vniPortMap = Maps.newHashMap();
+ tunnelPortMap = Maps.newHashMap();
+
+ arpHandler = new OpenstackArpHandler(openstackPortMap);
+
+ log.info("Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ packetService.removeProcessor(internalPacketProcessor);
+ deviceService.removeListener(internalDeviceListener);
+
+ deviceEventExcutorService.shutdown();
+
+ log.info("Stopped");
+ }
+
+ @Override
+ public void createPorts(OpenstackPort openstackPort) {
+ openstackPortMap.put(openstackPort.id(), openstackPort);
+ }
+
+ @Override
+ public void deletePorts() {
+
+ }
+
+ @Override
+ public void updatePorts() {
+
+ }
+
+ @Override
+ public void createNetwork(OpenstackNetwork openstackNetwork) {
+ openstackNetworkMap.put(openstackNetwork.id(), openstackNetwork);
+ }
+
+ private void processDeviceAdded(Device device) {
+ log.warn("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.warn("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.warn("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.warn("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.warn("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.warn("No subnet information for network {}", subnet.id());
+ // return null;
+ //}
+
+ //return Ip4Prefix.valueOf(subnet.cidr());
+ return null;
+ }
+
+ /**
+ * 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.warn("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.warn("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);
+ } else if (ethernet.getEtherType() == Ethernet.TYPE_IPV4) {
+ IPv4 ipPacket = (IPv4) ethernet.getPayload();
+
+ if (ipPacket.getProtocol() == IPv4.PROTOCOL_UDP) {
+ UDP udpPacket = (UDP) ipPacket.getPayload();
+ if (udpPacket.getDestinationPort() == DHCP_PORT) {
+ dhcpHandler.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
new file mode 100644
index 00000000..9ead05f0
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingRulePopulator.java
@@ -0,0 +1,228 @@
+/*
+* 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) {
+
+ //setFlowRuleForDHCP(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/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.java
new file mode 100644
index 00000000..d97b39c8
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/OpenstackSwitchingService.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.openstackswitching;
+
+/**
+ * It handles port management REST API from Openstack for VMs.
+ */
+public interface OpenstackSwitchingService {
+
+ /**
+ * Store the port information created by Openstack.
+ *
+ * @param openstackPort port information
+ */
+ void createPorts(OpenstackPort openstackPort);
+
+ /**
+ * Removes flow rules corresponding to the port removed by Openstack.
+ *
+ */
+ void deletePorts();
+
+ /**
+ * Updates flow rules corresponding to the port information updated by Openstack.
+ *
+ */
+ void updatePorts();
+
+ /**
+ * Store the network information created by openstack.
+ *
+ * @param openstackNetwork network information
+ */
+ void createNetwork(OpenstackNetwork openstackNetwork);
+
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/package-info.java
new file mode 100644
index 00000000..cd50f912
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/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/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.java
new file mode 100644
index 00000000..43bd1583
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkCodec.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.openstackswitching.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstackswitching.OpenstackNetwork;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implementation of the OpenstackNetwork Codec.
+ *
+ */
+public class OpenstackNetworkCodec extends JsonCodec<OpenstackNetwork> {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(OpenstackNetworkCodec.class);
+
+ private static final String NETWORK = "network";
+ private static final String NAME = "name";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String SEGMENTATION_ID = "provider:segmentation_id";
+ private static final String NETWORK_TYPE = "provider:network_type";
+ private static final String ID = "id";
+
+ @Override
+ public OpenstackNetwork decode(ObjectNode json, CodecContext context) {
+
+ JsonNode networkInfo = json.get(NETWORK);
+
+ String name = networkInfo.path(NAME).asText();
+ String tenantId = networkInfo.path(TENANT_ID).asText();
+ String id = networkInfo.path(ID).asText();
+
+ OpenstackNetwork.Builder onb = OpenstackNetwork.builder();
+ onb.name(name)
+ .tenantId(tenantId)
+ .id(id);
+
+ if (!networkInfo.path(NETWORK_TYPE).isMissingNode()) {
+ onb.name(networkInfo.path(NETWORK_TYPE).asText());
+ onb.segmentId(networkInfo.path(SEGMENTATION_ID).asText());
+ }
+
+ return onb.build();
+ }
+
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.java
new file mode 100644
index 00000000..f4c401fb
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackNetworkWebResource.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.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.POST;
+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;
+
+@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);
+
+ OpenstackNetwork openstackNetwork = NETWORK_CODEC.decode(networkNode, this);
+
+ 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();
+ }
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
new file mode 100644
index 00000000..765b6901
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortCodec.java
@@ -0,0 +1,104 @@
+/*
+ * 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.web;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.MacAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.openstackswitching.OpenstackPort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+
+/**
+ * It encodes and decodes the OpenstackPort.
+ */
+public class OpenstackPortCodec extends JsonCodec<OpenstackPort> {
+
+ private static Logger log = LoggerFactory
+ .getLogger(OpenstackPortCodec.class);
+
+ // JSON field names
+ private static final String PORT = "port";
+ private static final String STATUS = "status";
+ private static final String NAME = "name";
+ private static final String ADDRESS_PAIR = "allowed_address_pairs";
+ private static final String ADMIN_STATUS = "admin_status";
+ private static final String NETWORK_ID = "network_id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String DEVICE_OWNER = "device_owner";
+ private static final String MAC_ADDRESS = "mac_address";
+ private static final String FIXED_IPS = "fixed_ips";
+ private static final String SUBNET_ID = "subnet_id";
+ private static final String IP_ADDRESS = "ip_address";
+ private static final String ID = "id";
+ private static final String SECURITY_GROUPS = "security_groups";
+ private static final String DEVICE_ID = "device_id";
+
+ @Override
+ public OpenstackPort decode(ObjectNode json, CodecContext context) {
+
+ HashMap<String, Ip4Address> fixedIpMap = new HashMap<>();
+ JsonNode portInfo = json.get(PORT);
+
+ String status = portInfo.path(STATUS).asText();
+ String name = portInfo.path(NAME).asText();
+ boolean adminStateUp = portInfo.path(ADMIN_STATUS).asBoolean();
+ String networkId = portInfo.path(NETWORK_ID).asText();
+ String tenantId = portInfo.path(TENANT_ID).asText();
+ String deviceOwner = portInfo.path(DEVICE_OWNER).asText();
+ String macStr = portInfo.path(MAC_ADDRESS).asText();
+ ArrayNode fixedIpList = (ArrayNode) portInfo.path(FIXED_IPS);
+ for (JsonNode fixedIpInfo: fixedIpList) {
+ String subnetId = fixedIpInfo.path(SUBNET_ID).asText();
+ String ipAddressStr = fixedIpInfo.path(IP_ADDRESS).asText();
+ if (ipAddressStr != null) {
+ Ip4Address ipAddress = Ip4Address.valueOf(ipAddressStr);
+ fixedIpMap.put(subnetId, ipAddress);
+ }
+ }
+ String id = portInfo.path(ID).asText();
+ String securityGroups = portInfo.path(SECURITY_GROUPS).asText();
+ String deviceId = portInfo.path(DEVICE_ID).asText();
+
+ OpenstackPort.Builder openstackPortBuilder = OpenstackPort.builder();
+ openstackPortBuilder.portStatus(OpenstackPort.PortStatus.valueOf(status))
+ .name(name)
+ .adminState(adminStateUp)
+ .netwrokId(networkId)
+ .tenantId(tenantId)
+ .deviceOwner(deviceOwner)
+ .macAddress(MacAddress.valueOf(macStr))
+ .fixedIps(fixedIpMap)
+ .id(id)
+ .deviceId(deviceId);
+
+ // FIX ME
+ if (!securityGroups.isEmpty()) {
+ openstackPortBuilder.securityGroup(securityGroups);
+ }
+
+ OpenstackPort openstackPort = openstackPortBuilder.build();
+
+ return openstackPort;
+ }
+
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
new file mode 100644
index 00000000..67a9cebb
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/OpenstackPortWebResource.java
@@ -0,0 +1,106 @@
+/*
+ * 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.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.openstackswitching.OpenstackPort;
+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;
+
+@Path("ports")
+public class OpenstackPortWebResource extends AbstractWebResource {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(OpenstackPortWebResource.class);
+
+ private static final OpenstackPortCodec PORT_CODEC = new OpenstackPortCodec();
+
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createPorts(InputStream input) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode portNode = (ObjectNode) mapper.readTree(input);
+
+ OpenstackPort openstackPort = PORT_CODEC.decode(portNode, this);
+
+ OpenstackSwitchingService switchingService = get(OpenstackSwitchingService.class);
+ switchingService.createPorts(openstackPort);
+ log.info("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 {}",
+ e.toString());
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.toString())
+ .build();
+ }
+ }
+
+ @DELETE
+ @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();
+ }
+ }
+
+ @PUT
+ @Path("{id}")
+ @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();
+ }
+ }
+}
diff --git a/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/package-info.java
new file mode 100644
index 00000000..91e19c62
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/java/org/onosproject/openstackswitching/web/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 switching REST API.
+ */
+package org.onosproject.openstackswitching.web;
diff --git a/framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml b/framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000..53b0e2e9
--- /dev/null
+++ b/framework/src/onos/apps/openstackswitching/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,44 @@
+<?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.
+ -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ id="ONOS" version="2.5">
+ <display-name>Openstack Switching REST API v1.0</display-name>
+
+ <servlet>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.resourceConfigClass</param-name>
+ <param-value>com.sun.jersey.api.core.ClassNamesResourceConfig</param-value>
+ </init-param>
+ <init-param>
+ <param-name>com.sun.jersey.config.property.classnames</param-name>
+ <param-value>
+ org.onosproject.openstackswitching.web.OpenstackPortWebResource,
+ org.onosproject.openstackswitching.web.OpenstackNetworkWebResource
+ </param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
diff --git a/framework/src/onos/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java b/framework/src/onos/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
index 8466b95e..e0545023 100644
--- a/framework/src/onos/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
+++ b/framework/src/onos/apps/optical/src/main/java/org/onosproject/optical/OpticalPathProvisioner.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.optical;
+import com.google.common.collect.ImmutableList;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -45,16 +46,16 @@ import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.OpticalCircuitIntent;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.resource.device.IntentSetMultimap;
-import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceService;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEdge;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
@@ -101,9 +102,6 @@ public class OpticalPathProvisioner {
protected IntentSetMultimap intentSetMultimap;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService linkResourceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
private ApplicationId appId;
@@ -377,17 +375,17 @@ public class OpticalPathProvisioner {
* @param intent the intent
*/
private void releaseResources(Intent intent) {
- LinkResourceAllocations lra = linkResourceService.getAllocations(intent.id());
+ Collection<ResourceAllocation> allocations = resourceService.getResourceAllocations(intent.id());
if (intent instanceof OpticalConnectivityIntent) {
resourceService.release(intent.id());
- if (lra != null) {
- linkResourceService.releaseResources(lra);
+ if (!allocations.isEmpty()) {
+ resourceService.release(ImmutableList.copyOf(allocations));
}
} else if (intent instanceof OpticalCircuitIntent) {
resourceService.release(intent.id());
intentSetMultimap.releaseMapping(intent.id());
- if (lra != null) {
- linkResourceService.releaseResources(lra);
+ if (!allocations.isEmpty()) {
+ resourceService.release(ImmutableList.copyOf(allocations));
}
}
}
diff --git a/framework/src/onos/apps/pom.xml b/framework/src/onos/apps/pom.xml
index 98210736..005052fb 100644
--- a/framework/src/onos/apps/pom.xml
+++ b/framework/src/onos/apps/pom.xml
@@ -13,10 +13,7 @@
~ 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">
+ --><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>
@@ -60,6 +57,7 @@
<module>igmp</module>
<module>pim</module>
<module>mlb</module>
+ <module>openstackswitching</module>
</modules>
<properties>
diff --git a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
index b2ce0f8a..a27baaf9 100644
--- a/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
+++ b/framework/src/onos/apps/sdnip/src/main/java/org/onosproject/sdnip/PeerConnectivityManager.java
@@ -15,8 +15,6 @@
*/
package org.onosproject.sdnip;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.IPv6;
@@ -27,6 +25,8 @@ import org.onosproject.core.ApplicationId;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.config.NetworkConfigEvent;
+import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -43,7 +43,9 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -69,9 +71,10 @@ public class PeerConnectivityManager {
private final ApplicationId appId;
private final ApplicationId routerAppId;
- // Just putting something random here for now. Figure out exactly what
- // indexes we need when we start making use of them.
- private final Multimap<BgpConfig.BgpSpeakerConfig, PointToPointIntent> peerIntents;
+ private final Map<Key, PointToPointIntent> peerIntents;
+
+ private final InternalNetworkConfigListener configListener
+ = new InternalNetworkConfigListener();
/**
* Creates a new PeerConnectivityManager.
@@ -93,13 +96,14 @@ public class PeerConnectivityManager {
this.routerAppId = routerAppId;
this.interfaceService = interfaceService;
- peerIntents = HashMultimap.create();
+ peerIntents = new HashMap<>();
}
/**
* Starts the peer connectivity manager.
*/
public void start() {
+ configService.addListener(configListener);
setUpConnectivity();
}
@@ -107,6 +111,7 @@ public class PeerConnectivityManager {
* Stops the peer connectivity manager.
*/
public void stop() {
+ configService.removeListener(configListener);
}
/**
@@ -121,16 +126,27 @@ public class PeerConnectivityManager {
return;
}
+ Map<Key, PointToPointIntent> existingIntents = new HashMap<>(peerIntents);
+
for (BgpConfig.BgpSpeakerConfig bgpSpeaker : config.bgpSpeakers()) {
log.debug("Start to set up BGP paths for BGP speaker: {}",
bgpSpeaker);
buildSpeakerIntents(bgpSpeaker).forEach(i -> {
- peerIntents.put(bgpSpeaker, i);
- intentSynchronizer.submit(i);
+ PointToPointIntent intent = existingIntents.remove(i.key());
+ if (intent == null || !IntentUtils.equals(i, intent)) {
+ peerIntents.put(i.key(), i);
+ intentSynchronizer.submit(i);
+ }
});
-
}
+
+ // Remove any remaining intents that we used to have that we don't need
+ // anymore
+ existingIntents.values().forEach(i -> {
+ peerIntents.remove(i.key());
+ intentSynchronizer.withdraw(i);
+ });
}
private Collection<PointToPointIntent> buildSpeakerIntents(BgpConfig.BgpSpeakerConfig speaker) {
@@ -356,7 +372,7 @@ public class PeerConnectivityManager {
* @param srcIp source IP address
* @param dstIp destination IP address
* @param suffix suffix string
- * @return
+ * @return intent key
*/
private Key buildKey(IpAddress srcIp, IpAddress dstIp, String suffix) {
String keyString = new StringBuilder()
@@ -370,4 +386,26 @@ public class PeerConnectivityManager {
return Key.of(keyString, appId);
}
+ private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+ case CONFIG_REGISTERED:
+ break;
+ case CONFIG_UNREGISTERED:
+ break;
+ case CONFIG_ADDED:
+ case CONFIG_UPDATED:
+ case CONFIG_REMOVED:
+ if (event.configClass() == RoutingService.CONFIG_CLASS) {
+ setUpConnectivity();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
}
diff --git a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
index c4b2daad..0dcc969d 100644
--- a/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
+++ b/framework/src/onos/apps/sdnip/src/test/java/org/onosproject/sdnip/PeerConnectivityManagerTest.java
@@ -34,6 +34,7 @@ import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -60,8 +61,10 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.reset;
import static org.easymock.EasyMock.verify;
@@ -119,6 +122,8 @@ public class PeerConnectivityManagerTest extends AbstractIntentTest {
routingConfig = createMock(RoutingConfigurationService.class);
interfaceService = createMock(InterfaceService.class);
networkConfigService = createMock(NetworkConfigService.class);
+ networkConfigService.addListener(anyObject(NetworkConfigListener.class));
+ expectLastCall().anyTimes();
bgpConfig = createMock(BgpConfig.class);
// These will set expectations on routingConfig and interfaceService
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
index f42f84b1..36563f01 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/ArpHandler.java
@@ -35,7 +35,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
-import java.util.List;
+import java.util.Set;
+
import static com.google.common.base.Preconditions.checkNotNull;
public class ArpHandler {
@@ -112,7 +113,7 @@ public class ArpHandler {
private boolean isArpReqForRouter(DeviceId deviceId, ARP arpRequest) {
- List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
+ Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
if (gatewayIpAddresses != null) {
Ip4Address targetProtocolAddress = Ip4Address.valueOf(arpRequest
.getTargetProtocolAddress());
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 40ee55fc..c4a91c75 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
@@ -23,14 +23,12 @@ import org.onlab.packet.IpPrefix;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
-import org.onosproject.net.MastershipRole;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -97,7 +95,7 @@ public class DefaultRoutingHandler {
log.debug("populateAllRoutingRules: populationStatus is STARTED");
for (Device sw : srManager.deviceService.getDevices()) {
- if (srManager.mastershipService.getLocalRole(sw.id()) != MastershipRole.MASTER) {
+ if (!srManager.mastershipService.isLocalMaster(sw.id())) {
log.debug("populateAllRoutingRules: skipping device {}...we are not master",
sw.id());
continue;
@@ -146,8 +144,7 @@ public class DefaultRoutingHandler {
// Take the snapshots of the links
updatedEcmpSpgMap = new HashMap<>();
for (Device sw : srManager.deviceService.getDevices()) {
- if (srManager.mastershipService.
- getLocalRole(sw.id()) != MastershipRole.MASTER) {
+ if (!srManager.mastershipService.isLocalMaster(sw.id())) {
continue;
}
ECMPShortestPathGraph ecmpSpgUpdated =
@@ -273,8 +270,7 @@ public class DefaultRoutingHandler {
for (Device sw : srManager.deviceService.getDevices()) {
log.debug("Computing the impacted routes for device {} due to link fail",
sw.id());
- if (srManager.mastershipService.
- getLocalRole(sw.id()) != MastershipRole.MASTER) {
+ if (!srManager.mastershipService.isLocalMaster(sw.id())) {
continue;
}
ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
@@ -320,8 +316,7 @@ public class DefaultRoutingHandler {
for (Device sw : srManager.deviceService.getDevices()) {
log.debug("Computing the impacted routes for device {}",
sw.id());
- if (srManager.mastershipService.
- getLocalRole(sw.id()) != MastershipRole.MASTER) {
+ if (!srManager.mastershipService.isLocalMaster(sw.id())) {
log.debug("No mastership for {} and skip route optimization",
sw.id());
continue;
@@ -455,7 +450,7 @@ public class DefaultRoutingHandler {
// If both target switch and dest switch are edge routers, then set IP
// rule for both subnet and router IP.
if (config.isEdgeDevice(targetSw) && config.isEdgeDevice(destSw)) {
- List<Ip4Prefix> subnets = config.getSubnets(destSw);
+ Set<Ip4Prefix> subnets = config.getSubnets(destSw);
log.debug("* populateEcmpRoutingRulePartial in device {} towards {} for subnets {}",
targetSw, destSw, subnets);
result = rulePopulator.populateIpRuleForSubnet(targetSw,
@@ -499,14 +494,13 @@ public class DefaultRoutingHandler {
}
/**
- * Populates table miss entries for all tables, and pipeline rules for VLAN
- * and TCAM tables. XXX rename/rethink
+ * Populates filtering rules for permitting Router DstMac and VLAN.
*
* @param deviceId Switch ID to set the rules
*/
- public void populateTtpRules(DeviceId deviceId) {
- rulePopulator.populateTableVlan(deviceId);
- rulePopulator.populateTableTMac(deviceId);
+ public void populatePortAddressingRules(DeviceId deviceId) {
+ rulePopulator.populateRouterMacVlanFilters(deviceId);
+ rulePopulator.populateRouterIpPunts(deviceId);
}
/**
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
index 0bc155b8..828c51ce 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DeviceConfiguration.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.segmentrouting;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
@@ -38,20 +39,20 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Segment Routing configuration component that reads the
* segment routing related configuration from Network Configuration Manager
* component and organizes in more accessible formats.
- *
- * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
*/
public class DeviceConfiguration implements DeviceProperties {
private static final Logger log = LoggerFactory
.getLogger(DeviceConfiguration.class);
private final List<Integer> allSegmentIds = new ArrayList<>();
- private final HashMap<DeviceId, SegmentRouterInfo> deviceConfigMap = new HashMap<>();
+ private final ConcurrentHashMap<DeviceId, SegmentRouterInfo> deviceConfigMap
+ = new ConcurrentHashMap<>();
private class SegmentRouterInfo {
int nodeSid;
@@ -126,18 +127,17 @@ public class DeviceConfiguration implements DeviceProperties {
}
/**
- * Returns the segment id of a segment router.
+ * Returns the Node segment id of a segment router.
*
* @param deviceId device identifier
* @return segment id
*/
@Override
public int getSegmentId(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("getSegmentId for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).nodeSid);
- return deviceConfigMap.get(deviceId).nodeSid;
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getSegmentId for device{} is {}", deviceId, srinfo.nodeSid);
+ return srinfo.nodeSid;
} else {
log.warn("getSegmentId for device {} "
+ "throwing IllegalStateException "
@@ -147,10 +147,10 @@ public class DeviceConfiguration implements DeviceProperties {
}
/**
- * Returns the segment id of a segment router given its mac address.
+ * Returns the Node segment id of a segment router given its Router mac address.
*
* @param routerMac router mac address
- * @return segment id
+ * @return node segment id, or -1 if not found in config
*/
public int getSegmentId(MacAddress routerMac) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
@@ -164,10 +164,10 @@ public class DeviceConfiguration implements DeviceProperties {
}
/**
- * Returns the segment id of a segment router given its router ip address.
+ * Returns the Node segment id of a segment router given its Router ip address.
*
* @param routerAddress router ip address
- * @return segment id
+ * @return node segment id, or -1 if not found in config
*/
public int getSegmentId(Ip4Address routerAddress) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
@@ -188,11 +188,10 @@ public class DeviceConfiguration implements DeviceProperties {
*/
@Override
public MacAddress getDeviceMac(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("getDeviceMac for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).mac);
- return deviceConfigMap.get(deviceId).mac;
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getDeviceMac for device{} is {}", deviceId, srinfo.mac);
+ return srinfo.mac;
} else {
log.warn("getDeviceMac for device {} "
+ "throwing IllegalStateException "
@@ -208,11 +207,10 @@ public class DeviceConfiguration implements DeviceProperties {
* @return router ip address
*/
public Ip4Address getRouterIp(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("getDeviceIp for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).ip);
- return deviceConfigMap.get(deviceId).ip;
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getDeviceIp for device{} is {}", deviceId, srinfo.ip);
+ return srinfo.ip;
} else {
log.warn("getRouterIp for device {} "
+ "throwing IllegalStateException "
@@ -223,18 +221,17 @@ public class DeviceConfiguration implements DeviceProperties {
/**
* Indicates if the segment router is a edge router or
- * a transit/back bone router.
+ * a core/backbone router.
*
* @param deviceId device identifier
* @return boolean
*/
@Override
public boolean isEdgeDevice(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("isEdgeDevice for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).isEdge);
- return deviceConfigMap.get(deviceId).isEdge;
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("isEdgeDevice for device{} is {}", deviceId, srinfo.isEdge);
+ return srinfo.isEdge;
} else {
log.warn("isEdgeDevice for device {} "
+ "throwing IllegalStateException "
@@ -244,15 +241,35 @@ public class DeviceConfiguration implements DeviceProperties {
}
/**
- * Returns the segment ids of all configured segment routers.
+ * Returns the node segment ids of all configured segment routers.
*
- * @return list of segment ids
+ * @return list of node segment ids
*/
@Override
public List<Integer> getAllDeviceSegmentIds() {
return allSegmentIds;
}
+ @Override
+ public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId) {
+ Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
+
+ // Construct subnet-port mapping from port-subnet mapping
+ Map<PortNumber, Ip4Prefix> portSubnetMap =
+ this.deviceConfigMap.get(deviceId).subnets;
+ portSubnetMap.forEach((port, subnet) -> {
+ if (subnetPortMap.containsKey(subnet)) {
+ subnetPortMap.get(subnet).add(port);
+ } else {
+ ArrayList<PortNumber> ports = new ArrayList<>();
+ ports.add(port);
+ subnetPortMap.put(subnet, ports);
+ }
+ });
+
+ return subnetPortMap;
+ }
+
/**
* Returns the device identifier or data plane identifier (dpid)
* of a segment router given its segment id.
@@ -290,37 +307,68 @@ public class DeviceConfiguration implements DeviceProperties {
}
/**
- * Returns the configured subnet gateway ip addresses for a segment router.
+ * Returns the configured port ip addresses for a segment router.
+ * These addresses serve as gateway IP addresses for the subnets configured
+ * on those ports.
*
* @param deviceId device identifier
- * @return list of ip addresses
+ * @return immutable set of ip addresses configured on the ports or null if not found
*/
- public List<Ip4Address> getSubnetGatewayIps(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("getSubnetGatewayIps for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).gatewayIps.values());
- return new ArrayList<>(deviceConfigMap.get(deviceId).gatewayIps.values());
- } else {
- return null;
+ public Set<Ip4Address> getPortIPs(DeviceId deviceId) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getSubnetGatewayIps for device{} is {}", deviceId,
+ srinfo.gatewayIps.values());
+ return ImmutableSet.copyOf(srinfo.gatewayIps.values());
+ }
+ return null;
+ }
+
+ /**
+ * Returns the configured IP addresses per port
+ * for a segment router.
+ *
+ * @param deviceId device identifier
+ * @return map of port to gateway IP addresses or null if not found
+ */
+ public Map<PortNumber, Ip4Address> getPortIPMap(DeviceId deviceId) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ return srinfo.gatewayIps;
}
+ return null;
}
/**
* Returns the configured subnet prefixes for a segment router.
*
* @param deviceId device identifier
- * @return list of ip prefixes
+ * @return list of ip prefixes or null if not found
*/
- public List<Ip4Prefix> getSubnets(DeviceId deviceId) {
- if (deviceConfigMap.get(deviceId) != null) {
- log.trace("getSubnets for device{} is {}",
- deviceId,
- deviceConfigMap.get(deviceId).subnets.values());
- return new ArrayList<>(deviceConfigMap.get(deviceId).subnets.values());
- } else {
- return null;
+ public Set<Ip4Prefix> getSubnets(DeviceId deviceId) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ log.trace("getSubnets for device{} is {}", deviceId,
+ srinfo.subnets.values());
+ return ImmutableSet.copyOf(srinfo.subnets.values());
}
+ return null;
+ }
+
+ /**
+ * Returns the configured subnet on the given port, or null if no
+ * subnet has been configured on the port.
+ *
+ * @param deviceId device identifier
+ * @param pnum port identifier
+ * @return configured subnet on port, or null
+ */
+ public Ip4Prefix getPortSubnet(DeviceId deviceId, PortNumber pnum) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ return srinfo.subnets.get(pnum);
+ }
+ return null;
}
/**
@@ -349,7 +397,7 @@ public class DeviceConfiguration implements DeviceProperties {
* specified ip address as one of its subnet gateway ip address.
*
* @param gatewayIpAddress router gateway ip address
- * @return router mac address
+ * @return router mac address or null if not found
*/
public MacAddress getRouterMacForAGatewayIp(Ip4Address gatewayIpAddress) {
for (Map.Entry<DeviceId, SegmentRouterInfo> entry:
@@ -377,7 +425,7 @@ public class DeviceConfiguration implements DeviceProperties {
*/
public boolean inSameSubnet(DeviceId deviceId, Ip4Address hostIp) {
- List<Ip4Prefix> subnets = getSubnets(deviceId);
+ Set<Ip4Prefix> subnets = getSubnets(deviceId);
if (subnets == null) {
return false;
}
@@ -399,8 +447,9 @@ public class DeviceConfiguration implements DeviceProperties {
* @return list of port numbers
*/
public List<Integer> getPortsForAdjacencySid(DeviceId deviceId, int sid) {
- if (deviceConfigMap.get(deviceId) != null) {
- for (AdjacencySid asid : deviceConfigMap.get(deviceId).adjacencySids) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ for (AdjacencySid asid : srinfo.adjacencySids) {
if (asid.getAsid() == sid) {
return asid.getPorts();
}
@@ -419,12 +468,13 @@ public class DeviceConfiguration implements DeviceProperties {
* otherwise false
*/
public boolean isAdjacencySid(DeviceId deviceId, int sid) {
- if (deviceConfigMap.get(deviceId) != null) {
- if (deviceConfigMap.get(deviceId).adjacencySids.isEmpty()) {
+ SegmentRouterInfo srinfo = deviceConfigMap.get(deviceId);
+ if (srinfo != null) {
+ if (srinfo.adjacencySids.isEmpty()) {
return false;
} else {
for (AdjacencySid asid:
- deviceConfigMap.get(deviceId).adjacencySids) {
+ srinfo.adjacencySids) {
if (asid.getAsid() == sid) {
return true;
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
index f65f03e0..b3916b06 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/IcmpHandler.java
@@ -32,7 +32,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
-import java.util.List;
+import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -70,7 +70,7 @@ public class IcmpHandler {
DeviceId deviceId = connectPoint.deviceId();
Ip4Address destinationAddress =
Ip4Address.valueOf(ipv4.getDestinationAddress());
- List<Ip4Address> gatewayIpAddresses = config.getSubnetGatewayIps(deviceId);
+ Set<Ip4Address> gatewayIpAddresses = config.getPortIPs(deviceId);
Ip4Address routerIp = config.getRouterIp(deviceId);
IpPrefix routerIpPrefix = IpPrefix.valueOf(routerIp, IpPrefix.MAX_INET_MASK_LENGTH);
Ip4Address routerIpAddress = routerIpPrefix.getIp4Prefix().address();
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 7641571d..d46028e7 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
@@ -25,6 +25,7 @@ import org.onlab.packet.VlanId;
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;
import org.onosproject.net.flow.DefaultTrafficTreatment;
@@ -38,11 +39,13 @@ import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.flowobjective.ForwardingObjective.Builder;
+import org.onosproject.net.flowobjective.ForwardingObjective.Flag;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
@@ -57,6 +60,11 @@ public class RoutingRulePopulator {
private AtomicLong rulePopulationCounter;
private SegmentRoutingManager srManager;
private DeviceConfiguration config;
+
+ private static final int HIGHEST_PRIORITY = 0xffff;
+ private static final long OFPP_MAX = 0xffffff00L;
+
+
/**
* Creates a RoutingRulePopulator object.
*
@@ -98,7 +106,7 @@ public class RoutingRulePopulator {
TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
TrafficTreatment.Builder tbuilder = DefaultTrafficTreatment.builder();
- sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, 32));
+ sbuilder.matchIPDst(IpPrefix.valueOf(hostIp, IpPrefix.MAX_INET_MASK_LENGTH));
sbuilder.matchEthType(Ethernet.TYPE_IPV4);
tbuilder.deferred()
@@ -134,7 +142,7 @@ public class RoutingRulePopulator {
* @return true if all rules are set successfully, false otherwise
*/
public boolean populateIpRuleForSubnet(DeviceId deviceId,
- List<Ip4Prefix> subnets,
+ Set<Ip4Prefix> subnets,
DeviceId destSw,
Set<DeviceId> nextHops) {
@@ -350,40 +358,80 @@ public class RoutingRulePopulator {
}
/**
- * Populates VLAN flows rules. All packets are forwarded to TMAC table.
+ * Creates a filtering objective to permit all untagged packets with a
+ * dstMac corresponding to the router's MAC address. For those pipelines
+ * that need to internally assign vlans to untagged packets, this method
+ * provides per-subnet vlan-ids as metadata.
+ * <p>
+ * Note that the vlan assignment is only done by the master-instance for a switch.
+ * However we send the filtering objective from slave-instances as well, so
+ * that drivers can obtain other information (like Router MAC and IP).
*
- * @param deviceId switch ID to set the rules
+ * @param deviceId the switch dpid for the router
*/
- public void populateTableVlan(DeviceId deviceId) {
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
- fob.withKey(Criteria.matchInPort(PortNumber.ALL))
+ public void populateRouterMacVlanFilters(DeviceId deviceId) {
+ log.debug("Installing per-port filtering objective for untagged "
+ + "packets in device {}", deviceId);
+ for (Port port : srManager.deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ Ip4Prefix portSubnet = config.getPortSubnet(deviceId, port.number());
+ VlanId assignedVlan = (portSubnet == null)
+ ? VlanId.vlanId(SegmentRoutingManager.ASSIGNED_VLAN_NO_SUBNET)
+ : srManager.getSubnetAssignedVlanId(deviceId, portSubnet);
+ FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
+ fob.withKey(Criteria.matchInPort(port.number()))
+ .addCondition(Criteria.matchEthDst(config.getDeviceMac(deviceId)))
.addCondition(Criteria.matchVlanId(VlanId.NONE));
- fob.permit().fromApp(srManager.appId);
- log.debug("populateTableVlan: Installing filtering objective for untagged packets");
- srManager.flowObjectiveService.
- filter(deviceId,
- fob.add(new SRObjectiveContext(deviceId,
- SRObjectiveContext.ObjectiveType.FILTER)));
+ // vlan assignment is valid only if this instance is master
+ if (srManager.mastershipService.isLocalMaster(deviceId)) {
+ TrafficTreatment tt = DefaultTrafficTreatment.builder()
+ .pushVlan().setVlanId(assignedVlan).build();
+ fob.setMeta(tt);
+ }
+ fob.permit().fromApp(srManager.appId);
+ srManager.flowObjectiveService.
+ filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FILTER)));
+ }
+ }
}
/**
- * Populates TMAC table rules. IP packets are forwarded to IP table. MPLS
- * packets are forwarded to MPLS table.
+ * Creates a forwarding objective to punt all IP packets, destined to the
+ * router's port IP addresses, to the controller. Note that the input
+ * port should not be matched on, as these packets can come from any input.
+ * Furthermore, these are applied only by the master instance.
*
- * @param deviceId switch ID to set the rules
+ * @param deviceId the switch dpid for the router
*/
- public void populateTableTMac(DeviceId deviceId) {
-
- FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
- fob.withKey(Criteria.matchInPort(PortNumber.ALL))
- .addCondition(Criteria.matchEthDst(config
- .getDeviceMac(deviceId)));
- fob.permit().fromApp(srManager.appId);
- log.debug("populateTableTMac: Installing filtering objective for router mac");
- srManager.flowObjectiveService.
- filter(deviceId,
- fob.add(new SRObjectiveContext(deviceId,
- SRObjectiveContext.ObjectiveType.FILTER)));
+ public void populateRouterIpPunts(DeviceId deviceId) {
+ if (!srManager.mastershipService.isLocalMaster(deviceId)) {
+ log.debug("Not installing port-IP punts - not the master for dev:{} ",
+ deviceId);
+ return;
+ }
+ ForwardingObjective.Builder puntIp = DefaultForwardingObjective.builder();
+ Set<Ip4Address> allIps = new HashSet<Ip4Address>(config.getPortIPs(deviceId));
+ allIps.add(config.getRouterIp(deviceId));
+ for (Ip4Address ipaddr : allIps) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchIPDst(IpPrefix.valueOf(ipaddr,
+ IpPrefix.MAX_INET_MASK_LENGTH));
+ treatment.setOutput(PortNumber.CONTROLLER);
+ puntIp.withSelector(selector.build());
+ puntIp.withTreatment(treatment.build());
+ puntIp.withFlag(Flag.VERSATILE)
+ .withPriority(HIGHEST_PRIORITY)
+ .makePermanent()
+ .fromApp(srManager.appId);
+ log.debug("Installing forwarding objective to punt port IP addresses");
+ srManager.flowObjectiveService.
+ forward(deviceId,
+ puntIp.add(new SRObjectiveContext(deviceId,
+ SRObjectiveContext.ObjectiveType.FORWARDING)));
+ }
}
private PortNumber selectOnePort(DeviceId srcId, Set<DeviceId> destIds) {
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 eb2cf569..9d60b279 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
@@ -22,11 +22,17 @@ 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.VlanId;
import org.onlab.packet.IPv4;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.event.Event;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigRegistry;
@@ -45,7 +51,6 @@ 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.group.GroupKey;
import org.onosproject.net.host.HostService;
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkEvent;
@@ -56,6 +61,7 @@ import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.net.topology.TopologyService;
+import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapBuilder;
import org.onosproject.store.service.StorageService;
@@ -64,9 +70,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
@@ -133,8 +141,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
// Per device next objective ID store with (device id + neighbor set) as key
private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
Integer> nsNextObjStore = null;
+ private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null;
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
+ // Per device, per-subnet assigned-vlans store, with (device id + subnet
+ // IPv4 prefix) as key
+ private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
+ subnetVidStore = null;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected StorageService storageService;
@@ -163,6 +176,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private KryoNamespace.Builder kryoBuilder = null;
+ private static final short ASSIGNED_VLAN_START = 4093;
+ public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
+
@Activate
protected void activate() {
appId = coreService
@@ -170,6 +186,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
kryoBuilder = new KryoNamespace.Builder()
.register(NeighborSetNextObjectiveStoreKey.class,
+ SubnetNextObjectiveStoreKey.class,
+ SubnetAssignedVidStoreKey.class,
NeighborSet.class,
DeviceId.class,
URI.class,
@@ -180,7 +198,12 @@ public class SegmentRoutingManager implements SegmentRoutingService {
DefaultTunnel.class,
Policy.class,
TunnelPolicy.class,
- Policy.Type.class
+ Policy.Type.class,
+ VlanId.class,
+ Ip4Address.class,
+ Ip4Prefix.class,
+ IpAddress.Version.class,
+ ConnectPoint.class
);
log.debug("Creating EC map nsnextobjectivestore");
@@ -194,6 +217,16 @@ public class SegmentRoutingManager implements SegmentRoutingService {
.build();
log.trace("Current size {}", nsNextObjStore.size());
+ log.debug("Creating EC map subnetnextobjectivestore");
+ EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
+ subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
+
+ subnetNextObjStore = subnetNextObjMapBuilder
+ .withName("subnetnextobjectivestore")
+ .withSerializer(kryoBuilder)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+
EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
storageService.eventuallyConsistentMapBuilder();
@@ -212,6 +245,15 @@ public class SegmentRoutingManager implements SegmentRoutingService {
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
+ EventuallyConsistentMapBuilder<SubnetAssignedVidStoreKey, VlanId>
+ subnetVidStoreMapBuilder = storageService.eventuallyConsistentMapBuilder();
+
+ subnetVidStore = subnetVidStoreMapBuilder
+ .withName("subnetvidstore")
+ .withSerializer(kryoBuilder)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+
cfgService.addListener(cfgListener);
cfgService.registerConfigFactory(cfgFactory);
@@ -296,23 +338,72 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
/**
- * Returns the GroupKey object for the device and the NeighborSet given.
- * XXX is this called
+ * Returns the vlan-id assigned to the subnet configured for a device.
+ * If no vlan-id has been assigned, a new one is assigned out of a pool of ids,
+ * if and only if this controller instance is the master for the device.
+ * <p>
+ * USAGE: The assigned vlans are meant to be applied to untagged packets on those
+ * switches/pipelines that need this functionality. These vids are meant
+ * to be used internally within a switch, and thus need to be unique only
+ * on a switch level. Note that packets never go out on the wire with these
+ * vlans. Currently, vlan ids are assigned from value 4093 down.
+ * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
+ * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
+ * per subnet.
+ * XXX This method should avoid any vlans configured on the ports, but
+ * currently the app works only on untagged packets and as a result
+ * ignores any vlan configuration.
*
- * @param ns NeightborSet object for the GroupKey
- * @return GroupKey object for the NeighborSet
+ * @param deviceId switch dpid
+ * @param subnet IPv4 prefix for which assigned vlan is desired
+ * @return VlanId assigned for the subnet on the device, or
+ * null if no vlan assignment was found and this instance is not
+ * the master for the device.
*/
- public GroupKey getGroupKey(NeighborSet ns) {
- for (DefaultGroupHandler groupHandler : groupHandlerMap.values()) {
- return groupHandler.getGroupKey(ns);
+ public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
+ VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
+ deviceId, subnet));
+ if (assignedVid != null) {
+ log.debug("Query for subnet:{} on device:{} returned assigned-vlan "
+ + "{}", subnet, deviceId, assignedVid);
+ return assignedVid;
+ }
+ //check mastership for the right to assign a vlan
+ if (!mastershipService.isLocalMaster(deviceId)) {
+ log.warn("This controller instance is not the master for device {}. "
+ + "Cannot assign vlan-id for subnet {}", deviceId, subnet);
+ return null;
+ }
+ // vlan assignment is expensive but done only once
+ Set<Ip4Prefix> configuredSubnets = deviceConfiguration.getSubnets(deviceId);
+ Set<Short> assignedVlans = new HashSet<>();
+ Set<Ip4Prefix> unassignedSubnets = new HashSet<>();
+ for (Ip4Prefix sub : configuredSubnets) {
+ VlanId v = subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId,
+ sub));
+ if (v != null) {
+ assignedVlans.add(v.toShort());
+ } else {
+ unassignedSubnets.add(sub);
+ }
+ }
+ short nextAssignedVlan = ASSIGNED_VLAN_START;
+ if (!assignedVlans.isEmpty()) {
+ nextAssignedVlan = (short) (Collections.min(assignedVlans) - 1);
+ }
+ for (Ip4Prefix unsub : unassignedSubnets) {
+ subnetVidStore.put(new SubnetAssignedVidStoreKey(deviceId, unsub),
+ VlanId.vlanId(nextAssignedVlan--));
+ log.info("Assigned vlan: {} to subnet: {} on device: {}",
+ nextAssignedVlan + 1, unsub, deviceId);
}
- return null;
+ return subnetVidStore.get(new SubnetAssignedVidStoreKey(deviceId, subnet));
}
/**
- * Returns the next objective ID for the NeighborSet given. If the nextObjectiveID does not exist,
- * a new one is created and returned.
+ * Returns the next objective ID for the given NeighborSet.
+ * If the nextObjectiveID does not exist, a new one is created and returned.
*
* @param deviceId Device ID
* @param ns NegighborSet
@@ -329,6 +420,25 @@ public class SegmentRoutingManager implements SegmentRoutingService {
}
}
+ /**
+ * Returns the next objective ID for the Subnet given. If the nextObjectiveID does not exist,
+ * a new one is created and returned.
+ *
+ * @param deviceId Device ID
+ * @param prefix Subnet
+ * @return next objective ID
+ */
+ public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
+ if (groupHandlerMap.get(deviceId) != null) {
+ log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
+ return groupHandlerMap
+ .get(deviceId).getSubnetNextObjectiveId(prefix);
+ } else {
+ log.warn("getSubnetNextObjectiveId query in device {} not found", deviceId);
+ return -1;
+ }
+ }
+
private class InternalPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
@@ -423,6 +533,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
if (deviceService.isAvailable(((Device) event.subject()).id())) {
+ log.info("Processing device event {} for available device {}",
+ event.type(), ((Device) event.subject()).id());
processDeviceAdded((Device) event.subject());
}
} else if (event.type() == DeviceEvent.Type.PORT_REMOVED) {
@@ -484,20 +596,31 @@ public class SegmentRoutingManager implements SegmentRoutingService {
private void processDeviceAdded(Device device) {
log.debug("A new device with ID {} was added", device.id());
- //Irrespective whether the local is a MASTER or not for this device,
- //create group handler instance and push default TTP flow rules.
- //Because in a multi-instance setup, instances can initiate
- //groups for any devices. Also the default TTP rules are needed
- //to be pushed before inserting any IP table entries for any device
- DefaultGroupHandler dgh = DefaultGroupHandler.
+ // Irrespective of whether the local is a MASTER or not for this device,
+ // we need to create a SR-group-handler instance. This is because in a
+ // multi-instance setup, any instance can initiate forwarding/next-objectives
+ // for any switch (even if this instance is a SLAVE or not even connected
+ // to the switch). To handle this, a default-group-handler instance is necessary
+ // per switch.
+ DefaultGroupHandler groupHandler = DefaultGroupHandler.
createGroupHandler(device.id(),
appId,
deviceConfiguration,
linkService,
flowObjectiveService,
- nsNextObjStore);
- groupHandlerMap.put(device.id(), dgh);
- defaultRoutingHandler.populateTtpRules(device.id());
+ nsNextObjStore,
+ subnetNextObjStore);
+ groupHandlerMap.put(device.id(), groupHandler);
+
+ // Also, in some cases, drivers may need extra
+ // information to process rules (eg. Router IP/MAC); and so, we send
+ // port addressing rules to the driver as well irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+
+ if (mastershipService.isLocalMaster(device.id())) {
+ groupHandler.createGroupsFromSubnetConfig();
+ }
}
private void processPortRemoved(Device device, Port port) {
@@ -531,18 +654,29 @@ public class SegmentRoutingManager implements SegmentRoutingService {
tunnelHandler, policyStore);
for (Device device : deviceService.getDevices()) {
- //Irrespective whether the local is a MASTER or not for this device,
- //create group handler instance and push default TTP flow rules.
- //Because in a multi-instance setup, instances can initiate
- //groups for any devices. Also the default TTP rules are needed
- //to be pushed before inserting any IP table entries for any device
+ // Irrespective of whether the local is a MASTER or not for this device,
+ // we need to create a SR-group-handler instance. This is because in a
+ // multi-instance setup, any instance can initiate forwarding/next-objectives
+ // for any switch (even if this instance is a SLAVE or not even connected
+ // to the switch). To handle this, a default-group-handler instance is necessary
+ // per switch.
DefaultGroupHandler groupHandler = DefaultGroupHandler
.createGroupHandler(device.id(), appId,
deviceConfiguration, linkService,
flowObjectiveService,
- nsNextObjStore);
+ nsNextObjStore,
+ subnetNextObjStore);
groupHandlerMap.put(device.id(), groupHandler);
- defaultRoutingHandler.populateTtpRules(device.id());
+
+ // Also, in some cases, drivers may need extra
+ // information to process rules (eg. Router IP/MAC); and so, we send
+ // port addressing rules to the driver as well, irrespective of whether
+ // this instance is the master or not.
+ defaultRoutingHandler.populatePortAddressingRules(device.id());
+
+ if (mastershipService.isLocalMaster(device.id())) {
+ groupHandler.createGroupsFromSubnetConfig();
+ }
}
defaultRoutingHandler.startPopulationProcess();
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java
new file mode 100644
index 00000000..84b44c97
--- /dev/null
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SubnetAssignedVidStoreKey.java
@@ -0,0 +1,66 @@
+package org.onosproject.segmentrouting;
+
+import java.util.Objects;
+
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.net.DeviceId;
+
+/**
+ * Class definition for key used to map per device subnets to assigned Vlan ids.
+ *
+ */
+public class SubnetAssignedVidStoreKey {
+ private final DeviceId deviceId;
+ private final Ip4Prefix subnet;
+
+ public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) {
+ this.deviceId = deviceId;
+ this.subnet = subnet;
+ }
+
+ /**
+ * Returns the device identification used to create this key.
+ *
+ * @return the device identifier
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Returns the subnet information used to create this key.
+ *
+ * @return the subnet
+ */
+ public Ip4Prefix subnet() {
+ return subnet;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof SubnetAssignedVidStoreKey)) {
+ return false;
+ }
+ SubnetAssignedVidStoreKey that =
+ (SubnetAssignedVidStoreKey) o;
+ return (Objects.equals(this.deviceId, that.deviceId) &&
+ Objects.equals(this.subnet, that.subnet));
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 17;
+ result = 31 * result + Objects.hashCode(deviceId)
+ + Objects.hashCode(subnet);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Device: " + deviceId + " Subnet: " + subnet;
+ }
+
+}
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 c960adca..a5c1090f 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
@@ -52,9 +52,12 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
LinkService linkService,
FlowObjectiveService flowObjService,
EventuallyConsistentMap<
- NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore) {
- super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
+ NeighborSetNextObjectiveStoreKey,
+ Integer> nsNextObjStore,
+ EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
+ Integer> subnetNextObjStore) {
+ super(deviceId, appId, config, linkService, flowObjService,
+ nsNextObjStore, subnetNextObjStore);
}
@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 9bbde2f3..69a0d86f 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
@@ -25,10 +25,11 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.util.KryoNamespace;
@@ -74,7 +75,8 @@ public class DefaultGroupHandler {
// new HashMap<NeighborSet, Integer>();
protected EventuallyConsistentMap<
NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null;
- protected Random rand = new Random();
+ protected EventuallyConsistentMap<
+ SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null;
protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
.register(URI.class).register(HashSet.class)
@@ -89,8 +91,10 @@ public class DefaultGroupHandler {
LinkService linkService,
FlowObjectiveService flowObjService,
EventuallyConsistentMap<
- NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore) {
+ NeighborSetNextObjectiveStoreKey,
+ Integer> nsNextObjStore,
+ EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
+ Integer> subnetNextObjStore) {
this.deviceId = checkNotNull(deviceId);
this.appId = checkNotNull(appId);
this.deviceConfig = checkNotNull(config);
@@ -101,6 +105,7 @@ public class DefaultGroupHandler {
nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
this.flowObjectiveService = flowObjService;
this.nsNextObjStore = nsNextObjStore;
+ this.subnetNextObjStore = subnetNextObjStore;
populateNeighborMaps();
}
@@ -115,7 +120,8 @@ public class DefaultGroupHandler {
* @param config interface to retrieve the device properties
* @param linkService link service object
* @param flowObjService flow objective service object
- * @param nsNextObjStore next objective store map
+ * @param nsNextObjStore NeighborSet next objective store map
+ * @param subnetNextObjStore subnet next objective store map
* @return default group handler type
*/
public static DefaultGroupHandler createGroupHandler(DeviceId deviceId,
@@ -123,18 +129,23 @@ public class DefaultGroupHandler {
DeviceProperties config,
LinkService linkService,
FlowObjectiveService flowObjService,
- EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore) {
+ EventuallyConsistentMap<
+ NeighborSetNextObjectiveStoreKey,
+ Integer> nsNextObjStore,
+ EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
+ Integer> subnetNextObjStore) {
if (config.isEdgeDevice(deviceId)) {
return new DefaultEdgeGroupHandler(deviceId, appId, config,
linkService,
flowObjService,
- nsNextObjStore);
+ nsNextObjStore,
+ subnetNextObjStore);
} else {
return new DefaultTransitGroupHandler(deviceId, appId, config,
linkService,
flowObjService,
- nsNextObjStore);
+ nsNextObjStore,
+ subnetNextObjStore);
}
}
@@ -323,6 +334,21 @@ public class DefaultGroupHandler {
}
/**
+ * Returns the next objective associated with the subnet.
+ * If there is no next objective for this subnet, this API
+ * would create a next objective and return.
+ *
+ * @param prefix subnet information
+ * @return int if found or -1
+ */
+ public int getSubnetNextObjectiveId(IpPrefix prefix) {
+ Integer nextId = subnetNextObjStore.
+ get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
+
+ return (nextId != null) ? nextId : -1;
+ }
+
+ /**
* Checks if the next objective ID (group) for the neighbor set exists or not.
*
* @param ns neighbor set to check
@@ -486,6 +512,43 @@ public class DefaultGroupHandler {
}
}
+ 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 =
+ new SubnetNextObjectiveStoreKey(deviceId, subnet);
+
+ if (subnetNextObjStore.containsKey(key)) {
+ log.debug("Broadcast group for device {} and subnet {} exists",
+ deviceId, subnet);
+ return;
+ }
+
+ int nextId = flowObjectiveService.allocateNextId();
+
+ NextObjective.Builder nextObjBuilder = DefaultNextObjective
+ .builder().withId(nextId)
+ .withType(NextObjective.Type.BROADCAST).fromApp(appId);
+
+ ports.forEach(port -> {
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ tBuilder.setOutput(port);
+ nextObjBuilder.addTreatment(tBuilder.build());
+ });
+
+ NextObjective nextObj = nextObjBuilder.add();
+ flowObjectiveService.next(deviceId, nextObj);
+ log.debug("createGroupFromSubnetConfig: Submited "
+ + "next objective {} in device {}",
+ nextId, deviceId);
+
+ subnetNextObjStore.put(key, nextId);
+ });
+ }
+
public GroupKey getGroupKey(Object obj) {
return new DefaultGroupKey(kryo.build().serialize(obj));
}
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 3cb73aba..b009e869 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
@@ -45,9 +45,12 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
LinkService linkService,
FlowObjectiveService flowObjService,
EventuallyConsistentMap<
- NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore) {
- super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
+ NeighborSetNextObjectiveStoreKey,
+ Integer> nsNextObjStore,
+ EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
+ Integer> subnetNextObjStore) {
+ super(deviceId, appId, config, linkService, flowObjService,
+ nsNextObjStore, subnetNextObjStore);
}
@Override
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java
index 497f5256..d28d38d5 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DeviceProperties.java
@@ -16,9 +16,12 @@
package org.onosproject.segmentrouting.grouphandler;
import java.util.List;
+import java.util.Map;
+import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
/**
* Mechanism through which group handler module retrieves
@@ -33,6 +36,7 @@ public interface DeviceProperties {
* @return segment id of a device
*/
int getSegmentId(DeviceId deviceId);
+
/**
* Returns the Mac address of a device to be used in group creation.
*
@@ -40,6 +44,7 @@ public interface DeviceProperties {
* @return mac address of a device
*/
MacAddress getDeviceMac(DeviceId deviceId);
+
/**
* Indicates whether a device is edge device or transit/core device.
*
@@ -47,6 +52,7 @@ public interface DeviceProperties {
* @return boolean
*/
boolean isEdgeDevice(DeviceId deviceId);
+
/**
* Returns all segment IDs to be considered in building auto
*
@@ -54,4 +60,16 @@ public interface DeviceProperties {
* @return list of segment IDs
*/
List<Integer> getAllDeviceSegmentIds();
+
+ /**
+ * Returns subnet-to-ports mapping of given device.
+ *
+ * For each entry of the map
+ * Key: a subnet
+ * Value: a list of ports, which are bound to the subnet
+ *
+ * @param deviceId device identifier
+ * @return a map that contains all subnet-to-ports mapping of given device
+ */
+ Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId);
}
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
index e7e87839..e47a6625 100644
--- a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/PolicyGroupHandler.java
@@ -54,7 +54,8 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
* @param config interface to retrieve the device properties
* @param linkService link service object
* @param flowObjService flow objective service object
- * @param nsNextObjStore next objective store map
+ * @param nsNextObjStore NeighborSet next objective store map
+ * @param subnetNextObjStore subnet next objective store map
*/
public PolicyGroupHandler(DeviceId deviceId,
ApplicationId appId,
@@ -62,8 +63,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
LinkService linkService,
FlowObjectiveService flowObjService,
EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
- Integer> nsNextObjStore) {
- super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore);
+ Integer> nsNextObjStore,
+ EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
+ Integer> subnetNextObjStore) {
+ super(deviceId, appId, config, linkService, flowObjService,
+ nsNextObjStore, subnetNextObjStore);
}
public PolicyGroupIdentifier createPolicyGroupChain(String id,
diff --git a/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java
new file mode 100644
index 00000000..d6b16c7a
--- /dev/null
+++ b/framework/src/onos/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/SubnetNextObjectiveStoreKey.java
@@ -0,0 +1,78 @@
+/*
+ * 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.segmentrouting.grouphandler;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.net.DeviceId;
+
+import java.util.Objects;
+
+/**
+ * Class definition of Key for Subnet to NextObjective store.
+ */
+public class SubnetNextObjectiveStoreKey {
+ private final DeviceId deviceId;
+ private final IpPrefix prefix;
+
+ public SubnetNextObjectiveStoreKey(DeviceId deviceId,
+ IpPrefix prefix) {
+ this.deviceId = deviceId;
+ this.prefix = prefix;
+ }
+
+ /**
+ * Gets device id in this SubnetNextObjectiveStoreKey.
+ *
+ * @return device id
+ */
+ public DeviceId deviceId() {
+ return this.deviceId;
+ }
+
+ /**
+ * Gets subnet information in this SubnetNextObjectiveStoreKey.
+ *
+ * @return subnet information
+ */
+ public IpPrefix prefix() {
+ return this.prefix;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof SubnetNextObjectiveStoreKey)) {
+ return false;
+ }
+ SubnetNextObjectiveStoreKey that =
+ (SubnetNextObjectiveStoreKey) o;
+ return (Objects.equals(this.deviceId, that.deviceId) &&
+ Objects.equals(this.prefix, that.prefix));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deviceId, prefix);
+ }
+
+ @Override
+ public String toString() {
+ return "Device: " + deviceId + " Subnet: " + prefix;
+ }
+}
diff --git a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestAddCommand.java b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestAddCommand.java
index 204471c2..2d1aa0b8 100644
--- a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestAddCommand.java
+++ b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestAddCommand.java
@@ -23,7 +23,7 @@ import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
-import java.util.HashSet;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -44,7 +44,6 @@ public class SetTestAddCommand extends AbstractShellCommand {
String[] values = null;
Set<String> set;
- Set<String> toAdd = new HashSet<>();
Serializer serializer = Serializer.using(
@@ -68,13 +67,10 @@ public class SetTestAddCommand extends AbstractShellCommand {
}
} else if (values.length >= 1) {
// Add multiple elements to a set
- for (String value : values) {
- toAdd.add(value);
- }
- if (set.addAll(toAdd)) {
- print("%s was added to the set %s", toAdd, setName);
+ if (set.addAll(Arrays.asList(values))) {
+ print("%s was added to the set %s", Arrays.asList(values), setName);
} else {
- print("%s was already in set %s", toAdd, setName);
+ print("%s was already in set %s", Arrays.asList(values), setName);
}
}
}
diff --git a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestGetCommand.java b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestGetCommand.java
index fb36a06a..74c52c16 100644
--- a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestGetCommand.java
+++ b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestGetCommand.java
@@ -24,7 +24,7 @@ import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
-import java.util.HashSet;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -49,7 +49,6 @@ public class SetTestGetCommand extends AbstractShellCommand {
String[] values = null;
Set<String> set;
- Set<String> toCheck = new HashSet<>();
String output = "";
Serializer serializer = Serializer.using(
@@ -95,13 +94,10 @@ public class SetTestGetCommand extends AbstractShellCommand {
}
} else if (values.length > 1) {
//containsAll
- for (String value : values) {
- toCheck.add(value);
- }
- if (set.containsAll(toCheck)) {
- print("Set %s contains the the subset %s", setName, toCheck);
+ if (set.containsAll(Arrays.asList(values))) {
+ print("Set %s contains the the subset %s", setName, Arrays.asList(values));
} else {
- print("Set %s did not contain the the subset %s", setName, toCheck);
+ print("Set %s did not contain the the subset %s", setName, Arrays.asList(values));
}
}
}
diff --git a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestRemoveCommand.java b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestRemoveCommand.java
index d1f81e42..1fa073f3 100644
--- a/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestRemoveCommand.java
+++ b/framework/src/onos/apps/test/distributed-primitives/src/main/java/org/onosproject/distributedprimitives/cli/SetTestRemoveCommand.java
@@ -24,7 +24,7 @@ import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
-import java.util.HashSet;
+import java.util.Arrays;
import java.util.Set;
/**
@@ -54,7 +54,6 @@ public class SetTestRemoveCommand extends AbstractShellCommand {
String[] values = null;
Set<String> set;
- Set<String> givenValues = new HashSet<>();
Serializer serializer = Serializer.using(
new KryoNamespace.Builder().register(KryoNamespaces.BASIC).build());
@@ -79,13 +78,10 @@ public class SetTestRemoveCommand extends AbstractShellCommand {
}
if (retain) { // Keep only the given values
- for (String value : values) {
- givenValues.add(value);
- }
- if (set.retainAll(givenValues)) {
- print("%s was pruned to contain only elements of set %s", setName, givenValues);
+ if (set.retainAll(Arrays.asList(values))) {
+ print("%s was pruned to contain only elements of set %s", setName, Arrays.asList(values));
} else {
- print("%s was not changed by retaining only elements of the set %s", setName, givenValues);
+ print("%s was not changed by retaining only elements of the set %s", setName, Arrays.asList(values));
}
} else if (values.length == 1) {
// Remove a single element from the set
@@ -94,15 +90,12 @@ public class SetTestRemoveCommand extends AbstractShellCommand {
} else {
print("[%s] was not in set %s", values[0], setName);
}
- } else if (values.length >= 1) {
+ } else if (values.length > 1) {
// Remove multiple elements from a set
- for (String value : values) {
- givenValues.add(value);
- }
- if (set.removeAll(givenValues)) {
- print("%s was removed from the set %s", givenValues, setName);
+ if (set.removeAll(Arrays.asList(values))) {
+ print("%s was removed from the set %s", Arrays.asList(values), setName);
} else {
- print("No element of %s was in set %s", givenValues, setName);
+ print("No element of %s was in set %s", Arrays.asList(values), setName);
}
}
}
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/ConnectPointConfiguration.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/ConnectPointConfiguration.java
new file mode 100644
index 00000000..ff516d71
--- /dev/null
+++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/ConnectPointConfiguration.java
@@ -0,0 +1,55 @@
+/*
+ * 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.virtualbng;
+
+import org.onosproject.net.ConnectPoint;
+
+/**
+ * Configuration for a connect point.
+ */
+public class ConnectPointConfiguration {
+
+ private ConnectPoint connectPoint;
+
+ /**
+ * Creats a new connect point from a string representation.
+ *
+ * @param string connect point string
+ */
+ public ConnectPointConfiguration(String string) {
+ connectPoint = ConnectPoint.deviceConnectPoint(string);
+ }
+
+ /**
+ * Creates a new connect point from a string representation.
+ *
+ * @param string connect point string
+ * @return new connect point configuration
+ */
+ public static ConnectPointConfiguration of(String string) {
+ return new ConnectPointConfiguration(string);
+ }
+
+ /**
+ * Gets the connect point.
+ *
+ * @return connect point
+ */
+ public ConnectPoint connectPoint() {
+ return connectPoint;
+ }
+}
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfiguration.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfiguration.java
index ee2cbeaa..1841675f 100644
--- a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfiguration.java
+++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfiguration.java
@@ -17,13 +17,15 @@ package org.onosproject.virtualbng;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-
-import java.util.Collections;
-import java.util.List;
-
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
/**
* Contains the configuration data for virtual BNG that has been read from a
@@ -36,6 +38,7 @@ public final class VbngConfiguration {
private final MacAddress publicFacingMac;
private final IpAddress xosIpAddress;
private final int xosRestPort;
+ private final Map<String, ConnectPointConfiguration> hosts;
/**
* Default constructor.
@@ -46,6 +49,7 @@ public final class VbngConfiguration {
publicFacingMac = null;
xosIpAddress = null;
xosRestPort = 0;
+ hosts = null;
}
/**
@@ -57,6 +61,7 @@ public final class VbngConfiguration {
* public IP addresses
* @param xosIpAddress the XOS server IP address
* @param xosRestPort the port of the XOS server for REST
+ * @param hosts map of hosts
*/
@JsonCreator
public VbngConfiguration(@JsonProperty("localPublicIpPrefixes")
@@ -68,12 +73,15 @@ public final class VbngConfiguration {
@JsonProperty("xosIpAddress")
IpAddress xosIpAddress,
@JsonProperty("xosRestPort")
- int xosRestPort) {
+ int xosRestPort,
+ @JsonProperty("hosts")
+ Map<String, ConnectPointConfiguration> hosts) {
localPublicIpPrefixes = prefixes;
this.nextHopIpAddress = nextHopIpAddress;
this.publicFacingMac = publicFacingMac;
this.xosIpAddress = xosIpAddress;
this.xosRestPort = xosRestPort;
+ this.hosts = hosts;
}
/**
@@ -120,4 +128,13 @@ public final class VbngConfiguration {
public int getXosRestPort() {
return xosRestPort;
}
+
+ public Map<String, ConnectPoint> getHosts() {
+ return hosts.entrySet()
+ .stream()
+ .collect(Collectors.toMap(
+ e -> e.getKey(),
+ e -> e.getValue().connectPoint()
+ ));
+ }
}
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
index d27d6904..eb83e06c 100644
--- a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
+++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
@@ -16,16 +16,6 @@
package org.onosproject.virtualbng;
import com.fasterxml.jackson.databind.ObjectMapper;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -33,9 +23,19 @@ import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
/**
* Implementation of ConfigurationService which reads virtual BNG
* configuration from a file.
@@ -63,6 +63,7 @@ public class VbngConfigurationManager implements VbngConfigurationService {
private MacAddress macOfPublicIpAddresses;
private IpAddress xosIpAddress;
private int xosRestPort;
+ private Map<String, ConnectPoint> nodeToPort;
@Activate
public void activate() {
@@ -104,6 +105,8 @@ public class VbngConfigurationManager implements VbngConfigurationService {
macOfPublicIpAddresses = config.getPublicFacingMac();
xosIpAddress = config.getXosIpAddress();
xosRestPort = config.getXosRestPort();
+ nodeToPort = config.getHosts();
+
} catch (FileNotFoundException e) {
log.warn("Configuration file not found: {}", configFileName);
@@ -132,6 +135,11 @@ public class VbngConfigurationManager implements VbngConfigurationService {
return xosRestPort;
}
+ @Override
+ public Map<String, ConnectPoint> getNodeToPort() {
+ return nodeToPort;
+ }
+
// TODO handle the case: the number of public IP addresses is not enough
// for 1:1 mapping from public IP to private IP.
@Override
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
index ef8698a0..68c048f4 100644
--- a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
+++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationService.java
@@ -15,10 +15,11 @@
*/
package org.onosproject.virtualbng;
-import java.util.Map;
-
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+
+import java.util.Map;
/**
* Provides information about the virtual BNG configuration.
@@ -54,6 +55,13 @@ public interface VbngConfigurationService {
int getXosRestPort();
/**
+ * Gets the host to port map.
+ *
+ * @return host to port map
+ */
+ Map<String, ConnectPoint> getNodeToPort();
+
+ /**
* Evaluates whether an IP address is an assigned public IP address.
*
* @param ipAddress the IP address to evaluate
diff --git a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
index 5e82b7e8..e03b25e8 100644
--- a/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
+++ b/framework/src/onos/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngManager.java
@@ -15,18 +15,9 @@
*/
package org.onosproject.virtualbng;
-import static com.google.common.base.Preconditions.checkNotNull;
-
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.Maps;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ConcurrentHashMap;
-
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -42,7 +33,6 @@ import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
-import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
@@ -56,6 +46,13 @@ import org.onosproject.net.intent.PointToPointIntent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* This is a virtual Broadband Network Gateway (BNG) application. It mainly
* has 3 functions:
@@ -111,9 +108,8 @@ public class VbngManager implements VbngService {
p2pIntentsToHost = new ConcurrentHashMap<>();
privateIpAddressMap = new ConcurrentHashMap<>();
- setupMap();
-
nextHopIpAddress = vbngConfigurationService.getNextHopIpAddress();
+ nodeToPort = vbngConfigurationService.getNodeToPort();
hostListener = new InternalHostListener();
hostService.addListener(hostListener);
@@ -136,10 +132,16 @@ public class VbngManager implements VbngService {
*/
private void statusRecovery() {
log.info("vBNG starts to recover from XOS record......");
- RestClient restClient =
- new RestClient(vbngConfigurationService.getXosIpAddress(),
- vbngConfigurationService.getXosRestPort());
- ObjectNode map = restClient.getRest();
+ ObjectNode map;
+ try {
+ RestClient restClient =
+ new RestClient(vbngConfigurationService.getXosIpAddress(),
+ vbngConfigurationService.getXosRestPort());
+ map = restClient.getRest();
+ } catch (Exception e) {
+ log.error("Could not contact XOS", e);
+ return;
+ }
if (map == null) {
log.info("Stop to recover vBNG status due to the vBNG map "
+ "is null!");
@@ -168,21 +170,6 @@ public class VbngManager implements VbngService {
}
/**
- * Sets up mapping from hostname to connect point.
- */
- private void setupMap() {
- nodeToPort = Maps.newHashMap();
-
- nodeToPort.put("cordcompute01.onlab.us",
- new ConnectPoint(FABRIC_DEVICE_ID,
- PortNumber.portNumber(48)));
-
- nodeToPort.put("cordcompute02.onlab.us",
- new ConnectPoint(FABRIC_DEVICE_ID,
- PortNumber.portNumber(47)));
- }
-
- /**
* Creates a new vBNG.
*
* @param privateIpAddress a private IP address
diff --git a/framework/src/onos/apps/vtn/pom.xml b/framework/src/onos/apps/vtn/pom.xml
index c2cfe2be..e91b0c9b 100644
--- a/framework/src/onos/apps/vtn/pom.xml
+++ b/framework/src/onos/apps/vtn/pom.xml
@@ -37,4 +37,21 @@
<module>vtnweb</module>
<module>app</module>
</modules>
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava-testlib</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/SfcService.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/SfcService.java
new file mode 100644
index 00000000..a2748f5e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/SfcService.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import org.onosproject.vtnrsc.PortChain;
+
+/**
+ * SFC application that applies flows to the device.
+ */
+public interface SfcService {
+ /**
+ * Applies flow classification to OVS.
+ *
+ * @param portChain Port-Chain.
+ */
+ void InstallFlowClassification(PortChain portChain);
+
+
+ /**
+ * Remove flow classification from OVS.
+ *
+ * @param portChain Port-Chain.
+ */
+ void UnInstallFlowClassification(PortChain portChain);
+
+ /**
+ * Applies Service Function chain to OVS.
+ *
+ * @param portChain Port-Chain.
+ */
+ void InstallServiceFunctionChain(PortChain portChain);
+
+ /**
+ * Remove Service Function chain from OVS.
+ *
+ * @param portChain Port-Chain.
+ */
+ void UnInstallServiceFunctionChain(PortChain portChain);
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/SfcManager.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/SfcManager.java
new file mode 100644
index 00000000..1872295f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/SfcManager.java
@@ -0,0 +1,69 @@
+/*
+ * 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.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.vtnrsc.sfc.PortChain;
+import org.slf4j.Logger;
+
+/**
+ * Provides implementation of SFC Service.
+ */
+@Component(immediate = true)
+@Service
+public class SfcManager implements SfcService {
+
+ private final Logger log = getLogger(SfcManager.class);
+
+ @Activate
+ public void activate() {
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void InstallFlowClassification(PortChain portChain) {
+ log.debug("InstallFlowClassification");
+ //TODO: Installation of flow classification into OVS.
+ }
+
+ @Override
+ public void UnInstallFlowClassification(PortChain portChain) {
+ log.debug("UnInstallFlowClassification");
+ //TODO: Un-installation flow classification from OVS
+ }
+
+ @Override
+ public void InstallServiceFunctionChain(PortChain portChain) {
+ log.debug("InstallServiceFunctionChain");
+ //TODO: Installation of Service Function chain into OVS.
+ }
+
+ @Override
+ public void UnInstallServiceFunctionChain(PortChain portChain) {
+ log.debug("UnInstallServiceFunctionChain");
+ //TODO: Un-installation of Service Function chain from OVS.
+ }
+}
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/impl/package-info.java
new file mode 100644
index 00000000..0dba868c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/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.impl;
diff --git a/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/package-info.java b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/package-info.java
new file mode 100644
index 00000000..1dcb9929
--- /dev/null
+++ b/framework/src/onos/apps/vtn/sfcmgr/src/main/java/org/onosproject/sfc/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;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
new file mode 100644
index 00000000..39df2cff
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultFlowClassifier.java
@@ -0,0 +1,413 @@
+/*
+ * 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.Objects;
+import org.onlab.packet.IpPrefix;
+
+import com.google.common.base.MoreObjects;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Provides Default flow classifier.
+ */
+public final class DefaultFlowClassifier 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;
+ private static final int NULL_PORT = 0;
+ private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "FlowClassifier id can not be null.";
+ private static final String TENANT_ID_NOT_NULL = "Tenant id can not be null.";
+
+ /**
+ * Constructor to create default flow classifier.
+ *
+ * @param flowClassifierId flow classifier Id
+ * @param tenantId Tenant ID
+ * @param name flow classifier name
+ * @param description flow classifier description
+ * @param etherType etherType
+ * @param protocol IP protocol
+ * @param minSrcPortRange Minimum Source port range
+ * @param maxSrcPortRange Maximum Source port range
+ * @param minDstPortRange Minimum destination port range
+ * @param maxDstPortRange Maximum destination port range
+ * @param srcIpPrefix Source IP prefix
+ * @param dstIpPrefix destination IP prefix
+ * @param srcPort Source VirtualPort
+ * @param dstPort destination VirtualPort
+ */
+ private DefaultFlowClassifier(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;
+ }
+
+ /**
+ * Builder class for constructing Flow classifier.
+ */
+ public static class Builder implements FlowClassifier.Builder {
+
+ private FlowClassifierId flowClassifierId;
+ private TenantId tenantId;
+ private String name;
+ private boolean isFlowClassifierNameSet = false;
+ private String description;
+ private boolean isFlowClassifierDescriptionSet = false;
+ private String etherType;
+ private boolean isEtherTypeSet = false;
+ private String protocol;
+ private boolean isProtocolSet = false;
+ private int minSrcPortRange;
+ private boolean isMinSrcPortRangeSet = false;
+ private int maxSrcPortRange;
+ private boolean isMaxSrcPortRangeSet = false;
+ private int minDstPortRange;
+ private boolean isMinDstPortRangeSet = false;
+ private int maxDstPortRange;
+ private boolean isMaxDstPortRangeSet = false;
+ private IpPrefix srcIpPrefix;
+ private boolean isSrcIpPrefixSet = false;
+ private IpPrefix dstIpPrefix;
+ private boolean isDstIpPrefixSet = false;
+ private VirtualPortId srcPort;
+ private boolean isSrcPortSet = false;
+ private VirtualPortId dstPort;
+ private boolean isDstPortSet = false;
+
+ @Override
+ public FlowClassifier build() {
+
+ checkNotNull(flowClassifierId, FLOW_CLASSIFIER_ID_NOT_NULL);
+ checkNotNull(tenantId, TENANT_ID_NOT_NULL);
+ String name = null;
+ String description = null;
+ String etherType = null;
+ String protocol = null;
+ int minSrcPortRange = NULL_PORT;
+ int maxSrcPortRange = NULL_PORT;
+ int minDstPortRange = NULL_PORT;
+ int maxDstPortRange = NULL_PORT;
+ IpPrefix srcIpPrefix = null;
+ IpPrefix dstIpPrefix = null;
+ VirtualPortId srcPort = null;
+ VirtualPortId dstPort = null;
+
+ if (isFlowClassifierNameSet) {
+ name = this.name;
+ }
+ if (isFlowClassifierDescriptionSet) {
+ description = this.description;
+ }
+ if (isEtherTypeSet) {
+ etherType = this.etherType;
+ }
+ if (isProtocolSet) {
+ protocol = this.protocol;
+ }
+ if (isMinSrcPortRangeSet) {
+ minSrcPortRange = this.minSrcPortRange;
+ }
+ if (isMaxSrcPortRangeSet) {
+ maxSrcPortRange = this.maxSrcPortRange;
+ }
+ if (isMinDstPortRangeSet) {
+ minDstPortRange = this.minDstPortRange;
+ }
+ if (isMaxDstPortRangeSet) {
+ maxDstPortRange = this.maxDstPortRange;
+ }
+ if (isSrcIpPrefixSet) {
+ srcIpPrefix = this.srcIpPrefix;
+ }
+ if (isDstIpPrefixSet) {
+ dstIpPrefix = this.dstIpPrefix;
+ }
+ if (isSrcPortSet) {
+ srcPort = this.srcPort;
+ }
+ if (isDstPortSet) {
+ dstPort = this.dstPort;
+ }
+
+ return new DefaultFlowClassifier(flowClassifierId, tenantId, name, description, etherType, protocol,
+ minSrcPortRange, maxSrcPortRange, minDstPortRange, maxDstPortRange, srcIpPrefix, dstIpPrefix,
+ srcPort, dstPort);
+ }
+
+ @Override
+ public Builder setFlowClassifierId(FlowClassifierId flowClassifierId) {
+ this.flowClassifierId = flowClassifierId;
+ return this;
+ }
+
+ @Override
+ public Builder setTenantId(TenantId tenantId) {
+ this.tenantId = tenantId;
+ return this;
+ }
+
+ @Override
+ public Builder setName(String name) {
+ this.name = name;
+ this.isFlowClassifierNameSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setDescription(String description) {
+ this.description = description;
+ this.isFlowClassifierDescriptionSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setEtherType(String etherType) {
+ this.etherType = etherType;
+ this.isEtherTypeSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setProtocol(String protocol) {
+ this.protocol = protocol;
+ this.isProtocolSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setMinSrcPortRange(int minSrcPortRange) {
+ this.minSrcPortRange = minSrcPortRange;
+ this.isMinSrcPortRangeSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setMaxSrcPortRange(int maxSrcPortRange) {
+ this.maxSrcPortRange = maxSrcPortRange;
+ this.isMaxSrcPortRangeSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setMinDstPortRange(int minDstPortRange) {
+ this.minDstPortRange = minDstPortRange;
+ this.isMinDstPortRangeSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setMaxDstPortRange(int maxDstPortRange) {
+ this.maxDstPortRange = maxDstPortRange;
+ this.isMaxDstPortRangeSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setSrcIpPrefix(IpPrefix srcIpPrefix) {
+ this.srcIpPrefix = srcIpPrefix;
+ this.isSrcIpPrefixSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setDstIpPrefix(IpPrefix dstIpPrefix) {
+ this.dstIpPrefix = dstIpPrefix;
+ this.isDstIpPrefixSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setSrcPort(VirtualPortId srcPort) {
+ this.srcPort = srcPort;
+ this.isSrcPortSet = true;
+ return this;
+ }
+
+ @Override
+ public Builder setDstPort(VirtualPortId dstPort) {
+ this.dstPort = dstPort;
+ this.isDstPortSet = true;
+ return this;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(flowClassifierId, tenantId, name, description, etherType, protocol, minSrcPortRange,
+ maxSrcPortRange, minDstPortRange, maxDstPortRange, srcIpPrefix, dstIpPrefix, srcPort, dstPort);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultFlowClassifier) {
+ DefaultFlowClassifier other = (DefaultFlowClassifier) obj;
+ return Objects.equals(this.flowClassifierId, other.flowClassifierId)
+ && Objects.equals(this.tenantId, other.tenantId)
+ && Objects.equals(this.name, other.name)
+ && Objects.equals(this.description, other.description)
+ && Objects.equals(this.etherType, other.etherType)
+ && Objects.equals(this.protocol, other.protocol)
+ && Objects.equals(this.minSrcPortRange, other.minSrcPortRange)
+ && Objects.equals(this.maxSrcPortRange, other.maxSrcPortRange)
+ && Objects.equals(this.minDstPortRange, other.minDstPortRange)
+ && Objects.equals(this.maxDstPortRange, other.maxDstPortRange)
+ && Objects.equals(this.srcIpPrefix, other.srcIpPrefix)
+ && Objects.equals(this.dstIpPrefix, other.dstIpPrefix)
+ && Objects.equals(this.srcPort, other.srcPort)
+ && Objects.equals(this.dstPort, other.dstPort);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exactMatch(FlowClassifier flowClassifier) {
+ return this.equals(flowClassifier)
+ && Objects.equals(this.flowClassifierId, flowClassifier.flowClassifierId())
+ && Objects.equals(this.tenantId, flowClassifier.tenantId())
+ && Objects.equals(this.name, flowClassifier.name())
+ && Objects.equals(this.description, flowClassifier.description())
+ && Objects.equals(this.etherType, flowClassifier.etherType())
+ && Objects.equals(this.protocol, flowClassifier.protocol())
+ && Objects.equals(this.minSrcPortRange, flowClassifier.minSrcPortRange())
+ && Objects.equals(this.maxSrcPortRange, flowClassifier.maxSrcPortRange())
+ && Objects.equals(this.minDstPortRange, flowClassifier.minDstPortRange())
+ && Objects.equals(this.maxDstPortRange, flowClassifier.maxDstPortRange())
+ && Objects.equals(this.srcIpPrefix, flowClassifier.srcIpPrefix())
+ && Objects.equals(this.dstIpPrefix, flowClassifier.dstIpPrefix())
+ && Objects.equals(this.srcPort, flowClassifier.srcPort())
+ && Objects.equals(this.dstPort, flowClassifier.dstPort());
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("FlowClassifierId", flowClassifierId)
+ .add("TenantId", tenantId)
+ .add("Name", name)
+ .add("Description", description)
+ .add("String", etherType)
+ .add("Protocol", protocol)
+ .add("MinSrcPortRange", minSrcPortRange)
+ .add("MaxSrcPortRange", maxSrcPortRange)
+ .add("MinDstPortRange", minDstPortRange)
+ .add("MaxDstPortRange", maxDstPortRange)
+ .add("SrcIpPrefix", srcIpPrefix)
+ .add("DstIpPrefix", dstIpPrefix)
+ .add("SrcPort", srcPort)
+ .add("DstPort", dstPort)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
new file mode 100644
index 00000000..89b94b3e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortChain.java
@@ -0,0 +1,201 @@
+/*
+ * 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;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Implementation of port chain.
+ */
+public final class DefaultPortChain implements PortChain {
+
+ private final PortChainId portChainId;
+ private final TenantId tenantId;
+ private final String name;
+ private final String description;
+ private final List<PortPairGroupId> portPairGroupList;
+ private final List<FlowClassifierId> flowClassifierList;
+
+ /**
+ * Default constructor to create port chain.
+ *
+ * @param portChainId port chain id
+ * @param tenantId tenant id
+ * @param name name of port chain
+ * @param description description of port chain
+ * @param portPairGroupList port pair group list
+ * @param flowClassifierList flow classifier list
+ */
+ private DefaultPortChain(PortChainId portChainId, TenantId tenantId,
+ String name, String description,
+ List<PortPairGroupId> portPairGroupList,
+ List<FlowClassifierId> flowClassifierList) {
+
+ this.portChainId = portChainId;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.portPairGroupList = portPairGroupList;
+ this.flowClassifierList = flowClassifierList;
+ }
+
+ @Override
+ public PortChainId portChainId() {
+ return portChainId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public List<PortPairGroupId> portPairGroups() {
+ return ImmutableList.copyOf(portPairGroupList);
+ }
+
+ @Override
+ public List<FlowClassifierId> flowClassifiers() {
+ return ImmutableList.copyOf(flowClassifierList);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(portChainId, tenantId, name, description,
+ portPairGroupList, flowClassifierList);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPortChain) {
+ DefaultPortChain that = (DefaultPortChain) obj;
+ return Objects.equals(portChainId, that.portChainId) &&
+ Objects.equals(tenantId, that.tenantId) &&
+ Objects.equals(name, that.name) &&
+ Objects.equals(description, that.description) &&
+ Objects.equals(portPairGroupList, that.portPairGroupList) &&
+ Objects.equals(flowClassifierList, that.flowClassifierList);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exactMatch(PortChain portChain) {
+ return this.equals(portChain) &&
+ Objects.equals(this.portChainId, portChain.portChainId()) &&
+ Objects.equals(this.tenantId, portChain.tenantId());
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", portChainId.toString())
+ .add("tenantId", tenantId.toString())
+ .add("name", name)
+ .add("description", description)
+ .add("portPairGroupList", portPairGroupList)
+ .add("flowClassifier", flowClassifierList)
+ .toString();
+ }
+
+ /**
+ * To create an instance of the builder.
+ *
+ * @return instance of builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder class for Port chain.
+ */
+ public static final class Builder implements PortChain.Builder {
+
+ private PortChainId portChainId;
+ private TenantId tenantId;
+ private String name;
+ private String description;
+ private List<PortPairGroupId> portPairGroupList;
+ private List<FlowClassifierId> flowClassifierList;
+
+ @Override
+ public Builder setId(PortChainId portChainId) {
+ this.portChainId = portChainId;
+ return this;
+ }
+
+ @Override
+ public Builder setTenantId(TenantId tenantId) {
+ this.tenantId = tenantId;
+ return this;
+ }
+
+ @Override
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Builder setPortPairGroups(List<PortPairGroupId> portPairGroups) {
+ this.portPairGroupList = portPairGroups;
+ return this;
+ }
+
+ @Override
+ public Builder setFlowClassifiers(List<FlowClassifierId> flowClassifiers) {
+ this.flowClassifierList = flowClassifiers;
+ return this;
+ }
+
+ @Override
+ public PortChain build() {
+
+ checkNotNull(portChainId, "Port chain id cannot be null");
+ checkNotNull(tenantId, "Tenant id cannot be null");
+ checkNotNull(portPairGroupList, "Port pair groups cannot be null");
+
+ return new DefaultPortChain(portChainId, tenantId, name, description,
+ portPairGroupList, flowClassifierList);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPair.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPair.java
new file mode 100644
index 00000000..4b3b7cf3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPair.java
@@ -0,0 +1,198 @@
+/*
+ * 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;
+
+/**
+ * Implementation of port pair.
+ */
+public final class DefaultPortPair 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;
+
+ /**
+ * Default constructor to create Port Pair.
+ *
+ * @param portPairId port pair id
+ * @param tenantId tenant id
+ * @param name name of port pair
+ * @param description description of port pair
+ * @param ingress ingress port
+ * @param egress egress port
+ */
+ private DefaultPortPair(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 int hashCode() {
+ return Objects.hash(portPairId, tenantId, name, description,
+ ingress, egress);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPortPair) {
+ DefaultPortPair that = (DefaultPortPair) obj;
+ return Objects.equals(portPairId, that.portPairId) &&
+ Objects.equals(tenantId, that.tenantId) &&
+ Objects.equals(name, that.name) &&
+ Objects.equals(description, that.description) &&
+ Objects.equals(ingress, that.ingress) &&
+ Objects.equals(egress, that.egress);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exactMatch(PortPair portPair) {
+ return this.equals(portPair) &&
+ Objects.equals(this.portPairId, portPair.portPairId()) &&
+ Objects.equals(this.tenantId, portPair.tenantId());
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", portPairId.toString())
+ .add("tenantId", tenantId.tenantId())
+ .add("name", name)
+ .add("description", description)
+ .add("ingress", ingress)
+ .add("egress", egress)
+ .toString();
+ }
+
+ /**
+ * To create an instance of the builder.
+ *
+ * @return instance of builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder class for Port pair.
+ */
+ public static final class Builder implements PortPair.Builder {
+
+ private PortPairId portPairId;
+ private TenantId tenantId;
+ private String name;
+ private String description;
+ private String ingress;
+ private String egress;
+
+ @Override
+ public Builder setId(PortPairId portPairId) {
+ this.portPairId = portPairId;
+ return this;
+ }
+
+ @Override
+ public Builder setTenantId(TenantId tenantId) {
+ this.tenantId = tenantId;
+ return this;
+ }
+
+ @Override
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Builder setIngress(String ingress) {
+ this.ingress = ingress;
+ return this;
+ }
+
+ @Override
+ public Builder setEgress(String egress) {
+ this.egress = egress;
+ return this;
+ }
+
+ @Override
+ public PortPair build() {
+
+ checkNotNull(portPairId, "Port pair id cannot be null");
+ checkNotNull(tenantId, "Tenant id cannot be null");
+ checkNotNull(ingress, "Ingress of a port pair cannot be null");
+ checkNotNull(egress, "Egress of a port pair cannot be null");
+
+ return new DefaultPortPair(portPairId, tenantId, name, description,
+ ingress, egress);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
new file mode 100644
index 00000000..877cc6c9
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultPortPairGroup.java
@@ -0,0 +1,183 @@
+/*
+ * 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;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Implementation of port pair group.
+ */
+public final class DefaultPortPairGroup implements PortPairGroup {
+
+ private final PortPairGroupId portPairGroupId;
+ private final TenantId tenantId;
+ private final String name;
+ private final String description;
+ private final List<PortPairId> portPairList;
+
+ /**
+ * Default constructor to create Port Pair Group.
+ *
+ * @param portPairGroupId port pair group id
+ * @param tenantId tenant id
+ * @param name name of port pair group
+ * @param description description of port pair group
+ * @param portPairList list of port pairs
+ */
+ private DefaultPortPairGroup(PortPairGroupId portPairGroupId, TenantId tenantId,
+ String name, String description,
+ List<PortPairId> portPairList) {
+
+ this.portPairGroupId = portPairGroupId;
+ this.tenantId = tenantId;
+ this.name = name;
+ this.description = description;
+ this.portPairList = portPairList;
+ }
+
+ @Override
+ public PortPairGroupId portPairGroupId() {
+ return portPairGroupId;
+ }
+
+ @Override
+ public TenantId tenantId() {
+ return tenantId;
+ }
+
+ @Override
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public String description() {
+ return description;
+ }
+
+ @Override
+ public List<PortPairId> portPairs() {
+ return ImmutableList.copyOf(portPairList);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(portPairGroupId, tenantId, name, description,
+ portPairList);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPortPairGroup) {
+ DefaultPortPairGroup that = (DefaultPortPairGroup) obj;
+ return Objects.equals(portPairGroupId, that.portPairGroupId) &&
+ Objects.equals(tenantId, that.tenantId) &&
+ Objects.equals(name, that.name) &&
+ Objects.equals(description, that.description) &&
+ Objects.equals(portPairList, that.portPairList);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean exactMatch(PortPairGroup portPairGroup) {
+ return this.equals(portPairGroup) &&
+ Objects.equals(this.portPairGroupId, portPairGroup.portPairGroupId()) &&
+ Objects.equals(this.tenantId, portPairGroup.tenantId());
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("id", portPairGroupId.toString())
+ .add("tenantId", tenantId.toString())
+ .add("name", name)
+ .add("description", description)
+ .add("portPairGroupList", portPairList)
+ .toString();
+ }
+
+ /**
+ * To create an instance of the builder.
+ *
+ * @return instance of builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Builder class for Port pair group.
+ */
+ public static final class Builder implements PortPairGroup.Builder {
+
+ private PortPairGroupId portPairGroupId;
+ private TenantId tenantId;
+ private String name;
+ private String description;
+ private List<PortPairId> portPairList;
+
+ @Override
+ public Builder setId(PortPairGroupId portPairGroupId) {
+ this.portPairGroupId = portPairGroupId;
+ return this;
+ }
+
+ @Override
+ public Builder setTenantId(TenantId tenantId) {
+ this.tenantId = tenantId;
+ return this;
+ }
+
+ @Override
+ public Builder setName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ @Override
+ public Builder setDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ @Override
+ public Builder setPortPairs(List<PortPairId> portPairs) {
+ this.portPairList = portPairs;
+ return this;
+ }
+
+ @Override
+ public PortPairGroup build() {
+
+ checkNotNull(portPairGroupId, "Port pair group id cannot be null");
+ checkNotNull(tenantId, "Tenant id cannot be null");
+ checkNotNull(portPairList, "Port pairs cannot be null");
+
+ return new DefaultPortPairGroup(portPairGroupId, tenantId, name, description,
+ portPairList);
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifier.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifier.java
new file mode 100644
index 00000000..7b4108dc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifier.java
@@ -0,0 +1,259 @@
+/*
+ * 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.IpPrefix;
+
+/**
+ * Abstraction of an entity which provides flow classifier for service function chain.
+ * FlowClassifier classify the traffic based on the criteria defined in the request.
+ * The classification can be based on port range or source and destination IP address or
+ * other flow classifier elements.
+ */
+public interface FlowClassifier {
+
+ /**
+ * Returns flow classifier ID.
+ *
+ * @return flow classifier id
+ */
+ FlowClassifierId flowClassifierId();
+
+ /**
+ * Returns Tenant ID.
+ *
+ * @return tenant Id
+ */
+ TenantId tenantId();
+
+ /**
+ * Returns flow classifier name.
+ *
+ * @return flow classifier name
+ */
+ String name();
+
+ /**
+ * Returns flow classifier description.
+ *
+ * @return flow classifier description
+ */
+ String description();
+
+ /**
+ * Returns EtherType.
+ *
+ * @return EtherType
+ */
+ String etherType();
+
+ /**
+ * Returns IP Protocol.
+ *
+ * @return IP protocol
+ */
+ String protocol();
+
+ /**
+ * Returns minimum source port range.
+ *
+ * @return minimum source port range
+ */
+ int minSrcPortRange();
+
+ /**
+ * Returns maximum source port range.
+ *
+ * @return maximum source port range
+ */
+ int maxSrcPortRange();
+
+ /**
+ * Returns minimum destination port range.
+ *
+ * @return minimum destination port range
+ */
+ int minDstPortRange();
+
+ /**
+ * Returns maximum destination port range.
+ *
+ * @return maximum destination port range.
+ */
+ int maxDstPortRange();
+
+ /**
+ * Returns Source IP prefix.
+ *
+ * @return Source IP prefix
+ */
+ IpPrefix srcIpPrefix();
+
+ /**
+ * Returns Destination IP prefix.
+ *
+ * @return Destination IP prefix
+ */
+ IpPrefix dstIpPrefix();
+
+ /**
+ * Returns Source virtual port.
+ *
+ * @return Source virtual port
+ */
+ VirtualPortId srcPort();
+
+ /**
+ * Returns Destination virtual port.
+ *
+ * @return Destination virtual port
+ */
+ VirtualPortId dstPort();
+
+ /**
+ * Returns whether this Flow classifier is an exact match to the
+ * Flow classifier given in the argument.
+ *
+ * @param flowClassifier other flowClassifier to match against
+ * @return true if the flowClassifiers are an exact match, otherwise false
+ */
+ boolean exactMatch(FlowClassifier flowClassifier);
+
+ /**
+ * Builder for flow Classifier.
+ */
+ interface Builder {
+
+ /**
+ * Returns Flow Classifier.
+ *
+ * @return flow classifier.
+ */
+ FlowClassifier build();
+
+ /**
+ * Sets Flow Classifier ID.
+ *
+ * @param flowClassifierId flow classifier id.
+ * @return Builder object by setting flow classifier Id.
+ */
+ Builder setFlowClassifierId(FlowClassifierId flowClassifierId);
+
+ /**
+ * Sets Tenant ID.
+ *
+ * @param tenantId tenant id.
+ * @return Builder object by setting Tenant ID.
+ */
+ Builder setTenantId(TenantId tenantId);
+
+ /**
+ * Sets Flow classifier name.
+ *
+ * @param name flow classifier name
+ * @return builder object by setting flow classifier name
+ */
+ Builder setName(String name);
+
+ /**
+ * Sets flow classifier description.
+ *
+ * @param description flow classifier description
+ * @return flow classifier description
+ */
+ Builder setDescription(String description);
+
+ /**
+ * Sets EtherType.
+ *
+ * @param etherType EtherType
+ * @return EtherType
+ */
+ Builder setEtherType(String etherType);
+
+ /**
+ * Sets IP protocol.
+ *
+ * @param protocol IP protocol
+ * @return builder object by setting IP protocol
+ */
+ Builder setProtocol(String protocol);
+
+ /**
+ * Set minimum source port range.
+ *
+ * @param minRange minimum source port range
+ * @return builder object by setting minimum source port range
+ */
+ Builder setMinSrcPortRange(int minRange);
+
+ /**
+ * Sets maximum source port range.
+ *
+ * @param maxRange maximum source port range
+ * @return builder object by setting maximum source port range
+ */
+ Builder setMaxSrcPortRange(int maxRange);
+
+ /**
+ * Sets minimum destination port range.
+ *
+ * @param minRange minimum destination port range
+ * @return builder object by setting minimum destination port range
+ */
+ Builder setMinDstPortRange(int minRange);
+
+ /**
+ * Sets maximum destination port range.
+ *
+ * @param maxRange maximum destination port range.
+ * @return builder object by setting maximum destination port range.
+ */
+ Builder setMaxDstPortRange(int maxRange);
+
+ /**
+ * Sets Source IP prefix.
+ *
+ * @param srcIpPrefix Source IP prefix
+ * @return builder object by setting Source IP prefix
+ */
+ Builder setSrcIpPrefix(IpPrefix srcIpPrefix);
+
+ /**
+ * Sets Destination IP prefix.
+ *
+ * @param dstIpPrefix Destination IP prefix
+ * @return builder object by setting Destination IP prefix
+ */
+ Builder setDstIpPrefix(IpPrefix dstIpPrefix);
+
+ /**
+ * Sets Source virtual port.
+ *
+ * @param srcPort Source virtual port
+ * @return builder object by setting Source virtual port
+ */
+ Builder setSrcPort(VirtualPortId srcPort);
+
+ /**
+ * Sets Destination virtual port.
+ *
+ * @param dstPort Destination virtual port
+ * @return builder object by setting Destination virtual port
+ */
+ Builder setDstPort(VirtualPortId dstPort);
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.java
new file mode 100644
index 00000000..b789abe3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/FlowClassifierId.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.vtnrsc;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.UUID;
+import java.util.Objects;
+
+/**
+ * Flow classification identifier.
+ */
+public final class FlowClassifierId {
+
+ private final UUID flowClassifierId;
+
+ /**
+ * Constructor to create flow classifier id.
+ *
+ * @param flowClassifierId flow classifier id.
+ */
+ private FlowClassifierId(final UUID flowClassifierId) {
+ this.flowClassifierId = flowClassifierId;
+ }
+
+ /**
+ * Returns new flow classifier id.
+ *
+ * @param flowClassifierId flow classifier id
+ * @return new flow classifier id
+ */
+ public static FlowClassifierId flowClassifierId(final UUID flowClassifierId) {
+ return new FlowClassifierId(flowClassifierId);
+ }
+
+ /**
+ * Returns new flow classifier id.
+ *
+ * @param flowClassifierId flow classifier id
+ * @return new flow classifier id
+ */
+ public static FlowClassifierId flowClassifierId(final String flowClassifierId) {
+ return new FlowClassifierId(UUID.fromString(flowClassifierId));
+ }
+
+ /**
+ * Returns the value of flow classifier id.
+ *
+ * @return flow classifier id.
+ */
+ public UUID value() {
+ return flowClassifierId;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.flowClassifierId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof FlowClassifierId) {
+ final FlowClassifierId other = (FlowClassifierId) obj;
+ return Objects.equals(this.flowClassifierId, other.flowClassifierId);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("FlowClassifierId", flowClassifierId)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
new file mode 100644
index 00000000..d147eaaa
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChain.java
@@ -0,0 +1,148 @@
+/*
+ * 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.List;
+
+/**
+ * Abstraction of an entity providing Port Chain information.
+ * A Port Chain (Service Function Path) consists of
+ * a set of Neutron ports, to define the sequence of service functions
+ * a set of flow classifiers, to specify the classified traffic flows to enter the chain
+ */
+public interface PortChain {
+
+ /**
+ * Returns the ID of this port chain.
+ *
+ * @return the port chain id
+ */
+ PortChainId portChainId();
+
+ /**
+ * Returns the tenant id of this port chain.
+ *
+ * @return the tenant id
+ */
+ TenantId tenantId();
+
+ /**
+ * Returns the name of this port chain.
+ *
+ * @return name of port chain
+ */
+ String name();
+
+ /**
+ * Returns the description of this port chain.
+ *
+ * @return description of port chain
+ */
+ String description();
+
+ /**
+ * Returns the list of port pair groups associated with
+ * this port chain.
+ *
+ * @return list of port pair groups
+ */
+ List<PortPairGroupId> portPairGroups();
+
+ /**
+ * Returns the list of flow classifiers associated with
+ * this port chain.
+ *
+ * @return list of flow classifiers
+ */
+ List<FlowClassifierId> flowClassifiers();
+
+ /**
+ * Returns whether this port chain is an exact match to the port chain given
+ * in the argument.
+ * <p>
+ * Exact match means the port pair groups and flow classifiers match
+ * with the given port chain. It does not consider the port chain id, name
+ * and description.
+ * </p>
+ *
+ * @param portChain other port chain to match against
+ * @return true if the port chains are an exact match, otherwise false
+ */
+ boolean exactMatch(PortChain portChain);
+
+ /**
+ * A port chain builder..
+ */
+ interface Builder {
+
+ /**
+ * Assigns the port chain id to this object.
+ *
+ * @param portChainId the port chain id
+ * @return this the builder object
+ */
+ Builder setId(PortChainId portChainId);
+
+ /**
+ * Assigns tenant id to this object.
+ *
+ * @param tenantId tenant id of the port chain
+ * @return this the builder object
+ */
+ Builder setTenantId(TenantId tenantId);
+
+ /**
+ * Assigns the name to this object.
+ *
+ * @param name name of the port chain
+ * @return this the builder object
+ */
+ Builder setName(String name);
+
+ /**
+ * Assigns the description to this object.
+ *
+ * @param description description of the port chain
+ * @return this the builder object
+ */
+ Builder setDescription(String description);
+
+ /**
+ * Assigns the port pair groups associated with the port chain
+ * to this object.
+ *
+ * @param portPairGroups list of port pair groups
+ * @return this the builder object
+ */
+ Builder setPortPairGroups(List<PortPairGroupId> portPairGroups);
+
+ /**
+ * Assigns the flow classifiers associated with the port chain
+ * to this object.
+ *
+ * @param flowClassifiers list of flow classifiers
+ * @return this the builder object
+ */
+ Builder setFlowClassifiers(List<FlowClassifierId> flowClassifiers);
+
+ /**
+ * Builds a port chain object.
+ *
+ * @return a port chain.
+ */
+ PortChain build();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.java
new file mode 100644
index 00000000..66edbdcc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortChainId.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;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.UUID;
+
+import com.google.common.base.Objects;
+
+/**
+ * Representation of a Port Chain ID.
+ */
+public final class PortChainId {
+
+ private final UUID portChainId;
+
+ /**
+ * Private constructor for port chain id.
+ *
+ * @param id UUID id of port chain
+ */
+ private PortChainId(UUID id) {
+ checkNotNull(id, "Port chain id can not be null");
+ this.portChainId = id;
+ }
+
+ /**
+ * Constructor to create port chain id from UUID.
+ *
+ * @param id UUID of port chain
+ * @return object of port chain id
+ */
+ public static PortChainId portChainId(UUID id) {
+ return new PortChainId(id);
+ }
+
+ /**
+ * Constructor to create port chain id from string.
+ *
+ * @param id port chain id in string
+ * @return object of port chain id
+ */
+ public static PortChainId portChainId(String id) {
+ return new PortChainId(UUID.fromString(id));
+ }
+
+ /**
+ * Returns the value of port chain id.
+ *
+ * @return port chain id
+ */
+ public UUID value() {
+ return portChainId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj.getClass() == this.getClass()) {
+ PortChainId that = (PortChainId) obj;
+ return Objects.equal(this.portChainId, that.portChainId);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.portChainId);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("portChainId", portChainId.toString())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPair.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPair.java
new file mode 100644
index 00000000..f6285e61
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPair.java
@@ -0,0 +1,139 @@
+/*
+ * 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;
+
+
+/**
+ * Abstraction of an entity providing Port Pair information.
+ * A port pair represents a service function instance.
+ */
+public interface PortPair {
+
+ /**
+ * Returns the ID of this port Pair.
+ *
+ * @return the port pair id
+ */
+ PortPairId portPairId();
+
+ /**
+ * Returns the tenant id of this port pair.
+ *
+ * @return an tenant id
+ */
+ TenantId tenantId();
+
+ /**
+ * Returns the description of this port pair.
+ *
+ * @return description of port pair
+ */
+ String name();
+
+ /**
+ * Returns the description of this port pair.
+ *
+ * @return description of port pair
+ */
+ String description();
+
+ /**
+ * Returns the ingress port of this port pair.
+ *
+ * @return ingress of port pair
+ */
+ String ingress();
+
+ /**
+ * Returns the egress port of this port pair.
+ *
+ * @return egress of port pair
+ */
+ String egress();
+
+ /**
+ * Returns whether this port pair is an exact match to the port pair given
+ * in the argument.
+ * <p>
+ * Exact match means the Port port pairs match with the given port pair.
+ * It does not consider the port pair id, name and description.
+ * </p>
+ * @param portPair other port pair to match against
+ * @return true if the port pairs are an exact match, otherwise false
+ */
+ boolean exactMatch(PortPair portPair);
+
+ /**
+ * A port pair builder..
+ */
+ interface Builder {
+
+ /**
+ * Assigns the port pair id to this object.
+ *
+ * @param portPairId the port pair id
+ * @return this the builder object
+ */
+ Builder setId(PortPairId portPairId);
+
+ /**
+ * Assigns tenant id to this object.
+ *
+ * @param tenantId tenant id of the port pair
+ * @return this the builder object
+ */
+ Builder setTenantId(TenantId tenantId);
+
+ /**
+ * Assigns the name to this object.
+ *
+ * @param name name of the port pair
+ * @return this the builder object
+ */
+ Builder setName(String name);
+
+ /**
+ * Assigns the description to this object.
+ *
+ * @param description description of the port pair
+ * @return this the builder object
+ */
+ Builder setDescription(String description);
+
+ /**
+ * Assigns the ingress port to this object.
+ *
+ * @param port ingress port of the port pair
+ * @return this the builder object
+ */
+ Builder setIngress(String port);
+
+ /**
+ * Assigns the egress port to this object.
+ *
+ * @param port egress port of the port pair
+ * @return this the builder object
+ */
+ Builder setEgress(String port);
+
+ /**
+ * Builds a port pair object.
+ *
+ * @return a port pair.
+ */
+ PortPair build();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.java
new file mode 100644
index 00000000..f647b57f
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroup.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;
+
+import java.util.List;
+
+/**
+ * Abstraction of an entity providing Port Pair Group information.
+ * A port pair group consists of one or more port pairs.
+ */
+public interface PortPairGroup {
+
+ /**
+ * Returns the ID of this port pair group.
+ *
+ * @return the port pair group id
+ */
+ PortPairGroupId portPairGroupId();
+
+ /**
+ * Returns the tenant id of this port pair group.
+ *
+ * @return the tenant id
+ */
+ TenantId tenantId();
+
+ /**
+ * Returns the name of this port pair group.
+ *
+ * @return name of port pair group
+ */
+ String name();
+
+ /**
+ * Returns the description of this port pair group.
+ *
+ * @return description of port pair group
+ */
+ String description();
+
+ /**
+ * Returns the list of port pairs associated with this port pair group.
+ *
+ * @return list of port pairs
+ */
+ List<PortPairId> portPairs();
+
+ /**
+ * Returns whether this port pair group is an exact match to the
+ * port pair group given in the argument.
+ * <p>
+ * Exact match means the Port pairs match with the given port pair group.
+ * It does not consider the port pair group id, name and description.
+ * </p>
+ * @param portPairGroup other port pair group to match against
+ * @return true if the port pairs are an exact match, otherwise false
+ */
+ boolean exactMatch(PortPairGroup portPairGroup);
+
+ /**
+ * A port pair group builder..
+ */
+ interface Builder {
+
+ /**
+ * Assigns the port pair group id to this object.
+ *
+ * @param portPairGroupId the port pair group id
+ * @return this the builder object
+ */
+ Builder setId(PortPairGroupId portPairGroupId);
+
+ /**
+ * Assigns tenant id to this object.
+ *
+ * @param tenantId tenant id of port pair group
+ * @return this the builder object
+ */
+ Builder setTenantId(TenantId tenantId);
+
+ /**
+ * Assigns the name to this object.
+ *
+ * @param name name of the port pair group
+ * @return this the builder object
+ */
+ Builder setName(String name);
+
+ /**
+ * Assigns the description to this object.
+ *
+ * @param description description of the port pair group
+ * @return this the builder object
+ */
+ Builder setDescription(String description);
+
+ /**
+ * Assigns the port pairs associated with the port pair group
+ * to this object.
+ *
+ * @param portPairs list of port pairs
+ * @return this the builder object
+ */
+ Builder setPortPairs(List<PortPairId> portPairs);
+
+ /**
+ * Builds a port pair group object.
+ *
+ * @return a port pair group object.
+ */
+ PortPairGroup build();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.java
new file mode 100644
index 00000000..0474901c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairGroupId.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;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.UUID;
+
+import com.google.common.base.Objects;
+
+/**
+ * Representation of a Port Pair Group ID.
+ */
+public final class PortPairGroupId {
+
+ private final UUID portPairGroupId;
+
+ /**
+ * Private constructor for port pair group id.
+ *
+ * @param id UUID id of port pair group
+ */
+ private PortPairGroupId(UUID id) {
+ checkNotNull(id, "Port pair group id can not be null");
+ this.portPairGroupId = id;
+ }
+
+ /**
+ * Constructor to create port pair group id from UUID.
+ *
+ * @param id UUID of port pair group id
+ * @return object of port pair group id
+ */
+ public static PortPairGroupId portPairGroupId(UUID id) {
+ return new PortPairGroupId(id);
+ }
+
+ /**
+ * Constructor to create port pair group id from string.
+ *
+ * @param id port pair group id in string
+ * @return object of port pair group id
+ */
+ public static PortPairGroupId portPairGroupId(String id) {
+ return new PortPairGroupId(UUID.fromString(id));
+ }
+
+ /**
+ * Returns the value of port pair group id.
+ *
+ * @return port pair group id
+ */
+ public UUID value() {
+ return portPairGroupId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj.getClass() == this.getClass()) {
+ PortPairGroupId that = (PortPairGroupId) obj;
+ return Objects.equal(this.portPairGroupId, that.portPairGroupId);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.portPairGroupId);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("portPairGroupId", portPairGroupId.toString())
+ .toString();
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.java
new file mode 100644
index 00000000..05c31aac
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/PortPairId.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;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.UUID;
+
+import com.google.common.base.Objects;
+
+/**
+ * Representation of a Port Pair ID.
+ */
+public final class PortPairId {
+
+ private final UUID portPairId;
+
+ /**
+ * Private constructor for port pair id.
+ *
+ * @param id UUID id of port pair
+ */
+ private PortPairId(UUID id) {
+ checkNotNull(id, "Port chain id can not be null");
+ this.portPairId = id;
+ }
+
+ /**
+ * Constructor to create port pair id from UUID.
+ *
+ * @param id UUID of port pair id
+ * @return object of port pair id
+ */
+ public static PortPairId portPairId(UUID id) {
+ return new PortPairId(id);
+ }
+
+ /**
+ * Constructor to create port pair id from string.
+ *
+ * @param id port pair id in string
+ * @return object of port pair id
+ */
+ public static PortPairId portPairId(String id) {
+ return new PortPairId(UUID.fromString(id));
+ }
+
+ /**
+ * Returns teh value of port pair id.
+ *
+ * @return port pair id
+ */
+ public UUID value() {
+ return portPairId;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj.getClass() == this.getClass()) {
+ PortPairId that = (PortPairId) obj;
+ return Objects.equal(this.portPairId, that.portPairId);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(this.portPairId);
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("portPairId", portPairId.toString())
+ .toString();
+ }
+}
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
new file mode 100644
index 00000000..e379be81
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/FlowClassifierService.java
@@ -0,0 +1,72 @@
+/*
+ * 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;
+
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+
+/**
+ * Provides Services for Flow Classifier.
+ */
+public interface FlowClassifierService {
+
+ /**
+ * Store Flow Classifier.
+ *
+ * @param flowClassifier Flow Classifier
+ * @return true if adding Flow Classifier into store is success otherwise return false.
+ */
+ boolean createFlowClassifier(FlowClassifier flowClassifier);
+
+ /**
+ * Return the existing collection of Flow Classifier.
+ *
+ * @return Flow Classifier collections.
+ */
+ Iterable<FlowClassifier> getFlowClassifiers();
+
+ /**
+ * Check whether Flow Classifier is present based on given Flow Classifier Id.
+ *
+ * @param id Flow Classifier.
+ * @return true if Flow Classifier is present otherwise return false.
+ */
+ boolean hasFlowClassifier(FlowClassifierId id);
+
+ /**
+ * Retrieve the Flow Classifier based on given Flow Classifier id.
+ *
+ * @param id Flow Classifier Id.
+ * @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.
+ */
+ 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.
+ */
+ boolean removeFlowClassifier(FlowClassifierId id);
+} \ No newline at end of file
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
new file mode 100644
index 00000000..7238558a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/FlowClassifierManager.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.flowClassifier.impl;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+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.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.flowClassifier.FlowClassifierService;
+
+import org.slf4j.Logger;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Provides implementation of the Flow Classifier Service.
+ */
+@Component(immediate = true)
+@Service
+public class FlowClassifierManager implements FlowClassifierService {
+
+ private final Logger log = getLogger(FlowClassifierManager.class);
+
+ private static final String FLOW_CLASSIFIER_NOT_NULL = "Flow Classifier cannot be null";
+ private static final String FLOW_CLASSIFIER_ID_NOT_NULL = "Flow Classifier Id cannot be null";
+
+ private ConcurrentMap<FlowClassifierId, FlowClassifier> flowClassifierStore
+ = new ConcurrentHashMap<FlowClassifierId, FlowClassifier>();
+
+ @Activate
+ private void activate() {
+ log.info("Flow Classifier service activated");
+ }
+
+ @Deactivate
+ private void deactivate() {
+ 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;
+ }
+
+ @Override
+ public Iterable<FlowClassifier> getFlowClassifiers() {
+ return ImmutableList.copyOf(flowClassifierStore.values());
+ }
+
+ @Override
+ public boolean hasFlowClassifier(FlowClassifierId id) {
+ checkNotNull(id, FLOW_CLASSIFIER_ID_NOT_NULL);
+ return flowClassifierStore.containsKey(id);
+ }
+
+ @Override
+ public FlowClassifier getFlowClassifier(FlowClassifierId id) {
+ checkNotNull(id, FLOW_CLASSIFIER_ID_NOT_NULL);
+ return flowClassifierStore.get(id);
+ }
+
+ @Override
+ public boolean updateFlowClassifier(FlowClassifier flowClassifier) {
+ checkNotNull(flowClassifier, FLOW_CLASSIFIER_NOT_NULL);
+ FlowClassifierId id = flowClassifier.flowClassifierId();
+ return flowClassifierStore.replace(id, flowClassifierStore.get(id), flowClassifier);
+ }
+
+ @Override
+ public boolean removeFlowClassifier(FlowClassifierId id) {
+ checkNotNull(id, FLOW_CLASSIFIER_ID_NOT_NULL);
+ flowClassifierStore.remove(id);
+ if (flowClassifierStore.containsKey(id)) {
+ log.debug("The Flow Classifier removal is failed whose identifier is {}", id.toString());
+ return false;
+ }
+ return true;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/impl/package-info.java
new file mode 100644
index 00000000..4ea050b3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/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 flow Classifier service.
+ */
+package org.onosproject.vtnrsc.flowClassifier.impl;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/package-info.java
new file mode 100644
index 00000000..07584170
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/flowClassifier/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 flow Classifier of SFC.
+ */
+package org.onosproject.vtnrsc.flowClassifier;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.java
new file mode 100644
index 00000000..b4ff917e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/PortChainService.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.portchain;
+
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+
+/**
+ * Service for interacting with the inventory of port chains.
+ */
+public interface PortChainService {
+
+ /**
+ * Returns if the port chain is existed.
+ *
+ * @param portChainId port chain identifier
+ * @return true or false if one with the given identifier exists.
+ */
+ boolean exists(PortChainId portChainId);
+
+ /**
+ * Returns the number of port chains known to the system.
+ *
+ * @return number of port chains.
+ */
+ int getPortChainCount();
+
+ /**
+ * Returns an iterable collection of the currently known port chains.
+ *
+ * @return collection of port chains.
+ */
+ Iterable<PortChain> getPortChains();
+
+ /**
+ * Returns the portChain with the given identifier.
+ *
+ * @param portChainId port chain identifier
+ * @return PortChain or null if port chain with the given identifier is not
+ * known.
+ */
+ PortChain getPortChain(PortChainId portChainId);
+
+ /**
+ * Creates a PortChain in the store.
+ *
+ * @param portChain the port chain to create
+ * @return true if given port chain is created successfully.
+ */
+ boolean createPortChain(PortChain portChain);
+
+ /**
+ * Updates the portChain in the store.
+ *
+ * @param portChain the port chain to update
+ * @return true if given port chain is updated successfully.
+ */
+ boolean updatePortChain(PortChain portChain);
+
+ /**
+ * Deletes portChain by given portChainId.
+ *
+ * @param portChainId id of port chain to remove
+ * @return true if the give port chain is deleted successfully.
+ */
+ boolean removePortChain(PortChainId portChainId);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/package-info.java
new file mode 100644
index 00000000..74642bc3
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portchain/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 port chains.
+ */
+package org.onosproject.vtnrsc.portchain;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.java
new file mode 100644
index 00000000..77f483fc
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/PortPairGroupService.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.portpairgroup;
+
+import org.onosproject.vtnrsc.PortPairGroup;
+import org.onosproject.vtnrsc.PortPairGroupId;
+
+/**
+ * Service for interacting with the inventory of port pair groups.
+ */
+public interface PortPairGroupService {
+
+ /**
+ * Returns if the port pair group is existed.
+ *
+ * @param portPairGroupId port pair group identifier
+ * @return true or false if one with the given identifier exists.
+ */
+ boolean exists(PortPairGroupId portPairGroupId);
+
+ /**
+ * Returns the number of port pair groups known to the system.
+ *
+ * @return number of port pair groups.
+ */
+ int getPortPairGroupCount();
+
+ /**
+ * Returns an iterable collection of the currently known port pair groups.
+ *
+ * @return collection of port pair groups.
+ */
+ Iterable<PortPairGroup> getPortPairGroups();
+
+ /**
+ * Returns the portPairGroup with the given identifier.
+ *
+ * @param portPairGroupId port pair group identifier
+ * @return PortPairGroup or null if port pair group with the given identifier is not
+ * known.
+ */
+ PortPairGroup getPortPairGroup(PortPairGroupId portPairGroupId);
+
+ /**
+ * Creates a PortPairGroup in the store.
+ *
+ * @param portPairGroup the port pair group to create
+ * @return true if given port pair group is created successfully.
+ */
+ boolean createPortPairGroup(PortPairGroup portPairGroup);
+
+ /**
+ * Updates the portPairGroup in the store.
+ *
+ * @param portPairGroup the port pair group to update
+ * @return true if given port pair group is updated successfully.
+ */
+ boolean updatePortPairGroup(PortPairGroup portPairGroup);
+
+ /**
+ * Deletes portPairGroup by given portPairGroupId.
+ *
+ * @param portPairGroupId id of port pair group to remove
+ * @return true if the give port pair group is deleted successfully.
+ */
+ boolean removePortPairGroup(PortPairGroupId portPairGroupId);
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/package-info.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/package-info.java
new file mode 100644
index 00000000..8a79fe97
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/portpairgroup/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 port pair groups.
+ */
+package org.onosproject.vtnrsc.portpairgroup;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/TunnelConfigService.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/TunnelConfigService.java
deleted file mode 100644
index 6f3cf653..00000000
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/tunnel/TunnelConfigService.java
+++ /dev/null
@@ -1,72 +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.vtnrsc.tunnel;
-
-import org.onosproject.vtnrsc.Subnet;
-import org.onosproject.vtnrsc.SubnetId;
-
-
-/**
- * Service for interacting with the inventory of subnets.
- */
-public interface TunnelConfigService {
- /**
- * Returns the subnet with the specified identifier.
- *
- * @param subnetId subnet identifier
- * @return true or false
- */
- boolean exists(SubnetId subnetId);
- /**
- * Returns a collection of the currently known subnets.
- *
- * @return iterable collection of subnets
- */
- Iterable<Subnet> getSubnets();
-
- /**
- * Returns the subnet with the specified identifier.
- *
- * @param subnetId subnet identifier
- * @return subnet or null if one with the given identifier is not known
- */
- Subnet getSubnet(SubnetId subnetId);
- /**
- * Creates new subnets.
- *
- * @param subnets the iterable collection of subnets
- * @return true if the identifier subnet has been created right
- */
- boolean createSubnets(Iterable<Subnet> subnets);
-
- /**
- * Updates existing subnets.
- *
- * @param subnets the iterable collection of subnets
- * @return true if all subnets were updated successfully
- */
- boolean updateSubnets(Iterable<Subnet> subnets);
-
- /**
- * Administratively removes the specified subnets from the store.
- *
- * @param subnetIds the iterable collection of subnets identifier
- * @return true if remove identifier subnets successfully
- */
- boolean removeSubnets(Iterable<SubnetId> subnetIds);
-
-
-}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
index c45373b9..daec7839 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/virtualport/impl/VirtualPortManager.java
@@ -191,22 +191,20 @@ public class VirtualPortManager implements VirtualPortService {
@Override
public boolean updatePorts(Iterable<VirtualPort> vPorts) {
checkNotNull(vPorts, VIRTUALPORT_NOT_NULL);
- if (vPorts != null) {
- for (VirtualPort vPort : vPorts) {
- vPortStore.put(vPort.portId(), vPort);
- if (!vPortStore.containsKey(vPort.portId())) {
- log.debug("The virtualPort is not exist whose identifier is {}",
- vPort.portId().toString());
- return false;
- }
+ for (VirtualPort vPort : vPorts) {
+ vPortStore.put(vPort.portId(), vPort);
+ if (!vPortStore.containsKey(vPort.portId())) {
+ log.debug("The virtualPort is not exist whose identifier is {}",
+ vPort.portId().toString());
+ return false;
+ }
- vPortStore.put(vPort.portId(), vPort);
+ vPortStore.put(vPort.portId(), vPort);
- if (!vPort.equals(vPortStore.get(vPort.portId()))) {
- log.debug("The virtualPort is updated failed whose identifier is {}",
- vPort.portId().toString());
- return false;
- }
+ if (!vPort.equals(vPortStore.get(vPort.portId()))) {
+ log.debug("The virtualPort is updated failed whose identifier is {}",
+ vPort.portId().toString());
+ return false;
}
}
return true;
@@ -215,14 +213,12 @@ public class VirtualPortManager implements VirtualPortService {
@Override
public boolean removePorts(Iterable<VirtualPortId> vPortIds) {
checkNotNull(vPortIds, VIRTUALPORT_ID_NULL);
- if (vPortIds != null) {
- for (VirtualPortId vPortId : vPortIds) {
- vPortStore.remove(vPortId);
- if (vPortStore.containsKey(vPortId)) {
- log.debug("The virtualPort is removed failed whose identifier is {}",
- vPortId.toString());
- return false;
- }
+ for (VirtualPortId vPortId : vPortIds) {
+ vPortStore.remove(vPortId);
+ if (vPortStore.containsKey(vPortId)) {
+ log.debug("The virtualPort is removed failed whose identifier is {}",
+ vPortId.toString());
+ return false;
}
}
return true;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.java
new file mode 100644
index 00000000..fd5b1ee4
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FlowClassifierCodec.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.web;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import java.util.UUID;
+
+import org.onlab.packet.IpPrefix;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.DefaultFlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.VirtualPortId;
+import org.onosproject.vtnrsc.TenantId;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Flow Classifier JSON codec.
+ */
+public final class FlowClassifierCodec extends JsonCodec<FlowClassifier> {
+
+ private static final String FLOW_CLASSIFIER_ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String ETHER_TYPE = "etherType";
+ private static final String PROTOCOL = "protocol";
+ private static final String MIN_SRC_PORT_RANGE = "source_port_range_min";
+ private static final String MAX_SRC_PORT_RANGE = "source_port_range_max";
+ private static final String MIN_DST_PORT_RANGE = "destination_port_range_min";
+ private static final String MAX_DST_PORT_RANGE = "destination_port_range_max";
+ private static final String SRC_IP_PREFIX = "source_ip_prefix";
+ private static final String DST_IP_PREFIX = "destination_ip_prefix";
+ private static final String SRC_PORT = "logical_source_port";
+ private static final String DST_PORT = "logical_destination_port";
+ private static final String MISSING_MEMBER_MESSAGE = " member is required in Flow Classifier.";
+
+ @Override
+ public FlowClassifier decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ FlowClassifier.Builder resultBuilder = new DefaultFlowClassifier.Builder();
+
+ String flowClassifierId = nullIsIllegal(json.get(FLOW_CLASSIFIER_ID),
+ FLOW_CLASSIFIER_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setFlowClassifierId(FlowClassifierId.flowClassifierId(UUID.fromString(flowClassifierId)));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID), TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String flowClassiferName = nullIsIllegal(json.get(NAME), NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(flowClassiferName);
+
+ String flowClassiferDescription = nullIsIllegal(json.get(DESCRIPTION), DESCRIPTION + MISSING_MEMBER_MESSAGE)
+ .asText();
+ resultBuilder.setDescription(flowClassiferDescription);
+
+ String etherType = nullIsIllegal(json.get(ETHER_TYPE), ETHER_TYPE + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setEtherType(etherType);
+
+ String protocol = nullIsIllegal(json.get(PROTOCOL), PROTOCOL + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setProtocol(protocol);
+
+ int minSrcPortRange = nullIsIllegal(json.get(MIN_SRC_PORT_RANGE), MIN_SRC_PORT_RANGE + MISSING_MEMBER_MESSAGE)
+ .asInt();
+ resultBuilder.setMinSrcPortRange(minSrcPortRange);
+
+ int maxSrcPortRange = nullIsIllegal(json.get(MAX_SRC_PORT_RANGE), MAX_SRC_PORT_RANGE + MISSING_MEMBER_MESSAGE)
+ .asInt();
+ resultBuilder.setMaxSrcPortRange(maxSrcPortRange);
+
+ int minDstPortRange = nullIsIllegal(json.get(MIN_DST_PORT_RANGE), MIN_DST_PORT_RANGE + MISSING_MEMBER_MESSAGE)
+ .asInt();
+ resultBuilder.setMinDstPortRange(minDstPortRange);
+
+ int maxDstPortRange = nullIsIllegal(json.get(MAX_DST_PORT_RANGE), MAX_DST_PORT_RANGE + MISSING_MEMBER_MESSAGE)
+ .asInt();
+ resultBuilder.setMaxDstPortRange(maxDstPortRange);
+
+ String srcIpPrefix = nullIsIllegal(json.get(SRC_IP_PREFIX), SRC_IP_PREFIX + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setSrcIpPrefix(IpPrefix.valueOf(srcIpPrefix));
+
+ String dstIpPrefix = nullIsIllegal(json.get(DST_IP_PREFIX), DST_IP_PREFIX + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDstIpPrefix(IpPrefix.valueOf(dstIpPrefix));
+
+ String srcPort = nullIsIllegal(json.get(SRC_PORT), SRC_PORT + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setSrcPort(VirtualPortId.portId(srcPort));
+
+ String dstPort = nullIsIllegal(json.get(DST_PORT), DST_PORT + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDstPort(VirtualPortId.portId(dstPort));
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(FlowClassifier flowClassifier, CodecContext context) {
+ checkNotNull(flowClassifier, "flowClassifier cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put("FLOW_CLASSIFIER_ID", flowClassifier.flowClassifierId().toString())
+ .put("TENANT_ID", flowClassifier.tenantId().toString())
+ .put("NAME", flowClassifier.name())
+ .put("DESCRIPTION", flowClassifier.description())
+ .put("ETHER_TYPE", flowClassifier.etherType())
+ .put("PROTOCOL", flowClassifier.protocol())
+ .put("MIN_SRC_PORT_RANGE", flowClassifier.minSrcPortRange())
+ .put("MAX_SRC_PORT_RANGE", flowClassifier.maxSrcPortRange())
+ .put("MIN_DST_PORT_RANGE", flowClassifier.minDstPortRange())
+ .put("MAX_DST_PORT_RANGE", flowClassifier.maxDstPortRange())
+ .put("SRC_IP_PREFIX", flowClassifier.srcIpPrefix().toString())
+ .put("DST_IP_PREFIX", flowClassifier.dstIpPrefix().toString())
+ .put("SRC_PORT", flowClassifier.srcPort().toString())
+ .put("DST_PORT", flowClassifier.dstPort().toString());
+ return result;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/FlowClassifierIdTest.java
new file mode 100644
index 00000000..b2fed347
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/flowclassifier/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.flowclassifier;
+
+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.FlowClassifierId;
+
+import com.google.common.testing.EqualsTester;
+import java.util.UUID;
+
+/**
+ * Unit tests for FlowClassifierId class.
+ */
+public class FlowClassifierIdTest {
+
+ final FlowClassifierId flowClassifierId1 = FlowClassifierId
+ .flowClassifierId("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final FlowClassifierId sameAsFlowClassifierId1 = FlowClassifierId
+ .flowClassifierId("78dcd363-fc23-aeb6-f44b-56dc5e2fb3ae");
+ final FlowClassifierId flowClassifierId2 = FlowClassifierId
+ .flowClassifierId("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.flowClassifierId(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/subnet/DefaultAllocationPoolTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultAllocationPoolTest.java
new file mode 100644
index 00000000..4ce4def2
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultAllocationPoolTest.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.subnet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.vtnrsc.AllocationPool;
+import org.onosproject.vtnrsc.DefaultAllocationPool;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/subnet/DefaultHostRouteTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultHostRouteTest.java
new file mode 100644
index 00000000..2f751742
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/DefaultHostRouteTest.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.subnet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.vtnrsc.DefaultHostRoute;
+import org.onosproject.vtnrsc.HostRoute;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/subnet/SubnetIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/SubnetIdTest.java
new file mode 100644
index 00000000..d18dd41a
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/subnet/SubnetIdTest.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.subnet;
+
+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.SubnetId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/tenantnetwork/DefaultNeutronNetworkTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/DefaultNeutronNetworkTest.java
new file mode 100644
index 00000000..742d5933
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/DefaultNeutronNetworkTest.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tenantnetwork;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+import org.junit.Test;
+import org.onosproject.vtnrsc.DefaultTenantNetwork;
+import org.onosproject.vtnrsc.PhysicalNetwork;
+import org.onosproject.vtnrsc.SegmentationId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetwork;
+import org.onosproject.vtnrsc.TenantNetworkId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/tenantnetwork/PhysicalNetworkTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/PhysicalNetworkTest.java
new file mode 100644
index 00000000..e101795e
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/PhysicalNetworkTest.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.tenantnetwork;
+
+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.PhysicalNetwork;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/tenantnetwork/SegmentationIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/SegmentationIdTest.java
new file mode 100644
index 00000000..dea7baf6
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/SegmentationIdTest.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.tenantnetwork;
+
+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.SegmentationId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/tenantnetwork/TenantIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantIdTest.java
new file mode 100644
index 00000000..e9216383
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantIdTest.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.tenantnetwork;
+
+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.TenantId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/tenantnetwork/TenantNetworkIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantNetworkIdTest.java
new file mode 100644
index 00000000..8271b51c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/tenantnetwork/TenantNetworkIdTest.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.tenantnetwork;
+
+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.TenantNetworkId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/virtualport/AllowedAddressPairTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/AllowedAddressPairTest.java
new file mode 100644
index 00000000..dabe5896
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/AllowedAddressPairTest.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.virtualport;
+
+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.onlab.packet.MacAddress;
+import org.onosproject.vtnrsc.AllowedAddressPair;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/virtualport/DefaultVirtualPortTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/DefaultVirtualPortTest.java
new file mode 100644
index 00000000..8a0c8004
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/DefaultVirtualPortTest.java
@@ -0,0 +1,142 @@
+/*
+ * 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.virtualport;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+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 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.SubnetId;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.TenantNetworkId;
+import org.onosproject.vtnrsc.VirtualPort;
+import org.onosproject.vtnrsc.VirtualPortId;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/virtualport/FixedIpTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/FixedIpTest.java
new file mode 100644
index 00000000..1e33da09
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/FixedIpTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.virtualport;
+
+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.FixedIp;
+import org.onosproject.vtnrsc.SubnetId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/virtualport/SecurityGroupTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/SecurityGroupTest.java
new file mode 100644
index 00000000..8c04e499
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/SecurityGroupTest.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.virtualport;
+
+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.SecurityGroup;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/virtualport/VirtualPortIdTest.java b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/VirtualPortIdTest.java
new file mode 100644
index 00000000..2d63e91c
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/virtualport/VirtualPortIdTest.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.virtualport;
+
+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.VirtualPortId;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * 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/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
new file mode 100644
index 00000000..1450e4ef
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/FlowClassifierWebResource.java
@@ -0,0 +1,192 @@
+/*
+ * 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 javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static org.onlab.util.Tools.nullIsNotFound;
+import static javax.ws.rs.core.Response.Status.NOT_FOUND;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.UUID;
+
+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.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.onosproject.vtnrsc.FlowClassifier;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.vtnrsc.flowClassifier.FlowClassifierService;
+import org.onosproject.vtnrsc.web.FlowClassifierCodec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * Query and program flow classifier.
+ */
+@Path("flow_classifiers")
+public class FlowClassifierWebResource extends AbstractWebResource {
+
+ final FlowClassifierService service = get(FlowClassifierService.class);
+ final ObjectNode root = mapper().createObjectNode();
+ public static final String FLOW_CLASSIFIER_NOT_FOUND = "Flow classifier not found";
+
+ /**
+ * Get all flow classifiers created. Returns list of all flow classifiers
+ * created.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getFlowClassifiers() {
+ Iterable<FlowClassifier> flowClassifiers = service.getFlowClassifiers();
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("flow_classifiers", new FlowClassifierCodec().encode(flowClassifiers, this));
+ return ok(result.toString()).build();
+ }
+
+ /**
+ * Get details of a flow classifier. Returns details of a specified flow
+ * classifier id.
+ *
+ * @param id flow classifier id
+ * @return 200 OK
+ */
+ @GET
+ @Path("{flow_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response getFlowClassifier(@PathParam("flow_id") String id) {
+
+ if (!service.hasFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id)))) {
+ return Response.status(NOT_FOUND).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
+ }
+ FlowClassifier flowClassifier = nullIsNotFound(
+ service.getFlowClassifier(FlowClassifierId.flowClassifierId(UUID.fromString(id))),
+ FLOW_CLASSIFIER_NOT_FOUND);
+
+ ObjectNode result = new ObjectMapper().createObjectNode();
+ result.set("flow_classifier", new FlowClassifierCodec().encode(flowClassifier, this));
+ return ok(result.toString()).build();
+ }
+
+ /**
+ * Creates and stores a new flow classifier.
+ *
+ * @param flowClassifierId flow classifier identifier
+ * @param stream flow classifier from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Path("{flow_id}")
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createFlowClassifier(@PathParam("flow_id") String flowClassifierId, InputStream stream) {
+ URI location;
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+
+ FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
+ service.createFlowClassifier(flowClassifier);
+ location = new URI(flowClassifierId);
+ } catch (IOException | URISyntaxException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ return Response.created(location).build();
+ }
+
+ /**
+ * Creates and stores a new flow classifier.
+ *
+ * @param stream flow classifier from JSON
+ * @return status of the request - CREATED if the JSON is correct,
+ * BAD_REQUEST if the JSON is invalid
+ */
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Response createFlowClassifier(InputStream stream) {
+ URI location;
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+
+ FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
+ service.createFlowClassifier(flowClassifier);
+ location = new URI(flowClassifier.flowClassifierId().toString());
+ } catch (IOException | URISyntaxException ex) {
+ throw new IllegalArgumentException(ex);
+ }
+ return Response.created(location).build();
+ }
+
+ /**
+ * Update details of a flow classifier. Update details of a specified flow
+ * classifier id.
+ *
+ * @param id flow classifier id
+ * @param stream InputStream
+ * @return 200 OK
+ */
+ @PUT
+ @Path("{flow_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response updateFlowClassifier(@PathParam("flow_id") String id, final InputStream stream) {
+ try {
+ ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
+ FlowClassifier flowClassifier = codec(FlowClassifier.class).decode(jsonTree, this);
+ Boolean result = nullIsNotFound(service.updateFlowClassifier(flowClassifier), FLOW_CLASSIFIER_NOT_FOUND);
+ if (!result) {
+ return Response.status(204).entity(FLOW_CLASSIFIER_NOT_FOUND).build();
+ }
+ return Response.status(203).entity(result.toString()).build();
+ } catch (Exception e) {
+ return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()).build();
+ }
+ }
+
+ /**
+ * Delete details of a flow classifier. Delete details of a specified flow
+ * classifier id.
+ *
+ * @param id flow classifier id
+ * @return 200 OK
+ * @throws IOException when input doesn't match.
+ */
+ @Path("{flow_id}")
+ @DELETE
+ public Response deleteFlowClassifier(@PathParam("flow_id") String id) throws IOException {
+ try {
+ FlowClassifierId flowClassifierId = FlowClassifierId.flowClassifierId(UUID.fromString(id));
+ service.removeFlowClassifier(flowClassifierId);
+ return Response.status(201).entity("SUCCESS").build();
+ } catch (Exception e) {
+ return Response.status(INTERNAL_SERVER_ERROR).entity(e.toString()).build();
+ }
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/SubnetWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/SubnetWebResource.java
index 251dcffc..0cc59a4e 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/SubnetWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/SubnetWebResource.java
@@ -56,7 +56,7 @@ import org.onosproject.vtnrsc.TenantId;
import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.Subnet.Mode;
import org.onosproject.vtnrsc.subnet.SubnetService;
-import org.onosproject.vtnrsc.web.SubnetCodec;
+import org.onosproject.vtnweb.web.SubnetCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 0b877822..2dd931ea 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
@@ -51,7 +51,7 @@ import org.onosproject.vtnrsc.TenantNetworkId;
import org.onosproject.vtnrsc.TenantNetwork.State;
import org.onosproject.vtnrsc.TenantNetwork.Type;
import org.onosproject.vtnrsc.tenantnetwork.TenantNetworkService;
-import org.onosproject.vtnrsc.web.TenantNetworkCodec;
+import org.onosproject.vtnweb.web.TenantNetworkCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VirtualPortWebResource.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VirtualPortWebResource.java
index 03d3a653..e47a57df 100644
--- a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VirtualPortWebResource.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/resources/VirtualPortWebResource.java
@@ -58,7 +58,7 @@ import org.onosproject.vtnrsc.VirtualPort;
import org.onosproject.vtnrsc.VirtualPort.State;
import org.onosproject.vtnrsc.VirtualPortId;
import org.onosproject.vtnrsc.virtualport.VirtualPortService;
-import org.onosproject.vtnrsc.web.VirtualPortCodec;
+import org.onosproject.vtnweb.web.VirtualPortCodec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllocationPoolsCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllocationPoolsCodec.java
index 57c97c1c..4b6b662f 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllocationPoolsCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllocationPoolsCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllowedAddressPairCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllowedAddressPairCodec.java
index 7960808f..8ffc4e91 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/AllowedAddressPairCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/AllowedAddressPairCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FixedIpCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FixedIpCodec.java
index 96c9bb4e..559de685 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/FixedIpCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/FixedIpCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/HostRoutesCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/HostRoutesCodec.java
index 69ca6b3f..815a0d02 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/HostRoutesCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/HostRoutesCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.java
new file mode 100644
index 00000000..28da5cd1
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/PortChainCodec.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.vtnweb.web;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.vtnrsc.TenantId;
+import org.onosproject.vtnrsc.DefaultPortChain;
+import org.onosproject.vtnrsc.FlowClassifierId;
+import org.onosproject.vtnrsc.PortChain;
+import org.onosproject.vtnrsc.PortChainId;
+import org.onosproject.vtnrsc.PortPairGroupId;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.Lists;
+
+/**
+ * Port chain JSON codec.
+ */
+public final class PortChainCodec extends JsonCodec<PortChain> {
+
+ private static final String ID = "id";
+ private static final String TENANT_ID = "tenant_id";
+ private static final String NAME = "name";
+ private static final String DESCRIPTION = "description";
+ private static final String PORT_PAIR_GROUPS = "port_pair_groups";
+ private static final String FLOW_CLASSIFIERS = "flow_classifiers";
+ private static final String MISSING_MEMBER_MESSAGE =
+ " member is required in PortChain";
+
+ @Override
+ public PortChain decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ PortChain.Builder resultBuilder = new DefaultPortChain.Builder();
+
+ String id = nullIsIllegal(json.get(ID),
+ ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setId(PortChainId.portChainId(id));
+
+ String tenantId = nullIsIllegal(json.get(TENANT_ID),
+ TENANT_ID + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setTenantId(TenantId.tenantId(tenantId));
+
+ String name = nullIsIllegal(json.get(NAME),
+ NAME + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setName(name);
+
+ String description = nullIsIllegal(json.get(DESCRIPTION),
+ DESCRIPTION + MISSING_MEMBER_MESSAGE).asText();
+ resultBuilder.setDescription(description);
+
+ ArrayNode arrayNode = (ArrayNode) json.path(PORT_PAIR_GROUPS);
+ if (arrayNode != null) {
+ List<PortPairGroupId> list = Lists.newArrayList();
+ arrayNode.forEach(i -> list.add(PortPairGroupId.portPairGroupId(i.asText())));
+ resultBuilder.setPortPairGroups(list);
+ }
+
+ arrayNode = (ArrayNode) json.path(FLOW_CLASSIFIERS);
+ if (arrayNode != null) {
+ List<FlowClassifierId> list = Lists.newArrayList();
+ arrayNode.forEach(i -> list.add(FlowClassifierId.flowClassifierId(UUID.fromString(i.asText()))));
+ resultBuilder.setFlowClassifiers(list);
+ }
+
+ return resultBuilder.build();
+ }
+
+ @Override
+ public ObjectNode encode(PortChain portChain, CodecContext context) {
+ checkNotNull(portChain, "port pair cannot be null");
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(ID, portChain.portChainId().toString())
+ .put(TENANT_ID, portChain.tenantId().toString())
+ .put(NAME, portChain.name())
+ .put(DESCRIPTION, portChain.description())
+ .put(PORT_PAIR_GROUPS, portChain.portPairGroups().toString())
+ .put(FLOW_CLASSIFIERS, portChain.flowClassifiers().toString());
+ return result;
+ }
+}
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SecurityGroupCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SecurityGroupCodec.java
index c2ded196..18ed61ba 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SecurityGroupCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SecurityGroupCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SubnetCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SubnetCodec.java
index 122b75a9..e3d92fea 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/SubnetCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/SubnetCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/TenantNetworkCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/TenantNetworkCodec.java
index 48ba3b97..8adba034 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/TenantNetworkCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/TenantNetworkCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/VirtualPortCodec.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VirtualPortCodec.java
index e57d56bc..5cea5327 100644
--- a/framework/src/onos/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/web/VirtualPortCodec.java
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/VirtualPortCodec.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.vtnrsc.web;
+package org.onosproject.vtnweb.web;
import static com.google.common.base.Preconditions.checkNotNull;
diff --git a/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/package-info.java b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/package-info.java
new file mode 100644
index 00000000..3a609435
--- /dev/null
+++ b/framework/src/onos/apps/vtn/vtnweb/src/main/java/org/onosproject/vtnweb/web/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.
+ */
+
+/**
+ * Codecs for virtual tenant objects.
+ */
+package org.onosproject.vtnweb.web;
diff --git a/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.java
new file mode 100755
index 00000000..d2230967
--- /dev/null
+++ b/framework/src/onos/bgp/api/src/main/java/org/onosproject/bgp/controller/BgpPeerManager.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.bgp.controller;
+
+/**
+ * Responsible for keeping track of the current set BGPLS peers connected to the system.
+ *
+ */
+public interface BgpPeerManager {
+
+ /**
+ * Add connected peer.
+ *
+ * @param bgpId BGP ID to add
+ * @param bgpPeer BGp peer instance
+ *
+ * @return false if peer already exist, otherwise true
+ */
+ public boolean addConnectedPeer(BGPId bgpId, BGPPeer bgpPeer);
+
+ /**
+ * Validate wheather peer is connected.
+ *
+ * @param bgpId BGP ID to validate
+ *
+ * @return true if peer exist, otherwise false
+ */
+ public boolean isPeerConnected(BGPId bgpId);
+
+ /**
+ * Remove connected peer.
+ *
+ * @param bgpId BGP ID
+ */
+ public void removeConnectedPeer(BGPId bgpId);
+
+ /**
+ * Gets connected peer.
+ *
+ * @param bgpId BGP ID
+ * @return BGPPeer the connected peer, otherwise null
+ */
+ public BGPPeer getPeer(BGPId bgpId);
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactories.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactories.java
new file mode 100755
index 00000000..71b9cbff
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactories.java
@@ -0,0 +1,82 @@
+/*
+ * 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.bgpio.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.protocol.ver4.BGPFactoryVer4;
+import org.onosproject.bgpio.types.BGPHeader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstraction to provide the version for BGP.
+ */
+public final class BGPFactories {
+
+ protected static final Logger log = LoggerFactory.getLogger(BGPFactories.class);
+
+ private static final GenericReader GENERIC_READER = new GenericReader();
+
+ private BGPFactories() {
+ }
+
+ /**
+ * Returns the instance of BGP Version.
+ *
+ * @param version BGP version
+ * @return BGP version
+ */
+ public static BGPFactory getFactory(BGPVersion version) {
+ switch (version) {
+ case BGP_4:
+ return BGPFactoryVer4.INSTANCE;
+ default:
+ throw new IllegalArgumentException("[BGPFactory:]Unknown version: " + version);
+ }
+ }
+
+ /**
+ * Reader class for reading BGP messages from channel buffer.
+ *
+ */
+ private static class GenericReader implements BGPMessageReader<BGPMessage> {
+
+ @Override
+ public BGPMessage readFrom(ChannelBuffer bb, BGPHeader bgpHeader)
+ throws BGPParseException {
+ BGPFactory factory;
+
+ if (!bb.readable()) {
+ log.error("Empty message received");
+ throw new BGPParseException("Empty message received");
+ }
+ // TODO: Currently only BGP version 4 is supported
+ factory = org.onosproject.bgpio.protocol.ver4.BGPFactoryVer4.INSTANCE;
+ return factory.getReader().readFrom(bb, bgpHeader);
+ }
+ }
+
+ /**
+ * Returns BGP messsage generic reader.
+ *
+ * @return bgp message generic reader
+ */
+ public static BGPMessageReader<BGPMessage> getGenericReader() {
+ return GENERIC_READER;
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactory.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactory.java
new file mode 100755
index 00000000..cf6bf008
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPFactory.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.bgpio.protocol;
+
+/**
+ * Abstraction of an message factory providing builder functions to BGP messages
+ * and objects.
+ *
+ */
+public interface BGPFactory {
+
+ /**
+ * Gets the builder object for a open message.
+ *
+ * @return builder object for open message
+ */
+ BGPOpenMsg.Builder openMessageBuilder();
+
+ /**
+ * Gets the builder object for a keepalive message.
+ *
+ * @return builder object for keepalive message
+ */
+ BGPKeepaliveMsg.Builder keepaliveMessageBuilder();
+
+ /**
+ * Gets the builder object for a notification message.
+ *
+ * @return builder object for notification message.
+ */
+ BGPNotificationMsg.Builder notificationMessageBuilder();
+
+ /**
+ * Gets the BGP message reader.
+ *
+ * @return BGP message reader
+ */
+ BGPMessageReader<BGPMessage> getReader();
+
+ /**
+ * Returns BGP version.
+ *
+ * @return BGP version
+ */
+ BGPVersion getVersion();
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPNotificationMsg.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPNotificationMsg.java
index 56540dd3..a1d9d578 100644
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPNotificationMsg.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/BGPNotificationMsg.java
@@ -16,36 +16,34 @@
package org.onosproject.bgpio.protocol;
import org.onosproject.bgpio.exceptions.BGPParseException;
-import org.onosproject.bgpio.types.BGPHeader;
/**
- * Abstraction of an entity providing BGP Notification Message.
+ * Abstraction of an entity providing BGP notification message.
*/
public interface BGPNotificationMsg extends BGPMessage {
/**
- * Returns errorCode in Notification message.
+ * Returns errorCode in notification message.
*
- * @return errorCode in Notification message
+ * @return errorCode in notification message
*/
byte getErrorCode();
/**
- * Returns error SubCode in Notification message.
+ * Returns error subCode in notification message.
*
- * @return error SubCode in Notification message
+ * @return error subCode in notification message
*/
byte getErrorSubCode();
/**
- * Returns error data in Notification message.
+ * Returns error data in notification message.
*
- * @return error data in Notification message
+ * @return error data in notification message
*/
byte[] getData();
/**
- * Builder interface with get and set functions to build Notification
- * message.
+ * Builder interface with get and set functions to build notification message.
*/
public interface Builder extends BGPMessage.Builder {
@@ -53,26 +51,18 @@ public interface BGPNotificationMsg extends BGPMessage {
BGPNotificationMsg build() throws BGPParseException;
/**
- * Sets notification message header and returns its builder.
- *
- * @param header of notification message
- * @return Builder by setting notification message header
- */
- Builder setNotificationMsgHeader(BGPHeader header);
-
- /**
* Sets errorCode in notification message and return its builder.
*
* @param errorCode in notification message
- * @return builder by setting ErrorCode in notification message
+ * @return builder by setting errorCode in notification message
*/
Builder setErrorCode(byte errorCode);
/**
- * Sets error SubCode in notification message and return its builder.
+ * Sets error subCode in notification message and return its builder.
*
- * @param errorSubCode in notification Message
- * @return builder by setting ErrorSubCode in notification Message
+ * @param errorSubCode in notification message
+ * @return builder by setting error subCode in notification message
*/
Builder setErrorSubCode(byte errorSubCode);
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPFactoryVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPFactoryVer4.java
new file mode 100755
index 00000000..32af3854
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPFactoryVer4.java
@@ -0,0 +1,58 @@
+/*
+ * 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.bgpio.protocol.ver4;
+
+import org.onosproject.bgpio.protocol.BGPFactory;
+import org.onosproject.bgpio.protocol.BGPKeepaliveMsg;
+import org.onosproject.bgpio.protocol.BGPMessage;
+import org.onosproject.bgpio.protocol.BGPMessageReader;
+import org.onosproject.bgpio.protocol.BGPNotificationMsg;
+import org.onosproject.bgpio.protocol.BGPOpenMsg;
+import org.onosproject.bgpio.protocol.BGPVersion;
+
+/**
+ * Provides BGP Factory and returns builder classes for all objects and messages.
+ */
+public class BGPFactoryVer4 implements BGPFactory {
+
+ public static final BGPFactoryVer4 INSTANCE = new BGPFactoryVer4();
+
+ @Override
+ public BGPOpenMsg.Builder openMessageBuilder() {
+ return new BGPOpenMsgVer4.Builder();
+ }
+
+ @Override
+ public BGPKeepaliveMsg.Builder keepaliveMessageBuilder() {
+ return new BGPKeepaliveMsgVer4.Builder();
+ }
+
+ @Override
+ public BGPNotificationMsg.Builder notificationMessageBuilder() {
+ return new BGPNotificationMsgVer4.Builder();
+ }
+
+ @Override
+ public BGPMessageReader<BGPMessage> getReader() {
+ return BGPMessageVer4.READER;
+ }
+
+ @Override
+ public BGPVersion getVersion() {
+ return BGPVersion.BGP_4;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPMessageVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPMessageVer4.java
new file mode 100755
index 00000000..d45e3de1
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPMessageVer4.java
@@ -0,0 +1,109 @@
+/*
+ * 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.bgpio.protocol.ver4;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.protocol.BGPFactories;
+import org.onosproject.bgpio.protocol.BGPMessage;
+import org.onosproject.bgpio.protocol.BGPMessageReader;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPHeader;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides BGP messages.
+ */
+public abstract class BGPMessageVer4 {
+
+ protected static final Logger log = LoggerFactory.getLogger(BGPFactories.class);
+
+ static final byte OPEN_MSG_TYPE = 0x1;
+ static final byte KEEPALIVE_MSG_TYPE = 0x4;
+ static final byte UPDATE_MSG_TYPE = 0x2;
+ static final byte NOTIFICATION_MSG_TYPE = 0x3;
+ static final int MINIMUM_COMMON_HEADER_LENGTH = 19;
+ static final int HEADER_AND_MSG_LEN = 18;
+ static final int MAXIMUM_PACKET_LENGTH = 4096;
+
+ public static final BGPMessageVer4.Reader READER = new Reader();
+
+ /**
+ * Reader class for reading BGP messages from channel buffer.
+ *
+ */
+ static class Reader implements BGPMessageReader<BGPMessage> {
+ @Override
+ public BGPMessage readFrom(ChannelBuffer cb, BGPHeader bgpHeader)
+ throws BGPParseException {
+
+ if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) {
+ log.error("Packet should have minimum length.");
+ Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH,
+ cb.readableBytes());
+ }
+ if (cb.readableBytes() > MAXIMUM_PACKET_LENGTH) {
+ log.error("Packet length should not exceed {}.", MAXIMUM_PACKET_LENGTH);
+ Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH,
+ cb.readableBytes());
+ }
+ try {
+ // fixed value property version == 4
+ byte[] marker = new byte[BGPHeader.MARKER_LENGTH];
+ cb.readBytes(marker, 0, BGPHeader.MARKER_LENGTH);
+ bgpHeader.setMarker(marker);
+ for (int i = 0; i < BGPHeader.MARKER_LENGTH; i++) {
+ if (marker[i] != (byte) 0xff) {
+ throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR,
+ BGPErrorType.CONNECTION_NOT_SYNCHRONIZED, null);
+ }
+ }
+ short length = cb.readShort();
+ if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) {
+ Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, length);
+ }
+ bgpHeader.setLength(length);
+ byte type = cb.readByte();
+ bgpHeader.setType(type);
+ log.debug("Reading update message of type " + type);
+
+ int len = length - MINIMUM_COMMON_HEADER_LENGTH;
+ switch (type) {
+ case OPEN_MSG_TYPE:
+ log.debug("OPEN MESSAGE is received");
+ return BGPOpenMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
+ case KEEPALIVE_MSG_TYPE:
+ log.debug("KEEPALIVE MESSAGE is received");
+ return BGPKeepaliveMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
+ case UPDATE_MSG_TYPE:
+ log.debug("UPDATE MESSAGE is received");
+ // TODO: Update message version 4
+ case NOTIFICATION_MSG_TYPE:
+ log.debug("NOTIFICATION MESSAGE is received");
+ return BGPNotificationMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader);
+ default:
+ Validation.validateType(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_TYPE, type);
+ return null;
+ }
+ } catch (IndexOutOfBoundsException e) {
+ throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, null);
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java
index 064deada..3bddd375 100644
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BGPNotificationMsgVer4.java
@@ -44,7 +44,7 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg {
REFERENCE : RFC 4271
*/
- protected static final Logger log = LoggerFactory.getLogger(BGPNotificationMsgVer4.class);
+ private static final Logger log = LoggerFactory.getLogger(BGPNotificationMsgVer4.class);
static final byte PACKET_VERSION = 4;
//BGPHeader(19) + Error code(1) + Error subcode(1)
@@ -52,8 +52,10 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg {
static final int PACKET_MINIMUM_LENGTH = 2;
static final BGPType MSG_TYPE = BGPType.NOTIFICATION;
static final byte DEFAULT_ERRORSUBCODE = 0;
- static final byte[] MARKER = {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01};
+ static final byte[] MARKER = {(byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff };
static final byte MESSAGE_TYPE = 3;
static final BGPHeader DEFAULT_MESSAGE_HEADER = new BGPHeader(MARKER, BGPHeader.DEFAULT_HEADER_LENGTH,
MESSAGE_TYPE);
@@ -65,7 +67,7 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg {
public static final BGPNotificationMsgVer4.Reader READER = new Reader();
/**
- * Resets fields.
+ * Initialize fields.
*/
public BGPNotificationMsgVer4() {
this.bgpHeader = null;
@@ -154,13 +156,6 @@ class BGPNotificationMsgVer4 implements BGPNotificationMsg {
}
@Override
- public Builder setNotificationMsgHeader(BGPHeader header) {
- this.bgpHeader = header;
- this.isBGPHeaderSet = true;
- return this;
- }
-
- @Override
public Builder setHeader(BGPHeader bgpMsgHeader) {
this.bgpHeader = bgpMsgHeader;
return this;
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
new file mode 100644
index 00000000..08fea4c6
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
@@ -0,0 +1,190 @@
+/*
+ * 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.bgpio.protocol.ver4;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.As4Path;
+import org.onosproject.bgpio.types.AsPath;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.types.LocalPref;
+import org.onosproject.bgpio.types.Med;
+import org.onosproject.bgpio.types.NextHop;
+import org.onosproject.bgpio.types.Origin;
+import org.onosproject.bgpio.util.UnSupportedAttribute;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides Implementation of BGP Path Attribute.
+ */
+public class BgpPathAttributes {
+
+ /* Path attribute:
+ <attribute type, attribute length, attribute value>
+
+ 0 1
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Attr. Flags |Attr. Type Code|
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ REFERENCE : RFC 4271
+ */
+ protected static final Logger log = LoggerFactory.getLogger(BgpPathAttributes.class);
+
+ public static final int LINK_STATE_ATTRIBUTE_TYPE = 50;
+ public static final int MPREACHNLRI_TYPE = 14;
+ public static final int MPUNREACHNLRI_TYPE = 15;
+
+ private final List<BGPValueType> pathAttribute;
+
+ /**
+ * Initialize parameter.
+ */
+ public BgpPathAttributes() {
+ this.pathAttribute = null;
+ }
+
+ /**
+ * Constructor to initialize parameters for BGP path attributes.
+ *
+ * @param pathAttribute list of path attributes
+ */
+ public BgpPathAttributes(List<BGPValueType> pathAttribute) {
+ this.pathAttribute = pathAttribute;
+ }
+
+ /**
+ * Returns list of path attributes.
+ *
+ * @return list of path attributes
+ */
+ public List<BGPValueType> pathAttributes() {
+ return this.pathAttribute;
+ }
+
+ /**
+ * Reads from channelBuffer and parses BGP path attributes.
+ *
+ * @param cb channelBuffer
+ * @return object of BgpPathAttributes
+ * @throws BGPParseException while parsing BGP path attributes
+ */
+ public static BgpPathAttributes read(ChannelBuffer cb)
+ throws BGPParseException {
+
+ BGPValueType pathAttribute = null;
+ List<BGPValueType> pathAttributeList = new LinkedList<>();
+ boolean isOrigin = false;
+ boolean isAsPath = false;
+ boolean isNextHop = false;
+ boolean isMpReach = false;
+ boolean isMpUnReach = false;
+ while (cb.readableBytes() > 0) {
+ cb.markReaderIndex();
+ byte flags = cb.readByte();
+ byte typeCode = cb.readByte();
+ cb.resetReaderIndex();
+ switch (typeCode) {
+ case Origin.ORIGIN_TYPE:
+ pathAttribute = Origin.read(cb);
+ isOrigin = ((Origin) pathAttribute).isOriginSet();
+ break;
+ case AsPath.ASPATH_TYPE:
+ pathAttribute = AsPath.read(cb);
+ isAsPath = ((AsPath) pathAttribute).isaspathSet();
+ break;
+ case As4Path.AS4PATH_TYPE:
+ pathAttribute = As4Path.read(cb);
+ break;
+ case NextHop.NEXTHOP_TYPE:
+ pathAttribute = NextHop.read(cb);
+ isNextHop = ((NextHop) pathAttribute).isNextHopSet();
+ break;
+ case Med.MED_TYPE:
+ pathAttribute = Med.read(cb);
+ break;
+ case LocalPref.LOCAL_PREF_TYPE:
+ pathAttribute = LocalPref.read(cb);
+ break;
+ case MPREACHNLRI_TYPE:
+ //TODO: To be merged later
+ break;
+ case MPUNREACHNLRI_TYPE:
+ //TODO: To be merged later
+ break;
+ case LINK_STATE_ATTRIBUTE_TYPE:
+ //TODO: To be merged later
+ break;
+ default:
+ //skip bytes for unsupported attribute types
+ UnSupportedAttribute.read(cb);
+ }
+ pathAttributeList.add(pathAttribute);
+ }
+
+ checkMandatoryAttr(isOrigin, isAsPath, isNextHop, isMpReach, isMpUnReach);
+ //TODO:if mp_reach or mp_unreach not present ignore the packet
+ return new BgpPathAttributes(pathAttributeList);
+ }
+
+ /**
+ * Checks mandatory attributes are presents, if not present throws exception.
+ *
+ * @param isOrigin say whether origin attribute is present
+ * @param isAsPath say whether aspath attribute is present
+ * @param isNextHop say whether nexthop attribute is present
+ * @param isMpReach say whether mpreach attribute is present
+ * @param isMpUnReach say whether mpunreach attribute is present
+ * @throws BGPParseException if mandatory path attribute is not present
+ */
+ public static void checkMandatoryAttr(boolean isOrigin, boolean isAsPath,
+ boolean isNextHop, boolean isMpReach, boolean isMpUnReach)
+ throws BGPParseException {
+ if (!isOrigin) {
+ log.debug("Mandatory Attributes not Present");
+ Validation.validateType(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
+ Origin.ORIGIN_TYPE);
+ }
+ if (!isAsPath) {
+ log.debug("Mandatory Attributes not Present");
+ Validation.validateType(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
+ AsPath.ASPATH_TYPE);
+ }
+ if (!isMpUnReach && !isMpReach && !isNextHop) {
+ log.debug("Mandatory Attributes not Present");
+ Validation.validateType(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
+ NextHop.NEXTHOP_TYPE);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("pathAttribute", pathAttribute)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java
new file mode 100644
index 00000000..90e94e88
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/As4Path.java
@@ -0,0 +1,170 @@
+/*
+ * 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.bgpio.types;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides Implementation of As4Path BGP Path Attribute.
+ */
+public class As4Path implements BGPValueType {
+ private static final Logger log = LoggerFactory.getLogger(AsPath.class);
+ public static final byte AS4PATH_TYPE = 17;
+ public static final byte ASNUM_SIZE = 4;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+
+ private List<Integer> as4pathSet;
+ private List<Integer> as4pathSeq;
+
+ /**
+ * Initialize fields.
+ */
+ public As4Path() {
+ this.as4pathSeq = null;
+ this.as4pathSet = null;
+ }
+
+ /**
+ * Constructor to initialize parameters.
+ *
+ * @param as4pathSet AS4path Set
+ * @param as4pathSeq AS4path Sequence
+ */
+ public As4Path(List<Integer> as4pathSet, List<Integer> as4pathSeq) {
+ this.as4pathSeq = as4pathSeq;
+ this.as4pathSet = as4pathSet;
+ }
+
+ /**
+ * Reads from the channel buffer and parses As4Path.
+ *
+ * @param cb ChannelBuffer
+ * @return object of As4Path
+ * @throws BGPParseException while parsing As4Path
+ */
+ public static As4Path read(ChannelBuffer cb) throws BGPParseException {
+ List<Integer> as4pathSet = new ArrayList<>();
+ List<Integer> as4pathSeq = new ArrayList<>();
+ ChannelBuffer tempCb = cb.copy();
+ Validation validation = Validation.parseAttributeHeader(cb);
+
+ if (cb.readableBytes() < validation.getLength()) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ validation.getLength());
+ }
+ //if fourth bit is set length is read as short otherwise as byte , len includes type, length and value
+ int len = validation.isShort() ? validation.getLength() + TYPE_AND_LEN_AS_SHORT : validation
+ .getLength() + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ ChannelBuffer tempBuf = cb.readBytes(validation.getLength());
+ while (tempBuf.readableBytes() > 0) {
+ byte pathSegType = tempBuf.readByte();
+ //no of ASes
+ byte pathSegLen = tempBuf.readByte();
+ //length = no of Ases * ASnum size (4 bytes)
+ int length = pathSegLen * ASNUM_SIZE;
+ if (tempBuf.readableBytes() < length) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR, length);
+ }
+ ChannelBuffer aspathBuf = tempBuf.readBytes(length);
+ while (aspathBuf.readableBytes() > 0) {
+ int asNum;
+ asNum = aspathBuf.readInt();
+ switch (pathSegType) {
+ case AsPath.ASPATH_SET_TYPE:
+ as4pathSet.add(asNum);
+ break;
+ case AsPath.ASPATH_SEQ_TYPE:
+ as4pathSeq.add(asNum);
+ break;
+ default: log.debug("Other type Not Supported:" + pathSegType);
+ }
+ }
+ }
+ return new As4Path(as4pathSet, as4pathSeq);
+ }
+
+ @Override
+ public short getType() {
+ return AS4PATH_TYPE;
+ }
+
+ /**
+ * Returns list of ASNum in AS4path Sequence.
+ *
+ * @return list of ASNum in AS4path Sequence
+ */
+ public List<Integer> as4PathSEQ() {
+ return this.as4pathSeq;
+ }
+
+ /**
+ * Returns list of ASNum in AS4path Set.
+ *
+ * @return list of ASNum in AS4path Set
+ */
+ public List<Integer> as4PathSET() {
+ return this.as4pathSet;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(as4pathSet, as4pathSeq);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof As4Path) {
+ As4Path other = (As4Path) obj;
+ return Objects.equals(as4pathSet, other.as4pathSet) && Objects.equals(as4pathSeq, other.as4pathSeq);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .omitNullValues()
+ .add("as4pathSet", as4pathSet)
+ .add("as4pathSeq", as4pathSeq)
+ .toString();
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not required to Implement as of now
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java
new file mode 100644
index 00000000..100e14d7
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/AsPath.java
@@ -0,0 +1,209 @@
+/*
+ * 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.bgpio.types;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides Implementation of AsPath mandatory BGP Path Attribute.
+ */
+public class AsPath implements BGPValueType {
+ /**
+ * Enum to provide AS types.
+ */
+ public enum ASTYPE {
+ AS_SET(1), AS_SEQUENCE(2), AS_CONFED_SEQUENCE(3), AS_CONFED_SET(4);
+ int value;
+
+ /**
+ * Assign val with the value as the AS type.
+ *
+ * @param val AS type
+ */
+ ASTYPE(int val) {
+ value = val;
+ }
+
+ /**
+ * Returns value of AS type.
+ *
+ * @return AS type
+ */
+ public byte getType() {
+ return (byte) value;
+ }
+ }
+
+ private static final Logger log = LoggerFactory.getLogger(AsPath.class);
+ public static final byte ASPATH_TYPE = 2;
+ public static final byte ASPATH_SET_TYPE = 1;
+ public static final byte ASPATH_SEQ_TYPE = 2;
+ public static final byte ASNUM_SIZE = 2;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+
+ private boolean isAsPath = false;
+ private List<Short> aspathSet;
+ private List<Short> aspathSeq;
+
+ /**
+ * Initialize Fields.
+ */
+ public AsPath() {
+ this.aspathSeq = null;
+ this.aspathSet = null;
+ }
+
+ /**
+ * Constructor to initialize parameters.
+ *
+ * @param aspathSet ASpath Set type
+ * @param aspathSeq ASpath Sequence type
+ */
+ public AsPath(List<Short> aspathSet, List<Short> aspathSeq) {
+ this.aspathSeq = aspathSeq;
+ this.aspathSet = aspathSet;
+ this.isAsPath = true;
+ }
+
+ /**
+ * Reads from the channel buffer and parses AsPath.
+ *
+ * @param cb ChannelBuffer
+ * @return object of AsPath
+ * @throws BGPParseException while parsing AsPath
+ */
+ public static AsPath read(ChannelBuffer cb) throws BGPParseException {
+ List<Short> aspathSet = new ArrayList<>();
+ List<Short> aspathSeq = new ArrayList<>();
+ ChannelBuffer tempCb = cb.copy();
+ Validation validation = Validation.parseAttributeHeader(cb);
+
+ if (cb.readableBytes() < validation.getLength()) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ validation.getLength());
+ }
+ //if fourth bit is set, length is read as short otherwise as byte , len includes type, length and value
+ int len = validation.isShort() ? validation.getLength() + TYPE_AND_LEN_AS_SHORT : validation
+ .getLength() + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if (validation.getFirstBit() && !validation.getSecondBit() && validation.getThirdBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ ChannelBuffer tempBuf = cb.readBytes(validation.getLength());
+ while (tempBuf.readableBytes() > 0) {
+ byte pathSegType = tempBuf.readByte();
+ //no of ASes
+ byte pathSegLen = tempBuf.readByte();
+ int length = pathSegLen * ASNUM_SIZE;
+ if (tempBuf.readableBytes() < length) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR, length);
+ }
+ ChannelBuffer aspathBuf = tempBuf.readBytes(length);
+ while (aspathBuf.readableBytes() > 0) {
+ short asNum;
+ asNum = aspathBuf.readShort();
+ switch (pathSegType) {
+ case ASPATH_SET_TYPE:
+ aspathSet.add(asNum);
+ break;
+ case ASPATH_SEQ_TYPE:
+ aspathSeq.add(asNum);
+ break;
+ default: log.debug("Other type Not Supported:" + pathSegType);
+ }
+ }
+ }
+ return new AsPath(aspathSet, aspathSeq);
+ }
+
+ @Override
+ public short getType() {
+ return ASPATH_TYPE;
+ }
+
+ /**
+ * Returns whether ASpath path attribute is present.
+ *
+ * @return whether ASpath path attribute is present
+ */
+ public boolean isaspathSet() {
+ return this.isAsPath;
+ }
+
+ /**
+ * Returns list of ASNum in ASpath Sequence.
+ *
+ * @return list of ASNum in ASpath Sequence
+ */
+ public List<Short> asPathSeq() {
+ return this.aspathSeq;
+ }
+
+ /**
+ * Returns list of ASNum in ASpath SET.
+ *
+ * @return list of ASNum in ASpath SET
+ */
+ public List<Short> asPathSet() {
+ return this.aspathSet;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(aspathSet, aspathSeq);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof AsPath) {
+ AsPath other = (AsPath) obj;
+ return Objects.equals(aspathSet, other.aspathSet) && Objects.equals(aspathSeq, other.aspathSeq);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .omitNullValues()
+ .add("aspathSet", aspathSet)
+ .add("aspathSeq", aspathSeq)
+ .toString();
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not required to Implement as of now
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java
new file mode 100644
index 00000000..048d81ee
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/LocalPref.java
@@ -0,0 +1,120 @@
+/*
+ * 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.bgpio.types;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides implementation of LocalPref BGP Path Attribute.
+ */
+public class LocalPref implements BGPValueType {
+
+ private static final Logger log = LoggerFactory.getLogger(LocalPref.class);
+ public static final byte LOCAL_PREF_TYPE = 5;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+ public static final byte LOCAL_PREF_MAX_LEN = 4;
+
+ private int localPref;
+
+ /**
+ * Constructor to initialize LocalPref.
+ *
+ * @param localPref local preference
+ */
+ public LocalPref(int localPref) {
+ this.localPref = localPref;
+ }
+
+ /**
+ * Returns local preference value.
+ *
+ * @return local preference value
+ */
+ public int localPref() {
+ return this.localPref;
+ }
+
+ /**
+ * Reads the channel buffer and returns object of LocalPref.
+ *
+ * @param cb channelBuffer
+ * @return object of LocalPref
+ * @throws BGPParseException while parsing localPref attribute
+ */
+ public static LocalPref read(ChannelBuffer cb) throws BGPParseException {
+ int localPref;
+ ChannelBuffer tempCb = cb.copy();
+ Validation parseFlags = Validation.parseAttributeHeader(cb);
+ if ((parseFlags.getLength() > LOCAL_PREF_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ parseFlags.getLength());
+ }
+
+ int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN_AS_SHORT : parseFlags.getLength()
+ + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if (parseFlags.getFirstBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ localPref = cb.readInt();
+ return new LocalPref(localPref);
+ }
+
+ @Override
+ public short getType() {
+ return LOCAL_PREF_TYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(localPref);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof LocalPref) {
+ LocalPref other = (LocalPref) obj;
+ return Objects.equals(localPref, other.localPref);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("localPref", localPref)
+ .toString();
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not to implement as of now
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.java
new file mode 100644
index 00000000..49e1fc5a
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Med.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.bgpio.types;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides Implementation of Med BGP Path Attribute.
+ */
+public class Med implements BGPValueType {
+ private static final Logger log = LoggerFactory.getLogger(Med.class);
+ public static final byte MED_TYPE = 4;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+ public static final byte MED_MAX_LEN = 4;
+
+ private int med;
+
+ /**
+ * Constructor to initialize med.
+ *
+ * @param med MULTI_EXIT_DISC value
+ */
+ public Med(int med) {
+ this.med = med;
+ }
+
+ /**
+ * Returns Med value.
+ *
+ * @return Med value
+ */
+ public int med() {
+ return this.med;
+ }
+
+ /**
+ * Reads the channel buffer and returns object of Med.
+ *
+ * @param cb ChannelBuffer
+ * @return object of Med
+ * @throws BGPParseException while parsing Med path attribute
+ */
+ public static Med read(ChannelBuffer cb) throws BGPParseException {
+ int med;
+ ChannelBuffer tempCb = cb.copy();
+ Validation parseFlags = Validation.parseAttributeHeader(cb);
+
+ if ((parseFlags.getLength() > MED_MAX_LEN) || cb.readableBytes() < parseFlags.getLength()) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ parseFlags.getLength());
+ }
+ int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN_AS_SHORT : parseFlags
+ .getLength() + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if (!parseFlags.getFirstBit() && parseFlags.getSecondBit() && parseFlags.getThirdBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ med = cb.readInt();
+ return new Med(med);
+ }
+
+ @Override
+ public short getType() {
+ return MED_TYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(med);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Med) {
+ Med other = (Med) obj;
+ return Objects.equals(med, other.med);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("med", med)
+ .toString();
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not to implement as of now
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java
new file mode 100644
index 00000000..353ec3d5
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/NextHop.java
@@ -0,0 +1,138 @@
+/*
+ * 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.bgpio.types;
+
+import java.net.InetAddress;
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Preconditions;
+
+/**
+ * Implementation of NextHop BGP Path Attribute.
+ */
+public class NextHop implements BGPValueType {
+ private static final Logger log = LoggerFactory.getLogger(NextHop.class);
+ public static final byte NEXTHOP_TYPE = 3;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+
+ private boolean isNextHop = false;
+ private Ip4Address nextHop;
+
+ /**
+ * Constructor to initialize parameters.
+ *
+ * @param nextHop nextHop address
+ */
+ public NextHop(Ip4Address nextHop) {
+ this.nextHop = Preconditions.checkNotNull(nextHop);
+ this.isNextHop = true;
+ }
+
+ /**
+ * Returns whether next hop is present.
+ *
+ * @return whether next hop is present
+ */
+ public boolean isNextHopSet() {
+ return this.isNextHop;
+ }
+
+ /**
+ * Reads from ChannelBuffer and parses NextHop.
+ *
+ * @param cb ChannelBuffer
+ * @return object of NextHop
+ * @throws BGPParseException while parsing nexthop attribute
+ */
+ public static NextHop read(ChannelBuffer cb) throws BGPParseException {
+ Ip4Address nextHop;
+ ChannelBuffer tempCb = cb.copy();
+ Validation parseFlags = Validation.parseAttributeHeader(cb);
+
+ if (cb.readableBytes() < parseFlags.getLength()) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ parseFlags.getLength());
+ }
+ int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN_AS_SHORT : parseFlags
+ .getLength() + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ //TODO: use Validation.toInetAddress once Validation is merged
+ InetAddress ipAddress = (InetAddress) cb.readBytes(parseFlags.getLength());
+ if (ipAddress.isMulticastAddress()) {
+ throw new BGPParseException("Multicast address is not supported");
+ }
+
+ nextHop = Ip4Address.valueOf(ipAddress);
+ return new NextHop(nextHop);
+ }
+
+ /**
+ * Return nexthop address.
+ *
+ * @return nexthop address
+ */
+ public Ip4Address nextHop() {
+ return nextHop;
+ }
+
+ @Override
+ public short getType() {
+ return NEXTHOP_TYPE;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not required to be implemented now
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nextHop);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NextHop) {
+ NextHop other = (NextHop) obj;
+ return Objects.equals(nextHop, other.nextHop);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("nextHop", nextHop)
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java
new file mode 100644
index 00000000..3b2070de
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/Origin.java
@@ -0,0 +1,166 @@
+/*
+ * 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.bgpio.types;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Provides Implementation of mandatory BGP Origin path attribute.
+ */
+public class Origin implements BGPValueType {
+ private static final Logger log = LoggerFactory.getLogger(Origin.class);
+
+ /**
+ * Enum to provide ORIGIN types.
+ */
+ public enum ORIGINTYPE {
+ IGP(0), EGP(1), INCOMPLETE(2);
+ int value;
+ /**
+ * Assign val with the value as the ORIGIN type.
+ *
+ * @param val ORIGIN type
+ */
+ ORIGINTYPE(int val) {
+ value = val;
+ }
+
+ /**
+ * Returns value of ORIGIN type.
+ *
+ * @return ORIGIN type
+ */
+ public byte getType() {
+ return (byte) value;
+ }
+ }
+
+ public static final byte ORIGIN_TYPE = 1;
+ public static final byte ORIGIN_VALUE_LEN = 1;
+ public static final int TYPE_AND_LEN_AS_SHORT = 4;
+ public static final int TYPE_AND_LEN_AS_BYTE = 3;
+
+ private boolean isOrigin = false;
+ private byte origin;
+
+ /**
+ * Constructor to initialize parameters.
+ *
+ * @param origin origin value
+ */
+ public Origin(byte origin) {
+ this.origin = origin;
+ this.isOrigin = true;
+ }
+
+ /**
+ * Returns true if origin attribute is present otherwise false.
+ *
+ * @return whether origin is present or not
+ */
+ public boolean isOriginSet() {
+ return this.isOrigin;
+ }
+
+ /**
+ * Returns type of Origin in Enum values.
+ *
+ * @return type of Origin in Enum values
+ */
+ public ORIGINTYPE origin() {
+ if (this.origin == 0) {
+ return ORIGINTYPE.IGP;
+ } else if (this.origin == 1) {
+ return ORIGINTYPE.EGP;
+ } else {
+ return ORIGINTYPE.INCOMPLETE;
+ }
+ }
+
+ /**
+ * Reads from ChannelBuffer and parses Origin.
+ *
+ * @param cb ChannelBuffer
+ * @return object of Origin
+ * @throws BGPParseException while parsing Origin path attribute
+ */
+ public static Origin read(ChannelBuffer cb) throws BGPParseException {
+ ChannelBuffer tempCb = cb.copy();
+ Validation parseFlags = Validation.parseAttributeHeader(cb);
+
+ int len = parseFlags.isShort() ? parseFlags.getLength() + TYPE_AND_LEN_AS_SHORT : parseFlags
+ .getLength() + TYPE_AND_LEN_AS_BYTE;
+ ChannelBuffer data = tempCb.readBytes(len);
+ if ((parseFlags.getLength() > ORIGIN_VALUE_LEN) || (cb.readableBytes() < parseFlags.getLength())) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ parseFlags.getLength());
+ }
+ if (parseFlags.getFirstBit() && !parseFlags.getSecondBit() && parseFlags.getThirdBit()) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.ATTRIBUTE_FLAGS_ERROR, data);
+ }
+
+ byte originValue;
+ originValue = cb.readByte();
+ if ((originValue != ORIGINTYPE.INCOMPLETE.value) || (originValue != ORIGINTYPE.IGP.value) ||
+ (originValue != ORIGINTYPE.EGP.value)) {
+ throw new BGPParseException(BGPErrorType.UPDATE_MESSAGE_ERROR, BGPErrorType.INVALID_ORIGIN_ATTRIBUTE, data);
+ }
+ return new Origin(originValue);
+ }
+
+ @Override
+ public short getType() {
+ return ORIGIN_TYPE;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ //Not required to Implement as of now
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(origin);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof Origin) {
+ Origin other = (Origin) obj;
+ return Objects.equals(origin, other.origin);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("origin", origin)
+ .toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java
index ba02f6d1..e7f4a4c0 100755
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrNodeFlagBitTlv.java
@@ -30,7 +30,7 @@ import com.google.common.base.MoreObjects;
/**
* Implements BGP attribute node flag.
*/
-public class BgpAttrNodeFlagBitTlv implements BGPValueType {
+public final class BgpAttrNodeFlagBitTlv implements BGPValueType {
protected static final Logger log = LoggerFactory
.getLogger(BgpAttrNodeFlagBitTlv.class);
@@ -38,16 +38,15 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
public static final int ATTRNODE_FLAGBIT = 1024;
/* Node flag bit TLV */
- private boolean bOverloadBit;
- private boolean bAttachedBit;
- private boolean bExternalBit;
- private boolean bABRBit;
+ private final boolean bOverloadBit;
+ private final boolean bAttachedBit;
+ private final boolean bExternalBit;
+ private final boolean bAbrBit;
- public static final int BIT_SET = 1;
- public static final int FIRST_BIT = 0x80;
- public static final int SECOND_BIT = 0x40;
- public static final int THIRD_BIT = 0x20;
- public static final int FOURTH_BIT = 0x01;
+ public static final byte FIRST_BIT = (byte) 0x80;
+ public static final byte SECOND_BIT = 0x40;
+ public static final byte THIRD_BIT = 0x20;
+ public static final byte FOURTH_BIT = 0x01;
/**
* Constructor to initialize parameters.
@@ -55,14 +54,31 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
* @param bOverloadBit Overload bit
* @param bAttachedBit Attached bit
* @param bExternalBit External bit
- * @param bABRBit ABR Bit
+ * @param bAbrBit ABR Bit
*/
- BgpAttrNodeFlagBitTlv(boolean bOverloadBit, boolean bAttachedBit,
- boolean bExternalBit, boolean bABRBit) {
+ private BgpAttrNodeFlagBitTlv(boolean bOverloadBit, boolean bAttachedBit,
+ boolean bExternalBit, boolean bAbrBit) {
this.bOverloadBit = bOverloadBit;
this.bAttachedBit = bAttachedBit;
this.bExternalBit = bExternalBit;
- this.bABRBit = bABRBit;
+ this.bAbrBit = bAbrBit;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param bOverloadBit Overload bit
+ * @param bAttachedBit Attached bit
+ * @param bExternalBit External bit
+ * @param bAbrBit ABR Bit
+ * @return object of BgpAttrNodeFlagBitTlv
+ */
+ public static BgpAttrNodeFlagBitTlv of(final boolean bOverloadBit,
+ final boolean bAttachedBit,
+ final boolean bExternalBit,
+ final boolean bAbrBit) {
+ return new BgpAttrNodeFlagBitTlv(bOverloadBit, bAttachedBit,
+ bExternalBit, bAbrBit);
}
/**
@@ -77,11 +93,11 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
boolean bOverloadBit = false;
boolean bAttachedBit = false;
boolean bExternalBit = false;
- boolean bABRBit = false;
+ boolean bAbrBit = false;
short lsAttrLength = cb.readShort();
- if (lsAttrLength != 1) {
+ if ((lsAttrLength != 1) || (cb.readableBytes() < lsAttrLength)) {
Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
lsAttrLength);
@@ -89,13 +105,13 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
byte nodeFlagBits = cb.readByte();
- bOverloadBit = ((nodeFlagBits & (byte) FIRST_BIT) == FIRST_BIT);
- bAttachedBit = ((nodeFlagBits & (byte) SECOND_BIT) == SECOND_BIT);
- bExternalBit = ((nodeFlagBits & (byte) THIRD_BIT) == THIRD_BIT);
- bABRBit = ((nodeFlagBits & (byte) FOURTH_BIT) == FOURTH_BIT);
+ bOverloadBit = ((nodeFlagBits & FIRST_BIT) == FIRST_BIT);
+ bAttachedBit = ((nodeFlagBits & SECOND_BIT) == SECOND_BIT);
+ bExternalBit = ((nodeFlagBits & THIRD_BIT) == THIRD_BIT);
+ bAbrBit = ((nodeFlagBits & FOURTH_BIT) == FOURTH_BIT);
- return new BgpAttrNodeFlagBitTlv(bOverloadBit, bAttachedBit,
- bExternalBit, bABRBit);
+ return BgpAttrNodeFlagBitTlv.of(bOverloadBit, bAttachedBit,
+ bExternalBit, bAbrBit);
}
/**
@@ -103,7 +119,7 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
*
* @return Overload Bit
*/
- boolean getOverLoadBit() {
+ public boolean overLoadBit() {
return bOverloadBit;
}
@@ -112,7 +128,7 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
*
* @return Attached Bit
*/
- boolean getAttachedBit() {
+ public boolean attachedBit() {
return bAttachedBit;
}
@@ -121,7 +137,7 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
*
* @return External Bit
*/
- boolean getExternalBit() {
+ public boolean externalBit() {
return bExternalBit;
}
@@ -130,8 +146,8 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
*
* @return ABR Bit
*/
- boolean getABRBit() {
- return bABRBit;
+ public boolean abrBit() {
+ return bAbrBit;
}
@Override
@@ -141,13 +157,13 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
@Override
public int write(ChannelBuffer cb) {
- // TODO will be implementing it later
+ // TODO This will be implemented in the next version
return 0;
}
@Override
public int hashCode() {
- return Objects.hash(bOverloadBit, bAttachedBit, bExternalBit, bABRBit);
+ return Objects.hash(bOverloadBit, bAttachedBit, bExternalBit, bAbrBit);
}
@Override
@@ -161,7 +177,7 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
return Objects.equals(bOverloadBit, other.bOverloadBit)
&& Objects.equals(bAttachedBit, other.bAttachedBit)
&& Objects.equals(bExternalBit, other.bExternalBit)
- && Objects.equals(bABRBit, other.bABRBit);
+ && Objects.equals(bAbrBit, other.bAbrBit);
}
return false;
}
@@ -171,7 +187,7 @@ public class BgpAttrNodeFlagBitTlv implements BGPValueType {
return MoreObjects.toStringHelper(getClass())
.add("bOverloadBit", bOverloadBit)
.add("bAttachedBit", bAttachedBit)
- .add("bExternalBit", bExternalBit).add("bABRBit", bABRBit)
+ .add("bExternalBit", bExternalBit).add("bAbrBit", bAbrBit)
.toString();
}
}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java
index 00dffb58..a10d167a 100755
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV4.java
@@ -31,15 +31,15 @@ import com.google.common.base.MoreObjects;
/**
* Implements BGP attribute node router ID.
*/
-public class BgpAttrRouterIdV4 implements BGPValueType {
+public final class BgpAttrRouterIdV4 implements BGPValueType {
protected static final Logger log = LoggerFactory
.getLogger(BgpAttrRouterIdV4.class);
- public short sType;
+ private final short sType;
/* IPv4 Router-ID of Node */
- private Ip4Address ip4RouterId;
+ private final Ip4Address ip4RouterId;
/**
* Constructor to initialize the value.
@@ -47,35 +47,45 @@ public class BgpAttrRouterIdV4 implements BGPValueType {
* @param ip4RouterId IPV4 address of router
* @param sType TLV type
*/
- BgpAttrRouterIdV4(Ip4Address ip4RouterId, short sType) {
+ private BgpAttrRouterIdV4(Ip4Address ip4RouterId, short sType) {
this.ip4RouterId = ip4RouterId;
this.sType = sType;
}
/**
+ * Returns object of this class with specified values.
+ *
+ * @param ip4RouterId IPv4 address
+ * @param sType Type of this TLV
+ * @return object of BgpAttrRouterIdV4
+ */
+ public static BgpAttrRouterIdV4 of(final Ip4Address ip4RouterId,
+ final short sType) {
+ return new BgpAttrRouterIdV4(ip4RouterId, sType);
+ }
+
+ /**
* Reads the IPv4 Router-ID.
*
* @param cb ChannelBuffer
+ * @param sType tag type
* @return object of BgpAttrRouterIdV4
- * @throws BGPParseException while parsing BgpAttrNodeRouterId
+ * @throws BGPParseException while parsing BgpAttrRouterIdV4
*/
public static BgpAttrRouterIdV4 read(ChannelBuffer cb, short sType)
throws BGPParseException {
- byte[] ipBytes;
- Ip4Address ip4RouterId;
-
short lsAttrLength = cb.readShort();
- if (4 != lsAttrLength) {
+ if ((lsAttrLength != 4) || (cb.readableBytes() < lsAttrLength)) {
Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
lsAttrLength);
}
- ipBytes = new byte[lsAttrLength];
- cb.readBytes(ipBytes);
- ip4RouterId = Ip4Address.valueOf(ipBytes);
- return new BgpAttrRouterIdV4(ip4RouterId, sType);
+ byte[] ipBytes = new byte[lsAttrLength];
+ cb.readBytes(ipBytes, 0, lsAttrLength);
+ Ip4Address ip4RouterId = Ip4Address.valueOf(ipBytes);
+ return BgpAttrRouterIdV4.of(ip4RouterId, sType);
}
/**
@@ -83,7 +93,7 @@ public class BgpAttrRouterIdV4 implements BGPValueType {
*
* @return Router ID
*/
- Ip4Address getAttrRouterId() {
+ public Ip4Address attrRouterId() {
return ip4RouterId;
}
@@ -112,7 +122,7 @@ public class BgpAttrRouterIdV4 implements BGPValueType {
@Override
public int write(ChannelBuffer cb) {
- // TODO Auto-generated method stub
+ // TODO This will be implemented in the next version
return 0;
}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java
index 561c3d4c..ea63c379 100755
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpAttrRouterIdV6.java
@@ -31,15 +31,15 @@ import com.google.common.base.MoreObjects;
/**
* Implements BGP attribute IPv6 router ID.
*/
-public class BgpAttrRouterIdV6 implements BGPValueType {
+public final class BgpAttrRouterIdV6 implements BGPValueType {
protected static final Logger log = LoggerFactory
.getLogger(BgpAttrRouterIdV6.class);
- public short sType;
+ private final short sType;
/* IPv4 Router-ID of Node */
- private Ip6Address ip6RouterId;
+ private final Ip6Address ip6RouterId;
/**
* Constructor to initialize the value.
@@ -47,15 +47,28 @@ public class BgpAttrRouterIdV6 implements BGPValueType {
* @param ip6RouterId IPV6 address of the router ID
* @param sType TLV type
*/
- BgpAttrRouterIdV6(Ip6Address ip6RouterId, short sType) {
+ private BgpAttrRouterIdV6(Ip6Address ip6RouterId, short sType) {
this.ip6RouterId = ip6RouterId;
this.sType = sType;
}
/**
+ * Returns object of this class with specified values.
+ *
+ * @param ip6RouterId IPV6 address of the router ID
+ * @param sType TLV type
+ * @return object of BgpAttrRouterIdV6
+ */
+ public static BgpAttrRouterIdV6 of(final Ip6Address ip6RouterId,
+ final short sType) {
+ return new BgpAttrRouterIdV6(ip6RouterId, sType);
+ }
+
+ /**
* Reads the IPv6 Router-ID.
*
* @param cb ChannelBuffer
+ * @param sType TLV type
* @return object of BgpAttrRouterIdV6
* @throws BGPParseException while parsing BgpAttrRouterIdV6
*/
@@ -66,7 +79,7 @@ public class BgpAttrRouterIdV6 implements BGPValueType {
short lsAttrLength = cb.readShort();
- if (16 != lsAttrLength) {
+ if ((lsAttrLength != 16) || (cb.readableBytes() < lsAttrLength)) {
Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
lsAttrLength);
@@ -75,7 +88,7 @@ public class BgpAttrRouterIdV6 implements BGPValueType {
ipBytes = new byte[lsAttrLength];
cb.readBytes(ipBytes);
ip6RouterId = Ip6Address.valueOf(ipBytes);
- return new BgpAttrRouterIdV6(ip6RouterId, sType);
+ return BgpAttrRouterIdV6.of(ip6RouterId, sType);
}
/**
@@ -83,7 +96,7 @@ public class BgpAttrRouterIdV6 implements BGPValueType {
*
* @return Router ID
*/
- Ip6Address getAttrRouterId() {
+ public Ip6Address attrRouterId() {
return ip6RouterId;
}
@@ -112,7 +125,7 @@ public class BgpAttrRouterIdV6 implements BGPValueType {
@Override
public int write(ChannelBuffer cb) {
- // TODO Auto-generated method stub
+ // TODO This will be implemented in the next version
return 0;
}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java
new file mode 100755
index 00000000..c1cb299c
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrIgpMetric.java
@@ -0,0 +1,172 @@
+/*
+ * 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.bgpio.types.attr;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implements BGP link IGP metric attribute.
+ */
+public class BgpLinkAttrIgpMetric implements BGPValueType {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(BgpLinkAttrIgpMetric.class);
+
+ public static final int ATTRLINK_IGPMETRIC = 1095;
+ public static final int ATTRLINK_MAX_LEN = 3;
+
+ /* Variable metric length based on protocol */
+ public static final int ISIS_SMALL_METRIC = 1;
+ public static final int OSPF_LINK_METRIC = 2;
+ public static final int ISIS_WIDE_METRIC = 3;
+
+ /* IGP Metric */
+ private final int igpMetric;
+ private final int igpMetricLen;
+
+ /**
+ * Constructor to initialize the value.
+ *
+ * @param igpMetric 3 byte IGP metric data.
+ * @param igpMetricLen length of IGP metric data.
+ */
+ public BgpLinkAttrIgpMetric(final int igpMetric, final int igpMetricLen) {
+ this.igpMetric = igpMetric;
+ this.igpMetricLen = igpMetricLen;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param igpMetric 3 byte IGP metric data.
+ * @param igpMetricLen length of IGP metric data.
+ * @return object of BgpLinkAttrIgpMetric
+ */
+ public static BgpLinkAttrIgpMetric of(final int igpMetric,
+ final int igpMetricLen) {
+ return new BgpLinkAttrIgpMetric(igpMetric, igpMetricLen);
+ }
+
+ /**
+ * Reads the BGP link attributes IGP Metric.
+ *
+ * @param cb Channel buffer
+ * @return object of type BgpLinkAttrIgpMetric
+ * @throws BGPParseException while parsing BgpLinkAttrIgpMetric
+ */
+ public static BgpLinkAttrIgpMetric read(ChannelBuffer cb)
+ throws BGPParseException {
+
+ short linkigp;
+ int igpMetric = 0;
+ int igpMetricLen = 0;
+
+ short lsAttrLength = cb.readShort();
+
+ if (cb.readableBytes() < lsAttrLength
+ || lsAttrLength > ATTRLINK_MAX_LEN) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ lsAttrLength);
+ }
+
+ switch (lsAttrLength) {
+ case ISIS_SMALL_METRIC:
+ igpMetric = cb.readByte();
+ igpMetricLen = ISIS_SMALL_METRIC;
+ break;
+ case OSPF_LINK_METRIC:
+ igpMetric = cb.readShort();
+ igpMetricLen = OSPF_LINK_METRIC;
+ break;
+ case ISIS_WIDE_METRIC:
+ linkigp = cb.readShort();
+ igpMetric = cb.readByte();
+ igpMetric = (igpMetric << 16) | linkigp;
+ igpMetricLen = ISIS_WIDE_METRIC;
+ break;
+ default: // validation is already in place
+ break;
+ }
+
+ return BgpLinkAttrIgpMetric.of(igpMetric, igpMetricLen);
+ }
+
+ /**
+ * Returns the variable length IGP metric data.
+ *
+ * @return IGP metric data
+ */
+ public int attrLinkIgpMetric() {
+ return igpMetric;
+ }
+
+ /**
+ * Returns IGP metric data length.
+ *
+ * @return IGP metric length
+ */
+ public int attrLinkIgpMetricLength() {
+ return igpMetricLen;
+ }
+
+ @Override
+ public short getType() {
+ return ATTRLINK_IGPMETRIC;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(igpMetric, igpMetricLen);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof BgpLinkAttrIgpMetric) {
+ BgpLinkAttrIgpMetric other = (BgpLinkAttrIgpMetric) obj;
+ return Objects.equals(igpMetric, other.igpMetric)
+ && Objects.equals(igpMetricLen, other.igpMetricLen);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ // TODO This will be implemented in the next version
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("igpMetric", igpMetric).add("igpMetricLen", igpMetricLen)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java
new file mode 100755
index 00000000..61143fae
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrMplsProtocolMask.java
@@ -0,0 +1,152 @@
+/*
+ * 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.bgpio.types.attr;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implements BGP MPLS protocol mask attribute.
+ */
+public class BgpLinkAttrMplsProtocolMask implements BGPValueType {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(BgpLinkAttrMplsProtocolMask.class);
+
+ public static final int ATTRLINK_MPLSPROTOMASK = 1094;
+ public static final int MASK_BYTE_LEN = 1;
+
+ private final boolean bLdp;
+ private final boolean bRsvpTe;
+
+ public static final byte FIRST_BIT = (byte) 0x80;
+ public static final byte SECOND_BIT = 0x40;
+
+ /**
+ * Constructor to initialize the values.
+ *
+ * @param bLdp boolean value true if LDP flag is available
+ * @param bRsvpTe boolean value true if RSVP TE information is available
+ */
+ public BgpLinkAttrMplsProtocolMask(boolean bLdp, boolean bRsvpTe) {
+ this.bLdp = bLdp;
+ this.bRsvpTe = bRsvpTe;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param bLdp boolean value true if LDP flag is available
+ * @param bRsvpTe boolean value true if RSVP TE information is available
+ * @return object of BgpLinkAttrMplsProtocolMask
+ */
+ public static BgpLinkAttrMplsProtocolMask of(final boolean bLdp,
+ final boolean bRsvpTe) {
+ return new BgpLinkAttrMplsProtocolMask(bLdp, bRsvpTe);
+ }
+
+ /**
+ * Reads the BGP link attributes MPLS protocol mask.
+ *
+ * @param cb Channel buffer
+ * @return object of type BgpLinkAttrMPLSProtocolMask
+ * @throws BGPParseException while parsing BgpLinkAttrMplsProtocolMask
+ */
+ public static BgpLinkAttrMplsProtocolMask read(ChannelBuffer cb)
+ throws BGPParseException {
+ boolean bLdp = false;
+ boolean bRsvpTe = false;
+
+ short lsAttrLength = cb.readShort();
+
+ if ((lsAttrLength != MASK_BYTE_LEN)
+ || (cb.readableBytes() < lsAttrLength)) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ lsAttrLength);
+ }
+
+ byte flags = cb.readByte();
+
+ bLdp = ((flags & (byte) FIRST_BIT) == FIRST_BIT);
+ bRsvpTe = ((flags & (byte) SECOND_BIT) == SECOND_BIT);
+
+ return BgpLinkAttrMplsProtocolMask.of(bLdp, bRsvpTe);
+ }
+
+ /**
+ * Returns true if LDP bit is set.
+ *
+ * @return True if LDP information is set else false.
+ */
+ public boolean ldpBit() {
+ return bLdp;
+ }
+
+ /**
+ * Returns RSVP TE information.
+ *
+ * @return True if RSVP TE information is set else false.
+ */
+ public boolean rsvpBit() {
+ return bRsvpTe;
+ }
+
+ @Override
+ public short getType() {
+ return ATTRLINK_MPLSPROTOMASK;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bLdp, bRsvpTe);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof BgpLinkAttrMplsProtocolMask) {
+ BgpLinkAttrMplsProtocolMask other = (BgpLinkAttrMplsProtocolMask) obj;
+ return Objects.equals(bLdp, other.bLdp)
+ && Objects.equals(bRsvpTe, other.bRsvpTe);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ // TODO This will be implemented in the next version
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("bLdp", bLdp).add("bRsvpTe", bRsvpTe).toString();
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java
new file mode 100755
index 00000000..b45d95b8
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpLinkAttrProtectionType.java
@@ -0,0 +1,240 @@
+/*
+ * 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.bgpio.types.attr;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implements BGP link protection type attribute.
+ */
+public final class BgpLinkAttrProtectionType implements BGPValueType {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(BgpLinkAttrProtectionType.class);
+
+ public static final int ATTRLINK_PROTECTIONTYPE = 1093;
+ public static final int LINK_PROTECTION_LEN = 2;
+
+ public static final int EXTRA_TRAFFIC = 0x01;
+ public static final int UNPROTECTED = 0x02;
+ public static final int SHARED = 0x04;
+ public static final int DEDICATED_ONE_ISTO_ONE = 0x08;
+ public static final int DEDICATED_ONE_PLUS_ONE = 0x10;
+ public static final int ENHANCED = 0x20;
+
+ /* Link Protection type flags */
+ private final boolean bExtraTraffic;
+ private final boolean bUnprotected;
+ private final boolean bShared;
+ private final boolean bDedOneIstoOne;
+ private final boolean bDedOnePlusOne;
+ private final boolean bEnhanced;
+
+ /**
+ * Constructor to initialize the value.
+ *
+ * @param bExtraTraffic Extra Traffic
+ * @param bUnprotected Unprotected
+ * @param bShared Shared
+ * @param bDedOneIstoOne Dedicated 1:1
+ * @param bDedOnePlusOne Dedicated 1+1
+ * @param bEnhanced Enhanced
+ */
+ private BgpLinkAttrProtectionType(boolean bExtraTraffic,
+ boolean bUnprotected,
+ boolean bShared, boolean bDedOneIstoOne,
+ boolean bDedOnePlusOne, boolean bEnhanced) {
+ this.bExtraTraffic = bExtraTraffic;
+ this.bUnprotected = bUnprotected;
+ this.bShared = bShared;
+ this.bDedOneIstoOne = bDedOneIstoOne;
+ this.bDedOnePlusOne = bDedOnePlusOne;
+ this.bEnhanced = bEnhanced;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param bExtraTraffic Extra Traffic
+ * @param bUnprotected Unprotected
+ * @param bShared Shared
+ * @param bDedOneIstoOne Dedicated 1:1
+ * @param bDedOnePlusOne Dedicated 1+1
+ * @param bEnhanced Enhanced
+ * @return object of BgpLinkAttrProtectionType
+ */
+ public static BgpLinkAttrProtectionType of(boolean bExtraTraffic,
+ boolean bUnprotected,
+ boolean bShared,
+ boolean bDedOneIstoOne,
+ boolean bDedOnePlusOne,
+ boolean bEnhanced) {
+ return new BgpLinkAttrProtectionType(bExtraTraffic, bUnprotected,
+ bShared, bDedOneIstoOne,
+ bDedOnePlusOne, bEnhanced);
+ }
+
+ /**
+ * Reads the BGP link attributes protection type.
+ *
+ * @param cb Channel buffer
+ * @return object of type BgpLinkAttrProtectionType
+ * @throws BGPParseException while parsing BgpLinkAttrProtectionType
+ */
+ public static BgpLinkAttrProtectionType read(ChannelBuffer cb)
+ throws BGPParseException {
+ short linkProtectionType;
+ byte higherByte;
+ short lsAttrLength = cb.readShort();
+
+ boolean bExtraTraffic;
+ boolean bUnprotected;
+ boolean bShared;
+ boolean bDedOneIstoOne;
+ boolean bDedOnePlusOne;
+ boolean bEnhanced;
+
+ if ((lsAttrLength != LINK_PROTECTION_LEN)
+ || (cb.readableBytes() < lsAttrLength)) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ lsAttrLength);
+ }
+
+ linkProtectionType = cb.readShort();
+ higherByte = (byte) (linkProtectionType >> 8);
+
+ bExtraTraffic = ((higherByte & (byte) EXTRA_TRAFFIC) == EXTRA_TRAFFIC);
+ bUnprotected = ((higherByte & (byte) UNPROTECTED) == UNPROTECTED);
+ bShared = ((higherByte & (byte) SHARED) == SHARED);
+ bDedOneIstoOne = ((higherByte & (byte) DEDICATED_ONE_ISTO_ONE) == DEDICATED_ONE_ISTO_ONE);
+ bDedOnePlusOne = ((higherByte & (byte) DEDICATED_ONE_PLUS_ONE) == DEDICATED_ONE_PLUS_ONE);
+ bEnhanced = ((higherByte & (byte) ENHANCED) == ENHANCED);
+
+ return BgpLinkAttrProtectionType.of(bExtraTraffic, bUnprotected,
+ bShared, bDedOneIstoOne,
+ bDedOnePlusOne, bEnhanced);
+ }
+
+ /**
+ * Returns ExtraTraffic Bit.
+ *
+ * @return ExtraTraffic Bit
+ */
+ public boolean extraTraffic() {
+ return bExtraTraffic;
+ }
+
+ /**
+ * Returns Unprotected Bit.
+ *
+ * @return Unprotected Bit
+ */
+ public boolean unprotected() {
+ return bUnprotected;
+ }
+
+ /**
+ * Returns Shared Bit.
+ *
+ * @return Shared Bit
+ */
+ public boolean shared() {
+ return bShared;
+ }
+
+ /**
+ * Returns DedOneIstoOne Bit.
+ *
+ * @return DedOneIstoOne Bit
+ */
+ public boolean dedOneIstoOne() {
+ return bDedOneIstoOne;
+ }
+
+ /**
+ * Returns DedOnePlusOne Bit.
+ *
+ * @return DedOnePlusOne Bit
+ */
+ public boolean dedOnePlusOne() {
+ return bDedOnePlusOne;
+ }
+
+ /**
+ * Returns Enhanced Bit.
+ *
+ * @return Enhanced Bit
+ */
+ public boolean enhanced() {
+ return bEnhanced;
+ }
+
+ @Override
+ public short getType() {
+ return ATTRLINK_PROTECTIONTYPE;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(bExtraTraffic, bUnprotected, bShared,
+ bDedOneIstoOne, bDedOnePlusOne, bEnhanced);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof BgpLinkAttrProtectionType) {
+ BgpLinkAttrProtectionType other = (BgpLinkAttrProtectionType) obj;
+ return Objects.equals(bExtraTraffic, other.bExtraTraffic)
+ && Objects.equals(bUnprotected, other.bUnprotected)
+ && Objects.equals(bShared, other.bShared)
+ && Objects.equals(bDedOneIstoOne, other.bDedOneIstoOne)
+ && Objects.equals(bDedOnePlusOne, other.bDedOnePlusOne)
+ && Objects.equals(bEnhanced, other.bEnhanced);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ // TODO This will be implemented in the next version
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("bExtraTraffic", bExtraTraffic)
+ .add("bUnprotected", bUnprotected).add("bShared", bShared)
+ .add("bDedOneIstoOne", bDedOneIstoOne)
+ .add("bDedOnePlusOne", bDedOnePlusOne)
+ .add("bEnhanced", bEnhanced).toString();
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java
new file mode 100755
index 00000000..0678b81f
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrMetric.java
@@ -0,0 +1,131 @@
+/*
+ * 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.bgpio.types.attr;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implements BGP prefix metric attribute.
+ */
+public class BgpPrefixAttrMetric implements BGPValueType {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(BgpPrefixAttrMetric.class);
+
+ public static final int ATTR_PREFIX_METRIC = 1155;
+ public static final int ATTR_PREFIX_LEN = 4;
+
+ /* TE Default Metric */
+ private final int linkPfxMetric;
+
+ /**
+ * Constructor to initialize value.
+ *
+ * @param linkPfxMetric Prefix Metric
+ */
+ public BgpPrefixAttrMetric(int linkPfxMetric) {
+ this.linkPfxMetric = linkPfxMetric;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param linkPfxMetric Prefix Metric
+ * @return object of BgpPrefixAttrMetric
+ */
+ public static BgpPrefixAttrMetric of(final int linkPfxMetric) {
+ return new BgpPrefixAttrMetric(linkPfxMetric);
+ }
+
+ /**
+ * Reads the Prefix Metric.
+ *
+ * @param cb ChannelBuffer
+ * @return object of BgpPrefixAttrMetric
+ * @throws BGPParseException while parsing BgpPrefixAttrMetric
+ */
+ public static BgpPrefixAttrMetric read(ChannelBuffer cb)
+ throws BGPParseException {
+ int linkPfxMetric;
+
+ short lsAttrLength = cb.readShort(); // 4 Bytes
+
+ if ((lsAttrLength != ATTR_PREFIX_LEN)
+ || (cb.readableBytes() < lsAttrLength)) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ lsAttrLength);
+ }
+
+ linkPfxMetric = cb.readInt();
+
+ return BgpPrefixAttrMetric.of(linkPfxMetric);
+ }
+
+ /**
+ * Returns the Prefix Metric.
+ *
+ * @return Prefix Metric
+ */
+ public int attrPfxMetric() {
+ return linkPfxMetric;
+ }
+
+ @Override
+ public short getType() {
+ return ATTR_PREFIX_METRIC;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(linkPfxMetric);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof BgpPrefixAttrMetric) {
+ BgpPrefixAttrMetric other = (BgpPrefixAttrMetric) obj;
+ return Objects.equals(linkPfxMetric, other.linkPfxMetric);
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ // TODO This will be implemented in the next version
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("linkPfxMetric", linkPfxMetric).toString();
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java
new file mode 100755
index 00000000..cf043046
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/attr/BgpPrefixAttrOspfFwdAddr.java
@@ -0,0 +1,187 @@
+/*
+ * 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.bgpio.types.attr;
+
+import java.util.Objects;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.onosproject.bgpio.types.BGPErrorType;
+import org.onosproject.bgpio.types.BGPValueType;
+import org.onosproject.bgpio.util.Validation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.MoreObjects;
+
+/**
+ * Implements BGP prefix OSPF Forwarding address attribute.
+ */
+public class BgpPrefixAttrOspfFwdAddr implements BGPValueType {
+
+ protected static final Logger log = LoggerFactory
+ .getLogger(BgpPrefixAttrOspfFwdAddr.class);
+
+ public static final int ATTR_PREFIX_OSPFFWDADDR = 1156;
+ public static final int IPV4_LEN = 4;
+ public static final int IPV6_LEN = 16;
+
+ /* OSPF Forwarding Address */
+ private final short lsAttrLength;
+ private final Ip4Address ip4RouterId;
+ private final Ip6Address ip6RouterId;
+
+ /**
+ * Constructor to initialize the value.
+ *
+ * @param lsAttrLength length of the IP address
+ * @param ip4RouterId Valid IPV4 address if length is 4 else null
+ * @param ip6RouterId Valid IPV6 address if length is 16 else null
+ */
+ public BgpPrefixAttrOspfFwdAddr(short lsAttrLength, Ip4Address ip4RouterId,
+ Ip6Address ip6RouterId) {
+ this.lsAttrLength = lsAttrLength;
+ this.ip4RouterId = ip4RouterId;
+ this.ip6RouterId = ip6RouterId;
+ }
+
+ /**
+ * Returns object of this class with specified values.
+ *
+ * @param lsAttrLength length of the IP address
+ * @param ip4RouterId Valid IPV4 address if length is 4 else null
+ * @param ip6RouterId Valid IPV6 address if length is 16 else null
+ * @return object of BgpPrefixAttrOspfFwdAddr
+ */
+ public static BgpPrefixAttrOspfFwdAddr of(final short lsAttrLength,
+ final Ip4Address ip4RouterId,
+ final Ip6Address ip6RouterId) {
+ return new BgpPrefixAttrOspfFwdAddr(lsAttrLength, ip4RouterId,
+ ip6RouterId);
+ }
+
+ /**
+ * Reads the OSPF Forwarding Address.
+ *
+ * @param cb ChannelBuffer
+ * @return object of BgpPrefixAttrOSPFFwdAddr
+ * @throws BGPParseException while parsing BgpPrefixAttrOspfFwdAddr
+ */
+ public static BgpPrefixAttrOspfFwdAddr read(ChannelBuffer cb)
+ throws BGPParseException {
+ short lsAttrLength;
+ byte[] ipBytes;
+ Ip4Address ip4RouterId = null;
+ Ip6Address ip6RouterId = null;
+
+ lsAttrLength = cb.readShort();
+ ipBytes = new byte[lsAttrLength];
+
+ if ((cb.readableBytes() < lsAttrLength)) {
+ Validation.validateLen(BGPErrorType.UPDATE_MESSAGE_ERROR,
+ BGPErrorType.ATTRIBUTE_LENGTH_ERROR,
+ lsAttrLength);
+ }
+
+ cb.readBytes(ipBytes);
+
+ if (IPV4_LEN == lsAttrLength) {
+ ip4RouterId = Ip4Address.valueOf(ipBytes);
+ } else if (IPV6_LEN == lsAttrLength) {
+ ip6RouterId = Ip6Address.valueOf(ipBytes);
+ }
+
+ return BgpPrefixAttrOspfFwdAddr.of(lsAttrLength, ip4RouterId,
+ ip6RouterId);
+ }
+
+ /**
+ * Returns IPV4 Address of OSPF forwarding address.
+ *
+ * @return IPV4 address
+ */
+ public Ip4Address ospfv4FwdAddr() {
+ return ip4RouterId;
+ }
+
+ /**
+ * Returns IPV6 Address of OSPF forwarding address.
+ *
+ * @return IPV6 address
+ */
+ public Ip6Address ospfv6FwdAddr() {
+ return ip6RouterId;
+ }
+
+ /**
+ * Returns OSPF forwarding address length.
+ *
+ * @return length of the ip address
+ */
+ public short ospfFwdAddrLen() {
+ return lsAttrLength;
+ }
+
+ @Override
+ public short getType() {
+ return ATTR_PREFIX_OSPFFWDADDR;
+ }
+
+ @Override
+ public int hashCode() {
+ if (IPV4_LEN == lsAttrLength) {
+ return Objects.hash(ip4RouterId);
+ } else {
+ return Objects.hash(ip6RouterId);
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj instanceof BgpPrefixAttrOspfFwdAddr) {
+ BgpPrefixAttrOspfFwdAddr other = (BgpPrefixAttrOspfFwdAddr) obj;
+ if (IPV4_LEN == lsAttrLength) {
+ return Objects.equals(ip4RouterId, other.ip4RouterId);
+ } else {
+ return Objects.equals(ip6RouterId, other.ip6RouterId);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int write(ChannelBuffer cb) {
+ // TODO This will be implemented in the next version
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ if (IPV4_LEN == lsAttrLength) {
+ return MoreObjects.toStringHelper(getClass()).omitNullValues()
+ .add("ip4RouterId", ip4RouterId).toString();
+ } else {
+ return MoreObjects.toStringHelper(getClass()).omitNullValues()
+ .add("ip6RouterId", ip6RouterId).toString();
+ }
+ }
+}
diff --git a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
index 915aa580..bc131893 100644
--- a/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
+++ b/framework/src/onos/bgp/bgpio/src/main/java/org/onosproject/bgpio/util/Validation.java
@@ -16,6 +16,8 @@
package org.onosproject.bgpio.util;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Arrays;
import org.jboss.netty.buffer.ChannelBuffer;
@@ -23,6 +25,8 @@ import org.jboss.netty.buffer.ChannelBuffers;
import org.onlab.packet.IpAddress;
import org.onlab.packet.IpPrefix;
import org.onosproject.bgpio.exceptions.BGPParseException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.primitives.Ints;
@@ -30,10 +34,11 @@ import com.google.common.primitives.Ints;
* Provides methods to parse attribute header, validate length and type.
*/
public class Validation {
+ private static final Logger log = LoggerFactory.getLogger(Validation.class);
public static final byte FIRST_BIT = (byte) 0x80;
public static final byte SECOND_BIT = 0x40;
public static final byte THIRD_BIT = 0x20;
- public static final byte FOURTH_BIT = 0x01;
+ public static final byte FOURTH_BIT = (byte) 0x10;
public static final byte IPV4_SIZE = 4;
private boolean firstBit;
private boolean secondBit;
@@ -42,6 +47,16 @@ public class Validation {
private int len;
private boolean isShort;
+ /**
+ * Constructor to initialize parameter.
+ *
+ * @param firstBit in AttributeFlags
+ * @param secondBit in AttributeFlags
+ * @param thirdBit in AttributeFlags
+ * @param fourthBit in AttributeFlags
+ * @param len length
+ * @param isShort true if length is read as short otherwise false
+ */
Validation(boolean firstBit, boolean secondBit, boolean thirdBit, boolean fourthBit, int len, boolean isShort) {
this.firstBit = firstBit;
this.secondBit = secondBit;
@@ -119,6 +134,25 @@ public class Validation {
}
/**
+ * Convert byte array to InetAddress.
+ *
+ * @param length of IpAddress
+ * @param cb channelBuffer
+ * @return InetAddress
+ */
+ public static InetAddress toInetAddress(int length, ChannelBuffer cb) {
+ byte[] address = new byte[length];
+ cb.readBytes(address, 0, length);
+ InetAddress ipAddress = null;
+ try {
+ ipAddress = InetAddress.getByAddress(address);
+ } catch (UnknownHostException e) {
+ log.info("InetAddress convertion failed");
+ }
+ return ipAddress;
+ }
+
+ /**
* Returns first bit in type flags.
*
* @return first bit in type flags
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrNodeFlagBitTlvTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrNodeFlagBitTlvTest.java
new file mode 100644
index 00000000..5f1411ff
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrNodeFlagBitTlvTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.bgp;
+
+import org.junit.Test;
+import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for BGP attribute node flag.
+ */
+public class BgpAttrNodeFlagBitTlvTest {
+
+ private final boolean bOverloadBit = true;
+ private final boolean bAttachedBit = true;
+ private final boolean bExternalBit = true;
+ private final boolean bABRBit = true;
+
+ private final boolean bOverloadBit1 = false;
+ private final boolean bAttachedBit1 = false;
+ private final boolean bExternalBit1 = false;
+ private final boolean bABRBit1 = false;
+
+ private final BgpAttrNodeFlagBitTlv data = BgpAttrNodeFlagBitTlv
+ .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit);
+ private final BgpAttrNodeFlagBitTlv sameAsData = BgpAttrNodeFlagBitTlv
+ .of(bOverloadBit, bAttachedBit, bExternalBit, bABRBit);
+ private final BgpAttrNodeFlagBitTlv diffData = BgpAttrNodeFlagBitTlv
+ .of(bOverloadBit1, bAttachedBit1, bExternalBit1, bABRBit1);
+
+ @Test
+ public void basics() {
+
+ new EqualsTester().addEqualityGroup(data, sameAsData)
+ .addEqualityGroup(diffData).testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrRouterIdV6Test.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrRouterIdV6Test.java
new file mode 100644
index 00000000..72ca5dbf
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpAttrRouterIdV6Test.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.bgp;
+
+import org.junit.Test;
+import org.onlab.packet.Ip6Address;
+import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV6;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for BGP attribute node router ID.
+ */
+public class BgpAttrRouterIdV6Test {
+
+ private final short sType = 1;
+ private final Ip6Address ip6RouterId = Ip6Address
+ .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001");
+
+ private final short sType1 = 2;
+ private final Ip6Address ip6RouterId1 = Ip6Address
+ .valueOf("2004:0db8:0a0b:12f0:0000:0000:0000:0004");
+
+ private final BgpAttrRouterIdV6 data = BgpAttrRouterIdV6.of(ip6RouterId,
+ sType);
+ private final BgpAttrRouterIdV6 sameAsData = BgpAttrRouterIdV6
+ .of(ip6RouterId, sType);
+ private final BgpAttrRouterIdV6 diffData = BgpAttrRouterIdV6
+ .of(ip6RouterId1, sType1);
+
+ @Test
+ public void basics() {
+
+ new EqualsTester().addEqualityGroup(data, sameAsData)
+ .addEqualityGroup(diffData).testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrIgpMetricTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrIgpMetricTest.java
new file mode 100644
index 00000000..32280a79
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrIgpMetricTest.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.bgp;
+
+import org.junit.Test;
+import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for BGP link IGP metric attribute.
+ */
+public class BgpLinkAttrIgpMetricTest {
+ private final int val = 0x010203;
+ private final int valLen = 3;
+ private final int val1 = 0x01020304;
+ private final int val1Len = 4;
+
+ private final BgpLinkAttrIgpMetric data = BgpLinkAttrIgpMetric.of(val,
+ valLen);
+ private final BgpLinkAttrIgpMetric sameAsData = BgpLinkAttrIgpMetric
+ .of(val, valLen);
+ private final BgpLinkAttrIgpMetric diffData = BgpLinkAttrIgpMetric
+ .of(val1, val1Len);
+
+ @Test
+ public void basics() {
+ new EqualsTester().addEqualityGroup(data, sameAsData)
+ .addEqualityGroup(diffData).testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrProtectionTypeTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrProtectionTypeTest.java
new file mode 100644
index 00000000..89f97a83
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpLinkAttrProtectionTypeTest.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.bgp;
+
+import org.junit.Test;
+import org.onosproject.bgpio.types.attr.BgpLinkAttrProtectionType;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for MPLS protocol mask attribute.
+ */
+public class BgpLinkAttrProtectionTypeTest {
+ boolean bExtraTraffic = true;
+ boolean bUnprotected = true;
+ boolean bShared = true;
+ boolean bDedOneIstoOne = true;
+ boolean bDedOnePlusOne = true;
+ boolean bEnhanced = true;
+
+ boolean bExtraTraffic1 = false;
+ boolean bUnprotected1 = false;
+ boolean bShared1 = false;
+ boolean bDedOneIstoOne1 = false;
+ boolean bDedOnePlusOne1 = false;
+ boolean bEnhanced1 = false;
+
+ private final BgpLinkAttrProtectionType data = BgpLinkAttrProtectionType
+ .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne,
+ bDedOnePlusOne, bEnhanced);
+ private final BgpLinkAttrProtectionType sameAsData = BgpLinkAttrProtectionType
+ .of(bExtraTraffic, bUnprotected, bShared, bDedOneIstoOne,
+ bDedOnePlusOne, bEnhanced);
+ private final BgpLinkAttrProtectionType diffData = BgpLinkAttrProtectionType
+ .of(bExtraTraffic1, bUnprotected1, bShared1, bDedOneIstoOne1,
+ bDedOnePlusOne1, bEnhanced1);
+
+ @Test
+ public void basics() {
+
+ new EqualsTester().addEqualityGroup(data, sameAsData)
+ .addEqualityGroup(diffData).testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOspfFwdAddrTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOspfFwdAddrTest.java
new file mode 100644
index 00000000..f736bead
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/BgpPrefixAttrOspfFwdAddrTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.bgp;
+
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onosproject.bgpio.types.attr.BgpPrefixAttrOspfFwdAddr;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for BGP prefix metric attribute.
+ */
+public class BgpPrefixAttrOspfFwdAddrTest {
+
+ private final short lsAttrLength = 4;
+ private final Ip4Address ip4RouterId = Ip4Address.valueOf("192.168.1.1");
+ private final Ip6Address ip6RouterId = Ip6Address
+ .valueOf("2001:0db8:0a0b:12f0:0000:0000:0000:0001");
+
+ private final short lsAttrLength1 = 16;
+ private final Ip4Address ip4RouterId1 = Ip4Address.valueOf("192.168.1.2");
+ private final Ip6Address ip6RouterId1 = Ip6Address
+ .valueOf("1002:0db8:0a0b:12f0:0000:0000:0000:0002");
+
+ private final BgpPrefixAttrOspfFwdAddr data = BgpPrefixAttrOspfFwdAddr
+ .of(lsAttrLength, ip4RouterId, ip6RouterId);
+ private final BgpPrefixAttrOspfFwdAddr sameAsData = BgpPrefixAttrOspfFwdAddr
+ .of(lsAttrLength, ip4RouterId, ip6RouterId);
+ private final BgpPrefixAttrOspfFwdAddr diffData = BgpPrefixAttrOspfFwdAddr
+ .of(lsAttrLength1, ip4RouterId1, ip6RouterId1);
+
+ @Test
+ public void basics() {
+ new EqualsTester().addEqualityGroup(data, sameAsData)
+ .addEqualityGroup(diffData).testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/NextHopTest.java b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/NextHopTest.java
new file mode 100755
index 00000000..109197bb
--- /dev/null
+++ b/framework/src/onos/bgp/bgpio/src/test/java/org/onosproject/bgp/NextHopTest.java
@@ -0,0 +1,41 @@
+/*
+ * 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.bgp;
+
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onosproject.bgpio.types.NextHop;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Test for NextHop BGP Path Attribute.
+ */
+public class NextHopTest {
+ private final Ip4Address value1 = Ip4Address.valueOf("12.12.12.12");
+ private final Ip4Address value2 = Ip4Address.valueOf("12.12.12.13");
+ private final NextHop attr1 = new NextHop(value1);
+ private final NextHop sameAsAttr1 = new NextHop(value1);
+ private final NextHop attr2 = new NextHop(value2);
+
+ @Test
+ public void basics() {
+ new EqualsTester()
+ .addEqualityGroup(attr1, sameAsAttr1)
+ .addEqualityGroup(attr2)
+ .testEquals();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java
index 1df2f049..03d25cee 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/Comparators.java
@@ -71,7 +71,10 @@ public final class Comparators {
public static final Comparator<FlowRule> FLOW_RULE_COMPARATOR = new Comparator<FlowRule>() {
@Override
public int compare(FlowRule f1, FlowRule f2) {
- return Long.valueOf(f1.id().value()).compareTo(f2.id().value());
+ int tableCompare = Integer.valueOf(f1.tableId()).compareTo(f2.tableId());
+ return (tableCompare == 0)
+ ? Long.valueOf(f1.id().value()).compareTo(f2.id().value())
+ : tableCompare;
}
};
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java
index 57c41009..1049d90d 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/AddOpticalIntentCommand.java
@@ -44,12 +44,12 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
@Argument(index = 0, name = "ingressDevice",
description = "Ingress Device/Port Description",
required = true, multiValued = false)
- String ingressDeviceString = null;
+ String ingressDeviceString = "";
@Argument(index = 1, name = "egressDevice",
description = "Egress Device/Port Description",
required = true, multiValued = false)
- String egressDeviceString = null;
+ String egressDeviceString = "";
@Option(name = "-b", aliases = "--bidirectional",
description = "If this argument is passed the optical link created will be bidirectional, " +
@@ -65,7 +65,6 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
"Connect point must be in \"deviceUri/portNumber\" format");
DeviceId deviceId = DeviceId.deviceId(splitted[0]);
-
DeviceService deviceService = get(DeviceService.class);
List<Port> ports = deviceService.getPorts(deviceId);
@@ -87,7 +86,8 @@ public class AddOpticalIntentCommand extends ConnectivityIntentCommand {
ConnectPoint egress = createConnectPoint(egressDeviceString);
if (ingress == null || egress == null) {
- print("Could not create optical intent");
+ print("Invalid endpoint(s); could not create optical intent");
+ return;
}
DeviceService deviceService = get(DeviceService.class);
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
index de84f519..331cca17 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
@@ -123,8 +123,14 @@ public class FlowsListCommand extends AbstractShellCommand {
if (state != null && !state.equals("any")) {
s = FlowEntryState.valueOf(state.toUpperCase());
}
- Iterable<Device> devices = uri == null ? deviceService.getDevices() :
- Collections.singletonList(deviceService.getDevice(DeviceId.deviceId(uri)));
+ Iterable<Device> devices = null;
+ if (uri == null) {
+ devices = deviceService.getDevices();
+ } else {
+ Device dev = deviceService.getDevice(DeviceId.deviceId(uri));
+ devices = (dev == null) ? deviceService.getDevices()
+ : Collections.singletonList(dev);
+ }
for (Device d : devices) {
if (s == null) {
rules = newArrayList(service.getFlowEntries(d.id()));
diff --git a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java
index afbcab80..b10621de 100644
--- a/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java
+++ b/framework/src/onos/cli/src/main/java/org/onosproject/cli/net/GroupsListCommand.java
@@ -46,7 +46,7 @@ import static com.google.common.collect.Lists.newArrayList;
public class GroupsListCommand extends AbstractShellCommand {
private static final String FORMAT =
- " id=%s, state=%s, bytes=%s, packets=%s, appId=%s";
+ " id=%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s";
private static final String BUCKET_FORMAT =
" id=%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
@@ -121,7 +121,7 @@ public class GroupsListCommand extends AbstractShellCommand {
private void printGroups(DeviceId deviceId, List<Group> groups) {
print("deviceId=%s", deviceId);
for (Group group : groups) {
- print(FORMAT, group.id().id(), group.state(),
+ print(FORMAT, group.id().id(), group.state(), group.type(),
group.bytes(), group.packets(), group.appId().name());
int i = 0;
for (GroupBucket bucket:group.buckets().buckets()) {
diff --git a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index cf76febe..9bd5dd9f 100644
--- a/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/framework/src/onos/cli/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -19,7 +19,6 @@
<command>
<action class="org.onosproject.cli.SummaryCommand"/>
</command>
-
<command>
<action class="org.onosproject.cli.security.ReviewCommand"/>
<completers>
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
index 5f2b5fff..47944874 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterAdminService.java
@@ -30,9 +30,8 @@ public interface ClusterAdminService {
* instance.
*
* @param nodes set of nodes that form the cluster
- * @param ipPrefix IP address prefix, e.g. 10.0.1.*
*/
- void formCluster(Set<ControllerNode> nodes, String ipPrefix);
+ void formCluster(Set<ControllerNode> nodes);
/**
* Adds a new controller node to the cluster.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
deleted file mode 100644
index 1ee78b15..00000000
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterDefinitionService.java
+++ /dev/null
@@ -1,47 +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.cluster;
-
-import java.util.Set;
-
-/**
- * Service for obtaining the static definition of a controller cluster.
- */
-public interface ClusterDefinitionService {
-
- /**
- * Returns the local controller node.
- * @return local controller node
- */
- ControllerNode localNode();
-
- /**
- * Returns the set of seed nodes that should be used for discovering other members
- * of the cluster.
- * @return set of seed controller nodes
- */
- Set<ControllerNode> seedNodes();
-
- /**
- * Forms cluster configuration based on the specified set of node
- * information. Assumes subsequent restart for the new configuration to
- * take hold.
- *
- * @param nodes set of nodes that form the cluster
- * @param ipPrefix IP address prefix, e.g. 10.0.1.*
- */
- void formCluster(Set<ControllerNode> nodes, String ipPrefix);
-} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
new file mode 100644
index 00000000..e1eacfee
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
@@ -0,0 +1,185 @@
+/*
+ * 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.cluster;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Verify.verifyNotNull;
+import static com.google.common.base.Verify.verify;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * Cluster metadata.
+ * <p>
+ * Metadata specifies the attributes that define a ONOS cluster and comprises the collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes} and the collection of data
+ * {@link org.onosproject.cluster.Partition partitions}.
+ */
+public final class ClusterMetadata {
+
+ private String name;
+ private Set<ControllerNode> nodes;
+ private Set<Partition> partitions;
+
+ /**
+ * Returns a new cluster metadata builder.
+ * @return The cluster metadata builder.
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Returns the name of the cluster.
+ *
+ * @return cluster name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the collection of {@link org.onosproject.cluster.ControllerNode nodes} that make up the cluster.
+ * @return cluster nodes
+ */
+ public Collection<ControllerNode> getNodes() {
+ return this.nodes;
+ }
+
+ /**
+ * Returns the collection of data {@link org.onosproject.cluster.Partition partitions} that make up the cluster.
+ * @return collection of partitions.
+ */
+ public Collection<Partition> getPartitions() {
+ return this.partitions;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(ClusterMetadata.class)
+ .add("name", name)
+ .add("nodes", nodes)
+ .add("partitions", partitions)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.deepHashCode(new Object[] {name, nodes, partitions});
+ }
+
+ /*
+ * Provide a deep quality check of the meta data (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object object) {
+
+ if (!ClusterMetadata.class.isInstance(object)) {
+ return false;
+ }
+ ClusterMetadata that = (ClusterMetadata) object;
+
+ if (!this.name.equals(that.name) || this.nodes.size() != that.nodes.size()
+ || this.partitions.size() != that.partitions.size()) {
+ return false;
+ }
+
+ return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty()
+ && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty();
+ }
+
+ /**
+ * Builder for a {@link ClusterMetadata} instance.
+ */
+ public static class Builder {
+
+ private final ClusterMetadata metadata;
+
+ public Builder() {
+ metadata = new ClusterMetadata();
+ }
+
+ /**
+ * Sets the cluster name, returning the cluster metadata builder for method chaining.
+ * @param name cluster name
+ * @return this cluster metadata builder
+ */
+ public Builder withName(String name) {
+ metadata.name = checkNotNull(name);
+ return this;
+ }
+
+ /**
+ * Sets the collection of cluster nodes, returning the cluster metadata builder for method chaining.
+ * @param controllerNodes collection of cluster nodes
+ * @return this cluster metadata builder
+ */
+ public Builder withControllerNodes(Collection<ControllerNode> controllerNodes) {
+ metadata.nodes = ImmutableSet.copyOf(checkNotNull(controllerNodes));
+ return this;
+ }
+
+ /**
+ * Sets the collection of data partitions, returning the cluster metadata builder for method chaining.
+ * @param partitions collection of partitions
+ * @return this cluster metadata builder
+ */
+ public Builder withPartitions(Collection<Partition> partitions) {
+ metadata.partitions = ImmutableSet.copyOf(checkNotNull(partitions));
+ return this;
+ }
+
+ /**
+ * Builds the cluster metadata.
+ * @return cluster metadata
+ * @throws com.google.common.base.VerifyException VerifyException if the metadata is misconfigured
+ */
+ public ClusterMetadata build() {
+ verifyMetadata();
+ return metadata;
+ }
+
+ /**
+ * Validates the constructed metadata for semantic correctness.
+ * @throws VerifyException if the metadata is misconfigured.
+ */
+ private void verifyMetadata() {
+ verifyNotNull(metadata.getName(), "Cluster name must be specified");
+ verifyNotNull(metadata.getNodes(), "Cluster nodes must be specified");
+ verifyNotNull(metadata.getPartitions(), "Cluster partitions must be specified");
+ verify(!metadata.getNodes().isEmpty(), "Cluster nodes must not be empty");
+ verify(!metadata.getPartitions().isEmpty(), "Cluster nodes must not be empty");
+
+ // verify that partitions are constituted from valid cluster nodes.
+ boolean validPartitions = Collections2.transform(metadata.getNodes(), ControllerNode::id)
+ .containsAll(metadata.getPartitions()
+ .stream()
+ .flatMap(r -> r.getMembers().stream())
+ .collect(Collectors.toSet()));
+ verify(validPartitions, "Partition locations must be valid cluster nodes");
+ }
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.java
new file mode 100644
index 00000000..a0f461c4
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEvent.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.cluster;
+
+import org.onosproject.event.AbstractEvent;
+
+/**
+ * Describes a cluster metadata event.
+ */
+public class ClusterMetadataEvent extends AbstractEvent<ClusterMetadataEvent.Type, ClusterMetadata> {
+
+ /**
+ * Type of cluster metadata events.
+ */
+ public enum Type {
+ /**
+ * Signifies that the cluster metadata has changed.
+ */
+ METADATA_CHANGED,
+ }
+
+ /**
+ * Creates an event of a given type and for the specified metadata and the
+ * current time.
+ *
+ * @param type cluster metadata event type
+ * @param metadata cluster metadata subject
+ */
+ public ClusterMetadataEvent(Type type, ClusterMetadata metadata) {
+ super(type, metadata);
+ }
+
+ /**
+ * Creates an event of a given type and for the specified metadata and time.
+ *
+ * @param type cluster metadata event type
+ * @param metadata cluster metadata subject
+ * @param time occurrence time
+ */
+ public ClusterMetadataEvent(Type type, ClusterMetadata metadata, long time) {
+ super(type, metadata, time);
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
new file mode 100644
index 00000000..fdfaeed0
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataEventListener.java
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster;
+
+import org.onosproject.event.EventListener;
+
+/**
+ * Entity capable of receiving cluster metadata related events.
+ */
+public interface ClusterMetadataEventListener extends EventListener<ClusterMetadataEvent> {
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
new file mode 100644
index 00000000..25a6df63
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.cluster;
+
+/**
+ * Service for obtaining metadata information about the cluster.
+ */
+public interface ClusterMetadataService {
+
+ /**
+ * Returns the current cluster metadata.
+ * @return cluster metadata
+ */
+ ClusterMetadata getClusterMetadata();
+
+ /**
+ * Updates the cluster metadata.
+ * @param metadata new metadata
+ */
+ void setClusterMetadata(ClusterMetadata metadata);
+
+ /**
+ * Returns the local controller node representing this instance.
+ * @return local controller node
+ */
+ ControllerNode getLocalNode();
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.java
new file mode 100644
index 00000000..7e83b5b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStore.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.cluster;
+
+import java.util.Collection;
+
+import org.onosproject.store.Store;
+import org.onosproject.store.service.Versioned;
+
+/**
+ * Manages persistence of cluster metadata; not intended for direct use.
+ */
+public interface ClusterMetadataStore extends Store<ClusterMetadataEvent, ClusterMetadataStoreDelegate> {
+
+ /**
+ * Returns the cluster metadata.
+ * <p>
+ * The returned metadata is versioned to aid determining if a metadata instance is more recent than another.
+ * @return cluster metadata
+ */
+ Versioned<ClusterMetadata> getClusterMetadata();
+
+ /**
+ * Updates the cluster metadata.
+ * @param metadata new metadata value
+ */
+ void setClusterMetadata(ClusterMetadata metadata);
+
+ // TODO: The below methods should move to a separate store interface that is responsible for
+ // tracking cluster partition operational state.
+
+ /**
+ * Sets a controller node as an active member of a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @param nodeId id of controller node
+ */
+ void setActiveReplica(String partitionId, NodeId nodeId);
+
+ /**
+ * Removes a controller node as an active member for a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @param nodeId id of controller node
+ */
+ void unsetActiveReplica(String partitionId, NodeId nodeId);
+
+ /**
+ * Returns the collection of controller nodes that are the active replicas for a partition.
+ * <p>
+ * Active members are those replicas that are up to speed with the rest of the system and are
+ * usually capable of participating in the replica state management activities in accordance with
+ * the data consistency and replication protocol in use.
+ * @param partitionId partition identifier
+ * @return identifiers of controller nodes that are the active replicas
+ */
+ Collection<NodeId> getActiveReplicas(String partitionId);
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
new file mode 100644
index 00000000..b56b7a24
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/ClusterMetadataStoreDelegate.java
@@ -0,0 +1,24 @@
+/*
+ * 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.cluster;
+
+import org.onosproject.store.StoreDelegate;
+
+/**
+ * Cluster metadata store delegate abstraction.
+ */
+public interface ClusterMetadataStoreDelegate extends StoreDelegate<ClusterMetadataEvent> {
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
index 68b490f2..6cfb42c7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/NodeId.java
@@ -20,7 +20,7 @@ import java.util.Objects;
/**
* Controller cluster identity.
*/
-public class NodeId {
+public class NodeId implements Comparable<NodeId> {
private final String id;
@@ -55,4 +55,9 @@ public class NodeId {
return id;
}
+ @Override
+ public int compareTo(NodeId that) {
+ return this.id.compareTo(that.id);
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.java
new file mode 100644
index 00000000..1eca4aeb
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/cluster/Partition.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.cluster;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A data partition.
+ * <p>
+ * Partition represents a slice of the data space and is made up of a collection
+ * of {@link org.onosproject.cluster.ControllerNode nodes}
+ * that all maintain copies of this data.
+ */
+public class Partition {
+
+ private final String name;
+ private final Set<NodeId> members;
+
+ private Partition() {
+ name = null;
+ members = null;
+ }
+
+ public Partition(String name, Collection<NodeId> members) {
+ this.name = checkNotNull(name);
+ this.members = ImmutableSet.copyOf(checkNotNull(members));
+ }
+
+ /**
+ * Returns the partition name.
+ * <p>
+ * Each partition is identified by a unique name.
+ * @return partition name
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Returns the collection of controller node identifiers that make up this partition.
+ * @return collection of controller node identifiers
+ */
+ public Collection<NodeId> getMembers() {
+ return this.members;
+ }
+
+ @Override
+ public int hashCode() {
+ return Arrays.deepHashCode(new Object[] {name, members});
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (this == other) {
+ return true;
+ }
+
+ if (other == null || !Partition.class.isInstance(other)) {
+ return false;
+ }
+
+ Partition that = (Partition) other;
+
+ if (!this.name.equals(that.name) || (this.members == null && that.members != null)
+ || (this.members != null && that.members == null) || this.members.size() != that.members.size()) {
+ return false;
+ }
+
+ return Sets.symmetricDifference(this.members, that.members).isEmpty();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
index 7f157e95..e3d6993c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/BridgeConfig.java
@@ -36,6 +36,17 @@ public interface BridgeConfig extends HandlerBehaviour {
void addBridge(BridgeName bridgeName);
/**
+ * Adds a bridge with given bridge name and dpid, and sets the controller
+ * of the bridge with given controllers.
+ *
+ * @param bridgeName bridge name
+ * @param dpid dpid
+ * @param controllers list of controller
+ * @return true if succeeds, fail otherwise
+ */
+ boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers);
+
+ /**
* Remove a bridge.
*
* @param bridgeName bridge name
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java
new file mode 100644
index 00000000..54cbc7ac
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/ExtensionResolver.java
@@ -0,0 +1,40 @@
+/*
+ * 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.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+
+/**
+ * Provides access to the extension implemented by this driver.
+ */
+@Beta
+public interface ExtensionResolver extends HandlerBehaviour {
+
+ /**
+ * Gets an extension instruction instance of the specified type, if supported
+ * by the driver.
+ *
+ * @param type type of extension to get
+ * @return extension instruction
+ * @throws UnsupportedOperationException if the extension type is not
+ * supported by this driver
+ */
+ ExtensionInstruction getExtensionInstruction(ExtensionType type);
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
index 7e79a57e..e3b4c198 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/behaviour/TunnelConfig.java
@@ -32,6 +32,15 @@ public interface TunnelConfig extends HandlerBehaviour {
void createTunnel(TunnelDescription tunnel);
/**
+ * Creates a tunnel interface on a given bridge of this device.
+ *
+ * @param bridgeName bridge name
+ * @param tunnel tunnel description
+ * @return true if succeeds, false otherwise
+ */
+ boolean createTunnelInterface(BridgeName bridgeName, TunnelDescription tunnel);
+
+ /**
* Removes a tunnel on this device.
*
* @param tunnel tunnel descriptor
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
index 4416456c..453a7648 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficSelector.java
@@ -15,8 +15,14 @@
*/
package org.onosproject.net.flow;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableSet;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.TreeSet;
+
import org.onlab.packet.Ip6Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
@@ -27,13 +33,8 @@ import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeSet;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableSet;
/**
* Default traffic selector implementation.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
index 6174cef6..6beeecc9 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/DefaultTrafficTreatment.java
@@ -15,9 +15,11 @@
*/
package org.onosproject.net.flow;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.List;
+import java.util.Objects;
+
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
@@ -25,16 +27,17 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.meter.MeterId;
-import java.util.List;
-import java.util.Objects;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
/**
* Default traffic treatment implementation.
@@ -239,9 +242,11 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
case GROUP:
case QUEUE:
case L0MODIFICATION:
+ case L1MODIFICATION:
case L2MODIFICATION:
case L3MODIFICATION:
case L4MODIFICATION:
+ case EXTENSION:
current.add(instruction);
break;
case TABLE:
@@ -479,6 +484,12 @@ public final class DefaultTrafficTreatment implements TrafficTreatment {
}
@Override
+ public TrafficTreatment.Builder extension(ExtensionInstruction extension,
+ DeviceId deviceId) {
+ return add(Instructions.extension(extension, deviceId));
+ }
+
+ @Override
public TrafficTreatment build() {
if (deferred.size() == 0 && immediate.size() == 0
&& table == null && !clear) {
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
index c7fe8b85..b14ab99c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/TrafficTreatment.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.net.flow;
+import java.util.List;
+
import org.onlab.packet.EthType;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
@@ -22,13 +24,13 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.meter.MeterId;
-import java.util.List;
-
/**
* Abstraction of network traffic treatment.
*/
@@ -413,6 +415,15 @@ public interface TrafficTreatment {
Builder setUdpDst(TpPort port);
/**
+ * Uses an extension treatment.
+ *
+ * @param extension extension treatment
+ * @param deviceId device ID
+ * @return a treatment builder
+ */
+ Builder extension(ExtensionInstruction extension, DeviceId deviceId);
+
+ /**
* Builds an immutable traffic treatment descriptor.
* <p>
* If the treatment is empty when build() is called, it will add a default
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.java
new file mode 100644
index 00000000..9f22f888
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/AbstractExtensionInstruction.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.net.flow.instructions;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Abstract implementation of the set/get property methods of ExtensionInstruction.
+ */
+public abstract class AbstractExtensionInstruction implements ExtensionInstruction {
+
+ private static final String INVALID_KEY = "Invalid property key: ";
+ private static final String INVALID_TYPE = "Given type does not match field type: ";
+
+ @Override
+ public <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException {
+ Class<?> clazz = this.getClass();
+ try {
+ Field field = clazz.getDeclaredField(key);
+ field.setAccessible(true);
+ field.set(this, value);
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExtensionPropertyException(INVALID_KEY + key);
+ }
+ }
+
+ @Override
+ public <T> T getPropertyValue(String key) throws ExtensionPropertyException {
+ Class<?> clazz = this.getClass();
+ try {
+ Field field = clazz.getDeclaredField(key);
+ field.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ T result = (T) field.get(this);
+ return result;
+ } catch (NoSuchFieldException | IllegalAccessException e) {
+ throw new ExtensionPropertyException(INVALID_KEY + key);
+ } catch (ClassCastException e) {
+ throw new ExtensionPropertyException(INVALID_TYPE + key);
+ }
+ }
+
+ @Override
+ public List<String> getProperties() {
+ Class<?> clazz = this.getClass();
+
+ List<String> fields = new ArrayList<>();
+
+ for (Field field : clazz.getDeclaredFields()) {
+ fields.add(field.getName());
+ }
+
+ return fields;
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java
new file mode 100644
index 00000000..89e0cc5e
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionInstruction.java
@@ -0,0 +1,78 @@
+/*
+ * 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.net.flow.instructions;
+
+import java.util.List;
+
+/**
+ * An extensible instruction type.
+ */
+public interface ExtensionInstruction {
+
+ /**
+ * Gets the type of the extension instruction.
+ *
+ * @return type
+ */
+ ExtensionType type();
+
+ /**
+ * Sets a property on the extension instruction.
+ *
+ * @param key property key
+ * @param value value to set for the given key
+ * @param <T> class of the value
+ * @throws ExtensionPropertyException if the given key is not a valid
+ * property on this extension instruction
+ */
+ <T> void setPropertyValue(String key, T value) throws ExtensionPropertyException;
+
+ /**
+ * Gets a property value of an extension instruction.
+ *
+ * @param key property key
+ * @param <T> class of the value
+ * @return value of the property
+ * @throws ExtensionPropertyException if the given key is not a valid
+ * property on this extension instruction
+ */
+ <T> T getPropertyValue(String key) throws ExtensionPropertyException;
+
+ /**
+ * Gets a list of all properties on the extension instruction.
+ *
+ * @return list of properties
+ */
+ List<String> getProperties();
+
+ /**
+ * Serialize the extension instruction to a byte array.
+ *
+ * @return byte array
+ */
+ byte[] serialize();
+
+ /**
+ * Deserialize the extension instruction from a byte array. The properties
+ * of this object will be overwritten with the data in the byte array.
+ *
+ * @param data input byte array
+ */
+ void deserialize(byte[] data);
+
+
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java
index a77079ce..5750d09e 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/Treatment.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionPropertyException.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 Open Networking Laboratory
+ * 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.
@@ -13,24 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
-import org.onosproject.net.PortNumber;
+package org.onosproject.net.flow.instructions;
/**
- * Abstraction of different kinds of treatment that can be applied to an
- * outbound packet.
+ * Exception indicating there was an error while setting/getting an extension
+ * instruction property.
*/
-public interface Treatment {
+public class ExtensionPropertyException extends Exception {
- // TODO: implement these later: modifications, group
- // TODO: elsewhere provide factory methods for some default treatments
-
- /**
- * Returns the port number where the packet should be emitted.
- *
- * @return output port number
- */
- PortNumber output();
+ public ExtensionPropertyException(String message) {
+ super(message);
+ }
+ public ExtensionPropertyException(String message, Throwable cause) {
+ super(message, cause);
+ }
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.java
new file mode 100644
index 00000000..747a85b5
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionType.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.net.flow.instructions;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Type of extension instructions.
+ */
+@Beta
+public final class ExtensionType {
+
+ /**
+ * A list of well-known named extension instruction type codes.
+ */
+ public enum ExtensionTypes {
+ // TODO fix type numbers to include experimenter id
+ NICIRA_SET_TUNNEL_DST(31);
+
+ private ExtensionType type;
+
+ /**
+ * Creates a new named extension instruction type.
+ *
+ * @param type type code
+ */
+ ExtensionTypes(int type) {
+ this.type = new ExtensionType(type);
+ }
+
+ /**
+ * Gets the extension type object for this named type code.
+ *
+ * @return extension type object
+ */
+ public ExtensionType type() {
+ return type;
+ }
+ }
+
+ private final int type;
+
+ /**
+ * Creates an extension type with the given int type code.
+ *
+ * @param type type code
+ */
+ public ExtensionType(int type) {
+ this.type = type;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ExtensionType) {
+ final ExtensionType that = (ExtensionType) obj;
+ return this.type == that.type;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(ExtensionType.class)
+ .add("type", type)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
index 2f6a1cc1..31ad80c5 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instruction.java
@@ -92,7 +92,12 @@ public interface Instruction {
/**
* Signifies that the traffic should be modified in L4 way.
*/
- L4MODIFICATION
+ L4MODIFICATION,
+
+ /**
+ * Signifies that an extension instruction will be used.
+ */
+ EXTENSION
}
/**
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 8868bf7c..aad407c8 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -22,6 +22,7 @@ import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
import org.onosproject.core.GroupId;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
@@ -480,6 +481,20 @@ public final class Instructions {
}
/**
+ * Creates an extension instruction.
+ *
+ * @param extension extension instruction
+ * @param deviceId device ID
+ * @return extension instruction
+ */
+ public static ExtensionInstructionWrapper extension(ExtensionInstruction extension,
+ DeviceId deviceId) {
+ checkNotNull(extension, "Extension instruction cannot be null");
+ checkNotNull(deviceId, "Device ID cannot be null");
+ return new ExtensionInstructionWrapper(extension, deviceId);
+ }
+
+ /**
* Drop instruction.
*/
@Deprecated
@@ -820,6 +835,59 @@ public final class Instructions {
}
}
+ /**
+ * Extension instruction.
+ */
+ public static class ExtensionInstructionWrapper implements Instruction {
+ private final ExtensionInstruction extensionInstruction;
+ private final DeviceId deviceId;
+
+ ExtensionInstructionWrapper(ExtensionInstruction extension, DeviceId deviceId) {
+ extensionInstruction = extension;
+ this.deviceId = deviceId;
+ }
+
+ public ExtensionInstruction extensionInstruction() {
+ return extensionInstruction;
+ }
+
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public Type type() {
+ return Type.EXTENSION;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("extension", extensionInstruction)
+ .add("deviceId", deviceId)
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type().ordinal(), extensionInstruction, deviceId);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof ExtensionInstructionWrapper) {
+ ExtensionInstructionWrapper that = (ExtensionInstructionWrapper) obj;
+ return Objects.equals(extensionInstruction, that.extensionInstruction)
+ && Objects.equals(deviceId, that.deviceId);
+
+ }
+ return false;
+ }
+ }
+
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
index 7b5924fb..06305bf7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/DefaultFilteringObjective.java
@@ -18,6 +18,7 @@ package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -46,6 +47,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
private final int id;
private final Operation op;
private final Optional<ObjectiveContext> context;
+ private final TrafficTreatment meta;
private DefaultFilteringObjective(Builder builder) {
this.key = builder.key;
@@ -57,6 +59,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
this.conditions = builder.conditions;
this.op = builder.op;
this.context = Optional.ofNullable(builder.context);
+ this.meta = builder.meta;
this.id = Objects.hash(type, key, conditions, permanent,
timeout, appId, priority);
@@ -83,6 +86,12 @@ public final class DefaultFilteringObjective implements FilteringObjective {
}
@Override
+ public TrafficTreatment meta() {
+ return meta;
+ }
+
+
+ @Override
public int priority() {
return priority;
}
@@ -135,6 +144,7 @@ public final class DefaultFilteringObjective implements FilteringObjective {
private List<Criterion> conditions;
private Operation op;
private ObjectiveContext context;
+ private TrafficTreatment meta;
@Override
public Builder withKey(Criterion key) {
@@ -186,6 +196,12 @@ public final class DefaultFilteringObjective implements FilteringObjective {
}
@Override
+ public Builder setMeta(TrafficTreatment treatment) {
+ this.meta = treatment;
+ return this;
+ }
+
+ @Override
public FilteringObjective add() {
conditions = listBuilder.build();
op = Operation.ADD;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
index 58304571..29257c61 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/flowobjective/FilteringObjective.java
@@ -17,49 +17,54 @@ package org.onosproject.net.flowobjective;
import com.google.common.annotations.Beta;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criterion;
import java.util.Collection;
/**
* Represents a filtering flow objective. Each filtering flow objective
- * is made up of a key (criterion) to a set of criteria. Using this information
- * a pipeline aware driver will decide how this objective should be mapped
- * to the specific device pipeline. For example, consider the following
- * filtering objective:
- *
- * portX -&gt; {MAC1, IP1, MAC2}
- *
- * The driver could decide to pass L3 packet to the L3 table and L2 packets to
- * the L2 table for packets arriving on portX.
- *
- * Filtering objectives do not only represent what should be permitted into the
- * pipeline but can also be used to deny or drop unwanted packets by specifying
- * the appropriate type of filtering objective. It is also important to note
- * that submitting a filtering objective does not necessarily result in rules
- * programmed at the switch, the driver is free to decide when these rules are
- * programmed. For example, a filtering rule may only be programmed once a
- * corresponding forwarding objective has been received.
+ * is made up of a key (typically a PortCriterion) mapped to a set of criteria.
+ * Using this information, a pipeline aware driver will decide how this objective
+ * should be mapped to the device specific pipeline-tables in order to satisfy the
+ * filtering condition. For example, consider the following PERMIT filtering
+ * objective:
+ * <p>
+ * portX -&gt; {MAC1, VLAN1}
+ * <p>
+ * The driver could decide to pass packets to the MAC table or VLAN or PORT
+ * tables to ensure that only those packets arriving with the correct dst MAC
+ * and VLAN ids from Port X are allowed into the pipeline.
+ * <p>
+ * Filtering objectives of type PERMIT allow packets that match the key:criteria
+ * to enter the pipeline. As a result, the implication is that packets that don't
+ * match are automatically denied (dropped).
+ * <p>
+ * Filtering objectives of type DENY, are used to deny packets that would
+ * otherwise be permitted and forwarded through the pipeline (ie. those packets
+ * that make it through the PERMIT filters).
*/
@Beta
public interface FilteringObjective extends Objective {
enum Type {
/**
- * Enables the filtering condition.
+ * Permits packets that match the filtering condition to be processed
+ * by the rest of the pipeline. Automatically denies packets that don't
+ * match the criteria.
*/
PERMIT,
/**
- * Disables the filtering condition.
+ * Denies packets that make it through the permit filters.
*/
DENY
}
/**
- * Obtain the key for this filter.
+ * Obtain the key for this filter. The filter may or may not require a key.
*
- * @return a criterion
+ * @return a criterion, which could be null if no key was provided.
*/
Criterion key();
@@ -78,6 +83,16 @@ public interface FilteringObjective extends Objective {
Collection<Criterion> conditions();
/**
+ * Auxiliary optional information provided to the device-driver.Typically
+ * conveys information about changes (treatments) to packets that are
+ * permitted into the pipeline by the PERMIT filtering condition.
+ *
+ * @return a treatment on the packets that make it through the PERMIT filters.
+ * Value may be null if no meta information is provided.
+ */
+ TrafficTreatment meta();
+
+ /**
* Builder of Filtering objective entities.
*/
interface Builder extends Objective.Builder {
@@ -113,11 +128,20 @@ public interface FilteringObjective extends Objective {
Builder deny();
/**
+ * Set meta information about this filtering condition set.
+ *
+ * @param treatment traffic treatment to use
+ * @return a filtering builder
+ */
+ Builder setMeta(TrafficTreatment treatment);
+
+ /**
* Assigns an application id.
*
* @param appId an application id
* @return a filtering builder
*/
+ @Override
Builder fromApp(ApplicationId appId);
/**
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
index 6efd3e79..9d942ee4 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/group/DefaultGroupBucket.java
@@ -139,6 +139,20 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE
watchGroup);
}
+ /**
+ * Creates all group bucket.
+ *
+ * @param treatment traffic treatment associated with group bucket
+ * @return all group bucket object
+ */
+ public static GroupBucket createAllGroupBucket(TrafficTreatment treatment) {
+ return new DefaultGroupBucket(GroupDescription.Type.ALL,
+ treatment,
+ (short) -1,
+ null,
+ null);
+ }
+
@Override
public GroupDescription.Type type() {
return this.type;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
index bd4219ad..c1467241 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/HostToHostIntent.java
@@ -17,11 +17,15 @@ package org.onosproject.net.intent;
import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+
import org.onosproject.core.ApplicationId;
import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
import java.util.List;
@@ -33,6 +37,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Beta
public final class HostToHostIntent extends ConnectivityIntent {
+ static final LinkTypeConstraint NOT_OPTICAL = new LinkTypeConstraint(false, Link.Type.OPTICAL);
+
private final HostId one;
private final HostId two;
@@ -115,6 +121,15 @@ public final class HostToHostIntent extends ConnectivityIntent {
*/
public HostToHostIntent build() {
+ List<Constraint> theConstraints = constraints;
+ // If not-OPTICAL constraint hasn't been specified, add them
+ if (!constraints.contains(NOT_OPTICAL)) {
+ theConstraints = ImmutableList.<Constraint>builder()
+ .add(NOT_OPTICAL)
+ .addAll(constraints)
+ .build();
+ }
+
return new HostToHostIntent(
appId,
key,
@@ -122,7 +137,7 @@ public final class HostToHostIntent extends ConnectivityIntent {
two,
selector,
treatment,
- constraints,
+ theConstraints,
priority
);
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
index 18baafc8..0344acbf 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/Key.java
@@ -28,7 +28,7 @@ import java.util.Objects;
*/
// TODO maybe pull this up to utils
@Beta
-public abstract class Key {
+public abstract class Key implements Comparable<Key> {
//TODO consider making this a HashCode object (worry about performance)
private final long hash;
@@ -117,6 +117,12 @@ public abstract class Key {
Objects.equals(this.appId, other.appId) &&
Objects.equals(this.key, other.key);
}
+
+ @Override
+ public int compareTo(Key o) {
+ StringKey sk = (StringKey) o;
+ return this.key.compareTo(sk.key);
+ }
}
private static final class LongKey extends Key {
@@ -157,6 +163,13 @@ public abstract class Key {
this.key == other.key &&
Objects.equals(this.appId, other.appId);
}
+
+ @Override
+ public int compareTo(Key o) {
+ Long myKey = key;
+ Long otherKey = ((LongKey) o).key;
+ return myKey.compareTo(otherKey);
+ }
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
index 43b8e4b1..20ccb55d 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/intent/constraint/BandwidthConstraint.java
@@ -16,6 +16,8 @@
package org.onosproject.net.intent.constraint;
import com.google.common.annotations.Beta;
+
+import org.onlab.util.DataRateUnit;
import org.onosproject.net.Link;
import org.onosproject.net.resource.link.BandwidthResource;
import org.onosproject.net.resource.link.BandwidthResourceRequest;
@@ -32,7 +34,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Constraint that evaluates links based on available bandwidths.
*/
@Beta
-public class BandwidthConstraint extends BooleanConstraint {
+public final class BandwidthConstraint extends BooleanConstraint {
private final BandwidthResource bandwidth;
@@ -45,6 +47,17 @@ public class BandwidthConstraint extends BooleanConstraint {
this.bandwidth = checkNotNull(bandwidth, "Bandwidth cannot be null");
}
+ /**
+ * Creates a new bandwidth constraint.
+ *
+ * @param v required amount of bandwidth
+ * @param unit {@link DataRateUnit} of {@code v}
+ * @return {@link BandwidthConstraint} instance with given bandwidth requirement
+ */
+ public static BandwidthConstraint of(double v, DataRateUnit unit) {
+ return new BandwidthConstraint(BandwidthResource.of(v, unit));
+ }
+
// Constructor for serialization
private BandwidthConstraint() {
this.bandwidth = null;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
index 82d84743..ad684c8c 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceService.java
@@ -153,6 +153,14 @@ public interface ResourceService {
Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer);
/**
+ * Returns resource paths that point available child resources under the specified resource path.
+ *
+ * @param parent parent resource path
+ * @return available resource paths under the specified resource path
+ */
+ Collection<ResourcePath> getAvailableResources(ResourcePath parent);
+
+ /**
* Returns the availability of the specified resource.
*
* @param resource resource to check the availability
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
index 5a034b4d..2cab9d4b 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/newresource/ResourceStore.java
@@ -92,6 +92,14 @@ public interface ResourceStore {
Collection<ResourcePath> getResources(ResourceConsumer consumer);
/**
+ * Returns a collection of the child resources of the specified parent.
+ *
+ * @param parent parent of the resource to be returned
+ * @return a collection of the child resources of the specified resource
+ */
+ Collection<ResourcePath> getChildResources(ResourcePath parent);
+
+ /**
* Returns a collection of the resources which are children of the specified parent and
* whose type is the specified class.
*
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
index fe21e042..0bfb3795 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/BandwidthResource.java
@@ -16,7 +16,7 @@
package org.onosproject.net.resource.link;
import org.onlab.util.Bandwidth;
-
+import org.onlab.util.DataRateUnit;
import java.util.Objects;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -43,6 +43,17 @@ public final class BandwidthResource implements LinkResource {
}
/**
+ * Creates a new bandwidth resource.
+ *
+ * @param v amount of bandwidth to request
+ * @param unit {@link DataRateUnit} of {@code v}
+ * @return {@link BandwidthResource} instance with given bandwidth
+ */
+ public static BandwidthResource of(double v, DataRateUnit unit) {
+ return new BandwidthResource(Bandwidth.of(v, unit));
+ }
+
+ /**
* Returns bandwidth as a double value.
*
* @return bandwidth as a double value
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
index 5153aebf..f8e143a4 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/DefaultLinkResourceRequest.java
@@ -16,48 +16,47 @@
package org.onosproject.net.resource.link;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
import java.util.Objects;
+import java.util.stream.Collectors;
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
import org.onlab.util.Bandwidth;
import org.onosproject.net.Link;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentId;
-import com.google.common.collect.ImmutableSet;
-
import org.onosproject.net.intent.constraint.BandwidthConstraint;
import org.onosproject.net.intent.constraint.LambdaConstraint;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Implementation of {@link LinkResourceRequest}.
*/
public final class DefaultLinkResourceRequest implements LinkResourceRequest {
private final IntentId intentId;
- private final Collection<Link> links;
- private final Set<ResourceRequest> resources;
+ protected final Map<Link, Set<ResourceRequest>> requests;
/**
- * Creates a new link resource request with the given ID, links, and
- * resource requests.
+ * Creates a new link resource request with the specified Intent ID,
+ * and resource requests over links.
*
- * @param intentId intent ID related to this request
- * @param links a set of links for the request
- * @param resources a set of resources to be requested
+ * @param intentId intent ID associated with this request
+ * @param requests resource requests over links
*/
- private DefaultLinkResourceRequest(IntentId intentId,
- Collection<Link> links,
- Set<ResourceRequest> resources) {
- this.intentId = intentId;
- this.links = ImmutableSet.copyOf(links);
- this.resources = ImmutableSet.copyOf(resources);
+ private DefaultLinkResourceRequest(IntentId intentId, Map<Link, Set<ResourceRequest>> requests) {
+ this.intentId = checkNotNull(intentId);
+ this.requests = checkNotNull(ImmutableMap.copyOf(requests));
}
-
@Override
public ResourceType type() {
return null;
@@ -70,12 +69,19 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
@Override
public Collection<Link> links() {
- return links;
+ return requests.keySet();
}
@Override
public Set<ResourceRequest> resources() {
- return resources;
+ return requests.values().stream()
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<ResourceRequest> resources(Link link) {
+ return requests.get(link);
}
/**
@@ -95,8 +101,7 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
public static final class Builder implements LinkResourceRequest.Builder {
private IntentId intentId;
- private Collection<Link> links;
- private Set<ResourceRequest> resources;
+ private Map<Link, Set<ResourceRequest>> requests;
/**
* Creates a new link resource request.
@@ -106,18 +111,33 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
private Builder(IntentId intentId, Collection<Link> links) {
this.intentId = intentId;
- this.links = links;
- this.resources = new HashSet<>();
+ this.requests = new HashMap<>();
+ for (Link link : links) {
+ requests.put(link, new HashSet<>());
+ }
}
/**
* Adds lambda request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
@Override
public Builder addLambdaRequest() {
- resources.add(new LambdaResourceRequest());
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new LambdaResourceRequest());
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public LinkResourceRequest.Builder addLambdaRequest(LambdaResource lambda) {
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new LambdaResourceRequest(lambda));
+ }
return this;
}
@@ -125,10 +145,36 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
* Adds Mpls request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
@Override
public Builder addMplsRequest() {
- resources.add(new MplsLabelResourceRequest());
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new MplsLabelResourceRequest());
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public Builder addMplsRequest(MplsLabel label) {
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new MplsLabelResourceRequest(label));
+ }
+ return this;
+ }
+
+ @Beta
+ @Override
+ public LinkResourceRequest.Builder addMplsRequest(Map<Link, MplsLabel> labels) {
+ for (Link link : labels.keySet()) {
+ if (!requests.containsKey(link)) {
+ requests.put(link, new HashSet<>());
+ }
+ requests.get(link).add(new MplsLabelResourceRequest(labels.get(link)));
+ }
+
return this;
}
@@ -140,7 +186,9 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
@Override
public Builder addBandwidthRequest(double bandwidth) {
- resources.add(new BandwidthResourceRequest(new BandwidthResource(Bandwidth.bps(bandwidth))));
+ for (Link link : requests.keySet()) {
+ requests.get(link).add(new BandwidthResourceRequest(new BandwidthResource(Bandwidth.bps(bandwidth))));
+ }
return this;
}
@@ -162,13 +210,13 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
*/
@Override
public LinkResourceRequest build() {
- return new DefaultLinkResourceRequest(intentId, links, resources);
+ return new DefaultLinkResourceRequest(intentId, requests);
}
}
@Override
public int hashCode() {
- return Objects.hash(intentId, links);
+ return Objects.hash(intentId, links());
}
@Override
@@ -181,6 +229,6 @@ public final class DefaultLinkResourceRequest implements LinkResourceRequest {
}
final DefaultLinkResourceRequest other = (DefaultLinkResourceRequest) obj;
return Objects.equals(this.intentId, other.intentId)
- && Objects.equals(this.links, other.links);
+ && Objects.equals(this.links(), other.links());
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
index b0391f5a..d264d5e5 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LambdaResourceRequest.java
@@ -15,15 +15,50 @@
*/
package org.onosproject.net.resource.link;
+import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Representation of a request for lambda resource.
*/
public class LambdaResourceRequest implements ResourceRequest {
+ private final LambdaResource lambda;
+
+ /**
+ * Constructs a request specifying the given lambda.
+ *
+ * @param lambda lambda to be requested
+ */
+ @Beta
+ public LambdaResourceRequest(LambdaResource lambda) {
+ this.lambda = checkNotNull(lambda);
+ }
+
+ /**
+ * Constructs a request asking an arbitrary available lambda.
+ *
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ public LambdaResourceRequest() {
+ this.lambda = null;
+ }
+
+ /**
+ * Returns the lambda this request expects.
+ *
+ * @return the lambda this request expects
+ */
+ @Beta
+ public LambdaResource lambda() {
+ return lambda;
+ }
+
@Override
public ResourceType type() {
return ResourceType.LAMBDA;
@@ -32,6 +67,7 @@ public class LambdaResourceRequest implements ResourceRequest {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
+ .add("lambda", lambda)
.toString();
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
index 8023a92e..37622e79 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceRequest.java
@@ -16,8 +16,10 @@
package org.onosproject.net.resource.link;
import java.util.Collection;
+import java.util.Map;
import java.util.Set;
+import com.google.common.annotations.Beta;
import org.onosproject.net.Link;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.intent.IntentId;
@@ -50,22 +52,62 @@ public interface LinkResourceRequest extends ResourceRequest {
Set<ResourceRequest> resources();
/**
+ * Returns the set of resource request against the specified link.
+ *
+ * @param link link whose associated resource request is to be returned
+ * @return set of resource request against the specified link
+ */
+ @Beta
+ Set<ResourceRequest> resources(Link link);
+
+ /**
* Builder of link resource request.
*/
interface Builder {
- /**
+ /**
* Adds lambda request.
*
* @return self
+ * @deprecated in Emu Release
*/
+ @Deprecated
Builder addLambdaRequest();
/**
- * Adds MPLS request.
- *
- * @return self
- */
- Builder addMplsRequest();
+ * Adds lambda request.
+ *
+ * @param lambda lambda to be requested
+ * @return self
+ */
+ @Beta
+ Builder addLambdaRequest(LambdaResource lambda);
+
+ /**
+ * Adds MPLS request.
+ *
+ * @return self
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ Builder addMplsRequest();
+
+ /**
+ * Adds MPLS request.
+ *
+ * @param label MPLS label to be requested
+ * @return self
+ */
+ @Beta
+ Builder addMplsRequest(MplsLabel label);
+
+ /**
+ * Adds MPLS request against the specified links.
+ *
+ * @param labels MPLS labels to be requested against links
+ * @return self
+ */
+ @Beta
+ Builder addMplsRequest(Map<Link, MplsLabel> labels);
/**
* Adds bandwidth request with bandwidth value.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
index 6dc04dfc..71ea7e1a 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/LinkResourceService.java
@@ -22,7 +22,10 @@ import org.onosproject.net.resource.ResourceRequest;
/**
* Service for providing link resource allocation.
+ *
+ * @deprecated in Emu Release
*/
+@Deprecated
public interface LinkResourceService
extends ListenerService<LinkResourceEvent, LinkResourceListener> {
@@ -31,14 +34,18 @@ public interface LinkResourceService
*
* @param req resources to be allocated
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations requestResources(LinkResourceRequest req);
/**
* Releases resources.
*
* @param allocations resources to be released
+ * @deprecated in Emu Release
*/
+ @Deprecated
void releaseResources(LinkResourceAllocations allocations);
/**
@@ -47,7 +54,9 @@ public interface LinkResourceService
* @param req updated resource request
* @param oldAllocations old resource allocations
* @return new resource allocations
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations updateResources(LinkResourceRequest req,
LinkResourceAllocations oldAllocations);
@@ -55,7 +64,9 @@ public interface LinkResourceService
* Returns all allocated resources.
*
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<LinkResourceAllocations> getAllocations();
/**
@@ -63,7 +74,9 @@ public interface LinkResourceService
*
* @param link a target link
* @return allocated resources
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<LinkResourceAllocations> getAllocations(Link link);
/**
@@ -71,7 +84,9 @@ public interface LinkResourceService
*
* @param intentId the target Intent's id
* @return allocated resources for Intent
+ * @deprecated in Emu Release
*/
+ @Deprecated
LinkResourceAllocations getAllocations(IntentId intentId);
/**
@@ -79,7 +94,9 @@ public interface LinkResourceService
*
* @param link a target link
* @return available resources for the target link
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<ResourceRequest> getAvailableResources(Link link);
/**
@@ -88,7 +105,9 @@ public interface LinkResourceService
* @param link a target link
* @param allocations allocations to be included as available
* @return available resources for the target link
+ * @deprecated in Emu Release
*/
+ @Deprecated
Iterable<ResourceRequest> getAvailableResources(Link link,
LinkResourceAllocations allocations);
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
index 0a03f450..01a048b7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/net/resource/link/MplsLabelResourceRequest.java
@@ -15,15 +15,50 @@
*/
package org.onosproject.net.resource.link;
+import com.google.common.annotations.Beta;
import com.google.common.base.MoreObjects;
import org.onosproject.net.resource.ResourceRequest;
import org.onosproject.net.resource.ResourceType;
+import static com.google.common.base.Preconditions.checkNotNull;
+
/**
* Representation of a request for lambda resource.
*/
public class MplsLabelResourceRequest implements ResourceRequest {
+ private final MplsLabel mplsLabel;
+
+ /**
+ * Constructs a request specifying the given MPLS label.
+ *
+ * @param mplsLabel MPLS label to be requested
+ */
+ @Beta
+ public MplsLabelResourceRequest(MplsLabel mplsLabel) {
+ this.mplsLabel = checkNotNull(mplsLabel);
+ }
+
+ /**
+ * Constructs a request asking an arbitrary available MPLS label.
+ *
+ * @deprecated in Emu Release
+ */
+ @Deprecated
+ public MplsLabelResourceRequest() {
+ this.mplsLabel = null;
+ }
+
+ /**
+ * Returns the MPLS label this request expects.
+ *
+ * @return the MPLS label this request expects
+ */
+ @Beta
+ public MplsLabel mplsLabel() {
+ return mplsLabel;
+ }
+
@Override
public ResourceType type() {
return ResourceType.MPLS_LABEL;
@@ -32,6 +67,7 @@ public class MplsLabelResourceRequest implements ResourceRequest {
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
+ .add("mplsLabel", mplsLabel)
.toString();
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java
new file mode 100644
index 00000000..09065dec
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistenceService.java
@@ -0,0 +1,40 @@
+/*
+ * 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.persistence;
+
+/**
+ * Service that allows for the creation of local disk backed map for instance specific values that persist across
+ * restarts. Empty maps and sets are deleted on shutdown.
+ */
+public interface PersistenceService {
+ /**
+ * A builder for the creation of local persistent maps backed by disk.
+ *
+ * @param <K> the type of keys in this map
+ * @param <V> the type of values in this map
+ * @return a persistent map builder
+ */
+ <K, V> PersistentMapBuilder<K, V> persistentMapBuilder();
+
+ /**
+ * A builder for the creation of local persistent sets backed by disk.
+ *
+ * @param <E> the type of the elements
+ * @return a persistent set builder
+ */
+ <E> PersistentSetBuilder<E> persistentSetBuilder();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.java
new file mode 100644
index 00000000..c3c855e1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentMapBuilder.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.persistence;
+
+
+import org.onosproject.store.service.Serializer;
+
+import java.util.Map;
+
+/**
+ * The interface for a persistent map builder for use with mapDB.
+ */
+public interface PersistentMapBuilder<K, V> {
+
+ /**
+ * Sets the name of this map.
+ * @param name the string name of this map
+ * @return a persistent map builder with the name option now set
+ */
+ PersistentMapBuilder<K, V> withName(String name);
+
+ /**
+ * Sets the key serializer to be used to serialize this map, this is a required parameter.
+ * @param serializer the serializer to be used for keys
+ * @return a persistent map builder with the key serializer set
+ */
+ PersistentMapBuilder<K, V> withSerializer(Serializer serializer);
+
+ /**
+ * Validates the map settings and then builds this map in the database. Throws an exception if invalid settings
+ * are found.
+ * @return The map that was created
+ */
+ Map<K, V> build();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java
new file mode 100644
index 00000000..851872cf
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/PersistentSetBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * 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.persistence;
+
+import org.onosproject.store.service.Serializer;
+
+import java.util.Set;
+
+/**
+ * The default interface for the persistent set builder for use with mapDB.
+ */
+public interface PersistentSetBuilder<E> {
+
+ /**
+ * Sets the name of this set.
+ * @param name the string name of this set
+ * @return a persistent set builder with the name option now set
+ */
+ PersistentSetBuilder<E> withName(String name);
+
+ /**
+ * Sets the serializer to be used to serialize this set, this is a required parameter.
+ * @param serializer the serializer to be used
+ * @return a persistent set builder with the serializer set
+ */
+ PersistentSetBuilder<E> withSerializer(Serializer serializer);
+
+ /**
+ * Validates the set settings and then builds this map in the database. Throws an exception if invalid settings
+ * are found.
+ * @return The set that was created
+ */
+ Set<E> build();
+} \ No newline at end of file
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/package-info.java
new file mode 100644
index 00000000..6e11a5e1
--- /dev/null
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/persistence/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.
+ */
+
+/**
+ * Persistence service and builders.
+ */
+package org.onosproject.persistence;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
index 94942e20..ef972536 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/store/service/TransactionContext.java
@@ -56,9 +56,9 @@ public interface TransactionContext {
* Commits a transaction that was previously started thereby making its changes permanent
* and externally visible.
*
- * @throws TransactionException if transaction fails to commit
+ * @return true if this transaction succeeded, otherwise false.
*/
- void commit();
+ boolean commit();
/**
* Aborts any changes made in this transaction context and discarding all locally cached updates.
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
index e0d7d239..88796de7 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/UiTopoOverlay.java
@@ -16,6 +16,8 @@
package org.onosproject.ui;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostId;
import org.onosproject.ui.topo.PropertyPanel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -105,8 +107,9 @@ public class UiTopoOverlay {
* This default implementation does nothing.
*
* @param pp property panel model of summary data
+ * @param deviceId device id
*/
- public void modifyDeviceDetails(PropertyPanel pp) {
+ public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) {
}
/**
@@ -115,7 +118,8 @@ public class UiTopoOverlay {
* This default implementation does nothing.
*
* @param pp property panel model of summary data
+ * @param hostId host id
*/
- public void modifyHostDetails(PropertyPanel pp) {
+ public void modifyHostDetails(PropertyPanel pp, HostId hostId) {
}
}
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
index 0e1c248b..f7947a75 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/table/cell/AppIdFormatter.java
@@ -27,6 +27,7 @@ public final class AppIdFormatter extends AbstractCellFormatter {
// non-instantiable
private AppIdFormatter() { }
+ // NOTE: do not change this format; we parse it on the client side.
@Override
protected String nonNullFormat(Object value) {
ApplicationId appId = (ApplicationId) value;
diff --git a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
index 7b517111..4edb6712 100644
--- a/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
+++ b/framework/src/onos/core/api/src/main/java/org/onosproject/ui/topo/NodeBadge.java
@@ -40,7 +40,7 @@ public final class NodeBadge {
return "{" + code + "}";
}
- /** Returns the status code in string form. */
+ /* Returns the status code in string form. */
public String code() {
return code;
}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
index 3f7650e4..c3a95473 100644
--- a/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/intent/HostToHostIntentTest.java
@@ -16,15 +16,18 @@
package org.onosproject.net.intent;
import org.junit.Test;
+import org.onlab.util.DataRateUnit;
import org.onosproject.TestApplicationId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.HostId;
import org.onosproject.net.flow.TrafficSelector;
-
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import com.google.common.collect.ImmutableList;
import com.google.common.testing.EqualsTester;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.is;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onosproject.net.NetTestTools.hid;
@@ -102,6 +105,55 @@ public class HostToHostIntentTest extends IntentTest {
.testEquals();
}
+ @Test
+ public void testImplicitConstraintsAreAdded() {
+ final Constraint other = BandwidthConstraint.of(1, DataRateUnit.GBPS);
+ final HostToHostIntent intent = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of(other))
+ .build();
+
+ assertThat(intent.constraints(), hasItem(HostToHostIntent.NOT_OPTICAL));
+ }
+
+ @Test
+ public void testImplicitConstraints() {
+ final HostToHostIntent implicit = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .build();
+ final HostToHostIntent empty = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of())
+ .build();
+ final HostToHostIntent exact = HostToHostIntent.builder()
+ .appId(APPID)
+ .one(id1)
+ .two(id2)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(ImmutableList.of(HostToHostIntent.NOT_OPTICAL))
+ .build();
+
+ new EqualsTester()
+ .addEqualityGroup(implicit.constraints(),
+ empty.constraints(),
+ exact.constraints())
+ .testEquals();
+
+ }
+
@Override
protected Intent createOne() {
return HostToHostIntent.builder()
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java
new file mode 100644
index 00000000..592cd983
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/DefaultPacketRequestTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.net.packet;
+
+import org.junit.Test;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+
+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 the DefaultPacketRequest class.
+ */
+public class DefaultPacketRequestTest {
+
+ private final TrafficSelector selector = DefaultTrafficSelector
+ .builder()
+ .matchIcmpCode((byte) 1)
+ .build();
+
+ private final DefaultPacketRequest packetRequest1 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest sameAsacketRequest1 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest2 =
+ new DefaultPacketRequest(selector,
+ PacketPriority.CONTROL,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest3 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.REACTIVE,
+ NetTestTools.APP_ID);
+ private final DefaultPacketRequest packetRequest4 =
+ new DefaultPacketRequest(DefaultTrafficSelector.emptySelector(),
+ PacketPriority.CONTROL,
+ new DefaultApplicationId(1, "foo"));
+
+ /**
+ * Tests the operation of the equals(), toAstring() and hashCode() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(packetRequest1, sameAsacketRequest1)
+ .addEqualityGroup(packetRequest2)
+ .addEqualityGroup(packetRequest3)
+ .addEqualityGroup(packetRequest4)
+ .testEquals();
+ }
+
+ /**
+ * Tests that building and fetching from a DefaultPacketRequest is correct.
+ */
+ @Test
+ public void testConstruction() {
+ assertThat(packetRequest1.priority(), is(PacketPriority.CONTROL));
+ assertThat(packetRequest1.priority().priorityValue(),
+ is(PacketPriority.CONTROL.priorityValue()));
+ assertThat(packetRequest1.selector(), is(DefaultTrafficSelector.emptySelector()));
+ assertThat(packetRequest1.appId(), is(NetTestTools.APP_ID));
+ }
+
+ /**
+ * Checks that the DefaultPacketRequest class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPacketRequest.class);
+ }
+}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java
new file mode 100644
index 00000000..f0d45f0c
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketEventTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.net.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Unit tests for PacketEvent class.
+ */
+public class PacketEventTest {
+
+ OutboundPacket packet;
+
+ @Test
+ public void testConstruction1() {
+ long time = System.currentTimeMillis();
+ PacketEvent event = new PacketEvent(PacketEvent.Type.EMIT, packet);
+
+ assertThat(event.type(), is(PacketEvent.Type.EMIT));
+ assertThat(event.subject(), is(packet));
+ assertThat(event.time(), greaterThanOrEqualTo(time));
+ }
+
+ @Test
+ public void testConstruction2() {
+ long time = 12345678;
+ PacketEvent event = new PacketEvent(PacketEvent.Type.EMIT, packet, time);
+
+ assertThat(event.type(), is(PacketEvent.Type.EMIT));
+ assertThat(event.subject(), is(packet));
+ assertThat(event.time(), is(time));
+ }
+
+}
diff --git a/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.java
new file mode 100644
index 00000000..7b2ef541
--- /dev/null
+++ b/framework/src/onos/core/api/src/test/java/org/onosproject/net/packet/PacketProcessorTest.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.net.packet;
+
+import org.junit.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.lessThan;
+
+/**
+ * Unit tests for static APIs in the packet processor class.
+ */
+public class PacketProcessorTest {
+
+ /**
+ * Tests a priority in the advisor range.
+ */
+ @Test
+ public void testAdvisorPriorities() {
+ int advisorPriority = PacketProcessor.advisor(3);
+ assertThat(advisorPriority, lessThan(PacketProcessor.ADVISOR_MAX));
+ assertThat(advisorPriority, greaterThanOrEqualTo(0));
+ }
+
+ /**
+ * Tests a priority in the director range.
+ */
+ @Test
+ public void testDirectorPriorities() {
+ int directorPriority = PacketProcessor.director(3);
+ assertThat(directorPriority, lessThan(PacketProcessor.DIRECTOR_MAX));
+ assertThat(directorPriority, greaterThanOrEqualTo(PacketProcessor.ADVISOR_MAX));
+ }
+
+ /**
+ * Tests a priority in the observer range.
+ */
+ @Test
+ public void testObserverPriorities() {
+ int observerPriority = PacketProcessor.observer(3);
+ assertThat(observerPriority, lessThan(PacketProcessor.OBSERVER_MAX));
+ assertThat(observerPriority, greaterThanOrEqualTo(PacketProcessor.DIRECTOR_MAX));
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
index 4e0f2bd9..69c5e791 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeCriterionCodecHelper.java
@@ -15,6 +15,8 @@
*/
package org.onosproject.codec.impl;
+import static org.onlab.util.Tools.nullIsIllegal;
+
import java.util.HashMap;
import java.util.Map;
@@ -24,9 +26,13 @@ import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -34,8 +40,6 @@ import org.onosproject.net.flow.criteria.Criterion;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import static org.onlab.util.Tools.nullIsIllegal;
-
/**
* Decode portion of the criterion codec.
*/
@@ -95,6 +99,8 @@ public final class DecodeCriterionCodecHelper {
decoderMap.put(Criterion.Type.OCH_SIGID.name(), new OchSigIdDecoder());
decoderMap.put(Criterion.Type.OCH_SIGTYPE.name(), new OchSigTypeDecoder());
decoderMap.put(Criterion.Type.TUNNEL_ID.name(), new TunnelIdDecoder());
+ decoderMap.put(Criterion.Type.ODU_SIGID.name(), new OduSigIdDecoder());
+ decoderMap.put(Criterion.Type.ODU_SIGTYPE.name(), new OduSigTypeDecoder());
}
private class EthTypeDecoder implements CriterionDecoder {
@@ -415,7 +421,9 @@ public final class DecodeCriterionCodecHelper {
private class OchSigTypeDecoder implements CriterionDecoder {
@Override
public Criterion decodeCriterion(ObjectNode json) {
- return null;
+ OchSignalType ochSignalType = OchSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.OCH_SIGNAL_TYPE),
+ CriterionCodec.OCH_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+ return Criteria.matchOchSignalType(ochSignalType);
}
}
@@ -428,6 +436,34 @@ public final class DecodeCriterionCodecHelper {
}
}
+ private class OduSigIdDecoder implements CriterionDecoder {
+ @Override
+ public Criterion decodeCriterion(ObjectNode json) {
+ JsonNode oduSignalId = nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_ID),
+ CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE);
+
+ int tributaryPortNumber = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_PORT_NUMBER),
+ CriterionCodec.TRIBUTARY_PORT_NUMBER + MISSING_MEMBER_MESSAGE).asInt();
+ int tributarySlotLen = nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_LEN),
+ CriterionCodec.TRIBUTARY_SLOT_LEN + MISSING_MEMBER_MESSAGE).asInt();
+ byte[] tributarySlotBitmap = HexString.fromHexString(
+ nullIsIllegal(oduSignalId.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP),
+ CriterionCodec.TRIBUTARY_SLOT_BITMAP + MISSING_MEMBER_MESSAGE).asText());
+
+ return Criteria.matchOduSignalId(
+ OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap));
+ }
+ }
+
+ private class OduSigTypeDecoder implements CriterionDecoder {
+ @Override
+ public Criterion decodeCriterion(ObjectNode json) {
+ OduSignalType oduSignalType = OduSignalType.valueOf(nullIsIllegal(json.get(CriterionCodec.ODU_SIGNAL_TYPE),
+ CriterionCodec.ODU_SIGNAL_TYPE + MISSING_MEMBER_MESSAGE).asText());
+ return Criteria.matchOduSignalType(oduSignalType);
+ }
+ }
+
/**
* Decodes the JSON into a criterion object.
*
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
index 6a97a076..14555b3d 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/DecodeInstructionCodecHelper.java
@@ -15,26 +15,29 @@
*/
package org.onosproject.codec.impl;
+import static org.onlab.util.Tools.nullIsIllegal;
+
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.TpPort;
import org.onlab.packet.VlanId;
+import org.onlab.util.HexString;
import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.PortNumber;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
-import static org.onlab.util.Tools.nullIsIllegal;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Decoding portion of the instruction codec.
@@ -174,6 +177,30 @@ public final class DecodeInstructionCodecHelper {
}
/**
+ * Decodes a Layer 1 instruction.
+ *
+ * @return instruction object decoded from the JSON
+ * @throws IllegalArgumentException if the JSON is invalid
+ */
+ private Instruction decodeL1() {
+ String subType = json.get(InstructionCodec.SUBTYPE).asText();
+ if (subType.equals(L1ModificationInstruction.L1SubType.ODU_SIGID.name())) {
+ int tributaryPortNumber = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_PORT_NUMBER),
+ InstructionCodec.TRIBUTARY_PORT_NUMBER + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+ int tributarySlotLen = nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_LEN),
+ InstructionCodec.TRIBUTARY_SLOT_LEN + InstructionCodec.MISSING_MEMBER_MESSAGE).asInt();
+ byte[] tributarySlotBitmap = null;
+ tributarySlotBitmap = HexString.fromHexString(
+ nullIsIllegal(json.get(InstructionCodec.TRIBUTARY_SLOT_BITMAP),
+ InstructionCodec.TRIBUTARY_SLOT_BITMAP + InstructionCodec.MISSING_MEMBER_MESSAGE).asText());
+ return Instructions.modL1OduSignalId(OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen,
+ tributarySlotBitmap));
+ }
+ throw new IllegalArgumentException("L1 Instruction subtype "
+ + subType + " is not supported");
+ }
+
+ /**
* Decodes a Layer 4 instruction.
*
* @return instruction object decoded from the JSON
@@ -221,6 +248,8 @@ public final class DecodeInstructionCodecHelper {
return Instructions.createDrop();
} else if (type.equals(Instruction.Type.L0MODIFICATION.name())) {
return decodeL0();
+ } else if (type.equals(Instruction.Type.L1MODIFICATION.name())) {
+ return decodeL1();
} else if (type.equals(Instruction.Type.L2MODIFICATION.name())) {
return decodeL2();
} else if (type.equals(Instruction.Type.L3MODIFICATION.name())) {
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
index f7af736e..8fc6bbcf 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeCriterionCodecHelper.java
@@ -17,8 +17,10 @@ package org.onosproject.codec.impl;
import java.util.EnumMap;
+import org.onlab.util.HexString;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
@@ -370,12 +372,18 @@ public final class EncodeCriterionCodecHelper {
private static class FormatOduSignalId implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
- final OduSignalIdCriterion oduSignalIdCriterion =
- (OduSignalIdCriterion) criterion;
- return root.put(CriterionCodec.ODU_SIGNAL_ID, oduSignalIdCriterion.oduSignalId().toString());
+ OduSignalId oduSignalId = ((OduSignalIdCriterion) criterion).oduSignalId();
+ ObjectNode child = root.putObject(CriterionCodec.ODU_SIGNAL_ID);
+
+ child.put(CriterionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+ child.put(CriterionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+ child.put(CriterionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+
+ return root;
}
}
+
private static class FormatOduSignalType implements CriterionTypeFormatter {
@Override
public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
index d12e4ad8..2ec301db 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/EncodeInstructionCodecHelper.java
@@ -15,11 +15,14 @@
*/
package org.onosproject.codec.impl;
+import org.onlab.util.HexString;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -81,6 +84,36 @@ public final class EncodeInstructionCodecHelper {
}
/**
+ * Encode an L1 modification instruction.
+ *
+ * @param result json node that the instruction attributes are added to
+ * @param instruction The L1 instruction
+ * @param context context of the request
+ */
+ private void encodeL1(ObjectNode result) {
+ L1ModificationInstruction instruction =
+ (L1ModificationInstruction) this.instruction;
+ result.put(InstructionCodec.SUBTYPE, instruction.subtype().name());
+
+ switch (instruction.subtype()) {
+ case ODU_SIGID:
+ final L1ModificationInstruction.ModOduSignalIdInstruction oduSignalIdInstruction =
+ (L1ModificationInstruction.ModOduSignalIdInstruction) instruction;
+ OduSignalId oduSignalId = oduSignalIdInstruction.oduSignalId();
+
+ ObjectNode child = result.putObject("oduSignalId");
+
+ child.put(InstructionCodec.TRIBUTARY_PORT_NUMBER, oduSignalId.tributaryPortNumber());
+ child.put(InstructionCodec.TRIBUTARY_SLOT_LEN, oduSignalId.tributarySlotLength());
+ child.put(InstructionCodec.TRIBUTARY_SLOT_BITMAP, HexString.toHexString(oduSignalId.tributarySlotBitmap()));
+ break;
+ default:
+ log.info("Cannot convert L1 subtype of {}", instruction.subtype());
+ break;
+ }
+ }
+
+ /**
* Encode an L2 modification instruction.
*
* @param result json node that the instruction attributes are added to
@@ -222,6 +255,10 @@ public final class EncodeInstructionCodecHelper {
encodeL0(result);
break;
+ case L1MODIFICATION:
+ encodeL1(result);
+ break;
+
case L2MODIFICATION:
encodeL2(result);
break;
diff --git a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
index f4d5008a..d7307ad3 100644
--- a/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
+++ b/framework/src/onos/core/common/src/main/java/org/onosproject/codec/impl/InstructionCodec.java
@@ -50,6 +50,9 @@ public final class InstructionCodec extends JsonCodec<Instruction> {
protected static final String TUNNEL_ID = "tunnelId";
protected static final String TCP_PORT = "tcpPort";
protected static final String UDP_PORT = "udpPort";
+ protected static final String TRIBUTARY_PORT_NUMBER = "tributaryPortNumber";
+ protected static final String TRIBUTARY_SLOT_LEN = "tributarySlotLength";
+ protected static final String TRIBUTARY_SLOT_BITMAP = "tributarySlotBitmap";
protected static final String MISSING_MEMBER_MESSAGE =
" member is required in Instruction";
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
index 54e1146b..86374f81 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -31,6 +31,8 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalId;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
@@ -54,6 +56,10 @@ public class CriterionCodecTest {
final IpPrefix ipPrefix6 = IpPrefix.valueOf("fe80::/64");
final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
final TpPort tpPort = TpPort.tpPort(40000);
+ final int tributaryPortNumber = 11;
+ final int tributarySlotLen = 80;
+ final byte[] tributarySlotBitmap = new byte[] {1, 2, 3, 4, 2, 3, 4, 2, 3, 4};
+
/**
* Sets up for each test. Creates a context and fetches the criterion
@@ -427,4 +433,31 @@ public class CriterionCodecTest {
ObjectNode result = criterionCodec.encode(criterion, context);
assertThat(result, matchesCriterion(criterion));
}
+
+ /**
+ * Tests Odu Signal ID criterion.
+ */
+ @Test
+ public void matchOduSignalIdTest() {
+
+ OduSignalId oduSignalId = OduSignalId.oduSignalId(tributaryPortNumber, tributarySlotLen, tributarySlotBitmap);
+
+ Criterion criterion = Criteria.matchOduSignalId(oduSignalId);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests Odu Signal Type criterion.
+ */
+ @Test
+ public void matchOduSignalTypeTest() {
+
+ OduSignalType signalType = OduSignalType.ODU2;
+
+ Criterion criterion = Criteria.matchOduSignalType(signalType);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
index bb3acad5..b00632c3 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -15,13 +15,14 @@
*/
package org.onosproject.codec.impl;
-import com.google.common.base.Joiner;
+import java.util.Objects;
+
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.criteria.Criterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
@@ -40,6 +41,8 @@ import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -47,7 +50,8 @@ import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
-import java.util.Objects;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.google.common.base.Joiner;
/**
* Hamcrest matcher for criterion objects.
@@ -496,6 +500,44 @@ public final class CriterionJsonMatcher extends
return true;
}
+ /**
+ * Matches an ODU signal ID criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OduSignalIdCriterion criterion) {
+ final OduSignalId oduSignal = criterion.oduSignalId();
+ final JsonNode jsonOduSignal = jsonCriterion.get(CriterionCodec.ODU_SIGNAL_ID);
+ int jsonTpn = jsonOduSignal.get(CriterionCodec.TRIBUTARY_PORT_NUMBER).intValue();
+ int jsonTsLen = jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_LEN).intValue();
+ byte[] jsonTributaryBitMap = HexString.fromHexString(
+ jsonOduSignal.get(CriterionCodec.TRIBUTARY_SLOT_BITMAP).asText());
+ OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, jsonTributaryBitMap);
+ if (!oduSignal.equals(jsonOduSignalId)) {
+ description.appendText("oduSignalId was " + criterion);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an ODU signal Type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OduSignalTypeCriterion criterion) {
+ final String signalType = criterion.signalType().name();
+ final String jsonOduSignalType = jsonCriterion.get("oduSignalType").textValue();
+ if (!signalType.equals(jsonOduSignalType)) {
+ description.appendText("signalType was " + signalType);
+ return false;
+ }
+ return true;
+ }
+
+
@Override
public boolean matchesSafely(JsonNode jsonCriterion,
Description description) {
@@ -594,6 +636,12 @@ public final class CriterionJsonMatcher extends
case OCH_SIGTYPE:
return matchCriterion((OchSignalTypeCriterion) criterion);
+ case ODU_SIGID:
+ return matchCriterion((OduSignalIdCriterion) criterion);
+
+ case ODU_SIGTYPE:
+ return matchCriterion((OduSignalTypeCriterion) criterion);
+
default:
// Don't know how to format this type
description.appendText("unknown criterion type " +
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
index 6c88ac1e..f6a92131 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
@@ -15,6 +15,15 @@
*/
package org.onosproject.codec.impl;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.SortedMap;
@@ -35,6 +44,8 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.Lambda;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.OduSignalType;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.criteria.Criterion;
@@ -55,6 +66,9 @@ import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -62,9 +76,6 @@ import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
@@ -72,14 +83,8 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.net.NetTestTools.APP_ID;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
/**
* Flow rule codec unit tests.
@@ -382,7 +387,7 @@ public class FlowRuleCodecTest {
checkCommonData(rule);
- assertThat(rule.selector().criteria().size(), is(33));
+ assertThat(rule.selector().criteria().size(), is(36));
rule.selector().criteria()
.stream()
@@ -518,6 +523,25 @@ public class FlowRuleCodecTest {
criterion = getCriterion(Criterion.Type.TUNNEL_ID);
assertThat(((TunnelIdCriterion) criterion).tunnelId(),
is(100L));
+
+ criterion = getCriterion(Criterion.Type.OCH_SIGTYPE);
+ assertThat(((OchSignalTypeCriterion) criterion).signalType(),
+ is(OchSignalType.FIXED_GRID));
+
+ criterion = getCriterion(Criterion.Type.ODU_SIGTYPE);
+ assertThat(((OduSignalTypeCriterion) criterion).signalType(),
+ is(OduSignalType.ODU4));
+
+
+ criterion = getCriterion(Criterion.Type.ODU_SIGID);
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributaryPortNumber(),
+ is(1));
+
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotLength(),
+ is(80));
+
+ assertThat(((OduSignalIdCriterion) criterion).oduSignalId().tributarySlotBitmap(),
+ is(new byte [] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1}));
}
/**
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
index bafbc0f1..f7b0261e 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
@@ -15,6 +15,10 @@
*/
package org.onosproject.codec.impl;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
+
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.Ip4Address;
@@ -28,26 +32,23 @@ import org.onosproject.net.ChannelSpacing;
import org.onosproject.net.GridType;
import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Lambda;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import com.fasterxml.jackson.databind.node.ObjectNode;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
-
/**
* Unit tests for Instruction codec.
*/
public class InstructionCodecTest {
CodecContext context;
JsonCodec<Instruction> instructionCodec;
-
/**
* Sets up for each test. Creates a context and fetches the instruction
* codec.
@@ -122,6 +123,20 @@ public class InstructionCodecTest {
}
/**
+ * Tests the encoding of mod ODU signal ID instructions.
+ */
+ @Test
+ public void modOduSignalIdInstructionTest() {
+ OduSignalId oduSignalId = OduSignalId.oduSignalId(1, 8, new byte [] {8, 0, 0, 0, 0, 0, 0, 0, 0, 0});
+ L1ModificationInstruction.ModOduSignalIdInstruction instruction =
+ (L1ModificationInstruction.ModOduSignalIdInstruction)
+ Instructions.modL1OduSignalId(oduSignalId);
+ ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
* Tests the encoding of mod ether instructions.
*/
@Test
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
index c3cdca0f..9ffb3c3a 100644
--- a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
@@ -17,15 +17,25 @@ package org.onosproject.codec.impl;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onlab.util.HexString;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.DropInstruction;
+import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import com.fasterxml.jackson.databind.JsonNode;
-import static org.onosproject.net.flow.instructions.Instructions.*;
-import static org.onosproject.net.flow.instructions.L0ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L2ModificationInstruction.*;
-import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*;
-
/**
* Hamcrest matcher for instructions.
*/
@@ -133,7 +143,7 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
}
/**
- * Matches teh contents of a mod OCh singal instruction.
+ * Matches the contents of a mod OCh singal instruction.
*
* @param instructionJson JSON instruction to match
* @param description Description object used for recording errors
@@ -184,6 +194,40 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
}
/**
+ * Matches the contents of a mod ODU singal Id instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents matches, false otherwise
+ */
+ private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
+ Description description) {
+ ModOduSignalIdInstruction instructionToMatch =
+ (ModOduSignalIdInstruction) instruction;
+ String jsonSubType = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
+ description.appendText("subtype was " + jsonSubType);
+ return false;
+ }
+ String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+ final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
+ int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
+ int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
+ byte [] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
+ OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
+ if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
+ description.appendText("oduSignalId was " + instructionToMatch);
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
* Matches the contents of a mod Ethernet instruction.
*
* @param instructionJson JSON instruction to match
@@ -416,6 +460,8 @@ public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<Json
description);
} else if (instruction instanceof ModMplsLabelInstruction) {
return matchModMplsLabelInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModOduSignalIdInstruction) {
+ return matchModOduSingalIdInstruction(jsonInstruction, description);
} else if (instruction instanceof NoActionInstruction) {
return true;
}
diff --git a/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json b/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
index 1a96e92f..ccb2e161 100644
--- a/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
+++ b/framework/src/onos/core/common/src/test/resources/org/onosproject/codec/impl/criteria-flow.json
@@ -38,7 +38,10 @@
{"type":"MPLS_LABEL", "label":123},
{"type":"IPV6_EXTHDR", "exthdrFlags":99},
{"type":"OCH_SIGID", "lambda":122},
- {"type":"TUNNEL_ID", "tunnelId":100}
+ {"type":"TUNNEL_ID", "tunnelId":100},
+ {"type":"OCH_SIGTYPE", "ochSignalType":"FIXED_GRID"},
+ {"type":"ODU_SIGTYPE", "oduSignalType":"ODU4"},
+ {"type":"ODU_SIGID", "oduSignalId" : {"tributaryPortNumber":1, "tributarySlotLen":80, "tributarySlotBitmap":"01:01:01:01:01:01:01:01:01:01"}}
]
}
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
index 04d1dfdf..7ddac0ce 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterManager.java
@@ -25,17 +25,26 @@ import org.apache.karaf.system.SystemService;
import org.joda.time.DateTime;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ClusterAdminService;
-import org.onosproject.cluster.ClusterDefinitionService;
import org.onosproject.cluster.ClusterEvent;
import org.onosproject.cluster.ClusterEventListener;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.Partition;
import org.onosproject.event.AbstractListenerManager;
import org.slf4j.Logger;
+import com.google.common.collect.Lists;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import static com.google.common.base.Preconditions.checkArgument;
@@ -44,8 +53,6 @@ import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
-
-
/**
* Implementation of the cluster service.
*/
@@ -61,7 +68,7 @@ public class ClusterManager
private ClusterStoreDelegate delegate = new InternalStoreDelegate();
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterStore store;
@@ -73,8 +80,9 @@ public class ClusterManager
public void activate() {
store.setDelegate(delegate);
eventDispatcher.addSink(ClusterEvent.class, listenerRegistry);
- clusterDefinitionService.seedNodes()
- .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
+ clusterMetadataService.getClusterMetadata()
+ .getNodes()
+ .forEach(node -> store.addNode(node.id(), node.ip(), node.tcpPort()));
log.info("Started");
}
@@ -119,11 +127,16 @@ public class ClusterManager
}
@Override
- public void formCluster(Set<ControllerNode> nodes, String ipPrefix) {
+ public void formCluster(Set<ControllerNode> nodes) {
checkNotNull(nodes, "Nodes cannot be null");
checkArgument(!nodes.isEmpty(), "Nodes cannot be empty");
- checkNotNull(ipPrefix, "IP prefix cannot be null");
- clusterDefinitionService.formCluster(nodes, ipPrefix);
+
+ ClusterMetadata metadata = ClusterMetadata.builder()
+ .withName("default")
+ .withControllerNodes(nodes)
+ .withPartitions(buildDefaultPartitions(nodes))
+ .build();
+ clusterMetadataService.setClusterMetadata(metadata);
try {
log.warn("Shutting down container for cluster reconfiguration!");
systemService.reboot("now", SystemService.Swipe.NONE);
@@ -153,4 +166,21 @@ public class ClusterManager
post(event);
}
}
+
+ private static Collection<Partition> buildDefaultPartitions(Collection<ControllerNode> nodes) {
+ List<ControllerNode> sorted = new ArrayList<>(nodes);
+ Collections.sort(sorted, (o1, o2) -> o1.id().toString().compareTo(o2.id().toString()));
+ Collection<Partition> partitions = Lists.newArrayList();
+
+ int length = nodes.size();
+ int count = 3;
+ for (int i = 0; i < length; i++) {
+ Set<NodeId> set = new HashSet<>(count);
+ for (int j = 0; j < count; j++) {
+ set.add(sorted.get((i + j) % length).id());
+ }
+ partitions.add(new Partition("p" + (i + 1), set));
+ }
+ return partitions;
+ }
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
new file mode 100644
index 00000000..a0f7a833
--- /dev/null
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/cluster/impl/ClusterMetadataManager.java
@@ -0,0 +1,116 @@
+package org.onosproject.cluster.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collection;
+import java.util.Enumeration;
+
+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.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataEventListener;
+import org.onosproject.cluster.ClusterMetadataService;
+import org.onosproject.cluster.ClusterMetadataStore;
+import org.onosproject.cluster.ClusterMetadataStoreDelegate;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+
+/**
+ * Implementation of ClusterMetadataService.
+ */
+@Component(immediate = true)
+@Service
+public class ClusterMetadataManager
+ extends AbstractListenerManager<ClusterMetadataEvent, ClusterMetadataEventListener>
+ implements ClusterMetadataService {
+
+ private ControllerNode localNode;
+ private final Logger log = getLogger(getClass());
+
+ private ClusterMetadataStoreDelegate delegate = new InternalStoreDelegate();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterMetadataStore store;
+
+ @Activate
+ public void activate() {
+ store.setDelegate(delegate);
+ eventDispatcher.addSink(ClusterMetadataEvent.class, listenerRegistry);
+ establishSelfIdentity();
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ store.unsetDelegate(delegate);
+ eventDispatcher.removeSink(ClusterMetadataEvent.class);
+ log.info("Stopped");
+ }
+
+ @Override
+ public ClusterMetadata getClusterMetadata() {
+ return Versioned.valueOrElse(store.getClusterMetadata(), null);
+ }
+
+ @Override
+ public ControllerNode getLocalNode() {
+ return localNode;
+ }
+
+ @Override
+ public void setClusterMetadata(ClusterMetadata metadata) {
+ checkNotNull(metadata, "Cluster metadata cannot be null");
+ store.setClusterMetadata(metadata);
+ }
+
+ // Store delegate to re-post events emitted from the store.
+ private class InternalStoreDelegate implements ClusterMetadataStoreDelegate {
+ @Override
+ public void notify(ClusterMetadataEvent event) {
+ post(event);
+ }
+ }
+
+ private IpAddress findLocalIp(Collection<ControllerNode> controllerNodes) throws SocketException {
+ Enumeration<NetworkInterface> interfaces =
+ NetworkInterface.getNetworkInterfaces();
+ while (interfaces.hasMoreElements()) {
+ NetworkInterface iface = interfaces.nextElement();
+ Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
+ while (inetAddresses.hasMoreElements()) {
+ IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
+ if (controllerNodes.stream()
+ .map(ControllerNode::ip)
+ .anyMatch(nodeIp -> ip.equals(nodeIp))) {
+ return ip;
+ }
+ }
+ }
+ throw new IllegalStateException("Unable to determine local ip");
+ }
+
+ private void establishSelfIdentity() {
+ try {
+ IpAddress ip = findLocalIp(getClusterMetadata().getNodes());
+ localNode = getClusterMetadata().getNodes()
+ .stream()
+ .filter(node -> node.ip().equals(ip))
+ .findFirst()
+ .get();
+ } catch (SocketException e) {
+ throw new IllegalStateException("Cannot determine local IP", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
index 19377cf6..8f601497 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/device/impl/OpticalPortOperator.java
@@ -112,10 +112,10 @@ public final class OpticalPortOperator implements ConfigOperator {
return new OduCltPortDescription(port, odu.isEnabled(), odu.signalType(), sa);
case PACKET:
case FIBER:
+ case COPPER:
return new DefaultPortDescription(port, descr.isEnabled(), descr.type(),
descr.portSpeed(), sa);
default:
- // this includes copper ports.
log.warn("Unsupported optical port type {} - can't update", descr.type());
return descr;
}
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
index 137aca1e..0a1af6f5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionUtil.java
@@ -29,9 +29,11 @@ import org.onosproject.net.flow.criteria.VlanPcpCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
@@ -155,6 +157,7 @@ public final class FlowObjectiveCompositionUtil {
return treatmentBuilder.build();
}
+ //CHECKSTYLE:OFF
public static TrafficSelector revertTreatmentSelector(TrafficTreatment trafficTreatment,
TrafficSelector trafficSelector) {
@@ -195,14 +198,30 @@ public final class FlowObjectiveCompositionUtil {
} else {
return null;
}
- } else {
- break;
}
default:
break;
}
break;
}
+ case L1MODIFICATION: {
+ L1ModificationInstruction l1 = (L1ModificationInstruction) instruction;
+ switch (l1.subtype()) {
+ case ODU_SIGID:
+ if (criterionMap.containsKey(Criterion.Type.ODU_SIGID)) {
+ if (((OduSignalIdCriterion) criterionMap.get((Criterion.Type.ODU_SIGID))).oduSignalId()
+ .equals(((L1ModificationInstruction.ModOduSignalIdInstruction) l1)
+ .oduSignalId())) {
+ criterionMap.remove(Criterion.Type.ODU_SIGID);
+ } else {
+ return null;
+ }
+ }
+ default:
+ break;
+ }
+ break;
+ }
case L2MODIFICATION: {
L2ModificationInstruction l2 = (L2ModificationInstruction) instruction;
switch (l2.subtype()) {
@@ -344,6 +363,7 @@ public final class FlowObjectiveCompositionUtil {
return selectorBuilder.build();
}
+ //CHECKSTYLE:ON
public static Set<Criterion.Type> getTypeSet(TrafficSelector trafficSelector) {
Set<Criterion.Type> typeSet = new HashSet<>();
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
index 5fd1c85d..acc5a5d5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompiler.java
@@ -24,12 +24,14 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.EthType;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
+import org.onosproject.net.LinkKey;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -46,24 +48,23 @@ import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentCompiler;
import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.net.link.LinkStore;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
-import org.onosproject.net.resource.link.MplsLabel;
-import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
-import org.onosproject.net.resource.ResourceAllocation;
-import org.onosproject.net.resource.ResourceType;
import org.slf4j.Logger;
import java.util.Collections;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.net.LinkKey.linkKey;
import static org.slf4j.LoggerFactory.getLogger;
@Component(immediate = true)
@@ -78,18 +79,15 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService resourceService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkStore linkStore;
+ protected ResourceService resourceService;
protected ApplicationId appId;
@Override
public List<Intent> compile(MplsPathIntent intent, List<Intent> installable,
Set<LinkResourceAllocations> resources) {
- LinkResourceAllocations allocations = assignMplsLabel(intent);
- List<FlowRule> rules = generateRules(intent, allocations);
+ Map<LinkKey, MplsLabel> labels = assignMplsLabel(intent);
+ List<FlowRule> rules = generateRules(intent, labels);
return Collections.singletonList(new FlowRuleIntent(appId, rules, intent.resources()));
}
@@ -105,39 +103,60 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
intentExtensionService.unregisterCompiler(MplsPathIntent.class);
}
- private LinkResourceAllocations assignMplsLabel(MplsPathIntent intent) {
+ private Map<LinkKey, MplsLabel> assignMplsLabel(MplsPathIntent intent) {
// TODO: do it better... Suggestions?
- Set<Link> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
+ Set<LinkKey> linkRequest = Sets.newHashSetWithExpectedSize(intent.path()
.links().size() - 2);
for (int i = 1; i <= intent.path().links().size() - 2; i++) {
- Link link = intent.path().links().get(i);
+ LinkKey link = linkKey(intent.path().links().get(i));
linkRequest.add(link);
// add the inverse link. I want that the label is reserved both for
// the direct and inverse link
- linkRequest.add(linkStore.getLink(link.dst(), link.src()));
+ linkRequest.add(linkKey(link.dst(), link.src()));
}
- LinkResourceRequest.Builder request = DefaultLinkResourceRequest
- .builder(intent.id(), linkRequest).addMplsRequest();
- LinkResourceAllocations reqMpls = resourceService
- .requestResources(request.build());
- return reqMpls;
- }
+ Map<LinkKey, MplsLabel> labels = findMplsLabels(linkRequest);
+ if (labels.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ List<ResourcePath> resources = labels.entrySet().stream()
+ .map(x -> new ResourcePath(linkKey(x.getKey().src(), x.getKey().src()), x.getValue()))
+ .collect(Collectors.toList());
+ List<org.onosproject.net.newresource.ResourceAllocation> allocations =
+ resourceService.allocate(intent.id(), resources);
+ if (allocations.isEmpty()) {
+ Collections.emptyMap();
+ }
- private MplsLabel getMplsLabel(LinkResourceAllocations allocations, Link link) {
- for (ResourceAllocation allocation : allocations
- .getResourceAllocation(link)) {
- if (allocation.type() == ResourceType.MPLS_LABEL) {
- return ((MplsLabelResourceAllocation) allocation).mplsLabel();
+ return labels;
+ }
+ private Map<LinkKey, MplsLabel> findMplsLabels(Set<LinkKey> links) {
+ Map<LinkKey, MplsLabel> labels = new HashMap<>();
+ for (LinkKey link : links) {
+ Optional<MplsLabel> label = findMplsLabel(link);
+ if (label.isPresent()) {
+ labels.put(link, label.get());
}
}
- log.warn("MPLS label was not assigned successfully");
- return null;
+
+ return labels;
+ }
+
+ private Optional<MplsLabel> findMplsLabel(LinkKey link) {
+ return resourceService.getAvailableResources(new ResourcePath(link)).stream()
+ .filter(x -> x.lastComponent() instanceof MplsLabel)
+ .map(x -> (MplsLabel) x.lastComponent())
+ .findFirst();
+ }
+
+ private MplsLabel getMplsLabel(Map<LinkKey, MplsLabel> labels, LinkKey link) {
+ return labels.get(link);
}
private List<FlowRule> generateRules(MplsPathIntent intent,
- LinkResourceAllocations allocations) {
+ Map<LinkKey, MplsLabel> labels) {
Iterator<Link> links = intent.path().links().iterator();
Link srcLink = links.next();
@@ -149,7 +168,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
// Ingress traffic
// Get the new MPLS label
- MplsLabel mpls = getMplsLabel(allocations, link);
+ MplsLabel mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
MplsLabel prevLabel = mpls;
rules.add(ingressFlow(prev.port(), link, intent, mpls));
@@ -163,7 +182,7 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
if (links.hasNext()) {
// Transit traffic
// Get the new MPLS label
- mpls = getMplsLabel(allocations, link);
+ mpls = getMplsLabel(labels, linkKey(link));
checkNotNull(mpls);
rules.add(transitFlow(prev.port(), link, intent,
prevLabel, mpls));
@@ -181,7 +200,8 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule ingressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent, MplsLabel label) {
+ MplsPathIntent intent,
+ MplsLabel label) {
TrafficSelector.Builder ingressSelector = DefaultTrafficSelector
.builder(intent.selector());
@@ -193,10 +213,10 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
.matchMplsLabel(intent.ingressLabel().get());
// Swap the MPLS label
- treat.setMpls(label.label());
+ treat.setMpls(label);
} else {
// Push and set the MPLS label
- treat.pushMpls().setMpls(label.label());
+ treat.pushMpls().setMpls(label);
}
// Add the output action
treat.setOutput(link.src().port());
@@ -205,21 +225,21 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule transitFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel,
- MplsLabel outLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel,
+ MplsLabel outLabel) {
// Ignore the ingress Traffic Selector and use only the MPLS label
// assigned in the previous link
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder();
// Set the new label only if the label on the packet is
// different
if (!prevLabel.equals(outLabel)) {
- treat.setMpls(outLabel.label());
+ treat.setMpls(outLabel);
}
treat.setOutput(link.src().port());
@@ -227,14 +247,14 @@ public class MplsPathIntentCompiler implements IntentCompiler<MplsPathIntent> {
}
private FlowRule egressFlow(PortNumber inPort, Link link,
- MplsPathIntent intent,
- MplsLabel prevLabel) {
+ MplsPathIntent intent,
+ MplsLabel prevLabel) {
// egress point: either set the egress MPLS label or pop the
// MPLS label based on the intent annotations
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
selector.matchInPort(inPort).matchEthType(Ethernet.MPLS_UNICAST)
- .matchMplsLabel(prevLabel.label());
+ .matchMplsLabel(prevLabel);
// apply the intent's treatments
TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(intent
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
index c6eb7c5a..fce8498c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalCircuitIntentCompiler.java
@@ -17,6 +17,7 @@ package org.onosproject.net.intent.impl.compiler;
import org.apache.commons.lang3.tuple.Pair;
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;
@@ -70,7 +71,7 @@ import static com.google.common.base.Preconditions.checkArgument;
* An intent compiler for {@link org.onosproject.net.intent.OpticalCircuitIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalCircuitIntentCompiler implements IntentCompiler<OpticalCircuitIntent> {
private static final Logger log = LoggerFactory.getLogger(OpticalCircuitIntentCompiler.class);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
index eb5b4af8..d6725b7c 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/OpticalConnectivityIntentCompiler.java
@@ -16,7 +16,11 @@
package org.onosproject.net.intent.impl.compiler;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
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;
@@ -24,6 +28,7 @@ import org.onlab.util.Frequency;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.IndexedLambda;
import org.onosproject.net.Link;
import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
@@ -38,32 +43,29 @@ import org.onosproject.net.intent.IntentExtensionService;
import org.onosproject.net.intent.OpticalConnectivityIntent;
import org.onosproject.net.intent.OpticalPathIntent;
import org.onosproject.net.intent.impl.IntentCompilationException;
+import org.onosproject.net.newresource.ResourceAllocation;
import org.onosproject.net.newresource.ResourcePath;
import org.onosproject.net.newresource.ResourceService;
-import org.onosproject.net.resource.ResourceType;
-import org.onosproject.net.resource.link.DefaultLinkResourceRequest;
-import org.onosproject.net.resource.link.LambdaResource;
-import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LinkResourceAllocations;
-import org.onosproject.net.resource.link.LinkResourceRequest;
-import org.onosproject.net.resource.link.LinkResourceService;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.Topology;
import org.onosproject.net.topology.TopologyService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkArgument;
+import static org.onosproject.net.LinkKey.linkKey;
/**
* An intent compiler for {@link org.onosproject.net.intent.OpticalConnectivityIntent}.
*/
// For now, remove component designation until dependency on the new resource manager is available.
-// @Component(immediate = true)
+@Component(immediate = true)
public class OpticalConnectivityIntentCompiler implements IntentCompiler<OpticalConnectivityIntent> {
protected static final Logger log = LoggerFactory.getLogger(OpticalConnectivityIntentCompiler.class);
@@ -80,9 +82,6 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ResourceService resourceService;
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected LinkResourceService linkResourceService;
-
@Activate
public void activate() {
intentManager.registerCompiler(OpticalConnectivityIntent.class, this);
@@ -138,13 +137,12 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
ochSignal = srcOchPort.lambda();
} else {
// Request and reserve lambda on path
- LinkResourceAllocations linkAllocs = assignWavelength(intent, path);
- if (linkAllocs == null) {
+ IndexedLambda lambda = assignWavelength(intent, path);
+ if (lambda == null) {
continue;
}
- LambdaResourceAllocation lambdaAlloc = getWavelength(path, linkAllocs);
OmsPort omsPort = (OmsPort) deviceService.getPort(path.src().deviceId(), path.src().port());
- ochSignal = new OchSignal(lambdaAlloc.lambda().toInt(), omsPort.maxFrequency(), omsPort.grid());
+ ochSignal = new OchSignal((int) lambda.index(), omsPort.maxFrequency(), omsPort.grid());
}
// Create installable optical path intent
@@ -171,72 +169,46 @@ public class OpticalConnectivityIntentCompiler implements IntentCompiler<Optical
}
/**
- * Find the lambda allocated to the path.
- *
- * @param path the path
- * @param linkAllocs the link allocations
- * @return lambda allocated to the given path
- */
- private LambdaResourceAllocation getWavelength(Path path, LinkResourceAllocations linkAllocs) {
- return path.links().stream()
- .flatMap(x -> linkAllocs.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .findFirst()
- .map(x -> (LambdaResourceAllocation) x)
- .orElse(null);
- }
-
- /**
* Request and reserve first available wavelength across path.
*
* @param path path in WDM topology
- * @return first available lambda resource allocation
+ * @return first available lambda allocated
*/
- private LinkResourceAllocations assignWavelength(Intent intent, Path path) {
- LinkResourceRequest.Builder request =
- DefaultLinkResourceRequest.builder(intent.id(), path.links())
- .addLambdaRequest();
-
- LinkResourceAllocations allocations = linkResourceService.requestResources(request.build());
-
- if (!checkWavelengthContinuity(allocations, path)) {
- linkResourceService.releaseResources(allocations);
+ private IndexedLambda assignWavelength(Intent intent, Path path) {
+ Set<IndexedLambda> lambdas = findCommonLambdasOverLinks(path.links());
+ if (lambdas.isEmpty()) {
return null;
}
- return allocations;
- }
+ IndexedLambda minLambda = findFirstLambda(lambdas);
+ List<ResourcePath> lambdaResources = path.links().stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(x -> ResourcePath.child(x, minLambda))
+ .collect(Collectors.toList());
- /**
- * Checks wavelength continuity constraint across path, i.e., an identical lambda is used on all links.
- * @return true if wavelength continuity is met, false otherwise
- */
- private boolean checkWavelengthContinuity(LinkResourceAllocations allocations, Path path) {
- if (allocations == null) {
- return false;
+ List<ResourceAllocation> allocations = resourceService.allocate(intent.id(), lambdaResources);
+ if (allocations.isEmpty()) {
+ log.info("Resource allocation for {} failed (resource request: {})", intent, lambdaResources);
}
- List<LambdaResource> lambdas = path.links().stream()
- .flatMap(x -> allocations.getResourceAllocation(x).stream())
- .filter(x -> x.type() == ResourceType.LAMBDA)
- .map(x -> ((LambdaResourceAllocation) x).lambda())
- .collect(Collectors.toList());
+ return minLambda;
+ }
- LambdaResource lambda = null;
- for (LambdaResource nextLambda: lambdas) {
- if (nextLambda == null) {
- return false;
- }
- if (lambda == null) {
- lambda = nextLambda;
- continue;
- }
- if (!lambda.equals(nextLambda)) {
- return false;
- }
- }
+ private Set<IndexedLambda> findCommonLambdasOverLinks(List<Link> links) {
+ return links.stream()
+ .map(x -> new ResourcePath(linkKey(x.src(), x.dst())))
+ .map(resourceService::getAvailableResources)
+ .map(x -> Iterables.filter(x, r -> r.lastComponent() instanceof IndexedLambda))
+ .map(x -> Iterables.transform(x, r -> (IndexedLambda) r.lastComponent()))
+ .map(x -> (Set<IndexedLambda>) ImmutableSet.copyOf(x))
+ .reduce(Sets::intersection)
+ .orElse(Collections.emptySet());
+ }
- return true;
+ private IndexedLambda findFirstLambda(Set<IndexedLambda> lambdas) {
+ return lambdas.stream()
+ .findFirst()
+ .get();
}
private ConnectPoint staticPort(ConnectPoint connectPoint) {
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
index 5226967f..10fe75ea 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/newresource/impl/ResourceManager.java
@@ -41,7 +41,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* An implementation of ResourceService.
*/
-@Component(immediate = true, enabled = false)
+@Component(immediate = true)
@Service
@Beta
public final class ResourceManager implements ResourceService, ResourceAdminService {
@@ -127,6 +127,17 @@ public final class ResourceManager implements ResourceService, ResourceAdminServ
}
@Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ checkNotNull(parent);
+
+ Collection<ResourcePath> children = store.getChildResources(parent);
+ return children.stream()
+ // We access store twice in this method, then the store may be updated by others
+ .filter(x -> !store.getConsumer(x).isPresent())
+ .collect(Collectors.toList());
+ }
+
+ @Override
public boolean isAvailable(ResourcePath resource) {
checkNotNull(resource);
diff --git a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
index 8b9952ed..7eb189e5 100644
--- a/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
+++ b/framework/src/onos/core/net/src/main/java/org/onosproject/net/resource/impl/LinkResourceManager.java
@@ -31,7 +31,6 @@ import org.onosproject.net.resource.ResourceType;
import org.onosproject.net.resource.link.BandwidthResourceAllocation;
import org.onosproject.net.resource.link.BandwidthResourceRequest;
import org.onosproject.net.resource.link.DefaultLinkResourceAllocations;
-import org.onosproject.net.resource.link.LambdaResource;
import org.onosproject.net.resource.link.LambdaResourceAllocation;
import org.onosproject.net.resource.link.LambdaResourceRequest;
import org.onosproject.net.resource.link.LinkResourceAllocations;
@@ -46,15 +45,12 @@ import org.onosproject.net.resource.link.MplsLabelResourceAllocation;
import org.onosproject.net.resource.link.MplsLabelResourceRequest;
import org.slf4j.Logger;
-import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
import static org.onosproject.security.AppPermission.Type.*;
@@ -86,67 +82,6 @@ public class LinkResourceManager
log.info("Stopped");
}
- /**
- * Returns available lambdas on specified link.
- *
- * @param link the link
- * @return available lambdas on specified link
- */
- private Set<LambdaResource> getAvailableLambdas(Link link) {
- checkNotNull(link);
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<LambdaResource> lambdas = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.LAMBDA) {
- lambdas.add(((LambdaResourceAllocation) res).lambda());
- }
- }
- return lambdas;
- }
-
-
- /**
- * Returns available lambdas on specified links.
- *
- * @param links the links
- * @return available lambdas on specified links
- */
- private Iterable<LambdaResource> getAvailableLambdas(Iterable<Link> links) {
- checkNotNull(links);
- Iterator<Link> i = links.iterator();
- checkArgument(i.hasNext());
- Set<LambdaResource> lambdas = new HashSet<>(getAvailableLambdas(i.next()));
- while (i.hasNext()) {
- lambdas.retainAll(getAvailableLambdas(i.next()));
- }
- return lambdas;
- }
-
-
- /**
- * Returns available MPLS label on specified link.
- *
- * @param link the link
- * @return available MPLS labels on specified link
- */
- private Iterable<MplsLabel> getAvailableMplsLabels(Link link) {
- Set<ResourceAllocation> resAllocs = store.getFreeResources(link);
- if (resAllocs == null) {
- return Collections.emptySet();
- }
- Set<MplsLabel> mplsLabels = new HashSet<>();
- for (ResourceAllocation res : resAllocs) {
- if (res.type() == ResourceType.MPLS_LABEL) {
-
- mplsLabels.add(((MplsLabelResourceAllocation) res).mplsLabel());
- }
- }
-
- return mplsLabels;
- }
@Override
public LinkResourceAllocations requestResources(LinkResourceRequest req) {
@@ -164,26 +99,23 @@ public class LinkResourceManager
allocs.add(new BandwidthResourceAllocation(br.bandwidth()));
break;
case LAMBDA:
- Iterator<LambdaResource> lambdaIterator =
- getAvailableLambdas(req.links()).iterator();
- if (lambdaIterator.hasNext()) {
- allocs.add(new LambdaResourceAllocation(lambdaIterator.next()));
- } else {
- log.info("Failed to allocate lambda resource.");
- return null;
- }
+ LambdaResourceRequest lr = (LambdaResourceRequest) r;
+ allocs.add(new LambdaResourceAllocation(lr.lambda()));
break;
case MPLS_LABEL:
for (Link link : req.links()) {
if (allocsPerLink.get(link) == null) {
allocsPerLink.put(link, new HashSet<>());
}
- Iterator<MplsLabel> mplsIter = getAvailableMplsLabels(link)
- .iterator();
- if (mplsIter.hasNext()) {
- allocsPerLink.get(link)
- .add(new MplsLabelResourceAllocation(mplsIter
- .next()));
+
+ Optional<MplsLabel> label = req.resources(link).stream()
+ .filter(x -> x.type() == ResourceType.MPLS_LABEL)
+ .map(x -> (MplsLabelResourceRequest) x)
+ .map(MplsLabelResourceRequest::mplsLabel)
+ .findFirst();
+
+ if (label.isPresent()) {
+ allocsPerLink.get(link).add(new MplsLabelResourceAllocation(label.get()));
} else {
log.info("Failed to allocate MPLS resource.");
break;
@@ -258,10 +190,12 @@ public class LinkResourceManager
((BandwidthResourceAllocation) alloc).bandwidth()));
break;
case LAMBDA:
- result.add(new LambdaResourceRequest());
+ result.add(new LambdaResourceRequest(
+ ((LambdaResourceAllocation) alloc).lambda()));
break;
case MPLS_LABEL:
- result.add(new MplsLabelResourceRequest());
+ result.add(new MplsLabelResourceRequest(
+ ((MplsLabelResourceAllocation) alloc).mplsLabel()));
break;
default:
break;
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
new file mode 100644
index 00000000..06b2c81e
--- /dev/null
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MockResourceService.java
@@ -0,0 +1,100 @@
+/*
+ * 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.net.intent.impl.compiler;
+
+import com.google.common.collect.ImmutableList;
+import org.onlab.packet.MplsLabel;
+import org.onosproject.net.newresource.ResourceAllocation;
+import org.onosproject.net.newresource.ResourceConsumer;
+import org.onosproject.net.newresource.ResourcePath;
+import org.onosproject.net.newresource.ResourceService;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+class MockResourceService implements ResourceService {
+
+ private final Map<ResourcePath, ResourceConsumer> assignment = new HashMap<>();
+
+ @Override
+ public List<ResourceAllocation> allocate(ResourceConsumer consumer, List<ResourcePath> resources) {
+ assignment.putAll(
+ resources.stream().collect(Collectors.toMap(x -> x, x -> consumer))
+ );
+
+ return resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean release(List<ResourceAllocation> allocations) {
+ allocations.forEach(x -> assignment.remove(x.resource()));
+
+ return true;
+ }
+
+ @Override
+ public boolean release(ResourceConsumer consumer) {
+ List<ResourcePath> resources = assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(Map.Entry::getKey)
+ .collect(Collectors.toList());
+ List<ResourceAllocation> allocations = resources.stream()
+ .map(x -> new ResourceAllocation(x, consumer))
+ .collect(Collectors.toList());
+
+ return release(allocations);
+ }
+
+ @Override
+ public Optional<ResourceAllocation> getResourceAllocation(ResourcePath resource) {
+ return Optional.ofNullable(assignment.get(resource))
+ .map(x -> new ResourceAllocation(resource, x));
+ }
+
+ @Override
+ public <T> Collection<ResourceAllocation> getResourceAllocations(ResourcePath parent, Class<T> cls) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getKey().parent().isPresent())
+ .filter(x -> x.getKey().parent().get().equals(parent))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourceAllocation> getResourceAllocations(ResourceConsumer consumer) {
+ return assignment.entrySet().stream()
+ .filter(x -> x.getValue().equals(consumer))
+ .map(x -> new ResourceAllocation(x.getKey(), x.getValue()))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<ResourcePath> getAvailableResources(ResourcePath parent) {
+ ResourcePath resource = ResourcePath.child(parent, MplsLabel.mplsLabel(10));
+ return ImmutableList.of(resource);
+ }
+
+ @Override
+ public boolean isAvailable(ResourcePath resource) {
+ return true;
+ }
+}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
index 771a9883..6cceee12 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/intent/impl/compiler/MplsPathIntentCompilerTest.java
@@ -41,10 +41,8 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.FlowRuleIntent;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentExtensionService;
-import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.net.intent.MockIdGenerator;
import org.onosproject.net.intent.MplsPathIntent;
-import org.onosproject.store.trivial.SimpleLinkStore;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -52,6 +50,7 @@ import static org.easymock.EasyMock.replay;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
+import static org.onosproject.net.DefaultEdgeLink.createEdgeLink;
import static org.onosproject.net.Link.Type.DIRECT;
import static org.onosproject.net.NetTestTools.APP_ID;
import static org.onosproject.net.NetTestTools.PID;
@@ -61,10 +60,12 @@ public class MplsPathIntentCompilerTest {
private final ApplicationId appId = new TestApplicationId("test");
+ private final ConnectPoint d1pi = connectPoint("s1", 100);
private final ConnectPoint d1p1 = connectPoint("s1", 0);
private final ConnectPoint d2p0 = connectPoint("s2", 0);
private final ConnectPoint d2p1 = connectPoint("s2", 1);
private final ConnectPoint d3p1 = connectPoint("s3", 1);
+ private final ConnectPoint d3pe = connectPoint("s3", 100);
private final TrafficSelector selector = DefaultTrafficSelector.builder().build();
private final TrafficTreatment treatment = DefaultTrafficTreatment.builder().build();
@@ -75,8 +76,10 @@ public class MplsPathIntentCompilerTest {
Optional.of(MplsLabel.mplsLabel(20));
private final List<Link> links = Arrays.asList(
+ createEdgeLink(d1pi, true),
new DefaultLink(PID, d1p1, d2p0, DIRECT),
- new DefaultLink(PID, d2p1, d3p1, DIRECT)
+ new DefaultLink(PID, d2p1, d3p1, DIRECT),
+ createEdgeLink(d3pe, false)
);
private IdGenerator idGenerator = new MockIdGenerator();
@@ -92,8 +95,7 @@ public class MplsPathIntentCompilerTest {
expect(coreService.registerApplication("org.onosproject.net.intent"))
.andReturn(appId);
sut.coreService = coreService;
- sut.linkStore = new SimpleLinkStore();
- sut.resourceService = new IntentTestsMocks.MockResourceService();
+ sut.resourceService = new MockResourceService();
Intent.bindIdGenerator(idGenerator);
@@ -128,7 +130,7 @@ public class MplsPathIntentCompilerTest {
assertThat(compiled, hasSize(1));
Collection<FlowRule> rules = ((FlowRuleIntent) compiled.get(0)).flowRules();
- assertThat(rules, hasSize(1));
+ assertThat(rules, hasSize(3));
FlowRule rule = rules.stream()
.filter(x -> x.deviceId().equals(d2p0.deviceId()))
@@ -139,4 +141,5 @@ public class MplsPathIntentCompilerTest {
sut.deactivate();
}
+
}
diff --git a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
index 1a160d98..3e806a73 100644
--- a/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
+++ b/framework/src/onos/core/net/src/test/java/org/onosproject/net/proxyarp/impl/ProxyArpManagerTest.java
@@ -21,11 +21,19 @@ import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.ARP;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.ICMP6;
+import org.onlab.packet.IPacket;
+import org.onlab.packet.IPv6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
+import org.onlab.packet.ndp.NeighborAdvertisement;
+import org.onlab.packet.ndp.NeighborDiscoveryOptions;
+import org.onlab.packet.ndp.NeighborSolicitation;
import org.onosproject.incubator.net.intf.Interface;
import org.onosproject.incubator.net.intf.InterfaceService;
import org.onosproject.net.ConnectPoint;
@@ -66,9 +74,13 @@ 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.anyOf;
+import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
@@ -83,6 +95,8 @@ public class ProxyArpManagerTest {
private static final Ip4Address IP1 = Ip4Address.valueOf("192.168.1.1");
private static final Ip4Address IP2 = Ip4Address.valueOf("192.168.1.2");
+ private static final Ip6Address IP3 = Ip6Address.valueOf("1000::1");
+ private static final Ip6Address IP4 = Ip6Address.valueOf("1000::2");
private static final ProviderId PID = new ProviderId("of", "foo");
@@ -90,8 +104,14 @@ public class ProxyArpManagerTest {
private static final VlanId VLAN2 = VlanId.vlanId((short) 2);
private static final MacAddress MAC1 = MacAddress.valueOf("00:00:11:00:00:01");
private static final MacAddress MAC2 = MacAddress.valueOf("00:00:22:00:00:02");
+ private static final MacAddress MAC3 = MacAddress.valueOf("00:00:33:00:00:03");
+ private static final MacAddress MAC4 = MacAddress.valueOf("00:00:44:00:00:04");
+ private static final MacAddress SOLICITED_MAC3 = MacAddress.valueOf("33:33:FF:00:00:01");
private static final HostId HID1 = HostId.hostId(MAC1, VLAN1);
private static final HostId HID2 = HostId.hostId(MAC2, VLAN1);
+ private static final HostId HID3 = HostId.hostId(MAC3, VLAN1);
+ private static final HostId HID4 = HostId.hostId(MAC4, VLAN1);
+ private static final HostId SOLICITED_HID3 = HostId.hostId(SOLICITED_MAC3, VLAN1);
private static final DeviceId DID1 = getDeviceId(1);
private static final DeviceId DID2 = getDeviceId(2);
@@ -222,21 +242,29 @@ public class ProxyArpManagerTest {
for (int i = 1; i <= NUM_ADDRESS_PORTS; i++) {
ConnectPoint cp = new ConnectPoint(getDeviceId(i), P1);
- Ip4Prefix prefix1 =
- Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
- Ip4Address addr1 =
- Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
+
+ // Interface address for IPv4
+ Ip4Prefix prefix1 = Ip4Prefix.valueOf("10.0." + (2 * i - 1) + ".0/24");
+ Ip4Address addr1 = Ip4Address.valueOf("10.0." + (2 * i - 1) + ".1");
Ip4Prefix prefix2 = Ip4Prefix.valueOf("10.0." + (2 * i) + ".0/24");
Ip4Address addr2 = Ip4Address.valueOf("10.0." + (2 * i) + ".1");
InterfaceIpAddress ia1 = new InterfaceIpAddress(addr1, prefix1);
InterfaceIpAddress ia2 = new InterfaceIpAddress(addr2, prefix2);
- Interface intf1 = new Interface(cp, Sets.newHashSet(ia1),
+
+ // Interface address for IPv6
+ Ip6Prefix prefix3 = Ip6Prefix.valueOf((2 * i - 1) + "000::0/64");
+ Ip6Address addr3 = Ip6Address.valueOf((2 * i - 1) + "000::1");
+ Ip6Prefix prefix4 = Ip6Prefix.valueOf((2 * i) + "000::0/64");
+ Ip6Address addr4 = Ip6Address.valueOf((2 * i) + "000::1");
+ InterfaceIpAddress ia3 = new InterfaceIpAddress(addr3, prefix3);
+ InterfaceIpAddress ia4 = new InterfaceIpAddress(addr4, prefix4);
+
+ Interface intf1 = new Interface(cp, Sets.newHashSet(ia1, ia3),
MacAddress.valueOf(2 * i - 1),
VlanId.vlanId((short) 1));
- Interface intf2 = new Interface(cp, Sets.newHashSet(ia2),
+ Interface intf2 = new Interface(cp, Sets.newHashSet(ia2, ia4),
MacAddress.valueOf(2 * i),
VlanId.NONE);
-
interfaces.add(intf1);
interfaces.add(intf2);
@@ -321,6 +349,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct NDP reply is sent out the correct port.
+ */
+ @Test
+ public void testReplyKnownIpv6() {
+ //Set the return value of isEdgePoint from the edgemanager.
+ isEdgePointReturn = true;
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN1, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+
+ assertEquals(1, packetService.packets.size());
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ MAC3, MAC4, IP3, IP4);
+ verifyPacketOut(ndpReply, getLocation(5), packetService.packets.get(0));
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the ARP request is flooded out the correct edge ports.
*/
@@ -337,7 +400,6 @@ public class ProxyArpManagerTest {
.andReturn(Collections.emptySet());
expect(hostService.getHost(HID2)).andReturn(requestor);
-
replay(hostService);
replay(interfaceService);
@@ -355,6 +417,41 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyUnknownIpv6() {
+ isEdgePointReturn = true;
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup the set of edge ports to be used in the reply method
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
* destination host is known for that IP address, but is not on the same
* VLAN as the source host.
* Verifies the ARP request is flooded out the correct edge ports.
@@ -388,6 +485,46 @@ public class ProxyArpManagerTest {
verifyFlood(arpRequest);
}
+ /**
+ * Tests {@link ProxyArpManager#reply(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known for that IP address, but is not on the same
+ * VLAN as the source host.
+ * Verifies the NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testReplyDifferentVlanIpv6() {
+
+ Host replyer = new DefaultHost(PID, HID3, MAC3, VLAN2, getLocation(4),
+ Collections.singleton(IP3));
+
+ Host requestor = new DefaultHost(PID, HID4, MAC4, VLAN1, getLocation(5),
+ Collections.singleton(IP4));
+
+ expect(hostService.getHostsByIp(IP3))
+ .andReturn(Collections.singleton(replyer));
+ expect(interfaceService.getInterfacesByIp(IP4))
+ .andReturn(Collections.emptySet());
+ expect(hostService.getHost(HID4)).andReturn(requestor);
+
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //Setup for flood test
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+ proxyArp.reply(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
+ * Test ARP request from external network to an internal host.
+ */
@Test
public void testReplyToRequestForUs() {
Ip4Address theirIp = Ip4Address.valueOf("10.0.1.254");
@@ -422,6 +559,63 @@ public class ProxyArpManagerTest {
verifyPacketOut(arpReply, LOC1, packetService.packets.get(0));
}
+ /**
+ * Test NDP request from external network to an internal host.
+ */
+ @Test
+ public void testReplyToRequestForUsIpv6() {
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+ Ip6Address ourFirstIp = Ip6Address.valueOf("1000::1");
+ Ip6Address ourSecondIp = Ip6Address.valueOf("2000::1");
+ MacAddress firstMac = MacAddress.valueOf(1L);
+ MacAddress secondMac = MacAddress.valueOf(2L);
+
+ Host requestor = new DefaultHost(PID, HID2, MAC2, VLAN1, LOC1,
+ Collections.singleton(theirIp));
+
+ expect(hostService.getHost(HID2)).andReturn(requestor);
+ expect(hostService.getHostsByIp(ourFirstIp))
+ .andReturn(Collections.singleton(requestor));
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourFirstIp);
+ isEdgePointReturn = true;
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ Ethernet ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ firstMac,
+ MAC2,
+ ourFirstIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+
+ // Test a request for the second address on that port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC2,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ ourSecondIp);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(1, packetService.packets.size());
+
+ ndpReply = buildNDP(ICMP6.NEIGHBOR_ADVERTISEMENT,
+ secondMac,
+ MAC2,
+ ourSecondIp,
+ theirIp);
+ verifyPacketOut(ndpReply, LOC1, packetService.packets.get(0));
+ }
+
+ /**
+ * Request for a valid external IPv4 address but coming in the wrong port.
+ */
@Test
public void testReplyExternalPortBadRequest() {
replay(hostService); // no further host service expectations
@@ -442,6 +636,38 @@ public class ProxyArpManagerTest {
assertEquals(0, packetService.packets.size());
}
+ /**
+ * Request for a valid external IPv6 address but coming in the wrong port.
+ */
+ @Test
+ public void testReplyExternalPortBadRequestIpv6() {
+ replay(hostService); // no further host service expectations
+ replay(interfaceService);
+
+ Ip6Address theirIp = Ip6Address.valueOf("1000::ffff");
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ Ip6Address.valueOf("3000::1"));
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+
+ // Request for a valid internal IP address but coming in an external port
+ packetService.packets.clear();
+ ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC1,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ theirIp,
+ IP3);
+ proxyArp.reply(ndpRequest, LOC1);
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
+ * Test ARP request from internal network to an external host.
+ */
@Test
public void testReplyToRequestFromUs() {
Ip4Address ourIp = Ip4Address.valueOf("10.0.1.1");
@@ -474,6 +700,48 @@ public class ProxyArpManagerTest {
}
/**
+ * Test NDP request from internal network to an external host.
+ */
+ @Test
+ public void testReplyToRequestFromUsIpv6() {
+ Ip6Address ourIp = Ip6Address.valueOf("1000::1");
+ MacAddress ourMac = MacAddress.valueOf(1L);
+ Ip6Address theirIp = Ip6Address.valueOf("1000::100");
+
+ expect(hostService.getHostsByIp(theirIp)).andReturn(Collections.emptySet());
+ expect(interfaceService.getInterfacesByIp(ourIp))
+ .andReturn(Collections.singleton(new Interface(getLocation(1),
+ Collections.singleton(new InterfaceIpAddress(
+ ourIp,
+ IpPrefix.valueOf("1000::1/64"))),
+ ourMac,
+ VLAN1)));
+ expect(hostService.getHost(HostId.hostId(ourMac, VLAN1))).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ // This is a request from something inside our network (like a BGP
+ // daemon) to an external host.
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ ourMac,
+ MacAddress.valueOf("33:33:ff:00:00:01"),
+ ourIp,
+ theirIp);
+
+ //Ensure the packet is allowed through (it is not to an internal port)
+ isEdgePointReturn = true;
+
+ proxyArp.reply(ndpRequest, getLocation(5));
+ assertEquals(1, packetService.packets.size());
+ verifyPacketOut(ndpRequest, getLocation(1), packetService.packets.get(0));
+
+ // The same request from a random external port should fail
+ packetService.packets.clear();
+ proxyArp.reply(ndpRequest, getLocation(2));
+ assertEquals(0, packetService.packets.size());
+ }
+
+ /**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is known.
* Verifies the correct ARP request is sent out the correct port.
@@ -502,6 +770,35 @@ public class ProxyArpManagerTest {
/**
* Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is known.
+ * Verifies the correct ARP request is sent out the correct port.
+ */
+ @Test
+ public void testForwardToHostIpv6() {
+ Host host1 = new DefaultHost(PID, HID3, MAC3, VLAN1, LOC1,
+ Collections.singleton(IP3));
+ Host host2 = new DefaultHost(PID, HID4, MAC4, VLAN1, LOC2,
+ Collections.singleton(IP4));
+
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(host1);
+ expect(hostService.getHost(HID4)).andReturn(host2);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ proxyArp.forward(ndpRequest, LOC2);
+
+ assertEquals(1, packetService.packets.size());
+ OutboundPacket packet = packetService.packets.get(0);
+
+ verifyPacketOut(ndpRequest, LOC1, packet);
+ }
+
+ /**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
* destination host is not known.
* Verifies the correct ARP request is flooded out the correct edge ports.
*/
@@ -526,6 +823,33 @@ public class ProxyArpManagerTest {
}
/**
+ * Tests {@link ProxyArpManager#forward(Ethernet, ConnectPoint)} in the case where the
+ * destination host is not known.
+ * Verifies the correct NDP request is flooded out the correct edge ports.
+ */
+ @Test
+ public void testForwardFloodIpv6() {
+ expect(hostService.getHost(SOLICITED_HID3)).andReturn(null);
+ replay(hostService);
+ replay(interfaceService);
+
+ Ethernet ndpRequest = buildNDP(ICMP6.NEIGHBOR_SOLICITATION,
+ MAC4, SOLICITED_MAC3,
+ IP4, IP3);
+
+ //populate the list of edges when so that when forward hits flood in the manager it contains the values
+ //that should continue on
+ getEdgePointsNoArg = Lists.newLinkedList();
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("3"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("5"), PortNumber.portNumber(1)));
+ getEdgePointsNoArg.add(new ConnectPoint(DeviceId.deviceId("4"), PortNumber.portNumber(1)));
+
+ proxyArp.forward(ndpRequest, getLocation(6));
+
+ verifyFlood(ndpRequest);
+ }
+
+ /**
* Verifies that the given packet was flooded out all available edge ports,
* except for the input port.
*
@@ -626,6 +950,61 @@ public class ProxyArpManagerTest {
}
/**
+ * Builds an NDP packet with the given parameters.
+ *
+ * @param type NeighborSolicitation or NeighborAdvertisement
+ * @param srcMac source MAC address
+ * @param dstMac destination MAC address, or null if this is a request
+ * @param srcIp source IP address
+ * @param dstIp destination IP address
+ * @return the NDP packet
+ */
+ private Ethernet buildNDP(byte type, MacAddress srcMac, MacAddress dstMac,
+ Ip6Address srcIp, Ip6Address dstIp) {
+ assertThat(type, anyOf(
+ is(ICMP6.NEIGHBOR_SOLICITATION),
+ is(ICMP6.NEIGHBOR_ADVERTISEMENT)
+ ));
+ assertNotNull(srcMac);
+ assertNotNull(dstMac);
+ assertNotNull(srcIp);
+ assertNotNull(dstIp);
+
+ IPacket ndp;
+ if (type == ICMP6.NEIGHBOR_SOLICITATION) {
+ ndp = new NeighborSolicitation().setTargetAddress(dstIp.toOctets());
+ } else {
+ ndp = new NeighborAdvertisement()
+ .setSolicitedFlag((byte) 1)
+ .setOverrideFlag((byte) 1)
+ .setTargetAddress(srcIp.toOctets())
+ .addOption(NeighborDiscoveryOptions.TYPE_TARGET_LL_ADDRESS,
+ srcMac.toBytes());
+ }
+
+ ICMP6 icmp6 = new ICMP6();
+ icmp6.setIcmpType(type);
+ icmp6.setIcmpCode((byte) 0);
+ icmp6.setPayload(ndp);
+
+ IPv6 ipv6 = new IPv6();
+ ipv6.setDestinationAddress(dstIp.toOctets());
+ ipv6.setSourceAddress(srcIp.toOctets());
+ ipv6.setNextHeader(IPv6.PROTOCOL_ICMP6);
+ ipv6.setHopLimit((byte) 255);
+ ipv6.setPayload(icmp6);
+
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress(dstMac);
+ eth.setSourceMACAddress(srcMac);
+ eth.setEtherType(Ethernet.TYPE_IPV6);
+ eth.setVlanID(VLAN1.toShort());
+ eth.setPayload(ipv6);
+
+ return eth;
+ }
+
+ /**
* Test PacketService implementation that simply stores OutboundPackets
* passed to {@link #emit(OutboundPacket)} for later verification.
*/
diff --git a/framework/src/onos/core/store/dist/pom.xml b/framework/src/onos/core/store/dist/pom.xml
index cc293da4..f2ec2a71 100644
--- a/framework/src/onos/core/store/dist/pom.xml
+++ b/framework/src/onos/core/store/dist/pom.xml
@@ -71,7 +71,7 @@
<dependency>
<groupId>org.mapdb</groupId>
<artifactId>mapdb</artifactId>
- <version>1.0.7</version>
+ <version>1.0.8</version>
</dependency>
<dependency>
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java
deleted file mode 100644
index 75f05a31..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinition.java
+++ /dev/null
@@ -1,58 +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.store.cluster.impl;
-
-import java.util.Set;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Cluster definition.
- */
-public class ClusterDefinition {
-
- private Set<NodeInfo> nodes;
- private String ipPrefix;
-
- /**
- * Creates a new cluster definition.
- * @param nodes cluster nodes information
- * @param ipPrefix ip prefix common to all cluster nodes
- * @return cluster definition
- */
- public static ClusterDefinition from(Set<NodeInfo> nodes, String ipPrefix) {
- ClusterDefinition definition = new ClusterDefinition();
- definition.ipPrefix = ipPrefix;
- definition.nodes = ImmutableSet.copyOf(nodes);
- return definition;
- }
-
- /**
- * Returns set of cluster nodes info.
- * @return cluster nodes info
- */
- public Set<NodeInfo> getNodes() {
- return ImmutableSet.copyOf(nodes);
- }
-
- /**
- * Returns ipPrefix in dotted decimal notion.
- * @return ip prefix
- */
- public String getIpPrefix() {
- return ipPrefix;
- }
-} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java
deleted file mode 100644
index 8b0001d8..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionManager.java
+++ /dev/null
@@ -1,194 +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.store.cluster.impl;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-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.onlab.packet.IpAddress;
-import org.onosproject.cluster.ClusterDefinitionService;
-import org.onosproject.cluster.ControllerNode;
-import org.onosproject.cluster.DefaultControllerNode;
-import org.onosproject.cluster.NodeId;
-import org.onosproject.store.consistent.impl.DatabaseDefinition;
-import org.onosproject.store.consistent.impl.DatabaseDefinitionStore;
-import org.slf4j.Logger;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Enumeration;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import static java.net.NetworkInterface.getNetworkInterfaces;
-import static java.util.Collections.list;
-import static org.onosproject.cluster.DefaultControllerNode.DEFAULT_PORT;
-import static org.onosproject.store.consistent.impl.DatabaseManager.PARTITION_DEFINITION_FILE;
-import static org.slf4j.LoggerFactory.getLogger;
-
-/**
- * Implementation of ClusterDefinitionService.
- */
-@Component(immediate = true)
-@Service
-public class ClusterDefinitionManager implements ClusterDefinitionService {
-
- public static final String CLUSTER_DEFINITION_FILE = "../config/cluster.json";
- private static final String ONOS_NIC = "ONOS_NIC";
- private static final Logger log = getLogger(ClusterDefinitionManager.class);
- private ControllerNode localNode;
- private Set<ControllerNode> seedNodes;
-
- @Activate
- public void activate() {
- File clusterDefinitionFile = new File(CLUSTER_DEFINITION_FILE);
- ClusterDefinitionStore clusterDefinitionStore =
- new ClusterDefinitionStore(clusterDefinitionFile.getPath());
-
- if (!clusterDefinitionFile.exists()) {
- createDefaultClusterDefinition(clusterDefinitionStore);
- }
-
- try {
- ClusterDefinition clusterDefinition = clusterDefinitionStore.read();
- establishSelfIdentity(clusterDefinition);
- seedNodes = ImmutableSet
- .copyOf(clusterDefinition.getNodes())
- .stream()
- .filter(n -> !localNode.id().equals(new NodeId(n.getId())))
- .map(n -> new DefaultControllerNode(new NodeId(n.getId()),
- IpAddress.valueOf(n.getIp()),
- n.getTcpPort()))
- .collect(Collectors.toSet());
- } catch (IOException e) {
- throw new IllegalStateException("Failed to read cluster definition.", e);
- }
-
- log.info("Started");
- }
-
- @Deactivate
- public void deactivate() {
- log.info("Stopped");
- }
-
- @Override
- public ControllerNode localNode() {
- return localNode;
- }
-
- @Override
- public Set<ControllerNode> seedNodes() {
- return seedNodes;
- }
-
- @Override
- public void formCluster(Set<ControllerNode> nodes, String ipPrefix) {
- try {
- Set<NodeInfo> infos = Sets.newHashSet();
- nodes.forEach(n -> infos.add(NodeInfo.from(n.id().toString(),
- n.ip().toString(),
- n.tcpPort())));
-
- ClusterDefinition cdef = ClusterDefinition.from(infos, ipPrefix);
- new ClusterDefinitionStore(CLUSTER_DEFINITION_FILE).write(cdef);
-
- DatabaseDefinition ddef = DatabaseDefinition.from(infos);
- new DatabaseDefinitionStore(PARTITION_DEFINITION_FILE).write(ddef);
- } catch (IOException e) {
- log.error("Unable to form cluster", e);
- }
- }
-
- private IpAddress findLocalIp(ClusterDefinition clusterDefinition) throws SocketException {
- Enumeration<NetworkInterface> interfaces =
- NetworkInterface.getNetworkInterfaces();
- while (interfaces.hasMoreElements()) {
- NetworkInterface iface = interfaces.nextElement();
- Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
- while (inetAddresses.hasMoreElements()) {
- IpAddress ip = IpAddress.valueOf(inetAddresses.nextElement());
- if (clusterDefinition.getNodes().stream()
- .map(NodeInfo::getIp)
- .map(IpAddress::valueOf)
- .anyMatch(nodeIp -> ip.equals(nodeIp))) {
- return ip;
- }
- }
- }
- throw new IllegalStateException("Unable to determine local ip");
- }
-
- private void establishSelfIdentity(ClusterDefinition clusterDefinition) {
- try {
- IpAddress ip = findLocalIp(clusterDefinition);
- localNode = new DefaultControllerNode(new NodeId(ip.toString()), ip);
- } catch (SocketException e) {
- throw new IllegalStateException("Cannot determine local IP", e);
- }
- }
-
- private void createDefaultClusterDefinition(ClusterDefinitionStore store) {
- // Assumes IPv4 is returned.
- String ip = getSiteLocalAddress();
- String ipPrefix = ip.replaceFirst("\\.[0-9]*$", ".*");
- NodeInfo node = NodeInfo.from(ip, ip, DEFAULT_PORT);
- try {
- store.write(ClusterDefinition.from(ImmutableSet.of(node), ipPrefix));
- } catch (IOException e) {
- log.warn("Unable to write default cluster definition", e);
- }
- }
-
- /**
- * Returns the address that matches the IP prefix given in ONOS_NIC
- * environment variable if one was specified, or the first site local
- * address if one can be found or the loopback address otherwise.
- *
- * @return site-local address in string form
- */
- public static String getSiteLocalAddress() {
- try {
- String ipPrefix = System.getenv(ONOS_NIC);
- for (NetworkInterface nif : list(getNetworkInterfaces())) {
- for (InetAddress address : list(nif.getInetAddresses())) {
- IpAddress ip = IpAddress.valueOf(address);
- if (ipPrefix == null && address.isSiteLocalAddress() ||
- ipPrefix != null && matchInterface(ip.toString(), ipPrefix)) {
- return ip.toString();
- }
- }
- }
- } catch (SocketException e) {
- log.error("Unable to get network interfaces", e);
- }
-
- return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
- }
-
- // Indicates whether the specified interface address matches the given prefix.
- // FIXME: Add a facility to IpPrefix to make this more robust
- private static boolean matchInterface(String ip, String ipPrefix) {
- String s = ipPrefix.replaceAll("\\.\\*", "");
- return ip.startsWith(s);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java
deleted file mode 100644
index 2a2f4dc4..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/ClusterDefinitionStore.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.store.cluster.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.io.Files;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Allows for reading and writing cluster definition as a JSON file.
- */
-public class ClusterDefinitionStore {
-
- private final File file;
-
- /**
- * Creates a reader/writer of the cluster definition file.
- * @param filePath location of the definition file
- */
- public ClusterDefinitionStore(String filePath) {
- file = new File(filePath);
- }
-
- /**
- * Returns the cluster definition.
- * @return cluster definition
- * @throws IOException when I/O exception of some sort has occurred
- */
- public ClusterDefinition read() throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- return mapper.readValue(file, ClusterDefinition.class);
- }
-
- /**
- * Writes the specified cluster definition to file.
- * @param definition cluster definition
- * @throws IOException when I/O exception of some sort has occurred
- */
- public void write(ClusterDefinition definition) throws IOException {
- checkNotNull(definition);
- // write back to file
- Files.createParentDirs(file);
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeValue(file, definition);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
index 859efebf..3bb6a708 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
@@ -27,8 +27,8 @@ import org.apache.felix.scr.annotations.Service;
import org.joda.time.DateTime;
import org.onlab.packet.IpAddress;
import org.onlab.util.KryoNamespace;
-import org.onosproject.cluster.ClusterDefinitionService;
import org.onosproject.cluster.ClusterEvent;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterStore;
import org.onosproject.cluster.ClusterStoreDelegate;
import org.onosproject.cluster.ControllerNode;
@@ -99,14 +99,14 @@ public class DistributedClusterStore
private ControllerNode localNode;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MessagingService messagingService;
@Activate
public void activate() {
- localNode = clusterDefinitionService.localNode();
+ localNode = clusterMetadataService.getLocalNode();
messagingService.registerHandler(HEARTBEAT_MESSAGE,
new HeartbeatMessageHandler(), heartBeatMessageHandler);
@@ -116,9 +116,6 @@ public class DistributedClusterStore
heartBeatSender.scheduleWithFixedDelay(this::heartbeat, 0,
HEARTBEAT_INTERVAL_MS, TimeUnit.MILLISECONDS);
- addNode(localNode);
- updateState(localNode.id(), State.ACTIVE);
-
log.info("Started");
}
@@ -188,7 +185,7 @@ public class DistributedClusterStore
private void addNode(ControllerNode node) {
allNodes.put(node.id(), node);
- updateState(node.id(), State.INACTIVE);
+ updateState(node.id(), node.equals(localNode) ? State.ACTIVE : State.INACTIVE);
notifyDelegate(new ClusterEvent(ClusterEvent.Type.INSTANCE_ADDED, node));
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java
new file mode 100644
index 00000000..9f6c4130
--- /dev/null
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/StaticClusterMetadataStore.java
@@ -0,0 +1,221 @@
+package org.onosproject.store.cluster.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.net.NetworkInterface.getNetworkInterfaces;
+import static org.slf4j.LoggerFactory.getLogger;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+
+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.onlab.packet.IpAddress;
+import org.onosproject.cluster.ClusterMetadata;
+import org.onosproject.cluster.ClusterMetadataEvent;
+import org.onosproject.cluster.ClusterMetadataStore;
+import org.onosproject.cluster.ClusterMetadataStoreDelegate;
+import org.onosproject.cluster.ControllerNode;
+import org.onosproject.cluster.DefaultControllerNode;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.cluster.Partition;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.service.Versioned;
+import org.slf4j.Logger;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.google.common.base.Throwables;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+/**
+ * ClusterMetadataStore backed by a local file.
+ */
+@Component(immediate = true, enabled = true)
+@Service
+public class StaticClusterMetadataStore
+ extends AbstractStore<ClusterMetadataEvent, ClusterMetadataStoreDelegate>
+ implements ClusterMetadataStore {
+
+ private final Logger log = getLogger(getClass());
+ private static final String CLUSTER_METADATA_FILE = "../config/cluster.json";
+ private static final int DEFAULT_ONOS_PORT = 9876;
+ private final File metadataFile = new File(CLUSTER_METADATA_FILE);
+ private AtomicReference<ClusterMetadata> metadata = new AtomicReference<>();
+ private ObjectMapper mapper;
+ private long version;
+
+ @Activate
+ public void activate() {
+ mapper = new ObjectMapper();
+ SimpleModule module = new SimpleModule();
+ module.addSerializer(NodeId.class, new NodeIdSerializer());
+ module.addDeserializer(NodeId.class, new NodeIdDeserializer());
+ module.addSerializer(ControllerNode.class, new ControllerNodeSerializer());
+ module.addDeserializer(ControllerNode.class, new ControllerNodeDeserializer());
+ mapper.registerModule(module);
+ File metadataFile = new File(CLUSTER_METADATA_FILE);
+ if (metadataFile.exists()) {
+ try {
+ metadata.set(mapper.readValue(metadataFile, ClusterMetadata.class));
+ version = metadataFile.lastModified();
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ } else {
+ String localIp = getSiteLocalAddress();
+ ControllerNode localNode =
+ new DefaultControllerNode(new NodeId(localIp), IpAddress.valueOf(localIp), DEFAULT_ONOS_PORT);
+ metadata.set(ClusterMetadata.builder()
+ .withName("default")
+ .withControllerNodes(Arrays.asList(localNode))
+ .withPartitions(Lists.newArrayList(new Partition("p1", Lists.newArrayList(localNode.id()))))
+ .build());
+ version = System.currentTimeMillis();
+ }
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ log.info("Stopped");
+ }
+
+ @Override
+ public void setDelegate(ClusterMetadataStoreDelegate delegate) {
+ checkNotNull(delegate, "Delegate cannot be null");
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void unsetDelegate(ClusterMetadataStoreDelegate delegate) {
+ this.delegate = null;
+ }
+
+ @Override
+ public boolean hasDelegate() {
+ return this.delegate != null;
+ }
+
+ @Override
+ public Versioned<ClusterMetadata> getClusterMetadata() {
+ return new Versioned<>(metadata.get(), version);
+ }
+
+ @Override
+ public void setClusterMetadata(ClusterMetadata metadata) {
+ checkNotNull(metadata);
+ try {
+ Files.createParentDirs(metadataFile);
+ mapper.writeValue(metadataFile, metadata);
+ this.metadata.set(metadata);
+ } catch (IOException e) {
+ Throwables.propagate(e);
+ }
+ }
+
+ @Override
+ public void setActiveReplica(String partitionId, NodeId nodeId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void unsetActiveReplica(String partitionId, NodeId nodeId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Collection<NodeId> getActiveReplicas(String partitionId) {
+ return metadata.get().getPartitions()
+ .stream()
+ .filter(r -> r.getName().equals(partitionId))
+ .findFirst()
+ .map(r -> r.getMembers())
+ .orElse(null);
+ }
+
+ private static class ControllerNodeSerializer extends JsonSerializer<ControllerNode> {
+ @Override
+ public void serialize(ControllerNode node, JsonGenerator jgen, SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ jgen.writeStartObject();
+ jgen.writeStringField("id", node.id().toString());
+ jgen.writeStringField("ip", node.ip().toString());
+ jgen.writeNumberField("port", node.tcpPort());
+ jgen.writeEndObject();
+ }
+ }
+
+ private static class ControllerNodeDeserializer extends JsonDeserializer<ControllerNode> {
+ @Override
+ public ControllerNode deserialize(JsonParser jp, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ NodeId nodeId = new NodeId(node.get("id").textValue());
+ IpAddress ip = IpAddress.valueOf(node.get("ip").textValue());
+ int port = node.get("port").asInt();
+ return new DefaultControllerNode(nodeId, ip, port);
+ }
+ }
+
+ private static class NodeIdSerializer extends JsonSerializer<NodeId> {
+ @Override
+ public void serialize(NodeId nodeId, JsonGenerator jgen, SerializerProvider provider)
+ throws IOException, JsonProcessingException {
+ jgen.writeString(nodeId.toString());
+ }
+ }
+
+ private class NodeIdDeserializer extends JsonDeserializer<NodeId> {
+ @Override
+ public NodeId deserialize(JsonParser jp, DeserializationContext ctxt)
+ throws IOException, JsonProcessingException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ return new NodeId(node.asText());
+ }
+ }
+
+
+ private static String getSiteLocalAddress() {
+ Function<NetworkInterface, IpAddress> ipLookup = nif -> {
+ for (InetAddress address : Collections.list(nif.getInetAddresses())) {
+ if (address.isSiteLocalAddress()) {
+ return IpAddress.valueOf(address);
+ }
+ }
+ return null;
+ };
+ try {
+ IpAddress ip = ipLookup.apply(NetworkInterface.getByName("eth0"));
+ if (ip != null) {
+ return ip.toString();
+ }
+ for (NetworkInterface nif : Collections.list(getNetworkInterfaces())) {
+ ip = ipLookup.apply(nif);
+ if (ip != null) {
+ return ip.toString();
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Unable to get network interfaces", e);
+ }
+ return IpAddress.valueOf(InetAddress.getLoopbackAddress()).toString();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
index ffdd25f2..ddb45f71 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/IOLoopMessagingManager.java
@@ -22,7 +22,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.nio.service.IOLoopMessaging;
-import org.onosproject.cluster.ClusterDefinitionService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.slf4j.Logger;
@@ -38,11 +38,11 @@ public class IOLoopMessagingManager extends IOLoopMessaging {
private final Logger log = LoggerFactory.getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Activate
public void activate() throws Exception {
- ControllerNode localNode = clusterDefinitionService.localNode();
+ ControllerNode localNode = clusterMetadataService.getLocalNode();
super.start(new Endpoint(localNode.ip(), localNode.tcpPort()));
log.info("Started");
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
index 9328817b..23c81869 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
@@ -16,6 +16,7 @@
package org.onosproject.store.cluster.messaging.impl;
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;
@@ -23,7 +24,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.netty.NettyMessaging;
-import org.onosproject.cluster.ClusterDefinitionService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.cluster.messaging.Endpoint;
import org.slf4j.Logger;
@@ -41,11 +42,11 @@ public class NettyMessagingManager extends NettyMessaging {
private static final short MIN_KS_LENGTH = 6;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected ClusterDefinitionService clusterDefinitionService;
+ protected ClusterMetadataService clusterMetadataService;
@Activate
public void activate() throws Exception {
- ControllerNode localNode = clusterDefinitionService.localNode();
+ ControllerNode localNode = clusterMetadataService.getLocalNode();
getTLSParameters();
super.start(new Endpoint(localNode.ip(), localNode.tcpPort()));
log.info("Started");
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java
deleted file mode 100644
index 11b56c14..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinition.java
+++ /dev/null
@@ -1,108 +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.store.consistent.impl;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import org.onosproject.store.cluster.impl.NodeInfo;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
-/**
- * Partitioned database configuration.
- */
-public class DatabaseDefinition {
- private Map<String, Set<NodeInfo>> partitions;
- private Set<NodeInfo> nodes;
-
- /**
- * Creates a new DatabaseDefinition.
- *
- * @param partitions partition map
- * @param nodes set of nodes
- * @return database definition
- */
- public static DatabaseDefinition from(Map<String, Set<NodeInfo>> partitions,
- Set<NodeInfo> nodes) {
- checkNotNull(partitions);
- checkNotNull(nodes);
- DatabaseDefinition definition = new DatabaseDefinition();
- definition.partitions = ImmutableMap.copyOf(partitions);
- definition.nodes = ImmutableSet.copyOf(nodes);
- return definition;
- }
-
- /**
- * Creates a new DatabaseDefinition using default partitions.
- *
- * @param nodes set of nodes
- * @return database definition
- */
- public static DatabaseDefinition from(Set<NodeInfo> nodes) {
- return from(generateDefaultPartitions(nodes), nodes);
- }
-
- /**
- * Returns the map of database partitions.
- *
- * @return db partition map
- */
- public Map<String, Set<NodeInfo>> getPartitions() {
- return partitions;
- }
-
- /**
- * Returns the set of nodes.
- *
- * @return nodes
- */
- public Set<NodeInfo> getNodes() {
- return nodes;
- }
-
-
- /**
- * Generates set of default partitions using permutations of the nodes.
- *
- * @param nodes information about cluster nodes
- * @return default partition map
- */
- private static Map<String, Set<NodeInfo>> generateDefaultPartitions(Set<NodeInfo> nodes) {
- List<NodeInfo> sorted = new ArrayList<>(nodes);
- Collections.sort(sorted, (o1, o2) -> o1.getId().compareTo(o2.getId()));
- Map<String, Set<NodeInfo>> partitions = Maps.newHashMap();
-
- int length = nodes.size();
- int count = 3;
- for (int i = 0; i < length; i++) {
- Set<NodeInfo> set = new HashSet<>(count);
- for (int j = 0; j < count; j++) {
- set.add(sorted.get((i + j) % length));
- }
- partitions.put("p" + (i + 1), set);
- }
- return partitions;
- }
-
-} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java
deleted file mode 100644
index b77667b2..00000000
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseDefinitionStore.java
+++ /dev/null
@@ -1,74 +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.store.consistent.impl;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import java.io.File;
-import java.io.IOException;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.io.Files;
-
-/**
- * Allows for reading and writing partitioned database definition as a JSON file.
- */
-public class DatabaseDefinitionStore {
-
- private final File file;
-
- /**
- * Creates a reader/writer of the database definition file.
- *
- * @param filePath location of the definition file
- */
- public DatabaseDefinitionStore(String filePath) {
- file = new File(checkNotNull(filePath));
- }
-
- /**
- * Creates a reader/writer of the database definition file.
- *
- * @param filePath location of the definition file
- */
- public DatabaseDefinitionStore(File filePath) {
- file = checkNotNull(filePath);
- }
-
- /**
- * Returns the database definition.
- *
- * @return database definition
- * @throws IOException when I/O exception of some sort has occurred.
- */
- public DatabaseDefinition read() throws IOException {
- ObjectMapper mapper = new ObjectMapper();
- return mapper.readValue(file, DatabaseDefinition.class);
- }
-
- /**
- * Writes the specified database definition to file.
- *
- * @param definition database definition
- * @throws IOException when I/O exception of some sort has occurred.
- */
- public void write(DatabaseDefinition definition) throws IOException {
- checkNotNull(definition);
- // write back to file
- Files.createParentDirs(file);
- ObjectMapper mapper = new ObjectMapper();
- mapper.writeValue(file, definition);
- }
-}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
index 6ea7c220..3e89635a 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DatabaseManager.java
@@ -18,7 +18,6 @@ package org.onosproject.store.consistent.impl;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
@@ -50,12 +49,12 @@ import org.apache.felix.scr.annotations.Service;
import org.onosproject.app.ApplicationEvent;
import org.onosproject.app.ApplicationListener;
import org.onosproject.app.ApplicationService;
+import org.onosproject.cluster.ClusterMetadataService;
import org.onosproject.cluster.ClusterService;
+import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.IdGenerator;
-import org.onosproject.store.cluster.impl.ClusterDefinitionManager;
-import org.onosproject.store.cluster.impl.NodeInfo;
import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
import org.onosproject.store.ecmap.EventuallyConsistentMapBuilderImpl;
import org.onosproject.store.service.AtomicCounterBuilder;
@@ -73,8 +72,6 @@ import org.onosproject.store.service.Transaction;
import org.onosproject.store.service.TransactionContextBuilder;
import org.slf4j.Logger;
-import java.io.File;
-import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -99,8 +96,6 @@ public class DatabaseManager implements StorageService, StorageAdminService {
private final Logger log = getLogger(getClass());
- public static final int COPYCAT_TCP_PORT = 9876;
- public static final String PARTITION_DEFINITION_FILE = "../config/tablets.json";
public static final String BASE_PARTITION_NAME = "p0";
private static final int RAFT_ELECTION_TIMEOUT_MILLIS = 3000;
@@ -122,6 +117,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
Multimaps.synchronizedMultimap(ArrayListMultimap.create());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterMetadataService clusterMetadataService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterService clusterService;
@Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY, policy = ReferencePolicy.DYNAMIC)
@@ -130,8 +128,9 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ClusterCommunicationService clusterCommunicator;
- protected String nodeToUri(NodeInfo node) {
- return String.format("onos://%s:%d", node.getIp(), node.getTcpPort());
+ protected String nodeIdToUri(NodeId nodeId) {
+ ControllerNode node = clusterService.getNode(nodeId);
+ return String.format("onos://%s:%d", node.ip(), node.tcpPort());
}
protected void bindApplicationService(ApplicationService service) {
@@ -147,30 +146,22 @@ public class DatabaseManager implements StorageService, StorageAdminService {
@Activate
public void activate() {
localNodeId = clusterService.getLocalNode().id();
- // load database configuration
- File databaseDefFile = new File(PARTITION_DEFINITION_FILE);
- log.info("Loading database definition: {}", databaseDefFile.getAbsolutePath());
- Map<String, Set<NodeInfo>> partitionMap;
- try {
- DatabaseDefinitionStore databaseDefStore = new DatabaseDefinitionStore(databaseDefFile);
- if (!databaseDefFile.exists()) {
- createDefaultDatabaseDefinition(databaseDefStore);
- }
- partitionMap = databaseDefStore.read().getPartitions();
- } catch (IOException e) {
- throw new IllegalStateException("Failed to load database config", e);
- }
+ Map<String, Set<NodeId>> partitionMap = Maps.newHashMap();
+ clusterMetadataService.getClusterMetadata().getPartitions().forEach(p -> {
+ partitionMap.put(p.getName(), Sets.newHashSet(p.getMembers()));
+ });
+
String[] activeNodeUris = partitionMap.values()
.stream()
.reduce((s1, s2) -> Sets.union(s1, s2))
.get()
.stream()
- .map(this::nodeToUri)
+ .map(this::nodeIdToUri)
.toArray(String[]::new);
- String localNodeUri = nodeToUri(NodeInfo.of(clusterService.getLocalNode()));
+ String localNodeUri = nodeIdToUri(clusterMetadataService.getLocalNode().id());
Protocol protocol = new CopycatCommunicationProtocol(clusterService, clusterCommunicator);
ClusterConfig clusterConfig = new ClusterConfig()
@@ -198,7 +189,7 @@ public class DatabaseManager implements StorageService, StorageAdminService {
List<Database> partitions = partitionMap.entrySet()
.stream()
.map(entry -> {
- String[] replicas = entry.getValue().stream().map(this::nodeToUri).toArray(String[]::new);
+ String[] replicas = entry.getValue().stream().map(this::nodeIdToUri).toArray(String[]::new);
return newDatabaseConfig(entry.getKey(), newPersistentLog(), replicas);
})
.map(config -> {
@@ -229,17 +220,6 @@ public class DatabaseManager implements StorageService, StorageAdminService {
log.info("Started");
}
- private void createDefaultDatabaseDefinition(DatabaseDefinitionStore store) {
- // Assumes IPv4 is returned.
- String ip = ClusterDefinitionManager.getSiteLocalAddress();
- NodeInfo node = NodeInfo.from(ip, ip, COPYCAT_TCP_PORT);
- try {
- store.write(DatabaseDefinition.from(ImmutableSet.of(node)));
- } catch (IOException e) {
- log.warn("Unable to write default cluster definition", e);
- }
- }
-
@Deactivate
public void deactivate() {
CompletableFuture.allOf(inMemoryDatabase.close(), partitionedDatabase.close())
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
index b66f424b..73888221 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/consistent/impl/DefaultTransactionContext.java
@@ -86,7 +86,7 @@ public class DefaultTransactionContext implements TransactionContext {
@SuppressWarnings("unchecked")
@Override
- public void commit() {
+ public boolean commit() {
// TODO: rework commit implementation to be more intuitive
checkState(isOpen, TX_NOT_OPEN_ERROR);
CommitResponse response = null;
@@ -95,10 +95,11 @@ public class DefaultTransactionContext implements TransactionContext {
txMaps.values().forEach(m -> updates.addAll(m.prepareDatabaseUpdates()));
Transaction transaction = new DefaultTransaction(transactionId, updates);
response = Futures.getUnchecked(database.prepareAndCommit(transaction));
+ return response.success();
+ } catch (Exception e) {
+ abort();
+ return false;
} finally {
- if (response != null && !response.success()) {
- abort();
- }
isOpen = false;
}
}
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
index 973db494..687762e0 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
@@ -427,6 +427,7 @@ public class GossipDeviceStore
// Primary providers can respond to all changes, but ancillary ones
// should respond only to annotation changes.
+ DeviceEvent event = null;
if ((providerId.isAncillary() && annotationsChanged) ||
(!providerId.isAncillary() && (propertiesChanged || annotationsChanged))) {
boolean replaced = devices.replace(newDevice.id(), oldDevice, newDevice);
@@ -436,17 +437,18 @@ public class GossipDeviceStore
providerId, oldDevice, devices.get(newDevice.id())
, newDevice);
}
- if (!providerId.isAncillary()) {
- boolean wasOnline = availableDevices.contains(newDevice.id());
- markOnline(newDevice.id(), newTimestamp);
- if (!wasOnline) {
- notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null));
- }
- }
- return new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
+ event = new DeviceEvent(DeviceEvent.Type.DEVICE_UPDATED, newDevice, null);
}
- return null;
+
+ if (!providerId.isAncillary()) {
+ boolean wasOnline = availableDevices.contains(newDevice.id());
+ markOnline(newDevice.id(), newTimestamp);
+ if (!wasOnline) {
+ notifyDelegateIfNotNull(new DeviceEvent(DEVICE_AVAILABILITY_CHANGED, newDevice, null));
+ }
+ }
+ return event;
}
@Override
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
index e62a2d5c..f5ce47fc 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/ecmap/MapDbPersistentStore.java
@@ -100,4 +100,4 @@ class MapDbPersistentStore<K, V> implements PersistentStore<K, V> {
items.remove(keyBytes);
database.commit();
}
-}
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
index 10f79eb0..687576c3 100644
--- a/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
+++ b/framework/src/onos/core/store/dist/src/main/java/org/onosproject/store/newresource/impl/ConsistentResourceStore.java
@@ -52,7 +52,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Implementation of ResourceStore using TransactionalMap.
*/
-@Component(immediate = true, enabled = false)
+@Component(immediate = true)
@Service
@Beta
public class ConsistentResourceStore implements ResourceStore {
@@ -239,6 +239,18 @@ public class ConsistentResourceStore implements ResourceStore {
}
@Override
+ public Collection<ResourcePath> getChildResources(ResourcePath parent) {
+ checkNotNull(parent);
+
+ Versioned<List<ResourcePath>> children = childMap.get(parent);
+ if (children == null) {
+ return Collections.emptyList();
+ }
+
+ return children.value();
+ }
+
+ @Override
public <T> Collection<ResourcePath> getAllocatedResources(ResourcePath parent, Class<T> cls) {
checkNotNull(parent);
checkNotNull(cls);
diff --git a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
index 25e23d3a..61d1937e 100644
--- a/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
+++ b/framework/src/onos/core/store/dist/src/test/java/org/onosproject/store/intent/impl/PartitionManagerTest.java
@@ -325,5 +325,11 @@ public class PartitionManagerTest {
return Objects.equals(this.hash(), that.hash());
}
+
+ @Override
+ public int compareTo(Key o) {
+ Long thisHash = hash();
+ return thisHash.compareTo(o.hash());
+ }
}
}
diff --git a/framework/src/onos/core/store/persistence/pom.xml b/framework/src/onos/core/store/persistence/pom.xml
new file mode 100644
index 00000000..555de11a
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/pom.xml
@@ -0,0 +1,66 @@
+<?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>
+ <repositories>
+ <repository>
+ <id>repository.springsource.com.release</id>
+ <name>SpringSource OBR - Release</name>
+ <url>http://repository.springsource.com/maven/bundles/release</url>
+ </repository>
+ <repository>
+ <id>repository.springsource.com.external</id>
+ <name>SpringSource OBR - External</name>
+ <url>http://repository.springsource.com/maven/bundles/external</url>
+ </repository>
+ </repositories>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-core-store</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-core-persistence</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>ONOS Core persistent local store subsystem</description>
+
+
+
+ <dependencies>
+ <!--<dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ </dependency>-->
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mapdb</groupId>
+ <artifactId>mapdb</artifactId>
+ <version>1.0.8</version>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.java
new file mode 100644
index 00000000..88c7d148
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentMapBuilder.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.persistence.impl;
+
+import org.mapdb.DB;
+import org.onosproject.persistence.PersistentMapBuilder;
+import org.onosproject.store.service.Serializer;
+
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default builder for persistent maps stored in the mapDB local database via the persistence service.
+ */
+public class DefaultPersistentMapBuilder<K, V> implements PersistentMapBuilder<K, V> {
+
+ private final DB localDB;
+
+ private String name = null;
+
+ private Serializer serializer = null;
+
+
+ public DefaultPersistentMapBuilder(DB localDB) {
+ checkNotNull(localDB, "The local database cannot be null.");
+ this.localDB = localDB;
+ }
+
+ public PersistentMapBuilder<K, V> withName(String name) {
+ this.name = PersistenceManager.MAP_PREFIX + checkNotNull(name);
+ return this;
+ }
+
+ public PersistentMapBuilder<K, V> withSerializer(Serializer serializer) {
+ checkArgument(this.serializer == null);
+ checkNotNull(serializer);
+ this.serializer = serializer;
+ return this;
+ }
+
+ public Map<K, V> build() {
+ checkNotNull(name, "The name must be assigned.");
+ checkNotNull(serializer, "The key serializer must be assigned.");
+
+ return new PersistentMap<K, V>(serializer, localDB, name);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.java
new file mode 100644
index 00000000..e1544fb4
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/DefaultPersistentSetBuilder.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.persistence.impl;
+
+import org.mapdb.DB;
+import org.onosproject.persistence.PersistentSetBuilder;
+import org.onosproject.store.service.Serializer;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Default builder for persistent sets stored in the mapDB local database via the persistence service..
+ */
+public class DefaultPersistentSetBuilder<E> implements PersistentSetBuilder<E> {
+
+ private final DB localDB;
+
+ private String name = null;
+
+ private Serializer serializer = null;
+
+ public DefaultPersistentSetBuilder(DB localDB) {
+ this.localDB = checkNotNull(localDB, "The local database cannot be null.");
+ }
+
+ public PersistentSetBuilder<E> withName(String name) {
+ this.name = PersistenceManager.SET_PREFIX + checkNotNull(name);
+ return this;
+ }
+
+ public PersistentSetBuilder<E> withSerializer(Serializer serializer) {
+ checkArgument(this.serializer == null);
+ checkNotNull(serializer);
+ this.serializer = serializer;
+ return this;
+ }
+
+ public PersistentSet<E> build() {
+ checkNotNull(name, "The name must be assigned.");
+ checkNotNull(serializer, "The serializer must be assigned.");
+
+ return new PersistentSet<E>(serializer, localDB, name);
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java
new file mode 100644
index 00000000..f2ba20c2
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceException.java
@@ -0,0 +1,30 @@
+/*
+ * 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.persistence.impl;
+
+/**
+ * An exception defined for failures of the local persistent store system.
+ */
+
+/**
+ * Throws an exception with the specified message.
+ */
+public class PersistenceException extends RuntimeException {
+ public PersistenceException(String s) {
+ super(s);
+ }
+}
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
new file mode 100644
index 00000000..64a8683a
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistenceManager.java
@@ -0,0 +1,138 @@
+/*
+ * 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.persistence.impl;
+
+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.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.PersistenceService;
+import org.onosproject.persistence.PersistentMapBuilder;
+import org.onosproject.persistence.PersistentSetBuilder;
+import org.slf4j.Logger;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Service that maintains local disk backed maps and sets. This implementation automatically deletes empty structures
+ * on shutdown.
+ */
+@Component(immediate = true)
+@Service
+public class PersistenceManager implements PersistenceService {
+
+ private static final String DATABASE_PATH = "../data/localDB";
+
+ private static final String ENCLOSING_FOLDER = "../data";
+
+ static final String MAP_PREFIX = "map:";
+
+ static final String SET_PREFIX = "set:";
+
+ private final Logger log = getLogger(getClass());
+
+ private DB localDB = null;
+
+ private static final int FLUSH_FREQUENCY_MILLIS = 3000;
+
+ private final Timer timer = new Timer();
+
+ private final CommitTask commitTask = new CommitTask();
+
+ @Activate
+ public void activate() {
+ Path dbPath = Paths.get(DATABASE_PATH);
+ Path dbFolderPath = Paths.get(ENCLOSING_FOLDER);
+ //Make sure the directory exists, if it does not, make it.
+ if (!dbFolderPath.toFile().isDirectory()) {
+ log.info("The specified folder location for the database did not exist and will be created.");
+ try {
+ Files.createDirectories(dbFolderPath);
+ } catch (IOException e) {
+ log.error("Could not create the required folder for the database.");
+ throw new PersistenceException("Database folder could not be created.");
+ }
+ }
+ //Notify if the database file does not exist.
+ boolean dbFound = Files.exists(dbPath);
+ if (!dbFound) {
+ log.info("The database file could not be located, a new database will be constructed.");
+
+ } else {
+ log.info("A previous database file has been found.");
+ }
+ localDB = DBMaker.newFileDB(dbPath.toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ timer.schedule(commitTask, FLUSH_FREQUENCY_MILLIS, FLUSH_FREQUENCY_MILLIS);
+ log.info("Started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ for (Map.Entry<String, Object> entry : localDB.getAll().entrySet()) {
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ //This is a map implementation to be handled as such
+ if (value instanceof Map) {
+ Map asMap = (Map) value;
+ if (asMap.isEmpty()) {
+ //the map is empty and may be deleted
+ localDB.delete(key);
+ }
+ //This is a set implementation and can be handled as such
+ } else if (value instanceof Set) {
+ Set asSet = (Set) value;
+ if (asSet.isEmpty()) {
+ //the set is empty and may be deleted
+ localDB.delete(key);
+ }
+ }
+ }
+ localDB.commit();
+ localDB.close();
+ log.info("Stopped");
+ }
+
+ public <K, V> PersistentMapBuilder<K, V> persistentMapBuilder() {
+ return new DefaultPersistentMapBuilder<>(localDB);
+ }
+
+ public <E> PersistentSetBuilder<E> persistentSetBuilder() {
+ return new DefaultPersistentSetBuilder<>(localDB);
+ }
+
+ private class CommitTask extends TimerTask {
+
+ @Override
+ public void run() {
+ localDB.commit();
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java
new file mode 100644
index 00000000..4506bbda
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentMap.java
@@ -0,0 +1,192 @@
+/*
+ * 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.persistence.impl;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.mapdb.DB;
+import org.mapdb.Hasher;
+import org.onosproject.store.service.Serializer;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * A map implementation that stores and receives all data from a serialized internal map.
+ */
+public class PersistentMap<K, V> implements Map<K, V> {
+
+ private final Serializer serializer;
+
+ private final org.mapdb.DB database;
+
+ private final Map<byte[], byte[]> items;
+
+ private final String name;
+
+ public PersistentMap(Serializer serializer, DB database, String name) {
+ this.serializer = checkNotNull(serializer);
+ this.database = checkNotNull(database);
+ this.name = checkNotNull(name);
+
+ items = database
+ .createHashMap(name)
+ .keySerializer(org.mapdb.Serializer.BYTE_ARRAY)
+ .valueSerializer(org.mapdb.Serializer.BYTE_ARRAY)
+ .hasher(Hasher.BYTE_ARRAY)
+ .makeOrGet();
+ }
+
+ /**
+ * Reads this set in deserialized form into the provided map.
+ *
+ * @param items the map to be populated
+ */
+ public void readInto(Map<K, V> items) {
+ this.items.forEach((keyBytes, valueBytes) ->
+ items.put(serializer.decode(keyBytes),
+ serializer.decode(valueBytes)));
+ }
+
+ @Override
+ public V remove(Object key) {
+ checkNotNull(key, "Key can not be null.");
+ V removed = get(key);
+ items.remove(serializer.encode(key));
+ return removed;
+ }
+
+ @Override
+ public int size() {
+ return items.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return items.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ checkNotNull(key, "Key cannot be null.");
+ return items.containsKey(serializer.encode(key));
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ checkNotNull(value, "Value cannot be null.");
+ byte[] serialized = serializer.encode(value);
+ for (byte[] compareValue : items.values()) {
+ boolean same = true;
+ if (compareValue == null) {
+ same = false;
+ } else if (compareValue.length != serialized.length) {
+ same = false;
+ } else {
+ for (int i = 0; i < serialized.length; i++) {
+ if (serialized[i] != compareValue[i]) {
+ same = false;
+ break;
+ }
+ }
+ }
+ if (same) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public V get(Object key) {
+ checkNotNull(key, "Key cannot be null.");
+ return serializer.decode(items.get(serializer.encode(key)));
+ }
+
+ @Override
+ public V put(K key, V value) {
+ checkNotNull(key, "Key cannot be null.");
+ checkNotNull(value, "Value cannot be null.");
+ byte[] prevVal = items.put(serializer.encode(key), serializer.encode(value));
+ if (prevVal == null) {
+ return null;
+ }
+ return serializer.decode(prevVal);
+ }
+
+ @Override
+ public void putAll(Map<? extends K, ? extends V> m) {
+ checkNotNull(m, "The passed in map cannot be null.");
+ m.forEach((k, v) -> items.put(serializer.encode(k), serializer.encode(v)));
+ }
+
+ @Override
+ public void clear() {
+ items.clear();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ Set<K> keys = Sets.newHashSet();
+ items.keySet().forEach(k -> keys.add(serializer.decode(k)));
+ return keys;
+ }
+
+ @Override
+ public Collection<V> values() {
+ Collection<V> values = Sets.newHashSet();
+ items.values().forEach(v -> values.add(serializer.decode(v)));
+ return values;
+ }
+
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ Set<Entry<K, V>> entries = Sets.newHashSet();
+ items.entrySet().
+ forEach(e -> entries.add(Maps.immutableEntry(serializer.decode(e.getKey()),
+ serializer.decode(e.getValue()))));
+ return entries;
+ }
+
+ @Override
+ public boolean equals(Object map) {
+ //This is not threadsafe and on larger maps incurs a significant processing cost
+ if (!(map instanceof Map)) {
+ return false;
+ }
+ Map asMap = (Map) map;
+ if (this.size() != asMap.size()) {
+ return false;
+ }
+ for (Entry entry : this.entrySet()) {
+ Object key = entry.getKey();
+ if (!asMap.containsKey(key) || !asMap.get(key).equals(entry.getValue())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java
new file mode 100644
index 00000000..26118cf6
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/PersistentSet.java
@@ -0,0 +1,194 @@
+/*
+ * 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.persistence.impl;
+
+import com.google.common.collect.Iterators;
+import org.mapdb.DB;
+import org.mapdb.Hasher;
+import org.mapdb.Serializer;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * A set implementation that gets and receives all data from a serialized internal set.
+ */
+//TODO add locking for reads and writes
+public class PersistentSet<E> implements Set<E> {
+
+ private final org.onosproject.store.service.Serializer serializer;
+
+ private final org.mapdb.DB database;
+
+ private final Set<byte[]> items;
+
+ private final String name;
+
+ public PersistentSet(org.onosproject.store.service.Serializer serializer, DB database, String name) {
+ this.serializer = checkNotNull(serializer);
+ this.database = checkNotNull(database);
+ this.name = checkNotNull(name);
+
+ items = database
+ .createHashSet(name)
+ .serializer(Serializer.BYTE_ARRAY)
+ .hasher(Hasher.BYTE_ARRAY)
+ .makeOrGet();
+ }
+
+ public void readInto(Set<E> items) {
+ this.items.forEach(item -> items.add(serializer.decode(item)));
+ }
+
+ @Override
+ public int size() {
+ return items.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return items.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ checkNotNull(o, "The argument cannot be null");
+ return items.contains(serializer.encode(o));
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return Iterators.transform(items.iterator(), serializer::decode);
+ }
+
+ @Override
+ public Object[] toArray() {
+ Object[] retArray = new Object[items.size()];
+ int index = 0;
+ Iterator<byte[]> iterator = items.iterator();
+ while (iterator.hasNext()) {
+ retArray[index] = serializer.decode(iterator.next());
+ index++;
+ }
+ return retArray;
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a) {
+ checkNotNull(a, "The passed in array cannot be null.");
+ int index = 0;
+ Iterator<byte[]> iterator = items.iterator();
+ T[] retArray;
+ if (a.length >= items.size()) {
+ retArray = a;
+ } else {
+ retArray = (T[]) new Object[items.size()];
+ }
+ while (iterator.hasNext()) {
+ retArray[index++] = serializer.decode(iterator.next());
+ }
+ if (retArray.length > items.size()) {
+ retArray[index] = null;
+ }
+ return retArray;
+ }
+
+ @Override
+ public boolean add(E item) {
+ checkNotNull("Item to be added cannot be null.");
+ return items.add(serializer.encode(item));
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ checkNotNull(o, "Item to be removed cannot be null.");
+ return items.remove(serializer.encode(o));
+ }
+
+ @Override
+ public boolean containsAll(Collection<?> c) {
+ checkNotNull(c, "Collection cannot be internal.");
+ for (Object item : c) {
+ if (!items.contains(serializer.encode(item))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ checkNotNull(c, "The collection to be added cannot be null.");
+ boolean changed = false;
+ for (Object item : c) {
+ changed = items.add(serializer.encode(item)) || changed;
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ boolean changed = false;
+ for (byte[] item : items) {
+ E deserialized = serializer.decode(item);
+ if (!c.contains(deserialized)) {
+ changed = items.remove(item) || changed;
+ }
+ }
+ return changed;
+ }
+
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ boolean changed = false;
+ for (Object item : c) {
+ changed = items.remove(serializer.encode(item)) || changed;
+ }
+ return changed;
+ }
+
+ @Override
+ public void clear() {
+ items.clear();
+ }
+
+ @Override
+ public boolean equals(Object set) {
+ //This is not threadsafe and on larger sets incurs a significant processing cost
+ if (!(set instanceof Set)) {
+ return false;
+ }
+ Set asSet = (Set) set;
+ if (asSet.size() != this.size()) {
+ return false;
+ }
+ for (Object item : this) {
+ if (!asSet.contains(item)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+} \ No newline at end of file
diff --git a/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/impl/package-info.java
new file mode 100644
index 00000000..968a5046
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/java/org/onosproject/persistence/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.
+ */
+
+/**
+ * Implementations of core persistence classes.
+ */
+package org.onosproject.persistence.impl;
diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java
new file mode 100644
index 00000000..b059f18e
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentMapTest.java
@@ -0,0 +1,245 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Maps;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentMap;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Map.
+ */
+public class PersistentMapTest {
+
+ private Map<Integer, Integer> map = null;
+ private DB fakeDB = null;
+
+
+ /**
+ * Set up the database, create a map and a direct executor to handle it.
+ *
+ * @throws Exception if instantiation fails
+ */
+ @Before
+ public void setUp() throws Exception {
+ //Creates a db, a map within it and a basic integer serializer (async writing is off)
+ fakeDB = DBMaker
+ .newFileDB(Paths.get("../testDb").toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ map = new PersistentMap<Integer, Integer>(new Serializer() {
+ @Override
+ public <T> byte[] encode(T object) {
+ if (object == null) {
+ return null;
+ }
+ int num = (Integer) object;
+ byte[] result = new byte[4];
+
+ result[0] = (byte) (num >> 24);
+ result[1] = (byte) (num >> 16);
+ result[2] = (byte) (num >> 8);
+ result[3] = (byte) num;
+ return result;
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ int num = 0x00000000;
+
+ num = num | bytes[0] << 24;
+ num = num | bytes[1] << 16;
+ num = num | bytes[2] << 8;
+ num = num | bytes[3];
+
+ return (T) new java.lang.Integer(num);
+ }
+ }, fakeDB, "map");
+ }
+
+ /**
+ * Clears and deletes the map, closes the datbase and deletes the file.
+ *
+ * @throws Exception if shutdown fails
+ */
+ @After
+ public void tearDown() throws Exception {
+ map.clear();
+ fakeDB.delete("map:map");
+ fakeDB.commit();
+ fakeDB.close();
+ //This is key to prevent artifacts persisting between tests.
+ Paths.get("../testDB").toFile().delete();
+
+
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ //Checks removal and return values
+ fillMap(10);
+ assertEquals(10, map.size());
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The previous value was wrong.", new Integer(i), map.remove(i));
+ assertNull("The previous value was wrong.", map.remove(i));
+ //(i+1) compensates for base zero.
+ assertEquals("The size was wrong.", 10 - (i + 1), map.size());
+ }
+ }
+
+ @Test
+ public void testSize() throws Exception {
+ //Checks size values throughout addition and removal
+ for (int i = 0; i < 10; i++) {
+ map.put(i, i);
+ assertEquals("The map size is wrong.", i + 1, map.size());
+ }
+ for (int i = 0; i < 10; i++) {
+ map.remove(i);
+ assertEquals("The map size is wrong.", 9 - i, map.size());
+ }
+ }
+
+ @Test
+ public void testIsEmpty() throws Exception {
+ //Checks empty condition
+ //asserts that the map starts out empty
+ assertTrue("Map should be empty", map.isEmpty());
+ map.put(1, 1);
+ assertFalse("Map shouldn't be empty.", map.isEmpty());
+ map.remove(1);
+ assertTrue("Map should be empty", map.isEmpty());
+ }
+
+ @Test
+ public void testContains() throws Exception {
+ //Checks both containsKey and containsValue be aware the implementations vary widely (value does not use mapDB
+ //due to object '=='being an insufficient check)
+ for (int i = 0; i < 10; i++) {
+ assertFalse("Map should not contain the key", map.containsKey(i));
+ assertFalse("Map should not contain the value", map.containsValue(i));
+ map.put(i, i);
+ assertTrue("Map should contain the key", map.containsKey(i));
+ assertTrue("Map should contain the value", map.containsValue(i));
+ }
+ }
+
+ @Test
+ public void testGet() throws Exception {
+ //Tests value retrieval and nonexistent key return values
+ for (int i = 0; i < 10; i++) {
+ map.put(i, i);
+ for (int j = 0; j <= i; j++) {
+ assertEquals("The value was wrong.", new Integer(j), map.get(j));
+ }
+ }
+ assertNull("Null return value for nonexistent keys.", map.get(10));
+ }
+
+ @Test
+ public void testPutAll() throws Exception {
+ //Tests adding of an outside map
+ Map<Integer, Integer> testMap = Maps.newHashMap();
+ fillMap(10);
+ map.putAll(testMap);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The map should contain the current 'i' value.", map.containsKey(i));
+ assertTrue("The map should contain the current 'i' value.", map.containsValue(i));
+ }
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ //Tests clearing the map
+ assertTrue("Map was initialized incorrectly, should be empty.", map.isEmpty());
+ fillMap(10);
+ assertFalse("Map should contain entries now.", map.isEmpty());
+ map.clear();
+ assertTrue("Map should have been cleared of entries.", map.isEmpty());
+
+ }
+
+ @Test
+ public void testKeySet() throws Exception {
+ //Tests key set generation
+ fillMap(10);
+ Set<Integer> keys = map.keySet();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", keys.contains(i));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, keys.size());
+ }
+
+ @Test
+ public void testValues() throws Exception {
+ //Tests value set generation
+ fillMap(10);
+ Set<Integer> values = (Set<Integer>) map.values();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", values.contains(i));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, values.size());
+ }
+
+ @Test
+ public void testEntrySet() throws Exception {
+ //Test entry set generation (violates abstraction by knowing the type of the returned entries)
+ fillMap(10);
+ Set<Map.Entry<Integer, Integer>> entries = map.entrySet();
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The key set doesn't contain all keys 0-9", entries.contains(Maps.immutableEntry(i, i)));
+ }
+ assertEquals("The key set has an incorrect number of entries", 10, entries.size());
+ }
+
+ @Test public void testPut() throws Exception {
+ //Tests insertion behavior (particularly the returning of previous value)
+ fillMap(10);
+ for (int i = 0; i < 10; i++) {
+ assertEquals("Put should return the previous value", new Integer(i), map.put(i, i + 1));
+ }
+ assertNull(map.put(11, 11));
+ }
+
+ /**
+ * Populated the map with pairs of integers from (0, 0) up to (numEntries - 1, numEntries -1).
+ * @param numEntries number of entries to add
+ */
+ private void fillMap(int numEntries) {
+ for (int i = 0; i < numEntries; i++) {
+ map.put(i, i);
+ }
+ }
+}
diff --git a/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java
new file mode 100644
index 00000000..3107ab30
--- /dev/null
+++ b/framework/src/onos/core/store/persistence/src/main/test/test/PersistentSetTest.java
@@ -0,0 +1,274 @@
+/*
+ * 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 test;
+
+import com.google.common.collect.Sets;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mapdb.DB;
+import org.mapdb.DBMaker;
+import org.onosproject.persistence.impl.PersistentSet;
+import org.onosproject.store.service.Serializer;
+
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Test suite for Persistent Set.
+ */
+public class PersistentSetTest {
+
+ private Set<Integer> set = null;
+ private DB fakeDB = null;
+
+ @Before
+ public void setUp() throws Exception {
+ //Creates a db, a set within it and a basic integer serializer (async writing is off)
+ fakeDB = DBMaker
+ .newFileDB(Paths.get("../testDb").toFile())
+ .asyncWriteEnable()
+ .closeOnJvmShutdown()
+ .make();
+ set = new PersistentSet<Integer>(new Serializer() {
+ @Override
+ public <T> byte[] encode(T object) {
+ if (object == null) {
+ return null;
+ }
+ int num = (Integer) object;
+ byte[] result = new byte[4];
+
+ result[0] = (byte) (num >> 24);
+ result[1] = (byte) (num >> 16);
+ result[2] = (byte) (num >> 8);
+ result[3] = (byte) num;
+ return result;
+ }
+
+ @Override
+ public <T> T decode(byte[] bytes) {
+ if (bytes == null) {
+ return null;
+ }
+ int num = 0x00000000;
+
+ num = num | bytes[0] << 24;
+ num = num | bytes[1] << 16;
+ num = num | bytes[2] << 8;
+ num = num | bytes[3];
+
+ return (T) new java.lang.Integer(num);
+ }
+ }, fakeDB, "set");
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ set.clear();
+ fakeDB.delete("map:map");
+ fakeDB.commit();
+ fakeDB.close();
+ //This is key to prevent artifacts persisting between tests.
+ Paths.get("../testDB").toFile().delete();
+ }
+
+ @Test
+ public void testSize() throws Exception {
+ //Check correct sizing throughout population
+ for (int i = 0; i < 10; i++) {
+ set.add(i);
+ assertEquals("The set should have i + 1 entries.", i + 1, set.size());
+ }
+ }
+
+ @Test
+ public void testIsEmpty() throws Exception {
+ //test empty condition
+ assertTrue("The set should be initialized empty.", set.isEmpty());
+ fillSet(5, this.set);
+ assertFalse("The set should no longer be empty.", set.isEmpty());
+ set.clear();
+ assertTrue("The set should have been cleared.", set.isEmpty());
+ }
+
+ @Test
+ public void testContains() throws Exception {
+ //Test contains
+ assertFalse("The set should not contain anything", set.contains(1));
+ fillSet(10, this.set);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("The set should contain all values 0-9.", set.contains(i));
+ }
+ }
+
+ @Test
+ public void testIterator() throws Exception {
+ //Test iterator behavior (no order guarantees are made)
+ Set<Integer> validationSet = Sets.newHashSet();
+ fillSet(10, this.set);
+ fillSet(10, validationSet);
+ set.iterator().forEachRemaining(item -> assertTrue("Items were mismatched.", validationSet.remove(item)));
+ //All values should have been seen and removed
+ assertTrue("All entries in the validation set should have been removed.", validationSet.isEmpty());
+ }
+
+ @Test
+ public void testToArray() throws Exception {
+ //Test creation of a new array of the values
+ fillSet(10, set);
+ Object[] arr = set.toArray();
+ assertEquals("The array should be of length 10.", 10, arr.length);
+ for (int i = 0; i < 10; i++) {
+ assertTrue("All elements of the array should be in the set.", set.contains((Integer) arr[i]));
+ }
+ }
+
+ @Test
+ public void testToArray1() throws Exception {
+ //Test creation of a new array with the possibility of populating passed array if space allows
+ Integer[] originalArray = new Integer[9];
+ fillSet(9, set);
+ //Test the case where the array and set match in size
+ Object[] retArray = set.toArray(originalArray);
+ assertEquals("If the set can fit the array should be the one passed in.", originalArray, retArray);
+ //Test the case where the passe array is too small to fit the set
+ set.add(9);
+ assertNotEquals("A new set should be generated if the contents will not fit in the passed set",
+ set.toArray(originalArray), originalArray);
+ //Now test the case where there should be a null terminator
+ set.clear();
+ fillSet(5, set);
+ assertNull("The character one after last should be null if the array is larger than the set.",
+ set.toArray(originalArray)[5]);
+ }
+
+ @Test
+ public void testAdd() throws Exception {
+ //Test of add
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The size of the set is wrong.", i, set.size());
+ assertTrue("The first add of an element should be true.", set.add(i));
+ assertFalse("The second add of an element should be false.", set.add(i));
+ }
+ }
+
+ @Test
+ public void testRemove() throws Exception {
+ //Test removal
+ fillSet(10, set);
+ for (int i = 0; i < 10; i++) {
+ assertEquals("The size of the set is wrong.", 10 - i, set.size());
+ assertTrue("The first removal should be true.", set.remove(i));
+ assertFalse("The second removal should be false (item no longer contained).", set.remove(i));
+ }
+ assertTrue("All elements should have been removed.", set.isEmpty());
+ }
+
+ @Test
+ public void testContainsAll() throws Exception {
+ //Test contains with short circuiting
+ Set<Integer> integersToCheck = Sets.newHashSet();
+ fillSet(10, integersToCheck);
+ fillSet(10, set);
+ assertTrue("The sets should be identical so mutual subsets.", set.containsAll(integersToCheck));
+ set.remove(9);
+ assertFalse("The set should contain one fewer value.", set.containsAll(integersToCheck));
+ }
+
+ @Test
+ public void testAddAll() throws Exception {
+ //Test multi-adds with change checking
+ Set<Integer> integersToCheck = Sets.newHashSet();
+ fillSet(10, integersToCheck);
+ assertFalse("Set should be empty and so integers to check should not be a subset.",
+ set.containsAll(integersToCheck));
+ assertTrue("The set should have changed as a result of add all.", set.addAll(integersToCheck));
+ assertFalse("The set should not have changed as a result of add all a second time.",
+ set.addAll(integersToCheck));
+ assertTrue("The sets should now be equivalent.", set.containsAll(integersToCheck));
+ assertTrue("The sets should now be equivalent.", integersToCheck.containsAll(set));
+ }
+
+ @Test
+ public void testRetainAll() throws Exception {
+ //Test ability to generate the intersection set
+ Set<Integer> retainSet = Sets.newHashSet();
+ fillSet(10, set);
+ assertTrue("The set should have changed.", set.retainAll(retainSet));
+ assertTrue("The set should have been emptied.", set.isEmpty());
+ fillSet(10, set);
+ fillSet(10, retainSet);
+ Set<Integer> duplicateSet = new HashSet<>(set);
+ assertFalse("The set should not have changed.", set.retainAll(retainSet));
+ assertEquals("The set should be the same as the duplicate.", duplicateSet, set);
+ retainSet.remove(9);
+ assertTrue("The set should have changed.", set.retainAll(retainSet));
+ duplicateSet.remove(9);
+ assertEquals("The set should have had the nine element removed.", duplicateSet, set);
+ }
+
+ @Test
+ public void testRemoveAll() throws Exception {
+ //Test for mass removal and change checking
+ Set<Integer> removeSet = Sets.newHashSet();
+ fillSet(10, set);
+ Set<Integer> duplicateSet = Sets.newHashSet(set);
+ assertFalse("No elements should change.", set.removeAll(removeSet));
+ assertEquals("Set should not have diverged from the duplicate.", duplicateSet, set);
+ fillSet(5, removeSet);
+ assertTrue("Elements should have been removed.", set.removeAll(removeSet));
+ assertNotEquals("Duplicate set should no longer be equivalent.", duplicateSet, set);
+ assertEquals("Five elements should have been removed from set.", 5, set.size());
+ for (Integer item : removeSet) {
+ assertFalse("No element of remove set should remain.", set.contains(item));
+ }
+ }
+
+ @Test
+ public void testClear() throws Exception {
+ //Test set emptying
+ assertTrue("The set should be initialized empty.", set.isEmpty());
+ set.clear();
+ assertTrue("Clear should have no effect on an empty set.", set.isEmpty());
+ fillSet(10, set);
+ assertFalse("The set should no longer be empty.", set.isEmpty());
+ set.clear();
+ assertTrue("The set should be empty after clear.", set.isEmpty());
+ }
+
+ /**
+ * Populated the map with integers from (0) up to (numEntries - 1).
+ *
+ * @param numEntries number of entries to add
+ */
+ private void fillSet(int numEntries, Set<Integer> set) {
+ checkNotNull(set);
+ for (int i = 0; i < numEntries; i++) {
+ set.add(i);
+ }
+ }
+}
diff --git a/framework/src/onos/core/store/pom.xml b/framework/src/onos/core/store/pom.xml
index 2b246b83..219ae5d0 100644
--- a/framework/src/onos/core/store/pom.xml
+++ b/framework/src/onos/core/store/pom.xml
@@ -33,7 +33,8 @@
<modules>
<module>dist</module>
- <module>serializers</module>
+ <module>persistence</module>
+ <module>serializers</module>
</modules>
<dependencies>
diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java
new file mode 100644
index 00000000..6b12df96
--- /dev/null
+++ b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/ExtensionInstructionSerializer.java
@@ -0,0 +1,73 @@
+/*
+ * 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.store.serializers;
+
+import com.esotericsoftware.kryo.Kryo;
+import com.esotericsoftware.kryo.Serializer;
+import com.esotericsoftware.kryo.io.Input;
+import com.esotericsoftware.kryo.io.Output;
+import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.ExtensionResolver;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+import org.onosproject.net.flow.instructions.Instructions;
+
+/**
+ * Created by jono on 10/29/15.
+ */
+public class ExtensionInstructionSerializer extends
+ Serializer<Instructions.ExtensionInstructionWrapper> {
+
+ public ExtensionInstructionSerializer() {
+ super(false, true);
+ }
+
+ @Override
+ public void write(Kryo kryo, Output output, Instructions.ExtensionInstructionWrapper object) {
+ kryo.writeClassAndObject(output, object.extensionInstruction().type());
+ kryo.writeClassAndObject(output, object.deviceId());
+
+ kryo.writeClassAndObject(output, object.extensionInstruction().serialize());
+
+ }
+
+ @Override
+ public Instructions.ExtensionInstructionWrapper read(Kryo kryo, Input input,
+ Class<Instructions.ExtensionInstructionWrapper> type) {
+ ExtensionType exType = (ExtensionType) kryo.readClassAndObject(input);
+ DeviceId deviceId = (DeviceId) kryo.readClassAndObject(input);
+
+ DriverService driverService = DefaultServiceDirectory.getService(DriverService.class);
+ DriverHandler handler = new DefaultDriverHandler(
+ new DefaultDriverData(driverService.getDriver(deviceId), deviceId));
+
+ ExtensionResolver resolver = handler.behaviour(ExtensionResolver.class);
+
+ ExtensionInstruction instruction = resolver.getExtensionInstruction(exType);
+
+ byte[] bytes = (byte[]) kryo.readClassAndObject(input);
+
+ instruction.deserialize(bytes);
+
+ return Instructions.extension(instruction, deviceId);
+ }
+}
diff --git a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 5b5056cb..0312bafd 100644
--- a/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/framework/src/onos/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -70,6 +70,7 @@ import org.onosproject.net.OchPort;
import org.onosproject.net.OchSignal;
import org.onosproject.net.OchSignalType;
import org.onosproject.net.OduCltPort;
+import org.onosproject.net.OduSignalId;
import org.onosproject.net.OduSignalType;
import org.onosproject.net.OmsPort;
import org.onosproject.net.Port;
@@ -118,6 +119,8 @@ import org.onosproject.net.flow.criteria.MetadataCriterion;
import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.OchSignalCriterion;
import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.OduSignalIdCriterion;
+import org.onosproject.net.flow.criteria.OduSignalTypeCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.SctpPortCriterion;
import org.onosproject.net.flow.criteria.TcpPortCriterion;
@@ -125,8 +128,10 @@ import org.onosproject.net.flow.criteria.TunnelIdCriterion;
import org.onosproject.net.flow.criteria.UdpPortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+import org.onosproject.net.flow.instructions.ExtensionType;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L1ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
@@ -337,6 +342,8 @@ public final class KryoNamespaces {
IndexedLambdaCriterion.class,
OchSignalCriterion.class,
OchSignalTypeCriterion.class,
+ OduSignalIdCriterion.class,
+ OduSignalTypeCriterion.class,
Criterion.class,
Criterion.Type.class,
DefaultTrafficTreatment.class,
@@ -349,6 +356,9 @@ public final class KryoNamespaces {
L0ModificationInstruction.L0SubType.class,
L0ModificationInstruction.ModLambdaInstruction.class,
L0ModificationInstruction.ModOchSignalInstruction.class,
+ L1ModificationInstruction.class,
+ L1ModificationInstruction.L1SubType.class,
+ L1ModificationInstruction.ModOduSignalIdInstruction.class,
L2ModificationInstruction.class,
L2ModificationInstruction.L2SubType.class,
L2ModificationInstruction.ModEtherInstruction.class,
@@ -441,6 +451,8 @@ public final class KryoNamespaces {
.register(new HostLocationSerializer(), HostLocation.class)
.register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class)
.register(new AnnotationsSerializer(), DefaultAnnotations.class)
+ .register(new ExtensionInstructionSerializer(), Instructions.ExtensionInstructionWrapper.class)
+ .register(ExtensionType.class)
.register(Versioned.class)
.register(MapEvent.class)
.register(MapEvent.Type.class)
@@ -458,6 +470,7 @@ public final class KryoNamespaces {
.register(OduCltPort.SignalType.class)
.register(IndexedLambda.class)
.register(OchSignal.class)
+ .register(OduSignalId.class)
.register(OduCltPortDescription.class)
.register(OchPortDescription.class)
.register(OmsPortDescription.class)
diff --git a/framework/src/onos/docs/internal-bgpls b/framework/src/onos/docs/internal-bgpls
new file mode 100644
index 00000000..f264c7db
--- /dev/null
+++ b/framework/src/onos/docs/internal-bgpls
@@ -0,0 +1,2 @@
+org.onosproject.bgp.controller*
+org.onosproject.bgpio*
diff --git a/framework/src/onos/docs/internal-stores b/framework/src/onos/docs/internal-stores
index 13c00431..1f1f05ab 100644
--- a/framework/src/onos/docs/internal-stores
+++ b/framework/src/onos/docs/internal-stores
@@ -1 +1,2 @@
org.onosproject.store.*
+org.onosproject.persistence.impl
diff --git a/framework/src/onos/docs/internal.xml b/framework/src/onos/docs/internal.xml
index de9c1c64..602479eb 100644
--- a/framework/src/onos/docs/internal.xml
+++ b/framework/src/onos/docs/internal.xml
@@ -90,6 +90,10 @@
<packages>@internal-pcep</packages>
</group>
<group>
+ <title>BGP-LS Providers</title>
+ <packages>@internal-bgpls</packages>
+ </group>
+ <group>
<title>Other Providers</title>
<packages>@internal-providers</packages>
</group>
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java
new file mode 100644
index 00000000..082c5a6d
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionInterpreter.java
@@ -0,0 +1,84 @@
+/*
+ * 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.driver.extensions;
+
+import org.onlab.packet.Ip4Address;
+import org.onosproject.net.behaviour.ExtensionResolver;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+import org.onosproject.openflow.controller.ExtensionInterpreter;
+import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
+import org.projectfloodlight.openflow.types.IPv4Address;
+
+/**
+ * Interpreter for Nicira OpenFlow extensions.
+ */
+public class NiciraExtensionInterpreter extends AbstractHandlerBehaviour
+ implements ExtensionInterpreter, ExtensionResolver {
+
+ @Override
+ public boolean supported(ExtensionType extensionType) {
+ if (extensionType.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public OFAction mapInstruction(OFFactory factory, ExtensionInstruction extensionInstruction) {
+ ExtensionType type = extensionInstruction.type();
+ if (type.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST.type())) {
+ NiciraSetTunnelDst tunnelDst = (NiciraSetTunnelDst) extensionInstruction;
+ return factory.actions().setField(factory.oxms().tunnelIpv4Dst(
+ IPv4Address.of(tunnelDst.tunnelDst().toInt())));
+ }
+ return null;
+ }
+
+ @Override
+ public ExtensionInstruction mapAction(OFAction action) {
+ if (action.getType().equals(OFActionType.SET_FIELD)) {
+ OFActionSetField setFieldAction = (OFActionSetField) action;
+ OFOxm<?> oxm = setFieldAction.getField();
+ switch (oxm.getMatchField().id) {
+ case TUNNEL_IPV4_DST:
+ OFOxmTunnelIpv4Dst tunnelIpv4Dst = (OFOxmTunnelIpv4Dst) oxm;
+ return new NiciraSetTunnelDst(Ip4Address.valueOf(tunnelIpv4Dst.getValue().getInt()));
+ default:
+ throw new UnsupportedOperationException(
+ "Driver does not support extension type " + oxm.getMatchField().id);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ExtensionInstruction getExtensionInstruction(ExtensionType type) {
+ if (type.equals(ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST.type())) {
+ return new NiciraSetTunnelDst();
+ }
+ throw new UnsupportedOperationException(
+ "Driver does not support extension type " + type.toString());
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
new file mode 100644
index 00000000..16aa1b07
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
@@ -0,0 +1,106 @@
+/*
+ * 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.driver.extensions;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.Ip4Address;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.instructions.AbstractExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+import org.onosproject.store.serializers.Ip4AddressSerializer;
+
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Nicira set tunnel destination extension instruction.
+ */
+public class NiciraSetTunnelDst extends AbstractExtensionInstruction {
+
+ private Ip4Address tunnelDst;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(new Ip4AddressSerializer(), Ip4Address.class)
+ .register(byte[].class)
+ .build();
+
+ /**
+ * Creates a new set tunnel destination instruction.
+ */
+ NiciraSetTunnelDst() {
+ tunnelDst = null;
+ }
+
+ /**
+ * Creates a new set tunnel destination instruction with a particular IPv4
+ * address.
+ */
+ NiciraSetTunnelDst(Ip4Address tunnelDst) {
+ checkNotNull(tunnelDst);
+ this.tunnelDst = tunnelDst;
+ }
+
+ /**
+ * Gets the tunnel destination IPv4 address.
+ *
+ * @return tunnel destination IPv4 address
+ */
+ public Ip4Address tunnelDst() {
+ return tunnelDst;
+ }
+
+ @Override
+ public ExtensionType type() {
+ return ExtensionType.ExtensionTypes.NICIRA_SET_TUNNEL_DST.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ tunnelDst = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(tunnelDst);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(tunnelDst);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraSetTunnelDst) {
+ NiciraSetTunnelDst that = (NiciraSetTunnelDst) obj;
+ return Objects.equals(tunnelDst, that.tunnelDst);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("tunnelDst", tunnelDst)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java
new file mode 100644
index 00000000..d9d2460d
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+/**
+ * Processing of Nicira extensions.
+ */
+package org.onosproject.driver.extensions;
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
index 524163a1..77b48298 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java
@@ -22,11 +22,13 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.onlab.packet.IpAddress;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.BridgeConfig;
import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.BridgeName;
+import org.onosproject.net.behaviour.ControllerInfo;
import org.onosproject.net.behaviour.DefaultBridgeDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.PortDescription;
@@ -52,6 +54,13 @@ public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
}
@Override
+ public boolean addBridge(BridgeName bridgeName, String dpid, List<ControllerInfo> controllers) {
+ DriverHandler handler = handler();
+ OvsdbClientService clientService = getOvsdbClientService(handler);
+ return clientService.createBridge(bridgeName.name(), dpid, controllers);
+ }
+
+ @Override
public void deleteBridge(BridgeName bridgeName) {
DriverHandler handler = handler();
OvsdbClientService clientService = getOvsdbClientService(handler);
@@ -108,22 +117,22 @@ public class OvsdbBridgeConfig extends AbstractHandlerBehaviour
return ports.stream()
.map(x -> new DefaultPortDescription(
PortNumber.portNumber(x.portNumber().value()),
- true
- )
- )
+ true,
+ DefaultAnnotations.builder()
+ .set("portName", x.portName().value())
+ .build()))
.collect(Collectors.toSet());
}
- // OvsdbNodeId(IP:port) is used in the adaptor while DeviceId(ovsdb:IP:port)
+ // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
// is used in the core. So DeviceId need be changed to OvsdbNodeId.
private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
- int lastColon = deviceId.toString().lastIndexOf(":");
- int fistColon = deviceId.toString().indexOf(":");
- String ip = deviceId.toString().substring(fistColon + 1, lastColon);
- String port = deviceId.toString().substring(lastColon + 1);
- IpAddress ipAddress = IpAddress.valueOf(ip);
- long portL = Long.parseLong(port);
- return new OvsdbNodeId(ipAddress, portL);
+ String[] splits = deviceId.toString().split(":");
+ if (splits == null || splits.length < 1) {
+ return null;
+ }
+ IpAddress ipAddress = IpAddress.valueOf(splits[1]);
+ return new OvsdbNodeId(ipAddress, 0);
}
// Used for getting OvsdbClientService.
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java
index d32fb6be..a32553ad 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java
@@ -16,12 +16,14 @@
package org.onosproject.driver.ovsdb;
import java.util.Collection;
-
+import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.onlab.packet.IpAddress;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.BridgeName;
import org.onosproject.net.behaviour.DefaultTunnelDescription;
import org.onosproject.net.behaviour.IpTunnelEndPoint;
import org.onosproject.net.behaviour.TunnelConfig;
@@ -41,6 +43,8 @@ public class OvsdbTunnelConfig extends AbstractHandlerBehaviour
implements TunnelConfig {
private static final String DEFAULT_ADDRESS = "0.0.0.0";
+ private static final String OPTION_LOCAL_IP = "local_ip";
+ private static final String OPTION_REMOTE_IP = "remote_ip";
@Override
public void createTunnel(TunnelDescription tunnel) {
@@ -61,6 +65,22 @@ public class OvsdbTunnelConfig extends AbstractHandlerBehaviour
}
@Override
+ public boolean createTunnelInterface(BridgeName bridgeName, TunnelDescription tunnel) {
+ Map<String, String> options = ((DefaultAnnotations) tunnel.annotations()).asMap();
+ if (tunnel.src() != null) {
+ options.put(OPTION_LOCAL_IP, tunnel.src().toString());
+ }
+ if (tunnel.dst() != null) {
+ options.put(OPTION_REMOTE_IP, tunnel.dst().toString());
+ }
+
+ DriverHandler handler = handler();
+ OvsdbClientService ovsdbClient = getOvsdbNode(handler);
+ return ovsdbClient.createTunnel(bridgeName.name(), tunnel.tunnelName().toString(),
+ tunnel.type().toString().toLowerCase(), options);
+ }
+
+ @Override
public void removeTunnel(TunnelDescription tunnel) {
DriverHandler handler = handler();
OvsdbClientService ovsdbNode = getOvsdbNode(handler);
@@ -102,16 +122,15 @@ public class OvsdbTunnelConfig extends AbstractHandlerBehaviour
.collect(Collectors.toSet());
}
- // OvsdbNodeId(IP:port) is used in the adaptor while DeviceId(ovsdb:IP:port)
+ // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
// is used in the core. So DeviceId need be changed to OvsdbNodeId.
private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
- int lastColon = deviceId.toString().lastIndexOf(":");
- int fistColon = deviceId.toString().indexOf(":");
- String ip = deviceId.toString().substring(fistColon + 1, lastColon);
- String port = deviceId.toString().substring(lastColon + 1);
- IpAddress ipAddress = IpAddress.valueOf(ip);
- long portL = Long.parseLong(port);
- return new OvsdbNodeId(ipAddress, portL);
+ String[] splits = deviceId.toString().split(":");
+ if (splits == null || splits.length < 1) {
+ return null;
+ }
+ IpAddress ipAddress = IpAddress.valueOf(splits[1]);
+ return new OvsdbNodeId(ipAddress, 0);
}
private OvsdbClientService getOvsdbNode(DriverHandler handler) {
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
index c9ef451e..a830ed49 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA1Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
@@ -29,22 +29,23 @@ import org.slf4j.Logger;
/**
- * Driver for software switch emulation of the OFDPA 1.0 pipeline.
+ * Driver for software switch emulation of the OFDPA 2.0 pipeline.
* The software switch is the CPqD OF 1.3 switch.
*/
-public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline {
+public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
private final Logger log = getLogger(getClass());
@Override
protected void initializePipeline() {
processPortTable();
- //processVlanTable();
processTmacTable();
processIpTable();
- //processMcastTable();
processBridgingTable();
processAclTable();
+ // XXX implement table miss entries and default groups
+ //processVlanTable();
+ //processMPLSTable();
//processGroupTable();
}
@@ -169,6 +170,7 @@ public class CpqdOFDPA1Pipeline extends OFDPA1Pipeline {
}));
}
+ @Override
protected void processAclTable() {
//table miss entry - catch all to executed action-set
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA1Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
index f17309e1..b1a1256a 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA1Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
@@ -18,6 +18,7 @@ package org.onosproject.driver.pipeline;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
+import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -30,18 +31,26 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Data;
import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv4;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MPLS;
+import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
+import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.NextGroup;
import org.onosproject.net.behaviour.Pipeliner;
import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -81,6 +90,11 @@ import org.onosproject.net.group.GroupEvent;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupListener;
import org.onosproject.net.group.GroupService;
+import org.onosproject.net.packet.DefaultOutboundPacket;
+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.store.serializers.KryoNamespaces;
import org.slf4j.Logger;
@@ -90,19 +104,22 @@ import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalNotification;
/**
- * Driver for Broadcom's OF-DPA v1.0 TTP.
+ * Driver for Broadcom's OF-DPA v2.0 TTP.
*
*/
-public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeliner {
+public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeliner {
protected static final int PORT_TABLE = 0;
protected static final int VLAN_TABLE = 10;
protected static final int TMAC_TABLE = 20;
protected static final int UNICAST_ROUTING_TABLE = 30;
protected static final int MULTICAST_ROUTING_TABLE = 40;
+ protected static final int MPLS_TABLE_0 = 23;
+ protected static final int MPLS_TABLE_1 = 24;
protected static final int BRIDGING_TABLE = 50;
protected static final int ACL_TABLE = 60;
protected static final int MAC_LEARNING_TABLE = 254;
+ protected static final long OFPP_MAX = 0xffffff00L;
private static final int HIGHEST_PRIORITY = 0xffff;
private static final int DEFAULT_PRIORITY = 0x8000;
@@ -128,6 +145,8 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
*/
private static final int L2INTERFACEMASK = 0x0;
private static final int L3UNICASTMASK = 0x20000000;
+ //private static final int MPLSINTERFACEMASK = 0x90000000;
+ private static final int L3ECMPMASK = 0x70000000;
private final Logger log = getLogger(getClass());
private ServiceDirectory serviceDirectory;
@@ -137,7 +156,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
private FlowObjectiveStore flowObjectiveStore;
protected DeviceId deviceId;
protected ApplicationId driverId;
-
+ protected PacketService packetService;
+ protected DeviceService deviceService;
+ private InternalPacketProcessor processor = new InternalPacketProcessor();
private KryoNamespace appKryo = new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(GroupKey.class)
@@ -151,7 +172,9 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
private ScheduledExecutorService groupChecker =
Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner",
- "ofdpa1-%d"));
+ "ofdpa2-%d"));
+ private Set<IPCriterion> sentIpFilters = Collections.newSetFromMap(
+ new ConcurrentHashMap<IPCriterion, Boolean>());
@Override
public void init(DeviceId deviceId, PipelinerContext context) {
@@ -174,16 +197,29 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
flowRuleService = serviceDirectory.get(FlowRuleService.class);
groupService = serviceDirectory.get(GroupService.class);
flowObjectiveStore = context.store();
-
+ packetService = serviceDirectory.get(PacketService.class);
+ deviceService = serviceDirectory.get(DeviceService.class);
+ packetService.addProcessor(processor, PacketProcessor.director(2));
groupService.addListener(new InnerGroupListener());
driverId = coreService.registerApplication(
- "org.onosproject.driver.OFDPA1Pipeline");
+ "org.onosproject.driver.OFDPA2Pipeline");
+ // OF-DPA does not require initializing the pipeline as it puts default
+ // rules automatically in the hardware. However emulation of OFDPA in
+ // software switches does require table-miss-entries.
initializePipeline();
}
+ protected void initializePipeline() {
+
+ }
+
+ //////////////////////////////////////
+ // Flow Objectives
+ //////////////////////////////////////
+
@Override
public void filter(FilteringObjective filteringObjective) {
if (filteringObjective.type() == FilteringObjective.Type.PERMIT) {
@@ -191,6 +227,11 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
filteringObjective.op() == Objective.Operation.ADD,
filteringObjective.appId());
} else {
+ // Note that packets that don't match the PERMIT filter are
+ // automatically denied. The DENY filter is used to deny packets
+ // that are otherwise permitted by the PERMIT filter.
+ // Use ACL table flow rules here for DENY filtering objectives
+ log.debug("filter objective other than PERMIT currently not supported");
fail(filteringObjective, ObjectiveError.UNSUPPORTED);
}
}
@@ -257,25 +298,31 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
}
+ //////////////////////////////////////
+ // Flow handling
+ //////////////////////////////////////
+
/**
- * As per OFDPA 1.0 TTP, filtering of VLAN ids, MAC addresses (for routing)
+ * As per OFDPA 2.0 TTP, filtering of VLAN ids, MAC addresses (for routing)
* and IP addresses configured on switch ports happen in different tables.
* Note that IP filtering rules need to be added to the ACL table, as there
* is no mechanism to send to controller via IP table.
*
- * @param filt
- * @param install
- * @param applicationId
+ * @param filt the filtering objective
+ * @param install indicates whether to add or remove the objective
+ * @param applicationId the application that sent this objective
*/
private void processFilter(FilteringObjective filt,
boolean install, ApplicationId applicationId) {
// This driver only processes filtering criteria defined with switch
// ports as the key
- PortCriterion p = null; EthCriterion e = null; VlanIdCriterion v = null;
+ PortCriterion portCriterion = null;
+ EthCriterion ethCriterion = null;
+ VlanIdCriterion vidCriterion = null;
Collection<IPCriterion> ips = new ArrayList<IPCriterion>();
if (!filt.key().equals(Criteria.dummy()) &&
filt.key().type() == Criterion.Type.IN_PORT) {
- p = (PortCriterion) filt.key();
+ portCriterion = (PortCriterion) filt.key();
} else {
log.warn("No key defined in filtering objective from app: {}. Not"
+ "processing filtering objective", applicationId);
@@ -284,199 +331,238 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- for (Criterion c : filt.conditions()) {
- if (c.type() == Criterion.Type.ETH_DST) {
- e = (EthCriterion) c;
- } else if (c.type() == Criterion.Type.VLAN_VID) {
- v = (VlanIdCriterion) c;
- } else if (c.type() == Criterion.Type.IPV4_DST) {
- ips.add((IPCriterion) c);
+ for (Criterion criterion : filt.conditions()) {
+ if (criterion.type() == Criterion.Type.ETH_DST) {
+ ethCriterion = (EthCriterion) criterion;
+ } else if (criterion.type() == Criterion.Type.VLAN_VID) {
+ vidCriterion = (VlanIdCriterion) criterion;
+ } else if (criterion.type() == Criterion.Type.IPV4_DST) {
+ ips.add((IPCriterion) criterion);
} else {
- log.error("Unsupported filter {}", c);
+ log.error("Unsupported filter {}", criterion);
fail(filt, ObjectiveError.UNSUPPORTED);
return;
}
}
- log.debug("adding VLAN filtering rule in VLAN table: {}", e.mac());
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(p.port());
- selector.matchVlanId(v.vlanId());
- treatment.transition(TMAC_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
- ops = ops.add(rule);
+ VlanId assignedVlan = null;
+ if (vidCriterion != null && vidCriterion.vlanId() == VlanId.NONE) {
+ // untagged packets are assigned vlans in OF-DPA
+ if (filt.meta() == null) {
+ log.error("Missing metadata in filtering objective required "
+ + "for vlan assignment in dev {}", deviceId);
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+ for (Instruction i : filt.meta().allInstructions()) {
+ if (i instanceof ModVlanIdInstruction) {
+ assignedVlan = ((ModVlanIdInstruction) i).vlanId();
+ }
+ }
+ if (assignedVlan == null) {
+ log.error("Driver requires an assigned vlan-id to tag incoming "
+ + "untagged packets. Not processing vlan filters on "
+ + "device {}", deviceId);
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+ }
- log.debug("adding MAC filtering rules in TMAC table: {}", e.mac());
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(p.port());
- selector.matchVlanId(v.vlanId());
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchEthDst(e.mac());
- treatment.transition(UNICAST_ROUTING_TABLE);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- ops = ops.add(rule);
+ if (ethCriterion == null) {
+ log.debug("filtering objective missing dstMac, cannot program TMAC table");
+ } else {
+ for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion,
+ vidCriterion, assignedVlan,
+ applicationId)) {
+ log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}",
+ tmacRule, deviceId);
+ ops = install ? ops.add(tmacRule) : ops.remove(tmacRule);
+ }
+ }
+
+ if (ethCriterion == null || vidCriterion == null) {
+ log.debug("filtering objective missing dstMac or vlan, cannot program"
+ + "Vlan Table");
+ } else {
+ for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion,
+ assignedVlan,
+ applicationId)) {
+ log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}",
+ vlanRule, deviceId);
+ ops = install ? ops.add(vlanRule) : ops.remove(vlanRule);
+ }
+ }
- log.debug("adding IP filtering rules in ACL table");
for (IPCriterion ipaddr : ips) {
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ipaddr.ip());
- treatment.setOutput(PortNumber.CONTROLLER);
- rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(HIGHEST_PRIORITY)
- .fromApp(applicationId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- ops = ops.add(rule);
+ // since we ignore port information for IP rules, and the same (gateway) IP
+ // can be configured on multiple ports, we make sure that we send
+ // only a single rule to the switch.
+ if (!sentIpFilters.contains(ipaddr)) {
+ sentIpFilters.add(ipaddr);
+ log.debug("adding IP filtering rules in ACL table {} for dev: {}",
+ ipaddr, deviceId);
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchIPDst(ipaddr.ip());
+ treatment.setOutput(PortNumber.CONTROLLER);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(HIGHEST_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(ACL_TABLE).build();
+ ops = install ? ops.add(rule) : ops.remove(rule);
+ }
}
- ops = install ? ops.add(rule) : ops.remove(rule);
// apply filtering flow rules
flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
- log.info("Applied filtering rules");
+ log.info("Applied {} filtering rules in device {}",
+ ops.stages().get(0).size(), deviceId);
pass(filt);
}
@Override
public void onError(FlowRuleOperations ops) {
- log.info("Failed to apply filtering rules");
+ log.info("Failed to apply all filtering rules in dev {}", deviceId);
fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}));
}
-
/**
- * As per the OFDPA 1.0 TTP, packets are sent out of ports by using
- * a chain of groups, namely an L3 Unicast Group that points to an L2 Interface
- * Group which in turns points to an output port. The Next Objective passed
- * in by the application has to be broken up into a group chain
- * to satisfy this TTP.
+ * Allows untagged packets into pipeline by assigning a vlan id.
+ * Vlan assignment is done by the application.
+ * Allows tagged packets into pipeline as per configured port-vlan info.
*
- * @param nextObj the nextObjective of type SIMPLE
+ * @param portCriterion port on device for which this filter is programmed
+ * @param vidCriterion vlan assigned to port, or NONE for untagged
+ * @param assignedVlan assigned vlan-id for untagged packets
+ * @param applicationId for application programming this filter
+ * @return list of FlowRule for port-vlan filters
*/
- private void processSimpleNextObjective(NextObjective nextObj) {
- // break up simple next objective to GroupChain objects
- TrafficTreatment treatment = nextObj.next().iterator().next();
- // for the l2interface group, get vlan and port info
- // for the l3unicast group, get the src/dst mac and vlan info
- TrafficTreatment.Builder l3utt = DefaultTrafficTreatment.builder();
- TrafficTreatment.Builder l2itt = DefaultTrafficTreatment.builder();
- VlanId vlanid = null;
- long portNum = 0;
- for (Instruction ins : treatment.allInstructions()) {
- if (ins.type() == Instruction.Type.L2MODIFICATION) {
- L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
- switch (l2ins.subtype()) {
- case ETH_DST:
- l3utt.setEthDst(((ModEtherInstruction) l2ins).mac());
- break;
- case ETH_SRC:
- l3utt.setEthSrc(((ModEtherInstruction) l2ins).mac());
- break;
- case VLAN_ID:
- vlanid = ((ModVlanIdInstruction) l2ins).vlanId();
- l3utt.setVlanId(vlanid);
- break;
- case DEC_MPLS_TTL:
- case MPLS_LABEL:
- case MPLS_POP:
- case MPLS_PUSH:
- case VLAN_PCP:
- case VLAN_POP:
- case VLAN_PUSH:
- default:
- break;
+ protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
+ VlanIdCriterion vidCriterion,
+ VlanId assignedVlan,
+ ApplicationId applicationId) {
+ List<FlowRule> rules = new ArrayList<FlowRule>();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchVlanId(vidCriterion.vlanId());
+ if (vidCriterion.vlanId() == VlanId.NONE) {
+ // untagged packets are assigned vlans
+ treatment.pushVlan().setVlanId(assignedVlan);
+ // XXX ofdpa may require an additional vlan match on the assigned vlan
+ // and it may not require the push.
+ }
+ treatment.transition(TMAC_TABLE);
+
+ // ofdpa cannot match on ALL portnumber, so we need to use separate
+ // rules for each port.
+ List<PortNumber> portnums = new ArrayList<PortNumber>();
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
}
- } else if (ins.type() == Instruction.Type.OUTPUT) {
- portNum = ((OutputInstruction) ins).port().toLong();
- l2itt.add(ins);
- } else {
- log.warn("Driver does not handle this type of TrafficTreatment"
- + " instruction in nextObjectives: {}", ins.type());
}
+ } else {
+ portnums.add(portCriterion.port());
}
-
- // assemble information for ofdpa l2interface group
- int l2gk = nextObj.id() | GROUP1MASK;
- final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
- Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum;
-
- // assemble information for ofdpa l3unicast group
- int l3gk = nextObj.id() | GROUP0MASK;
- final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk));
- Integer l3groupId = L3UNICASTMASK | (int) portNum;
- l3utt.group(new DefaultGroupId(l2groupId));
- GroupChainElem gce = new GroupChainElem(l3groupkey, l3groupId,
- l3utt.build(), nextObj.appId());
-
- // create object for local and distributed storage
- List<GroupKey> gkeys = new ArrayList<GroupKey>();
- gkeys.add(l3groupkey); // group0 in chain
- gkeys.add(l2groupkey); // group1 in chain
- OfdpaGroupChain ofdpaGrp = new OfdpaGroupChain(gkeys, nextObj);
-
- // store l2groupkey with the groupChainElem for the l3group that depends on it
- pendingGroups.put(l2groupkey, gce);
-
- // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it
- pendingNextObjectives.put(l3groupkey, ofdpaGrp);
-
- // create group description for the ofdpa l2interfacegroup and send to groupservice
- GroupBucket bucket =
- DefaultGroupBucket.createIndirectGroupBucket(l2itt.build());
- GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket)),
- l2groupkey,
- l2groupId,
- nextObj.appId());
- groupService.addGroup(groupDescription);
+ for (PortNumber pnum : portnums) {
+ selector.matchInPort(pnum);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(VLAN_TABLE).build();
+ rules.add(rule);
+ }
+ return rules;
}
/**
- * Processes next element of a group chain. Assumption is that if this
- * group points to another group, the latter has already been created
- * and this driver has received notification for it. A second assumption is
- * that if there is another group waiting for this group then the appropriate
- * stores already have the information to act upon the notification for the
- * creating of this group.
+ * Allows routed packets with correct destination MAC to be directed
+ * to unicast-IP routing table or MPLS forwarding table.
+ * XXX need to add rule for multicast routing.
*
- * @param gce the group chain element to be processed next
+ * @param portCriterion port on device for which this filter is programmed
+ * @param ethCriterion dstMac of device for which is filter is programmed
+ * @param vidCriterion vlan assigned to port, or NONE for untagged
+ * @param assignedVlan assigned vlan-id for untagged packets
+ * @param applicationId for application programming this filter
+ * @return list of FlowRule for port-vlan filters
+
*/
- private void processGroupChain(GroupChainElem gce) {
- GroupBucket bucket = DefaultGroupBucket
- .createIndirectGroupBucket(gce.getBucketActions());
- GroupDescription groupDesc = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket)),
- gce.getGkey(),
- gce.getGivenGroupId(),
- gce.getAppId());
- groupService.addGroup(groupDesc);
+ protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion,
+ EthCriterion ethCriterion,
+ VlanIdCriterion vidCriterion,
+ VlanId assignedVlan,
+ ApplicationId applicationId) {
+ //handling untagged packets via assigned VLAN
+ if (vidCriterion.vlanId() == VlanId.NONE) {
+ vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
+ }
+ // ofdpa cannot match on ALL portnumber, so we need to use separate
+ // rules for each port.
+ List<PortNumber> portnums = new ArrayList<PortNumber>();
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
+ }
+ }
+ } else {
+ portnums.add(portCriterion.port());
+ }
+
+ List<FlowRule> rules = new ArrayList<FlowRule>();
+ for (PortNumber pnum : portnums) {
+ // for unicast IP packets
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(pnum);
+ selector.matchVlanId(vidCriterion.vlanId());
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchEthDst(ethCriterion.mac());
+ treatment.transition(UNICAST_ROUTING_TABLE);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ rules.add(rule);
+ //for MPLS packets
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(pnum);
+ selector.matchVlanId(vidCriterion.vlanId());
+ selector.matchEthType(Ethernet.MPLS_UNICAST);
+ selector.matchEthDst(ethCriterion.mac());
+ treatment.transition(MPLS_TABLE_0);
+ rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ rules.add(rule);
+ }
+ return rules;
}
private Collection<FlowRule> processForward(ForwardingObjective fwd) {
@@ -493,7 +579,7 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
/**
- * In the OF-DPA 1.0 pipeline, versatile forwarding objectives go to the
+ * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the
* ACL table.
* @param fwd the forwarding objective of type 'versatile'
* @return a collection of flow rules to be sent to the switch. An empty
@@ -508,37 +594,46 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
(EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if (ethType == null) {
log.error("Versatile forwarding objective must include ethType");
- fail(fwd, ObjectiveError.UNKNOWN);
+ fail(fwd, ObjectiveError.BADPARAMS);
return Collections.emptySet();
}
- if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) {
- log.warn("Installing ARP rule to table 60");
-
- // currently need to punt from ACL table should use:
- // OF apply-actions-instruction
- // To use OF write-actions-instruction
- /*TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
- fwd.treatment().allInstructions().stream()
- .forEach(ti -> tb.deferred().add(ti));*/
-
- FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
- .fromApp(fwd.appId())
- .withPriority(fwd.priority())
- .forDevice(deviceId)
- .withSelector(fwd.selector())
- .withTreatment(fwd.treatment())
- .makePermanent()
- .forTable(ACL_TABLE);
-
- return Collections.singletonList(ruleBuilder.build());
+ if (fwd.nextId() == null && fwd.treatment() == null) {
+ log.error("Forwarding objective {} from {} must contain "
+ + "nextId or Treatment", fwd.selector(), fwd.appId());
+ return Collections.emptySet();
+ }
+ // XXX driver does not currently do type checking as per Tables 65-67 in
+ // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller.
+ if (fwd.treatment() != null &&
+ fwd.treatment().allInstructions().size() == 1 &&
+ fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
+ OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
+ if (o.port() == PortNumber.CONTROLLER) {
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .fromApp(fwd.appId())
+ .withPriority(fwd.priority())
+ .forDevice(deviceId)
+ .withSelector(fwd.selector())
+ .withTreatment(fwd.treatment())
+ .makePermanent()
+ .forTable(ACL_TABLE);
+ return Collections.singletonList(ruleBuilder.build());
+ } else {
+ log.warn("Only allowed treatments in versatile forwarding "
+ + "objectives are punts to the controller");
+ return Collections.emptySet();
+ }
}
- // XXX not handling other versatile flows yet
+ if (fwd.nextId() != null) {
+ // XXX overide case
+ log.warn("versatile objective --> next Id not yet implemeted");
+ }
return Collections.emptySet();
}
/**
- * In the OF-DPA 1.0 pipeline, specific forwarding refers to the IP table
+ * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table
* (unicast or multicast) or the L2 table (mac + vlan).
*
* @param fwd the forwarding objective of type 'specific'
@@ -602,151 +697,126 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
}
-
private void fail(Objective obj, ObjectiveError error) {
if (obj.context().isPresent()) {
obj.context().get().onError(obj, error);
}
}
+ //////////////////////////////////////
+ // Group handling
+ //////////////////////////////////////
- protected void initializePipeline() {
- processPortTable();
- processVlanTable();
- processTmacTable();
- processIpTable();
- //processMcastTable();
- //processBridgingTable();
- //processAclTable();
- //processGroupTable();
- //processMplsTable();
- }
-
- protected void processMplsTable() {
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchEthType(Ethernet.MPLS_UNICAST);
- selector.matchMplsLabel(MplsLabel.mplsLabel(0xff));
- selector.matchMplsBos(true);
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.popMpls(Ethernet.TYPE_IPV4);
- treatment.transition(ACL_TABLE);
- FlowRule test = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build()).withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY).fromApp(driverId).makePermanent()
- .forTable(25).build();
- ops = ops.add(test);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized mpls table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize mpls table");
+ /**
+ * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
+ * a chain of groups, namely an L3 Unicast Group that points to an L2 Interface
+ * Group which in turns points to an output port. The Next Objective passed
+ * in by the application has to be broken up into a group chain
+ * to satisfy this TTP.
+ *
+ * @param nextObj the nextObjective of type SIMPLE
+ */
+ private void processSimpleNextObjective(NextObjective nextObj) {
+ // break up simple next objective to GroupChain objects
+ TrafficTreatment treatment = nextObj.next().iterator().next();
+ // for the l2interface group, get vlan and port info
+ // for the l3unicast group, get the src/dst mac and vlan info
+ TrafficTreatment.Builder l3utt = DefaultTrafficTreatment.builder();
+ TrafficTreatment.Builder l2itt = DefaultTrafficTreatment.builder();
+ VlanId vlanid = null;
+ long portNum = 0;
+ for (Instruction ins : treatment.allInstructions()) {
+ if (ins.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
+ switch (l2ins.subtype()) {
+ case ETH_DST:
+ l3utt.setEthDst(((ModEtherInstruction) l2ins).mac());
+ break;
+ case ETH_SRC:
+ l3utt.setEthSrc(((ModEtherInstruction) l2ins).mac());
+ break;
+ case VLAN_ID:
+ vlanid = ((ModVlanIdInstruction) l2ins).vlanId();
+ l3utt.setVlanId(vlanid);
+ break;
+ case DEC_MPLS_TTL:
+ case MPLS_LABEL:
+ case MPLS_POP:
+ case MPLS_PUSH:
+ case VLAN_PCP:
+ case VLAN_POP:
+ case VLAN_PUSH:
+ default:
+ break;
+ }
+ } else if (ins.type() == Instruction.Type.OUTPUT) {
+ portNum = ((OutputInstruction) ins).port().toLong();
+ l2itt.add(ins);
+ } else {
+ log.warn("Driver does not handle this type of TrafficTreatment"
+ + " instruction in nextObjectives: {}", ins.type());
}
- }));
+ }
- }
+ // assemble information for ofdpa l2interface group
+ int l2gk = nextObj.id() | GROUP1MASK;
+ final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
+ Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum;
- protected void processPortTable() {
- //XXX is table miss entry enough or do we need to do the maskable in-port 0?
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchInPort(PortNumber.portNumber(0)); // should be maskable?
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.transition(VLAN_TABLE);
- FlowRule tmisse = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(PORT_TABLE).build();
- /*ops = ops.add(tmisse);
+ // assemble information for ofdpa l3unicast group
+ int l3gk = nextObj.id() | GROUP0MASK;
+ final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk));
+ Integer l3groupId = L3UNICASTMASK | (int) portNum;
+ l3utt.group(new DefaultGroupId(l2groupId));
+ GroupChainElem gce = new GroupChainElem(l3groupkey, l3groupId,
+ l3utt.build(), nextObj.appId());
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized port table");
- }
+ // create object for local and distributed storage
+ List<GroupKey> gkeys = new ArrayList<GroupKey>();
+ gkeys.add(l3groupkey); // group0 in chain
+ gkeys.add(l2groupkey); // group1 in chain
+ OfdpaGroupChain ofdpaGrp = new OfdpaGroupChain(gkeys, nextObj);
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize port table");
- }
- }));*/
+ // store l2groupkey with the groupChainElem for the l3group that depends on it
+ pendingGroups.put(l2groupkey, gce);
- }
+ // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it
+ pendingNextObjectives.put(l3groupkey, ofdpaGrp);
- private void processVlanTable() {
- // Table miss entry is not required as ofdpa default is to drop
- // In OF terms, the absence of a t.m.e. also implies drop
+ // create group description for the ofdpa l2interfacegroup and send to groupservice
+ GroupBucket bucket =
+ DefaultGroupBucket.createIndirectGroupBucket(l2itt.build());
+ GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket)),
+ l2groupkey,
+ l2groupId,
+ nextObj.appId());
+ groupService.addGroup(groupDescription);
}
-
- protected void processTmacTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.transition(BRIDGING_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- /*ops = ops.add(rule); // XXX bug in ofdpa
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized tmac table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize tmac table");
- }
- }));*/
+ /**
+ * Processes next element of a group chain. Assumption is that if this
+ * group points to another group, the latter has already been created
+ * and this driver has received notification for it. A second assumption is
+ * that if there is another group waiting for this group then the appropriate
+ * stores already have the information to act upon the notification for the
+ * creating of this group.
+ *
+ * @param gce the group chain element to be processed next
+ */
+ private void processGroupChain(GroupChainElem gce) {
+ GroupBucket bucket = DefaultGroupBucket
+ .createIndirectGroupBucket(gce.getBucketActions());
+ GroupDescription groupDesc = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket)),
+ gce.getGkey(),
+ gce.getGivenGroupId(),
+ gce.getAppId());
+ groupService.addGroup(groupDesc);
}
- protected void processIpTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector = DefaultTrafficSelector.builder();
- treatment = DefaultTrafficTreatment.builder();
- treatment.transition(ACL_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(UNICAST_ROUTING_TABLE).build();
- /*ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized IP table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize unicast IP table");
- }
- }));*/
- }
private class GroupChecker implements Runnable {
@Override
@@ -884,4 +954,416 @@ public class OFDPA1Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
}
+
+ //////////////////////////////////////
+ // Test code to be used for future
+ // static-flow-pusher app
+ //////////////////////////////////////
+
+ public void processStaticFlows() {
+ //processPortTable();
+ processGroupTable();
+ processVlanTable();
+ processTmacTable();
+ processIpTable();
+ //processMcastTable();
+ //processBridgingTable();
+ processAclTable();
+ sendPackets();
+ processMplsTable();
+ }
+
+ protected void processGroupTable() {
+ TrafficTreatment.Builder act = DefaultTrafficTreatment.builder();
+
+ act.popVlan(); // to send out untagged packets
+ act.setOutput(PortNumber.portNumber(24));
+ GroupBucket bucket =
+ DefaultGroupBucket.createIndirectGroupBucket(act.build());
+ final GroupKey groupkey = new DefaultGroupKey(appKryo.serialize(500));
+ Integer groupId = 0x00c80018; //l2 interface, vlan 200, port 24
+ GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket)),
+ groupkey,
+ groupId,
+ driverId);
+ groupService.addGroup(groupDescription);
+
+ TrafficTreatment.Builder act2 = DefaultTrafficTreatment.builder();
+ act2.setOutput(PortNumber.portNumber(40));
+ GroupBucket bucket2 = DefaultGroupBucket.createIndirectGroupBucket(act2.build());
+ final GroupKey groupkey2 = new DefaultGroupKey(appKryo.serialize(502));
+ Integer groupId2 = 0x00c50028; //l2 interface, vlan 197, port 40
+ GroupDescription groupDescription2 = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket2)),
+ groupkey2,
+ groupId2,
+ driverId);
+ groupService.addGroup(groupDescription2);
+
+ while (groupService.getGroup(deviceId, groupkey2) == null) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ //Now for L3 Unicast group
+ TrafficTreatment.Builder act3 = DefaultTrafficTreatment.builder();
+ act3.setEthDst(MacAddress.valueOf(0x2020));
+ act3.setEthSrc(MacAddress.valueOf(0x1010));
+ act3.setVlanId(VlanId.vlanId((short) 200));
+ act3.group(new DefaultGroupId(0x00c80018)); // point to L2 interface
+ // MPLS interface group - does not work for popping single label
+ //Integer secGroupId = MPLSINTERFACEMASK | 38; // 0x90000026
+ Integer groupId3 = L3UNICASTMASK | 1; // 0x20000001
+ GroupBucket bucket3 =
+ DefaultGroupBucket.createIndirectGroupBucket(act3.build());
+ final GroupKey groupkey3 = new DefaultGroupKey(appKryo.serialize(503));
+ GroupDescription groupDescription3 = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket3)),
+ groupkey3,
+ groupId3,
+ driverId);
+ groupService.addGroup(groupDescription3);
+
+ //Another L3 Unicast group
+ TrafficTreatment.Builder act4 = DefaultTrafficTreatment.builder();
+ act4.setEthDst(MacAddress.valueOf(0x3030));
+ act4.setEthSrc(MacAddress.valueOf(0x1010));
+ act4.setVlanId(VlanId.vlanId((short) 197));
+ act4.group(new DefaultGroupId(0x00c50028)); // point to L2 interface
+ Integer groupId4 = L3UNICASTMASK | 2; // 0x20000002
+ GroupBucket bucket4 =
+ DefaultGroupBucket.createIndirectGroupBucket(act4.build());
+ final GroupKey groupkey4 = new DefaultGroupKey(appKryo.serialize(504));
+ GroupDescription groupDescription4 = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(bucket4)),
+ groupkey4,
+ groupId4,
+ driverId);
+ groupService.addGroup(groupDescription4);
+
+ while (groupService.getGroup(deviceId, groupkey4) == null) {
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ // L3 ecmp group
+ TrafficTreatment.Builder act5 = DefaultTrafficTreatment.builder();
+ act5.group(new DefaultGroupId(0x20000001));
+ TrafficTreatment.Builder act6 = DefaultTrafficTreatment.builder();
+ act6.group(new DefaultGroupId(0x20000002));
+ GroupBucket buckete1 =
+ DefaultGroupBucket.createSelectGroupBucket(act5.build());
+ GroupBucket buckete2 =
+ DefaultGroupBucket.createSelectGroupBucket(act6.build());
+ List<GroupBucket> bktlist = new ArrayList<GroupBucket>();
+ bktlist.add(buckete1);
+ bktlist.add(buckete2);
+ final GroupKey groupkey5 = new DefaultGroupKey(appKryo.serialize(505));
+ Integer groupId5 = L3ECMPMASK | 5; // 0x70000005
+ GroupDescription groupDescription5 = new DefaultGroupDescription(deviceId,
+ GroupDescription.Type.SELECT,
+ new GroupBuckets(bktlist),
+ groupkey5,
+ groupId5,
+ driverId);
+ groupService.addGroup(groupDescription5);
+
+
+ }
+
+ @SuppressWarnings("deprecation")
+ protected void processMplsTable() {
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.matchEthType(Ethernet.MPLS_UNICAST);
+ selector.matchMplsLabel(MplsLabel.mplsLabel(0xff)); //255
+ selector.matchMplsBos(true);
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.decMplsTtl(); // nw_ttl does not work
+ treatment.copyTtlIn();
+ treatment.popMpls(Ethernet.TYPE_IPV4);
+ treatment.deferred().group(new DefaultGroupId(0x20000001)); // point to L3 Unicast
+ //treatment.deferred().group(new DefaultGroupId(0x70000005)); // point to L3 ECMP
+ treatment.transition(ACL_TABLE);
+ FlowRule test = DefaultFlowRule.builder().forDevice(deviceId)
+ .withSelector(selector.build()).withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY).fromApp(driverId).makePermanent()
+ .forTable(24).build();
+ ops = ops.add(test);
+
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized mpls table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize mpls table");
+ }
+ }));
+
+ }
+
+ protected void processPortTable() {
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ selector.matchInPort(PortNumber.portNumber(0)); // should be maskable?
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ treatment.transition(VLAN_TABLE);
+ FlowRule tmisse = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(LOWEST_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(PORT_TABLE).build();
+ ops = ops.add(tmisse);
+
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized port table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize port table");
+ }
+ }));
+
+ }
+
+ private void processVlanTable() {
+ // Table miss entry is not required as ofdpa default is to drop
+ // In OF terms, the absence of a t.m.e. also implies drop
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(PortNumber.portNumber(12));
+ selector.matchVlanId(VlanId.vlanId((short) 100));
+ treatment.transition(TMAC_TABLE);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(VLAN_TABLE).build();
+ ops = ops.add(rule);
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized vlan table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize vlan table");
+ }
+ }));
+ }
+
+ protected void processTmacTable() {
+ //table miss entry
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(PortNumber.portNumber(12));
+ selector.matchVlanId(VlanId.vlanId((short) 100));
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
+ treatment.transition(UNICAST_ROUTING_TABLE);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ ops = ops.add(rule);
+
+ selector.matchEthType(Ethernet.MPLS_UNICAST);
+ treatment.transition(MPLS_TABLE_0);
+ FlowRule rulempls = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ ops = ops.add(rulempls);
+
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized tmac table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize tmac table");
+ }
+ }));
+ }
+
+ protected void processIpTable() {
+ //table miss entry
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchIPDst(IpPrefix.valueOf("2.0.0.0/16"));
+ treatment.deferred().group(new DefaultGroupId(0x20000001));
+ treatment.transition(ACL_TABLE);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(30000)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(UNICAST_ROUTING_TABLE).build();
+ ops = ops.add(rule);
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized IP table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize unicast IP table");
+ }
+ }));
+ }
+
+ protected void processAclTable() {
+ //table miss entry
+ FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
+ treatment.deferred().group(new DefaultGroupId(0x20000001));
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(60000)
+ .fromApp(driverId)
+ .makePermanent()
+ .forTable(ACL_TABLE).build();
+ ops = ops.add(rule);
+ flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.info("Initialized Acl table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.info("Failed to initialize Acl table");
+ }
+ }));
+ }
+
+ private void sendPackets() {
+ Ethernet eth = new Ethernet();
+ eth.setDestinationMACAddress("00:00:00:00:00:02");
+ eth.setSourceMACAddress("00:00:00:11:22:33");
+ eth.setVlanID((short) 100);
+ eth.setEtherType(Ethernet.MPLS_UNICAST);
+ MPLS mplsPkt = new MPLS();
+ mplsPkt.setLabel(255);
+ mplsPkt.setTtl((byte) 5);
+
+ IPv4 ipv4 = new IPv4();
+
+ ipv4.setDestinationAddress("4.0.5.6");
+ ipv4.setSourceAddress("1.0.2.3");
+ ipv4.setTtl((byte) 64);
+ ipv4.setChecksum((short) 0);
+
+ UDP udp = new UDP();
+ udp.setDestinationPort(666);
+ udp.setSourcePort(333);
+ udp.setPayload(new Data(new byte[]{(byte) 1, (byte) 2}));
+ udp.setChecksum((short) 0);
+
+ ipv4.setPayload(udp);
+ mplsPkt.setPayload(ipv4);
+ eth.setPayload(mplsPkt);
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(24))
+ .build();
+ OutboundPacket packet = new DefaultOutboundPacket(deviceId,
+ treatment,
+ ByteBuffer.wrap(eth.serialize()));
+
+
+ Ethernet eth2 = new Ethernet();
+ eth2.setDestinationMACAddress("00:00:00:00:00:02");
+ eth2.setSourceMACAddress("00:00:00:11:22:33");
+ eth2.setVlanID((short) 100);
+ eth2.setEtherType(Ethernet.TYPE_IPV4);
+
+ IPv4 ipv42 = new IPv4();
+ ipv42.setDestinationAddress("2.0.0.2");
+ ipv42.setSourceAddress("1.0.9.9");
+ ipv42.setTtl((byte) 64);
+ ipv42.setChecksum((short) 0);
+
+ UDP udp2 = new UDP();
+ udp2.setDestinationPort(999);
+ udp2.setSourcePort(333);
+ udp2.setPayload(new Data(new byte[]{(byte) 1, (byte) 2}));
+ udp2.setChecksum((short) 0);
+
+ ipv42.setPayload(udp2);
+ eth2.setPayload(ipv42);
+
+ TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(26))
+ .build();
+ OutboundPacket packet2 = new DefaultOutboundPacket(deviceId,
+ treatment2,
+ ByteBuffer.wrap(eth2.serialize()));
+
+
+ log.info("Emitting packets now");
+ packetService.emit(packet);
+ packetService.emit(packet);
+ packetService.emit(packet2);
+ packetService.emit(packet);
+ packetService.emit(packet);
+ log.info("Done emitting packets");
+ }
+
+ private class InternalPacketProcessor implements PacketProcessor {
+
+ @Override
+ public void process(PacketContext context) {
+
+
+ }
+ }
+
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
index c02ba3ca..31297ff4 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
@@ -53,6 +53,7 @@ import org.onosproject.net.flow.criteria.MplsCriterion;
import org.onosproject.net.flow.criteria.PortCriterion;
import org.onosproject.net.flow.criteria.VlanIdCriterion;
import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.FlowObjectiveStore;
import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -246,6 +247,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
private void addGroup(NextObjective nextObjective) {
log.debug("addGroup with type{} for nextObjective id {}",
nextObjective.type(), nextObjective.id());
+ List<GroupBucket> buckets;
switch (nextObjective.type()) {
case SIMPLE:
log.debug("processing SIMPLE next objective");
@@ -273,7 +275,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
break;
case HASHED:
log.debug("processing HASHED next objective");
- List<GroupBucket> buckets = nextObjective
+ buckets = nextObjective
.next()
.stream()
.map((treatment) -> DefaultGroupBucket
@@ -297,8 +299,32 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
}
break;
case BROADCAST:
+ log.debug("processing BROADCAST next objective");
+ buckets = nextObjective
+ .next()
+ .stream()
+ .map((treatment) -> DefaultGroupBucket
+ .createAllGroupBucket(treatment))
+ .collect(Collectors.toList());
+ if (!buckets.isEmpty()) {
+ final GroupKey key = new DefaultGroupKey(
+ appKryo.serialize(nextObjective
+ .id()));
+ GroupDescription groupDescription = new DefaultGroupDescription(
+ deviceId,
+ GroupDescription.Type.ALL,
+ new GroupBuckets(buckets),
+ key,
+ null,
+ nextObjective.appId());
+ log.debug("Creating BROADCAST group for next objective id {}",
+ nextObjective.id());
+ groupService.addGroup(groupDescription);
+ pendingGroups.put(key, nextObjective);
+ }
+ break;
case FAILOVER:
- log.debug("BROADCAST and FAILOVER next objectives not supported");
+ log.debug("FAILOVER next objectives not supported");
fail(nextObjective, ObjectiveError.UNSUPPORTED);
log.warn("Unsupported next objective type {}", nextObjective.type());
break;
@@ -326,6 +352,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
} else if (group.type() == GroupDescription.Type.SELECT) {
bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
+ } else if (group.type() == GroupDescription.Type.ALL) {
+ bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
} else {
log.warn("Unsupported Group type {}", group.type());
return;
@@ -356,6 +384,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
} else if (group.type() == GroupDescription.Type.SELECT) {
bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
+ } else if (group.type() == GroupDescription.Type.ALL) {
+ bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
} else {
log.warn("Unsupported Group type {}", group.type());
return;
@@ -383,7 +413,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
private Collection<FlowRule> processVersatile(ForwardingObjective fwd) {
log.debug("Processing versatile forwarding objective");
TrafficSelector selector = fwd.selector();
-
+ TrafficTreatment treatment = null;
EthTypeCriterion ethType =
(EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if (ethType == null) {
@@ -410,15 +440,26 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
return Collections.emptySet();
}
treatmentBuilder.deferred().group(group.id());
+ treatment = treatmentBuilder.build();
log.debug("Adding OUTGROUP action");
}
+ } else if (fwd.treatment() != null) {
+ if (fwd.treatment().allInstructions().size() == 1 &&
+ fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) {
+ OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0);
+ if (o.port() == PortNumber.CONTROLLER) {
+ log.warn("Punts to the controller are handled by misses in"
+ + " the TMAC, IP and MPLS tables.");
+ return Collections.emptySet();
+ }
+ }
+ treatment = fwd.treatment();
} else {
- log.warn("VERSATILE forwarding objective need next objective ID.");
+ log.warn("VERSATILE forwarding objective needs next objective ID "
+ + "or treatment.");
return Collections.emptySet();
}
- TrafficTreatment treatment = treatmentBuilder.build();
-
FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
.fromApp(fwd.appId()).withPriority(fwd.priority())
.forDevice(deviceId).withSelector(fwd.selector())
@@ -527,7 +568,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
protected List<FlowRule> processEthDstFilter(Criterion c,
FilteringObjective filt,
ApplicationId applicationId) {
- List<FlowRule> rules = new ArrayList<FlowRule>();
+ List<FlowRule> rules = new ArrayList<>();
EthCriterion e = (EthCriterion) c;
TrafficSelector.Builder selectorIp = DefaultTrafficSelector
.builder();
@@ -565,7 +606,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
protected List<FlowRule> processVlanIdFilter(Criterion c,
FilteringObjective filt,
ApplicationId applicationId) {
- List<FlowRule> rules = new ArrayList<FlowRule>();
+ List<FlowRule> rules = new ArrayList<>();
VlanIdCriterion v = (VlanIdCriterion) c;
log.debug("adding rule for VLAN: {}", v.vlanId());
TrafficSelector.Builder selector = DefaultTrafficSelector
@@ -616,21 +657,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
ops = install ? ops.add(rule) : ops.remove(rule);
}
} else if (c.type() == Criterion.Type.IPV4_DST) {
- IPCriterion ip = (IPCriterion) c;
- log.debug("adding rule for IP: {}", ip.ip());
- TrafficSelector.Builder selector = DefaultTrafficSelector
- .builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment
- .builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(ip.ip());
- treatment.transition(aclTableId);
- FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(filt.priority()).fromApp(applicationId)
- .makePermanent().forTable(ipv4UnicastTableId).build();
- ops = install ? ops.add(rule) : ops.remove(rule);
+ log.debug("driver does not process IP filtering rules as it " +
+ "sends all misses in the IP table to the controller");
} else {
log.warn("Driver does not currently process filtering condition"
+ " of type: {}", c.type());
@@ -762,6 +790,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
this.key = key;
}
+ @SuppressWarnings("unused")
public GroupKey key() {
return key;
}
diff --git a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
index 5059d4bf..af498832 100644
--- a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
+++ b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
@@ -32,12 +32,19 @@
impl="org.onosproject.driver.handshaker.NiciraSwitchHandshaker"/>
<behaviour api="org.onosproject.net.behaviour.ControllerConfig"
impl="org.onosproject.driver.ovsdb.OvsdbControllerConfig"/>
+ <behaviour api="org.onosproject.openflow.controller.ExtensionInterpreter"
+ impl="org.onosproject.driver.extensions.NiciraExtensionInterpreter" />
+ <behaviour api="org.onosproject.net.behaviour.ExtensionResolver"
+ impl="org.onosproject.driver.extensions.NiciraExtensionInterpreter" />
</driver>
<driver name="ovs-corsa" extends="ovs"
manufacturer="Corsa" hwVersion="emulation" swVersion="0.0.0">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
impl="org.onosproject.driver.pipeline.OVSCorsaPipeline"/>
</driver>
+ <!-- Emulation of the spring-open pipeline using a CPqD OF 1.3 software switch.
+ ~ This driver is the default driver assigned to the CPqD switch.
+ -->
<driver name="spring-open-cpqd" extends="default"
manufacturer="Stanford University, Ericsson Research and CPqD Research"
hwVersion="OpenFlow 1.3 Reference Userspace Switch" swVersion=".*">
@@ -66,7 +73,7 @@
<driver name="ofdpa" extends="default"
manufacturer="Broadcom Corp." hwVersion="OF-DPA.*" swVersion="OF-DPA.*">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.OFDPA1Pipeline"/>
+ impl="org.onosproject.driver.pipeline.OFDPA2Pipeline"/>
</driver>
<driver name="pmc-olt" extends="default"
manufacturer="Big Switch Networks" hwVersion="ivs 0.5" swVersion="ivs 0.5">
@@ -109,7 +116,7 @@
manufacturer="ONF"
hwVersion="OF1.3 Software Switch from CPqD" swVersion="for Group Chaining">
<behaviour api="org.onosproject.net.behaviour.Pipeliner"
- impl="org.onosproject.driver.pipeline.CpqdOFDPA1Pipeline"/>
+ impl="org.onosproject.driver.pipeline.CpqdOFDPA2Pipeline"/>
</driver>
<driver name="calient" extends="default"
manufacturer="calient inc" hwVersion="calient hardware"
diff --git a/framework/src/onos/features/features.xml b/framework/src/onos/features/features.xml
index dec02998..1aae0f33 100644
--- a/framework/src/onos/features/features.xml
+++ b/framework/src/onos/features/features.xml
@@ -96,6 +96,7 @@
<bundle>mvn:org.onosproject/onos-core-net/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-common/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-dist/@ONOS-VERSION</bundle>
+ <bundle>mvn:org.onosproject/onos-core-persistence/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onos-core-serializers/@ONOS-VERSION</bundle>
<bundle>mvn:org.onosproject/onlab-netty/@ONOS-VERSION</bundle>
</feature>
diff --git a/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/package-info.java b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/package-info.java
new file mode 100644
index 00000000..6cea24d1
--- /dev/null
+++ b/framework/src/onos/incubator/api/src/main/java/org/onosproject/incubator/net/intf/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.
+ */
+
+/**
+ * Interface Service.
+ */
+package org.onosproject.incubator.net.intf;
diff --git a/framework/src/onos/netconf/api/src/main/java/org/onosproject/netconf/package-info.java b/framework/src/onos/netconf/api/src/main/java/org/onosproject/netconf/package-info.java
new file mode 100644
index 00000000..5562bd33
--- /dev/null
+++ b/framework/src/onos/netconf/api/src/main/java/org/onosproject/netconf/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.
+ */
+
+/**
+ * Created by ray on 10/30/15.
+ */
+package org.onosproject.netconf;
diff --git a/framework/src/onos/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java b/framework/src/onos/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/package-info.java
new file mode 100644
index 00000000..84992bf2
--- /dev/null
+++ b/framework/src/onos/netconf/ctl/src/main/java/org/onosproject/netconf/ctl/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.
+ */
+
+/**
+ * Created by ray on 10/30/15.
+ */
+package org.onosproject.netconf.ctl;
diff --git a/framework/src/onos/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java b/framework/src/onos/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/package-info.java
new file mode 100644
index 00000000..616a7ce5
--- /dev/null
+++ b/framework/src/onos/netconf/rfc/src/main/java/org/onosproject/netconf/rfc/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.
+ */
+
+/**
+ * Created by ray on 10/30/15.
+ */
+package org.onosproject.netconf.rfc;
diff --git a/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionInterpreter.java b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionInterpreter.java
new file mode 100644
index 00000000..44b121ac
--- /dev/null
+++ b/framework/src/onos/openflow/api/src/main/java/org/onosproject/openflow/controller/ExtensionInterpreter.java
@@ -0,0 +1,58 @@
+/*
+ * 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.openflow.controller;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
+import org.onosproject.net.flow.instructions.ExtensionType;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.action.OFAction;
+
+/**
+ * Interprets extension instructions and converts them to/from OpenFlow objects.
+ */
+@Beta
+public interface ExtensionInterpreter extends HandlerBehaviour {
+
+ /**
+ * Returns true if the given extension instruction is supported by this
+ * driver.
+ *
+ * @param extensionType extension instruction type
+ * @return true if the instruction is supported, otherwise false
+ */
+ boolean supported(ExtensionType extensionType);
+
+ /**
+ * Maps an extension instruction to an OpenFlow action.
+ *
+ * @param factory OpenFlow factory
+ * @param extensionInstruction extension instruction
+ * @return OpenFlow action
+ */
+ OFAction mapInstruction(OFFactory factory, ExtensionInstruction extensionInstruction);
+
+ /**
+ * Maps an OpenFlow action to an extension instruction.
+ *
+ * @param action OpenFlow action
+ * @return extension instruction
+ */
+ ExtensionInstruction mapAction(OFAction action);
+
+}
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/EventSubject.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/EventSubject.java
index 6a067244..d8aaef65 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/EventSubject.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/EventSubject.java
@@ -16,8 +16,7 @@
package org.onosproject.ovsdb.controller;
/**
- * Represents for a entity that carry important information for listener.
+ * Representation for an entity that carries important information for a listener.
*/
public interface EventSubject {
-
}
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridge.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridge.java
index 1ee0a367..18c59e14 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridge.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridge.java
@@ -21,7 +21,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a ovsdb bridge. This class is immutable.
+ * The class representing an ovsdb bridge.
+ * This class is immutable.
*/
public final class OvsdbBridge {
@@ -29,7 +30,7 @@ public final class OvsdbBridge {
private final OvsdbDatapathId datapathId;
/**
- * Constructor from a OvsdbBridgeName bridgeName and a OvsdbDatapathId
+ * Constructor from an OvsdbBridgeName bridgeName and an OvsdbDatapathId
* datapathId.
*
* @param bridgeName the bridgeName to use
@@ -43,16 +44,16 @@ public final class OvsdbBridge {
}
/**
- * Gets the bridge name of the bridge.
+ * Gets the bridge name of bridge.
*
- * @return the bridge name of the bridge
+ * @return the bridge name of bridge
*/
public OvsdbBridgeName bridgeName() {
return bridgeName;
}
/**
- * Gets the datapathId of the bridge.
+ * Gets the datapathId of bridge.
*
* @return datapathId the datapathId to use
*/
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridgeName.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridgeName.java
index daedff5f..899799fa 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridgeName.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbBridgeName.java
@@ -21,14 +21,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a bridge name. This class is immutable.
+ * The class representing a bridge name.
+ * This class is immutable.
*/
public final class OvsdbBridgeName {
private final String value;
/**
- * Constructor from a String bridge name.
+ * Constructor from a String.
*
* @param value the bridge name to use
*/
@@ -38,7 +39,7 @@ public final class OvsdbBridgeName {
}
/**
- * Gets the value of the bridge name.
+ * Gets the value of bridge name.
*
* @return the value of the bridge name
*/
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index e619f8e0..edd25ac6 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -43,7 +43,7 @@ public interface OvsdbClientService extends OvsdbRPC {
OvsdbNodeId nodeId();
/**
- * Creates the configuration for the tunnel.
+ * Creates the configuration for tunnel.
*
* @param srcIp source IP address
* @param dstIp destination IP address
@@ -62,7 +62,7 @@ public interface OvsdbClientService extends OvsdbRPC {
boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options);
/**
- * Drops the configuration for the tunnel.
+ * Drops the configuration for tunnel.
*
* @param srcIp source IP address
* @param dstIp destination IP address
@@ -70,7 +70,7 @@ public interface OvsdbClientService extends OvsdbRPC {
void dropTunnel(IpAddress srcIp, IpAddress dstIp);
/**
- * Gets tunnels of the node.
+ * Gets tunnels of node.
*
* @return set of tunnels; empty if no tunnel is find
*/
@@ -102,14 +102,14 @@ public interface OvsdbClientService extends OvsdbRPC {
void dropBridge(String bridgeName);
/**
- * Gets bridges of the node.
+ * Gets bridges of node.
*
* @return set of bridges; empty if no bridge is find
*/
Set<OvsdbBridge> getBridges();
/**
- * Gets controllers of the node.
+ * Gets controllers of node.
*
* @param openflowDeviceId target device id
* @return set of controllers; empty if no controller is find
@@ -155,7 +155,7 @@ public interface OvsdbClientService extends OvsdbRPC {
void dropPort(String bridgeName, String portName);
/**
- * Gets ports of the bridge.
+ * Gets ports of bridge.
*
* @return set of ports; empty if no ports is find
*/
@@ -247,7 +247,7 @@ public interface OvsdbClientService extends OvsdbRPC {
DatabaseSchema getDatabaseSchema(String dbName);
/**
- * Gets the ovsdb row from the local ovsdb store.
+ * Gets the ovsdb row from local ovsdb store.
*
* @param dbName database name
* @param tableName table name
@@ -257,7 +257,7 @@ public interface OvsdbClientService extends OvsdbRPC {
Row getRow(String dbName, String tableName, String uuid);
/**
- * Removes the ovsdb row from the local ovsdb store.
+ * Removes the ovsdb row from local ovsdb store.
*
* @param dbName database name
* @param tableName table name
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbController.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbController.java
index 24bfeae9..f22a5787 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbController.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbController.java
@@ -21,7 +21,7 @@ import org.onlab.packet.TpPort;
import java.util.List;
/**
- * Abstraction of an ovsdb controller. Serves as a one stop shop for obtaining
+ * Abstraction of an ovsdb controller. Serves as an one stop shop for obtaining
* OvsdbNode and (un)register listeners on ovsdb events and ovsdb node events.
*/
public interface OvsdbController {
@@ -62,7 +62,7 @@ public interface OvsdbController {
List<OvsdbNodeId> getNodeIds();
/**
- * Gets a ovsdb client by node identifier.
+ * Gets an ovsdb client by node identifier.
*
* @param nodeId node identifier
* @return OvsdbClient ovsdb node information
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbDatapathId.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbDatapathId.java
index 1a2d8366..8ccf45f2 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbDatapathId.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbDatapathId.java
@@ -20,13 +20,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a datapathid. This class is immutable.
+ * The class representing a datapathid.
+ * This class is immutable.
*/
public final class OvsdbDatapathId {
private final String value;
/**
- * Constructor from a String datapathid.
+ * Constructor from a String.
*
* @param value the datapathid to use
*/
@@ -36,9 +37,9 @@ public final class OvsdbDatapathId {
}
/**
- * Gets the value of the datapathid.
+ * Gets the value of datapathid.
*
- * @return the value of the datapathid
+ * @return the value of datapathid
*/
public String value() {
return value;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbEventSubject.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbEventSubject.java
index 263027f2..226a26e6 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbEventSubject.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbEventSubject.java
@@ -21,7 +21,7 @@ import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
/**
- * Represents for a entity that carry important information for listener.
+ * Represents for an entity that carry important information for listener.
*/
public interface OvsdbEventSubject extends EventSubject {
/**
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbIfaceId.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbIfaceId.java
index b0535d21..10ba80bc 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbIfaceId.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbIfaceId.java
@@ -20,13 +20,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a ifaceid. This class is immutable.
+ * The class representing an ifaceid.
+ * This class is immutable.
*/
public class OvsdbIfaceId {
private final String value;
/**
- * Constructor from a String ifaceid.
+ * Constructor from a String.
*
* @param value the ifaceid to use
*/
@@ -36,9 +37,9 @@ public class OvsdbIfaceId {
}
/**
- * Gets the value of the ifaceid.
+ * Gets the value of ifaceid.
*
- * @return the value of the ifaceid
+ * @return the value of ifaceid
*/
public String value() {
return value;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbNodeId.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbNodeId.java
index 2c1a440b..f3bba4b8 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbNodeId.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbNodeId.java
@@ -39,7 +39,7 @@ public final class OvsdbNodeId {
public OvsdbNodeId(IpAddress ipAddress, long port) {
checkNotNull(ipAddress, "ipAddress is not null");
this.ipAddress = ipAddress.toString();
- this.nodeId = ipAddress + ":" + port;
+ this.nodeId = ipAddress.toString();
}
@Override
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPort.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPort.java
index 3c04f6a5..deea42d7 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPort.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPort.java
@@ -29,7 +29,7 @@ public final class OvsdbPort {
private final OvsdbPortName portName;
/**
- * Constructor from a OvsdbPortNumber portNumber, OvsdbPortName portName.
+ * Constructor from OvsdbPortNumber portNumber, OvsdbPortName portName.
*
* @param portNumber the portNumber to use
* @param portName the portName to use
@@ -42,18 +42,18 @@ public final class OvsdbPort {
}
/**
- * Gets the port number of the port.
+ * Gets the port number of port.
*
- * @return the port number of the port
+ * @return the port number of port
*/
public OvsdbPortNumber portNumber() {
return portNumber;
}
/**
- * Gets the port name of the port.
+ * Gets the port name of port.
*
- * @return the port name of the port
+ * @return the port name of port
*/
public OvsdbPortName portName() {
return portName;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortName.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortName.java
index aa0f55b0..d9c7c2da 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortName.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortName.java
@@ -21,14 +21,15 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a port number. This class is immutable.
+ * The class representing a port number.
+ * This class is immutable.
*/
public final class OvsdbPortName {
private final String value;
/**
- * Constructor from a String port name.
+ * Constructor from a String.
*
* @param value the port name to use
*/
@@ -38,9 +39,9 @@ public final class OvsdbPortName {
}
/**
- * Gets the value of the port name.
+ * Gets the value of port name.
*
- * @return the value of the port name
+ * @return the value of port name
*/
public String value() {
return value;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortNumber.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortNumber.java
index 9c57b5df..bd094d04 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortNumber.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbPortNumber.java
@@ -20,14 +20,15 @@ import static com.google.common.base.MoreObjects.toStringHelper;
import java.util.Objects;
/**
- * The class representing a port number. This class is immutable.
+ * The class representing a port number.
+ * This class is immutable.
*/
public final class OvsdbPortNumber {
private final long value;
/**
- * Constructor from a long port number.
+ * Constructor from a long value.
*
* @param value the port number to use
*/
@@ -36,9 +37,9 @@ public final class OvsdbPortNumber {
}
/**
- * Gets the value of the port number.
+ * Gets the value of port number.
*
- * @return the value of the port number
+ * @return the value of port number
*/
public long value() {
return value;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTableStore.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTableStore.java
index 1d9146eb..72b64f32 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTableStore.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTableStore.java
@@ -29,18 +29,18 @@ public class OvsdbTableStore {
/**
* Gets the ovsdbRowStore.
*
- * @param tableName a ovsdb table name
- * @return OvsdbRowStore the data of the table
+ * @param tableName an ovsdb table name
+ * @return OvsdbRowStore the data of table
*/
public OvsdbRowStore getRows(String tableName) {
return tableStore.get(tableName);
}
/**
- * Create or update a value to tableStore.
+ * Creates or updates a value to tableStore.
*
- * @param tableName key of the tableName
- * @param rowStore a row of the table
+ * @param tableName key of tableName
+ * @param rowStore a row of table
*/
public void createOrUpdateTable(String tableName, OvsdbRowStore rowStore) {
tableStore.put(tableName, rowStore);
@@ -49,14 +49,14 @@ public class OvsdbTableStore {
/**
* Drops a value to table data.
*
- * @param tableName key of the tableName
+ * @param tableName key of tableName
*/
public void dropTable(String tableName) {
tableStore.remove(tableName);
}
/**
- * Gets the tableStore.
+ * Gets tableStore.
*
* @return tableStore
*/
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java
index e1c5c7fd..8c857da4 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnel.java
@@ -23,7 +23,8 @@ import java.util.Objects;
import org.onlab.packet.IpAddress;
/**
- * The class representing a ovsdb tunnel. This class is immutable.
+ * The class representing an ovsdb tunnel.
+ * This class is immutable.
*/
public final class OvsdbTunnel {
@@ -38,7 +39,7 @@ public final class OvsdbTunnel {
private final OvsdbTunnelName tunnelName;
/**
- * Constructor from a IpAddress localIp, IpAddress remoteIp Type tunnelType,
+ * Constructor from an IpAddress localIp, IpAddress remoteIp Type tunnelType,
* OvsdbTunnelName tunnelName.
*
* @param localIp the localIp to use
@@ -58,36 +59,36 @@ public final class OvsdbTunnel {
}
/**
- * Gets the local IP of the tunnel.
+ * Gets the local IP of tunnel.
*
- * @return the local IP of the tunnel
+ * @return the local IP of tunnel
*/
public IpAddress localIp() {
return localIp;
}
/**
- * Gets the remote IP of the tunnel.
+ * Gets the remote IP of tunnel.
*
- * @return the remote IP of the tunnel
+ * @return the remote IP of tunnel
*/
public IpAddress remoteIp() {
return remoteIp;
}
/**
- * Gets the tunnel type of the tunnel.
+ * Gets the tunnel type of tunnel.
*
- * @return the tunnel type of the tunnel
+ * @return the tunnel type of tunnel
*/
public Type tunnelType() {
return tunnelType;
}
/**
- * Gets the tunnel name of the tunnel.
+ * Gets the tunnel name of tunnel.
*
- * @return the tunnel name of the tunnel
+ * @return the tunnel name of tunnel
*/
public OvsdbTunnelName tunnelName() {
return tunnelName;
diff --git a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java
index 116f6217..80befab3 100644
--- a/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java
+++ b/framework/src/onos/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbTunnelName.java
@@ -21,13 +21,14 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
/**
- * The class representing a tunnel name. This class is immutable.
+ * The class representing a tunnel name.
+ * This class is immutable.
*/
public final class OvsdbTunnelName {
private final String value;
/**
- * Constructor from a String tunnel name.
+ * Constructor from a String.
*
* @param value the tunnel name to use
*/
@@ -37,9 +38,9 @@ public final class OvsdbTunnelName {
}
/**
- * Gets the value of the tunnel name.
+ * Gets the value of tunnel name.
*
- * @return the value of the tunnel name
+ * @return the value of tunnel name
*/
public String value() {
return value;
diff --git a/framework/src/onos/pom.xml b/framework/src/onos/pom.xml
index b9fdfe22..4686e3f3 100644
--- a/framework/src/onos/pom.xml
+++ b/framework/src/onos/pom.xml
@@ -58,6 +58,7 @@
<module>tools/package/archetypes</module>
<module>tools/package/branding</module>
+ <module>tools/build/conf</module>
<module>bgp</module>
</modules>
@@ -79,7 +80,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <onos-build-conf.version>1.0</onos-build-conf.version>
+ <onos-build-conf.version>1.1-SNAPSHOT</onos-build-conf.version>
<netty4.version>4.0.23.Final</netty4.version>
<copycat.version>0.5.0.onos</copycat.version>
<openflowj.version>0.9.0.onos</openflowj.version>
diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
index a840f856..98442033 100644
--- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
+++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LLDPLinkProvider.java
@@ -27,6 +27,7 @@ import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.Ethernet;
import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cluster.ClusterService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.mastership.MastershipEvent;
@@ -37,6 +38,7 @@ import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.LinkKey;
import org.onosproject.net.Port;
+import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -60,6 +62,7 @@ import java.io.IOException;
import java.util.Dictionary;
import java.util.EnumSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
@@ -86,6 +89,10 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
"Settings: enabled={}, useBDDP={}, probeRate={}, " +
"staleLinkAge={}, lldpSuppression={}";
+ // When a Device/Port has this annotation, do not send out LLDP/BDDP
+ public static final String NO_LLDP = "no-lldp";
+
+
private final Logger log = getLogger(getClass());
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -109,6 +116,12 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService cfgService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ClusterService clusterService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected NetworkConfigRegistry cfgRegistry;
+
private LinkProviderService providerService;
private ScheduledExecutorService executor;
@@ -207,7 +220,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
newLldpSuppression = isNullOrEmpty(s) ? DEFAULT_LLDP_SUPPRESSION_CONFIG : s;
} catch (NumberFormatException e) {
- log.warn(e.getMessage());
+ log.warn("Component configuration had invalid values", e);
newEnabled = enabled;
newUseBddp = useBDDP;
newProbeRate = probeRate;
@@ -227,6 +240,14 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
enable();
} else if (wasEnabled && !enabled) {
disable();
+ } else {
+ // reflect changes in suppression rules to discovery helpers
+ // FIXME: After migrating to Network Configuration Subsystem,
+ // it should be possible to update only changed subset
+ if (enabled) {
+ // update all discovery helper state
+ loadDevices();
+ }
}
log.info(FORMAT, enabled, useBDDP, probeRate, staleLinkAge, lldpSuppression);
@@ -277,31 +298,96 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
* Loads available devices and registers their ports to be probed.
*/
private void loadDevices() {
- for (Device device : deviceService.getAvailableDevices()) {
- if (rules.isSuppressed(device)) {
- log.debug("LinkDiscovery from {} disabled by configuration", device.id());
- continue;
- }
- LinkDiscovery ld = new LinkDiscovery(device, context);
- discoverers.put(device.id(), ld);
- addPorts(ld, device.id());
+ deviceService.getAvailableDevices()
+ .forEach(d -> updateDevice(d)
+ .ifPresent(ld -> updatePorts(ld, d.id())));
+ }
+
+ /**
+ * Updates discovery helper for specified device.
+ *
+ * Adds and starts a discovery helper for specified device if enabled,
+ * calls {@link #removeDevice(DeviceId)} otherwise.
+ *
+ * @param device device to add
+ * @return discovery helper if discovery is enabled for the device
+ */
+ private Optional<LinkDiscovery> updateDevice(Device device) {
+ if (rules.isSuppressed(device)) {
+ log.trace("LinkDiscovery from {} disabled by configuration", device.id());
+ removeDevice(device.id());
+ return Optional.empty();
+ }
+ LinkDiscovery ld = discoverers.computeIfAbsent(device.id(),
+ did -> new LinkDiscovery(device, context));
+ if (ld.isStopped()) {
+ ld.start();
}
+ return Optional.of(ld);
}
/**
- * Adds ports of the specified device to the specified discovery helper.
+ * Removes after stopping discovery helper for specified device.
+ * @param deviceId device to remove
*/
- private void addPorts(LinkDiscovery discoverer, DeviceId deviceId) {
- for (Port p : deviceService.getPorts(deviceId)) {
- if (rules.isSuppressed(p)) {
- continue;
- }
- if (!p.number().isLogical()) {
- discoverer.addPort(p);
- }
+ private void removeDevice(final DeviceId deviceId) {
+ discoverers.computeIfPresent(deviceId, (did, ld) -> {
+ ld.stop();
+ providerService.linksVanished(deviceId);
+ return null;
+ });
+
+ }
+
+ /**
+ * Updates ports of the specified device to the specified discovery helper.
+ */
+ private void updatePorts(LinkDiscovery discoverer, DeviceId deviceId) {
+ deviceService.getPorts(deviceId).forEach(p -> updatePort(discoverer, p));
+ }
+
+ /**
+ * Updates discovery helper state of the specified port.
+ *
+ * Adds a port to the discovery helper if up and discovery is enabled,
+ * or calls {@link #removePort(Port)} otherwise.
+ */
+ private void updatePort(LinkDiscovery discoverer, Port port) {
+ if (rules.isSuppressed(port)) {
+ log.trace("LinkDiscovery from {} disabled by configuration", port);
+ removePort(port);
+ return;
+ }
+
+ // check if enabled and turn off discovery?
+ if (!port.isEnabled()) {
+ removePort(port);
+ return;
+ }
+
+ if (!port.number().isLogical()) {
+ discoverer.addPort(port);
}
}
+ /**
+ * Removes a port from the specified discovery helper.
+ * @param port the port
+ */
+ private void removePort(Port port) {
+ if (port.element() instanceof Device) {
+ Device d = (Device) port.element();
+ LinkDiscovery ld = discoverers.get(d.id());
+ if (ld != null) {
+ ld.removePort(port.number());
+ }
+
+ ConnectPoint point = new ConnectPoint(d.id(), port.number());
+ providerService.linksVanished(point);
+ } else {
+ log.warn("Attempted to remove non-Device port", port);
+ }
+ }
/**
* Loads LLDP suppression rules.
@@ -317,7 +403,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
// default rule to suppress ROADM to maintain compatibility
rules = new SuppressionRules(ImmutableSet.of(),
EnumSet.of(Device.Type.ROADM),
- ImmutableMap.of());
+ ImmutableMap.of(NO_LLDP, SuppressionRules.ANY_VALUE));
}
// should refresh discoverers when we need dynamic reconfiguration
@@ -367,10 +453,9 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
log.debug("Device {} doesn't exist, or isn't there yet", deviceId);
return;
}
- if (rules.isSuppressed(device)) {
- return;
+ if (clusterService.getLocalNode().id().equals(event.roleInfo().master())) {
+ updateDevice(device).ifPresent(ld -> updatePorts(ld, device.id()));
}
- discoverers.computeIfAbsent(deviceId, k -> new LinkDiscovery(device, context));
}
}
@@ -381,7 +466,6 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
private class InternalDeviceListener implements DeviceListener {
@Override
public void event(DeviceEvent event) {
- LinkDiscovery ld;
Device device = event.subject();
Port port = event.port();
if (device == null) {
@@ -393,73 +477,33 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
switch (event.type()) {
case DEVICE_ADDED:
case DEVICE_UPDATED:
- synchronized (discoverers) {
- ld = discoverers.get(deviceId);
- if (ld == null) {
- if (rules != null && rules.isSuppressed(device)) {
- log.debug("LinkDiscovery from {} disabled by configuration", device.id());
- return;
- }
- log.debug("Device added ({}) {}", event.type(), deviceId);
- discoverers.put(deviceId, new LinkDiscovery(device, context));
- } else {
- if (ld.isStopped()) {
- log.debug("Device restarted ({}) {}", event.type(), deviceId);
- ld.start();
- }
- }
- }
+ updateDevice(device).ifPresent(ld -> updatePorts(ld, deviceId));
break;
case PORT_ADDED:
case PORT_UPDATED:
if (port.isEnabled()) {
- ld = discoverers.get(deviceId);
- if (ld == null) {
- return;
- }
- if (rules.isSuppressed(port)) {
- log.debug("LinkDiscovery from {}@{} disabled by configuration",
- port.number(), device.id());
- return;
- }
- if (!port.number().isLogical()) {
- log.debug("Port added {}", port);
- ld.addPort(port);
- }
+ updateDevice(device).ifPresent(ld -> updatePort(ld, port));
} else {
log.debug("Port down {}", port);
- ConnectPoint point = new ConnectPoint(deviceId, port.number());
- providerService.linksVanished(point);
+ removePort(port);
}
break;
case PORT_REMOVED:
log.debug("Port removed {}", port);
- ConnectPoint point = new ConnectPoint(deviceId, port.number());
- providerService.linksVanished(point);
-
+ removePort(port);
break;
case DEVICE_REMOVED:
case DEVICE_SUSPENDED:
log.debug("Device removed {}", deviceId);
- ld = discoverers.get(deviceId);
- if (ld == null) {
- return;
- }
- ld.stop();
- providerService.linksVanished(deviceId);
+ removeDevice(deviceId);
break;
case DEVICE_AVAILABILITY_CHANGED:
- ld = discoverers.get(deviceId);
- if (ld == null) {
- return;
- }
if (deviceService.isAvailable(deviceId)) {
log.debug("Device up {}", deviceId);
- ld.start();
+ updateDevice(device);
} else {
- providerService.linksVanished(deviceId);
log.debug("Device down {}", deviceId);
- ld.stop();
+ removeDevice(deviceId);
}
break;
case PORT_STATS_UPDATED:
@@ -508,17 +552,7 @@ public class LLDPLinkProvider extends AbstractProvider implements LinkProvider {
}
// check what deviceService sees, to see if we are missing anything
try {
- for (Device dev : deviceService.getDevices()) {
- if (rules.isSuppressed(dev)) {
- continue;
- }
- DeviceId did = dev.id();
- synchronized (discoverers) {
- LinkDiscovery ld = discoverers
- .computeIfAbsent(did, k -> new LinkDiscovery(dev, context));
- addPorts(ld, did);
- }
- }
+ loadDevices();
} catch (Exception e) {
// Catch all exceptions to avoid task being suppressed
log.error("Exception thrown during synchronization process", e);
diff --git a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
index 8cdfd50f..7dc9aed0 100644
--- a/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
+++ b/framework/src/onos/providers/lldp/src/main/java/org/onosproject/provider/lldp/impl/LinkDiscovery.java
@@ -61,7 +61,7 @@ class LinkDiscovery implements TimerTask {
private final ONOSLLDP lldpPacket;
private final Ethernet ethPacket;
- private Ethernet bddpEth;
+ private final Ethernet bddpEth;
private Timeout timeout;
private volatile boolean isStopped;
@@ -126,7 +126,7 @@ class LinkDiscovery implements TimerTask {
}
/**
- * Add physical port port to discovery process.
+ * Add physical port to discovery process.
* Send out initial LLDP and label it as slow port.
*
* @param port the port
@@ -141,6 +141,14 @@ class LinkDiscovery implements TimerTask {
}
/**
+ * removed physical port from discovery process.
+ * @param port the port number
+ */
+ void removePort(PortNumber port) {
+ ports.remove(port.toLong());
+ }
+
+ /**
* Handles an incoming LLDP packet. Creates link in topology and adds the
* link for staleness tracking.
*
diff --git a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java b/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
index b4b7b7b6..6070b857 100644
--- a/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
+++ b/framework/src/onos/providers/lldp/src/test/java/org/onosproject/provider/lldp/impl/LLDPLinkProviderTest.java
@@ -16,6 +16,7 @@
package org.onosproject.provider.lldp.impl;
import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.junit.After;
@@ -32,7 +33,9 @@ import org.onosproject.core.CoreService;
import org.onosproject.core.DefaultApplicationId;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.mastership.MastershipService;
+import org.onosproject.net.Annotations;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultDevice;
import org.onosproject.net.DefaultPort;
import org.onosproject.net.Device;
@@ -73,6 +76,7 @@ public class LLDPLinkProviderTest {
private static final DeviceId DID1 = DeviceId.deviceId("of:0000000000000001");
private static final DeviceId DID2 = DeviceId.deviceId("of:0000000000000002");
+ private static final DeviceId DID3 = DeviceId.deviceId("of:0000000000000003");
private static Port pd1;
private static Port pd2;
@@ -133,10 +137,35 @@ public class LLDPLinkProviderTest {
deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_REMOVED, DID1));
- assertTrue("Discoverer is not gone", provider.discoverers.get(DID1).isStopped());
+ final LinkDiscovery linkDiscovery = provider.discoverers.get(DID1);
+ if (linkDiscovery != null) {
+ // If LinkDiscovery helper is there after DEVICE_REMOVED,
+ // it should be stopped
+ assertTrue("Discoverer is not stopped", linkDiscovery.isStopped());
+ }
assertTrue("Device is not gone.", vanishedDpid(DID1));
}
+ /**
+ * Checks that links on a reconfigured switch are properly removed.
+ */
+ @Test
+ public void switchSuppressed() {
+ // add device to stub DeviceService
+ deviceService.putDevice(device(DID3));
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
+
+ assertFalse("Device not added", provider.discoverers.isEmpty());
+
+ // update device in stub DeviceService with suppression config
+ deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
+ .set(LLDPLinkProvider.NO_LLDP, "true")
+ .build()));
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
+
+ assertTrue("Links on suppressed Device was expected to vanish.", vanishedDpid(DID3));
+ }
+
@Test
public void portUp() {
deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
@@ -152,27 +181,101 @@ public class LLDPLinkProviderTest {
deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 1, false)));
-
-
assertFalse("Port added to discoverer",
provider.discoverers.get(DID1).containsPort(1L));
assertTrue("Port is not gone.", vanishedPort(1L));
}
@Test
+ public void portRemoved() {
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
+ deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID1, port(DID1, 3, true)));
+ deviceListener.event(portEvent(DeviceEvent.Type.PORT_REMOVED, DID1, port(DID1, 3, true)));
+
+ assertTrue("Port is not gone.", vanishedPort(3L));
+ assertFalse("Port was not removed from discoverer",
+ provider.discoverers.get(DID1).containsPort(3L));
+ }
+
+ /**
+ * Checks that discovery on reconfigured switch are properly restarted.
+ */
+ @Test
+ public void portSuppressedByDeviceConfig() {
+
+ /// When Device is configured with suppression:ON, Port also is same
+
+ // add device in stub DeviceService with suppression configured
+ deviceService.putDevice(device(DID3, DefaultAnnotations.builder()
+ .set(LLDPLinkProvider.NO_LLDP, "true")
+ .build()));
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
+
+ // non-suppressed port added to suppressed device
+ final long portno3 = 3L;
+ deviceService.putPorts(DID3, port(DID3, portno3, true));
+ deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, portno3, true)));
+
+ // discovery on device is expected to be stopped
+ LinkDiscovery linkDiscovery = provider.discoverers.get(DID3);
+ if (linkDiscovery != null) {
+ assertTrue("Discovery expected to be stopped", linkDiscovery.isStopped());
+ }
+
+ /// When Device is reconfigured without suppression:OFF,
+ /// Port should be included for discovery
+
+ // update device in stub DeviceService without suppression configured
+ deviceService.putDevice(device(DID3));
+ // update the Port in stub DeviceService. (Port has reference to Device)
+ deviceService.putPorts(DID3, port(DID3, portno3, true));
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_UPDATED, DID3));
+
+ // discovery should come back on
+ assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
+ assertTrue("Discoverer should contain the port there", provider.discoverers.get(DID3).containsPort(portno3));
+ }
+
+ /**
+ * Checks that discovery on reconfigured port are properly restarted.
+ */
+ @Test
+ public void portSuppressedByPortConfig() {
+ // add device in stub DeviceService without suppression configured
+ deviceService.putDevice(device(DID3));
+ deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID3));
+
+ // suppressed port added to non-suppressed device
+ final long portno3 = 3L;
+ final Port port3 = port(DID3, portno3, true,
+ DefaultAnnotations.builder()
+ .set(LLDPLinkProvider.NO_LLDP, "true")
+ .build());
+ deviceService.putPorts(DID3, port3);
+ deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port3));
+
+ // discovery helper should be there turned on
+ assertFalse("Discoverer is expected to start", provider.discoverers.get(DID3).isStopped());
+ assertFalse("Discoverer should not contain the port there",
+ provider.discoverers.get(DID3).containsPort(portno3));
+ }
+
+ @Test
public void portUnknown() {
deviceListener.event(deviceEvent(DeviceEvent.Type.DEVICE_ADDED, DID1));
- deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID2, port(DID2, 1, false)));
+ // Note: DID3 hasn't been added to TestDeviceService, but only port is added
+ deviceListener.event(portEvent(DeviceEvent.Type.PORT_ADDED, DID3, port(DID3, 1, false)));
assertNull("DeviceId exists",
- provider.discoverers.get(DID2));
+ provider.discoverers.get(DID3));
}
@Test
public void unknownPktCtx() {
- PacketContext pktCtx = new TestPacketContext(deviceService.getDevice(DID2));
+ // Note: DID3 hasn't been added to TestDeviceService
+ PacketContext pktCtx = new TestPacketContext(device(DID3));
testProcessor.process(pktCtx);
assertFalse("Context should still be free", pktCtx.isHandled());
@@ -206,6 +309,16 @@ public class LLDPLinkProviderTest {
}
+ private DefaultDevice device(DeviceId did) {
+ return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
+ "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
+ }
+
+ private DefaultDevice device(DeviceId did, Annotations annotations) {
+ return new DefaultDevice(ProviderId.NONE, did, Device.Type.SWITCH,
+ "TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId(), annotations);
+ }
+
@SuppressWarnings(value = { "unused" })
private DeviceEvent portEvent(DeviceEvent.Type type, DeviceId did, PortNumber port) {
return new DeviceEvent(type, deviceService.getDevice(did),
@@ -221,6 +334,10 @@ public class LLDPLinkProviderTest {
PortNumber.portNumber(port), enabled);
}
+ private Port port(DeviceId did, long port, boolean enabled, Annotations annotations) {
+ return new DefaultPort(deviceService.getDevice(did),
+ PortNumber.portNumber(port), enabled, annotations);
+ }
private boolean vanishedDpid(DeviceId... dids) {
for (int i = 0; i < dids.length; i++) {
@@ -384,10 +501,9 @@ public class LLDPLinkProviderTest {
private class TestDeviceService extends DeviceServiceAdapter {
- private Map<DeviceId, Device> devices = new HashMap<>();
+ private final Map<DeviceId, Device> devices = new HashMap<>();
private final ArrayListMultimap<DeviceId, Port> ports =
ArrayListMultimap.create();
-
public TestDeviceService() {
Device d1 = new DefaultDevice(ProviderId.NONE, DID1, Device.Type.SWITCH,
"TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
@@ -395,7 +511,6 @@ public class LLDPLinkProviderTest {
"TESTMF", "TESTHW", "TESTSW", "TESTSN", new ChassisId());
devices.put(DID1, d1);
devices.put(DID2, d2);
-
pd1 = new DefaultPort(d1, PortNumber.portNumber(1), true);
pd2 = new DefaultPort(d1, PortNumber.portNumber(2), true);
pd3 = new DefaultPort(d2, PortNumber.portNumber(1), true);
@@ -405,6 +520,15 @@ public class LLDPLinkProviderTest {
ports.putAll(DID2, Lists.newArrayList(pd3, pd4));
}
+ private void putDevice(Device device) {
+ DeviceId deviceId = device.id();
+ devices.put(deviceId, device);
+ }
+
+ private void putPorts(DeviceId did, Port...ports) {
+ this.ports.putAll(did, Lists.newArrayList(ports));
+ }
+
@Override
public int getDeviceCount() {
return devices.values().size();
@@ -412,7 +536,7 @@ public class LLDPLinkProviderTest {
@Override
public Iterable<Device> getDevices() {
- return Collections.emptyList();
+ return ImmutableList.copyOf(devices.values());
}
@Override
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index 1039d049..4d5b6b28 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -15,15 +15,7 @@
*/
package org.onosproject.provider.of.flow.impl;
-import static org.onosproject.net.flow.criteria.Criteria.matchLambda;
-import static org.onosproject.net.flow.criteria.Criteria.matchOchSignalType;
-import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupChannelSpacing;
-import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupGridType;
-import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOchSignalType;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.List;
-
+import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
@@ -36,6 +28,11 @@ import org.onosproject.core.DefaultGroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Lambda;
import org.onosproject.net.PortNumber;
+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.DefaultFlowEntry;
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.DefaultTrafficSelector;
@@ -47,6 +44,7 @@ import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.openflow.controller.Dpid;
+import org.onosproject.openflow.controller.ExtensionInterpreter;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
@@ -55,13 +53,13 @@ import org.projectfloodlight.openflow.protocol.action.OFActionCircuit;
import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
import org.projectfloodlight.openflow.protocol.action.OFActionGroup;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
-import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
import org.projectfloodlight.openflow.protocol.action.OFActionPopMpls;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlDst;
import org.projectfloodlight.openflow.protocol.action.OFActionSetDlSrc;
import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
import org.projectfloodlight.openflow.protocol.action.OFActionSetNwDst;
import org.projectfloodlight.openflow.protocol.action.OFActionSetNwSrc;
+import org.projectfloodlight.openflow.protocol.action.OFActionSetQueue;
import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanPcp;
import org.projectfloodlight.openflow.protocol.action.OFActionSetVlanVid;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
@@ -75,7 +73,6 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmOchSigidBasic;
import org.projectfloodlight.openflow.protocol.ver13.OFFactoryVer13;
import org.projectfloodlight.openflow.types.CircuitSignalID;
-import org.projectfloodlight.openflow.types.EthType;
import org.projectfloodlight.openflow.types.IPv4Address;
import org.projectfloodlight.openflow.types.IPv6Address;
import org.projectfloodlight.openflow.types.Masked;
@@ -87,7 +84,14 @@ import org.projectfloodlight.openflow.types.U8;
import org.projectfloodlight.openflow.types.VlanPcp;
import org.slf4j.Logger;
-import com.google.common.collect.Lists;
+import java.util.List;
+
+import static org.onosproject.net.flow.criteria.Criteria.matchLambda;
+import static org.onosproject.net.flow.criteria.Criteria.matchOchSignalType;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupChannelSpacing;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupGridType;
+import static org.onosproject.provider.of.flow.impl.OpenFlowValueMapper.lookupOchSignalType;
+import static org.slf4j.LoggerFactory.getLogger;
public class FlowEntryBuilder {
private final Logger log = getLogger(getClass());
@@ -108,7 +112,9 @@ public class FlowEntryBuilder {
private final FlowType type;
- public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry) {
+ private final DriverService driverService;
+
+ public FlowEntryBuilder(Dpid dpid, OFFlowStatsEntry entry, DriverService driverService) {
this.stat = entry;
this.match = entry.getMatch();
this.instructions = getInstructions(entry);
@@ -116,9 +122,10 @@ public class FlowEntryBuilder {
this.removed = null;
this.flowMod = null;
this.type = FlowType.STAT;
+ this.driverService = driverService;
}
- public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed) {
+ public FlowEntryBuilder(Dpid dpid, OFFlowRemoved removed, DriverService driverService) {
this.match = removed.getMatch();
this.removed = removed;
@@ -127,10 +134,10 @@ public class FlowEntryBuilder {
this.stat = null;
this.flowMod = null;
this.type = FlowType.REMOVED;
-
+ this.driverService = driverService;
}
- public FlowEntryBuilder(Dpid dpid, OFFlowMod fm) {
+ public FlowEntryBuilder(Dpid dpid, OFFlowMod fm, DriverService driverService) {
this.match = fm.getMatch();
this.dpid = dpid;
this.instructions = getInstructions(fm);
@@ -138,6 +145,7 @@ public class FlowEntryBuilder {
this.flowMod = fm;
this.stat = null;
this.removed = null;
+ this.driverService = driverService;
}
public FlowEntry build(FlowEntryState... state) {
@@ -309,7 +317,7 @@ public class FlowEntryBuilder {
break;
case SET_FIELD:
OFActionSetField setField = (OFActionSetField) act;
- handleSetField(builder, setField.getField());
+ handleSetField(builder, setField);
break;
case POP_MPLS:
OFActionPopMpls popMpls = (OFActionPopMpls) act;
@@ -365,7 +373,8 @@ public class FlowEntryBuilder {
}
- private void handleSetField(TrafficTreatment.Builder builder, OFOxm<?> oxm) {
+ private void handleSetField(TrafficTreatment.Builder builder, OFActionSetField action) {
+ OFOxm<?> oxm = action.getField();
switch (oxm.getMatchField().id) {
case VLAN_PCP:
@SuppressWarnings("unchecked")
@@ -434,6 +443,13 @@ public class FlowEntryBuilder {
OFOxm<TransportPort> udpsrc = (OFOxm<TransportPort>) oxm;
builder.setUdpSrc(TpPort.tpPort(udpsrc.getValue().getPort()));
break;
+ case TUNNEL_IPV4_DST:
+ DriverHandler driver = getDriver(dpid);
+ ExtensionInterpreter interpreter = driver.behaviour(ExtensionInterpreter.class);
+ if (interpreter != null) {
+ builder.extension(interpreter.mapAction(action), DeviceId.deviceId(Dpid.uri(dpid)));
+ }
+ break;
case ARP_OP:
case ARP_SHA:
case ARP_SPA:
@@ -520,11 +536,7 @@ public class FlowEntryBuilder {
break;
case ETH_TYPE:
int ethType = match.get(MatchField.ETH_TYPE).getValue();
- if (ethType == EthType.VLAN_FRAME.getValue()) {
- builder.matchVlanId(VlanId.ANY);
- } else {
- builder.matchEthType((short) ethType);
- }
+ builder.matchEthType((short) ethType);
break;
case VLAN_VID:
VlanId vlanId = null;
@@ -703,4 +715,11 @@ public class FlowEntryBuilder {
}
return builder.build();
}
+
+ private DriverHandler getDriver(Dpid dpid) {
+ DeviceId deviceId = DeviceId.deviceId(Dpid.uri(dpid));
+ Driver driver = driverService.getDriver(deviceId);
+ DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
+ return handler;
+ }
}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
index e050524a..7eca4920 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
@@ -15,16 +15,13 @@
*/
package org.onosproject.provider.of.flow.impl;
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.Optional;
-
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.Ip6Address;
import org.onlab.packet.Ip6Prefix;
import org.onlab.packet.VlanId;
import org.onosproject.net.OchSignal;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.criteria.Criterion;
@@ -85,6 +82,10 @@ import org.projectfloodlight.openflow.types.VlanPcp;
import org.projectfloodlight.openflow.types.VlanVid;
import org.slf4j.Logger;
+import java.util.Optional;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
/**
* Builder for OpenFlow flow mods based on FlowRules.
*/
@@ -96,6 +97,7 @@ public abstract class FlowModBuilder {
private final FlowRule flowRule;
private final TrafficSelector selector;
protected final Long xid;
+ protected final Optional<DriverService> driverService;
/**
* Creates a new flow mod builder.
@@ -107,12 +109,13 @@ public abstract class FlowModBuilder {
*/
public static FlowModBuilder builder(FlowRule flowRule,
OFFactory factory,
- Optional<Long> xid) {
+ Optional<Long> xid,
+ Optional<DriverService> driverService) {
switch (factory.getVersion()) {
case OF_10:
- return new FlowModBuilderVer10(flowRule, factory, xid);
+ return new FlowModBuilderVer10(flowRule, factory, xid, driverService);
case OF_13:
- return new FlowModBuilderVer13(flowRule, factory, xid);
+ return new FlowModBuilderVer13(flowRule, factory, xid, driverService);
default:
throw new UnsupportedOperationException(
"No flow mod builder for protocol version " + factory.getVersion());
@@ -126,12 +129,13 @@ public abstract class FlowModBuilder {
* @param factory the OpenFlow factory to use to build the flow mod
* @param xid the transaction ID
*/
- protected FlowModBuilder(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
+ protected FlowModBuilder(FlowRule flowRule, OFFactory factory, Optional<Long> xid,
+ Optional<DriverService> driverService) {
this.factory = factory;
this.flowRule = flowRule;
this.selector = flowRule.selector();
this.xid = xid.orElse(0L);
-
+ this.driverService = driverService;
}
/**
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
index f77819d5..c7898414 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer10.java
@@ -17,6 +17,7 @@ package org.onosproject.provider.of.flow.impl;
import org.onlab.packet.Ip4Address;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.instructions.Instruction;
@@ -68,8 +69,9 @@ public class FlowModBuilderVer10 extends FlowModBuilder {
* @param xid the transaction ID
*/
protected FlowModBuilderVer10(FlowRule flowRule,
- OFFactory factory, Optional<Long> xid) {
- super(flowRule, factory, xid);
+ OFFactory factory, Optional<Long> xid,
+ Optional<DriverService> driverService) {
+ super(flowRule, factory, xid, driverService);
this.treatment = flowRule.treatment();
}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
index 64b4360a..a99aa817 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilderVer13.java
@@ -18,10 +18,16 @@ package org.onosproject.provider.of.flow.impl;
import com.google.common.collect.Lists;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.OchSignal;
import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.ExtensionInstruction;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
@@ -34,15 +40,16 @@ import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsBosInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
-import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModTunnelIdInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction;
import org.onosproject.net.flow.instructions.L4ModificationInstruction.ModTransportPortInstruction;
+import org.onosproject.openflow.controller.ExtensionInterpreter;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFlowAdd;
import org.projectfloodlight.openflow.protocol.OFFlowDelete;
@@ -88,6 +95,7 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
private static final int OFPCML_NO_BUFFER = 0xffff;
private final TrafficTreatment treatment;
+ private final DeviceId deviceId;
/**
* Constructor for a flow mod builder for OpenFlow 1.3.
@@ -96,10 +104,12 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
* @param factory the OpenFlow factory to use to build the flow mod
* @param xid the transaction ID
*/
- protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid) {
- super(flowRule, factory, xid);
+ protected FlowModBuilderVer13(FlowRule flowRule, OFFactory factory, Optional<Long> xid,
+ Optional<DriverService> driverService) {
+ super(flowRule, factory, xid, driverService);
this.treatment = flowRule.treatment();
+ this.deviceId = flowRule.deviceId();
}
@Override
@@ -256,6 +266,10 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
//FIXME: should not occur here.
tableFound = true;
break;
+ case EXTENSION:
+ actions.add(buildExtensionAction(((Instructions.ExtensionInstructionWrapper) i)
+ .extensionInstruction()));
+ break;
default:
log.warn("Instruction type {} not yet implemented.", i.type());
}
@@ -467,4 +481,20 @@ public class FlowModBuilderVer13 extends FlowModBuilder {
return null;
}
+ private OFAction buildExtensionAction(ExtensionInstruction i) {
+ if (!driverService.isPresent()) {
+ log.error("No driver service present");
+ return null;
+ }
+ Driver driver = driverService.get().getDriver(deviceId);
+ if (driver.hasBehaviour(ExtensionInterpreter.class)) {
+ DefaultDriverHandler handler =
+ new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
+ ExtensionInterpreter interpreter = handler.behaviour(ExtensionInterpreter.class);
+ return interpreter.mapInstruction(factory(), i);
+ }
+
+ return null;
+ }
+
}
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
index 487cae96..d5186fa9 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/NewAdaptiveFlowStatsCollector.java
@@ -16,21 +16,10 @@
package org.onosproject.provider.of.flow.impl;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
-
import org.onosproject.net.flow.DefaultTypedFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
@@ -47,9 +36,19 @@ import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.TableId;
import org.slf4j.Logger;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.groupedThreads;
-import static org.onosproject.net.flow.TypedStoredFlowEntry.*;
+import static org.onosproject.net.flow.TypedStoredFlowEntry.FlowLiveType;
import static org.slf4j.LoggerFactory.getLogger;
/**
@@ -232,7 +231,8 @@ public class NewAdaptiveFlowStatsCollector {
// send openflow flow stats request message with getting the specific flow entry(fe) to a given switch sw
private void ofFlowStatsRequestFlowSend(FlowEntry fe) {
// set find match
- Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty()).buildMatch();
+ Match match = FlowModBuilder.builder(fe, sw.factory(), Optional.empty(),
+ Optional.empty()).buildMatch();
// set find tableId
TableId tableId = TableId.of(fe.tableId());
// set output port
diff --git a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index 6374ca55..b37cb42c 100644
--- a/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/framework/src/onos/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -21,7 +21,6 @@ import com.google.common.cache.RemovalCause;
import com.google.common.cache.RemovalNotification;
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;
import org.apache.felix.scr.annotations.Deactivate;
@@ -32,6 +31,7 @@ import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.CompletedBatchOperation;
import org.onosproject.net.flow.DefaultTableStatisticsEntry;
import org.onosproject.net.flow.FlowEntry;
@@ -61,12 +61,12 @@ import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowRemoved;
import org.projectfloodlight.openflow.protocol.OFFlowStatsReply;
-import org.projectfloodlight.openflow.protocol.OFTableStatsReply;
-import org.projectfloodlight.openflow.protocol.OFTableStatsEntry;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFPortStatus;
import org.projectfloodlight.openflow.protocol.OFStatsReply;
import org.projectfloodlight.openflow.protocol.OFStatsType;
+import org.projectfloodlight.openflow.protocol.OFTableStatsEntry;
+import org.projectfloodlight.openflow.protocol.OFTableStatsReply;
import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
import org.projectfloodlight.openflow.protocol.errormsg.OFFlowModFailedErrorMsg;
import org.slf4j.Logger;
@@ -106,6 +106,9 @@ public class OpenFlowRuleProvider extends AbstractProvider
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService cfgService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
private static final int DEFAULT_POLL_FREQUENCY = 5;
@Property(name = "flowPollFrequency", intValue = DEFAULT_POLL_FREQUENCY,
label = "Frequency (in seconds) for polling flow statistics")
@@ -269,7 +272,7 @@ public class OpenFlowRuleProvider extends AbstractProvider
return;
}
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
- Optional.empty()).buildFlowAdd());
+ Optional.empty(), Optional.of(driverService)).buildFlowAdd());
if (adaptiveFlowSampling) {
// Add TypedFlowEntry to deviceFlowEntries in NewAdaptiveFlowStatsCollector
@@ -298,7 +301,7 @@ public class OpenFlowRuleProvider extends AbstractProvider
return;
}
sw.sendMsg(FlowModBuilder.builder(flowRule, sw.factory(),
- Optional.empty()).buildFlowDel());
+ Optional.empty(), Optional.of(driverService)).buildFlowDel());
if (adaptiveFlowSampling) {
// Remove TypedFlowEntry to deviceFlowEntries in NewAdaptiveFlowStatsCollector
@@ -334,7 +337,8 @@ public class OpenFlowRuleProvider extends AbstractProvider
continue;
}
FlowModBuilder builder =
- FlowModBuilder.builder(fbe.target(), sw.factory(), Optional.of(batch.id()));
+ FlowModBuilder.builder(fbe.target(), sw.factory(),
+ Optional.of(batch.id()), Optional.of(driverService));
NewAdaptiveFlowStatsCollector collector = afsCollectors.get(dpid);
switch (fbe.operator()) {
case ADD:
@@ -423,7 +427,7 @@ public class OpenFlowRuleProvider extends AbstractProvider
case FLOW_REMOVED:
OFFlowRemoved removed = (OFFlowRemoved) msg;
- FlowEntry fr = new FlowEntryBuilder(dpid, removed).build();
+ FlowEntry fr = new FlowEntryBuilder(dpid, removed, driverService).build();
providerService.flowRemoved(fr);
if (adaptiveFlowSampling) {
@@ -474,7 +478,7 @@ public class OpenFlowRuleProvider extends AbstractProvider
InternalCacheEntry entry =
pendingBatches.getIfPresent(msg.getXid());
if (entry != null) {
- entry.appendFailure(new FlowEntryBuilder(dpid, fm).build());
+ entry.appendFailure(new FlowEntryBuilder(dpid, fm, driverService).build());
} else {
log.error("No matching batch for this error: {}", error);
}
@@ -501,7 +505,7 @@ public class OpenFlowRuleProvider extends AbstractProvider
DeviceId did = DeviceId.deviceId(Dpid.uri(dpid));
List<FlowEntry> flowEntries = replies.getEntries().stream()
- .map(entry -> new FlowEntryBuilder(dpid, entry).build())
+ .map(entry -> new FlowEntryBuilder(dpid, entry, driverService).build())
.collect(Collectors.toList());
if (adaptiveFlowSampling) {
diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupBucketEntryBuilder.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupBucketEntryBuilder.java
index b9de7c0f..d3a23782 100644
--- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupBucketEntryBuilder.java
+++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupBucketEntryBuilder.java
@@ -115,6 +115,10 @@ public class GroupBucketEntryBuilder {
DefaultGroupBucket.createFailoverGroupBucket(treatment,
port, groupId);
break;
+ case ALL:
+ groupBucket =
+ DefaultGroupBucket.createAllGroupBucket(treatment);
+ break;
default:
log.error("Unsupported Group type : {}", type);
}
diff --git a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index 8acf08ee..5783c842 100644
--- a/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/framework/src/onos/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -252,7 +252,7 @@ public class OpenFlowGroupProvider extends AbstractProvider implements GroupProv
private GroupDescription.Type getGroupType(OFGroupType type) {
switch (type) {
case ALL:
- return GroupDescription.Type.ALL;
+ return GroupDescription.Type.ALL;
case INDIRECT:
return GroupDescription.Type.INDIRECT;
case SELECT:
diff --git a/framework/src/onos/providers/ovsdb/host/src/main/java/org/onosproject/ovsdb/provider/host/OvsdbHostProvider.java b/framework/src/onos/providers/ovsdb/host/src/main/java/org/onosproject/ovsdb/provider/host/OvsdbHostProvider.java
index 0e3e1564..031fda78 100644
--- a/framework/src/onos/providers/ovsdb/host/src/main/java/org/onosproject/ovsdb/provider/host/OvsdbHostProvider.java
+++ b/framework/src/onos/providers/ovsdb/host/src/main/java/org/onosproject/ovsdb/provider/host/OvsdbHostProvider.java
@@ -111,7 +111,7 @@ public class OvsdbHostProvider extends AbstractProvider implements HostProvider
}
switch (event.type()) {
case PORT_ADDED:
- HostId hostId = HostId.hostId(subject.hwAddress(), null);
+ HostId hostId = HostId.hostId(subject.hwAddress(), VlanId.vlanId());
DeviceId deviceId = DeviceId.deviceId(uri(subject.dpid().value()));
PortNumber portNumber = PortNumber.portNumber(subject
.portNumber().value(), subject.portName().value());
@@ -127,7 +127,7 @@ public class OvsdbHostProvider extends AbstractProvider implements HostProvider
providerService.hostDetected(hostId, hostDescription);
break;
case PORT_REMOVED:
- HostId host = HostId.hostId(subject.hwAddress(), null);
+ HostId host = HostId.hostId(subject.hwAddress(), VlanId.vlanId());
providerService.hostVanished(host);
break;
default:
diff --git a/framework/src/onos/tools/build/conf/pom.xml b/framework/src/onos/tools/build/conf/pom.xml
index 29e4dea0..d56168f2 100644
--- a/framework/src/onos/tools/build/conf/pom.xml
+++ b/framework/src/onos/tools/build/conf/pom.xml
@@ -27,7 +27,7 @@
<groupId>org.onosproject</groupId>
<artifactId>onos-build-conf</artifactId>
- <version>1.1</version>
+ <version>1.1-SNAPSHOT</version>
<description>Various ONOS build settings</description>
<properties>
diff --git a/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml b/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml
index 1bb3b0bf..e04479c5 100644
--- a/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml
+++ b/framework/src/onos/tools/build/conf/src/main/resources/onos/checkstyle.xml
@@ -67,9 +67,7 @@
-->
<!-- Checks that a package-info.java file exists for each package. -->
<!-- See http://checkstyle.sf.net/config_javadoc.html#JavadocPackage -->
- <!-- ONOS does not currently supply package level Javadoc information
- in package-info files -->
- <!-- <module name="JavadocPackage"/> -->
+ <module name="JavadocPackage"/>
<!-- Checks whether files end with a new line. -->
<!-- See http://checkstyle.sf.net/config_misc.html#NewlineAtEndOfFile -->
diff --git a/framework/src/onos/tools/build/conf/src/main/resources/onos/suppressions.xml b/framework/src/onos/tools/build/conf/src/main/resources/onos/suppressions.xml
index a71d941f..6d8f1982 100644
--- a/framework/src/onos/tools/build/conf/src/main/resources/onos/suppressions.xml
+++ b/framework/src/onos/tools/build/conf/src/main/resources/onos/suppressions.xml
@@ -29,4 +29,12 @@
<suppress files=".*" checks="HiddenField"/>
<suppress files=".java" checks="NewlineAtEndOfFile"/>
+ <!-- Suppressions for unit testing code -->
+ <suppress checks="JavadocPackage"
+ files=".*/src/test/.*.java"
+ />
+
+ <suppress checks="JavadocPackage"
+ files=".*/thirdparty/.*.java"/>
+
</suppressions>
diff --git a/framework/src/onos/tools/dev/bin/onos-build-selective b/framework/src/onos/tools/dev/bin/onos-build-selective
index ac2dec8e..351c53ac 100755
--- a/framework/src/onos/tools/dev/bin/onos-build-selective
+++ b/framework/src/onos/tools/dev/bin/onos-build-selective
@@ -15,9 +15,11 @@ if [ -n "$projects" ]; then
# Ascertain artifact IDs of the projects to be rebuilt
modulesERE=""
for pd in ${projects//,/ }; do
- artifactId=$(grep -E "^ <artifactId>.*</artifactId>$" ${pd}/pom.xml | \
- sed 's/.[^>]*>//;s/<.*//')
- modulesERE="$modulesERE|$artifactId"
+ if [ -f ${pd}/pom.xml ]; then
+ artifactId=$(grep -E "^ <artifactId>.*</artifactId>$" ${pd}/pom.xml | \
+ sed 's/.[^>]*>//;s/<.*//')
+ modulesERE="$modulesERE|$artifactId"
+ fi
done
modulesERE=${modulesERE#|*}
diff --git a/framework/src/onos/tools/dev/bin/onos-build-selective.exclude b/framework/src/onos/tools/dev/bin/onos-build-selective.exclude
index 1265494e..487f848c 100644
--- a/framework/src/onos/tools/dev/bin/onos-build-selective.exclude
+++ b/framework/src/onos/tools/dev/bin/onos-build-selective.exclude
@@ -6,4 +6,5 @@
.*/cord-gui/.*
.*/jdvue/.*
.*/ovsdb/api/.*
-.*/netconf/flow/.* \ No newline at end of file
+.*/netconf/flow/.*
+.*/vtn/sfcmgr/.* \ No newline at end of file
diff --git a/framework/src/onos/tools/dev/bin/onos-setup-karaf b/framework/src/onos/tools/dev/bin/onos-setup-karaf
index 3323d9d1..cbe62253 100755
--- a/framework/src/onos/tools/dev/bin/onos-setup-karaf
+++ b/framework/src/onos/tools/dev/bin/onos-setup-karaf
@@ -97,13 +97,11 @@ fi
echo "Creating local cluster configs for IP $IP..."
[ -d $STAGE/config ] || mkdir -p $STAGE/config
cat > $STAGE/config/cluster.json <<EOF
- { "ipPrefix": "$SUBNET.*",
- "nodes":[ { "id": "$IP", "ip": "$IP", "tcpPort": 9876 }]}
-EOF
-
-cat > $STAGE/config/tablets.json <<EOF
- { "nodes": [ { "ip": "$IP", "id": "$IP", "tcpPort": 9876 }],
- "partitions": { "p1": [ { "ip": "$IP", "id": "$IP", "tcpPort": 9876 }]}}
+{
+ "name": "default",
+ "nodes": [ {"id": "$IP", "ip": "$IP", "port": 9876 } ],
+ "partitions": [ { "name": "p1", "members": [ "$IP" ] } ]
+}
EOF
if [ "$CLEAN" = "true" ]; then
diff --git a/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovMessageHandler.java b/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovMessageHandler.java
index 7c35cc53..65e3489f 100644
--- a/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovMessageHandler.java
+++ b/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovMessageHandler.java
@@ -33,7 +33,10 @@ import org.onosproject.net.link.LinkService;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.topo.DeviceHighlight;
import org.onosproject.ui.topo.Highlights;
+import org.onosproject.ui.topo.NodeBadge;
+import org.onosproject.ui.topo.NodeBadge.Status;
import org.onosproject.ui.topo.TopoJson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -224,11 +227,26 @@ public class AppUiTopovMessageHandler extends UiMessageHandler {
if (elementOfNote != null && elementOfNote instanceof Device) {
DeviceId devId = (DeviceId) elementOfNote.id();
Set<Link> links = linkService.getDeviceEgressLinks(devId);
- sendHighlights(fromLinks(links, devId));
+ Highlights highlights = fromLinks(links, devId);
+ addDeviceBadge(highlights, devId, links.size());
+ sendHighlights(highlights);
}
// Note: could also process Host, if available
}
+ private void addDeviceBadge(Highlights h, DeviceId devId, int n) {
+ DeviceHighlight dh = new DeviceHighlight(devId.toString());
+ dh.setBadge(createBadge(n));
+ h.add(dh);
+ }
+
+ private NodeBadge createBadge(int n) {
+ Status status = n > 3 ? Status.ERROR : Status.WARN;
+ String noun = n > 3 ? "(critical)" : "(problematic)";
+ String msg = "Egress links: " + n + " " + noun;
+ return NodeBadge.number(status, n, msg);
+ }
+
private Highlights fromLinks(Set<Link> links, DeviceId devId) {
DemoLinkMap linkMap = new DemoLinkMap();
if (links != null) {
diff --git a/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovOverlay.java b/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovOverlay.java
index 98999825..48e75a5a 100644
--- a/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovOverlay.java
+++ b/framework/src/onos/tools/package/archetypes/uitopo/src/main/resources/archetype-resources/src/main/java/AppUiTopovOverlay.java
@@ -18,13 +18,20 @@
*/
package ${package};
+import org.onosproject.net.DeviceId;
import org.onosproject.ui.UiTopoOverlay;
import org.onosproject.ui.topo.ButtonId;
import org.onosproject.ui.topo.PropertyPanel;
import org.onosproject.ui.topo.TopoConstants.CoreButtons;
import org.onosproject.ui.topo.TopoConstants.Glyphs;
-import static org.onosproject.ui.topo.TopoConstants.Properties.*;
+import static org.onosproject.ui.topo.TopoConstants.Properties.FLOWS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.INTENTS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.LATITUDE;
+import static org.onosproject.ui.topo.TopoConstants.Properties.LONGITUDE;
+import static org.onosproject.ui.topo.TopoConstants.Properties.TOPOLOGY_SSCS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.TUNNELS;
+import static org.onosproject.ui.topo.TopoConstants.Properties.VERSION;
/**
* Our topology overlay.
@@ -61,7 +68,7 @@ public class AppUiTopovOverlay extends UiTopoOverlay {
}
@Override
- public void modifyDeviceDetails(PropertyPanel pp) {
+ public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) {
pp.title(MY_DEVICE_TITLE);
pp.removeProps(LATITUDE, LONGITUDE);
diff --git a/framework/src/onos/tools/test/bin/onos-config b/framework/src/onos/tools/test/bin/onos-config
index 348cb839..e37dc3b2 100755
--- a/framework/src/onos/tools/test/bin/onos-config
+++ b/framework/src/onos/tools/test/bin/onos-config
@@ -37,17 +37,6 @@ export ONOS_BOOT_FEATURES="${ONOS_BOOT_FEATURES:-webconsole,onos-api,onos-core,o
# ONOS builtin apps and providers ignited by default
export ONOS_APPS="${ONOS_APPS:-drivers,openflow}"
-# Generate a cluster.json from the ON* environment variables
-CDEF_FILE=/tmp/${remote}.cluster.json
-echo "{ \"ipPrefix\": \"$ONOS_NIC\"," > $CDEF_FILE
-echo " \"nodes\":[" >> $CDEF_FILE
-for node in $(env | sort | egrep "OC[2-9]+" | cut -d= -f2); do
- echo " { \"id\": \"$node\", \"ip\": \"$node\", \"tcpPort\": 9876 }," >> $CDEF_FILE
-done
-echo " { \"id\": \"$OC1\", \"ip\": \"$OC1\", \"tcpPort\": 9876 }" >> $CDEF_FILE
-echo "]}" >> $CDEF_FILE
-scp -q $CDEF_FILE $remote:$ONOS_INSTALL_DIR/config/cluster.json
-
ssh $remote "
echo \"onos.ip = \$(sudo ifconfig | grep $ONOS_NIC | cut -d: -f2 | cut -d\\ -f1)\" \
>> $ONOS_INSTALL_DIR/$KARAF_DIST/etc/system.properties
@@ -66,10 +55,10 @@ ssh $remote "
done
"
-# Generate a default tablets.json from the ON* environment variables
-TDEF_FILE=/tmp/${remote}.tablets.json
-onos-gen-partitions $TDEF_FILE
-scp -q $TDEF_FILE $remote:$ONOS_INSTALL_DIR/config/tablets.json
+# Generate a default cluster.json from the ON* environment variables
+CDEF_FILE=/tmp/${remote}.cluster.json
+onos-gen-partitions $CDEF_FILE
+scp -q $CDEF_FILE $remote:$ONOS_INSTALL_DIR/config/cluster.json
# Copy tools/package/config/ to remote
scp -qr ${ONOS_ROOT}/tools/package/config/ $remote:$ONOS_INSTALL_DIR/
diff --git a/framework/src/onos/tools/test/bin/onos-execute-expect b/framework/src/onos/tools/test/bin/onos-execute-expect
new file mode 100755
index 00000000..6ad95699
--- /dev/null
+++ b/framework/src/onos/tools/test/bin/onos-execute-expect
@@ -0,0 +1,27 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Executes a command on the given ONOS instance and matches the output
+# to the passed one.
+# First argument is the IP address of the machine to run the command on,
+# then you pass the command and it's arguments if needed, then --expect and
+# after it the string of what the output should be.
+# Example:
+# onos-execute-expect 1.1.1.1 fooCommand fooParamenter --expect fooOutputString
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+
+aux=/tmp/stc-$$.log
+trap "rm -f $aux 2>/dev/null" EXIT
+ip=$1
+cmd=""
+for a in ${*:2}; do shift; if [ "$a" = "--expect" ]; then break; fi; cmd="$cmd $a"; done
+expect="${@: -1}"
+onos $ip $cmd > $aux
+cat $aux
+grep -q $expect $aux && echo "expected value found" && exit 0
+exit 1
+
+
diff --git a/framework/src/onos/tools/test/bin/onos-gen-partitions b/framework/src/onos/tools/test/bin/onos-gen-partitions
index a2558392..35195b04 100755
--- a/framework/src/onos/tools/test/bin/onos-gen-partitions
+++ b/framework/src/onos/tools/test/bin/onos-gen-partitions
@@ -23,22 +23,27 @@ def get_OC_vars():
return sorted(vars, key=alphanum_key)
def get_nodes(vars, port=9876):
- node = lambda k: { 'id': k, 'ip': k, 'tcpPort': port }
+ node = lambda k: { 'id': k, 'ip': k, 'port': port }
return [ node(environ[v]) for v in vars ]
def generate_permutations(nodes, k):
l = deque(nodes)
- perms = {}
+ perms = []
for i in range(1, len(nodes)+1):
- perms['p%d' % i] = list(l)[:k]
+ part = {
+ 'name': 'p%d' % i,
+ 'members': list(l)[:k]
+ }
+ perms.append(part)
l.rotate(-1)
- return OrderedDict(sorted(perms.iteritems(), key=lambda (k, v): alphanum_key(k)))
+ return perms
if __name__ == '__main__':
vars = get_OC_vars()
nodes = get_nodes(vars)
- partitions = generate_permutations(nodes, 3)
- data = {
+ partitions = generate_permutations([v.get('id') for v in nodes], 3)
+ data = {
+ 'name': 'default',
'nodes': nodes,
'partitions': partitions
}
diff --git a/framework/src/onos/tools/test/bin/onos-secure-ssh b/framework/src/onos/tools/test/bin/onos-secure-ssh
index a3980e17..6d898ee8 100755
--- a/framework/src/onos/tools/test/bin/onos-secure-ssh
+++ b/framework/src/onos/tools/test/bin/onos-secure-ssh
@@ -10,7 +10,8 @@ nodes=$(env | sort | egrep "OC[0-9]+" | cut -d= -f2)
for node in $nodes; do
# Prune the node entry from the known hosts file since server key changes
- ssh-keygen -f "$HOME/.ssh/known_hosts" -R [$node]:8101
+ ssh-keygen -f "$HOME/.ssh/known_hosts" -R [$node]:8101 ||
+ ( echo "Failed to remove key from known_hosts" >&2 && exit 1 )
# Setup passwordless login for the local user on the remote node
ssh $ONOS_USER@$node "
diff --git a/framework/src/onos/tools/test/bin/stc b/framework/src/onos/tools/test/bin/stc
index 8737cf3f..60a1720e 100755
--- a/framework/src/onos/tools/test/bin/stc
+++ b/framework/src/onos/tools/test/bin/stc
@@ -20,6 +20,7 @@ scenario=${1:-smoke}
# If stcColor is not set, we will enable color if this is an interactive session
[ -t 1 ] && interactive=true || interactive=false
+[ -t 1 ] && notInteractive=false || notInteractive=true
# stc requires that ONOS_USE_SSH=true, but we will store the old value and reset it after
sshSet=$([ -z ${ONOS_USE_SSH+x} ]) && oldSSH=$ONOS_USE_SSH
@@ -27,7 +28,8 @@ export ONOS_USE_SSH=true
# Run stc
[ -z "$stcDebug" ] && DEBUG_OPTS=""
-stcColor=${stcColor:-$interactive} java $DEBUG_OPTS -jar $JAR $scenario "$@"
+stcColor=${stcColor:-$interactive} stcDumpLogs=${stcDumpLogs:-$notInteractive} \
+ java $DEBUG_OPTS -jar $JAR $scenario "$@"
# Reset the old value of ONOS_USE_SSH
[ $sshSet ] && export ONOS_USE_SSH=oldSSH || unset ONOS_USE_SSH
diff --git a/framework/src/onos/tools/test/scenarios/dist-test-seq.xml b/framework/src/onos/tools/test/scenarios/dist-test-seq.xml
new file mode 100644
index 00000000..2e99fa27
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/dist-test-seq.xml
@@ -0,0 +1,67 @@
+<!--
+ ~ Copyright 20${OCI}5 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.
+ -->
+
+<scenario name="dist-test"
+ description="ONOS distributed primitives setup">
+ <group name="Distributed-Primitives">
+ <!--<import file="${ONOS_SCENARIOS}/prerequisites.xml"/>-->
+
+ <!--<import file="${ONOS_SCENARIOS}/setup.xml"/>
+ <dependency name="Setup" requires="Prerequisites"/>-->
+
+ <sequential var="${OC#}" starts="Distributed-App-${#}" ends="Check-Distributed-Exceptions-${#-1}">
+ <step name="Distributed-App-${#}"
+ requires="Setup"
+ exec="onos ${OC#} app activate org.onosproject.distributedprimitives"/>
+
+ <step name="Test-Counter-Increment-${#}"
+ requires="Distributed-App-${#}"
+ exec="onos-execute-expect ${OC#} counter-test-increment fooCounter 5 --expect updated"/>
+
+ <step name="Test-Add-${#}"
+ requires="Distributed-App-${#}"
+ exec="onos-execute-expect ${OC#} set-test-add fooSet foo --expect added"/>
+
+ <step name="Test-Get-${#}"
+ requires="Test-Add-${#}"
+ exec="onos-execute-expect ${OC#} set-test-get fooSet foo --expect contains"/>
+
+ <step name="Test-Remove-${#}"
+ requires="Test-Get-${#}"
+ exec="onos-execute-expect ${OC#} set-test-remove fooSet foo --expect removed"/>
+
+ <step name="Test-Add-Multiple-${#}"
+ requires="Test-Remove-${#}"
+ exec="onos-execute-expect ${OC#} set-test-add fooSet foo foo2 foo3 --expect added"/>
+
+ <step name="Test-Get-Multiple-${#}"
+ requires="Test-Add-Multiple-${#}"
+ exec="onos-execute-expect ${OC#} set-test-get fooSet foo foo2 foo3 --expect contains"/>
+
+ <step name="Test-Remove-Multiple-${#}"
+ requires="Test-Get-Multiple-${#}"
+ exec="onos-execute-expect ${OC#} set-test-remove fooSet foo foo2 foo3 --expect removed"/>
+
+ <step name="Sleep-${#}"
+ exec="sleep 2"
+ requires="Test-Remove-Multiple-${#}"/>
+ <!--Check with check logs-->
+ <step name="Check-Distributed-Exceptions-${#}"
+ exec="onos-check-logs ${OC#}"
+ requires="Sleep-${#}"/>
+ </sequential>
+ </group>
+</scenario> \ No newline at end of file
diff --git a/framework/src/onos/tools/test/scenarios/dist-test.xml b/framework/src/onos/tools/test/scenarios/dist-test.xml
new file mode 100644
index 00000000..5e7dab0b
--- /dev/null
+++ b/framework/src/onos/tools/test/scenarios/dist-test.xml
@@ -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.
+-->
+
+<scenario name="dist-test"
+ description="ONOS distributed primitives setup">
+ <group name="Distributed-Primitives">
+
+ <!--<import file="${ONOS_SCENARIOS}/setup.xml"/>
+ <dependency name="Setup" requires="Prerequisites"/>-->
+
+ <step name="Distributed-App"
+ requires="Setup"
+ exec="onos ${OCI} app activate org.onosproject.distributedprimitives"/>
+
+ <step name="Test-Counter-Increment"
+ requires="Distributed-App"
+ exec="onos-execute-expect ${OCI} counter-test-increment fooCounter 5 --expect updated"/>
+
+ <step name="Test-Add"
+ requires="Distributed-App"
+ exec="onos-execute-expect ${OCI} set-test-add fooSet foo --expect added"/>
+
+ <step name="Test-Get"
+ requires="Test-Add"
+ exec="onos-execute-expect ${OCI} set-test-get fooSet foo --expect contains"/>
+
+ <step name="Test-Remove"
+ requires="Test-Get"
+ exec="onos-execute-expect ${OCI} set-test-remove fooSet foo --expect removed"/>
+
+ <step name="Test-Add-Multiple"
+ requires="Test-Remove"
+ exec="onos-execute-expect ${OCI} set-test-add fooSet foo foo2 foo3 --expect added"/>
+
+ <step name="Test-Get-Multiple"
+ requires="Test-Add-Multiple"
+ exec="onos-execute-expect ${OCI} set-test-get fooSet foo foo2 foo3 --expect contains"/>
+
+ <step name="Test-Remove-Multiple"
+ requires="Test-Get-Multiple"
+ exec="onos-execute-expect ${OCI} set-test-remove fooSet foo foo2 foo3 --expect removed"/>
+
+ <step name="Test-Map-Put"
+ requires="Distributed-App"
+ exec="onos-execute-expect ${OCI} transactional-map-test-put 1 foo --expect Created"/>
+
+ <step name="Test-Map-Get"
+ requires="Test-Map-Put"
+ exec="onos-execute-expect ${OCI} transactional-map-test-get Key1 --expect Key-value"/>
+
+ <!--Check with check logs-->
+ <step name="Check-Distributed-Exceptions"
+ exec="onos-check-logs ${OCI}"
+ requires="Test-Map-Get"/>
+ </group>
+</scenario>
+
diff --git a/framework/src/onos/tools/test/topos/opticalUtils.py b/framework/src/onos/tools/test/topos/opticalUtils.py
index a1ae834b..5d955e51 100644
--- a/framework/src/onos/tools/test/topos/opticalUtils.py
+++ b/framework/src/onos/tools/test/topos/opticalUtils.py
@@ -344,7 +344,10 @@ class LINCSwitch(OpticalSwitch):
continue
portDict = {}
portDict[ 'port' ] = port
- portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER'
+ portType = 'COPPER'
+ if isinstance(intf.link, LINCLink):
+ portType = 'OCH' if intf.link.isCrossConnect else 'OMS'
+ portDict[ 'type' ] = portType
intfList = [ intf.link.intf1, intf.link.intf2 ]
intfList.remove(intf)
portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0
@@ -787,7 +790,10 @@ class LINCIntf(OpticalIntf):
configDict = {}
configDict[ 'port' ] = self.port
configDict[ 'speed' ] = self.speed
- configDict[ 'type' ] = 'FIBER'
+ portType = 'COPPER'
+ if isinstance(self.link, LINCLink):
+ portType = 'OCH' if self.link.isCrossConnect else 'OMS'
+ configDict[ 'type' ] = portType
return configDict
def config(self, *args, **kwargs):
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/Ethernet.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
index 003c1772..9ab5cab1 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/packet/Ethernet.java
@@ -18,6 +18,12 @@
package org.onlab.packet;
+import org.onlab.packet.ndp.NeighborAdvertisement;
+import org.onlab.packet.ndp.NeighborSolicitation;
+import org.onlab.packet.ndp.Redirect;
+import org.onlab.packet.ndp.RouterAdvertisement;
+import org.onlab.packet.ndp.RouterSolicitation;
+
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.HashMap;
@@ -531,27 +537,114 @@ public class Ethernet extends BasePacket {
sb.append("\nnw_proto: ");
sb.append(p.getProtocol());
- if (pkt instanceof TCP) {
- sb.append("\ntp_src: ");
- sb.append(((TCP) pkt).getSourcePort());
- sb.append("\ntp_dst: ");
- sb.append(((TCP) pkt).getDestinationPort());
-
- } else if (pkt instanceof UDP) {
- sb.append("\ntp_src: ");
- sb.append(((UDP) pkt).getSourcePort());
- sb.append("\ntp_dst: ");
- sb.append(((UDP) pkt).getDestinationPort());
+ IPacket payload = pkt.getPayload();
+ if (payload != null) {
+ if (payload instanceof TCP) {
+ sb.append("\ntp_src: ");
+ sb.append(((TCP) payload).getSourcePort());
+ sb.append("\ntp_dst: ");
+ sb.append(((TCP) payload).getDestinationPort());
+
+ } else if (payload instanceof UDP) {
+ sb.append("\ntp_src: ");
+ sb.append(((UDP) payload).getSourcePort());
+ sb.append("\ntp_dst: ");
+ sb.append(((UDP) payload).getDestinationPort());
+ } else if (payload instanceof ICMP) {
+ final ICMP icmp = (ICMP) payload;
+ sb.append("\nicmp_type: ");
+ sb.append(icmp.getIcmpType());
+ sb.append("\nicmp_code: ");
+ sb.append(icmp.getIcmpCode());
+ }
}
-
- if (pkt instanceof ICMP) {
- final ICMP icmp = (ICMP) pkt;
- sb.append("\nicmp_type: ");
- sb.append(icmp.getIcmpType());
- sb.append("\nicmp_code: ");
- sb.append(icmp.getIcmpCode());
+ } else if (pkt instanceof IPv6) {
+ final IPv6 ipv6 = (IPv6) pkt;
+ sb.append("\nipv6_src: ");
+ sb.append(Ip6Address.valueOf(ipv6.getSourceAddress()).toString());
+ sb.append("\nipv6_dst: ");
+ sb.append(Ip6Address.valueOf(ipv6.getDestinationAddress()).toString());
+ sb.append("\nipv6_proto: ");
+ sb.append(ipv6.getNextHeader());
+
+ IPacket payload = pkt.getPayload();
+ if (payload != null && payload instanceof ICMP6) {
+ final ICMP6 icmp6 = (ICMP6) payload;
+ sb.append("\nicmp6_type: ");
+ sb.append(icmp6.getIcmpType());
+ sb.append("\nicmp6_code: ");
+ sb.append(icmp6.getIcmpCode());
+
+ payload = payload.getPayload();
+ if (payload != null) {
+ if (payload instanceof NeighborSolicitation) {
+ final NeighborSolicitation ns = (NeighborSolicitation) payload;
+ sb.append("\nns_target_addr: ");
+ sb.append(Ip6Address.valueOf(ns.getTargetAddress()).toString());
+ ns.getOptions().forEach(option -> {
+ sb.append("\noption_type: ");
+ sb.append(option.type());
+ sb.append("\noption_data: ");
+ sb.append(bytesToHex(option.data()));
+ });
+ } else if (payload instanceof NeighborAdvertisement) {
+ final NeighborAdvertisement na = (NeighborAdvertisement) payload;
+ sb.append("\nna_target_addr: ");
+ sb.append(Ip6Address.valueOf(na.getTargetAddress()).toString());
+ sb.append("\nna_solicited_flag: ");
+ sb.append(na.getSolicitedFlag());
+ sb.append("\nna_router_flag: ");
+ sb.append(na.getRouterFlag());
+ sb.append("\nna_override_flag: ");
+ sb.append(na.getOverrideFlag());
+ na.getOptions().forEach(option -> {
+ sb.append("\noption_type: ");
+ sb.append(option.type());
+ sb.append("\noption_data: ");
+ sb.append(bytesToHex(option.data()));
+ });
+ } else if (payload instanceof RouterSolicitation) {
+ final RouterSolicitation rs = (RouterSolicitation) payload;
+ sb.append("\nrs");
+ rs.getOptions().forEach(option -> {
+ sb.append("\noption_type: ");
+ sb.append(option.type());
+ sb.append("\noption_data: ");
+ sb.append(bytesToHex(option.data()));
+ });
+ } else if (payload instanceof RouterAdvertisement) {
+ final RouterAdvertisement ra = (RouterAdvertisement) payload;
+ sb.append("\nra_hop_limit: ");
+ sb.append(ra.getCurrentHopLimit());
+ sb.append("\nra_mflag: ");
+ sb.append(ra.getMFlag());
+ sb.append("\nra_oflag: ");
+ sb.append(ra.getOFlag());
+ sb.append("\nra_reachable_time: ");
+ sb.append(ra.getReachableTime());
+ sb.append("\nra_retransmit_time: ");
+ sb.append(ra.getRetransmitTimer());
+ sb.append("\nra_router_lifetime: ");
+ sb.append(ra.getRouterLifetime());
+ ra.getOptions().forEach(option -> {
+ sb.append("\noption_type: ");
+ sb.append(option.type());
+ sb.append("\noption_data: ");
+ sb.append(bytesToHex(option.data()));
+ });
+ } else if (payload instanceof Redirect) {
+ final Redirect rd = (Redirect) payload;
+ sb.append("\nrd_target_addr: ");
+ sb.append(Ip6Address.valueOf(rd.getTargetAddress()).toString());
+ rd.getOptions().forEach(option -> {
+ sb.append("\noption_type: ");
+ sb.append(option.type());
+ sb.append("\noption_data: ");
+ sb.append(bytesToHex(option.data()));
+ });
+ }
+ }
}
-
} else if (pkt instanceof DHCP) {
sb.append("\ndhcp packet");
} else if (pkt instanceof Data) {
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Bandwidth.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
index 349e660f..60806568 100644
--- a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/Bandwidth.java
@@ -42,6 +42,17 @@ public final class Bandwidth implements RichComparable<Bandwidth> {
}
/**
+ * Creates a new instance with given bandwidth.
+ *
+ * @param v bandwidth value
+ * @param unit {@link DataRateUnit} of {@code v}
+ * @return {@link Bandwidth} instance with given bandwidth
+ */
+ public static Bandwidth of(double v, DataRateUnit unit) {
+ return new Bandwidth(unit.toBitsPerSecond(v));
+ }
+
+ /**
* Creates a new instance with given bandwidth in bps.
*
* @param bps bandwidth value to be assigned
diff --git a/framework/src/onos/utils/misc/src/main/java/org/onlab/util/DataRateUnit.java b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/DataRateUnit.java
new file mode 100644
index 00000000..d49ed7b5
--- /dev/null
+++ b/framework/src/onos/utils/misc/src/main/java/org/onlab/util/DataRateUnit.java
@@ -0,0 +1,64 @@
+package org.onlab.util;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Data rate unit.
+ */
+@Beta
+public enum DataRateUnit {
+ /**
+ * Bit per second.
+ */
+ BPS(1L),
+ /**
+ * Kilobit per second.
+ * (Decimal/SI)
+ */
+ KBPS(1_000L),
+ /**
+ * Megabit per second.
+ * (Decimal/SI)
+ */
+ MBPS(1_000_000L),
+ /**
+ * Gigabit per second.
+ * (Decimal/SI)
+ */
+ GBPS(1_000_000_000L);
+
+ private final long multiplier;
+
+ DataRateUnit(long multiplier) {
+ this.multiplier = multiplier;
+ }
+
+ /**
+ * Returns the multiplier to use, when converting value of this unit to bps.
+ *
+ * @return multiplier
+ */
+ public long multiplier() {
+ return multiplier;
+ }
+
+ /**
+ * Converts given value in this unit to bits per seconds.
+ *
+ * @param v data rate value
+ * @return {@code v} in bits per seconds
+ */
+ public long toBitsPerSecond(long v) {
+ return v * multiplier;
+ }
+
+ /**
+ * Converts given value in this unit to bits per seconds.
+ *
+ * @param v data rate value
+ * @return {@code v} in bits per seconds
+ */
+ public double toBitsPerSecond(double v) {
+ return v * multiplier;
+ }
+}
diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/AbstractAccumulatorTest.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/AbstractAccumulatorTest.java
index db7224ad..8a409c3d 100644
--- a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/AbstractAccumulatorTest.java
+++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/AbstractAccumulatorTest.java
@@ -31,7 +31,10 @@ import static org.onlab.junit.TestTools.assertAfter;
public class AbstractAccumulatorTest {
- private final ManuallyAdvancingTimer timer = new ManuallyAdvancingTimer();
+ private final ManuallyAdvancingTimer timer = new ManuallyAdvancingTimer(true);
+
+ private static final int LONG_REAL_TIME_DELAY = 30;
+ private static final int SHORT_REAL_TIME_DELAY = 5;
@Test
@@ -52,7 +55,7 @@ public class AbstractAccumulatorTest {
accumulator.add(new TestItem("d"));
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("e"));
- timer.advanceTimeMillis(20, 10);
+ timer.advanceTimeMillis(20, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "abcde", accumulator.batch);
}
@@ -61,16 +64,16 @@ public class AbstractAccumulatorTest {
public void timeTrigger() {
TestAccumulator accumulator = new TestAccumulator();
accumulator.add(new TestItem("a"));
- timer.advanceTimeMillis(30, 1);
+ timer.advanceTimeMillis(30, SHORT_REAL_TIME_DELAY);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("b"));
- timer.advanceTimeMillis(30, 1);
+ timer.advanceTimeMillis(30, SHORT_REAL_TIME_DELAY);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("c"));
- timer.advanceTimeMillis(30, 1);
+ timer.advanceTimeMillis(30, SHORT_REAL_TIME_DELAY);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("d"));
- timer.advanceTimeMillis(10, 10);
+ timer.advanceTimeMillis(10, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "abcd", accumulator.batch);
}
@@ -81,7 +84,7 @@ public class AbstractAccumulatorTest {
accumulator.add(new TestItem("a"));
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("b"));
- timer.advanceTimeMillis(70, 10);
+ timer.advanceTimeMillis(70, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "ab", accumulator.batch);
}
@@ -93,10 +96,10 @@ public class AbstractAccumulatorTest {
accumulator.add(new TestItem("a"));
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("b"));
- timer.advanceTimeMillis(80, 1);
+ timer.advanceTimeMillis(80, SHORT_REAL_TIME_DELAY);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.ready = true;
- timer.advanceTimeMillis(80, 10);
+ timer.advanceTimeMillis(80, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "ab", accumulator.batch);
}
@@ -105,12 +108,12 @@ public class AbstractAccumulatorTest {
public void readyLongTrigger() {
TestAccumulator accumulator = new TestAccumulator();
accumulator.ready = false;
- timer.advanceTimeMillis(120, 1);
+ timer.advanceTimeMillis(120, SHORT_REAL_TIME_DELAY);
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.add(new TestItem("a"));
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.ready = true;
- timer.advanceTimeMillis(120, 10);
+ timer.advanceTimeMillis(120, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "a", accumulator.batch);
}
@@ -128,7 +131,7 @@ public class AbstractAccumulatorTest {
assertTrue("should not have fired yet", accumulator.batch.isEmpty());
accumulator.ready = true;
accumulator.add(new TestItem("g"));
- timer.advanceTimeMillis(10, 10);
+ timer.advanceTimeMillis(10, LONG_REAL_TIME_DELAY);
assertFalse("should have fired", accumulator.batch.isEmpty());
assertEquals("incorrect batch", "abcdefg", accumulator.batch);
}
diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimer.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimer.java
index 4116cbef..8fb008e8 100644
--- a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimer.java
+++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimer.java
@@ -65,6 +65,14 @@ public class ManuallyAdvancingTimer extends java.util.Timer {
/* Data structure for tracking tasks */
private final TaskQueue queue = new TaskQueue();
+ /* Whether execution should execute on the executor thread or the calling thread. */
+ private final boolean runLocally;
+
+ public ManuallyAdvancingTimer(boolean runLocally) {
+ this.runLocally = runLocally;
+ }
+
+
@Override
public void schedule(TimerTask task, long delay) {
if (!staticsPopulated) {
@@ -165,14 +173,16 @@ public class ManuallyAdvancingTimer extends java.util.Timer {
/**
* Advances the virtual time a certain number of millis triggers execution delays a certain amount to
- * allow time for execution.
+ * allow time for execution. If runLocally is true then all real time delays are ignored.
*
* @param virtualTimeAdvance the time to be advances in millis of simulated time.
* @param realTimeDelay the time to delay in real time to allow for processing.
*/
public void advanceTimeMillis(long virtualTimeAdvance, int realTimeDelay) {
timerKeeper.advanceTimeMillis(virtualTimeAdvance);
- delay(realTimeDelay);
+ if (!runLocally) {
+ delay(realTimeDelay);
+ }
}
/**
@@ -238,7 +248,11 @@ public class ManuallyAdvancingTimer extends java.util.Timer {
e.printStackTrace();
return false;
}
- executorService.execute(task);
+ if (runLocally) {
+ task.run();
+ } else {
+ executorService.execute(task);
+ }
return true;
} else {
//Calculate next execution time, using absolute value of period
@@ -253,7 +267,11 @@ public class ManuallyAdvancingTimer extends java.util.Timer {
}
//Schedule next execution
queue.insertOrdered(task);
- executorService.execute(task);
+ if (runLocally) {
+ task.run();
+ } else {
+ executorService.execute(task);
+ }
return true;
}
}
diff --git a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimerTest.java b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimerTest.java
index b8e1e85e..36b50e67 100644
--- a/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimerTest.java
+++ b/framework/src/onos/utils/misc/src/test/java/org/onlab/util/ManuallyAdvancingTimerTest.java
@@ -47,14 +47,14 @@ public class ManuallyAdvancingTimerTest {
private AtomicInteger tasksRunCount;
// FIXME if this class fails first try increasing the real time delay to account for heavy system load.
- private static final int REAL_TIME_DELAY = 1;
+ private static final int REAL_TIME_DELAY = 10;
/**
* Sets up the testing environment.
*/
@Before
public void setup() {
- timer = new ManuallyAdvancingTimer();
+ timer = new ManuallyAdvancingTimer(true);
idGenerator = new AtomicInteger(1);
tasksRunCount = new AtomicInteger(0);
taskList = Lists.newArrayList();
diff --git a/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Main.java b/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Main.java
index bc10ec7a..ca04a7c2 100644
--- a/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Main.java
+++ b/framework/src/onos/utils/stc/src/main/java/org/onlab/stc/Main.java
@@ -16,13 +16,16 @@
package org.onlab.stc;
import com.google.common.collect.ImmutableList;
+import com.google.common.io.Files;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.util.log.Logger;
import org.onlab.stc.Coordinator.Status;
+import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@@ -64,10 +67,12 @@ public final class Main {
private String runToPatterns = "";
private Coordinator coordinator;
+ private Compiler compiler;
private Monitor monitor;
private Listener delegate = new Listener();
private static boolean useColor = Objects.equals("true", System.getenv("stcColor"));
+ private static boolean dumpLogs = Objects.equals("true", System.getenv("stcDumpLogs"));
// usage: stc [<scenario-file>] [run]
// usage: stc [<scenario-file>] run [from <from-patterns>] [to <to-patterns>]]
@@ -113,7 +118,7 @@ public final class Main {
Scenario scenario = Scenario.loadScenario(new FileInputStream(scenarioFile));
// Elaborate scenario
- Compiler compiler = new Compiler(scenario);
+ compiler = new Compiler(scenario);
compiler.compile();
// Setup the process flow coordinator
@@ -221,7 +226,7 @@ public final class Main {
/**
* Internal delegate to monitor the process execution.
*/
- private static class Listener implements StepProcessListener {
+ private class Listener implements StepProcessListener {
@Override
public void onStart(Step step, String command) {
logStatus(currentTimeMillis(), step.name(), IN_PROGRESS, command);
@@ -230,6 +235,9 @@ public final class Main {
@Override
public void onCompletion(Step step, Status status) {
logStatus(currentTimeMillis(), step.name(), status, null);
+ if (dumpLogs && !(step instanceof Group) && status == FAILED) {
+ dumpLogs(step);
+ }
}
@Override
@@ -246,6 +254,18 @@ public final class Main {
}
}
+ // Dumps the step logs to standard output.
+ private void dumpLogs(Step step) {
+ File logFile = new File(compiler.logDir(), step.name() + ".log");
+ try {
+ print(">>>>>");
+ Files.copy(logFile, System.out);
+ print("<<<<<");
+ } catch (IOException e) {
+ print("Unable to dump log file %s", logFile.getName());
+ }
+ }
+
// Produces a description of event using the specified step status.
private static String action(Status status) {
return status == IN_PROGRESS ? "started" :
diff --git a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
index dd9b9fc3..312f6e35 100644
--- a/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
+++ b/framework/src/onos/web/api/src/main/java/org/onosproject/rest/resources/ClusterWebResource.java
@@ -84,10 +84,9 @@ public class ClusterWebResource extends AbstractWebResource {
public Response formCluster(InputStream config) throws IOException {
JsonCodec<ControllerNode> codec = codec(ControllerNode.class);
ObjectNode root = (ObjectNode) mapper().readTree(config);
- String ipPrefix = root.path("ipPrefix").asText();
List<ControllerNode> nodes = codec.decode((ArrayNode) root.path("nodes"), this);
- get(ClusterAdminService.class).formCluster(new HashSet<>(nodes), ipPrefix);
+ get(ClusterAdminService.class).formCluster(new HashSet<>(nodes));
return Response.ok().build();
}
diff --git a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
index 8acdc2cf..82b7a782 100644
--- a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
+++ b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TopologyViewMessageHandler.java
@@ -27,12 +27,14 @@ import org.onosproject.cluster.ClusterEventListener;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
+import org.onosproject.core.DefaultApplicationId;
import org.onosproject.event.Event;
import org.onosproject.mastership.MastershipAdminService;
import org.onosproject.mastership.MastershipEvent;
import org.onosproject.mastership.MastershipListener;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.HostId;
import org.onosproject.net.HostLocation;
@@ -48,11 +50,14 @@ import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentListener;
+import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkListener;
+import org.onosproject.ui.JsonUtils;
import org.onosproject.ui.RequestHandler;
import org.onosproject.ui.UiConnection;
import org.onosproject.ui.impl.TrafficMonitor.Mode;
@@ -76,7 +81,9 @@ import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.cluster.ClusterEvent.Type.INSTANCE_ADDED;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.HostId.hostId;
-import static org.onosproject.net.device.DeviceEvent.Type.*;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_ADDED;
+import static org.onosproject.net.device.DeviceEvent.Type.DEVICE_UPDATED;
+import static org.onosproject.net.device.DeviceEvent.Type.PORT_STATS_UPDATED;
import static org.onosproject.net.host.HostEvent.Type.HOST_ADDED;
import static org.onosproject.net.link.LinkEvent.Type.LINK_ADDED;
import static org.onosproject.ui.JsonUtils.envelope;
@@ -97,6 +104,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
private static final String REQ_NEXT_INTENT = "requestNextRelatedIntent";
private static final String REQ_PREV_INTENT = "requestPrevRelatedIntent";
private static final String REQ_SEL_INTENT_TRAFFIC = "requestSelectedIntentTraffic";
+ private static final String SEL_INTENT = "selectIntent";
private static final String REQ_ALL_FLOW_TRAFFIC = "requestAllFlowTraffic";
private static final String REQ_ALL_PORT_TRAFFIC = "requestAllPortTraffic";
private static final String REQ_DEV_LINK_FLOWS = "requestDeviceLinkFlows";
@@ -117,9 +125,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
private static final String SPRITE_LIST_RESPONSE = "spriteListResponse";
private static final String SPRITE_DATA_RESPONSE = "spriteDataResponse";
private static final String UPDATE_INSTANCE = "updateInstance";
+ private static final String TOPO_START_DONE = "topoStartDone";
// fields
private static final String ID = "id";
+ private static final String KEY = "key";
+ private static final String APP_ID = "appId";
+ private static final String APP_NAME = "appName";
private static final String DEVICE = "device";
private static final String HOST = "host";
private static final String CLASS = "class";
@@ -135,7 +147,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
private static final String DEACTIVATE = "deactivate";
- private static final String APP_ID = "org.onosproject.gui";
+ private static final String MY_APP_ID = "org.onosproject.gui";
private static final long TRAFFIC_PERIOD = 5000;
private static final long SUMMARY_PERIOD = 30000;
@@ -176,7 +188,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
@Override
public void init(UiConnection connection, ServiceDirectory directory) {
super.init(connection, directory);
- appId = directory.get(CoreService.class).registerApplication(APP_ID);
+ appId = directory.get(CoreService.class).registerApplication(MY_APP_ID);
traffic = new TrafficMonitor(TRAFFIC_PERIOD, servicesBundle, this);
}
@@ -213,6 +225,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
new ReqNextIntent(),
new ReqPrevIntent(),
new ReqSelectedIntentTraffic(),
+ new SelIntent(),
new CancelTraffic()
);
@@ -241,6 +254,7 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
sendAllDevices();
sendAllLinks();
sendAllHosts();
+ sendTopoStartDone();
}
}
@@ -344,11 +358,13 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
PropertyPanel pp = null;
if (type.equals(DEVICE)) {
- pp = deviceDetails(deviceId(id), sid);
- overlayCache.currentOverlay().modifyDeviceDetails(pp);
+ DeviceId did = deviceId(id);
+ pp = deviceDetails(did, sid);
+ overlayCache.currentOverlay().modifyDeviceDetails(pp, did);
} else if (type.equals(HOST)) {
- pp = hostDetails(hostId(id), sid);
- overlayCache.currentOverlay().modifyHostDetails(pp);
+ HostId hid = hostId(id);
+ pp = hostDetails(hid, sid);
+ overlayCache.currentOverlay().modifyHostDetails(pp, hid);
}
sendMessage(envelope(SHOW_DETAILS, sid, json(pp)));
@@ -524,6 +540,31 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
}
}
+ private final class SelIntent extends RequestHandler {
+ private SelIntent() {
+ super(SEL_INTENT);
+ }
+
+ @Override
+ public void process(long sid, ObjectNode payload) {
+ int appId = Integer.parseInt(string(payload, APP_ID));
+ String appName = string(payload, APP_NAME);
+ ApplicationId applicId = new DefaultApplicationId(appId, appName);
+ long intentKey = Long.decode(string(payload, KEY));
+
+ Key key = Key.of(intentKey, applicId);
+ log.debug("Attempting to select intent key={}", key);
+
+ Intent intent = intentService.getIntent(key);
+ if (intent == null) {
+ log.debug("no such intent found!");
+ } else {
+ log.debug("starting to monitor intent {}", key);
+ traffic.monitor(intent);
+ }
+ }
+ }
+
private final class CancelTraffic extends RequestHandler {
private CancelTraffic() {
super(CANCEL_TRAFFIC);
@@ -623,6 +664,9 @@ public class TopologyViewMessageHandler extends TopologyViewMessageHandlerBase {
return hostIds;
}
+ private void sendTopoStartDone() {
+ sendMessage(JsonUtils.envelope(TOPO_START_DONE, objectNode()));
+ }
private synchronized void startSummaryMonitoring() {
stopSummaryMonitoring();
diff --git a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
index ea8ca3ea..f4b5598d 100644
--- a/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
+++ b/framework/src/onos/web/gui/src/main/java/org/onosproject/ui/impl/TrafficOverlay.java
@@ -17,6 +17,7 @@
package org.onosproject.ui.impl;
+import org.onosproject.net.DeviceId;
import org.onosproject.ui.UiTopoOverlay;
import org.onosproject.ui.topo.ButtonId;
import org.onosproject.ui.topo.PropertyPanel;
@@ -55,7 +56,7 @@ public class TrafficOverlay extends UiTopoOverlay {
}
@Override
- public void modifyDeviceDetails(PropertyPanel pp) {
+ public void modifyDeviceDetails(PropertyPanel pp, DeviceId deviceId) {
pp.addButton(SHOW_DEVICE_FLOWS)
.addButton(SHOW_RELATED_TRAFFIC);
}
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css
index 46dbdb52..ded05cf1 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.css
@@ -34,6 +34,10 @@
border-radius: 6px;
}
+.floatpanel.dialog {
+ top: 180px;
+}
+
html[data-platform='iPad'] .floatpanel {
top: 80px;
}
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js
index aef71eee..10f04813 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/layer/panel.js
@@ -171,7 +171,10 @@
}
angular.module('onosLayer')
- .factory('PanelService', ['$log', 'FnService', function (_$log_, _fs_) {
+ .factory('PanelService',
+ ['$log', '$window', 'FnService',
+
+ function (_$log_, _$window_, _fs_) {
$log = _$log_;
fs = _fs_;
@@ -210,5 +213,4 @@
destroyPanel: destroyPanel
};
}]);
-
}());
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js
index 15b44bc9..12536361 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/svg/icon.js
@@ -37,6 +37,8 @@
play: 'play',
stop: 'stop',
+ topo: 'topo',
+
refresh: 'refresh',
garbage: 'garbage',
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css
index 18b81ba6..356ac0f7 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.css
@@ -81,7 +81,7 @@ div.summary-list tr.no-data td {
}
.light div.summary-list tr.selected {
- background-color: deepskyblue;
+ background-color: deepskyblue !important;
}
.dark div.summary-list tr.selected {
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
index 24161bbb..6a5ffb1f 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/tableBuilder.js
@@ -47,6 +47,7 @@
resp = o.tag + 'DataResponse',
onSel = fs.isF(o.selCb),
onResp = fs.isF(o.respCb),
+ idKey = o.idKey || 'id',
oldTableData = [],
loaded = false,
refreshPromise, loadingPromise;
@@ -104,7 +105,8 @@
// === selecting a row functions ----------------
function selCb($event, selRow) {
- o.scope.selId = (o.scope.selId === selRow.id) ? null : selRow.id;
+ var selId = selRow[idKey];
+ o.scope.selId = (o.scope.selId === selId) ? null : selId;
onSel && onSel($event, selRow);
}
o.scope.selectCallback = selCb;
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css
index ed9cd48d..dfa50c37 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.css
@@ -23,7 +23,6 @@
}
#ov-intent div.ctrl-btns {
- width: 45px;
}
.light #ov-intent tr:nth-child(6n + 1),
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html
index 4883beed..98aa5659 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.html
@@ -1,24 +1,13 @@
-<!--
- ~ 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.
- -->
-
<!-- Intent partial HTML -->
<div id="ov-intent">
<div class="tabular-header">
<h2>Intents ({{tableData.length}} total)</h2>
<div class="ctrl-btns">
+ <div ng-class="{active: !!selId}"
+ icon icon-id="topo" icon-size="36"
+ tooltip tt-msg="topoTip"
+ ng-click="showIntent()"></div>
+ <div class="separator"></div>
<div class="refresh" ng-class="{active: autoRefresh}"
icon icon-size="36" icon-id="refresh"
tooltip tt-msg="autoRefreshTip"
@@ -51,6 +40,8 @@
</tr>
<tr ng-repeat-start="intent in tableData track by $index"
+ ng-click="selectCallback($event, intent)"
+ ng-class="{selected: intent.key === selId}"
ng-repeat-complete row-id="{{intent.key}}">
<td>{{intent.appId}}</td>
<td>{{intent.key}}</td>
@@ -58,10 +49,14 @@
<td>{{intent.priority}}</td>
<td>{{intent.state}}</td>
</tr>
- <tr row-id="{{intent.key}}">
+ <tr ng-click="selectCallback($event, intent)"
+ ng-class="{selected: intent.key === selId}"
+ row-id="{{intent.key}}">
<td class="resources" colspan="5">{{intent.resources}}</td>
</tr>
- <tr row-id="{{intent.key}}" ng-repeat-end>
+ <tr ng-click="selectCallback($event, intent)"
+ ng-class="{selected: intent.key === selId}"
+ row-id="{{intent.key}}" ng-repeat-end>
<td class="details" colspan="5">{{intent.details}}</td>
</tr>
</table>
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js
index 5810f347..19f2c076 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/intent/intent.js
@@ -23,14 +23,37 @@
angular.module('ovIntent', [])
.controller('OvIntentCtrl',
- ['$log', '$scope', 'TableBuilderService',
+ ['$log', '$scope', 'TableBuilderService', 'NavService',
- function ($log, $scope, tbs) {
- tbs.buildTable({
- scope: $scope,
- tag: 'intent'
- });
+ function ($log, $scope, tbs, ns) {
- $log.log('OvIntentCtrl has been created');
- }]);
+ function selCb($event, row) {
+ $log.debug('Got a click on:', row);
+ var m = /(\d+)\s:\s(.*)/.exec(row.appId),
+ id = m ? m[1] : null,
+ name = m ? m[2] : null;
+
+ $scope.intentData = ($scope.selId && m) ? {
+ intentAppId: id,
+ intentAppName: name,
+ intentKey: row.key
+ } : null;
+ }
+
+ tbs.buildTable({
+ scope: $scope,
+ tag: 'intent',
+ selCb: selCb,
+ idKey: 'key'
+ });
+
+ $scope.topoTip = 'Show selected intent on topology view';
+
+ $scope.showIntent = function () {
+ var d = $scope.intentData;
+ d && ns.navTo('topo', d);
+ };
+
+ $log.log('OvIntentCtrl has been created');
+ }]);
}());
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css
index f4b089a0..dda6d5c6 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.css
@@ -96,6 +96,24 @@ html[data-platform='iPad'] #topo-p-detail {
height: 30px;
}
+/* --- Topo Dialog Panel --- */
+
+#topo-p-dialog .dialog-button {
+ display: inline-block;
+ cursor: pointer;
+ height: 20px;
+ padding: 2px 6px;
+ margin: 4px;
+ float: right;
+}
+
+.light #topo-p-dialog .dialog-button {
+ background-color: #fec;
+}
+.dark #topo-p-dialog .dialog-button {
+ background-color: #369;
+}
+
/* --- general topo-panel styling --- */
.topo-p div.header div.icon {
@@ -427,6 +445,39 @@ html[data-platform='iPad'] #topo-p-detail {
fill: #f90;
}
+/* Badges */
+/* (... works for both light and dark themes...) */
+#ov-topo svg .node .badge circle {
+ stroke: #aaa;
+}
+
+#ov-topo svg .node .badge.badgeInfo circle {
+ fill: #ccf;
+}
+
+#ov-topo svg .node .badge.badgeWarn circle {
+ fill: #da2;
+}
+
+#ov-topo svg .node .badge.badgeError circle {
+ fill: #e44;
+}
+
+#ov-topo svg .node .badge use {
+ fill: white;
+}
+
+#ov-topo svg .node .badge.badgeInfo use {
+ fill: #448;
+}
+
+#ov-topo svg .node .badge text {
+ fill: white;
+}
+
+#ov-topo svg .node .badge.badgeInfo text {
+ fill: #448;
+}
/* Host Nodes */
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js
index 0dfd6281..7ddfd136 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topo.js
@@ -412,6 +412,12 @@
flash.enable(true);
}
+ function topoStartDone() {
+ var d = $scope.intentData;
+ if (d) {
+ tts.selectIntent(d);
+ }
+ }
// --- Controller Definition -----------------------------------------
@@ -430,7 +436,8 @@
_zs_, _gs_, _ms_, _sus_, _flash_, _wss_, _ps_, _tes_, _tfs_,
_tps_, _tis_, _tss_, _tls_, _tts_, _tos_, _fltr_, _ttbs_, tspr,
_ttip_, _tov_) {
- var projection,
+ var params = $loc.search(),
+ projection,
dim,
uplink = {
// provides function calls back into this space
@@ -438,7 +445,8 @@
projection: function () { return projection; },
zoomLayer: function () { return zoomLayer; },
zoomer: function () { return zoomer; },
- opacifyMap: opacifyMap
+ opacifyMap: opacifyMap,
+ topoStartDone: topoStartDone
};
$scope = _$scope_;
@@ -469,6 +477,14 @@
ttip = _ttip_;
tov = _tov_;
+ if (params.intentKey && params.intentAppId && params.intentAppName) {
+ $scope.intentData = {
+ key: params.intentKey,
+ appId: params.intentAppId,
+ appName: params.intentAppName
+ };
+ }
+
$scope.notifyResize = function () {
svgResized(fs.windowSize(mast.mastHeight()));
};
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
index 1f061dd6..1d2c5b10 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoD3.js
@@ -55,8 +55,23 @@
height: 14
}
},
+ badgeConfig = {
+ radius: 12,
+ yoff: 5,
+ gdelta: 10
+ },
icfg;
+ var status = {
+ i: 'badgeInfo',
+ w: 'badgeWarn',
+ e: 'badgeError'
+ };
+
+ function badgeStatus(badge) {
+ return status[badge.status] || status.i;
+ }
+
// internal state
var deviceLabelIndex = 0,
hostLabelIndex = 0;
@@ -186,12 +201,15 @@
}
- function updateDeviceLabel(d) {
+ function updateDeviceRendering(d) {
var label = trimLabel(deviceLabel(d)),
noLabel = !label,
node = d.el,
dim = icfg.device.dim,
- box, dx, dy;
+ box, dx, dy, bsel,
+ bdg = d.badge,
+ bcr = badgeConfig.radius,
+ bcgd = badgeConfig.gdelta;
node.select('text')
.text(label)
@@ -216,23 +234,34 @@
node.select('g.deviceIcon')
.transition()
.attr('transform', sus.translate(dx, dy));
- }
- function updateDeviceBadge(d) {
- // TODO: Fix this WIP
- var node = d.el,
- bsel;
+ // handle badge, if defined
+ if (bdg) {
+ node.select('g.badge').remove();
- if (d.badge) {
bsel = node.append('g')
.classed('badge', true)
- .attr('transform', sus.translate(-14, -14));
+ .classed(badgeStatus(bdg), true)
+ .attr('transform', sus.translate(dx + dim, dy));
bsel.append('circle')
- .attr('r', 14);
- bsel.append('text')
- .attr('transform', sus.translate(-5, 3))
- .text('42');
+ .attr('r', bcr);
+
+ if (bdg.txt) {
+ bsel.append('text')
+ .attr('dy', badgeConfig.yoff)
+ .attr('text-anchor', 'middle')
+ .text(bdg.txt);
+ } else if (bdg.gid) {
+ bsel.append('use')
+ .attr({
+ width: bcgd * 2,
+ height: bcgd * 2,
+ transform: sus.translate(-bcgd, -bcgd),
+ 'xlink:href': '#' + bdg.gid
+ });
+
+ }
}
}
@@ -258,8 +287,7 @@
function deviceExisting(d) {
var node = d.el;
node.classed('online', d.online);
- updateDeviceLabel(d);
- updateDeviceBadge(d);
+ updateDeviceRendering(d);
api.posNode(d, true);
}
@@ -574,7 +602,7 @@
deviceLabel: deviceLabel,
trimLabel: trimLabel,
- updateDeviceLabel: updateDeviceLabel,
+ updateDeviceLabel: updateDeviceRendering,
updateHostLabel: updateHostLabel,
updateDeviceColors: updateDeviceColors,
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js
new file mode 100644
index 00000000..93079183
--- /dev/null
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoDialog.js
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+/*
+ ONOS GUI -- Topology Dialog Module.
+ Defines functions for manipulating a dialog box.
+ */
+
+(function () {
+ 'use strict';
+
+ // injected refs
+ var $log, $window, $rootScope, fs, ps, bns;
+
+ // constants
+ var pCls = 'topo-p dialog',
+ idDialog = 'topo-p-dialog',
+ panelOpts = {
+ width: 300,
+ edge: 'left'
+ };
+
+ // internal state
+ var pApi, panel, dApi;
+
+ // TODO: ESC key invokes Cancel callback
+ // TODO: Enter invokes OK callback
+
+ // create the dialog; return its API
+ function createDialog() {
+ var header, body, footer,
+ p = ps.createPanel(idDialog, panelOpts);
+ p.classed(pCls, true);
+ panel = p;
+
+ function reset() {
+ p.empty();
+ p.append('div').classed('header', true);
+ p.append('div').classed('body', true);
+ p.append('div').classed('footer', true);
+
+ header = p.el().select('.header');
+ body = p.el().select('.body');
+ footer = p.el().select('.footer');
+ }
+
+ function hAppend(x) {
+ if (typeof x === 'string') {
+ return header.append(x);
+ }
+ header.node().appendChild(x.node());
+ return header;
+ }
+
+ function bAppend(x) {
+ if (typeof x === 'string') {
+ return body.append(x);
+ }
+ body.node().appendChild(x.node());
+ return body;
+ }
+
+ function fAppend(x) {
+ if (typeof x === 'string') {
+ return footer.append(x);
+ }
+ footer.node().appendChild(x.node());
+ return footer;
+ }
+
+ function destroy() {
+ ps.destroyPanel(idDialog);
+ }
+
+ return {
+ reset: reset,
+ appendHeader: hAppend,
+ appendBody: bAppend,
+ appendFooter: fAppend,
+ destroy: destroy
+ };
+ }
+
+ function makeButton(text, callback) {
+ var cb = fs.isF(callback);
+
+ function invoke() {
+ cb && cb();
+ panel.hide();
+ }
+ return createDiv('dialog-button')
+ .text(text)
+ .on('click', invoke);
+ }
+
+ function addContent(content) {
+ if (pApi) {
+ pApi.appendBody(content);
+ }
+ return dApi;
+ }
+
+ function addButton(text, cb) {
+ if (pApi) {
+ pApi.appendFooter(makeButton(text, cb));
+ }
+ return dApi;
+ }
+
+ // opens the dialog (creates if necessary)
+ function openDialog() {
+ $log.debug('Open DIALOG');
+ if (!pApi) {
+ pApi = createDialog();
+ }
+ pApi.reset();
+ pApi.appendHeader('h2').text('=dialog=');
+ panel.show();
+
+ // return the dialog object API
+ dApi = {
+ addContent: addContent,
+ addButton: addButton
+ };
+ return dApi;
+ }
+
+ // closes the dialog (destroying panel)
+ function closeDialog() {
+ $log.debug('Close DIALOG');
+ if (pApi) {
+ panel.hide();
+ pApi.destroy();
+ pApi = null;
+ dApi = null;
+ }
+ }
+
+ // creates a detached div, returning D3 selection
+ // optional CSS class may be provided
+ function createDiv(cls) {
+ var div = d3.select(document.createElement('div'));
+ if (cls) {
+ div.classed(cls, true);
+ }
+ return div;
+ }
+
+ // ==========================
+
+ angular.module('ovTopo')
+ .factory('TopoDialogService',
+ ['$log', '$window', '$rootScope', 'FnService', 'PanelService', 'ButtonService',
+
+ function (_$log_, _$window_, _$rootScope_,
+ _fs_, _ps_, _bns_) {
+ $log = _$log_;
+ $window = _$window_;
+ $rootScope = _$rootScope_;
+ fs = _fs_;
+ ps = _ps_;
+ bns = _bns_;
+
+ return {
+ openDialog: openDialog,
+ closeDialog: closeDialog,
+ createDiv: createDiv
+ };
+ }]);
+}());
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js
index 5fd38bf6..2957629a 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoEvent.js
@@ -60,6 +60,8 @@
updateLink: tfs,
removeLink: tfs,
+ topoStartDone: tfs,
+
spriteListResponse: tspr,
spriteDataResponse: tspr
};
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
index f00b87fa..844d7dc9 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -240,6 +240,11 @@
}
}
+ function topoStartDone(data) {
+ // called when the initial barrage of data has been sent from server
+ uplink.topoStartDone();
+ }
+
// ========================
function nodeById(id) {
@@ -1140,7 +1145,8 @@
removeHost: removeHost,
addLink: addLink,
updateLink: updateLink,
- removeLink: removeLink
+ removeLink: removeLink,
+ topoStartDone: topoStartDone
};
}]);
}());
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index 9a3b4358..2dee4c40 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -34,7 +34,8 @@
// internal state
var overlays = {},
- current = null;
+ current = null,
+ reset = true;
function error(fn, msg) {
$log.error(tos + fn + '(): ' + msg);
@@ -144,7 +145,8 @@
payload[op] = oid;
}
- if (!same) {
+ if (reset || !same) {
+ reset = false;
current && doop('deactivate');
current = overlays[id];
current && doop('activate');
@@ -390,6 +392,7 @@
tbSelection: tbSelection,
installButtons: installButtons,
addDetailButton: addDetailButton,
+ resetOnToolbarDestroy: function () { reset = true; },
hooks: {
escape: escapeHook,
emptySelect: emptySelectHook,
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js
index 483c4baa..4ad76903 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoSelect.js
@@ -240,6 +240,33 @@
return cc;
}
+ // returns a selection context, providing info about what is selected
+ function selectionContext() {
+ var devices = [],
+ hosts = [],
+ types = {};
+
+ angular.forEach(selections, function (d) {
+ var o = d.obj,
+ c = o.class;
+
+ if (c === 'device') {
+ devices.push(o.id);
+ types[o.id] = o.type;
+ }
+ if (c === 'host') {
+ hosts.push(o.id);
+ types[o.id] = o.type;
+ }
+ });
+
+ return {
+ devices: devices,
+ hosts: hosts,
+ types: types
+ };
+ }
+
// === -----------------------------------------------------
// === MODULE DEFINITION ===
@@ -280,7 +307,8 @@
selectOrder: function () { return selectOrder; },
somethingSelected: somethingSelected,
- clickConsumed: clickConsumed
+ clickConsumed: clickConsumed,
+ selectionContext: selectionContext
};
}]);
}());
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
index 3928cd21..06285442 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoToolbar.js
@@ -243,6 +243,7 @@
function destroyToolbar() {
tbs.destroyToolbar(name);
+ tov.resetOnToolbarDestroy();
}
// allows us to ensure the button states track key strokes
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
index ca379360..ff690c49 100644
--- a/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
+++ b/framework/src/onos/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
@@ -152,6 +152,14 @@
}
}
+ // force the system to create a single intent selection
+ function selectIntent(data) {
+ trafficMode = 'intents';
+ hoverMode = null;
+ wss.sendEvent('selectIntent', data);
+ flash.flash('Selecting Intent ' + data.key);
+ }
+
// === ------------------------------------------------------
// action buttons on detail panel (multiple selection)
@@ -207,6 +215,7 @@
showPrevIntent: showPrevIntent,
showNextIntent: showNextIntent,
showSelectedIntentTraffic: showSelectedIntentTraffic,
+ selectIntent: selectIntent,
// invoked from mouseover/mouseout and selection change
requestTrafficForMode: requestTrafficForMode,
diff --git a/framework/src/onos/web/gui/src/main/webapp/index.html b/framework/src/onos/web/gui/src/main/webapp/index.html
index 5df3c664..7e0d9b7d 100644
--- a/framework/src/onos/web/gui/src/main/webapp/index.html
+++ b/framework/src/onos/web/gui/src/main/webapp/index.html
@@ -98,6 +98,7 @@
<script src="app/view/topo/topo.js"></script>
<script src="app/view/topo/topoD3.js"></script>
<script src="app/view/topo/topoEvent.js"></script>
+ <script src="app/view/topo/topoDialog.js"></script>
<script src="app/view/topo/topoFilter.js"></script>
<script src="app/view/topo/topoForce.js"></script>
<script src="app/view/topo/topoInst.js"></script>
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json
new file mode 100644
index 00000000..4f35403f
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_10_showHighlights_stuff.json
@@ -0,0 +1,63 @@
+{
+ "event": "showHighlights",
+ "payload": {
+ "devices": [
+ {
+ "id": "of:0000000000000001",
+ "badge": {
+ "status": "i",
+ "gid": "xMark",
+ "msg": "x marks the spot"
+ }
+ },
+ {
+ "id": "of:0000000000000002",
+ "badge": {
+ "status": "w",
+ "gid": "crown",
+ "msg": "it's good to be the King"
+ }
+ },
+ {
+ "id": "of:0000000000000003",
+ "badge": {
+ "status": "e",
+ "gid": "chain",
+ "msg": "the weakest link"
+ }
+ },
+ {
+ "id": "of:0000000000000004",
+ "badge": {
+ "status": "i",
+ "txt": "1",
+ "msg": "singular sensation"
+ }
+ },
+ {
+ "id": "of:0000000000000005",
+ "badge": {
+ "status": "w",
+ "txt": "42",
+ "msg": "life, the universe, and everything!"
+ }
+ },
+ {
+ "id": "of:0000000000000006",
+ "badge": {
+ "status": "e",
+ "txt": "99",
+ "msg": "cadbury's flake"
+ }
+ }
+ ],
+ "hosts": [],
+ "links": [
+ {
+ "css": "primary",
+ "id": "of:0000000000000001/5-of:0000000000000002/7",
+ "label": "Foo!"
+ }
+ ]
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json
index 615efd25..615efd25 100644
--- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_showHighlights_clear.json
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_11_showHighlights_clear.json
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json
new file mode 100644
index 00000000..57f3251b
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addDevice_s3.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000003",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-3",
+ "of:0000000000000003"
+ ],
+ "metaUi": {
+ "x": 600,
+ "y": 200
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json
new file mode 100644
index 00000000..bab00488
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_5_addDevice_s4.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000004",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-4",
+ "of:0000000000000004"
+ ],
+ "metaUi": {
+ "x": 200,
+ "y": 400
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json
new file mode 100644
index 00000000..6ee18080
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_addDevice_s5.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000005",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-5",
+ "of:0000000000000005"
+ ],
+ "metaUi": {
+ "x": 400,
+ "y": 420
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json
deleted file mode 100644
index 74c42c5c..00000000
--- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_6_showHighlights_stuff.json
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- "event": "showHighlights",
- "payload": {
- "devices": [
- {
- "id": "of:0000000000000001",
- "badge": {
- "status": "e",
- "gid": "xMark",
- "msg": "x marks the spot"
- }
- },
- {
- "id": "of:0000000000000002",
- "badge": {
- "status": "w",
- "txt": "7"
- }
- }
- ],
- "hosts": [],
- "links": [
- {
- "css": "primary",
- "id": "of:0000000000000001/5-of:0000000000000002/7",
- "label": "Antz!"
- }
- ]
- }
-}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json
new file mode 100644
index 00000000..4554996e
--- /dev/null
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_addDevice_s6.json
@@ -0,0 +1,18 @@
+{
+ "event": "addDevice",
+ "payload": {
+ "id": "of:0000000000000006",
+ "type": "switch",
+ "online": true,
+ "master": "ONOS",
+ "labels": [
+ "",
+ "switch-6",
+ "of:0000000000000006"
+ ],
+ "metaUi": {
+ "x": 600,
+ "y": 400
+ }
+ }
+}
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_8_addLink_1_2.json
index fb952837..fb952837 100644
--- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_4_addLink_1_2.json
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_8_addLink_1_2.json
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json
index 615efd25..615efd25 100644
--- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_7_showHighlights_clear.json
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/ev_9_showHighlights_clear.json
diff --git a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json
index 0ca4f4f4..ae093d69 100644
--- a/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json
+++ b/framework/src/onos/web/gui/src/test/_karma/ev/badges/scenario.json
@@ -4,7 +4,7 @@
],
"title": "Demo adding badges",
"params": {
- "lastAuto": 5
+ "lastAuto": 9
},
"description": [
"Demonstrate the device badging feature."