Handling multiple layers of spines.

Also in this commit:
     - Triggering swap group creation and accounting for it in DestinationSet
     - Fixes in ofdpa2 and ofdpa3 pipeline to allow SR Continue operation
     - Renaming mplsSet in DestinationSet to notBos
     - Removing unused RandomDestinationSet
     - Bug fix in ofdpa driver for swap group chain creation
     - Bug fix in ofdpa driver for verify group operation
     - Better internal bookeeping of device ports and associated neighbors

Change-Id: I2b8f1c4c0b305ef847d57ca7a5320943e06d190d
diff --git a/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java b/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
index 7f839cf..0626bc8 100644
--- a/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
+++ b/app/src/main/java/org/onosproject/segmentrouting/grouphandler/DestinationSet.java
@@ -28,15 +28,17 @@
 import static org.slf4j.LoggerFactory.getLogger;
 
 /**
- * Representation of a set of destination switch dpids along with their edge-node
- * labels. Meant to be used as a lookup-key in a hash-map to retrieve an ECMP-group
- * that hashes packets towards a specific destination switch,
- * or paired-destination switches.
+ * Representation of a set of destination switch dpids along with their
+ * edge-node labels. Meant to be used as a lookup-key in a hash-map to retrieve
+ * an ECMP-group that hashes packets towards a specific destination switch, or
+ * paired-destination switches. May also be used to represent cases where the
+ * forwarding does not use ECMP groups (ie SIMPLE next objectives)
  */
 public class DestinationSet {
     public static final int NO_EDGE_LABEL = -1;
     private static final int NOT_ASSIGNED = 0;
-    private boolean mplsSet;
+    private boolean notBos; // XXX replace with enum
+    private boolean swap; // XXX replace with enum
     private final DeviceId dstSw1;
     private final int edgeLabel1;
     private final DeviceId dstSw2;
@@ -48,12 +50,14 @@
     /**
      * Constructor for a single destination with no Edge label.
      *
-     * @param isMplsSet indicates if it is a mpls destination set
+     * @param isNotBos indicates if it is meant for a non bottom-of-stack label
+     * @param isSwap indicates if it is meant for a swap action
      * @param dstSw the destination switch
      */
-    public DestinationSet(boolean isMplsSet, DeviceId dstSw) {
+    public DestinationSet(boolean isNotBos, boolean isSwap, DeviceId dstSw) {
         this.edgeLabel1 = NO_EDGE_LABEL;
-        this.mplsSet = isMplsSet;
+        this.notBos = isNotBos;
+        this.swap = isSwap;
         this.dstSw1 = dstSw;
         this.edgeLabel2 = NOT_ASSIGNED;
         this.dstSw2 = null;
@@ -62,13 +66,15 @@
     /**
      * Constructor for a single destination with Edge label.
      *
-     * @param isMplsSet indicates if it is a mpls destination set
+     * @param isNotBos indicates if it is meant for a non bottom-of-stack label
+     * @param isSwap indicates if it is meant for a swap action
      * @param edgeLabel label to be pushed as part of group operation
      * @param dstSw the destination switch
      */
-    public DestinationSet(boolean isMplsSet,
+    public DestinationSet(boolean isNotBos, boolean isSwap,
                        int edgeLabel, DeviceId dstSw) {
-        this.mplsSet = isMplsSet;
+        this.notBos = isNotBos;
+        this.swap = isSwap;
         this.edgeLabel1 = edgeLabel;
         this.dstSw1 = dstSw;
         this.edgeLabel2 = NOT_ASSIGNED;
@@ -76,19 +82,23 @@
     }
 
     /**
-     * Constructor for paired destination switches and their associated
-     * edge labels.
+     * Constructor for paired destination switches and their associated edge
+     * labels.
      *
-     * @param isMplsSet indicates if it is a mpls destination set
-     * @param edgeLabel1 label to be pushed as part of group operation for dstSw1
+     * @param isNotBos indicates if it is meant for a non bottom-of-stack label
+     * @param isSwap indicates if it is meant for a swap action
+     * @param edgeLabel1 label to be pushed as part of group operation for
+     *            dstSw1
      * @param dstSw1 one of the paired destination switches
-     * @param edgeLabel2 label to be pushed as part of group operation for dstSw2
+     * @param edgeLabel2 label to be pushed as part of group operation for
+     *            dstSw2
      * @param dstSw2 the other paired destination switch
      */
-    public DestinationSet(boolean isMplsSet,
+    public DestinationSet(boolean isNotBos, boolean isSwap,
                           int edgeLabel1, DeviceId dstSw1,
                           int edgeLabel2, DeviceId dstSw2) {
-        this.mplsSet = isMplsSet;
+        this.notBos = isNotBos;
+        this.swap = isSwap;
         if (dstSw1.toString().compareTo(dstSw2.toString()) <= 0) {
             this.edgeLabel1 = edgeLabel1;
             this.dstSw1 = dstSw1;
@@ -108,52 +118,13 @@
     public DestinationSet() {
         this.edgeLabel1 = NOT_ASSIGNED;
         this.edgeLabel2 = NOT_ASSIGNED;
-        this.mplsSet = true;
+        this.notBos = true;
+        this.swap = true;
         this.dstSw1 = DeviceId.NONE;
         this.dstSw2 = DeviceId.NONE;
     }
 
     /**
-     * Factory method for DestinationSet hierarchy.
-     *
-     * @param random the expected behavior.
-     * @param isMplsSet indicates if it is a mpls destination set
-     * @param dstSw the destination switch
-     * @return the destination set object.
-     */
-    public static DestinationSet destinationSet(boolean random,
-                                          boolean isMplsSet, DeviceId dstSw) {
-        return random ? new RandomDestinationSet(dstSw)
-                      : new DestinationSet(isMplsSet, dstSw);
-    }
-
-    /**
-     * Factory method for DestinationSet hierarchy.
-     *
-     * @param random the expected behavior.
-     * @param isMplsSet indicates if it is a mpls destination set
-     * @param edgeLabel label to be pushed as part of group operation
-     * @param dstSw the destination switch
-     * @return the destination set object
-     */
-    public static DestinationSet destinationSet(boolean random,
-                                          boolean isMplsSet, int edgeLabel,
-                                          DeviceId dstSw) {
-        return random ? new RandomDestinationSet(edgeLabel, dstSw)
-                      : new DestinationSet(isMplsSet, edgeLabel, dstSw);
-    }
-
-    /**
-     * Factory method for DestinationSet hierarchy.
-     *
-     * @param random the expected behavior.
-     * @return the destination set object
-     */
-    public static DestinationSet destinationSet(boolean random) {
-        return random ? new RandomDestinationSet() : new DestinationSet();
-    }
-
-    /**
      * Gets the label associated with given destination switch.
      *
      * @param dstSw the destination switch
@@ -183,12 +154,21 @@
     }
 
     /**
-     * Gets the value of mplsSet.
+     * Gets the value of notBos.
      *
-     * @return the value of mplsSet
+     * @return the value of notBos
      */
-    public boolean mplsSet() {
-        return mplsSet;
+    public boolean notBos() {
+        return notBos;
+    }
+
+    /**
+     * Gets the value of swap.
+     *
+     * @return the value of swap
+     */
+    public boolean swap() {
+        return swap;
     }
 
     // The list of destination ids and label are used for comparison.
@@ -202,7 +182,8 @@
         }
         DestinationSet that = (DestinationSet) o;
         boolean equal = (this.edgeLabel1 == that.edgeLabel1 &&
-                            this.mplsSet == that.mplsSet &&
+                            this.notBos == that.notBos &&
+                            this.swap == that.swap &&
                             this.dstSw1.equals(that.dstSw1));
         if (this.dstSw2 != null && that.dstSw2 == null ||
                 this.dstSw2 == null && that.dstSw2 != null) {
@@ -219,15 +200,26 @@
     @Override
     public int hashCode() {
         if (dstSw2 == null) {
-            return Objects.hash(mplsSet, edgeLabel1, dstSw1);
+            return Objects.hash(notBos, swap, edgeLabel1, dstSw1);
         }
-        return Objects.hash(mplsSet, edgeLabel1, dstSw1, edgeLabel2, dstSw2);
+        return Objects.hash(notBos, swap, edgeLabel1, dstSw1, edgeLabel2,
+                            dstSw2);
     }
 
     @Override
     public String toString() {
+        String type;
+        if (!notBos && !swap) {
+            type = "default";
+        } else if (!notBos && swap) {
+            type = "swapbos";
+        } else if (notBos && !swap) {
+            type = "not-bos";
+        } else {
+            type = "swap-nb";
+        }
         ToStringHelper h = toStringHelper(this)
-                                .add("MplsSet", mplsSet)
+                                .add("Type", type)
                                 .add("DstSw1", dstSw1)
                                 .add("Label1", edgeLabel1);
         if (dstSw2 != null) {