Charles Chan
Committed by Gerrit Code Review

CORD-349 Support VLAN cross-connect traffic

Change related to this topic:
- Support VLAN cross-connect traffic
    Utilize ports subjectClass to achieve. For non-xConnect port, set interface VLAN to -1
- Remove VLAN checking since we have multiple VLANs per port
- Hash the L2 interface group key generation to include VLAN as well
- Update the network-cfg.json sample

Other refactoring changes:
- Read next objective stores from srManager directly
- Use constant for flow priority
- CORD-267 Javadoc fix

Change-Id: I4ca8c2d9c8b3633a4a0101c5070d19343f7e5b90
Showing 31 changed files with 803 additions and 298 deletions
...@@ -41,6 +41,10 @@ import java.util.Set; ...@@ -41,6 +41,10 @@ import java.util.Set;
41 41
42 import static com.google.common.base.Preconditions.checkNotNull; 42 import static com.google.common.base.Preconditions.checkNotNull;
43 43
44 +/**
45 + * Handler of ARP packets that responses or forwards ARP packets that
46 + * are sent to the controller.
47 + */
44 public class ArpHandler { 48 public class ArpHandler {
45 49
46 private static Logger log = LoggerFactory.getLogger(ArpHandler.class); 50 private static Logger log = LoggerFactory.getLogger(ArpHandler.class);
......
...@@ -37,6 +37,10 @@ import java.util.concurrent.locks.ReentrantLock; ...@@ -37,6 +37,10 @@ import java.util.concurrent.locks.ReentrantLock;
37 37
38 import static com.google.common.base.Preconditions.checkNotNull; 38 import static com.google.common.base.Preconditions.checkNotNull;
39 39
40 +/**
41 + * Default routing handler that is responsible for route computing and
42 + * routing rule population.
43 + */
40 public class DefaultRoutingHandler { 44 public class DefaultRoutingHandler {
41 45
42 private static Logger log = LoggerFactory 46 private static Logger log = LoggerFactory
...@@ -512,6 +516,7 @@ public class DefaultRoutingHandler { ...@@ -512,6 +516,7 @@ public class DefaultRoutingHandler {
512 */ 516 */
513 public void populatePortAddressingRules(DeviceId deviceId) { 517 public void populatePortAddressingRules(DeviceId deviceId) {
514 rulePopulator.populateRouterMacVlanFilters(deviceId); 518 rulePopulator.populateRouterMacVlanFilters(deviceId);
519 + rulePopulator.populateXConnectVlanFilters(deviceId);
515 rulePopulator.populateRouterIpPunts(deviceId); 520 rulePopulator.populateRouterIpPunts(deviceId);
516 } 521 }
517 522
......
...@@ -20,7 +20,7 @@ import java.util.List; ...@@ -20,7 +20,7 @@ import java.util.List;
20 import static com.google.common.base.Preconditions.checkNotNull; 20 import static com.google.common.base.Preconditions.checkNotNull;
21 21
22 /** 22 /**
23 - * Tunnel class. 23 + * Default Tunnel class.
24 */ 24 */
25 public class DefaultTunnel implements Tunnel { 25 public class DefaultTunnel implements Tunnel {
26 26
......
...@@ -38,6 +38,10 @@ import java.util.Set; ...@@ -38,6 +38,10 @@ import java.util.Set;
38 38
39 import static com.google.common.base.Preconditions.checkNotNull; 39 import static com.google.common.base.Preconditions.checkNotNull;
40 40
41 +/**
42 + * Handler of ICMP packets that responses or forwards ICMP packets that
43 + * are sent to the controller.
44 + */
41 public class IcmpHandler { 45 public class IcmpHandler {
42 46
43 private static Logger log = LoggerFactory.getLogger(IcmpHandler.class); 47 private static Logger log = LoggerFactory.getLogger(IcmpHandler.class);
......
...@@ -37,6 +37,10 @@ import java.util.concurrent.ConcurrentLinkedQueue; ...@@ -37,6 +37,10 @@ import java.util.concurrent.ConcurrentLinkedQueue;
37 37
38 import static com.google.common.base.Preconditions.checkNotNull; 38 import static com.google.common.base.Preconditions.checkNotNull;
39 39
40 +/**
41 + * Handler of IP packets that forwards IP packets that are sent to the controller,
42 + * except the ICMP packets which are processed by @link{IcmpHandler}.
43 + */
40 public class IpHandler { 44 public class IpHandler {
41 45
42 private static Logger log = LoggerFactory.getLogger(IpHandler.class); 46 private static Logger log = LoggerFactory.getLogger(IpHandler.class);
......
...@@ -24,16 +24,24 @@ public interface Policy { ...@@ -24,16 +24,24 @@ public interface Policy {
24 * Enums for policy type. 24 * Enums for policy type.
25 */ 25 */
26 enum Type { 26 enum Type {
27 - // Tunnel flow policy type 27 + /**
28 + * Tunnel flow policy type.
29 + */
28 TUNNEL_FLOW, 30 TUNNEL_FLOW,
29 31
30 - // Load balancing policy type 32 + /**
33 + * Load balancing policy type.
34 + */
31 LOADBALANCE, 35 LOADBALANCE,
32 36
33 - // policy to avoid specific routers or links 37 + /**
38 + * policy to avoid specific routers or links.
39 + */
34 AVOID, 40 AVOID,
35 41
36 - // Access Control policy type 42 + /**
43 + * Access Control policy type.
44 + */
37 DENY 45 DENY
38 } 46 }
39 47
......
...@@ -48,18 +48,43 @@ public class PolicyHandler { ...@@ -48,18 +48,43 @@ public class PolicyHandler {
48 private FlowObjectiveService flowObjectiveService; 48 private FlowObjectiveService flowObjectiveService;
49 private TunnelHandler tunnelHandler; 49 private TunnelHandler tunnelHandler;
50 private final EventuallyConsistentMap<String, Policy> policyStore; 50 private final EventuallyConsistentMap<String, Policy> policyStore;
51 - 51 + /**
52 + * Result of policy creation.
53 + */
52 public enum Result { 54 public enum Result {
55 + /**
56 + * Success.
57 + */
53 SUCCESS, 58 SUCCESS,
59 +
60 + /**
61 + * The same policy exists already.
62 + */
54 POLICY_EXISTS, 63 POLICY_EXISTS,
64 +
65 + /**
66 + * The policy ID exists already.
67 + */
55 ID_EXISTS, 68 ID_EXISTS,
69 +
70 + /**
71 + * Cannot find associated tunnel.
72 + */
56 TUNNEL_NOT_FOUND, 73 TUNNEL_NOT_FOUND,
74 +
75 + /**
76 + * Policy was not found.
77 + */
57 POLICY_NOT_FOUND, 78 POLICY_NOT_FOUND,
79 +
80 + /**
81 + * Policy type {} is not supported yet.
82 + */
58 UNSUPPORTED_TYPE 83 UNSUPPORTED_TYPE
59 } 84 }
60 85
61 /** 86 /**
62 - * Creates a reference. 87 + * Constructs policy handler.
63 * 88 *
64 * @param appId segment routing application ID 89 * @param appId segment routing application ID
65 * @param deviceConfiguration DeviceConfiguration reference 90 * @param deviceConfiguration DeviceConfiguration reference
......
...@@ -23,6 +23,7 @@ import org.onlab.packet.IpPrefix; ...@@ -23,6 +23,7 @@ import org.onlab.packet.IpPrefix;
23 import org.onlab.packet.MacAddress; 23 import org.onlab.packet.MacAddress;
24 import org.onlab.packet.MplsLabel; 24 import org.onlab.packet.MplsLabel;
25 import org.onlab.packet.VlanId; 25 import org.onlab.packet.VlanId;
26 +import org.onosproject.net.ConnectPoint;
26 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; 27 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
27 import org.onosproject.segmentrouting.config.DeviceConfiguration; 28 import org.onosproject.segmentrouting.config.DeviceConfiguration;
28 import org.onosproject.segmentrouting.grouphandler.NeighborSet; 29 import org.onosproject.segmentrouting.grouphandler.NeighborSet;
...@@ -49,11 +50,15 @@ import org.slf4j.LoggerFactory; ...@@ -49,11 +50,15 @@ import org.slf4j.LoggerFactory;
49 import java.util.ArrayList; 50 import java.util.ArrayList;
50 import java.util.HashSet; 51 import java.util.HashSet;
51 import java.util.List; 52 import java.util.List;
53 +import java.util.Map;
52 import java.util.Set; 54 import java.util.Set;
53 import java.util.concurrent.atomic.AtomicLong; 55 import java.util.concurrent.atomic.AtomicLong;
54 56
55 import static com.google.common.base.Preconditions.checkNotNull; 57 import static com.google.common.base.Preconditions.checkNotNull;
56 58
59 +/**
60 + * Populator of segment routing flow rules.
61 + */
57 public class RoutingRulePopulator { 62 public class RoutingRulePopulator {
58 private static final Logger log = LoggerFactory 63 private static final Logger log = LoggerFactory
59 .getLogger(RoutingRulePopulator.class); 64 .getLogger(RoutingRulePopulator.class);
...@@ -63,6 +68,10 @@ public class RoutingRulePopulator { ...@@ -63,6 +68,10 @@ public class RoutingRulePopulator {
63 private DeviceConfiguration config; 68 private DeviceConfiguration config;
64 69
65 private static final int HIGHEST_PRIORITY = 0xffff; 70 private static final int HIGHEST_PRIORITY = 0xffff;
71 + //
72 + private static final int XCONNECT_PRIORITY = 1000;
73 + private static final int DEFAULT_PRIORITY = 100;
74 + private static final int FLOOD_PRIORITY = 5;
66 private static final long OFPP_MAX = 0xffffff00L; 75 private static final long OFPP_MAX = 0xffffff00L;
67 76
68 77
...@@ -120,6 +129,14 @@ public class RoutingRulePopulator { ...@@ -120,6 +129,14 @@ public class RoutingRulePopulator {
120 rulePopulationCounter.incrementAndGet(); 129 rulePopulationCounter.incrementAndGet();
121 } 130 }
122 131
132 + /**
133 + * Removes IP rules for host when the host is gone.
134 + *
135 + * @param deviceId device ID of the device that host attaches to
136 + * @param hostIp IP address of the host
137 + * @param hostMac MAC address of the host
138 + * @param outPort port that host attaches to
139 + */
123 public void revokeIpRuleForHost(DeviceId deviceId, Ip4Address hostIp, 140 public void revokeIpRuleForHost(DeviceId deviceId, Ip4Address hostIp,
124 MacAddress hostMac, PortNumber outPort) { 141 MacAddress hostMac, PortNumber outPort) {
125 log.debug("Revoke IP table entry for host {} at {}:{}", 142 log.debug("Revoke IP table entry for host {} at {}:{}",
...@@ -175,7 +192,7 @@ public class RoutingRulePopulator { ...@@ -175,7 +192,7 @@ public class RoutingRulePopulator {
175 .withSelector(selector) 192 .withSelector(selector)
176 .nextStep(portNextObjId) 193 .nextStep(portNextObjId)
177 .fromApp(srManager.appId).makePermanent() 194 .fromApp(srManager.appId).makePermanent()
178 - .withPriority(100).withFlag(ForwardingObjective.Flag.SPECIFIC); 195 + .withPriority(DEFAULT_PRIORITY).withFlag(ForwardingObjective.Flag.SPECIFIC);
179 } 196 }
180 197
181 /** 198 /**
...@@ -369,7 +386,7 @@ public class RoutingRulePopulator { ...@@ -369,7 +386,7 @@ public class RoutingRulePopulator {
369 for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) { 386 for (ForwardingObjective.Builder fwdObjBuilder : fwdObjBuilders) {
370 ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId) 387 ((Builder) ((Builder) fwdObjBuilder.fromApp(srManager.appId)
371 .makePermanent()).withSelector(selector) 388 .makePermanent()).withSelector(selector)
372 - .withPriority(100)) 389 + .withPriority(DEFAULT_PRIORITY))
373 .withFlag(ForwardingObjective.Flag.SPECIFIC); 390 .withFlag(ForwardingObjective.Flag.SPECIFIC);
374 srManager.flowObjectiveService. 391 srManager.flowObjectiveService.
375 forward(deviceId, 392 forward(deviceId,
...@@ -464,7 +481,8 @@ public class RoutingRulePopulator { ...@@ -464,7 +481,8 @@ public class RoutingRulePopulator {
464 FilteringObjective.Builder fob = DefaultFilteringObjective.builder(); 481 FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
465 fob.withKey(Criteria.matchInPort(port.number())) 482 fob.withKey(Criteria.matchInPort(port.number()))
466 .addCondition(Criteria.matchEthDst(deviceMac)) 483 .addCondition(Criteria.matchEthDst(deviceMac))
467 - .addCondition(Criteria.matchVlanId(VlanId.NONE)); 484 + .addCondition(Criteria.matchVlanId(VlanId.NONE))
485 + .withPriority(DEFAULT_PRIORITY);
468 // vlan assignment is valid only if this instance is master 486 // vlan assignment is valid only if this instance is master
469 if (srManager.mastershipService.isLocalMaster(deviceId)) { 487 if (srManager.mastershipService.isLocalMaster(deviceId)) {
470 TrafficTreatment tt = DefaultTrafficTreatment.builder() 488 TrafficTreatment tt = DefaultTrafficTreatment.builder()
...@@ -558,7 +576,7 @@ public class RoutingRulePopulator { ...@@ -558,7 +576,7 @@ public class RoutingRulePopulator {
558 fob.withFlag(Flag.SPECIFIC) 576 fob.withFlag(Flag.SPECIFIC)
559 .withSelector(sbuilder.build()) 577 .withSelector(sbuilder.build())
560 .nextStep(nextId) 578 .nextStep(nextId)
561 - .withPriority(5) 579 + .withPriority(FLOOD_PRIORITY)
562 .fromApp(srManager.appId) 580 .fromApp(srManager.appId)
563 .makePermanent(); 581 .makePermanent();
564 582
...@@ -572,6 +590,86 @@ public class RoutingRulePopulator { ...@@ -572,6 +590,86 @@ public class RoutingRulePopulator {
572 }); 590 });
573 } 591 }
574 592
593 + /**
594 + * Creates a filtering objective to permit VLAN cross-connect traffic.
595 + *
596 + * @param deviceId the DPID of the switch
597 + */
598 + public void populateXConnectVlanFilters(DeviceId deviceId) {
599 + Map<VlanId, List<ConnectPoint>> xConnectsForDevice =
600 + config.getXConnects();
601 + xConnectsForDevice.forEach((vlanId, connectPoints) -> {
602 + // Only proceed the xConnect for given device
603 + for (ConnectPoint connectPoint : connectPoints) {
604 + if (!connectPoint.deviceId().equals(deviceId)) {
605 + return;
606 + }
607 + }
608 +
609 + connectPoints.forEach(connectPoint -> {
610 + FilteringObjective.Builder fob = DefaultFilteringObjective.builder();
611 + fob.withKey(Criteria.matchInPort(connectPoint.port()))
612 + .addCondition(Criteria.matchVlanId(vlanId))
613 + .addCondition(Criteria.matchEthDst(MacAddress.NONE))
614 + .withPriority(XCONNECT_PRIORITY);
615 +
616 + fob.permit().fromApp(srManager.appId);
617 + srManager.flowObjectiveService
618 + .filter(deviceId, fob.add(new SRObjectiveContext(deviceId,
619 + SRObjectiveContext.ObjectiveType.FILTER)));
620 + });
621 + });
622 + }
623 +
624 + /**
625 + * Populates a forwarding objective that points the VLAN cross-connect
626 + * packets to a broadcast group.
627 + *
628 + * @param deviceId switch ID to set the rules
629 + */
630 + public void populateXConnectBroadcastRule(DeviceId deviceId) {
631 + Map<VlanId, List<ConnectPoint>> xConnects =
632 + config.getXConnects();
633 + xConnects.forEach((vlanId, connectPoints) -> {
634 + // Only proceed the xConnect for given device
635 + for (ConnectPoint connectPoint : connectPoints) {
636 + if (!connectPoint.deviceId().equals(deviceId)) {
637 + return;
638 + }
639 + }
640 +
641 + int nextId = srManager.getXConnectNextObjectiveId(deviceId, vlanId);
642 + if (nextId < 0) {
643 + log.error("Cannot install cross-connect broadcast rule in dev:{} " +
644 + "due to missing nextId:{}", deviceId, nextId);
645 + return;
646 + }
647 +
648 + /*
649 + * Driver should treat objectives with MacAddress.NONE and !VlanId.NONE
650 + * as the VLAN cross-connect broadcast rules
651 + */
652 + TrafficSelector.Builder sbuilder = DefaultTrafficSelector.builder();
653 + sbuilder.matchVlanId(vlanId);
654 + sbuilder.matchEthDst(MacAddress.NONE);
655 +
656 + ForwardingObjective.Builder fob = DefaultForwardingObjective.builder();
657 + fob.withFlag(Flag.SPECIFIC)
658 + .withSelector(sbuilder.build())
659 + .nextStep(nextId)
660 + .withPriority(DEFAULT_PRIORITY)
661 + .fromApp(srManager.appId)
662 + .makePermanent();
663 +
664 + srManager.flowObjectiveService.forward(
665 + deviceId,
666 + fob.add(new SRObjectiveContext(
667 + deviceId,
668 + SRObjectiveContext.ObjectiveType.FORWARDING)
669 + )
670 + );
671 + });
672 + }
575 673
576 private static class SRObjectiveContext implements ObjectiveContext { 674 private static class SRObjectiveContext implements ObjectiveContext {
577 enum ObjectiveType { 675 enum ObjectiveType {
......
...@@ -69,7 +69,6 @@ import org.onosproject.net.device.DeviceListener; ...@@ -69,7 +69,6 @@ import org.onosproject.net.device.DeviceListener;
69 import org.onosproject.net.device.DeviceService; 69 import org.onosproject.net.device.DeviceService;
70 import org.onosproject.net.flowobjective.FlowObjectiveService; 70 import org.onosproject.net.flowobjective.FlowObjectiveService;
71 import org.onosproject.net.host.HostService; 71 import org.onosproject.net.host.HostService;
72 -import org.onosproject.net.intent.IntentService;
73 import org.onosproject.net.link.LinkEvent; 72 import org.onosproject.net.link.LinkEvent;
74 import org.onosproject.net.link.LinkListener; 73 import org.onosproject.net.link.LinkListener;
75 import org.onosproject.net.link.LinkService; 74 import org.onosproject.net.link.LinkService;
...@@ -77,8 +76,8 @@ import org.onosproject.net.packet.InboundPacket; ...@@ -77,8 +76,8 @@ import org.onosproject.net.packet.InboundPacket;
77 import org.onosproject.net.packet.PacketContext; 76 import org.onosproject.net.packet.PacketContext;
78 import org.onosproject.net.packet.PacketProcessor; 77 import org.onosproject.net.packet.PacketProcessor;
79 import org.onosproject.net.packet.PacketService; 78 import org.onosproject.net.packet.PacketService;
80 -import org.onosproject.net.topology.TopologyService;
81 import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey; 79 import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey;
80 +import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey;
82 import org.onosproject.store.service.EventuallyConsistentMap; 81 import org.onosproject.store.service.EventuallyConsistentMap;
83 import org.onosproject.store.service.EventuallyConsistentMapBuilder; 82 import org.onosproject.store.service.EventuallyConsistentMapBuilder;
84 import org.onosproject.store.service.StorageService; 83 import org.onosproject.store.service.StorageService;
...@@ -102,6 +101,9 @@ import java.util.concurrent.TimeUnit; ...@@ -102,6 +101,9 @@ import java.util.concurrent.TimeUnit;
102 101
103 @Service 102 @Service
104 @Component(immediate = true) 103 @Component(immediate = true)
104 +/**
105 + * Segment routing manager.
106 + */
105 public class SegmentRoutingManager implements SegmentRoutingService { 107 public class SegmentRoutingManager implements SegmentRoutingService {
106 108
107 private static Logger log = LoggerFactory 109 private static Logger log = LoggerFactory
...@@ -111,15 +113,9 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -111,15 +113,9 @@ public class SegmentRoutingManager implements SegmentRoutingService {
111 protected CoreService coreService; 113 protected CoreService coreService;
112 114
113 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 115 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
114 - protected TopologyService topologyService;
115 -
116 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
117 protected PacketService packetService; 116 protected PacketService packetService;
118 117
119 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 118 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
120 - protected IntentService intentService;
121 -
122 - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
123 protected HostService hostService; 119 protected HostService hostService;
124 120
125 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 121 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
...@@ -157,16 +153,27 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -157,16 +153,27 @@ public class SegmentRoutingManager implements SegmentRoutingService {
157 @SuppressWarnings("rawtypes") 153 @SuppressWarnings("rawtypes")
158 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>(); 154 private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
159 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap = 155 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
160 - new ConcurrentHashMap<DeviceId, DefaultGroupHandler>(); 156 + new ConcurrentHashMap<>();
161 - // Per device next objective ID store with (device id + neighbor set) as key 157 + /**
162 - private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer> 158 + * Per device next objective ID store with (device id + neighbor set) as key.
159 + */
160 + public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
163 nsNextObjStore = null; 161 nsNextObjStore = null;
164 - // Per device next objective ID store with (device id + subnet) as key 162 + /**
165 - private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer> 163 + * Per device next objective ID store with (device id + subnet) as key.
164 + */
165 + public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
166 subnetNextObjStore = null; 166 subnetNextObjStore = null;
167 - // Per device next objective ID store with (device id + port) as key 167 + /**
168 - private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer> 168 + * Per device next objective ID store with (device id + port) as key.
169 + */
170 + public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
169 portNextObjStore = null; 171 portNextObjStore = null;
172 + /**
173 + * Per cross-connect objective ID store with VLAN ID as key.
174 + */
175 + public EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
176 + xConnectNextObjStore = null;
170 // Per device, per-subnet assigned-vlans store, with (device id + subnet 177 // Per device, per-subnet assigned-vlans store, with (device id + subnet
171 // IPv4 prefix) as key 178 // IPv4 prefix) as key
172 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId> 179 private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
...@@ -204,7 +211,13 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -204,7 +211,13 @@ public class SegmentRoutingManager implements SegmentRoutingService {
204 211
205 private KryoNamespace.Builder kryoBuilder = null; 212 private KryoNamespace.Builder kryoBuilder = null;
206 213
214 + /**
215 + * The starting value of per-subnet VLAN ID assignment.
216 + */
207 private static final short ASSIGNED_VLAN_START = 4093; 217 private static final short ASSIGNED_VLAN_START = 4093;
218 + /**
219 + * The default VLAN ID assigned to the interfaces without subnet config.
220 + */
208 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094; 221 public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
209 222
210 @Activate 223 @Activate
...@@ -262,6 +275,15 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -262,6 +275,15 @@ public class SegmentRoutingManager implements SegmentRoutingService {
262 .withTimestampProvider((k, v) -> new WallClockTimestamp()) 275 .withTimestampProvider((k, v) -> new WallClockTimestamp())
263 .build(); 276 .build();
264 277
278 + log.debug("Creating EC map xconnectnextobjectivestore");
279 + EventuallyConsistentMapBuilder<XConnectNextObjectiveStoreKey, Integer>
280 + xConnectNextObjStoreBuilder = storageService.eventuallyConsistentMapBuilder();
281 + xConnectNextObjStore = xConnectNextObjStoreBuilder
282 + .withName("xconnectnextobjectivestore")
283 + .withSerializer(kryoBuilder)
284 + .withTimestampProvider((k, v) -> new WallClockTimestamp())
285 + .build();
286 +
265 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder = 287 EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
266 storageService.eventuallyConsistentMapBuilder(); 288 storageService.eventuallyConsistentMapBuilder();
267 tunnelStore = tunnelMapBuilder 289 tunnelStore = tunnelMapBuilder
...@@ -394,9 +416,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -394,9 +416,6 @@ public class SegmentRoutingManager implements SegmentRoutingService {
394 * Vlan id 4094 expected to be used for all ports that are not assigned subnets. 416 * Vlan id 4094 expected to be used for all ports that are not assigned subnets.
395 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned 417 * Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
396 * per subnet. 418 * per subnet.
397 - * XXX This method should avoid any vlans configured on the ports, but
398 - * currently the app works only on untagged packets and as a result
399 - * ignores any vlan configuration.
400 * 419 *
401 * @param deviceId switch dpid 420 * @param deviceId switch dpid
402 * @param subnet IPv4 prefix for which assigned vlan is desired 421 * @param subnet IPv4 prefix for which assigned vlan is desired
...@@ -404,6 +423,7 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -404,6 +423,7 @@ public class SegmentRoutingManager implements SegmentRoutingService {
404 * null if no vlan assignment was found and this instance is not 423 * null if no vlan assignment was found and this instance is not
405 * the master for the device. 424 * the master for the device.
406 */ 425 */
426 + // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
407 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) { 427 public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
408 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey( 428 VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
409 deviceId, subnet)); 429 deviceId, subnet));
...@@ -514,6 +534,25 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -514,6 +534,25 @@ public class SegmentRoutingManager implements SegmentRoutingService {
514 } 534 }
515 } 535 }
516 536
537 + /**
538 + * Returns the next objective ID of type broadcast associated with the VLAN
539 + * cross-connection.
540 + *
541 + * @param deviceId Device ID for the cross-connection
542 + * @param vlanId VLAN ID for the cross-connection
543 + * @return next objective ID or -1 if it was not found
544 + */
545 + public int getXConnectNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
546 + DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
547 + if (ghdlr != null) {
548 + return ghdlr.getXConnectNextObjectiveId(vlanId);
549 + } else {
550 + log.warn("getPortNextObjectiveId query - groupHandler for device {}"
551 + + " not found", deviceId);
552 + return -1;
553 + }
554 + }
555 +
517 private class InternalPacketProcessor implements PacketProcessor { 556 private class InternalPacketProcessor implements PacketProcessor {
518 @Override 557 @Override
519 public void process(PacketContext context) { 558 public void process(PacketContext context) {
...@@ -707,9 +746,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -707,9 +746,6 @@ public class SegmentRoutingManager implements SegmentRoutingService {
707 deviceConfiguration, 746 deviceConfiguration,
708 linkService, 747 linkService,
709 flowObjectiveService, 748 flowObjectiveService,
710 - nsNextObjStore,
711 - subnetNextObjStore,
712 - portNextObjStore,
713 this); 749 this);
714 } catch (DeviceConfigNotFoundException e) { 750 } catch (DeviceConfigNotFoundException e) {
715 log.warn(e.getMessage() + " Aborting processDeviceAdded."); 751 log.warn(e.getMessage() + " Aborting processDeviceAdded.");
...@@ -727,6 +763,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -727,6 +763,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
727 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 763 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
728 groupHandler.createGroupsFromSubnetConfig(); 764 groupHandler.createGroupsFromSubnetConfig();
729 routingRulePopulator.populateSubnetBroadcastRule(device.id()); 765 routingRulePopulator.populateSubnetBroadcastRule(device.id());
766 + groupHandler.createGroupsForXConnect(device.id());
767 + routingRulePopulator.populateXConnectBroadcastRule(device.id());
730 } 768 }
731 } 769 }
732 770
...@@ -742,10 +780,18 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -742,10 +780,18 @@ public class SegmentRoutingManager implements SegmentRoutingService {
742 private class InternalConfigListener implements NetworkConfigListener { 780 private class InternalConfigListener implements NetworkConfigListener {
743 SegmentRoutingManager segmentRoutingManager; 781 SegmentRoutingManager segmentRoutingManager;
744 782
783 + /**
784 + * Constructs the internal network config listener.
785 + *
786 + * @param srMgr segment routing manager
787 + */
745 public InternalConfigListener(SegmentRoutingManager srMgr) { 788 public InternalConfigListener(SegmentRoutingManager srMgr) {
746 this.segmentRoutingManager = srMgr; 789 this.segmentRoutingManager = srMgr;
747 } 790 }
748 791
792 + /**
793 + * Reads network config and initializes related data structure accordingly.
794 + */
749 public void configureNetwork() { 795 public void configureNetwork() {
750 deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService); 796 deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService);
751 797
...@@ -777,9 +823,6 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -777,9 +823,6 @@ public class SegmentRoutingManager implements SegmentRoutingService {
777 deviceConfiguration, 823 deviceConfiguration,
778 linkService, 824 linkService,
779 flowObjectiveService, 825 flowObjectiveService,
780 - nsNextObjStore,
781 - subnetNextObjStore,
782 - portNextObjStore,
783 segmentRoutingManager); 826 segmentRoutingManager);
784 } catch (DeviceConfigNotFoundException e) { 827 } catch (DeviceConfigNotFoundException e) {
785 log.warn(e.getMessage() + " Aborting configureNetwork."); 828 log.warn(e.getMessage() + " Aborting configureNetwork.");
...@@ -798,6 +841,8 @@ public class SegmentRoutingManager implements SegmentRoutingService { ...@@ -798,6 +841,8 @@ public class SegmentRoutingManager implements SegmentRoutingService {
798 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id()); 841 DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
799 groupHandler.createGroupsFromSubnetConfig(); 842 groupHandler.createGroupsFromSubnetConfig();
800 routingRulePopulator.populateSubnetBroadcastRule(device.id()); 843 routingRulePopulator.populateSubnetBroadcastRule(device.id());
844 + groupHandler.createGroupsForXConnect(device.id());
845 + routingRulePopulator.populateXConnectBroadcastRule(device.id());
801 } 846 }
802 } 847 }
803 848
......
...@@ -6,13 +6,18 @@ import org.onlab.packet.Ip4Prefix; ...@@ -6,13 +6,18 @@ import org.onlab.packet.Ip4Prefix;
6 import org.onosproject.net.DeviceId; 6 import org.onosproject.net.DeviceId;
7 7
8 /** 8 /**
9 - * Class definition for key used to map per device subnets to assigned Vlan ids. 9 + * Key of assigned VLAN ID store.
10 - *
11 */ 10 */
12 public class SubnetAssignedVidStoreKey { 11 public class SubnetAssignedVidStoreKey {
13 private final DeviceId deviceId; 12 private final DeviceId deviceId;
14 private final Ip4Prefix subnet; 13 private final Ip4Prefix subnet;
15 14
15 + /**
16 + * Constructs the key of per subnet VLAN ID store.
17 + *
18 + * @param deviceId device ID of the VLAN cross-connection
19 + * @param subnet subnet information
20 + */
16 public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) { 21 public SubnetAssignedVidStoreKey(DeviceId deviceId, Ip4Prefix subnet) {
17 this.deviceId = deviceId; 22 this.deviceId = deviceId;
18 this.subnet = subnet; 23 this.subnet = subnet;
......
...@@ -43,16 +43,54 @@ public class TunnelHandler { ...@@ -43,16 +43,54 @@ public class TunnelHandler {
43 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap; 43 private Map<DeviceId, DefaultGroupHandler> groupHandlerMap;
44 private LinkService linkService; 44 private LinkService linkService;
45 45
46 + /**
47 + * Result of tunnel creation or removal.
48 + */
46 public enum Result { 49 public enum Result {
50 + /**
51 + * Success.
52 + */
47 SUCCESS, 53 SUCCESS,
54 +
55 + /**
56 + * More than one router needs to specified to created a tunnel.
57 + */
48 WRONG_PATH, 58 WRONG_PATH,
59 +
60 + /**
61 + * The same tunnel exists already.
62 + */
49 TUNNEL_EXISTS, 63 TUNNEL_EXISTS,
64 +
65 + /**
66 + * The same tunnel ID exists already.
67 + */
50 ID_EXISTS, 68 ID_EXISTS,
69 +
70 + /**
71 + * Tunnel not found.
72 + */
51 TUNNEL_NOT_FOUND, 73 TUNNEL_NOT_FOUND,
74 +
75 + /**
76 + * Cannot remove the tunnel used by a policy.
77 + */
52 TUNNEL_IN_USE, 78 TUNNEL_IN_USE,
79 +
80 + /**
81 + * Failed to create/remove groups for the tunnel.
82 + */
53 INTERNAL_ERROR 83 INTERNAL_ERROR
54 } 84 }
55 85
86 + /**
87 + * Constructs tunnel handler.
88 + *
89 + * @param linkService link service
90 + * @param deviceConfiguration device configuration
91 + * @param groupHandlerMap group handler map
92 + * @param tunnelStore tunnel store
93 + */
56 public TunnelHandler(LinkService linkService, 94 public TunnelHandler(LinkService linkService,
57 DeviceConfiguration deviceConfiguration, 95 DeviceConfiguration deviceConfiguration,
58 Map<DeviceId, DefaultGroupHandler> groupHandlerMap, 96 Map<DeviceId, DefaultGroupHandler> groupHandlerMap,
......
...@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSet; ...@@ -19,6 +19,7 @@ import com.google.common.collect.ImmutableSet;
19 import org.onlab.packet.Ip4Address; 19 import org.onlab.packet.Ip4Address;
20 import org.onlab.packet.Ip4Prefix; 20 import org.onlab.packet.Ip4Prefix;
21 import org.onlab.packet.MacAddress; 21 import org.onlab.packet.MacAddress;
22 +import org.onlab.packet.VlanId;
22 import org.onosproject.incubator.net.config.basics.ConfigException; 23 import org.onosproject.incubator.net.config.basics.ConfigException;
23 import org.onosproject.incubator.net.config.basics.InterfaceConfig; 24 import org.onosproject.incubator.net.config.basics.InterfaceConfig;
24 import org.onosproject.incubator.net.intf.Interface; 25 import org.onosproject.incubator.net.intf.Interface;
...@@ -33,6 +34,7 @@ import org.slf4j.LoggerFactory; ...@@ -33,6 +34,7 @@ import org.slf4j.LoggerFactory;
33 import java.util.ArrayList; 34 import java.util.ArrayList;
34 import java.util.HashMap; 35 import java.util.HashMap;
35 import java.util.HashSet; 36 import java.util.HashSet;
37 +import java.util.LinkedList;
36 import java.util.List; 38 import java.util.List;
37 import java.util.Map; 39 import java.util.Map;
38 import java.util.Set; 40 import java.util.Set;
...@@ -48,8 +50,8 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -48,8 +50,8 @@ public class DeviceConfiguration implements DeviceProperties {
48 private static final Logger log = LoggerFactory 50 private static final Logger log = LoggerFactory
49 .getLogger(DeviceConfiguration.class); 51 .getLogger(DeviceConfiguration.class);
50 private final List<Integer> allSegmentIds = new ArrayList<>(); 52 private final List<Integer> allSegmentIds = new ArrayList<>();
51 - private final ConcurrentHashMap<DeviceId, SegmentRouterInfo> deviceConfigMap 53 + private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
52 - = new ConcurrentHashMap<>(); 54 + private final Map<VlanId, List<ConnectPoint>> xConnects = new ConcurrentHashMap<>();
53 55
54 private class SegmentRouterInfo { 56 private class SegmentRouterInfo {
55 int nodeSid; 57 int nodeSid;
...@@ -62,14 +64,14 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -62,14 +64,14 @@ public class DeviceConfiguration implements DeviceProperties {
62 Map<Integer, Set<Integer>> adjacencySids; 64 Map<Integer, Set<Integer>> adjacencySids;
63 65
64 public SegmentRouterInfo() { 66 public SegmentRouterInfo() {
65 - this.gatewayIps = new HashMap<>(); 67 + gatewayIps = new HashMap<>();
66 - this.subnets = new HashMap<>(); 68 + subnets = new HashMap<>();
67 } 69 }
68 } 70 }
69 71
70 /** 72 /**
71 - * Constructor. Reads all the configuration for all devices of type 73 + * Constructs device configuration for all Segment Router devices,
72 - * Segment Router and organizes into various maps for easier access. 74 + * organizing the data into various maps for easier access.
73 * 75 *
74 * @param cfgService config service 76 * @param cfgService config service
75 */ 77 */
...@@ -88,8 +90,8 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -88,8 +90,8 @@ public class DeviceConfiguration implements DeviceProperties {
88 info.isEdge = config.isEdgeRouter(); 90 info.isEdge = config.isEdgeRouter();
89 info.adjacencySids = config.adjacencySids(); 91 info.adjacencySids = config.adjacencySids();
90 92
91 - this.deviceConfigMap.put(info.deviceId, info); 93 + deviceConfigMap.put(info.deviceId, info);
92 - this.allSegmentIds.add(info.nodeSid); 94 + allSegmentIds.add(info.nodeSid);
93 }); 95 });
94 96
95 // Read gatewayIps and subnets from port subject. 97 // Read gatewayIps and subnets from port subject.
...@@ -106,17 +108,42 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -106,17 +108,42 @@ public class DeviceConfiguration implements DeviceProperties {
106 return; 108 return;
107 } 109 }
108 networkInterfaces.forEach(networkInterface -> { 110 networkInterfaces.forEach(networkInterface -> {
109 - DeviceId dpid = networkInterface.connectPoint().deviceId(); 111 + VlanId vlanId = networkInterface.vlan();
110 - PortNumber port = networkInterface.connectPoint().port(); 112 + ConnectPoint connectPoint = networkInterface.connectPoint();
111 - SegmentRouterInfo info = this.deviceConfigMap.get(dpid); 113 + DeviceId dpid = connectPoint.deviceId();
114 + PortNumber port = connectPoint.port();
115 + SegmentRouterInfo info = deviceConfigMap.get(dpid);
112 116
113 // skip if there is no corresponding device for this ConenctPoint 117 // skip if there is no corresponding device for this ConenctPoint
114 if (info != null) { 118 if (info != null) {
119 + // Extract subnet information
115 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses(); 120 Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
116 interfaceAddresses.forEach(interfaceAddress -> { 121 interfaceAddresses.forEach(interfaceAddress -> {
117 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address()); 122 info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
118 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix()); 123 info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
119 }); 124 });
125 +
126 + // Extract VLAN cross-connect information
127 + // Do not setup cross-connect if VLAN is NONE
128 + if (vlanId.equals(VlanId.NONE)) {
129 + return;
130 + }
131 + List<ConnectPoint> connectPoints = xConnects.get(vlanId);
132 + if (connectPoints != null) {
133 + if (connectPoints.size() != 1) {
134 + log.warn("Cross-connect should only have two endpoints. Aborting.");
135 + return;
136 + }
137 + if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
138 + log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
139 + return;
140 + }
141 + connectPoints.add(connectPoint);
142 + } else {
143 + connectPoints = new LinkedList<>();
144 + connectPoints.add(connectPoint);
145 + xConnects.put(vlanId, connectPoints);
146 + }
120 } 147 }
121 }); 148 });
122 149
...@@ -235,6 +262,11 @@ public class DeviceConfiguration implements DeviceProperties { ...@@ -235,6 +262,11 @@ public class DeviceConfiguration implements DeviceProperties {
235 return subnetPortMap; 262 return subnetPortMap;
236 } 263 }
237 264
265 + @Override
266 + public Map<VlanId, List<ConnectPoint>> getXConnects() {
267 + return xConnects;
268 + }
269 +
238 /** 270 /**
239 * Returns the device identifier or data plane identifier (dpid) 271 * Returns the device identifier or data plane identifier (dpid)
240 * of a segment router given its segment id. 272 * of a segment router given its segment id.
......
...@@ -21,6 +21,8 @@ import java.util.Map; ...@@ -21,6 +21,8 @@ import java.util.Map;
21 import org.onlab.packet.Ip4Address; 21 import org.onlab.packet.Ip4Address;
22 import org.onlab.packet.Ip4Prefix; 22 import org.onlab.packet.Ip4Prefix;
23 import org.onlab.packet.MacAddress; 23 import org.onlab.packet.MacAddress;
24 +import org.onlab.packet.VlanId;
25 +import org.onosproject.net.ConnectPoint;
24 import org.onosproject.net.DeviceId; 26 import org.onosproject.net.DeviceId;
25 import org.onosproject.net.PortNumber; 27 import org.onosproject.net.PortNumber;
26 28
...@@ -93,4 +95,11 @@ public interface DeviceProperties { ...@@ -93,4 +95,11 @@ public interface DeviceProperties {
93 * @return a map that contains all subnet-to-ports mapping of given device 95 * @return a map that contains all subnet-to-ports mapping of given device
94 */ 96 */
95 Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId); 97 Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId);
98 +
99 + /**
100 + * Returns the VLAN cross-connect configuration.
101 + *
102 + * @return A map of that maps VLAN ID to a list of cross-connect endpoints
103 + */
104 + Map<VlanId, List<ConnectPoint>> getXConnects();
96 } 105 }
......
...@@ -35,24 +35,24 @@ import java.util.Set; ...@@ -35,24 +35,24 @@ import java.util.Set;
35 * Configuration object for Segment Routing Application. 35 * Configuration object for Segment Routing Application.
36 */ 36 */
37 public class SegmentRoutingConfig extends Config<DeviceId> { 37 public class SegmentRoutingConfig extends Config<DeviceId> {
38 - public static final String NAME = "name"; 38 + private static final String NAME = "name";
39 - public static final String IP = "routerIp"; 39 + private static final String IP = "routerIp";
40 - public static final String MAC = "routerMac"; 40 + private static final String MAC = "routerMac";
41 - public static final String SID = "nodeSid"; 41 + private static final String SID = "nodeSid";
42 - public static final String EDGE = "isEdgeRouter"; 42 + private static final String EDGE = "isEdgeRouter";
43 - public static final String ADJSIDS = "adjacencySids"; 43 + private static final String ADJSIDS = "adjacencySids";
44 - public static final String ADJSID = "adjSid"; 44 + private static final String ADJSID = "adjSid";
45 - public static final String PORTS = "ports"; 45 + private static final String PORTS = "ports";
46 46
47 @Override 47 @Override
48 public boolean isValid() { 48 public boolean isValid() {
49 return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) && 49 return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) &&
50 - this.name() != null && 50 + name() != null &&
51 - this.routerIp() != null && 51 + routerIp() != null &&
52 - this.routerMac() != null && 52 + routerMac() != null &&
53 - this.nodeSid() != -1 && 53 + nodeSid() != -1 &&
54 - this.isEdgeRouter() != null && 54 + isEdgeRouter() != null &&
55 - this.adjacencySids() != null; 55 + adjacencySids() != null;
56 } 56 }
57 57
58 /** 58 /**
......
...@@ -26,7 +26,6 @@ import org.onosproject.net.flowobjective.FlowObjectiveService; ...@@ -26,7 +26,6 @@ import org.onosproject.net.flowobjective.FlowObjectiveService;
26 import org.onosproject.net.link.LinkService; 26 import org.onosproject.net.link.LinkService;
27 import org.onosproject.segmentrouting.SegmentRoutingManager; 27 import org.onosproject.segmentrouting.SegmentRoutingManager;
28 import org.onosproject.segmentrouting.config.DeviceProperties; 28 import org.onosproject.segmentrouting.config.DeviceProperties;
29 -import org.onosproject.store.service.EventuallyConsistentMap;
30 29
31 /** 30 /**
32 * Default ECMP group handler creation module for an edge device. 31 * Default ECMP group handler creation module for an edge device.
...@@ -47,22 +46,13 @@ import org.onosproject.store.service.EventuallyConsistentMap; ...@@ -47,22 +46,13 @@ import org.onosproject.store.service.EventuallyConsistentMap;
47 * 8) what about ecmp no label case 46 * 8) what about ecmp no label case
48 */ 47 */
49 public class DefaultEdgeGroupHandler extends DefaultGroupHandler { 48 public class DefaultEdgeGroupHandler extends DefaultGroupHandler {
50 - // TODO Access stores through srManager
51 protected DefaultEdgeGroupHandler(DeviceId deviceId, 49 protected DefaultEdgeGroupHandler(DeviceId deviceId,
52 ApplicationId appId, 50 ApplicationId appId,
53 DeviceProperties config, 51 DeviceProperties config,
54 LinkService linkService, 52 LinkService linkService,
55 FlowObjectiveService flowObjService, 53 FlowObjectiveService flowObjService,
56 - EventuallyConsistentMap<
57 - NeighborSetNextObjectiveStoreKey,
58 - Integer> nsNextObjStore,
59 - EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
60 - Integer> subnetNextObjStore,
61 - EventuallyConsistentMap<PortNextObjectiveStoreKey,
62 - Integer> portNextObjStore,
63 SegmentRoutingManager srManager) { 54 SegmentRoutingManager srManager) {
64 - super(deviceId, appId, config, linkService, flowObjService, 55 + super(deviceId, appId, config, linkService, flowObjService, srManager);
65 - nsNextObjStore, subnetNextObjStore, portNextObjStore, srManager);
66 } 56 }
67 57
68 @Override 58 @Override
......
...@@ -35,6 +35,7 @@ import org.onlab.packet.MplsLabel; ...@@ -35,6 +35,7 @@ import org.onlab.packet.MplsLabel;
35 import org.onlab.packet.VlanId; 35 import org.onlab.packet.VlanId;
36 import org.onlab.util.KryoNamespace; 36 import org.onlab.util.KryoNamespace;
37 import org.onosproject.core.ApplicationId; 37 import org.onosproject.core.ApplicationId;
38 +import org.onosproject.net.ConnectPoint;
38 import org.onosproject.net.DeviceId; 39 import org.onosproject.net.DeviceId;
39 import org.onosproject.net.Link; 40 import org.onosproject.net.Link;
40 import org.onosproject.net.PortNumber; 41 import org.onosproject.net.PortNumber;
...@@ -48,8 +49,6 @@ import org.onosproject.net.flowobjective.NextObjective; ...@@ -48,8 +49,6 @@ import org.onosproject.net.flowobjective.NextObjective;
48 import org.onosproject.net.flowobjective.Objective; 49 import org.onosproject.net.flowobjective.Objective;
49 import org.onosproject.net.flowobjective.ObjectiveContext; 50 import org.onosproject.net.flowobjective.ObjectiveContext;
50 import org.onosproject.net.flowobjective.ObjectiveError; 51 import org.onosproject.net.flowobjective.ObjectiveError;
51 -import org.onosproject.net.group.DefaultGroupKey;
52 -import org.onosproject.net.group.GroupKey;
53 import org.onosproject.net.link.LinkService; 52 import org.onosproject.net.link.LinkService;
54 import org.onosproject.segmentrouting.SegmentRoutingManager; 53 import org.onosproject.segmentrouting.SegmentRoutingManager;
55 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; 54 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
...@@ -81,12 +80,14 @@ public class DefaultGroupHandler { ...@@ -81,12 +80,14 @@ public class DefaultGroupHandler {
81 //local store for ports on this device connected to neighbor-device-id 80 //local store for ports on this device connected to neighbor-device-id
82 protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap = 81 protected ConcurrentHashMap<PortNumber, DeviceId> portDeviceMap =
83 new ConcurrentHashMap<>(); 82 new ConcurrentHashMap<>();
84 - protected EventuallyConsistentMap< 83 + protected EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
85 - NeighborSetNextObjectiveStoreKey, Integer> nsNextObjStore = null; 84 + nsNextObjStore = null;
86 - protected EventuallyConsistentMap< 85 + protected EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
87 - SubnetNextObjectiveStoreKey, Integer> subnetNextObjStore = null; 86 + subnetNextObjStore = null;
88 - protected EventuallyConsistentMap< 87 + protected EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
89 - PortNextObjectiveStoreKey, Integer> portNextObjStore = null; 88 + portNextObjStore = null;
89 + protected EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
90 + xConnectNextObjStore = null;
90 private SegmentRoutingManager srManager; 91 private SegmentRoutingManager srManager;
91 92
92 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder() 93 protected KryoNamespace.Builder kryo = new KryoNamespace.Builder()
...@@ -97,17 +98,10 @@ public class DefaultGroupHandler { ...@@ -97,17 +98,10 @@ public class DefaultGroupHandler {
97 .register(GroupBucketIdentifier.class) 98 .register(GroupBucketIdentifier.class)
98 .register(GroupBucketIdentifier.BucketOutputType.class); 99 .register(GroupBucketIdentifier.BucketOutputType.class);
99 100
100 - // TODO Access stores through srManager
101 protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId, 101 protected DefaultGroupHandler(DeviceId deviceId, ApplicationId appId,
102 DeviceProperties config, 102 DeviceProperties config,
103 LinkService linkService, 103 LinkService linkService,
104 FlowObjectiveService flowObjService, 104 FlowObjectiveService flowObjService,
105 - EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
106 - Integer> nsNextObjStore,
107 - EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
108 - Integer> subnetNextObjStore,
109 - EventuallyConsistentMap<PortNextObjectiveStoreKey,
110 - Integer> portNextObjStore,
111 SegmentRoutingManager srManager) { 105 SegmentRoutingManager srManager) {
112 this.deviceId = checkNotNull(deviceId); 106 this.deviceId = checkNotNull(deviceId);
113 this.appId = checkNotNull(appId); 107 this.appId = checkNotNull(appId);
...@@ -123,9 +117,10 @@ public class DefaultGroupHandler { ...@@ -123,9 +117,10 @@ public class DefaultGroupHandler {
123 + " Skipping value assignment in DefaultGroupHandler"); 117 + " Skipping value assignment in DefaultGroupHandler");
124 } 118 }
125 this.flowObjectiveService = flowObjService; 119 this.flowObjectiveService = flowObjService;
126 - this.nsNextObjStore = nsNextObjStore; 120 + this.nsNextObjStore = srManager.nsNextObjStore;
127 - this.subnetNextObjStore = subnetNextObjStore; 121 + this.subnetNextObjStore = srManager.subnetNextObjStore;
128 - this.portNextObjStore = portNextObjStore; 122 + this.portNextObjStore = srManager.portNextObjStore;
123 + this.xConnectNextObjStore = srManager.xConnectNextObjStore;
129 this.srManager = srManager; 124 this.srManager = srManager;
130 125
131 populateNeighborMaps(); 126 populateNeighborMaps();
...@@ -141,8 +136,7 @@ public class DefaultGroupHandler { ...@@ -141,8 +136,7 @@ public class DefaultGroupHandler {
141 * @param config interface to retrieve the device properties 136 * @param config interface to retrieve the device properties
142 * @param linkService link service object 137 * @param linkService link service object
143 * @param flowObjService flow objective service object 138 * @param flowObjService flow objective service object
144 - * @param nsNextObjStore NeighborSet next objective store map 139 + * @param srManager segment routing manager
145 - * @param subnetNextObjStore subnet next objective store map
146 * @throws DeviceConfigNotFoundException if the device configuration is not found 140 * @throws DeviceConfigNotFoundException if the device configuration is not found
147 * @return default group handler type 141 * @return default group handler type
148 */ 142 */
...@@ -152,12 +146,6 @@ public class DefaultGroupHandler { ...@@ -152,12 +146,6 @@ public class DefaultGroupHandler {
152 DeviceProperties config, 146 DeviceProperties config,
153 LinkService linkService, 147 LinkService linkService,
154 FlowObjectiveService flowObjService, 148 FlowObjectiveService flowObjService,
155 - EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
156 - Integer> nsNextObjStore,
157 - EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
158 - Integer> subnetNextObjStore,
159 - EventuallyConsistentMap<PortNextObjectiveStoreKey,
160 - Integer> portNextObjStore,
161 SegmentRoutingManager srManager) 149 SegmentRoutingManager srManager)
162 throws DeviceConfigNotFoundException { 150 throws DeviceConfigNotFoundException {
163 // handle possible exception in the caller 151 // handle possible exception in the caller
...@@ -165,18 +153,12 @@ public class DefaultGroupHandler { ...@@ -165,18 +153,12 @@ public class DefaultGroupHandler {
165 return new DefaultEdgeGroupHandler(deviceId, appId, config, 153 return new DefaultEdgeGroupHandler(deviceId, appId, config,
166 linkService, 154 linkService,
167 flowObjService, 155 flowObjService,
168 - nsNextObjStore,
169 - subnetNextObjStore,
170 - portNextObjStore,
171 srManager 156 srManager
172 ); 157 );
173 } else { 158 } else {
174 return new DefaultTransitGroupHandler(deviceId, appId, config, 159 return new DefaultTransitGroupHandler(deviceId, appId, config,
175 linkService, 160 linkService,
176 flowObjService, 161 flowObjService,
177 - nsNextObjStore,
178 - subnetNextObjStore,
179 - portNextObjStore,
180 srManager); 162 srManager);
181 } 163 }
182 } 164 }
...@@ -194,6 +176,8 @@ public class DefaultGroupHandler { ...@@ -194,6 +176,8 @@ public class DefaultGroupHandler {
194 * discovered on this device. 176 * discovered on this device.
195 * 177 *
196 * @param newLink new neighbor link 178 * @param newLink new neighbor link
179 + * @param isMaster true if local instance is the master
180 + *
197 */ 181 */
198 public void linkUp(Link newLink, boolean isMaster) { 182 public void linkUp(Link newLink, boolean isMaster) {
199 183
...@@ -296,6 +280,7 @@ public class DefaultGroupHandler { ...@@ -296,6 +280,7 @@ public class DefaultGroupHandler {
296 * Performs group recovery procedures when a port goes down on this device. 280 * Performs group recovery procedures when a port goes down on this device.
297 * 281 *
298 * @param port port number that has gone down 282 * @param port port number that has gone down
283 + * @param isMaster true if local instance is the master
299 */ 284 */
300 public void portDown(PortNumber port, boolean isMaster) { 285 public void portDown(PortNumber port, boolean isMaster) {
301 if (portDeviceMap.get(port) == null) { 286 if (portDeviceMap.get(port) == null) {
...@@ -448,8 +433,8 @@ public class DefaultGroupHandler { ...@@ -448,8 +433,8 @@ public class DefaultGroupHandler {
448 */ 433 */
449 public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment, 434 public int getPortNextObjectiveId(PortNumber portNum, TrafficTreatment treatment,
450 TrafficSelector meta) { 435 TrafficSelector meta) {
451 - Integer nextId = portNextObjStore. 436 + Integer nextId = portNextObjStore
452 - get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment)); 437 + .get(new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
453 if (nextId == null) { 438 if (nextId == null) {
454 log.trace("getPortNextObjectiveId in device{}: Next objective id " 439 log.trace("getPortNextObjectiveId in device{}: Next objective id "
455 + "not found for {} and {} creating", deviceId, portNum); 440 + "not found for {} and {} creating", deviceId, portNum);
...@@ -458,7 +443,33 @@ public class DefaultGroupHandler { ...@@ -458,7 +443,33 @@ public class DefaultGroupHandler {
458 new PortNextObjectiveStoreKey(deviceId, portNum, treatment)); 443 new PortNextObjectiveStoreKey(deviceId, portNum, treatment));
459 if (nextId == null) { 444 if (nextId == null) {
460 log.warn("getPortNextObjectiveId: unable to create next obj" 445 log.warn("getPortNextObjectiveId: unable to create next obj"
461 - + "for dev:{} port{}", deviceId, portNum); 446 + + "for dev:{} port:{}", deviceId, portNum);
447 + return -1;
448 + }
449 + }
450 + return nextId;
451 + }
452 +
453 + /**
454 + * Returns the next objective ID of type broadcast associated with the VLAN
455 + * cross-connection.
456 + *
457 + * @param vlanId VLAN ID for the cross-connection
458 + * @return int if found or created, -1 if there are errors during the
459 + * creation of the next objective
460 + */
461 + public int getXConnectNextObjectiveId(VlanId vlanId) {
462 + Integer nextId = xConnectNextObjStore
463 + .get(new XConnectNextObjectiveStoreKey(deviceId, vlanId));
464 + if (nextId == null) {
465 + log.trace("getXConnectNextObjectiveId: Next objective id "
466 + + "not found for device {} and vlan {}. Creating", deviceId, vlanId);
467 + createGroupsForXConnect(deviceId);
468 + nextId = xConnectNextObjStore.get(
469 + new XConnectNextObjectiveStoreKey(deviceId, vlanId));
470 + if (nextId == null) {
471 + log.warn("getXConnectNextObjectiveId: Next objective id "
472 + + "not found for device {} and vlan {}.", deviceId, vlanId);
462 return -1; 473 return -1;
463 } 474 }
464 } 475 }
...@@ -655,7 +666,6 @@ public class DefaultGroupHandler { ...@@ -655,7 +666,6 @@ public class DefaultGroupHandler {
655 666
656 /** 667 /**
657 * Creates broadcast groups for all ports in the same configured subnet. 668 * Creates broadcast groups for all ports in the same configured subnet.
658 - *
659 */ 669 */
660 public void createGroupsFromSubnetConfig() { 670 public void createGroupsFromSubnetConfig() {
661 Map<Ip4Prefix, List<PortNumber>> subnetPortMap = 671 Map<Ip4Prefix, List<PortNumber>> subnetPortMap =
...@@ -700,6 +710,54 @@ public class DefaultGroupHandler { ...@@ -700,6 +710,54 @@ public class DefaultGroupHandler {
700 }); 710 });
701 } 711 }
702 712
713 + /**
714 + * Creates broadcast groups for VLAN cross-connect ports.
715 + *
716 + * @param deviceId the DPID of the switch
717 + */
718 + public void createGroupsForXConnect(DeviceId deviceId) {
719 + Map<VlanId, List<ConnectPoint>> xConnectsForDevice = deviceConfig.getXConnects();
720 +
721 + xConnectsForDevice.forEach((vlanId, connectPoints) -> {
722 + // Only proceed the xConnect for given device
723 + for (ConnectPoint connectPoint : connectPoints) {
724 + if (!connectPoint.deviceId().equals(deviceId)) {
725 + return;
726 + }
727 + }
728 +
729 + // Check if the next obj is already in the store
730 + XConnectNextObjectiveStoreKey key =
731 + new XConnectNextObjectiveStoreKey(deviceId, vlanId);
732 + if (xConnectNextObjStore.containsKey(key)) {
733 + log.debug("Cross-connect Broadcast group for device {} and vlanId {} exists",
734 + deviceId, vlanId);
735 + return;
736 + }
737 +
738 + TrafficSelector metadata =
739 + DefaultTrafficSelector.builder().matchVlanId(vlanId).build();
740 + int nextId = flowObjectiveService.allocateNextId();
741 +
742 + NextObjective.Builder nextObjBuilder = DefaultNextObjective
743 + .builder().withId(nextId)
744 + .withType(NextObjective.Type.BROADCAST).fromApp(appId)
745 + .withMeta(metadata);
746 +
747 + connectPoints.forEach(connectPoint -> {
748 + TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
749 + tBuilder.setOutput(connectPoint.port());
750 + nextObjBuilder.addTreatment(tBuilder.build());
751 + });
752 +
753 + NextObjective nextObj = nextObjBuilder.add();
754 + flowObjectiveService.next(deviceId, nextObj);
755 + log.debug("createGroupsForXConnect: Submited next objective {} in device {}",
756 + nextId, deviceId);
757 + xConnectNextObjStore.put(key, nextId);
758 + });
759 + }
760 +
703 761
704 /** 762 /**
705 * Create simple next objective for a single port. The treatments can include 763 * Create simple next objective for a single port. The treatments can include
...@@ -730,11 +788,6 @@ public class DefaultGroupHandler { ...@@ -730,11 +788,6 @@ public class DefaultGroupHandler {
730 portNextObjStore.put(key, nextId); 788 portNextObjStore.put(key, nextId);
731 } 789 }
732 790
733 -
734 - public GroupKey getGroupKey(Object obj) {
735 - return new DefaultGroupKey(kryo.build().serialize(obj));
736 - }
737 -
738 /** 791 /**
739 * Removes groups for the next objective ID given. 792 * Removes groups for the next objective ID given.
740 * 793 *
...@@ -766,6 +819,9 @@ public class DefaultGroupHandler { ...@@ -766,6 +819,9 @@ public class DefaultGroupHandler {
766 return false; 819 return false;
767 } 820 }
768 821
822 + /**
823 + * Removes all groups from all next objective stores.
824 + */
769 public void removeAllGroups() { 825 public void removeAllGroups() {
770 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry: 826 for (Map.Entry<NeighborSetNextObjectiveStoreKey, Integer> entry:
771 nsNextObjStore.entrySet()) { 827 nsNextObjStore.entrySet()) {
......
...@@ -26,7 +26,6 @@ import org.onosproject.net.link.LinkService; ...@@ -26,7 +26,6 @@ import org.onosproject.net.link.LinkService;
26 import org.onosproject.segmentrouting.SegmentRoutingManager; 26 import org.onosproject.segmentrouting.SegmentRoutingManager;
27 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; 27 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
28 import org.onosproject.segmentrouting.config.DeviceProperties; 28 import org.onosproject.segmentrouting.config.DeviceProperties;
29 -import org.onosproject.store.service.EventuallyConsistentMap;
30 29
31 /** 30 /**
32 * Default ECMP group handler creation module for a transit device. 31 * Default ECMP group handler creation module for a transit device.
...@@ -41,22 +40,13 @@ import org.onosproject.store.service.EventuallyConsistentMap; ...@@ -41,22 +40,13 @@ import org.onosproject.store.service.EventuallyConsistentMap;
41 * 2) all ports to D3 + with no label push, 40 * 2) all ports to D3 + with no label push,
42 */ 41 */
43 public class DefaultTransitGroupHandler extends DefaultGroupHandler { 42 public class DefaultTransitGroupHandler extends DefaultGroupHandler {
44 - // TODO Access stores through srManager
45 protected DefaultTransitGroupHandler(DeviceId deviceId, 43 protected DefaultTransitGroupHandler(DeviceId deviceId,
46 ApplicationId appId, 44 ApplicationId appId,
47 DeviceProperties config, 45 DeviceProperties config,
48 LinkService linkService, 46 LinkService linkService,
49 FlowObjectiveService flowObjService, 47 FlowObjectiveService flowObjService,
50 - EventuallyConsistentMap<
51 - NeighborSetNextObjectiveStoreKey,
52 - Integer> nsNextObjStore,
53 - EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
54 - Integer> subnetNextObjStore,
55 - EventuallyConsistentMap<PortNextObjectiveStoreKey,
56 - Integer> portNextObjStore,
57 SegmentRoutingManager srManager) { 48 SegmentRoutingManager srManager) {
58 - super(deviceId, appId, config, linkService, flowObjService, 49 + super(deviceId, appId, config, linkService, flowObjService, srManager);
59 - nsNextObjStore, subnetNextObjStore, portNextObjStore, srManager);
60 } 50 }
61 51
62 @Override 52 @Override
......
...@@ -21,22 +21,38 @@ import java.util.Objects; ...@@ -21,22 +21,38 @@ import java.util.Objects;
21 import org.onosproject.net.DeviceId; 21 import org.onosproject.net.DeviceId;
22 22
23 /** 23 /**
24 - * Class definition of Key for Neighborset to NextObjective store. 24 + * Key of Neighborset next objective store.
25 */ 25 */
26 public class NeighborSetNextObjectiveStoreKey { 26 public class NeighborSetNextObjectiveStoreKey {
27 private final DeviceId deviceId; 27 private final DeviceId deviceId;
28 private final NeighborSet ns; 28 private final NeighborSet ns;
29 29
30 + /**
31 + * Constructs the key of neighbor set next objective store.
32 + *
33 + * @param deviceId device ID
34 + * @param ns neighbor set
35 + */
30 public NeighborSetNextObjectiveStoreKey(DeviceId deviceId, 36 public NeighborSetNextObjectiveStoreKey(DeviceId deviceId,
31 NeighborSet ns) { 37 NeighborSet ns) {
32 this.deviceId = deviceId; 38 this.deviceId = deviceId;
33 this.ns = ns; 39 this.ns = ns;
34 } 40 }
35 41
42 + /**
43 + * Returns the device ID in the key.
44 + *
45 + * @return device ID
46 + */
36 public DeviceId deviceId() { 47 public DeviceId deviceId() {
37 return this.deviceId; 48 return this.deviceId;
38 } 49 }
39 50
51 + /**
52 + * Returns the neighbor set in the key.
53 + *
54 + * @return neighbor set
55 + */
40 public NeighborSet neighborSet() { 56 public NeighborSet neighborSet() {
41 return this.ns; 57 return this.ns;
42 } 58 }
......
...@@ -31,7 +31,6 @@ import org.onosproject.segmentrouting.SegmentRoutingManager; ...@@ -31,7 +31,6 @@ import org.onosproject.segmentrouting.SegmentRoutingManager;
31 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException; 31 import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
32 import org.onosproject.segmentrouting.config.DeviceProperties; 32 import org.onosproject.segmentrouting.config.DeviceProperties;
33 import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType; 33 import org.onosproject.segmentrouting.grouphandler.GroupBucketIdentifier.BucketOutputType;
34 -import org.onosproject.store.service.EventuallyConsistentMap;
35 import org.onosproject.net.DeviceId; 34 import org.onosproject.net.DeviceId;
36 import org.onosproject.net.PortNumber; 35 import org.onosproject.net.PortNumber;
37 import org.onosproject.net.flow.DefaultTrafficTreatment; 36 import org.onosproject.net.flow.DefaultTrafficTreatment;
...@@ -51,33 +50,31 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -51,33 +50,31 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
51 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>(); 50 private HashMap<PolicyGroupIdentifier, PolicyGroupIdentifier> dependentGroups = new HashMap<>();
52 51
53 /** 52 /**
54 - * Policy group handler constructor. 53 + * Constructs policy group handler.
55 * 54 *
56 * @param deviceId device identifier 55 * @param deviceId device identifier
57 * @param appId application identifier 56 * @param appId application identifier
58 * @param config interface to retrieve the device properties 57 * @param config interface to retrieve the device properties
59 * @param linkService link service object 58 * @param linkService link service object
60 * @param flowObjService flow objective service object 59 * @param flowObjService flow objective service object
61 - * @param nsNextObjStore NeighborSet next objective store map 60 + * @param srManager segment routing manager
62 - * @param subnetNextObjStore subnet next objective store map
63 */ 61 */
64 - // TODO Access stores through srManager
65 public PolicyGroupHandler(DeviceId deviceId, 62 public PolicyGroupHandler(DeviceId deviceId,
66 ApplicationId appId, 63 ApplicationId appId,
67 DeviceProperties config, 64 DeviceProperties config,
68 LinkService linkService, 65 LinkService linkService,
69 FlowObjectiveService flowObjService, 66 FlowObjectiveService flowObjService,
70 - EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey,
71 - Integer> nsNextObjStore,
72 - EventuallyConsistentMap<SubnetNextObjectiveStoreKey,
73 - Integer> subnetNextObjStore,
74 - EventuallyConsistentMap<PortNextObjectiveStoreKey,
75 - Integer> portNextObjStore,
76 SegmentRoutingManager srManager) { 67 SegmentRoutingManager srManager) {
77 - super(deviceId, appId, config, linkService, flowObjService, 68 + super(deviceId, appId, config, linkService, flowObjService, srManager);
78 - nsNextObjStore, subnetNextObjStore, portNextObjStore, srManager);
79 } 69 }
80 70
71 + /**
72 + * Creates policy group chain.
73 + *
74 + * @param id unique identifier associated with the policy group
75 + * @param params a list of policy group params
76 + * @return policy group identifier
77 + */
81 public PolicyGroupIdentifier createPolicyGroupChain(String id, 78 public PolicyGroupIdentifier createPolicyGroupChain(String id,
82 List<PolicyGroupParams> params) { 79 List<PolicyGroupParams> params) {
83 List<GroupBucketIdentifier> bucketIds = new ArrayList<>(); 80 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
...@@ -222,69 +219,18 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -222,69 +219,18 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
222 } 219 }
223 220
224 //TODO: Use nextObjective APIs to handle the group chains 221 //TODO: Use nextObjective APIs to handle the group chains
225 - /*@Override 222 + /*
226 - protected void handleGroupEvent(GroupEvent event) { 223 + @Override
227 - if (event.type() == GroupEvent.Type.GROUP_ADDED) { 224 + protected void handleGroupEvent(GroupEvent event) {}
228 - if (dependentGroups.get(event.subject().appCookie()) != null) { 225 + */
229 - PolicyGroupIdentifier dependentGroupKey = dependentGroups.get(event.subject().appCookie());
230 - dependentGroups.remove(event.subject().appCookie());
231 - boolean fullyResolved = true;
232 - for (GroupBucketIdentifier bucketId:
233 - dependentGroupKey.bucketIds()) {
234 - if (bucketId.type() != BucketOutputType.GROUP) {
235 - continue;
236 - }
237 - if (dependentGroups.containsKey(bucketId.outGroup())) {
238 - fullyResolved = false;
239 - break;
240 - }
241 - }
242 -
243 - if (fullyResolved) {
244 - List<GroupBucket> outBuckets = new ArrayList<GroupBucket>();
245 - for (GroupBucketIdentifier bucketId:
246 - dependentGroupKey.bucketIds()) {
247 - TrafficTreatment.Builder tBuilder =
248 - DefaultTrafficTreatment.builder();
249 - if (bucketId.label() != NeighborSet.NO_EDGE_LABEL) {
250 - tBuilder.pushMpls()
251 - .setMpls(MplsLabel.
252 - mplsLabel(bucketId.label()));
253 - }
254 - //TODO: BoS
255 - if (bucketId.type() == BucketOutputType.PORT) {
256 - DeviceId neighbor = portDeviceMap.
257 - get(bucketId.outPort());
258 - tBuilder.setOutput(bucketId.outPort())
259 - .setEthDst(deviceConfig.
260 - getDeviceMac(neighbor))
261 - .setEthSrc(nodeMacAddr);
262 - } else {
263 - if (groupService.
264 - getGroup(deviceId,
265 - getGroupKey(bucketId.
266 - outGroup())) == null) {
267 - throw new IllegalStateException();
268 - }
269 - GroupId indirectGroupId = groupService.
270 - getGroup(deviceId,
271 - getGroupKey(bucketId.
272 - outGroup())).id();
273 - tBuilder.group(indirectGroupId);
274 - }
275 - outBuckets.add(DefaultGroupBucket.
276 - createSelectGroupBucket(tBuilder.build()));
277 - }
278 - GroupDescription desc = new
279 - DefaultGroupDescription(deviceId,
280 - GroupDescription.Type.SELECT,
281 - new GroupBuckets(outBuckets));
282 - groupService.addGroup(desc);
283 - }
284 - }
285 - }
286 - }*/
287 226
227 + /**
228 + * Generates policy group key.
229 + *
230 + * @param id unique identifier associated with the policy group
231 + * @param params a list of policy group params
232 + * @return policy group identifier
233 + */
288 public PolicyGroupIdentifier generatePolicyGroupKey(String id, 234 public PolicyGroupIdentifier generatePolicyGroupKey(String id,
289 List<PolicyGroupParams> params) { 235 List<PolicyGroupParams> params) {
290 List<GroupBucketIdentifier> bucketIds = new ArrayList<>(); 236 List<GroupBucketIdentifier> bucketIds = new ArrayList<>();
...@@ -354,6 +300,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler { ...@@ -354,6 +300,11 @@ public class PolicyGroupHandler extends DefaultGroupHandler {
354 return innermostGroupkey; 300 return innermostGroupkey;
355 } 301 }
356 302
303 + /**
304 + * Removes policy group chain.
305 + *
306 + * @param key policy group identifier
307 + */
357 public void removeGroupChain(PolicyGroupIdentifier key) { 308 public void removeGroupChain(PolicyGroupIdentifier key) {
358 checkArgument(key != null); 309 checkArgument(key != null);
359 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>(); 310 List<PolicyGroupIdentifier> groupsToBeDeleted = new ArrayList<>();
......
...@@ -28,7 +28,7 @@ public class PolicyGroupIdentifier { ...@@ -28,7 +28,7 @@ public class PolicyGroupIdentifier {
28 private List<GroupBucketIdentifier> bucketIds; 28 private List<GroupBucketIdentifier> bucketIds;
29 29
30 /** 30 /**
31 - * Constructor. 31 + * Constructs policy group identifier.
32 * 32 *
33 * @param id unique identifier associated with the policy group 33 * @param id unique identifier associated with the policy group
34 * @param input policy group params associated with this group 34 * @param input policy group params associated with this group
......
...@@ -7,15 +7,23 @@ import org.onosproject.net.flow.TrafficTreatment; ...@@ -7,15 +7,23 @@ import org.onosproject.net.flow.TrafficTreatment;
7 import java.util.Objects; 7 import java.util.Objects;
8 8
9 /** 9 /**
10 - * Class definition of Key for Device/Port to NextObjective store. Since there 10 + * Key of Device/Port to NextObjective store.
11 - * can be multiple next objectives to the same physical port, we differentiate 11 + *
12 - * between them by including the treatment in the key. 12 + * Since there can be multiple next objectives to the same physical port,
13 + * we differentiate between them by including the treatment in the key.
13 */ 14 */
14 public class PortNextObjectiveStoreKey { 15 public class PortNextObjectiveStoreKey {
15 private final DeviceId deviceId; 16 private final DeviceId deviceId;
16 private final PortNumber portNum; 17 private final PortNumber portNum;
17 private final TrafficTreatment treatment; 18 private final TrafficTreatment treatment;
18 19
20 + /**
21 + * Constructs the key of port next objective store.
22 + *
23 + * @param deviceId device ID
24 + * @param portNum port number
25 + * @param treatment treatment that will be applied to the interface
26 + */
19 public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum, 27 public PortNextObjectiveStoreKey(DeviceId deviceId, PortNumber portNum,
20 TrafficTreatment treatment) { 28 TrafficTreatment treatment) {
21 this.deviceId = deviceId; 29 this.deviceId = deviceId;
......
...@@ -22,12 +22,18 @@ import org.onosproject.net.DeviceId; ...@@ -22,12 +22,18 @@ import org.onosproject.net.DeviceId;
22 import java.util.Objects; 22 import java.util.Objects;
23 23
24 /** 24 /**
25 - * Class definition of Key for Subnet to NextObjective store. 25 + * Key of Subnet to NextObjective store.
26 */ 26 */
27 public class SubnetNextObjectiveStoreKey { 27 public class SubnetNextObjectiveStoreKey {
28 private final DeviceId deviceId; 28 private final DeviceId deviceId;
29 private final IpPrefix prefix; 29 private final IpPrefix prefix;
30 30
31 + /**
32 + * Constructs the key of subnet next objective store.
33 + *
34 + * @param deviceId device ID
35 + * @param prefix subnet information
36 + */
31 public SubnetNextObjectiveStoreKey(DeviceId deviceId, 37 public SubnetNextObjectiveStoreKey(DeviceId deviceId,
32 IpPrefix prefix) { 38 IpPrefix prefix) {
33 this.deviceId = deviceId; 39 this.deviceId = deviceId;
......
1 +/*
2 + * Copyright 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.VlanId;
20 +import org.onosproject.net.DeviceId;
21 +
22 +import java.util.Objects;
23 +
24 +/**
25 + * Key of VLAN cross-connect next objective store.
26 + */
27 +public class XConnectNextObjectiveStoreKey {
28 + private final DeviceId deviceId;
29 + private final VlanId vlanId;
30 +
31 + /**
32 + * Constructs the key of cross-connect next objective store.
33 + *
34 + * @param deviceId device ID of the VLAN cross-connection
35 + * @param vlanId VLAN ID of the VLAN cross-connection
36 + */
37 + public XConnectNextObjectiveStoreKey(DeviceId deviceId, VlanId vlanId) {
38 + this.deviceId = deviceId;
39 + this.vlanId = vlanId;
40 + }
41 +
42 + /**
43 + * Returns the device ID of this key.
44 + *
45 + * @return device ID
46 + */
47 + public DeviceId deviceId() {
48 + return this.deviceId;
49 + }
50 +
51 + /**
52 + * Returns the VLAN ID of this key.
53 + *
54 + * @return VLAN ID
55 + */
56 + public VlanId vlanId() {
57 + return this.vlanId;
58 + }
59 +
60 + @Override
61 + public boolean equals(Object o) {
62 + if (this == o) {
63 + return true;
64 + }
65 + if (!(o instanceof XConnectNextObjectiveStoreKey)) {
66 + return false;
67 + }
68 + XConnectNextObjectiveStoreKey that =
69 + (XConnectNextObjectiveStoreKey) o;
70 + return (Objects.equals(this.deviceId, that.deviceId) &&
71 + Objects.equals(this.vlanId, that.vlanId));
72 + }
73 +
74 + // The list of neighbor ids and label are used for comparison.
75 + @Override
76 + public int hashCode() {
77 + return Objects.hash(deviceId, vlanId);
78 + }
79 +
80 + @Override
81 + public String toString() {
82 + return "Device: " + deviceId + " VlanId: " + vlanId;
83 + }
84 +}
...@@ -21,6 +21,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; ...@@ -21,6 +21,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
21 import org.onosproject.segmentrouting.Policy; 21 import org.onosproject.segmentrouting.Policy;
22 import org.onosproject.segmentrouting.TunnelPolicy; 22 import org.onosproject.segmentrouting.TunnelPolicy;
23 23
24 +/**
25 + * Codec of Policy class.
26 + */
24 public final class PolicyCodec extends JsonCodec<Policy> { 27 public final class PolicyCodec extends JsonCodec<Policy> {
25 28
26 // JSON field names 29 // JSON field names
......
...@@ -26,6 +26,9 @@ import org.onosproject.segmentrouting.Tunnel; ...@@ -26,6 +26,9 @@ import org.onosproject.segmentrouting.Tunnel;
26 import java.util.ArrayList; 26 import java.util.ArrayList;
27 import java.util.List; 27 import java.util.List;
28 28
29 +/**
30 + * Codec of Tunnel class.
31 + */
29 public final class TunnelCodec extends JsonCodec<Tunnel> { 32 public final class TunnelCodec extends JsonCodec<Tunnel> {
30 33
31 // JSON field names 34 // JSON field names
......
1 package org.onosproject.driver.pipeline; 1 package org.onosproject.driver.pipeline;
2 2
3 +import com.google.common.base.Objects;
3 import com.google.common.cache.Cache; 4 import com.google.common.cache.Cache;
4 import com.google.common.cache.CacheBuilder; 5 import com.google.common.cache.CacheBuilder;
5 import com.google.common.cache.RemovalCause; 6 import com.google.common.cache.RemovalCause;
...@@ -69,12 +70,18 @@ public class OFDPA2GroupHandler { ...@@ -69,12 +70,18 @@ public class OFDPA2GroupHandler {
69 * L2 Flood Groups have <4bits-4><12bits-vlanid><16bits-index> 70 * L2 Flood Groups have <4bits-4><12bits-vlanid><16bits-index>
70 * L3 VPN Groups have <4bits-9><4bits-2><24bits-index> 71 * L3 VPN Groups have <4bits-9><4bits-2><24bits-index>
71 */ 72 */
72 - private static final int L2INTERFACEMASK = 0x0; 73 + private static final int L2_INTERFACE_TYPE = 0x00000000;
73 - private static final int L3UNICASTMASK = 0x20000000; 74 + private static final int L3_UNICAST_TYPE = 0x20000000;
74 - private static final int MPLSINTERFACEMASK = 0x90000000; 75 + private static final int MPLS_INTERFACE_TYPE = 0x90000000;
75 - private static final int L3ECMPMASK = 0x70000000; 76 + private static final int MPLS_L3VPN_SUBTYPE = 0x92000000;
76 - private static final int L2FLOODMASK = 0x40000000; 77 + private static final int L3_ECMP_TYPE = 0x70000000;
77 - private static final int L3VPNMASK = 0x92000000; 78 + private static final int L2_FLOOD_TYPE = 0x40000000;
79 +
80 + private static final int TYPE_MASK = 0x0fffffff;
81 + private static final int SUBTYPE_MASK = 0x00ffffff;
82 +
83 + private static final int PORT_LOWER_BITS_MASK = 0x3f;
84 + private static final long PORT_HIGHER_BITS_MASK = ~PORT_LOWER_BITS_MASK;
78 85
79 private final Logger log = getLogger(getClass()); 86 private final Logger log = getLogger(getClass());
80 private ServiceDirectory serviceDirectory; 87 private ServiceDirectory serviceDirectory;
...@@ -252,18 +259,9 @@ public class OFDPA2GroupHandler { ...@@ -252,18 +259,9 @@ public class OFDPA2GroupHandler {
252 + " instruction in simple nextObjectives: {}", ins.type()); 259 + " instruction in simple nextObjectives: {}", ins.type());
253 } 260 }
254 } 261 }
255 - //use the vlanid associated with the port
256 - VlanId vlanid = port2Vlan.get(portNum);
257 -
258 - if (vlanid == null && nextObj.meta() != null) {
259 - // use metadata vlan info if available
260 - Criterion vidCriterion = nextObj.meta().getCriterion(Criterion.Type.VLAN_VID);
261 - if (vidCriterion != null) {
262 - vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
263 - }
264 - }
265 262
266 - if (vlanid == null) { 263 + VlanId vlanId = readVlanFromMeta(nextObj);
264 + if (vlanId == null) {
267 log.error("Driver cannot process an L2/L3 group chain without " 265 log.error("Driver cannot process an L2/L3 group chain without "
268 + "egress vlan information for dev: {} port:{}", 266 + "egress vlan information for dev: {} port:{}",
269 deviceId, portNum); 267 deviceId, portNum);
...@@ -271,11 +269,11 @@ public class OFDPA2GroupHandler { ...@@ -271,11 +269,11 @@ public class OFDPA2GroupHandler {
271 } 269 }
272 270
273 // assemble information for ofdpa l2interface group 271 // assemble information for ofdpa l2interface group
274 - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum.toLong(); 272 + int l2groupId = L2_INTERFACE_TYPE | (vlanId.toShort() << 16) | (int) portNum.toLong();
275 // a globally unique groupkey that is different for ports in the same devices 273 // a globally unique groupkey that is different for ports in the same devices
276 // but different for the same portnumber on different devices. Also different 274 // but different for the same portnumber on different devices. Also different
277 // for the various group-types created out of the same next objective. 275 // for the various group-types created out of the same next objective.
278 - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong()); 276 + int l2gk = l2InterfaceGroupKey(deviceId, vlanId, portNum.toLong());
279 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk)); 277 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk));
280 278
281 // create group description for the l2interfacegroup 279 // create group description for the l2interfacegroup
...@@ -399,20 +397,20 @@ public class OFDPA2GroupHandler { ...@@ -399,20 +397,20 @@ public class OFDPA2GroupHandler {
399 } 397 }
400 398
401 // assemble information for ofdpa l2interface group 399 // assemble information for ofdpa l2interface group
402 - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum; 400 + int l2groupId = L2_INTERFACE_TYPE | (vlanid.toShort() << 16) | (int) portNum;
403 // a globally unique groupkey that is different for ports in the same devices 401 // a globally unique groupkey that is different for ports in the same devices
404 // but different for the same portnumber on different devices. Also different 402 // but different for the same portnumber on different devices. Also different
405 // for the various group-types created out of the same next objective. 403 // for the various group-types created out of the same next objective.
406 - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum); 404 + int l2gk = l2InterfaceGroupKey(deviceId, vlanid, portNum);
407 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk)); 405 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk));
408 406
409 // assemble information for outer group 407 // assemble information for outer group
410 GroupDescription outerGrpDesc = null; 408 GroupDescription outerGrpDesc = null;
411 if (mpls) { 409 if (mpls) {
412 // outer group is MPLSInteface 410 // outer group is MPLSInteface
413 - Integer mplsgroupId = MPLSINTERFACEMASK | (int) portNum; 411 + int mplsgroupId = MPLS_INTERFACE_TYPE | (int) portNum;
414 // using mplsinterfacemask in groupkey to differentiate from l2interface 412 // using mplsinterfacemask in groupkey to differentiate from l2interface
415 - int mplsgk = MPLSINTERFACEMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum)); 413 + int mplsgk = MPLS_INTERFACE_TYPE | (SUBTYPE_MASK & (deviceId.hashCode() << 8 | (int) portNum));
416 final GroupKey mplsgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(mplsgk)); 414 final GroupKey mplsgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(mplsgk));
417 outerTtb.group(new DefaultGroupId(l2groupId)); 415 outerTtb.group(new DefaultGroupId(l2groupId));
418 // create the mpls-interface group description to wait for the 416 // create the mpls-interface group description to wait for the
...@@ -432,8 +430,8 @@ public class OFDPA2GroupHandler { ...@@ -432,8 +430,8 @@ public class OFDPA2GroupHandler {
432 mplsgroupkey, nextId); 430 mplsgroupkey, nextId);
433 } else { 431 } else {
434 // outer group is L3Unicast 432 // outer group is L3Unicast
435 - Integer l3groupId = L3UNICASTMASK | (int) portNum; 433 + int l3groupId = L3_UNICAST_TYPE | (int) portNum;
436 - int l3gk = L3UNICASTMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum)); 434 + int l3gk = L3_UNICAST_TYPE | (TYPE_MASK & (deviceId.hashCode() << 8 | (int) portNum));
437 final GroupKey l3groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3gk)); 435 final GroupKey l3groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3gk));
438 outerTtb.group(new DefaultGroupId(l2groupId)); 436 outerTtb.group(new DefaultGroupId(l2groupId));
439 // create the l3unicast group description to wait for the 437 // create the l3unicast group description to wait for the
...@@ -488,14 +486,11 @@ public class OFDPA2GroupHandler { ...@@ -488,14 +486,11 @@ public class OFDPA2GroupHandler {
488 // break up broadcast next objective to multiple groups 486 // break up broadcast next objective to multiple groups
489 Collection<TrafficTreatment> buckets = nextObj.next(); 487 Collection<TrafficTreatment> buckets = nextObj.next();
490 488
491 - // Read VLAN information from the metadata 489 + VlanId vlanId = readVlanFromMeta(nextObj);
492 - TrafficSelector metadata = nextObj.meta(); 490 + if (vlanId == null) {
493 - Criterion criterion = metadata.getCriterion(Criterion.Type.VLAN_VID);
494 - if (criterion == null) {
495 log.warn("Required VLAN ID info in nextObj metadata but not found. Aborting"); 491 log.warn("Required VLAN ID info in nextObj metadata but not found. Aborting");
496 return; 492 return;
497 } 493 }
498 - VlanId vlanId = ((VlanIdCriterion) criterion).vlanId();
499 494
500 // each treatment is converted to an L2 interface group 495 // each treatment is converted to an L2 interface group
501 List<GroupDescription> l2interfaceGroupDescs = new ArrayList<>(); 496 List<GroupDescription> l2interfaceGroupDescs = new ArrayList<>();
...@@ -520,26 +515,15 @@ public class OFDPA2GroupHandler { ...@@ -520,26 +515,15 @@ public class OFDPA2GroupHandler {
520 portNum = ((Instructions.OutputInstruction) ins).port(); 515 portNum = ((Instructions.OutputInstruction) ins).port();
521 newTreatment.add(ins); 516 newTreatment.add(ins);
522 } else { 517 } else {
523 - log.debug("TrafficTreatment of type {} not permitted in " 518 + log.debug("TrafficTreatment of type {} not permitted in " +
524 - + " broadcast nextObjective", ins.type()); 519 + " broadcast nextObjective", ins.type());
525 } 520 }
526 } 521 }
527 522
528 - // Ensure that all ports of this broadcast nextObj are in the same vlan
529 - // XXX maybe HA issue here?
530 - VlanId expectedVlanId = port2Vlan.putIfAbsent(portNum, vlanId);
531 - if (expectedVlanId != null && !vlanId.equals(expectedVlanId)) {
532 - log.error("Driver requires all ports in a broadcast nextObj "
533 - + "to be in the same vlan. Different vlans found "
534 - + "{} and {}. Aborting group creation", vlanId, expectedVlanId);
535 - return;
536 - }
537 -
538 -
539 // assemble info for l2 interface group 523 // assemble info for l2 interface group
540 - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong()); 524 + int l2gk = l2InterfaceGroupKey(deviceId, vlanId, portNum.toLong());
541 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk)); 525 final GroupKey l2groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2gk));
542 - Integer l2groupId = L2INTERFACEMASK | (vlanId.toShort() << 16) | 526 + int l2groupId = L2_INTERFACE_TYPE | (vlanId.toShort() << 16) |
543 (int) portNum.toLong(); 527 (int) portNum.toLong();
544 GroupBucket l2interfaceGroupBucket = 528 GroupBucket l2interfaceGroupBucket =
545 DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build()); 529 DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build());
...@@ -565,8 +549,8 @@ public class OFDPA2GroupHandler { ...@@ -565,8 +549,8 @@ public class OFDPA2GroupHandler {
565 } 549 }
566 550
567 // assemble info for l2 flood group 551 // assemble info for l2 flood group
568 - Integer l2floodgroupId = L2FLOODMASK | (vlanId.toShort() << 16) | nextObj.id(); 552 + Integer l2floodgroupId = L2_FLOOD_TYPE | (vlanId.toShort() << 16) | nextObj.id();
569 - int l2floodgk = L2FLOODMASK | nextObj.id() << 12; 553 + int l2floodgk = L2_FLOOD_TYPE | nextObj.id() << 12;
570 final GroupKey l2floodgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2floodgk)); 554 final GroupKey l2floodgroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l2floodgk));
571 // collection of group buckets pointing to all the l2 interface groups 555 // collection of group buckets pointing to all the l2 interface groups
572 List<GroupBucket> l2floodBuckets = new ArrayList<>(); 556 List<GroupBucket> l2floodBuckets = new ArrayList<>();
...@@ -610,8 +594,6 @@ public class OFDPA2GroupHandler { ...@@ -610,8 +594,6 @@ public class OFDPA2GroupHandler {
610 } 594 }
611 } 595 }
612 596
613 -
614 -
615 /** 597 /**
616 * As per the OFDPA 2.0 TTP, packets are sent out of ports by using 598 * As per the OFDPA 2.0 TTP, packets are sent out of ports by using
617 * a chain of groups. The hashed Next Objective passed in by the application 599 * a chain of groups. The hashed Next Objective passed in by the application
...@@ -643,7 +625,7 @@ public class OFDPA2GroupHandler { ...@@ -643,7 +625,7 @@ public class OFDPA2GroupHandler {
643 .createSelectGroupBucket(ttb.build()); 625 .createSelectGroupBucket(ttb.build());
644 l3ecmpGroupBuckets.add(sbucket); 626 l3ecmpGroupBuckets.add(sbucket);
645 } 627 }
646 - int l3ecmpGroupId = L3ECMPMASK | nextObj.id() << 12; 628 + int l3ecmpGroupId = L3_ECMP_TYPE | nextObj.id() << 12;
647 GroupKey l3ecmpGroupKey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3ecmpGroupId)); 629 GroupKey l3ecmpGroupKey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3ecmpGroupId));
648 GroupDescription l3ecmpGroupDesc = 630 GroupDescription l3ecmpGroupDesc =
649 new DefaultGroupDescription( 631 new DefaultGroupDescription(
...@@ -752,8 +734,8 @@ public class OFDPA2GroupHandler { ...@@ -752,8 +734,8 @@ public class OFDPA2GroupHandler {
752 onelabelGroupInfo.outerGrpDesc.givenGroupId())); 734 onelabelGroupInfo.outerGrpDesc.givenGroupId()));
753 GroupBucket l3vpnGrpBkt = 735 GroupBucket l3vpnGrpBkt =
754 DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build()); 736 DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
755 - int l3vpngroupId = L3VPNMASK | l3vpnindex.incrementAndGet(); 737 + int l3vpngroupId = MPLS_L3VPN_SUBTYPE | l3vpnindex.incrementAndGet();
756 - int l3vpngk = L3VPNMASK | nextObj.id() << 12 | l3vpnindex.get(); 738 + int l3vpngk = MPLS_L3VPN_SUBTYPE | nextObj.id() << 12 | l3vpnindex.get();
757 GroupKey l3vpngroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3vpngk)); 739 GroupKey l3vpngroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3vpngk));
758 GroupDescription l3vpnGroupDesc = 740 GroupDescription l3vpnGroupDesc =
759 new DefaultGroupDescription( 741 new DefaultGroupDescription(
...@@ -821,7 +803,7 @@ public class OFDPA2GroupHandler { ...@@ -821,7 +803,7 @@ public class OFDPA2GroupHandler {
821 GroupBucket sbucket = DefaultGroupBucket.createSelectGroupBucket(ttb.build()); 803 GroupBucket sbucket = DefaultGroupBucket.createSelectGroupBucket(ttb.build());
822 804
823 // recreate the original L3 ECMP group id and description 805 // recreate the original L3 ECMP group id and description
824 - int l3ecmpGroupId = L3ECMPMASK | nextObjective.id() << 12; 806 + int l3ecmpGroupId = L3_ECMP_TYPE | nextObjective.id() << 12;
825 GroupKey l3ecmpGroupKey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3ecmpGroupId)); 807 GroupKey l3ecmpGroupKey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3ecmpGroupId));
826 808
827 // Although GroupDescriptions are not necessary for adding buckets to 809 // Although GroupDescriptions are not necessary for adding buckets to
...@@ -1049,6 +1031,32 @@ public class OFDPA2GroupHandler { ...@@ -1049,6 +1031,32 @@ public class OFDPA2GroupHandler {
1049 } 1031 }
1050 } 1032 }
1051 1033
1034 + private VlanId readVlanFromMeta(NextObjective nextObj) {
1035 + TrafficSelector metadata = nextObj.meta();
1036 + Criterion criterion = metadata.getCriterion(Criterion.Type.VLAN_VID);
1037 + return (criterion == null)
1038 + ? null : ((VlanIdCriterion) criterion).vlanId();
1039 + }
1040 +
1041 + /**
1042 + * Returns a hash as the L2 Interface Group Key.
1043 + *
1044 + * Keep the lower 6-bit for port since port number usually smaller than 64.
1045 + * Hash other information into remaining 28 bits.
1046 + *
1047 + * @param deviceId Device ID
1048 + * @param vlanId VLAN ID
1049 + * @param portNumber Port number
1050 + * @return L2 interface group key
1051 + */
1052 + private int l2InterfaceGroupKey(
1053 + DeviceId deviceId, VlanId vlanId, long portNumber) {
1054 + int portLowerBits = (int) portNumber & PORT_LOWER_BITS_MASK;
1055 + long portHigherBits = portNumber & PORT_HIGHER_BITS_MASK;
1056 + int hash = Objects.hashCode(deviceId, vlanId, portHigherBits);
1057 + return L2_INTERFACE_TYPE | (TYPE_MASK & hash << 6) | portLowerBits;
1058 + }
1059 +
1052 private class InnerGroupListener implements GroupListener { 1060 private class InnerGroupListener implements GroupListener {
1053 @Override 1061 @Override
1054 public void event(GroupEvent event) { 1062 public void event(GroupEvent event) {
......
...@@ -305,11 +305,16 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -305,11 +305,16 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
305 } 305 }
306 306
307 VlanId assignedVlan = null; 307 VlanId assignedVlan = null;
308 - if (vidCriterion != null && vidCriterion.vlanId() == VlanId.NONE) { 308 + // For VLAN cross-connect packets, use the configured VLAN
309 - // untagged packets are assigned vlans in OF-DPA 309 + if (vidCriterion != null) {
310 + if (vidCriterion.vlanId() != VlanId.NONE) {
311 + assignedVlan = vidCriterion.vlanId();
312 +
313 + // For untagged packets, assign a VLAN ID
314 + } else {
310 if (filt.meta() == null) { 315 if (filt.meta() == null) {
311 - log.error("Missing metadata in filtering objective required " 316 + log.error("Missing metadata in filtering objective required " +
312 - + "for vlan assignment in dev {}", deviceId); 317 + "for vlan assignment in dev {}", deviceId);
313 fail(filt, ObjectiveError.BADPARAMS); 318 fail(filt, ObjectiveError.BADPARAMS);
314 return; 319 return;
315 } 320 }
...@@ -326,8 +331,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -326,8 +331,9 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
326 return; 331 return;
327 } 332 }
328 } 333 }
334 + }
329 335
330 - if (ethCriterion == null) { 336 + if (ethCriterion == null || ethCriterion.mac().equals(MacAddress.NONE)) {
331 log.debug("filtering objective missing dstMac, cannot program TMAC table"); 337 log.debug("filtering objective missing dstMac, cannot program TMAC table");
332 } else { 338 } else {
333 for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, 339 for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion,
...@@ -340,8 +346,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline ...@@ -340,8 +346,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
340 } 346 }
341 347
342 if (ethCriterion == null || vidCriterion == null) { 348 if (ethCriterion == null || vidCriterion == null) {
343 - log.debug("filtering objective missing dstMac or vlan, cannot program" 349 + log.debug("filtering objective missing dstMac or VLAN, "
344 - + "Vlan Table"); 350 + + "cannot program VLAN Table");
345 } else { 351 } else {
346 for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, 352 for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion,
347 assignedVlan, 353 assignedVlan,
......
...@@ -837,7 +837,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -837,7 +837,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
837 if (vlanIdCriterion.vlanId() != VlanId.NONE) { 837 if (vlanIdCriterion.vlanId() != VlanId.NONE) {
838 selector.matchVlanId(vlanIdCriterion.vlanId()); 838 selector.matchVlanId(vlanIdCriterion.vlanId());
839 selector.matchInPort(p.port()); 839 selector.matchInPort(p.port());
840 - treatment.deferred().popVlan();
841 } else { 840 } else {
842 selector.matchInPort(p.port()); 841 selector.matchInPort(p.port());
843 treatment.immediate().pushVlan().setVlanId(assignedVlan); 842 treatment.immediate().pushVlan().setVlanId(assignedVlan);
...@@ -887,11 +886,16 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -887,11 +886,16 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
887 } 886 }
888 887
889 VlanId assignedVlan = null; 888 VlanId assignedVlan = null;
890 - if (vlanIdCriterion != null && vlanIdCriterion.vlanId() == VlanId.NONE) { 889 + if (vlanIdCriterion != null) {
891 - // Assign a VLAN ID to untagged packets 890 + // For VLAN cross-connect packets, use the configured VLAN
891 + if (vlanIdCriterion.vlanId() != VlanId.NONE) {
892 + assignedVlan = vlanIdCriterion.vlanId();
893 +
894 + // For untagged packets, assign a VLAN ID
895 + } else {
892 if (filt.meta() == null) { 896 if (filt.meta() == null) {
893 - log.error("Missing metadata in filtering objective required " 897 + log.error("Missing metadata in filtering objective required " +
894 - + "for vlan assignment in dev {}", deviceId); 898 + "for vlan assignment in dev {}", deviceId);
895 fail(filt, ObjectiveError.BADPARAMS); 899 fail(filt, ObjectiveError.BADPARAMS);
896 return; 900 return;
897 } 901 }
...@@ -908,6 +912,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -908,6 +912,7 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
908 return; 912 return;
909 } 913 }
910 } 914 }
915 + }
911 916
912 if (ethCriterion == null) { 917 if (ethCriterion == null) {
913 log.debug("filtering objective missing dstMac, cannot program TMAC table"); 918 log.debug("filtering objective missing dstMac, cannot program TMAC table");
...@@ -923,9 +928,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour ...@@ -923,9 +928,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
923 } 928 }
924 } 929 }
925 930
926 - if (ethCriterion == null || vlanIdCriterion == null) { 931 + if (vlanIdCriterion == null) {
927 - log.debug("filtering objective missing dstMac or vlan, cannot program" 932 + log.debug("filtering objective missing VLAN ID criterion, "
928 - + "Vlan Table"); 933 + + "cannot program VLAN Table");
929 } else { 934 } else {
930 for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion, 935 for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion,
931 filt, 936 filt,
......
1 +{
2 + "ports" : {
3 + "of:0000000000000001/3" : {
4 + "interfaces" : [
5 + {
6 + "ips" : [ "10.0.1.254/24" ],
7 + "vlan" : "-1"
8 + },
9 + {
10 + "vlan" : "100"
11 + }
12 + ]
13 + },
14 + "of:0000000000000001/4" : {
15 + "interfaces" : [
16 + {
17 + "ips" : [ "10.0.1.254/24" ],
18 + "vlan" : "-1"
19 + }
20 + ]
21 + },
22 + "of:0000000000000001/5" : {
23 + "interfaces" : [
24 + {
25 + "vlan" : "100"
26 + }
27 + ]
28 + },
29 + "of:0000000000000002/3" : {
30 + "interfaces" : [
31 + {
32 + "ips" : [ "10.0.2.254/24" ],
33 + "vlan" : "-1"
34 + }
35 + ]
36 + },
37 + "of:0000000000000002/4" : {
38 + "interfaces" : [
39 + {
40 + "ips" : [ "10.0.2.254/24" ],
41 + "vlan" : "-1"
42 + }
43 + ]
44 + }
45 + },
46 + "devices" : {
47 + "of:0000000000000001" : {
48 + "segmentrouting" : {
49 + "name" : "Leaf-R1",
50 + "nodeSid" : 101,
51 + "routerIp" : "10.0.1.254",
52 + "routerMac" : "00:00:00:00:01:80",
53 + "isEdgeRouter" : true,
54 + "adjacencySids" : []
55 + }
56 + },
57 + "of:0000000000000002" : {
58 + "segmentrouting" : {
59 + "name" : "Leaf-R2",
60 + "nodeSid" : 102,
61 + "routerIp" : "10.0.2.254",
62 + "routerMac" : "00:00:00:00:02:80",
63 + "isEdgeRouter" : true,
64 + "adjacencySids" : []
65 + }
66 + },
67 + "of:0000000000000191" : {
68 + "segmentrouting" : {
69 + "name" : "Spine-R1",
70 + "nodeSid" : 103,
71 + "routerIp" : "192.168.0.11",
72 + "routerMac" : "00:00:01:00:11:80",
73 + "isEdgeRouter" : false,
74 + "adjacencySids" : []
75 + }
76 + },
77 + "of:0000000000000192" : {
78 + "segmentrouting" : {
79 + "name" : "Spine-R2",
80 + "nodeSid" : 104,
81 + "routerIp" : "192.168.0.22",
82 + "routerMac" : "00:00:01:00:22:80",
83 + "isEdgeRouter" : false,
84 + "adjacencySids" : []
85 + }
86 + }
87 + },
88 + "hosts" : {
89 + "00:00:00:00:00:01/4093" : {
90 + "basic": {
91 + "ips": ["10.0.1.1"],
92 + "location": "of:0000000000000001/3"
93 + }
94 + },
95 + "00:00:00:00:00:02/4093" : {
96 + "basic": {
97 + "ips": ["10.0.1.2"],
98 + "location": "of:0000000000000001/4"
99 + }
100 + },
101 + "00:00:00:00:00:03/4093" : {
102 + "basic": {
103 + "ips": ["10.0.2.1"],
104 + "location": "of:0000000000000002/3"
105 + }
106 + },
107 + "00:00:00:00:00:04/4093" : {
108 + "basic": {
109 + "ips": ["10.0.2.2"],
110 + "location": "of:0000000000000002/4"
111 + }
112 + }
113 + }
114 +}
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
4 "interfaces" : [ 4 "interfaces" : [
5 { 5 {
6 "ips" : [ "10.0.1.254/24" ], 6 "ips" : [ "10.0.1.254/24" ],
7 - "mac" : "08:9e:01:82:38:68", 7 + "vlan" : "-1"
8 - "vlan" : "100"
9 } 8 }
10 ] 9 ]
11 }, 10 },
...@@ -13,8 +12,7 @@ ...@@ -13,8 +12,7 @@
13 "interfaces" : [ 12 "interfaces" : [
14 { 13 {
15 "ips" : [ "10.0.1.254/24" ], 14 "ips" : [ "10.0.1.254/24" ],
16 - "mac" : "08:9e:01:82:38:68", 15 + "vlan" : "-1"
17 - "vlan" : "100"
18 } 16 }
19 ] 17 ]
20 }, 18 },
...@@ -22,8 +20,7 @@ ...@@ -22,8 +20,7 @@
22 "interfaces" : [ 20 "interfaces" : [
23 { 21 {
24 "ips" : [ "10.0.2.254/24" ], 22 "ips" : [ "10.0.2.254/24" ],
25 - "mac" : "08:9e:01:82:38:68", 23 + "vlan" : "-1"
26 - "vlan" : "100"
27 } 24 }
28 ] 25 ]
29 }, 26 },
...@@ -31,8 +28,7 @@ ...@@ -31,8 +28,7 @@
31 "interfaces" : [ 28 "interfaces" : [
32 { 29 {
33 "ips" : [ "10.0.2.254/24" ], 30 "ips" : [ "10.0.2.254/24" ],
34 - "mac" : "08:9e:01:82:38:68", 31 + "vlan" : "-1"
35 - "vlan" : "100"
36 } 32 }
37 ] 33 ]
38 } 34 }
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
4 "interfaces" : [ 4 "interfaces" : [
5 { 5 {
6 "ips" : [ "10.0.1.254/24" ], 6 "ips" : [ "10.0.1.254/24" ],
7 - "mac" : "08:9e:01:82:38:68", 7 + "vlan" : "-1"
8 - "vlan" : "100"
9 } 8 }
10 ] 9 ]
11 }, 10 },
...@@ -13,8 +12,7 @@ ...@@ -13,8 +12,7 @@
13 "interfaces" : [ 12 "interfaces" : [
14 { 13 {
15 "ips" : [ "10.0.1.254/24" ], 14 "ips" : [ "10.0.1.254/24" ],
16 - "mac" : "08:9e:01:82:38:68", 15 + "vlan" : "-1"
17 - "vlan" : "100"
18 } 16 }
19 ] 17 ]
20 }, 18 },
...@@ -22,8 +20,7 @@ ...@@ -22,8 +20,7 @@
22 "interfaces" : [ 20 "interfaces" : [
23 { 21 {
24 "ips" : [ "10.0.2.254/24" ], 22 "ips" : [ "10.0.2.254/24" ],
25 - "mac" : "08:9e:01:82:38:68", 23 + "vlan" : "-1"
26 - "vlan" : "100"
27 } 24 }
28 ] 25 ]
29 }, 26 },
...@@ -31,8 +28,7 @@ ...@@ -31,8 +28,7 @@
31 "interfaces" : [ 28 "interfaces" : [
32 { 29 {
33 "ips" : [ "10.0.2.254/24" ], 30 "ips" : [ "10.0.2.254/24" ],
34 - "mac" : "08:9e:01:82:38:68", 31 + "vlan" : "-1"
35 - "vlan" : "100"
36 } 32 }
37 ] 33 ]
38 }, 34 },
...@@ -40,8 +36,7 @@ ...@@ -40,8 +36,7 @@
40 "interfaces" : [ 36 "interfaces" : [
41 { 37 {
42 "ips" : [ "10.0.3.254/24" ], 38 "ips" : [ "10.0.3.254/24" ],
43 - "mac" : "08:9e:01:82:38:68", 39 + "vlan" : "-1"
44 - "vlan" : "100"
45 } 40 }
46 ] 41 ]
47 }, 42 },
...@@ -49,8 +44,7 @@ ...@@ -49,8 +44,7 @@
49 "interfaces" : [ 44 "interfaces" : [
50 { 45 {
51 "ips" : [ "10.0.3.254/24" ], 46 "ips" : [ "10.0.3.254/24" ],
52 - "mac" : "08:9e:01:82:38:68", 47 + "vlan" : "-1"
53 - "vlan" : "100"
54 } 48 }
55 ] 49 ]
56 }, 50 },
...@@ -58,8 +52,7 @@ ...@@ -58,8 +52,7 @@
58 "interfaces" : [ 52 "interfaces" : [
59 { 53 {
60 "ips" : [ "10.0.4.254/24" ], 54 "ips" : [ "10.0.4.254/24" ],
61 - "mac" : "08:9e:01:82:38:68", 55 + "vlan" : "-1"
62 - "vlan" : "100"
63 } 56 }
64 ] 57 ]
65 }, 58 },
...@@ -67,8 +60,7 @@ ...@@ -67,8 +60,7 @@
67 "interfaces" : [ 60 "interfaces" : [
68 { 61 {
69 "ips" : [ "10.0.4.254/24" ], 62 "ips" : [ "10.0.4.254/24" ],
70 - "mac" : "08:9e:01:82:38:68", 63 + "vlan" : "-1"
71 - "vlan" : "100"
72 } 64 }
73 ] 65 ]
74 } 66 }
......