Committed by
Gerrit Code Review
CORD-348 multicast support in SegmentRouting and vRouter
In this submission: * Setup/teardown multicast route according to SinkAdded/SinkRemoved event - ingressVlan and egressVlan is configurable through network config * Change behavior of OFDPA VLAN assignment - Always use the VLAN in metadata if present * Bugfix of writing immutable object NOT in this submission (coming soon): * Error handling (e.g. link/device failure recovery) Change-Id: I9be11af04eb2d6456b865c7e59e96cc02370f846
Showing
17 changed files
with
540 additions
and
96 deletions
... | @@ -29,11 +29,13 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; | ... | @@ -29,11 +29,13 @@ import org.apache.felix.scr.annotations.ReferenceCardinality; |
29 | import org.onlab.packet.Ethernet; | 29 | import org.onlab.packet.Ethernet; |
30 | import org.onlab.packet.IpAddress; | 30 | import org.onlab.packet.IpAddress; |
31 | import org.onlab.packet.IpPrefix; | 31 | import org.onlab.packet.IpPrefix; |
32 | +import org.onlab.packet.MacAddress; | ||
32 | import org.onlab.packet.VlanId; | 33 | import org.onlab.packet.VlanId; |
33 | import org.onlab.util.Tools; | 34 | import org.onlab.util.Tools; |
34 | import org.onosproject.cfg.ComponentConfigService; | 35 | import org.onosproject.cfg.ComponentConfigService; |
35 | import org.onosproject.core.ApplicationId; | 36 | import org.onosproject.core.ApplicationId; |
36 | import org.onosproject.core.CoreService; | 37 | import org.onosproject.core.CoreService; |
38 | +import org.onosproject.incubator.net.config.basics.McastConfig; | ||
37 | import org.onosproject.incubator.net.intf.Interface; | 39 | import org.onosproject.incubator.net.intf.Interface; |
38 | import org.onosproject.incubator.net.intf.InterfaceEvent; | 40 | import org.onosproject.incubator.net.intf.InterfaceEvent; |
39 | import org.onosproject.incubator.net.intf.InterfaceListener; | 41 | import org.onosproject.incubator.net.intf.InterfaceListener; |
... | @@ -44,9 +46,12 @@ import org.onosproject.incubator.net.routing.RouteListener; | ... | @@ -44,9 +46,12 @@ import org.onosproject.incubator.net.routing.RouteListener; |
44 | import org.onosproject.incubator.net.routing.RouteService; | 46 | import org.onosproject.incubator.net.routing.RouteService; |
45 | import org.onosproject.net.ConnectPoint; | 47 | import org.onosproject.net.ConnectPoint; |
46 | import org.onosproject.net.DeviceId; | 48 | import org.onosproject.net.DeviceId; |
49 | +import org.onosproject.net.config.ConfigFactory; | ||
47 | import org.onosproject.net.config.NetworkConfigEvent; | 50 | import org.onosproject.net.config.NetworkConfigEvent; |
48 | import org.onosproject.net.config.NetworkConfigListener; | 51 | import org.onosproject.net.config.NetworkConfigListener; |
52 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
49 | import org.onosproject.net.config.NetworkConfigService; | 53 | import org.onosproject.net.config.NetworkConfigService; |
54 | +import org.onosproject.net.config.basics.SubjectFactories; | ||
50 | import org.onosproject.net.device.DeviceEvent; | 55 | import org.onosproject.net.device.DeviceEvent; |
51 | import org.onosproject.net.device.DeviceListener; | 56 | import org.onosproject.net.device.DeviceListener; |
52 | import org.onosproject.net.device.DeviceService; | 57 | import org.onosproject.net.device.DeviceService; |
... | @@ -102,6 +107,9 @@ public class SingleSwitchFibInstaller { | ... | @@ -102,6 +107,9 @@ public class SingleSwitchFibInstaller { |
102 | protected NetworkConfigService networkConfigService; | 107 | protected NetworkConfigService networkConfigService; |
103 | 108 | ||
104 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 109 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
110 | + protected NetworkConfigRegistry networkConfigRegistry; | ||
111 | + | ||
112 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
105 | protected ComponentConfigService componentConfigService; | 113 | protected ComponentConfigService componentConfigService; |
106 | 114 | ||
107 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 115 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
... | @@ -123,6 +131,7 @@ public class SingleSwitchFibInstaller { | ... | @@ -123,6 +131,7 @@ public class SingleSwitchFibInstaller { |
123 | 131 | ||
124 | private List<String> interfaces; | 132 | private List<String> interfaces; |
125 | 133 | ||
134 | + private ApplicationId coreAppId; | ||
126 | private ApplicationId routerAppId; | 135 | private ApplicationId routerAppId; |
127 | 136 | ||
128 | // Reference count for how many times a next hop is used by a route | 137 | // Reference count for how many times a next hop is used by a route |
... | @@ -138,13 +147,25 @@ public class SingleSwitchFibInstaller { | ... | @@ -138,13 +147,25 @@ public class SingleSwitchFibInstaller { |
138 | private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener(); | 147 | private InternalInterfaceListener internalInterfaceList = new InternalInterfaceListener(); |
139 | private InternalRouteListener routeListener = new InternalRouteListener(); | 148 | private InternalRouteListener routeListener = new InternalRouteListener(); |
140 | 149 | ||
150 | + private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory = | ||
151 | + new ConfigFactory<ApplicationId, McastConfig>(SubjectFactories.APP_SUBJECT_FACTORY, | ||
152 | + McastConfig.class, "multicast") { | ||
153 | + @Override | ||
154 | + public McastConfig createConfig() { | ||
155 | + return new McastConfig(); | ||
156 | + } | ||
157 | + }; | ||
158 | + | ||
141 | @Activate | 159 | @Activate |
142 | protected void activate(ComponentContext context) { | 160 | protected void activate(ComponentContext context) { |
143 | componentConfigService.registerProperties(getClass()); | 161 | componentConfigService.registerProperties(getClass()); |
144 | modified(context); | 162 | modified(context); |
145 | 163 | ||
164 | + coreAppId = coreService.registerApplication(CoreService.CORE_APP_NAME); | ||
146 | routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID); | 165 | routerAppId = coreService.registerApplication(RoutingService.ROUTER_APP_ID); |
147 | 166 | ||
167 | + networkConfigRegistry.registerConfigFactory(mcastConfigFactory); | ||
168 | + | ||
148 | deviceListener = new InternalDeviceListener(); | 169 | deviceListener = new InternalDeviceListener(); |
149 | deviceService.addListener(deviceListener); | 170 | deviceService.addListener(deviceListener); |
150 | 171 | ||
... | @@ -368,6 +389,7 @@ public class SingleSwitchFibInstaller { | ... | @@ -368,6 +389,7 @@ public class SingleSwitchFibInstaller { |
368 | } | 389 | } |
369 | 390 | ||
370 | createFilteringObjective(install, intf); | 391 | createFilteringObjective(install, intf); |
392 | + createMcastFilteringObjective(install, intf); | ||
371 | } | 393 | } |
372 | } | 394 | } |
373 | 395 | ||
... | @@ -380,10 +402,14 @@ public class SingleSwitchFibInstaller { | ... | @@ -380,10 +402,14 @@ public class SingleSwitchFibInstaller { |
380 | } | 402 | } |
381 | 403 | ||
382 | createFilteringObjective(install, intf); | 404 | createFilteringObjective(install, intf); |
405 | + createMcastFilteringObjective(install, intf); | ||
383 | } | 406 | } |
384 | 407 | ||
385 | //create filtering objective for interface | 408 | //create filtering objective for interface |
386 | private void createFilteringObjective(boolean install, Interface intf) { | 409 | private void createFilteringObjective(boolean install, Interface intf) { |
410 | + VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ? | ||
411 | + VlanId.vlanId(ASSIGNED_VLAN) : | ||
412 | + egressVlan(); | ||
387 | 413 | ||
388 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | 414 | FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); |
389 | // first add filter for the interface | 415 | // first add filter for the interface |
... | @@ -393,12 +419,12 @@ public class SingleSwitchFibInstaller { | ... | @@ -393,12 +419,12 @@ public class SingleSwitchFibInstaller { |
393 | fob.withPriority(PRIORITY_OFFSET); | 419 | fob.withPriority(PRIORITY_OFFSET); |
394 | if (intf.vlan() == VlanId.NONE) { | 420 | if (intf.vlan() == VlanId.NONE) { |
395 | TrafficTreatment tt = DefaultTrafficTreatment.builder() | 421 | TrafficTreatment tt = DefaultTrafficTreatment.builder() |
396 | - .pushVlan().setVlanId(VlanId.vlanId(ASSIGNED_VLAN)).build(); | 422 | + .pushVlan().setVlanId(assignedVlan).build(); |
397 | fob.withMeta(tt); | 423 | fob.withMeta(tt); |
398 | } | 424 | } |
399 | - | ||
400 | fob.permit().fromApp(routerAppId); | 425 | fob.permit().fromApp(routerAppId); |
401 | sendFilteringObjective(install, fob, intf); | 426 | sendFilteringObjective(install, fob, intf); |
427 | + | ||
402 | if (controlPlaneConnectPoint != null) { | 428 | if (controlPlaneConnectPoint != null) { |
403 | // then add the same mac/vlan filters for control-plane connect point | 429 | // then add the same mac/vlan filters for control-plane connect point |
404 | fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port())); | 430 | fob.withKey(Criteria.matchInPort(controlPlaneConnectPoint.port())); |
... | @@ -406,6 +432,27 @@ public class SingleSwitchFibInstaller { | ... | @@ -406,6 +432,27 @@ public class SingleSwitchFibInstaller { |
406 | } | 432 | } |
407 | } | 433 | } |
408 | 434 | ||
435 | + //create filtering objective for multicast traffic | ||
436 | + private void createMcastFilteringObjective(boolean install, Interface intf) { | ||
437 | + VlanId assignedVlan = (egressVlan().equals(VlanId.NONE)) ? | ||
438 | + VlanId.vlanId(ASSIGNED_VLAN) : | ||
439 | + egressVlan(); | ||
440 | + | ||
441 | + FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); | ||
442 | + // first add filter for the interface | ||
443 | + fob.withKey(Criteria.matchInPort(intf.connectPoint().port())) | ||
444 | + .addCondition(Criteria.matchEthDstMasked(MacAddress.IPV4_MULTICAST, | ||
445 | + MacAddress.IPV4_MULTICAST_MASK)) | ||
446 | + .addCondition(Criteria.matchVlanId(ingressVlan())); | ||
447 | + fob.withPriority(PRIORITY_OFFSET); | ||
448 | + TrafficTreatment tt = DefaultTrafficTreatment.builder() | ||
449 | + .pushVlan().setVlanId(assignedVlan).build(); | ||
450 | + fob.withMeta(tt); | ||
451 | + | ||
452 | + fob.permit().fromApp(routerAppId); | ||
453 | + sendFilteringObjective(install, fob, intf); | ||
454 | + } | ||
455 | + | ||
409 | private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob, | 456 | private void sendFilteringObjective(boolean install, FilteringObjective.Builder fob, |
410 | Interface intf) { | 457 | Interface intf) { |
411 | 458 | ||
... | @@ -419,6 +466,18 @@ public class SingleSwitchFibInstaller { | ... | @@ -419,6 +466,18 @@ public class SingleSwitchFibInstaller { |
419 | flowObjectiveService.filter(deviceId, filter); | 466 | flowObjectiveService.filter(deviceId, filter); |
420 | } | 467 | } |
421 | 468 | ||
469 | + private VlanId ingressVlan() { | ||
470 | + McastConfig mcastConfig = | ||
471 | + networkConfigService.getConfig(coreAppId, McastConfig.class); | ||
472 | + return (mcastConfig != null) ? mcastConfig.ingressVlan() : VlanId.NONE; | ||
473 | + } | ||
474 | + | ||
475 | + private VlanId egressVlan() { | ||
476 | + McastConfig mcastConfig = | ||
477 | + networkConfigService.getConfig(coreAppId, McastConfig.class); | ||
478 | + return (mcastConfig != null) ? mcastConfig.egressVlan() : VlanId.NONE; | ||
479 | + } | ||
480 | + | ||
422 | private class InternalRouteListener implements RouteListener { | 481 | private class InternalRouteListener implements RouteListener { |
423 | @Override | 482 | @Override |
424 | public void event(RouteEvent event) { | 483 | public void event(RouteEvent event) { |
... | @@ -490,7 +549,6 @@ public class SingleSwitchFibInstaller { | ... | @@ -490,7 +549,6 @@ public class SingleSwitchFibInstaller { |
490 | } | 549 | } |
491 | 550 | ||
492 | private class InternalInterfaceListener implements InterfaceListener { | 551 | private class InternalInterfaceListener implements InterfaceListener { |
493 | - | ||
494 | @Override | 552 | @Override |
495 | public void event(InterfaceEvent event) { | 553 | public void event(InterfaceEvent event) { |
496 | Interface intf = event.subject(); | 554 | Interface intf = event.subject(); | ... | ... |
... | @@ -40,6 +40,7 @@ import org.onosproject.incubator.net.routing.RouteServiceAdapter; | ... | @@ -40,6 +40,7 @@ import org.onosproject.incubator.net.routing.RouteServiceAdapter; |
40 | import org.onosproject.net.ConnectPoint; | 40 | import org.onosproject.net.ConnectPoint; |
41 | import org.onosproject.net.DeviceId; | 41 | import org.onosproject.net.DeviceId; |
42 | import org.onosproject.net.PortNumber; | 42 | import org.onosproject.net.PortNumber; |
43 | +import org.onosproject.net.config.NetworkConfigRegistry; | ||
43 | import org.onosproject.net.config.NetworkConfigService; | 44 | import org.onosproject.net.config.NetworkConfigService; |
44 | import org.onosproject.net.device.DeviceListener; | 45 | import org.onosproject.net.device.DeviceListener; |
45 | import org.onosproject.net.device.DeviceService; | 46 | import org.onosproject.net.device.DeviceService; |
... | @@ -105,6 +106,7 @@ public class SingleSwitchFibInstallerTest { | ... | @@ -105,6 +106,7 @@ public class SingleSwitchFibInstallerTest { |
105 | private final Set<Interface> interfaces = Sets.newHashSet(); | 106 | private final Set<Interface> interfaces = Sets.newHashSet(); |
106 | private InterfaceService interfaceService; | 107 | private InterfaceService interfaceService; |
107 | private NetworkConfigService networkConfigService; | 108 | private NetworkConfigService networkConfigService; |
109 | + private NetworkConfigRegistry networkConfigRegistry; | ||
108 | private FlowObjectiveService flowObjectiveService; | 110 | private FlowObjectiveService flowObjectiveService; |
109 | private DeviceService deviceService; | 111 | private DeviceService deviceService; |
110 | private static final ApplicationId APPID = TestApplicationId.create("foo"); | 112 | private static final ApplicationId APPID = TestApplicationId.create("foo"); |
... | @@ -128,13 +130,15 @@ public class SingleSwitchFibInstallerTest { | ... | @@ -128,13 +130,15 @@ public class SingleSwitchFibInstallerTest { |
128 | interfaceService = createMock(InterfaceService.class); | 130 | interfaceService = createMock(InterfaceService.class); |
129 | 131 | ||
130 | networkConfigService = createMock(NetworkConfigService.class); | 132 | networkConfigService = createMock(NetworkConfigService.class); |
133 | + networkConfigRegistry = createMock(NetworkConfigRegistry.class); | ||
131 | flowObjectiveService = createMock(FlowObjectiveService.class); | 134 | flowObjectiveService = createMock(FlowObjectiveService.class); |
132 | deviceService = new TestDeviceService(); | 135 | deviceService = new TestDeviceService(); |
133 | CoreService coreService = createNiceMock(CoreService.class); | 136 | CoreService coreService = createNiceMock(CoreService.class); |
134 | - expect(coreService.registerApplication(anyString())).andReturn(APPID); | 137 | + expect(coreService.registerApplication(anyString())).andReturn(APPID).anyTimes(); |
135 | replay(coreService); | 138 | replay(coreService); |
136 | 139 | ||
137 | sSfibInstaller.networkConfigService = networkConfigService; | 140 | sSfibInstaller.networkConfigService = networkConfigService; |
141 | + sSfibInstaller.networkConfigRegistry = networkConfigRegistry; | ||
138 | sSfibInstaller.interfaceService = interfaceService; | 142 | sSfibInstaller.interfaceService = interfaceService; |
139 | sSfibInstaller.flowObjectiveService = flowObjectiveService; | 143 | sSfibInstaller.flowObjectiveService = flowObjectiveService; |
140 | sSfibInstaller.coreService = coreService; | 144 | sSfibInstaller.coreService = coreService; | ... | ... |
... | @@ -3,9 +3,9 @@ COMPILE_DEPS = [ | ... | @@ -3,9 +3,9 @@ COMPILE_DEPS = [ |
3 | '//lib:org.apache.karaf.shell.console', | 3 | '//lib:org.apache.karaf.shell.console', |
4 | '//lib:javax.ws.rs-api', | 4 | '//lib:javax.ws.rs-api', |
5 | '//cli:onos-cli', | 5 | '//cli:onos-cli', |
6 | + '//core/store/serializers:onos-core-serializers', | ||
6 | '//incubator/api:onos-incubator-api', | 7 | '//incubator/api:onos-incubator-api', |
7 | '//utils/rest:onlab-rest', | 8 | '//utils/rest:onlab-rest', |
8 | - '//core/store/serializers:onos-core-serializers', | ||
9 | ] | 9 | ] |
10 | 10 | ||
11 | TEST_DEPS = [ | 11 | TEST_DEPS = [ | ... | ... |
... | @@ -51,7 +51,11 @@ | ... | @@ -51,7 +51,11 @@ |
51 | <artifactId>onos-cli</artifactId> | 51 | <artifactId>onos-cli</artifactId> |
52 | <version>${project.version}</version> | 52 | <version>${project.version}</version> |
53 | </dependency> | 53 | </dependency> |
54 | - | 54 | + <dependency> |
55 | + <groupId>org.onosproject</groupId> | ||
56 | + <artifactId>onos-core-serializers</artifactId> | ||
57 | + <version>${project.version}</version> | ||
58 | + </dependency> | ||
55 | <dependency> | 59 | <dependency> |
56 | <groupId>org.apache.karaf.shell</groupId> | 60 | <groupId>org.apache.karaf.shell</groupId> |
57 | <artifactId>org.apache.karaf.shell.console</artifactId> | 61 | <artifactId>org.apache.karaf.shell.console</artifactId> |
... | @@ -84,12 +88,10 @@ | ... | @@ -84,12 +88,10 @@ |
84 | <groupId>com.fasterxml.jackson.core</groupId> | 88 | <groupId>com.fasterxml.jackson.core</groupId> |
85 | <artifactId>jackson-databind</artifactId> | 89 | <artifactId>jackson-databind</artifactId> |
86 | </dependency> | 90 | </dependency> |
87 | - | ||
88 | <dependency> | 91 | <dependency> |
89 | <groupId>com.fasterxml.jackson.core</groupId> | 92 | <groupId>com.fasterxml.jackson.core</groupId> |
90 | <artifactId>jackson-annotations</artifactId> | 93 | <artifactId>jackson-annotations</artifactId> |
91 | </dependency> | 94 | </dependency> |
92 | - | ||
93 | <dependency> | 95 | <dependency> |
94 | <groupId>org.osgi</groupId> | 96 | <groupId>org.osgi</groupId> |
95 | <artifactId>org.osgi.compendium</artifactId> | 97 | <artifactId>org.osgi.compendium</artifactId> |
... | @@ -103,7 +105,6 @@ | ... | @@ -103,7 +105,6 @@ |
103 | <artifactId>onlab-junit</artifactId> | 105 | <artifactId>onlab-junit</artifactId> |
104 | <scope>test</scope> | 106 | <scope>test</scope> |
105 | </dependency> | 107 | </dependency> |
106 | - | ||
107 | <dependency> | 108 | <dependency> |
108 | <groupId>org.onosproject</groupId> | 109 | <groupId>org.onosproject</groupId> |
109 | <artifactId>onos-api</artifactId> | 110 | <artifactId>onos-api</artifactId> | ... | ... |
This diff is collapsed. Click to expand it.
... | @@ -73,8 +73,8 @@ public class NetworkConfigEventHandler { | ... | @@ -73,8 +73,8 @@ public class NetworkConfigEventHandler { |
73 | SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get(); | 73 | SegmentRoutingAppConfig config = (SegmentRoutingAppConfig) event.config().get(); |
74 | SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get(); | 74 | SegmentRoutingAppConfig prevConfig = (SegmentRoutingAppConfig) event.prevConfig().get(); |
75 | deviceService.getAvailableDevices().forEach(device -> { | 75 | deviceService.getAvailableDevices().forEach(device -> { |
76 | - Set<MacAddress> macAddresses = getMacAddresses(config); | 76 | + Set<MacAddress> macAddresses = new HashSet<>(getMacAddresses(config)); |
77 | - Set<MacAddress> prevMacAddresses = getMacAddresses(prevConfig); | 77 | + Set<MacAddress> prevMacAddresses = new HashSet<>(getMacAddresses(prevConfig)); |
78 | // Avoid removing and re-adding unchanged MAC addresses since | 78 | // Avoid removing and re-adding unchanged MAC addresses since |
79 | // FlowObjective does not guarantee the execution order. | 79 | // FlowObjective does not guarantee the execution order. |
80 | Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses); | 80 | Set<MacAddress> sameMacAddresses = new HashSet<>(macAddresses); | ... | ... |
... | @@ -33,6 +33,7 @@ import org.onosproject.cfg.ComponentConfigService; | ... | @@ -33,6 +33,7 @@ import org.onosproject.cfg.ComponentConfigService; |
33 | import org.onosproject.core.ApplicationId; | 33 | import org.onosproject.core.ApplicationId; |
34 | import org.onosproject.core.CoreService; | 34 | import org.onosproject.core.CoreService; |
35 | import org.onosproject.event.Event; | 35 | import org.onosproject.event.Event; |
36 | +import org.onosproject.incubator.net.config.basics.McastConfig; | ||
36 | import org.onosproject.mastership.MastershipService; | 37 | import org.onosproject.mastership.MastershipService; |
37 | import org.onosproject.net.ConnectPoint; | 38 | import org.onosproject.net.ConnectPoint; |
38 | import org.onosproject.net.Device; | 39 | import org.onosproject.net.Device; |
... | @@ -60,23 +61,27 @@ import org.onosproject.net.flowobjective.ObjectiveContext; | ... | @@ -60,23 +61,27 @@ import org.onosproject.net.flowobjective.ObjectiveContext; |
60 | import org.onosproject.net.flowobjective.ObjectiveError; | 61 | import org.onosproject.net.flowobjective.ObjectiveError; |
61 | import org.onosproject.net.host.HostEvent; | 62 | import org.onosproject.net.host.HostEvent; |
62 | import org.onosproject.net.host.HostListener; | 63 | import org.onosproject.net.host.HostListener; |
63 | -import org.onosproject.net.host.HostService; | 64 | +import org.onosproject.net.mcast.McastEvent; |
64 | -import org.onosproject.net.link.LinkEvent; | 65 | +import org.onosproject.net.mcast.McastListener; |
65 | -import org.onosproject.net.link.LinkListener; | 66 | +import org.onosproject.net.mcast.MulticastRouteService; |
66 | -import org.onosproject.net.link.LinkService; | ||
67 | -import org.onosproject.net.packet.InboundPacket; | ||
68 | -import org.onosproject.net.packet.PacketContext; | ||
69 | import org.onosproject.net.packet.PacketPriority; | 67 | import org.onosproject.net.packet.PacketPriority; |
70 | -import org.onosproject.net.packet.PacketProcessor; | 68 | +import org.onosproject.net.topology.TopologyService; |
71 | -import org.onosproject.net.packet.PacketService; | ||
72 | import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; | 69 | import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; |
73 | import org.onosproject.segmentrouting.config.DeviceConfiguration; | 70 | import org.onosproject.segmentrouting.config.DeviceConfiguration; |
74 | -import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig; | ||
75 | import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig; | 71 | import org.onosproject.segmentrouting.config.SegmentRoutingDeviceConfig; |
72 | +import org.onosproject.segmentrouting.config.SegmentRoutingAppConfig; | ||
76 | import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler; | 73 | import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler; |
77 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; | 74 | import org.onosproject.segmentrouting.grouphandler.NeighborSet; |
78 | import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey; | 75 | import org.onosproject.segmentrouting.grouphandler.NeighborSetNextObjectiveStoreKey; |
79 | import org.onosproject.segmentrouting.grouphandler.PortNextObjectiveStoreKey; | 76 | import org.onosproject.segmentrouting.grouphandler.PortNextObjectiveStoreKey; |
77 | +import org.onosproject.net.host.HostService; | ||
78 | +import org.onosproject.net.link.LinkEvent; | ||
79 | +import org.onosproject.net.link.LinkListener; | ||
80 | +import org.onosproject.net.link.LinkService; | ||
81 | +import org.onosproject.net.packet.InboundPacket; | ||
82 | +import org.onosproject.net.packet.PacketContext; | ||
83 | +import org.onosproject.net.packet.PacketProcessor; | ||
84 | +import org.onosproject.net.packet.PacketService; | ||
80 | import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey; | 85 | import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey; |
81 | import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey; | 86 | import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey; |
82 | import org.onosproject.store.serializers.KryoNamespaces; | 87 | import org.onosproject.store.serializers.KryoNamespaces; |
... | @@ -143,6 +148,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -143,6 +148,12 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
143 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | 148 | @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) |
144 | protected ComponentConfigService compCfgService; | 149 | protected ComponentConfigService compCfgService; |
145 | 150 | ||
151 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
152 | + protected MulticastRouteService multicastRouteService; | ||
153 | + | ||
154 | + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) | ||
155 | + protected TopologyService topologyService; | ||
156 | + | ||
146 | protected ArpHandler arpHandler = null; | 157 | protected ArpHandler arpHandler = null; |
147 | protected IcmpHandler icmpHandler = null; | 158 | protected IcmpHandler icmpHandler = null; |
148 | protected IpHandler ipHandler = null; | 159 | protected IpHandler ipHandler = null; |
... | @@ -157,8 +168,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -157,8 +168,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
157 | private InternalLinkListener linkListener = null; | 168 | private InternalLinkListener linkListener = null; |
158 | private InternalDeviceListener deviceListener = null; | 169 | private InternalDeviceListener deviceListener = null; |
159 | private NetworkConfigEventHandler netcfgHandler = null; | 170 | private NetworkConfigEventHandler netcfgHandler = null; |
171 | + private McastEventHandler mcastEventHandler = null; | ||
160 | private InternalEventHandler eventHandler = new InternalEventHandler(); | 172 | private InternalEventHandler eventHandler = new InternalEventHandler(); |
161 | private final InternalHostListener hostListener = new InternalHostListener(); | 173 | private final InternalHostListener hostListener = new InternalHostListener(); |
174 | + private final InternalConfigListener cfgListener = new InternalConfigListener(this); | ||
175 | + private final InternalMcastListener mcastListener = new InternalMcastListener(); | ||
162 | 176 | ||
163 | private ScheduledExecutorService executorService = Executors | 177 | private ScheduledExecutorService executorService = Executors |
164 | .newScheduledThreadPool(1); | 178 | .newScheduledThreadPool(1); |
... | @@ -196,29 +210,32 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -196,29 +210,32 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
196 | private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; | 210 | private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; |
197 | private EventuallyConsistentMap<String, Policy> policyStore = null; | 211 | private EventuallyConsistentMap<String, Policy> policyStore = null; |
198 | 212 | ||
199 | - private final InternalConfigListener cfgListener = | 213 | + private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> deviceConfigFactory = |
200 | - new InternalConfigListener(this); | ||
201 | - | ||
202 | - private final ConfigFactory<DeviceId, SegmentRoutingDeviceConfig> cfgDeviceFactory = | ||
203 | new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY, | 214 | new ConfigFactory<DeviceId, SegmentRoutingDeviceConfig>(SubjectFactories.DEVICE_SUBJECT_FACTORY, |
204 | - SegmentRoutingDeviceConfig.class, | 215 | + SegmentRoutingDeviceConfig.class, "segmentrouting") { |
205 | - "segmentrouting") { | ||
206 | @Override | 216 | @Override |
207 | public SegmentRoutingDeviceConfig createConfig() { | 217 | public SegmentRoutingDeviceConfig createConfig() { |
208 | return new SegmentRoutingDeviceConfig(); | 218 | return new SegmentRoutingDeviceConfig(); |
209 | } | 219 | } |
210 | }; | 220 | }; |
211 | - | 221 | + private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> appConfigFactory = |
212 | - private final ConfigFactory<ApplicationId, SegmentRoutingAppConfig> cfgAppFactory = | ||
213 | new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(SubjectFactories.APP_SUBJECT_FACTORY, | 222 | new ConfigFactory<ApplicationId, SegmentRoutingAppConfig>(SubjectFactories.APP_SUBJECT_FACTORY, |
214 | - SegmentRoutingAppConfig.class, | 223 | + SegmentRoutingAppConfig.class, "segmentrouting") { |
215 | - "segmentrouting") { | ||
216 | @Override | 224 | @Override |
217 | public SegmentRoutingAppConfig createConfig() { | 225 | public SegmentRoutingAppConfig createConfig() { |
218 | return new SegmentRoutingAppConfig(); | 226 | return new SegmentRoutingAppConfig(); |
219 | } | 227 | } |
220 | }; | 228 | }; |
221 | 229 | ||
230 | + private ConfigFactory<ApplicationId, McastConfig> mcastConfigFactory = | ||
231 | + new ConfigFactory<ApplicationId, McastConfig>(SubjectFactories.APP_SUBJECT_FACTORY, | ||
232 | + McastConfig.class, "multicast") { | ||
233 | + @Override | ||
234 | + public McastConfig createConfig() { | ||
235 | + return new McastConfig(); | ||
236 | + } | ||
237 | + }; | ||
238 | + | ||
222 | private Object threadSchedulerLock = new Object(); | 239 | private Object threadSchedulerLock = new Object(); |
223 | private static int numOfEventsQueued = 0; | 240 | private static int numOfEventsQueued = 0; |
224 | private static int numOfEventsExecuted = 0; | 241 | private static int numOfEventsExecuted = 0; |
... | @@ -312,14 +329,17 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -312,14 +329,17 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
312 | linkListener = new InternalLinkListener(); | 329 | linkListener = new InternalLinkListener(); |
313 | deviceListener = new InternalDeviceListener(); | 330 | deviceListener = new InternalDeviceListener(); |
314 | netcfgHandler = new NetworkConfigEventHandler(this); | 331 | netcfgHandler = new NetworkConfigEventHandler(this); |
332 | + mcastEventHandler = new McastEventHandler(this); | ||
315 | 333 | ||
316 | cfgService.addListener(cfgListener); | 334 | cfgService.addListener(cfgListener); |
317 | - cfgService.registerConfigFactory(cfgDeviceFactory); | 335 | + cfgService.registerConfigFactory(deviceConfigFactory); |
318 | - cfgService.registerConfigFactory(cfgAppFactory); | 336 | + cfgService.registerConfigFactory(appConfigFactory); |
337 | + cfgService.registerConfigFactory(mcastConfigFactory); | ||
319 | hostService.addListener(hostListener); | 338 | hostService.addListener(hostListener); |
320 | packetService.addProcessor(processor, PacketProcessor.director(2)); | 339 | packetService.addProcessor(processor, PacketProcessor.director(2)); |
321 | linkService.addListener(linkListener); | 340 | linkService.addListener(linkListener); |
322 | deviceService.addListener(deviceListener); | 341 | deviceService.addListener(deviceListener); |
342 | + multicastRouteService.addListener(mcastListener); | ||
323 | 343 | ||
324 | // Request ARP packet-in | 344 | // Request ARP packet-in |
325 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 345 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
... | @@ -351,8 +371,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -351,8 +371,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
351 | @Deactivate | 371 | @Deactivate |
352 | protected void deactivate() { | 372 | protected void deactivate() { |
353 | cfgService.removeListener(cfgListener); | 373 | cfgService.removeListener(cfgListener); |
354 | - cfgService.unregisterConfigFactory(cfgDeviceFactory); | 374 | + cfgService.unregisterConfigFactory(deviceConfigFactory); |
355 | - cfgService.unregisterConfigFactory(cfgAppFactory); | 375 | + cfgService.unregisterConfigFactory(appConfigFactory); |
376 | + cfgService.unregisterConfigFactory(mcastConfigFactory); | ||
356 | 377 | ||
357 | // Withdraw ARP packet-in | 378 | // Withdraw ARP packet-in |
358 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); | 379 | TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); |
... | @@ -362,12 +383,20 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -362,12 +383,20 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
362 | packetService.removeProcessor(processor); | 383 | packetService.removeProcessor(processor); |
363 | linkService.removeListener(linkListener); | 384 | linkService.removeListener(linkListener); |
364 | deviceService.removeListener(deviceListener); | 385 | deviceService.removeListener(deviceListener); |
386 | + multicastRouteService.removeListener(mcastListener); | ||
387 | + | ||
365 | processor = null; | 388 | processor = null; |
366 | linkListener = null; | 389 | linkListener = null; |
367 | - deviceService = null; | 390 | + deviceListener = null; |
368 | - | ||
369 | groupHandlerMap.clear(); | 391 | groupHandlerMap.clear(); |
370 | 392 | ||
393 | + nsNextObjStore.destroy(); | ||
394 | + subnetNextObjStore.destroy(); | ||
395 | + portNextObjStore.destroy(); | ||
396 | + xConnectNextObjStore.destroy(); | ||
397 | + tunnelStore.destroy(); | ||
398 | + policyStore.destroy(); | ||
399 | + subnetVidStore.destroy(); | ||
371 | log.info("Stopped"); | 400 | log.info("Stopped"); |
372 | } | 401 | } |
373 | 402 | ||
... | @@ -1186,6 +1215,27 @@ public class SegmentRoutingManager implements SegmentRoutingService { | ... | @@ -1186,6 +1215,27 @@ public class SegmentRoutingManager implements SegmentRoutingService { |
1186 | } | 1215 | } |
1187 | } | 1216 | } |
1188 | 1217 | ||
1218 | + private class InternalMcastListener implements McastListener { | ||
1219 | + @Override | ||
1220 | + public void event(McastEvent event) { | ||
1221 | + switch (event.type()) { | ||
1222 | + case SOURCE_ADDED: | ||
1223 | + mcastEventHandler.processSourceAdded(event); | ||
1224 | + break; | ||
1225 | + case SINK_ADDED: | ||
1226 | + mcastEventHandler.processSinkAdded(event); | ||
1227 | + break; | ||
1228 | + case SINK_REMOVED: | ||
1229 | + mcastEventHandler.processSinkRemoved(event); | ||
1230 | + break; | ||
1231 | + case ROUTE_ADDED: | ||
1232 | + case ROUTE_REMOVED: | ||
1233 | + default: | ||
1234 | + break; | ||
1235 | + } | ||
1236 | + } | ||
1237 | + } | ||
1238 | + | ||
1189 | private static class BridgingTableObjectiveContext implements ObjectiveContext { | 1239 | private static class BridgingTableObjectiveContext implements ObjectiveContext { |
1190 | final MacAddress mac; | 1240 | final MacAddress mac; |
1191 | final VlanId vlanId; | 1241 | final VlanId vlanId; | ... | ... |
... | @@ -496,12 +496,22 @@ public class DeviceConfiguration implements DeviceProperties { | ... | @@ -496,12 +496,22 @@ public class DeviceConfiguration implements DeviceProperties { |
496 | return srinfo != null && srinfo.adjacencySids.containsKey(sid); | 496 | return srinfo != null && srinfo.adjacencySids.containsKey(sid); |
497 | } | 497 | } |
498 | 498 | ||
499 | + /** | ||
500 | + * Gets connect points for which segment routing does not install subnet rules. | ||
501 | + * | ||
502 | + * @return set of connect points | ||
503 | + */ | ||
499 | public Set<ConnectPoint> suppressSubnet() { | 504 | public Set<ConnectPoint> suppressSubnet() { |
500 | SegmentRoutingAppConfig appConfig = | 505 | SegmentRoutingAppConfig appConfig = |
501 | cfgService.getConfig(appId, SegmentRoutingAppConfig.class); | 506 | cfgService.getConfig(appId, SegmentRoutingAppConfig.class); |
502 | return (appConfig != null) ? appConfig.suppressSubnet() : ImmutableSet.of(); | 507 | return (appConfig != null) ? appConfig.suppressSubnet() : ImmutableSet.of(); |
503 | } | 508 | } |
504 | 509 | ||
510 | + /** | ||
511 | + * Gets connect points for which segment routing does not install host rules. | ||
512 | + * | ||
513 | + * @return set of connect points | ||
514 | + */ | ||
505 | public Set<ConnectPoint> suppressHost() { | 515 | public Set<ConnectPoint> suppressHost() { |
506 | SegmentRoutingAppConfig appConfig = | 516 | SegmentRoutingAppConfig appConfig = |
507 | cfgService.getConfig(appId, SegmentRoutingAppConfig.class); | 517 | cfgService.getConfig(appId, SegmentRoutingAppConfig.class); | ... | ... |
1 | +/* | ||
2 | + * Copyright 2015-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.segmentrouting.grouphandler; | ||
18 | + | ||
19 | +import org.onlab.packet.IpAddress; | ||
20 | +import org.onosproject.net.DeviceId; | ||
21 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
22 | +import static com.google.common.base.Preconditions.checkArgument; | ||
23 | +import static com.google.common.base.Preconditions.checkNotNull; | ||
24 | +import java.util.Objects; | ||
25 | + | ||
26 | +/** | ||
27 | + * Key of multicast next objective store. | ||
28 | + */ | ||
29 | +public class McastNextObjectiveStoreKey { | ||
30 | + private final IpAddress mcastIp; | ||
31 | + private final DeviceId deviceId; | ||
32 | + | ||
33 | + /** | ||
34 | + * Constructs the key of multicast next objective store. | ||
35 | + * | ||
36 | + * @param mcastIp multicast group IP address | ||
37 | + * @param deviceId device ID | ||
38 | + */ | ||
39 | + public McastNextObjectiveStoreKey(IpAddress mcastIp, DeviceId deviceId) { | ||
40 | + checkNotNull(mcastIp, "mcastIp cannot be null"); | ||
41 | + checkNotNull(deviceId, "deviceId cannot be null"); | ||
42 | + checkArgument(mcastIp.isMulticast(), "mcastIp must be a multicast address"); | ||
43 | + this.mcastIp = mcastIp; | ||
44 | + this.deviceId = deviceId; | ||
45 | + } | ||
46 | + | ||
47 | + /** | ||
48 | + * Returns the multicast IP address of this key. | ||
49 | + * | ||
50 | + * @return multicast IP | ||
51 | + */ | ||
52 | + public IpAddress mcastIp() { | ||
53 | + return this.mcastIp; | ||
54 | + } | ||
55 | + | ||
56 | + /** | ||
57 | + * Returns the device ID of this key. | ||
58 | + * | ||
59 | + * @return device ID | ||
60 | + */ | ||
61 | + public DeviceId deviceId() { | ||
62 | + return this.deviceId; | ||
63 | + } | ||
64 | + | ||
65 | + @Override | ||
66 | + public boolean equals(Object o) { | ||
67 | + if (this == o) { | ||
68 | + return true; | ||
69 | + } | ||
70 | + if (!(o instanceof McastNextObjectiveStoreKey)) { | ||
71 | + return false; | ||
72 | + } | ||
73 | + McastNextObjectiveStoreKey that = | ||
74 | + (McastNextObjectiveStoreKey) o; | ||
75 | + return (Objects.equals(this.mcastIp, that.mcastIp) && | ||
76 | + Objects.equals(this.deviceId, that.deviceId)); | ||
77 | + } | ||
78 | + | ||
79 | + @Override | ||
80 | + public int hashCode() { | ||
81 | + return Objects.hash(mcastIp, deviceId); | ||
82 | + } | ||
83 | + | ||
84 | + @Override | ||
85 | + public String toString() { | ||
86 | + return toStringHelper(getClass()) | ||
87 | + .add("mcastIp", mcastIp) | ||
88 | + .add("deviceId", deviceId) | ||
89 | + .toString(); | ||
90 | + } | ||
91 | +} |
... | @@ -22,6 +22,7 @@ import java.util.Collections; | ... | @@ -22,6 +22,7 @@ import java.util.Collections; |
22 | import java.util.Optional; | 22 | import java.util.Optional; |
23 | import java.util.Set; | 23 | import java.util.Set; |
24 | 24 | ||
25 | +import static com.google.common.base.MoreObjects.toStringHelper; | ||
25 | import static com.google.common.base.Preconditions.checkNotNull; | 26 | import static com.google.common.base.Preconditions.checkNotNull; |
26 | 27 | ||
27 | /** | 28 | /** |
... | @@ -102,4 +103,13 @@ public final class McastRouteInfo { | ... | @@ -102,4 +103,13 @@ public final class McastRouteInfo { |
102 | return sinks; | 103 | return sinks; |
103 | } | 104 | } |
104 | 105 | ||
106 | + @Override | ||
107 | + public String toString() { | ||
108 | + return toStringHelper(this) | ||
109 | + .add("route", route()) | ||
110 | + .add("sink", sink()) | ||
111 | + .add("source", source()) | ||
112 | + .add("sinks", sinks()) | ||
113 | + .toString(); | ||
114 | + } | ||
105 | } | 115 | } | ... | ... |
... | @@ -22,8 +22,6 @@ import java.util.Collection; | ... | @@ -22,8 +22,6 @@ import java.util.Collection; |
22 | import java.util.Collections; | 22 | import java.util.Collections; |
23 | import java.util.Deque; | 23 | import java.util.Deque; |
24 | import java.util.List; | 24 | import java.util.List; |
25 | -import java.util.Set; | ||
26 | -import java.util.concurrent.ConcurrentHashMap; | ||
27 | 25 | ||
28 | import com.google.common.collect.ImmutableList; | 26 | import com.google.common.collect.ImmutableList; |
29 | import com.google.common.collect.ImmutableSet; | 27 | import com.google.common.collect.ImmutableSet; |
... | @@ -279,17 +277,6 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline { | ... | @@ -279,17 +277,6 @@ public class CpqdOfdpa2Pipeline extends Ofdpa2Pipeline { |
279 | } | 277 | } |
280 | 278 | ||
281 | for (PortNumber pnum : portnums) { | 279 | for (PortNumber pnum : portnums) { |
282 | - // update storage | ||
283 | - groupHandler.port2Vlan.put(pnum, storeVlan); | ||
284 | - Set<PortNumber> vlanPorts = groupHandler.vlan2Port.get(storeVlan); | ||
285 | - if (vlanPorts == null) { | ||
286 | - vlanPorts = Collections.newSetFromMap( | ||
287 | - new ConcurrentHashMap<PortNumber, Boolean>()); | ||
288 | - vlanPorts.add(pnum); | ||
289 | - groupHandler.vlan2Port.put(storeVlan, vlanPorts); | ||
290 | - } else { | ||
291 | - vlanPorts.add(pnum); | ||
292 | - } | ||
293 | // create rest of flowrule | 280 | // create rest of flowrule |
294 | selector.matchInPort(pnum); | 281 | selector.matchInPort(pnum); |
295 | FlowRule rule = DefaultFlowRule.builder() | 282 | FlowRule rule = DefaultFlowRule.builder() | ... | ... |
... | @@ -65,7 +65,6 @@ import java.util.Collection; | ... | @@ -65,7 +65,6 @@ import java.util.Collection; |
65 | import java.util.Collections; | 65 | import java.util.Collections; |
66 | import java.util.Deque; | 66 | import java.util.Deque; |
67 | import java.util.List; | 67 | import java.util.List; |
68 | -import java.util.Map; | ||
69 | import java.util.Objects; | 68 | import java.util.Objects; |
70 | import java.util.Set; | 69 | import java.util.Set; |
71 | import java.util.concurrent.ConcurrentHashMap; | 70 | import java.util.concurrent.ConcurrentHashMap; |
... | @@ -123,10 +122,6 @@ public class Ofdpa2GroupHandler { | ... | @@ -123,10 +122,6 @@ public class Ofdpa2GroupHandler { |
123 | // index number for group creation | 122 | // index number for group creation |
124 | private AtomicCounter nextIndex; | 123 | private AtomicCounter nextIndex; |
125 | 124 | ||
126 | - // local stores for port-vlan mapping | ||
127 | - protected Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<>(); | ||
128 | - protected Map<VlanId, Set<PortNumber>> vlan2Port = new ConcurrentHashMap<>(); | ||
129 | - | ||
130 | // local store for pending bucketAdds - by design there can only be one | 125 | // local store for pending bucketAdds - by design there can only be one |
131 | // pending bucket for a group | 126 | // pending bucket for a group |
132 | protected ConcurrentHashMap<Integer, NextObjective> pendingBuckets = new ConcurrentHashMap<>(); | 127 | protected ConcurrentHashMap<Integer, NextObjective> pendingBuckets = new ConcurrentHashMap<>(); | ... | ... |
... | @@ -313,31 +313,22 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -313,31 +313,22 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
313 | } | 313 | } |
314 | 314 | ||
315 | VlanId assignedVlan = null; | 315 | VlanId assignedVlan = null; |
316 | - // For VLAN cross-connect packets, use the configured VLAN | ||
317 | if (vidCriterion != null) { | 316 | if (vidCriterion != null) { |
318 | - if (vidCriterion.vlanId() != VlanId.NONE) { | 317 | + // Use the VLAN in metadata whenever a metadata is provided |
318 | + if (filt.meta() != null) { | ||
319 | + assignedVlan = readVlanFromTreatment(filt.meta()); | ||
320 | + // Use the VLAN in criterion if metadata is not present and the traffic is tagged | ||
321 | + } else if (!vidCriterion.vlanId().equals(VlanId.NONE)) { | ||
319 | assignedVlan = vidCriterion.vlanId(); | 322 | assignedVlan = vidCriterion.vlanId(); |
323 | + } | ||
320 | 324 | ||
321 | - // For untagged packets, assign a VLAN ID | 325 | + if (assignedVlan == null) { |
322 | - } else { | 326 | + log.error("Driver fails to extract VLAN information. " |
323 | - if (filt.meta() == null) { | 327 | + + "Not proccessing VLAN filters on device {}.", deviceId); |
324 | - log.error("Missing metadata in filtering objective required " + | 328 | + log.debug("VLAN ID in criterion={}, metadata={}", |
325 | - "for vlan assignment in dev {}", deviceId); | 329 | + readVlanFromTreatment(filt.meta()), vidCriterion.vlanId()); |
326 | - fail(filt, ObjectiveError.BADPARAMS); | 330 | + fail(filt, ObjectiveError.BADPARAMS); |
327 | - return; | 331 | + return; |
328 | - } | ||
329 | - for (Instruction i : filt.meta().allInstructions()) { | ||
330 | - if (i instanceof ModVlanIdInstruction) { | ||
331 | - assignedVlan = ((ModVlanIdInstruction) i).vlanId(); | ||
332 | - } | ||
333 | - } | ||
334 | - if (assignedVlan == null) { | ||
335 | - log.error("Driver requires an assigned vlan-id to tag incoming " | ||
336 | - + "untagged packets. Not processing vlan filters on " | ||
337 | - + "device {}", deviceId); | ||
338 | - fail(filt, ObjectiveError.BADPARAMS); | ||
339 | - return; | ||
340 | - } | ||
341 | } | 332 | } |
342 | } | 333 | } |
343 | 334 | ||
... | @@ -457,22 +448,14 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -457,22 +448,14 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
457 | TrafficSelector.Builder preSelector = null; | 448 | TrafficSelector.Builder preSelector = null; |
458 | TrafficTreatment.Builder preTreatment = null; | 449 | TrafficTreatment.Builder preTreatment = null; |
459 | 450 | ||
460 | - | ||
461 | treatment.transition(TMAC_TABLE); | 451 | treatment.transition(TMAC_TABLE); |
462 | 452 | ||
463 | - VlanId storeVlan = null; | ||
464 | if (vidCriterion.vlanId() == VlanId.NONE) { | 453 | if (vidCriterion.vlanId() == VlanId.NONE) { |
465 | // untagged packets are assigned vlans | 454 | // untagged packets are assigned vlans |
466 | OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(VlanId.NONE); | 455 | OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(VlanId.NONE); |
467 | selector.extension(ofdpaMatchVlanVid, deviceId); | 456 | selector.extension(ofdpaMatchVlanVid, deviceId); |
468 | OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(assignedVlan); | 457 | OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(assignedVlan); |
469 | treatment.extension(ofdpaSetVlanVid, deviceId); | 458 | treatment.extension(ofdpaSetVlanVid, deviceId); |
470 | - // ofdpa requires an additional vlan match rule for the assigned vlan | ||
471 | - // and it does not require the push when setting the assigned vlan. | ||
472 | - // It also requires the extra rule to be sent to the switch before we | ||
473 | - // send the untagged match rule. | ||
474 | - // None of this in compliance with OF standard. | ||
475 | - storeVlan = assignedVlan; | ||
476 | 459 | ||
477 | preSelector = DefaultTrafficSelector.builder(); | 460 | preSelector = DefaultTrafficSelector.builder(); |
478 | OfdpaMatchVlanVid preOfdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan); | 461 | OfdpaMatchVlanVid preOfdpaMatchVlanVid = new OfdpaMatchVlanVid(assignedVlan); |
... | @@ -482,7 +465,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -482,7 +465,11 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
482 | } else { | 465 | } else { |
483 | OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vidCriterion.vlanId()); | 466 | OfdpaMatchVlanVid ofdpaMatchVlanVid = new OfdpaMatchVlanVid(vidCriterion.vlanId()); |
484 | selector.extension(ofdpaMatchVlanVid, deviceId); | 467 | selector.extension(ofdpaMatchVlanVid, deviceId); |
485 | - storeVlan = vidCriterion.vlanId(); | 468 | + |
469 | + if (!assignedVlan.equals(vidCriterion.vlanId())) { | ||
470 | + OfdpaSetVlanVid ofdpaSetVlanVid = new OfdpaSetVlanVid(assignedVlan); | ||
471 | + treatment.extension(ofdpaSetVlanVid, deviceId); | ||
472 | + } | ||
486 | } | 473 | } |
487 | 474 | ||
488 | // ofdpa cannot match on ALL portnumber, so we need to use separate | 475 | // ofdpa cannot match on ALL portnumber, so we need to use separate |
... | @@ -499,17 +486,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -499,17 +486,6 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
499 | } | 486 | } |
500 | 487 | ||
501 | for (PortNumber pnum : portnums) { | 488 | for (PortNumber pnum : portnums) { |
502 | - // update storage | ||
503 | - groupHandler.port2Vlan.put(pnum, storeVlan); | ||
504 | - Set<PortNumber> vlanPorts = groupHandler.vlan2Port.get(storeVlan); | ||
505 | - if (vlanPorts == null) { | ||
506 | - vlanPorts = Collections.newSetFromMap( | ||
507 | - new ConcurrentHashMap<PortNumber, Boolean>()); | ||
508 | - vlanPorts.add(pnum); | ||
509 | - groupHandler.vlan2Port.put(storeVlan, vlanPorts); | ||
510 | - } else { | ||
511 | - vlanPorts.add(pnum); | ||
512 | - } | ||
513 | // create rest of flowrule | 489 | // create rest of flowrule |
514 | selector.matchInPort(pnum); | 490 | selector.matchInPort(pnum); |
515 | FlowRule rule = DefaultFlowRule.builder() | 491 | FlowRule rule = DefaultFlowRule.builder() |
... | @@ -1112,4 +1088,13 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline | ... | @@ -1112,4 +1088,13 @@ public class Ofdpa2Pipeline extends AbstractHandlerBehaviour implements Pipeline |
1112 | Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST); | 1088 | Criterion criterion = selector.getCriterion(Criterion.Type.IPV4_DST); |
1113 | return (criterion == null) ? null : ((IPCriterion) criterion).ip(); | 1089 | return (criterion == null) ? null : ((IPCriterion) criterion).ip(); |
1114 | } | 1090 | } |
1091 | + | ||
1092 | + private static VlanId readVlanFromTreatment(TrafficTreatment treatment) { | ||
1093 | + for (Instruction i : treatment.allInstructions()) { | ||
1094 | + if (i instanceof ModVlanIdInstruction) { | ||
1095 | + return ((ModVlanIdInstruction) i).vlanId(); | ||
1096 | + } | ||
1097 | + } | ||
1098 | + return null; | ||
1099 | + } | ||
1115 | } | 1100 | } | ... | ... |
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.config.basics; | ||
18 | + | ||
19 | +import com.google.common.annotations.Beta; | ||
20 | +import org.onlab.packet.VlanId; | ||
21 | +import org.onosproject.core.ApplicationId; | ||
22 | +import org.onosproject.net.config.Config; | ||
23 | + | ||
24 | +/** | ||
25 | + * Configuration for multicast. | ||
26 | + */ | ||
27 | +@Beta | ||
28 | +public class McastConfig extends Config<ApplicationId> { | ||
29 | + private static final String INGRESS_VLAN = "ingressVlan"; | ||
30 | + private static final String EGRESS_VLAN = "egressVlan"; | ||
31 | + | ||
32 | + @Override | ||
33 | + public boolean isValid() { | ||
34 | + return hasOnlyFields(INGRESS_VLAN, EGRESS_VLAN) && | ||
35 | + ingressVlan() != null && egressVlan() != null; | ||
36 | + } | ||
37 | + | ||
38 | + /** | ||
39 | + * Gets ingress VLAN of multicast traffic. | ||
40 | + * | ||
41 | + * @return Ingress VLAN ID | ||
42 | + */ | ||
43 | + public VlanId ingressVlan() { | ||
44 | + if (!object.has(INGRESS_VLAN)) { | ||
45 | + return VlanId.NONE; | ||
46 | + } | ||
47 | + | ||
48 | + try { | ||
49 | + return VlanId.vlanId(object.path(INGRESS_VLAN).asText()); | ||
50 | + } catch (IllegalArgumentException e) { | ||
51 | + return null; | ||
52 | + } | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * Sets ingress VLAN of multicast traffic. | ||
57 | + * | ||
58 | + * @param vlanId Ingress VLAN ID | ||
59 | + * @return this {@link McastConfig} | ||
60 | + */ | ||
61 | + public McastConfig setIngressVlan(VlanId vlanId) { | ||
62 | + if (vlanId == null) { | ||
63 | + object.remove(INGRESS_VLAN); | ||
64 | + } else { | ||
65 | + object.put(INGRESS_VLAN, vlanId.toString()); | ||
66 | + } | ||
67 | + return this; | ||
68 | + } | ||
69 | + | ||
70 | + /** | ||
71 | + * Gets egress VLAN of multicast traffic. | ||
72 | + * | ||
73 | + * @return Egress VLAN ID | ||
74 | + */ | ||
75 | + public VlanId egressVlan() { | ||
76 | + if (!object.has(EGRESS_VLAN)) { | ||
77 | + return VlanId.NONE; | ||
78 | + } | ||
79 | + | ||
80 | + try { | ||
81 | + return VlanId.vlanId(object.path(EGRESS_VLAN).asText()); | ||
82 | + } catch (IllegalArgumentException e) { | ||
83 | + return null; | ||
84 | + } | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Sets egress VLAN of multicast traffic. | ||
89 | + * | ||
90 | + * @param vlanId Egress VLAN ID | ||
91 | + * @return this {@link McastConfig} | ||
92 | + */ | ||
93 | + public McastConfig setEgressVlan(VlanId vlanId) { | ||
94 | + if (vlanId == null) { | ||
95 | + object.remove(EGRESS_VLAN); | ||
96 | + } else { | ||
97 | + object.put(EGRESS_VLAN, vlanId.toString()); | ||
98 | + } | ||
99 | + return this; | ||
100 | + } | ||
101 | +} |
incubator/api/src/test/java/org/onosproject/incubator/net/config/basics/McastConfigTest.java
0 → 100644
1 | +/* | ||
2 | + * Copyright 2016-present Open Networking Laboratory | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +package org.onosproject.incubator.net.config.basics; | ||
18 | + | ||
19 | +import com.fasterxml.jackson.databind.JsonNode; | ||
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | ||
21 | +import com.google.common.annotations.Beta; | ||
22 | +import org.junit.Before; | ||
23 | +import org.junit.Test; | ||
24 | +import org.onlab.packet.VlanId; | ||
25 | +import org.onosproject.TestApplicationId; | ||
26 | +import org.onosproject.core.ApplicationId; | ||
27 | +import org.onosproject.core.CoreService; | ||
28 | +import org.onosproject.net.config.Config; | ||
29 | +import org.onosproject.net.config.ConfigApplyDelegate; | ||
30 | + | ||
31 | +import java.io.InputStream; | ||
32 | + | ||
33 | +import static org.hamcrest.Matchers.is; | ||
34 | +import static org.junit.Assert.*; | ||
35 | + | ||
36 | +/** | ||
37 | + * Tests for class {@link McastConfig}. | ||
38 | + */ | ||
39 | +@Beta | ||
40 | +public class McastConfigTest { | ||
41 | + private static final TestApplicationId APP_ID = | ||
42 | + new TestApplicationId(CoreService.CORE_APP_NAME); | ||
43 | + private McastConfig config; | ||
44 | + private McastConfig invalidConfig; | ||
45 | + | ||
46 | + private static final VlanId INGRESS_VLAN_1 = VlanId.NONE; | ||
47 | + private static final VlanId EGRESS_VLAN_1 = VlanId.NONE; | ||
48 | + private static final VlanId INGRESS_VLAN_2 = VlanId.vlanId((short) 100); | ||
49 | + private static final VlanId EGRESS_VLAN_2 = VlanId.vlanId((short) 100); | ||
50 | + | ||
51 | + /** | ||
52 | + * Initialize test related variables. | ||
53 | + * | ||
54 | + * @throws Exception | ||
55 | + */ | ||
56 | + @Before | ||
57 | + public void setUp() throws Exception { | ||
58 | + InputStream jsonStream = McastConfigTest.class | ||
59 | + .getResourceAsStream("/mcast-config.json"); | ||
60 | + InputStream invalidJsonStream = McastConfigTest.class | ||
61 | + .getResourceAsStream("/mcast-config-invalid.json"); | ||
62 | + | ||
63 | + ApplicationId subject = APP_ID; | ||
64 | + String key = CoreService.CORE_APP_NAME; | ||
65 | + ObjectMapper mapper = new ObjectMapper(); | ||
66 | + JsonNode jsonNode = mapper.readTree(jsonStream); | ||
67 | + JsonNode invalidJsonNode = mapper.readTree(invalidJsonStream); | ||
68 | + ConfigApplyDelegate delegate = new MockDelegate(); | ||
69 | + | ||
70 | + config = new McastConfig(); | ||
71 | + config.init(subject, key, jsonNode, mapper, delegate); | ||
72 | + invalidConfig = new McastConfig(); | ||
73 | + invalidConfig.init(subject, key, invalidJsonNode, mapper, delegate); | ||
74 | + } | ||
75 | + | ||
76 | + /** | ||
77 | + * Tests config validity. | ||
78 | + * | ||
79 | + * @throws Exception | ||
80 | + */ | ||
81 | + @Test | ||
82 | + public void isValid() throws Exception { | ||
83 | + assertTrue(config.isValid()); | ||
84 | + assertFalse(invalidConfig.isValid()); | ||
85 | + } | ||
86 | + | ||
87 | + /** | ||
88 | + * Tests ingress VLAN getter. | ||
89 | + * | ||
90 | + * @throws Exception | ||
91 | + */ | ||
92 | + @Test | ||
93 | + public void ingressVlan() throws Exception { | ||
94 | + VlanId ingressVlan = config.ingressVlan(); | ||
95 | + assertNotNull("ingressVlan should not be null", ingressVlan); | ||
96 | + assertThat(ingressVlan, is(INGRESS_VLAN_1)); | ||
97 | + } | ||
98 | + | ||
99 | + /** | ||
100 | + * Tests ingress VLAN setter. | ||
101 | + * | ||
102 | + * @throws Exception | ||
103 | + */ | ||
104 | + @Test | ||
105 | + public void setIngressVlan() throws Exception { | ||
106 | + config.setIngressVlan(INGRESS_VLAN_2); | ||
107 | + | ||
108 | + VlanId ingressVlan = config.ingressVlan(); | ||
109 | + assertNotNull("ingressVlan should not be null", ingressVlan); | ||
110 | + assertThat(ingressVlan, is(INGRESS_VLAN_2)); | ||
111 | + } | ||
112 | + | ||
113 | + /** | ||
114 | + * Tests egress VLAN getter. | ||
115 | + * | ||
116 | + * @throws Exception | ||
117 | + */ | ||
118 | + @Test | ||
119 | + public void egressVlan() throws Exception { | ||
120 | + VlanId egressVlan = config.egressVlan(); | ||
121 | + assertNotNull("egressVlan should not be null", egressVlan); | ||
122 | + assertThat(egressVlan, is(EGRESS_VLAN_1)); | ||
123 | + } | ||
124 | + | ||
125 | + /** | ||
126 | + * Tests egress VLAN setter. | ||
127 | + * | ||
128 | + * @throws Exception | ||
129 | + */ | ||
130 | + @Test | ||
131 | + public void setEgressVlan() throws Exception { | ||
132 | + config.setEgressVlan(EGRESS_VLAN_2); | ||
133 | + | ||
134 | + VlanId egressVlan = config.egressVlan(); | ||
135 | + assertNotNull("egressVlan should not be null", egressVlan); | ||
136 | + assertThat(egressVlan, is(EGRESS_VLAN_2)); | ||
137 | + } | ||
138 | + | ||
139 | + private class MockDelegate implements ConfigApplyDelegate { | ||
140 | + @Override | ||
141 | + public void onApply(Config config) { | ||
142 | + } | ||
143 | + } | ||
144 | +} | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
-
Please register or login to post a comment