Charles Chan
Committed by Gerrit Code Review

[CORD-46] Create a broadcast group for each subnet

DONE
- Expose subnet-to-ports information from DeviceProperties and DeviceConfiguration
- Create subnetNextObjectiveStore to store <DeviceId, IpPrefix> to nextId mapping
- Implement broadcast NextObjective in SpringOpenTTP
      Use ALL group type to achieve broadcast

TODO (not in this submission)
- Push ARP table for a host when its location is learned
- Push default ARP table miss rule. Action = to the broadcast group

Change-Id: I2de28095e85289e75af3fc7a02c811b270b342ad
...@@ -23,7 +23,6 @@ import org.onlab.packet.IpPrefix; ...@@ -23,7 +23,6 @@ import org.onlab.packet.IpPrefix;
23 import org.onosproject.net.Device; 23 import org.onosproject.net.Device;
24 import org.onosproject.net.DeviceId; 24 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.Link; 25 import org.onosproject.net.Link;
26 -import org.onosproject.net.MastershipRole;
27 import org.slf4j.Logger; 26 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
29 28
...@@ -97,7 +96,7 @@ public class DefaultRoutingHandler { ...@@ -97,7 +96,7 @@ public class DefaultRoutingHandler {
97 log.debug("populateAllRoutingRules: populationStatus is STARTED"); 96 log.debug("populateAllRoutingRules: populationStatus is STARTED");
98 97
99 for (Device sw : srManager.deviceService.getDevices()) { 98 for (Device sw : srManager.deviceService.getDevices()) {
100 - if (srManager.mastershipService.getLocalRole(sw.id()) != MastershipRole.MASTER) { 99 + if (!srManager.mastershipService.isLocalMaster(sw.id())) {
101 log.debug("populateAllRoutingRules: skipping device {}...we are not master", 100 log.debug("populateAllRoutingRules: skipping device {}...we are not master",
102 sw.id()); 101 sw.id());
103 continue; 102 continue;
...@@ -146,8 +145,7 @@ public class DefaultRoutingHandler { ...@@ -146,8 +145,7 @@ public class DefaultRoutingHandler {
146 // Take the snapshots of the links 145 // Take the snapshots of the links
147 updatedEcmpSpgMap = new HashMap<>(); 146 updatedEcmpSpgMap = new HashMap<>();
148 for (Device sw : srManager.deviceService.getDevices()) { 147 for (Device sw : srManager.deviceService.getDevices()) {
149 - if (srManager.mastershipService. 148 + if (!srManager.mastershipService.isLocalMaster(sw.id())) {
150 - getLocalRole(sw.id()) != MastershipRole.MASTER) {
151 continue; 149 continue;
152 } 150 }
153 ECMPShortestPathGraph ecmpSpgUpdated = 151 ECMPShortestPathGraph ecmpSpgUpdated =
...@@ -273,8 +271,7 @@ public class DefaultRoutingHandler { ...@@ -273,8 +271,7 @@ public class DefaultRoutingHandler {
273 for (Device sw : srManager.deviceService.getDevices()) { 271 for (Device sw : srManager.deviceService.getDevices()) {
274 log.debug("Computing the impacted routes for device {} due to link fail", 272 log.debug("Computing the impacted routes for device {} due to link fail",
275 sw.id()); 273 sw.id());
276 - if (srManager.mastershipService. 274 + if (!srManager.mastershipService.isLocalMaster(sw.id())) {
277 - getLocalRole(sw.id()) != MastershipRole.MASTER) {
278 continue; 275 continue;
279 } 276 }
280 ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id()); 277 ECMPShortestPathGraph ecmpSpg = currentEcmpSpgMap.get(sw.id());
...@@ -320,8 +317,7 @@ public class DefaultRoutingHandler { ...@@ -320,8 +317,7 @@ public class DefaultRoutingHandler {
320 for (Device sw : srManager.deviceService.getDevices()) { 317 for (Device sw : srManager.deviceService.getDevices()) {
321 log.debug("Computing the impacted routes for device {}", 318 log.debug("Computing the impacted routes for device {}",
322 sw.id()); 319 sw.id());
323 - if (srManager.mastershipService. 320 + if (!srManager.mastershipService.isLocalMaster(sw.id())) {
324 - getLocalRole(sw.id()) != MastershipRole.MASTER) {
325 log.debug("No mastership for {} and skip route optimization", 321 log.debug("No mastership for {} and skip route optimization",
326 sw.id()); 322 sw.id());
327 continue; 323 continue;
......
...@@ -44,8 +44,6 @@ import java.util.concurrent.ConcurrentHashMap; ...@@ -44,8 +44,6 @@ import java.util.concurrent.ConcurrentHashMap;
44 * Segment Routing configuration component that reads the 44 * Segment Routing configuration component that reads the
45 * segment routing related configuration from Network Configuration Manager 45 * segment routing related configuration from Network Configuration Manager
46 * component and organizes in more accessible formats. 46 * component and organizes in more accessible formats.
47 - *
48 - * TODO: Merge multiple Segment Routing configuration wrapper classes into one.
49 */ 47 */
50 public class DeviceConfiguration implements DeviceProperties { 48 public class DeviceConfiguration implements DeviceProperties {
51 49
...@@ -251,6 +249,26 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -251,6 +249,26 @@ public class DeviceConfiguration implements DeviceProperties {
251 return allSegmentIds; 249 return allSegmentIds;
252 } 250 }
253 251
252 + @Override
253 + public Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId) {
254 + Map<Ip4Prefix, List<PortNumber>> subnetPortMap = new HashMap<>();
255 +
256 + // Construct subnet-port mapping from port-subnet mapping
257 + Map<PortNumber, Ip4Prefix> portSubnetMap =
258 + this.deviceConfigMap.get(deviceId).subnets;
259 + portSubnetMap.forEach((port, subnet) -> {
260 + if (subnetPortMap.containsKey(subnet)) {
261 + subnetPortMap.get(subnet).add(port);
262 + } else {
263 + ArrayList<PortNumber> ports = new ArrayList<>();
264 + ports.add(port);
265 + subnetPortMap.put(subnet, ports);
266 + }
267 + });
268 +
269 + return subnetPortMap;
270 + }
271 +
254 /** 272 /**
255 * Returns the device identifier or data plane identifier (dpid) 273 * Returns the device identifier or data plane identifier (dpid)
256 * of a segment router given its segment id. 274 * of a segment router given its segment id.
......
...@@ -22,13 +22,17 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -22,13 +22,17 @@ import org.apache.felix.scr.annotations.Reference;
22 import org.apache.felix.scr.annotations.ReferenceCardinality; 22 import org.apache.felix.scr.annotations.ReferenceCardinality;
23 import org.apache.felix.scr.annotations.Service; 23 import org.apache.felix.scr.annotations.Service;
24 import org.onlab.packet.Ethernet; 24 import org.onlab.packet.Ethernet;
25 +import org.onlab.packet.VlanId;
25 import org.onlab.packet.IPv4; 26 import org.onlab.packet.IPv4;
27 +import org.onlab.packet.Ip4Address;
26 import org.onlab.packet.Ip4Prefix; 28 import org.onlab.packet.Ip4Prefix;
27 -import org.onlab.packet.VlanId; 29 +import org.onlab.packet.IpAddress;
30 +import org.onlab.packet.IpPrefix;
28 import org.onlab.util.KryoNamespace; 31 import org.onlab.util.KryoNamespace;
29 import org.onosproject.core.ApplicationId; 32 import org.onosproject.core.ApplicationId;
30 import org.onosproject.core.CoreService; 33 import org.onosproject.core.CoreService;
31 import org.onosproject.event.Event; 34 import org.onosproject.event.Event;
35 +import org.onosproject.net.ConnectPoint;
32 import org.onosproject.net.config.ConfigFactory; 36 import org.onosproject.net.config.ConfigFactory;
33 import org.onosproject.net.config.NetworkConfigEvent; 37 import org.onosproject.net.config.NetworkConfigEvent;
34 import org.onosproject.net.config.NetworkConfigRegistry; 38 import org.onosproject.net.config.NetworkConfigRegistry;
...@@ -57,6 +61,7 @@ import org.onosproject.net.packet.PacketContext; ...@@ -57,6 +61,7 @@ import org.onosproject.net.packet.PacketContext;
57 import org.onosproject.net.packet.PacketProcessor; 61 import org.onosproject.net.packet.PacketProcessor;
58 import org.onosproject.net.packet.PacketService; 62 import org.onosproject.net.packet.PacketService;
59 import org.onosproject.net.topology.TopologyService; 63 import org.onosproject.net.topology.TopologyService;
64 +import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey;
60 import org.onosproject.store.service.EventuallyConsistentMap; 65 import org.onosproject.store.service.EventuallyConsistentMap;
61 import org.onosproject.store.service.EventuallyConsistentMapBuilder; 66 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
62 import org.onosproject.store.service.StorageService; 67 import org.onosproject.store.service.StorageService;
...@@ -136,6 +141,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -136,6 +141,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
136 // Per device next objective ID store with (device id + neighbor set) as key 141 // Per device next objective ID store with (device id + neighbor set) as key
137 private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, 142 private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
138 Integer> nsNextObjStore = null; 143 Integer> nsNextObjStore = null;
144 + private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null;
139 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null; 145 private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
140 private EventuallyConsistentMap<String, Policy> policyStore = null; 146 private EventuallyConsistentMap<String, Policy> policyStore = null;
141 // Per device, per-subnet assigned-vlans store, with (device id + subnet 147 // Per device, per-subnet assigned-vlans store, with (device id + subnet
...@@ -180,6 +186,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -180,6 +186,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
180 186
181 kryoBuilder = new KryoNamespace.Builder() 187 kryoBuilder = new KryoNamespace.Builder()
182 .register(NeighborSetNextObjectiveStoreKey.class, 188 .register(NeighborSetNextObjectiveStoreKey.class,
189 + SubnetNextObjectiveStoreKey.class,
190 + SubnetAssignedVidStoreKey.class,
183 NeighborSet.class, 191 NeighborSet.class,
184 DeviceId.class, 192 DeviceId.class,
185 URI.class, 193 URI.class,
...@@ -191,8 +199,11 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -191,8 +199,11 @@ public class SegmentRoutingManager implements SegmentRoutingService {
191 Policy.class, 199 Policy.class,
192 TunnelPolicy.class, 200 TunnelPolicy.class,
193 Policy.Type.class, 201 Policy.Type.class,
194 - SubnetAssignedVidStoreKey.class, 202 + VlanId.class,
195 - VlanId.class 203 + Ip4Address.class,
204 + Ip4Prefix.class,
205 + IpAddress.Version.class,
206 + ConnectPoint.class
196 ); 207 );
197 208
198 log.debug("Creating EC map nsnextobjectivestore"); 209 log.debug("Creating EC map nsnextobjectivestore");
...@@ -206,6 +217,16 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -206,6 +217,16 @@ public class SegmentRoutingManager implements SegmentRoutingService {
206 .build(); 217 .build();
207 log.trace("Current size {}", nsNextObjStore.size()); 218 log.trace("Current size {}", nsNextObjStore.size());
208 219
220 + log.debug("Creating EC map subnetnextobjectivestore");
221 + EventuallyConsistentMapBuilder<SubnetNextObjectiveStoreKey, Integer>
222 + subnetNextObjMapBuilder = storageService.eventuallyConsistentMapBuilder();
223 +
224 + subnetNextObjStore = subnetNextObjMapBuilder
225 + .withName("subnetnextobjectivestore")
226 + .withSerializer(kryoBuilder)
227 + .withTimestampProvider((k, v) -> new WallClockTimestamp())
228 + .build();
229 +
209 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder = 230 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
210 storageService.eventuallyConsistentMapBuilder(); 231 storageService.eventuallyConsistentMapBuilder();
211 232
...@@ -399,6 +420,25 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -399,6 +420,25 @@ public class SegmentRoutingManager implements SegmentRoutingService {
399 } 420 }
400 } 421 }
401 422
423 + /**
424 + * Returns the next objective ID for the Subnet given. If the nextObjectiveID does not exist,
425 + * a new one is created and returned.
426 + *
427 + * @param deviceId Device ID
428 + * @param prefix Subnet
429 + * @return next objective ID
430 + */
431 + public int getSubnetNextObjectiveId(DeviceId deviceId, IpPrefix prefix) {
432 + if (groupHandlerMap.get(deviceId) != null) {
433 + log.trace("getSubnetNextObjectiveId query in device {}", deviceId);
434 + return groupHandlerMap
435 + .get(deviceId).getSubnetNextObjectiveId(prefix);
436 + } else {
437 + log.warn("getSubnetNextObjectiveId query in device {} not found", deviceId);
438 + return -1;
439 + }
440 + }
441 +
402 private class InternalPacketProcessor implements PacketProcessor { 442 private class InternalPacketProcessor implements PacketProcessor {
403 @Override 443 @Override
404 public void process(PacketContext context) { 444 public void process(PacketContext context) {
...@@ -559,15 +599,20 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -559,15 +599,20 @@ public class SegmentRoutingManager implements SegmentRoutingService {
559 //Because in a multi-instance setup, instances can initiate 599 //Because in a multi-instance setup, instances can initiate
560 //groups for any devices. Also the default TTP rules are needed 600 //groups for any devices. Also the default TTP rules are needed
561 //to be pushed before inserting any IP table entries for any device 601 //to be pushed before inserting any IP table entries for any device
562 - DefaultGroupHandler dgh = DefaultGroupHandler. 602 + DefaultGroupHandler groupHandler = DefaultGroupHandler.
563 createGroupHandler(device.id(), 603 createGroupHandler(device.id(),
564 appId, 604 appId,
565 deviceConfiguration, 605 deviceConfiguration,
566 linkService, 606 linkService,
567 flowObjectiveService, 607 flowObjectiveService,
568 - nsNextObjStore); 608 + nsNextObjStore,
569 - groupHandlerMap.put(device.id(), dgh); 609 + subnetNextObjStore);
610 + groupHandlerMap.put(device.id(), groupHandler);
570 defaultRoutingHandler.populatePortAddressingRules(device.id()); 611 defaultRoutingHandler.populatePortAddressingRules(device.id());
612 +
613 + if (mastershipService.isLocalMaster(device.id())) {
614 + groupHandler.createGroupsFromSubnetConfig();
615 + }
571 } 616 }
572 617
573 private void processPortRemoved(Device device, Port port) { 618 private void processPortRemoved(Device device, Port port) {
...@@ -610,9 +655,14 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -610,9 +655,14 @@ public class SegmentRoutingManager implements SegmentRoutingService {
610 .createGroupHandler(device.id(), appId, 655 .createGroupHandler(device.id(), appId,
611 deviceConfiguration, linkService, 656 deviceConfiguration, linkService,
612 flowObjectiveService, 657 flowObjectiveService,
613 - nsNextObjStore); 658 + nsNextObjStore,
659 + subnetNextObjStore);
614 groupHandlerMap.put(device.id(), groupHandler); 660 groupHandlerMap.put(device.id(), groupHandler);
615 defaultRoutingHandler.populatePortAddressingRules(device.id()); 661 defaultRoutingHandler.populatePortAddressingRules(device.id());
662 +
663 + if (mastershipService.isLocalMaster(device.id())) {
664 + groupHandler.createGroupsFromSubnetConfig();
665 + }
616 } 666 }
617 667
618 defaultRoutingHandler.startPopulationProcess(); 668 defaultRoutingHandler.startPopulationProcess();
......
...@@ -53,8 +53,11 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler { ...@@ -53,8 +53,11 @@ public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
53 FlowObjectiveService flowObjService, 53 FlowObjectiveService flowObjService,
54 EventuallyConsistentMap< 54 EventuallyConsistentMap<
55 NeighborSetNextObjectiveStoreKey, 55 NeighborSetNextObjectiveStoreKey,
56 - Integer> nsNextObjStore) { 56 + Integer> nsNextObjStore,
57 - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); 57 + EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
58 + Integer> subnetNextObjStore) {
59 + super(deviceId, appId, config, linkService, flowObjService,
60 + nsNextObjStore, subnetNextObjStore);
58 } 61 }
59 62
60 @Override 63 @Override
......
...@@ -25,10 +25,11 @@ import java.util.HashMap; ...@@ -25,10 +25,11 @@ import java.util.HashMap;
25 import java.util.HashSet; 25 import java.util.HashSet;
26 import java.util.List; 26 import java.util.List;
27 import java.util.Map; 27 import java.util.Map;
28 -import java.util.Random;
29 import java.util.Set; 28 import java.util.Set;
30 import java.util.stream.Collectors; 29 import java.util.stream.Collectors;
31 30
31 +import org.onlab.packet.Ip4Prefix;
32 +import org.onlab.packet.IpPrefix;
32 import org.onlab.packet.MacAddress; 33 import org.onlab.packet.MacAddress;
33 import org.onlab.packet.MplsLabel; 34 import org.onlab.packet.MplsLabel;
34 import org.onlab.util.KryoNamespace; 35 import org.onlab.util.KryoNamespace;
...@@ -74,7 +75,8 @@ public class DefaultGroupHandler { ...@@ -74,7 +75,8 @@ public class DefaultGroupHandler {
74 // new HashMap<NeighborSet, Integer>(); 75 // new HashMap<NeighborSet, Integer>();
75 protected EventuallyConsistentMap< 76 protected EventuallyConsistentMap<
76 NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null; 77 NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null;
77 - protected Random rand = new Random(); 78 + protected EventuallyConsistentMap<
79 + SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null;
78 80
79 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() 81 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
80 .register(URI.class).register(HashSet.class) 82 .register(URI.class).register(HashSet.class)
...@@ -90,7 +92,9 @@ public class DefaultGroupHandler { ...@@ -90,7 +92,9 @@ public class DefaultGroupHandler {
90 FlowObjectiveService flowObjService, 92 FlowObjectiveService flowObjService,
91 EventuallyConsistentMap< 93 EventuallyConsistentMap<
92 NeighborSetNextObjectiveStoreKey, 94 NeighborSetNextObjectiveStoreKey,
93 - Integer> nsNextObjStore) { 95 + Integer> nsNextObjStore,
96 + EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
97 + Integer> subnetNextObjStore) {
94 this.deviceId = checkNotNull(deviceId); 98 this.deviceId = checkNotNull(deviceId);
95 this.appId = checkNotNull(appId); 99 this.appId = checkNotNull(appId);
96 this.deviceConfig = checkNotNull(config); 100 this.deviceConfig = checkNotNull(config);
...@@ -101,6 +105,7 @@ public class DefaultGroupHandler { ...@@ -101,6 +105,7 @@ public class DefaultGroupHandler {
101 nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId)); 105 nodeMacAddr = checkNotNull(config.getDeviceMac(deviceId));
102 this.flowObjectiveService = flowObjService; 106 this.flowObjectiveService = flowObjService;
103 this.nsNextObjStore = nsNextObjStore; 107 this.nsNextObjStore = nsNextObjStore;
108 + this.subnetNextObjStore = subnetNextObjStore;
104 109
105 populateNeighborMaps(); 110 populateNeighborMaps();
106 } 111 }
...@@ -115,7 +120,8 @@ public class DefaultGroupHandler { ...@@ -115,7 +120,8 @@ public class DefaultGroupHandler {
115 * @param config interface to retrieve the device properties 120 * @param config interface to retrieve the device properties
116 * @param linkService link service object 121 * @param linkService link service object
117 * @param flowObjService flow objective service object 122 * @param flowObjService flow objective service object
118 - * @param nsNextObjStore next objective store map 123 + * @param nsNextObjStore NeighborSet next objective store map
124 + * @param subnetNextObjStore subnet next objective store map
119 * @return default group handler type 125 * @return default group handler type
120 */ 126 */
121 public static DefaultGroupHandler createGroupHandler(DeviceId deviceId, 127 public static DefaultGroupHandler createGroupHandler(DeviceId deviceId,
...@@ -123,18 +129,23 @@ public class DefaultGroupHandler { ...@@ -123,18 +129,23 @@ public class DefaultGroupHandler {
123 DeviceProperties config, 129 DeviceProperties config,
124 LinkService linkService, 130 LinkService linkService,
125 FlowObjectiveService flowObjService, 131 FlowObjectiveService flowObjService,
126 - EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, 132 + EventuallyConsistentMap<
127 - Integer> nsNextObjStore) { 133 + NeighborSetNextObjectiveStoreKey,
134 + Integer> nsNextObjStore,
135 + EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
136 + Integer> subnetNextObjStore) {
128 if (config.isEdgeDevice(deviceId)) { 137 if (config.isEdgeDevice(deviceId)) {
129 return new DefaultEdgeGroupHandler(deviceId, appId, config, 138 return new DefaultEdgeGroupHandler(deviceId, appId, config,
130 linkService, 139 linkService,
131 flowObjService, 140 flowObjService,
132 - nsNextObjStore); 141 + nsNextObjStore,
142 + subnetNextObjStore);
133 } else { 143 } else {
134 return new DefaultTransitGroupHandler(deviceId, appId, config, 144 return new DefaultTransitGroupHandler(deviceId, appId, config,
135 linkService, 145 linkService,
136 flowObjService, 146 flowObjService,
137 - nsNextObjStore); 147 + nsNextObjStore,
148 + subnetNextObjStore);
138 } 149 }
139 } 150 }
140 151
...@@ -323,6 +334,44 @@ public class DefaultGroupHandler { ...@@ -323,6 +334,44 @@ public class DefaultGroupHandler {
323 } 334 }
324 335
325 /** 336 /**
337 + * Returns the next objective associated with the neighborset.
338 + * If there is no next objective for this neighborset, this API
339 + * would create a next objective and return.
340 + *
341 + * @param prefix subnet information
342 + * @return int if found or -1
343 + */
344 + public int getSubnetNextObjectiveId(IpPrefix prefix) {
345 + Integer nextId = subnetNextObjStore.
346 + get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
347 + if (nextId == null) {
348 + log.trace("getSubnetNextObjectiveId in device{}: Next objective id "
349 + + "not found for {} and creating", deviceId, prefix);
350 + log.trace("getSubnetNextObjectiveId: subnetNextObjStore contents for device {}: {}",
351 + deviceId,
352 + subnetNextObjStore.entrySet()
353 + .stream()
354 + .filter((subnetStoreEntry) ->
355 + (subnetStoreEntry.getKey().deviceId().equals(deviceId)))
356 + .collect(Collectors.toList()));
357 + createGroupsFromSubnetConfig();
358 + nextId = subnetNextObjStore.
359 + get(new SubnetNextObjectiveStoreKey(deviceId, prefix));
360 + if (nextId == null) {
361 + log.warn("subnetNextObjStore: unable to create next objective");
362 + return -1;
363 + } else {
364 + log.debug("subnetNextObjStore in device{}: Next objective id {} "
365 + + "created for {}", deviceId, nextId, prefix);
366 + }
367 + } else {
368 + log.trace("subnetNextObjStore in device{}: Next objective id {} "
369 + + "found for {}", deviceId, nextId, prefix);
370 + }
371 + return nextId;
372 + }
373 +
374 + /**
326 * Checks if the next objective ID (group) for the neighbor set exists or not. 375 * Checks if the next objective ID (group) for the neighbor set exists or not.
327 * 376 *
328 * @param ns neighbor set to check 377 * @param ns neighbor set to check
...@@ -486,6 +535,35 @@ public class DefaultGroupHandler { ...@@ -486,6 +535,35 @@ public class DefaultGroupHandler {
486 } 535 }
487 } 536 }
488 537
538 + public void createGroupsFromSubnetConfig() {
539 + Map<Ip4Prefix, List<PortNumber>> subnetPortMap =
540 + this.deviceConfig.getSubnetPortsMap(this.deviceId);
541 +
542 + // Construct a broadcast group for each subnet
543 + subnetPortMap.forEach((subnet, ports) -> {
544 + int nextId = flowObjectiveService.allocateNextId();
545 +
546 + NextObjective.Builder nextObjBuilder = DefaultNextObjective
547 + .builder().withId(nextId)
548 + .withType(NextObjective.Type.BROADCAST).fromApp(appId);
549 +
550 + ports.forEach(port -> {
551 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
552 + tBuilder.setOutput(port);
553 + nextObjBuilder.addTreatment(tBuilder.build());
554 + });
555 +
556 + NextObjective nextObj = nextObjBuilder.add();
557 + flowObjectiveService.next(deviceId, nextObj);
558 + log.debug("createGroupFromSubnetConfig: Submited "
559 + + "next objective {} in device {}",
560 + nextId, deviceId);
561 + SubnetNextObjectiveStoreKey key =
562 + new SubnetNextObjectiveStoreKey(deviceId, subnet);
563 + subnetNextObjStore.put(key, nextId);
564 + });
565 + }
566 +
489 public GroupKey getGroupKey(Object obj) { 567 public GroupKey getGroupKey(Object obj) {
490 return new DefaultGroupKey(kryo.build().serialize(obj)); 568 return new DefaultGroupKey(kryo.build().serialize(obj));
491 } 569 }
......
...@@ -46,8 +46,11 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler { ...@@ -46,8 +46,11 @@ public class DefaultTransitGroupHandler extends DefaultGroupHandler {
46 FlowObjectiveService flowObjService, 46 FlowObjectiveService flowObjService,
47 EventuallyConsistentMap< 47 EventuallyConsistentMap<
48 NeighborSetNextObjectiveStoreKey, 48 NeighborSetNextObjectiveStoreKey,
49 - Integer> nsNextObjStore) { 49 + Integer> nsNextObjStore,
50 - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); 50 + EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
51 + Integer> subnetNextObjStore) {
52 + super(deviceId, appId, config, linkService, flowObjService,
53 + nsNextObjStore, subnetNextObjStore);
51 } 54 }
52 55
53 @Override 56 @Override
......
...@@ -16,9 +16,12 @@ ...@@ -16,9 +16,12 @@
16 package org.onosproject.segmentrouting.grouphandler; 16 package org.onosproject.segmentrouting.grouphandler;
17 17
18 import java.util.List; 18 import java.util.List;
19 +import java.util.Map;
19 20
21 +import org.onlab.packet.Ip4Prefix;
20 import org.onlab.packet.MacAddress; 22 import org.onlab.packet.MacAddress;
21 import org.onosproject.net.DeviceId; 23 import org.onosproject.net.DeviceId;
24 +import org.onosproject.net.PortNumber;
22 25
23 /** 26 /**
24 * Mechanism through which group handler module retrieves 27 * Mechanism through which group handler module retrieves
...@@ -33,6 +36,7 @@ public interface DeviceProperties { ...@@ -33,6 +36,7 @@ public interface DeviceProperties {
33 * @return segment id of a device 36 * @return segment id of a device
34 */ 37 */
35 int getSegmentId(DeviceId deviceId); 38 int getSegmentId(DeviceId deviceId);
39 +
36 /** 40 /**
37 * Returns the Mac address of a device to be used in group creation. 41 * Returns the Mac address of a device to be used in group creation.
38 * 42 *
...@@ -40,6 +44,7 @@ public interface DeviceProperties { ...@@ -40,6 +44,7 @@ public interface DeviceProperties {
40 * @return mac address of a device 44 * @return mac address of a device
41 */ 45 */
42 MacAddress getDeviceMac(DeviceId deviceId); 46 MacAddress getDeviceMac(DeviceId deviceId);
47 +
43 /** 48 /**
44 * Indicates whether a device is edge device or transit/core device. 49 * Indicates whether a device is edge device or transit/core device.
45 * 50 *
...@@ -47,6 +52,7 @@ public interface DeviceProperties { ...@@ -47,6 +52,7 @@ public interface DeviceProperties {
47 * @return boolean 52 * @return boolean
48 */ 53 */
49 boolean isEdgeDevice(DeviceId deviceId); 54 boolean isEdgeDevice(DeviceId deviceId);
55 +
50 /** 56 /**
51 * Returns all segment IDs to be considered in building auto 57 * Returns all segment IDs to be considered in building auto
52 * 58 *
...@@ -54,4 +60,16 @@ public interface DeviceProperties { ...@@ -54,4 +60,16 @@ public interface DeviceProperties {
54 * @return list of segment IDs 60 * @return list of segment IDs
55 */ 61 */
56 List<Integer> getAllDeviceSegmentIds(); 62 List<Integer> getAllDeviceSegmentIds();
63 +
64 + /**
65 + * Returns subnet-to-ports mapping of given device.
66 + *
67 + * For each entry of the map
68 + * Key: a subnet
69 + * Value: a list of ports, which are bound to the subnet
70 + *
71 + * @param deviceId device identifier
72 + * @return a map that contains all subnet-to-ports mapping of given device
73 + */
74 + Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId);
57 } 75 }
......
...@@ -54,7 +54,8 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -54,7 +54,8 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
54 * @param config interface to retrieve the device properties 54 * @param config interface to retrieve the device properties
55 * @param linkService link service object 55 * @param linkService link service object
56 * @param flowObjService flow objective service object 56 * @param flowObjService flow objective service object
57 - * @param nsNextObjStore next objective store map 57 + * @param nsNextObjStore NeighborSet next objective store map
58 + * @param subnetNextObjStore subnet next objective store map
58 */ 59 */
59 public PolicyGroupHandler(DeviceId deviceId, 60 public PolicyGroupHandler(DeviceId deviceId,
60 ApplicationId appId, 61 ApplicationId appId,
...@@ -62,8 +63,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -62,8 +63,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
62 LinkService linkService, 63 LinkService linkService,
63 FlowObjectiveService flowObjService, 64 FlowObjectiveService flowObjService,
64 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, 65 EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
65 - Integer> nsNextObjStore) { 66 + Integer> nsNextObjStore,
66 - super(deviceId, appId, config, linkService, flowObjService, nsNextObjStore); 67 + EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
68 + Integer> subnetNextObjStore) {
69 + super(deviceId, appId, config, linkService, flowObjService,
70 + nsNextObjStore, subnetNextObjStore);
67 } 71 }
68 72
69 public PolicyGroupIdentifier createPolicyGroupChain(String id, 73 public PolicyGroupIdentifier createPolicyGroupChain(String id,
......
1 +/*
2 + * Copyright 2014-2015 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.IpPrefix;
20 +import org.onosproject.net.DeviceId;
21 +
22 +import java.util.Objects;
23 +
24 +/**
25 + * Class definition of Key for Subnet to NextObjective store.
26 + */
27 +public class SubnetNextObjectiveStoreKey {
28 + private final DeviceId deviceId;
29 + private final IpPrefix prefix;
30 +
31 + public SubnetNextObjectiveStoreKey(DeviceId deviceId,
32 + IpPrefix prefix) {
33 + this.deviceId = deviceId;
34 + this.prefix = prefix;
35 + }
36 +
37 + /**
38 + * Gets device id in this SubnetNextObjectiveStoreKey.
39 + *
40 + * @return device id
41 + */
42 + public DeviceId deviceId() {
43 + return this.deviceId;
44 + }
45 +
46 + /**
47 + * Gets subnet information in this SubnetNextObjectiveStoreKey.
48 + *
49 + * @return subnet information
50 + */
51 + public IpPrefix prefix() {
52 + return this.prefix;
53 + }
54 +
55 + @Override
56 + public boolean equals(Object o) {
57 + if (this == o) {
58 + return true;
59 + }
60 + if (!(o instanceof SubnetNextObjectiveStoreKey)) {
61 + return false;
62 + }
63 + SubnetNextObjectiveStoreKey that =
64 + (SubnetNextObjectiveStoreKey) o;
65 + return (Objects.equals(this.deviceId, that.deviceId) &&
66 + Objects.equals(this.prefix, that.prefix));
67 + }
68 +
69 + @Override
70 + public int hashCode() {
71 + return Objects.hash(deviceId, prefix);
72 + }
73 +
74 + @Override
75 + public String toString() {
76 + return "Device: " + deviceId + " Subnet: " + prefix;
77 + }
78 +}
...@@ -139,6 +139,20 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE ...@@ -139,6 +139,20 @@ public final class DefaultGroupBucket implements GroupBucket, StoredGroupBucketE
139 watchGroup); 139 watchGroup);
140 } 140 }
141 141
142 + /**
143 + * Creates all group bucket.
144 + *
145 + * @param treatment traffic treatment associated with group bucket
146 + * @return all group bucket object
147 + */
148 + public static GroupBucket createAllGroupBucket(TrafficTreatment treatment) {
149 + return new DefaultGroupBucket(GroupDescription.Type.ALL,
150 + treatment,
151 + (short) -1,
152 + null,
153 + null);
154 + }
155 +
142 @Override 156 @Override
143 public GroupDescription.Type type() { 157 public GroupDescription.Type type() {
144 return this.type; 158 return this.type;
......
...@@ -247,6 +247,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -247,6 +247,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
247 private void addGroup(NextObjective nextObjective) { 247 private void addGroup(NextObjective nextObjective) {
248 log.debug("addGroup with type{} for nextObjective id {}", 248 log.debug("addGroup with type{} for nextObjective id {}",
249 nextObjective.type(), nextObjective.id()); 249 nextObjective.type(), nextObjective.id());
250 + List<GroupBucket> buckets;
250 switch (nextObjective.type()) { 251 switch (nextObjective.type()) {
251 case SIMPLE: 252 case SIMPLE:
252 log.debug("processing SIMPLE next objective"); 253 log.debug("processing SIMPLE next objective");
...@@ -274,7 +275,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -274,7 +275,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
274 break; 275 break;
275 case HASHED: 276 case HASHED:
276 log.debug("processing HASHED next objective"); 277 log.debug("processing HASHED next objective");
277 - List<GroupBucket> buckets = nextObjective 278 + buckets = nextObjective
278 .next() 279 .next()
279 .stream() 280 .stream()
280 .map((treatment) -> DefaultGroupBucket 281 .map((treatment) -> DefaultGroupBucket
...@@ -298,8 +299,32 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -298,8 +299,32 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
298 } 299 }
299 break; 300 break;
300 case BROADCAST: 301 case BROADCAST:
302 + log.debug("processing BROADCAST next objective");
303 + buckets = nextObjective
304 + .next()
305 + .stream()
306 + .map((treatment) -> DefaultGroupBucket
307 + .createAllGroupBucket(treatment))
308 + .collect(Collectors.toList());
309 + if (!buckets.isEmpty()) {
310 + final GroupKey key = new DefaultGroupKey(
311 + appKryo.serialize(nextObjective
312 + .id()));
313 + GroupDescription groupDescription = new DefaultGroupDescription(
314 + deviceId,
315 + GroupDescription.Type.ALL,
316 + new GroupBuckets(buckets),
317 + key,
318 + null,
319 + nextObjective.appId());
320 + log.debug("Creating BROADCAST group for next objective id {}",
321 + nextObjective.id());
322 + groupService.addGroup(groupDescription);
323 + pendingGroups.put(key, nextObjective);
324 + }
325 + break;
301 case FAILOVER: 326 case FAILOVER:
302 - log.debug("BROADCAST and FAILOVER next objectives not supported"); 327 + log.debug("FAILOVER next objectives not supported");
303 fail(nextObjective, ObjectiveError.UNSUPPORTED); 328 fail(nextObjective, ObjectiveError.UNSUPPORTED);
304 log.warn("Unsupported next objective type {}", nextObjective.type()); 329 log.warn("Unsupported next objective type {}", nextObjective.type());
305 break; 330 break;
...@@ -327,6 +352,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -327,6 +352,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
327 bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); 352 bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
328 } else if (group.type() == GroupDescription.Type.SELECT) { 353 } else if (group.type() == GroupDescription.Type.SELECT) {
329 bucket = DefaultGroupBucket.createSelectGroupBucket(treatment); 354 bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
355 + } else if (group.type() == GroupDescription.Type.ALL) {
356 + bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
330 } else { 357 } else {
331 log.warn("Unsupported Group type {}", group.type()); 358 log.warn("Unsupported Group type {}", group.type());
332 return; 359 return;
...@@ -357,6 +384,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -357,6 +384,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
357 bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); 384 bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment);
358 } else if (group.type() == GroupDescription.Type.SELECT) { 385 } else if (group.type() == GroupDescription.Type.SELECT) {
359 bucket = DefaultGroupBucket.createSelectGroupBucket(treatment); 386 bucket = DefaultGroupBucket.createSelectGroupBucket(treatment);
387 + } else if (group.type() == GroupDescription.Type.ALL) {
388 + bucket = DefaultGroupBucket.createAllGroupBucket(treatment);
360 } else { 389 } else {
361 log.warn("Unsupported Group type {}", group.type()); 390 log.warn("Unsupported Group type {}", group.type());
362 return; 391 return;
...@@ -539,7 +568,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -539,7 +568,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
539 protected List<FlowRule> processEthDstFilter(Criterion c, 568 protected List<FlowRule> processEthDstFilter(Criterion c,
540 FilteringObjective filt, 569 FilteringObjective filt,
541 ApplicationId applicationId) { 570 ApplicationId applicationId) {
542 - List<FlowRule> rules = new ArrayList<FlowRule>(); 571 + List<FlowRule> rules = new ArrayList<>();
543 EthCriterion e = (EthCriterion) c; 572 EthCriterion e = (EthCriterion) c;
544 TrafficSelector.Builder selectorIp = DefaultTrafficSelector 573 TrafficSelector.Builder selectorIp = DefaultTrafficSelector
545 .builder(); 574 .builder();
...@@ -577,7 +606,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -577,7 +606,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
577 protected List<FlowRule> processVlanIdFilter(Criterion c, 606 protected List<FlowRule> processVlanIdFilter(Criterion c,
578 FilteringObjective filt, 607 FilteringObjective filt,
579 ApplicationId applicationId) { 608 ApplicationId applicationId) {
580 - List<FlowRule> rules = new ArrayList<FlowRule>(); 609 + List<FlowRule> rules = new ArrayList<>();
581 VlanIdCriterion v = (VlanIdCriterion) c; 610 VlanIdCriterion v = (VlanIdCriterion) c;
582 log.debug("adding rule for VLAN: {}", v.vlanId()); 611 log.debug("adding rule for VLAN: {}", v.vlanId());
583 TrafficSelector.Builder selector = DefaultTrafficSelector 612 TrafficSelector.Builder selector = DefaultTrafficSelector
......
...@@ -115,6 +115,10 @@ public class GroupBucketEntryBuilder { ...@@ -115,6 +115,10 @@ public class GroupBucketEntryBuilder {
115 DefaultGroupBucket.createFailoverGroupBucket(treatment, 115 DefaultGroupBucket.createFailoverGroupBucket(treatment,
116 port, groupId); 116 port, groupId);
117 break; 117 break;
118 + case ALL:
119 + groupBucket =
120 + DefaultGroupBucket.createAllGroupBucket(treatment);
121 + break;
118 default: 122 default:
119 log.error("Unsupported Group type : {}", type); 123 log.error("Unsupported Group type : {}", type);
120 } 124 }
......