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/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
index dbac596..3d2d337 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceConfiguration.java
@@ -19,6 +19,7 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
import org.onosproject.incubator.net.config.basics.ConfigException;
import org.onosproject.incubator.net.config.basics.InterfaceConfig;
import org.onosproject.incubator.net.intf.Interface;
@@ -33,6 +34,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -48,8 +50,8 @@
private static final Logger log = LoggerFactory
.getLogger(DeviceConfiguration.class);
private final List<Integer> allSegmentIds = new ArrayList<>();
- private final ConcurrentHashMap<DeviceId, SegmentRouterInfo> deviceConfigMap
- = new ConcurrentHashMap<>();
+ private final Map<DeviceId, SegmentRouterInfo> deviceConfigMap = new ConcurrentHashMap<>();
+ private final Map<VlanId, List<ConnectPoint>> xConnects = new ConcurrentHashMap<>();
private class SegmentRouterInfo {
int nodeSid;
@@ -62,14 +64,14 @@
Map<Integer, Set<Integer>> adjacencySids;
public SegmentRouterInfo() {
- this.gatewayIps = new HashMap<>();
- this.subnets = new HashMap<>();
+ gatewayIps = new HashMap<>();
+ subnets = new HashMap<>();
}
}
/**
- * Constructor. Reads all the configuration for all devices of type
- * Segment Router and organizes into various maps for easier access.
+ * Constructs device configuration for all Segment Router devices,
+ * organizing the data into various maps for easier access.
*
* @param cfgService config service
*/
@@ -88,8 +90,8 @@
info.isEdge = config.isEdgeRouter();
info.adjacencySids = config.adjacencySids();
- this.deviceConfigMap.put(info.deviceId, info);
- this.allSegmentIds.add(info.nodeSid);
+ deviceConfigMap.put(info.deviceId, info);
+ allSegmentIds.add(info.nodeSid);
});
// Read gatewayIps and subnets from port subject.
@@ -106,17 +108,42 @@
return;
}
networkInterfaces.forEach(networkInterface -> {
- DeviceId dpid = networkInterface.connectPoint().deviceId();
- PortNumber port = networkInterface.connectPoint().port();
- SegmentRouterInfo info = this.deviceConfigMap.get(dpid);
+ VlanId vlanId = networkInterface.vlan();
+ ConnectPoint connectPoint = networkInterface.connectPoint();
+ DeviceId dpid = connectPoint.deviceId();
+ PortNumber port = connectPoint.port();
+ SegmentRouterInfo info = deviceConfigMap.get(dpid);
// skip if there is no corresponding device for this ConenctPoint
if (info != null) {
+ // Extract subnet information
Set<InterfaceIpAddress> interfaceAddresses = networkInterface.ipAddresses();
interfaceAddresses.forEach(interfaceAddress -> {
info.gatewayIps.put(port, interfaceAddress.ipAddress().getIp4Address());
info.subnets.put(port, interfaceAddress.subnetAddress().getIp4Prefix());
});
+
+ // Extract VLAN cross-connect information
+ // Do not setup cross-connect if VLAN is NONE
+ if (vlanId.equals(VlanId.NONE)) {
+ return;
+ }
+ List<ConnectPoint> connectPoints = xConnects.get(vlanId);
+ if (connectPoints != null) {
+ if (connectPoints.size() != 1) {
+ log.warn("Cross-connect should only have two endpoints. Aborting.");
+ return;
+ }
+ if (!connectPoints.get(0).deviceId().equals(connectPoint.deviceId())) {
+ log.warn("Cross-connect endpoints must be on the same switch. Aborting.");
+ return;
+ }
+ connectPoints.add(connectPoint);
+ } else {
+ connectPoints = new LinkedList<>();
+ connectPoints.add(connectPoint);
+ xConnects.put(vlanId, connectPoints);
+ }
}
});
@@ -235,6 +262,11 @@
return subnetPortMap;
}
+ @Override
+ public Map<VlanId, List<ConnectPoint>> getXConnects() {
+ return xConnects;
+ }
+
/**
* Returns the device identifier or data plane identifier (dpid)
* of a segment router given its segment id.
diff --git a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
index a39c956..9d4d884 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/DeviceProperties.java
@@ -21,6 +21,8 @@
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.PortNumber;
@@ -93,4 +95,11 @@
* @return a map that contains all subnet-to-ports mapping of given device
*/
Map<Ip4Prefix, List<PortNumber>> getSubnetPortsMap(DeviceId deviceId);
+
+ /**
+ * Returns the VLAN cross-connect configuration.
+ *
+ * @return A map of that maps VLAN ID to a list of cross-connect endpoints
+ */
+ Map<VlanId, List<ConnectPoint>> getXConnects();
}
diff --git a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
index f788925..64486c6 100644
--- a/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
+++ b/src/main/java/org/onosproject/segmentrouting/config/SegmentRoutingConfig.java
@@ -35,24 +35,24 @@
* Configuration object for Segment Routing Application.
*/
public class SegmentRoutingConfig extends Config<DeviceId> {
- public static final String NAME = "name";
- public static final String IP = "routerIp";
- public static final String MAC = "routerMac";
- public static final String SID = "nodeSid";
- public static final String EDGE = "isEdgeRouter";
- public static final String ADJSIDS = "adjacencySids";
- public static final String ADJSID = "adjSid";
- public static final String PORTS = "ports";
+ private static final String NAME = "name";
+ private static final String IP = "routerIp";
+ private static final String MAC = "routerMac";
+ private static final String SID = "nodeSid";
+ private static final String EDGE = "isEdgeRouter";
+ private static final String ADJSIDS = "adjacencySids";
+ private static final String ADJSID = "adjSid";
+ private static final String PORTS = "ports";
@Override
public boolean isValid() {
return hasOnlyFields(NAME, IP, MAC, SID, EDGE, ADJSIDS, ADJSID, PORTS) &&
- this.name() != null &&
- this.routerIp() != null &&
- this.routerMac() != null &&
- this.nodeSid() != -1 &&
- this.isEdgeRouter() != null &&
- this.adjacencySids() != null;
+ name() != null &&
+ routerIp() != null &&
+ routerMac() != null &&
+ nodeSid() != -1 &&
+ isEdgeRouter() != null &&
+ adjacencySids() != null;
}
/**