- Fix a bug of returning null in getDpidIfNeightborOf() when there is no neighbor.
- Add a feature to pick only one port when ECMP in transit router is NOT supported, when creating a tunnel (including tunnel stitching)

Change-Id: I20711c1504fca4adfcf12997558372655339a11d
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 90f7a8f..06ddb37 100644
--- a/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
+++ b/src/main/java/net/onrc/onos/apps/segmentrouting/SegmentRoutingManager.java
@@ -1056,7 +1056,6 @@
     }
 
 
-
     // ************************************
     // Policy routing classes and functions
     // ************************************
@@ -1248,6 +1247,7 @@
             log.debug("Failed to get a tunnel rule.");
             return false;
         }
+
         for (TunnelRouteInfo route: stitchingRule) {
             NeighborSet ns = new NeighborSet();
             for (Dpid dpid: route.getFwdSwDpid())
@@ -1686,7 +1686,7 @@
             if (fwdSwDpids == null || fwdSwDpids.isEmpty()) {
                 log.warn("There is no route from node {} to node {}",
                         srcSw.getDpid(), nodeId);
-                return null;
+                return fwdSws;
             }
 
             for (Dpid dpid: fwdSwDpids) {
@@ -1701,7 +1701,9 @@
     }
 
     /**
-     * Get port numbers of the neighbor set
+     * Get port numbers of the neighbor set.
+     * If ECMP in transit router is not supported, then only one port should be returned
+     * regardless of number of nodes in neighbor set.
      *
      * @param srcSwDpid source switch
      * @param ns Neighbor set of the switch
@@ -1714,8 +1716,21 @@
         if (srcSwitch == null)
             return null;
         for (Dpid neighborDpid: ns.getDpids()) {
-            Link link = srcSwitch.getLinkToNeighbor(neighborDpid);
-            portList.add(link.getSrcPort().getNumber());
+            if (!supportTransitECMP && ns.getDpids().size() == 1) {
+                Switch dstSwitch = mutableTopology.getSwitch(neighborDpid);
+                if (isTransitRouter(srcSwitch) && isTransitRouter(dstSwitch)) {
+                    Link link = srcSwitch.getLinkToNeighbor(neighborDpid);
+                    portList.add(link.getSrcPort().getNumber());
+                    break;
+                }
+            }
+            else {
+                for (Link link: srcSwitch.getOutgoingLinks()) {
+                    if (link.getDstSwitch().getDpid().equals(neighborDpid)) {
+                        portList.add(link.getSrcPort().getNumber());
+                    }
+                }
+            }
         }
 
         return portList;
@@ -1921,7 +1936,9 @@
     }
 
     /**
-     * Get the forwarding Switch DPIDs to send packets to a node
+     * Get the forwarding Switch DPIDs to send packets to a node.
+     * If ECMP in transit routers is not supported, only one switch needs to be
+     * selected as the neighbor set to forward packets to.
      *
      * @param srcSw source switch
      * @param nodeId destination node Id
@@ -1956,6 +1973,11 @@
                         else {
                             Dpid firstVia = via.get(via.size()-1);
                             fwdSws.add(firstVia);
+                            if (!supportTransitECMP &&
+                                isTransitRouter(targetSw) &&
+                                isTransitRouter(mutableTopology.getSwitch(firstVia))) {
+                                return fwdSws;
+                            }
                         }
                     }
                 }