CORD-512 Support vSG <-> vRouter default route

- Support multiple subnets per port. getIpPort() will only return the first non-/32 and non-/0 subnet
    /32 is used as vSG subnet
    /0 is used as default gateway
- Support multiple L3 unicast group on a single port
    Change the way to generate the group ID and group key
- Special case for 0.0.0.0 host. Push a /0 to IP table instead of /32
- Implement vRouterConfig
    Put VR MAC to TMAC table of all leaves when config added
        When processEthDst see PortNumber.ANY in key, match ETH_DST only
- For OFDPA, wipe existing instruction before sending to controller
    So packet that misses L3 unicast table won't be sent to controller twice
- For SpringOpenTTP, pop VLAN before sending to controller
- Move several constant definitions to SegmentRoutingService
- Add minimum priority for IP rules such that /0 won't collide with zero priority default rules
- Update the config sample
    Use VLAN=-1 for hosts
    Add example for default route

Change-Id: Id751697ce36a7e5c13b3859350ff21b585c38525
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OFDPA2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OFDPA2GroupHandler.java
index 828b778..883182b 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OFDPA2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OFDPA2GroupHandler.java
@@ -6,6 +6,7 @@
 import com.google.common.cache.RemovalCause;
 import com.google.common.cache.RemovalNotification;
 import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.MacAddress;
 import org.onlab.packet.MplsLabel;
 import org.onlab.packet.VlanId;
 import org.onosproject.core.ApplicationId;
@@ -95,7 +96,7 @@
             Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", "ofdpa2-%d"));
 
     // index number for group creation
-    private AtomicInteger l3vpnindex = new AtomicInteger(0);
+    private AtomicInteger l3VpnIndex = new AtomicInteger(0);
 
     // local stores for port-vlan mapping
     protected Map<PortNumber, VlanId> port2Vlan = new ConcurrentHashMap<>();
@@ -332,12 +333,14 @@
         VlanId vlanid = null;
         long portNum = 0;
         boolean setVlan = false, popVlan = false;
+        MacAddress dstMac = MacAddress.ZERO;
         for (Instruction ins : treatment.allInstructions()) {
             if (ins.type() == Instruction.Type.L2MODIFICATION) {
                 L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
                 switch (l2ins.subtype()) {
                     case ETH_DST:
-                        outerTtb.setEthDst(((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
+                        dstMac = ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac();
+                        outerTtb.setEthDst(dstMac);
                         break;
                     case ETH_SRC:
                         outerTtb.setEthSrc(((L2ModificationInstruction.ModEtherInstruction) l2ins).mac());
@@ -430,8 +433,11 @@
                     mplsgroupkey, nextId);
         } else {
             // outer group is L3Unicast
-            int l3groupId = L3_UNICAST_TYPE | (int) portNum;
-            int l3gk = L3_UNICAST_TYPE | (TYPE_MASK & (deviceId.hashCode() << 8 | (int) portNum));
+            int l3groupId = L3_UNICAST_TYPE |
+                    (TYPE_MASK & (int) (dstMac.toLong() & 0xffff) << 6 | (int) portNum);
+            int l3gk = L3_UNICAST_TYPE |
+                    (TYPE_MASK & (deviceId.hashCode() << 22 |
+                            (int) (dstMac.toLong() & 0xffff) << 6 | (int) portNum));
             final GroupKey l3groupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3gk));
             outerTtb.group(new DefaultGroupId(l2groupId));
             // create the l3unicast group description to wait for the
@@ -734,8 +740,8 @@
                                 onelabelGroupInfo.outerGrpDesc.givenGroupId()));
                 GroupBucket l3vpnGrpBkt  =
                         DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build());
-                int l3vpngroupId = MPLS_L3VPN_SUBTYPE | l3vpnindex.incrementAndGet();
-                int l3vpngk = MPLS_L3VPN_SUBTYPE | nextObj.id() << 12 | l3vpnindex.get();
+                int l3vpngroupId = MPLS_L3VPN_SUBTYPE | l3VpnIndex.incrementAndGet();
+                int l3vpngk = MPLS_L3VPN_SUBTYPE | nextObj.id() << 12 | l3VpnIndex.get();
                 GroupKey l3vpngroupkey = new DefaultGroupKey(OFDPA2Pipeline.appKryo.serialize(l3vpngk));
                 GroupDescription l3vpnGroupDesc =
                         new DefaultGroupDescription(