Modify the stitching rule to support adjacency SID
- support the case when sub tunnel starts with adjacency SID
- support the case when sub tunnel ends with adjacency SID
(Stitching occurs in the adjacecy SID - actually the desintation node)
- Does NOT support when the case sub tunnel ends with adjacecy SID with multiple ports
(In this case, we need to fork logic to create multiple rules)
Change-Id: I2e16af62ec8aa69574e50d121d15bfd8e97654c5
diff --git a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
index f352e43..54c6d72 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -1332,6 +1332,14 @@
return true;
}
+ /**
+ * Create groups for the tunnel
+ *
+ * @param tunnelId tunnel ID
+ * @param routeInfo label stacks for the tunnel
+ * @param ns NeighborSet to forward packets
+ * @return group ID, return -1 if it fails
+ */
private int createGroupsForTunnel(String tunnelId, TunnelRouteInfo routeInfo,
NeighborSet ns) {
@@ -1435,7 +1443,7 @@
*/
private List<TunnelRouteInfo> getStitchingRule(List<String> route) {
- if (route.isEmpty() || route.size() < 2)
+ if (route.isEmpty() || route.size() < 3)
return null;
List<TunnelRouteInfo> rules = new ArrayList<TunnelRouteInfo>();
@@ -1447,41 +1455,9 @@
}
String srcDpid = srcSw.getDpid().toString();
- /*
- if (route.size() <= MAX_NUM_LABELS+1) {
- boolean match =false;
- TunnelRouteInfo routeInfo = new TunnelRouteInfo();
- routeInfo.setSrcDpid(srcSw.getDpid().toString());
- String nodeId = route.get(1);
- List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw, nodeId);
- if (fwdSwDpids == null){
- return null;
- }
- for (Dpid dpid: fwdSwDpids) {
- if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
- List<Dpid> fwdSws = new ArrayList<Dpid>();
- fwdSws.add(dpid);
- routeInfo.setFwdSwDpid(fwdSws);
- match = true;
- break;
- }
- }
- route.remove(0); // remove source router from the list
- if (match) {
- route.remove(0);
- }
- else {
- routeInfo.setFwdSwDpid(fwdSwDpids);
- }
- routeInfo.setRoute(route);
- rules.add(routeInfo);
- return rules;
- }
- */
-
int i = 0;
TunnelRouteInfo routeInfo = new TunnelRouteInfo();
- boolean checkNeighbor = true;
+ boolean checkNeighbor = false;
String prevAdjacencySid = null;
String prevNodeId = null;
@@ -1489,46 +1465,34 @@
// The first node ID is always the source router.
// We assume that the first ID cannot be an Adjacency SID.
if (i == 0) {
- routeInfo.setSrcDpid(srcDpid);
srcSw = getSwitchFromNodeId(nodeId);
+ if (srcDpid == null)
+ srcDpid = srcSw.getDpid().toString();
+ routeInfo.setSrcDpid(srcDpid);
+ checkNeighbor = true;
i++;
}
+ // if this is the first node ID to put the label stack..
else if (i == 1) {
- if (isAdjacencySid(nodeId)) {
- routeInfo.addRoute(nodeId);
- i++;
- prevAdjacencySid = nodeId;
- }
- else if (checkNeighbor) {
- // Check if next node is the neighbor SW of the source SW
- List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw,
- nodeId);
- if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
- log.debug("There is no route from node {} to node {}",
- srcSw.getDpid(), nodeId);
- return null;
- }
- // If first Id is one of the neighbors, do not include it to route, but set it as a fwd SW.
- boolean match = false;
- for (Dpid dpid: fwdSwDpids) {
- if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
- List<Dpid> fwdSws = new ArrayList<Dpid>();
- fwdSws.add(dpid);
- routeInfo.setFwdSwDpid(fwdSws);
- match = true;
- break;
+ if (checkNeighbor) {
+ List<Dpid> fwdSws = getDpidIfNeighborOf(nodeId, srcSw);
+ // if nodeId is NOT the neighbor of srcSw..
+ if (fwdSws.isEmpty()) {
+ fwdSws = getForwardingSwitchForNodeId(srcSw,nodeId);
+ if (fwdSws == null || fwdSws.isEmpty()) {
+ log.warn("There is no route from node {} to node {}",
+ srcSw.getDpid(), nodeId);
+ return null;
}
- }
- if (!match) {
routeInfo.addRoute(nodeId);
- routeInfo.setFwdSwDpid(fwdSwDpids);
i++;
}
+ routeInfo.setFwdSwDpid(fwdSws);
// we check only the next node ID of the source router
checkNeighbor = false;
-
- // if we don't need to check neighbor
- }else {
+ }
+ // if neighbor check is already done, then just add it
+ else {
routeInfo.addRoute(nodeId);
i++;
}
@@ -1548,12 +1512,30 @@
i++;
}
+ // If the adjacency ID is added the label stack,
+ // then we need to check if the next node is the destination of the adjacency SID
+ if (isAdjacencySid(nodeId))
+ prevAdjacencySid = nodeId;
+
// If the number of labels reaches the limit, start over the procedure
if (i == MAX_NUM_LABELS+1) {
+
rules.add(routeInfo);
routeInfo = new TunnelRouteInfo();
- srcSw = getSwitchFromNodeId(nodeId);
- srcDpid = getSwitchFromNodeId(nodeId).getDpid().toString();
+
+ if (!isAdjacencySid(nodeId)) {
+ srcSw = getSwitchFromNodeId(nodeId);
+ }
+ // If the previous sub tunnel finishes with adjacency SID, then we need to
+ // start the procedure from the adjacency destination ID
+ // TODO: if we more than one port are assigned to the adjacency node, then we need to
+ // create multiple rules
+ else {
+ List<Switch> destNodeList = getAdjacencyDestinationNode(prevNodeId, nodeId);
+ if (destNodeList != null && !destNodeList.isEmpty())
+ srcSw = destNodeList.get(0);
+ }
+ srcDpid = srcSw.getDpid().toString();
routeInfo.setSrcDpid(srcDpid);
i = 1;
checkNeighbor = true;
@@ -1563,8 +1545,10 @@
prevNodeId = nodeId;
}
+
if (i < MAX_NUM_LABELS+1) {
rules.add(routeInfo);
+ // NOTE: empty label stack can happen
}
return rules;
@@ -1679,6 +1663,85 @@
// Utility functions
// ************************************
+ /**
+ * Get the destination Nodes of the adjacency Sid
+ *
+ * @param nodeId node ID of the adjacency Sid
+ * @param adjacencySid adjacency Sid
+ * @return List of Switch, empty list if not found
+ */
+ private List<Switch> getAdjacencyDestinationNode(String nodeId, String adjacencySid) {
+ List<Switch> dstSwList = new ArrayList<Switch>();
+
+ HashMap<Integer, List<Integer>> adjacencySidInfo =
+ adjacencySidTable.get(Integer.valueOf(nodeId));
+ List<Integer> ports = adjacencySidInfo.get(Integer.valueOf(adjacencySid));
+ Switch srcSw = getSwitchFromNodeId(nodeId);
+ for (Integer port: ports) {
+ for (Link link: srcSw.getOutgoingLinks()) {
+ if (link.getSrcPort().getPortNumber().value() == port) {
+ dstSwList.add(link.getDstSwitch());
+ }
+ }
+ }
+
+ return dstSwList;
+
+ }
+
+ /**
+ * Get the DPID of the router with node ID IF the node ID is the neighbor of the
+ * Switch srcSW.
+ * If the nodeId is the adjacency Sid, then it returns the destination router DPIDs.
+ *
+ * @param nodeId Node ID to check
+ * @param srcSw target Switch
+ * @return List of DPID of nodeId, empty list if the nodeId is not the neighbor of srcSW
+ */
+ private List<Dpid> getDpidIfNeighborOf(String nodeId, Switch srcSw) {
+ List<Dpid> fwdSws = new ArrayList<Dpid>();
+ // if the nodeID is the adjacency ID, then we need to regard it as the
+ // neighbor node ID and need to return the destination router DPID(s)
+ if (isAdjacencySid(nodeId)) {
+ String srcNodeId = this.getMplsLabel(srcSw.getDpid().toString());
+ HashMap<Integer, List<Integer>> adjacencySidInfo =
+ adjacencySidTable.get(Integer.valueOf(srcNodeId));
+ List<Integer> ports = adjacencySidInfo.get(Integer.valueOf(nodeId));
+
+ for (Integer port: ports) {
+ for (Link link: srcSw.getOutgoingLinks()) {
+ if (link.getSrcPort().getPortNumber().value() == port) {
+ fwdSws.add(link.getDstSwitch().getDpid());
+ }
+ }
+ }
+ }
+ else {
+ List<Dpid> fwdSwDpids = getForwardingSwitchForNodeId(srcSw,nodeId);
+ if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
+ log.warn("There is no route from node {} to node {}",
+ srcSw.getDpid(), nodeId);
+ return null;
+ }
+
+ for (Dpid dpid: fwdSwDpids) {
+ if (getMplsLabel(dpid.toString()).toString().equals(nodeId)) {
+ fwdSws.add(dpid);
+ break;
+ }
+ }
+ }
+
+ return fwdSws;
+ }
+
+ /**
+ * Get port numbers of the neighbor set
+ *
+ * @param srcSwDpid source switch
+ * @param ns Neighbor set of the switch
+ * @return List of PortNumber, null if not found
+ */
private List<PortNumber> getPortsFromNeighborSet(String srcSwDpid, NeighborSet ns) {
List<PortNumber> portList = new ArrayList<PortNumber>();