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
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 0f20451..592c0b1 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -69,7 +69,6 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.host.HostService;
-import org.onosproject.net.intent.IntentService;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.link.LinkListener;
import org.onosproject.net.link.LinkService;
@@ -77,8 +76,8 @@
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.topology.TopologyService;
import org.onosproject.segmentrouting.grouphandler.SubnetNextObjectiveStoreKey;
+import org.onosproject.segmentrouting.grouphandler.XConnectNextObjectiveStoreKey;
import org.onosproject.store.service.EventuallyConsistentMap;
import org.onosproject.store.service.EventuallyConsistentMapBuilder;
import org.onosproject.store.service.StorageService;
@@ -102,6 +101,9 @@
@Service
@Component(immediate = true)
+/**
+ * Segment routing manager.
+ */
public class SegmentRoutingManager implements SegmentRoutingService {
private static Logger log = LoggerFactory
@@ -111,15 +113,9 @@
protected CoreService coreService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected TopologyService topologyService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
- protected IntentService intentService;
-
- @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -157,20 +153,31 @@
@SuppressWarnings("rawtypes")
private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<Event>();
private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
- new ConcurrentHashMap<DeviceId, DefaultGroupHandler>();
- // Per device next objective ID store with (device id + neighbor set) as key
- private EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
+ new ConcurrentHashMap<>();
+ /**
+ * Per device next objective ID store with (device id + neighbor set) as key.
+ */
+ public EventuallyConsistentMap<NeighborSetNextObjectiveStoreKey, Integer>
nsNextObjStore = null;
- // Per device next objective ID store with (device id + subnet) as key
- private EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
+ /**
+ * Per device next objective ID store with (device id + subnet) as key.
+ */
+ public EventuallyConsistentMap<SubnetNextObjectiveStoreKey, Integer>
subnetNextObjStore = null;
- // Per device next objective ID store with (device id + port) as key
- private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
+ /**
+ * Per device next objective ID store with (device id + port) as key.
+ */
+ public EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
+ /**
+ * Per cross-connect objective ID store with VLAN ID as key.
+ */
+ public EventuallyConsistentMap<XConnectNextObjectiveStoreKey, Integer>
+ xConnectNextObjStore = null;
// Per device, per-subnet assigned-vlans store, with (device id + subnet
// IPv4 prefix) as key
private EventuallyConsistentMap<SubnetAssignedVidStoreKey, VlanId>
- subnetVidStore = null;
+ subnetVidStore = null;
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
@@ -204,7 +211,13 @@
private KryoNamespace.Builder kryoBuilder = null;
+ /**
+ * The starting value of per-subnet VLAN ID assignment.
+ */
private static final short ASSIGNED_VLAN_START = 4093;
+ /**
+ * The default VLAN ID assigned to the interfaces without subnet config.
+ */
public static final short ASSIGNED_VLAN_NO_SUBNET = 4094;
@Activate
@@ -262,6 +275,15 @@
.withTimestampProvider((k, v) -> new WallClockTimestamp())
.build();
+ log.debug("Creating EC map xconnectnextobjectivestore");
+ EventuallyConsistentMapBuilder<XConnectNextObjectiveStoreKey, Integer>
+ xConnectNextObjStoreBuilder = storageService.eventuallyConsistentMapBuilder();
+ xConnectNextObjStore = xConnectNextObjStoreBuilder
+ .withName("xconnectnextobjectivestore")
+ .withSerializer(kryoBuilder)
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+
EventuallyConsistentMapBuilder<String, Tunnel> tunnelMapBuilder =
storageService.eventuallyConsistentMapBuilder();
tunnelStore = tunnelMapBuilder
@@ -394,9 +416,6 @@
* Vlan id 4094 expected to be used for all ports that are not assigned subnets.
* Vlan id 4095 is reserved and unused. Only a single vlan id is assigned
* per subnet.
- * XXX This method should avoid any vlans configured on the ports, but
- * currently the app works only on untagged packets and as a result
- * ignores any vlan configuration.
*
* @param deviceId switch dpid
* @param subnet IPv4 prefix for which assigned vlan is desired
@@ -404,6 +423,7 @@
* null if no vlan assignment was found and this instance is not
* the master for the device.
*/
+ // TODO: We should avoid assigning VLAN IDs that are used by VLAN cross-connection.
public VlanId getSubnetAssignedVlanId(DeviceId deviceId, Ip4Prefix subnet) {
VlanId assignedVid = subnetVidStore.get(new SubnetAssignedVidStoreKey(
deviceId, subnet));
@@ -508,7 +528,26 @@
if (ghdlr != null) {
return ghdlr.getPortNextObjectiveId(portNum, treatment, meta);
} else {
- log.warn("getPortNextObjectiveId query - groupHandler for device {}"
+ log.warn("getPortNextObjectiveId query - groupHandler for device {}"
+ + " not found", deviceId);
+ return -1;
+ }
+ }
+
+ /**
+ * Returns the next objective ID of type broadcast associated with the VLAN
+ * cross-connection.
+ *
+ * @param deviceId Device ID for the cross-connection
+ * @param vlanId VLAN ID for the cross-connection
+ * @return next objective ID or -1 if it was not found
+ */
+ public int getXConnectNextObjectiveId(DeviceId deviceId, VlanId vlanId) {
+ DefaultGroupHandler ghdlr = groupHandlerMap.get(deviceId);
+ if (ghdlr != null) {
+ return ghdlr.getXConnectNextObjectiveId(vlanId);
+ } else {
+ log.warn("getPortNextObjectiveId query - groupHandler for device {}"
+ " not found", deviceId);
return -1;
}
@@ -707,9 +746,6 @@
deviceConfiguration,
linkService,
flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore,
- portNextObjStore,
this);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting processDeviceAdded.");
@@ -727,6 +763,8 @@
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
routingRulePopulator.populateSubnetBroadcastRule(device.id());
+ groupHandler.createGroupsForXConnect(device.id());
+ routingRulePopulator.populateXConnectBroadcastRule(device.id());
}
}
@@ -742,10 +780,18 @@
private class InternalConfigListener implements NetworkConfigListener {
SegmentRoutingManager segmentRoutingManager;
+ /**
+ * Constructs the internal network config listener.
+ *
+ * @param srMgr segment routing manager
+ */
public InternalConfigListener(SegmentRoutingManager srMgr) {
this.segmentRoutingManager = srMgr;
}
+ /**
+ * Reads network config and initializes related data structure accordingly.
+ */
public void configureNetwork() {
deviceConfiguration = new DeviceConfiguration(segmentRoutingManager.cfgService);
@@ -777,9 +823,6 @@
deviceConfiguration,
linkService,
flowObjectiveService,
- nsNextObjStore,
- subnetNextObjStore,
- portNextObjStore,
segmentRoutingManager);
} catch (DeviceConfigNotFoundException e) {
log.warn(e.getMessage() + " Aborting configureNetwork.");
@@ -798,6 +841,8 @@
DefaultGroupHandler groupHandler = groupHandlerMap.get(device.id());
groupHandler.createGroupsFromSubnetConfig();
routingRulePopulator.populateSubnetBroadcastRule(device.id());
+ groupHandler.createGroupsForXConnect(device.id());
+ routingRulePopulator.populateXConnectBroadcastRule(device.id());
}
}