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/CpqdOFDPA2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
index 9889967..1fafabc 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
@@ -25,6 +25,7 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.google.common.collect.ImmutableList;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.MacAddress;
 import org.onlab.packet.IpPrefix;
@@ -288,6 +289,11 @@
                                                  VlanIdCriterion vidCriterion,
                                                  VlanId assignedVlan,
                                                  ApplicationId applicationId) {
+        // Consider PortNumber.ANY as wildcard. Match ETH_DST only
+        if (portCriterion != null && portCriterion.port() == PortNumber.ANY) {
+            return processEthDstOnlyFilter(ethCriterion, applicationId);
+        }
+
         //handling untagged packets via assigned VLAN
         if (vidCriterion.vlanId() == VlanId.NONE) {
             vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
@@ -354,6 +360,32 @@
         return rules;
     }
 
+    @Override
+    protected List<FlowRule> processEthDstOnlyFilter(EthCriterion ethCriterion,
+            ApplicationId applicationId) {
+        TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+        selector.matchEthType(Ethernet.TYPE_IPV4);
+        selector.matchEthDst(ethCriterion.mac());
+        /*
+         * Note: CpqD switches do not handle MPLS-related operation properly
+         * for a packet with VLAN tag. We pop VLAN here as a workaround.
+         * Side effect: HostService learns redundant hosts with same MAC but
+         * different VLAN. No known side effect on the network reachability.
+         */
+        treatment.popVlan();
+        treatment.transition(UNICAST_ROUTING_TABLE);
+        FlowRule rule = DefaultFlowRule.builder()
+                .forDevice(deviceId)
+                .withSelector(selector.build())
+                .withTreatment(treatment.build())
+                .withPriority(DEFAULT_PRIORITY)
+                .fromApp(applicationId)
+                .makePermanent()
+                .forTable(TMAC_TABLE).build();
+        return ImmutableList.<FlowRule>builder().add(rule).build();
+    }
+
     /*
      * Cpqd emulation allows MPLS ecmp.
      *
@@ -600,6 +632,7 @@
                     log.warn("Cannot process instruction in versatile fwd {}", ins);
                 }
             }
+            ttBuilder.wipeDeferred();
         }
         if (fwd.nextId() != null) {
             // overide case