Implemented VLAN-to-VLAN routing support for SDN-IP.

SDN-IP can now support peering and routing between hosts that are connected
on VLANs.

Changes include:
 * Updated NetworkConfigReader app to read (optional) VLAN configuration
 * Updated VlanId to support the 'VLAN present' value - in a match this means
   that a VLAN tag must be present, but it can contain any value.
 * Updated SDN-IP to set destination VLAN tag values if appropriate
 * Updated FlowModBuilder and FlowEntryBuilder to support 'VLAN present' value
 * Slew of test updates.

Change-Id: Ief48cede5c1fd50e1efa851da5a97fb4a8edda29
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
index 576c003..a78cadb 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowEntryBuilder.java
@@ -15,10 +15,7 @@
  */
 package org.onosproject.provider.of.flow.impl;
 
-import static org.slf4j.LoggerFactory.getLogger;
-
-import java.util.List;
-
+import com.google.common.collect.Lists;
 import org.onlab.packet.Ip4Address;
 import org.onlab.packet.Ip4Prefix;
 import org.onlab.packet.Ip6Prefix;
@@ -63,7 +60,9 @@
 import org.projectfloodlight.openflow.types.VlanPcp;
 import org.slf4j.Logger;
 
-import com.google.common.collect.Lists;
+import java.util.List;
+
+import static org.slf4j.LoggerFactory.getLogger;
 
 public class FlowEntryBuilder {
     private final Logger log = getLogger(getClass());
@@ -380,8 +379,19 @@
                 builder.matchVlanPcp(vlanPcp);
                 break;
             case VLAN_VID:
-                VlanId vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
-                builder.matchVlanId(vlanId);
+                VlanId vlanId = null;
+                if (match.isPartiallyMasked(MatchField.VLAN_VID)) {
+                    Masked<OFVlanVidMatch> masked = match.getMasked(MatchField.VLAN_VID);
+                    if (masked.getValue().equals(OFVlanVidMatch.PRESENT)
+                            && masked.getMask().equals(OFVlanVidMatch.PRESENT)) {
+                        vlanId = VlanId.ANY;
+                    }
+                } else {
+                    vlanId = VlanId.vlanId(match.get(MatchField.VLAN_VID).getVlan());
+                }
+                if (vlanId != null) {
+                    builder.matchVlanId(vlanId);
+                }
                 break;
             case TCP_DST:
                 builder.matchTcpDst((short) match.get(MatchField.TCP_DST).getPort());
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
index 78efee2..016b0cf 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/FlowModBuilder.java
@@ -15,10 +15,11 @@
  */
 package org.onosproject.provider.of.flow.impl;
 
-import static org.slf4j.LoggerFactory.getLogger;
-
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
 import org.onlab.packet.Ip6Address;
 import org.onlab.packet.Ip6Prefix;
+import org.onlab.packet.VlanId;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.TrafficSelector;
 import org.onosproject.net.flow.criteria.Criteria;
@@ -26,16 +27,14 @@
 import org.onosproject.net.flow.criteria.Criteria.EthTypeCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPCriterion;
 import org.onosproject.net.flow.criteria.Criteria.IPProtocolCriterion;
+import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
 import org.onosproject.net.flow.criteria.Criteria.LambdaCriterion;
 import org.onosproject.net.flow.criteria.Criteria.PortCriterion;
 import org.onosproject.net.flow.criteria.Criteria.TcpPortCriterion;
 import org.onosproject.net.flow.criteria.Criteria.VlanIdCriterion;
 import org.onosproject.net.flow.criteria.Criteria.VlanPcpCriterion;
-import org.onosproject.net.flow.criteria.Criteria.Icmpv6TypeCriterion;
-import org.onosproject.net.flow.criteria.Criteria.Icmpv6CodeCriterion;
 import org.onosproject.net.flow.criteria.Criterion;
-import org.onlab.packet.Ip4Address;
-import org.onlab.packet.Ip4Prefix;
 import org.projectfloodlight.openflow.protocol.OFFactory;
 import org.projectfloodlight.openflow.protocol.OFFlowAdd;
 import org.projectfloodlight.openflow.protocol.OFFlowDelete;
@@ -60,6 +59,8 @@
 
 import java.util.Optional;
 
+import static org.slf4j.LoggerFactory.getLogger;
+
 /**
  * Builder for OpenFlow flow mods based on FlowRules.
  */
@@ -199,8 +200,14 @@
                 break;
             case VLAN_VID:
                 VlanIdCriterion vid = (VlanIdCriterion) c;
-                mBuilder.setExact(MatchField.VLAN_VID,
-                        OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
+
+                if (vid.vlanId().equals(VlanId.ANY)) {
+                    mBuilder.setMasked(MatchField.VLAN_VID, OFVlanVidMatch.PRESENT,
+                                       OFVlanVidMatch.PRESENT);
+                } else {
+                    mBuilder.setExact(MatchField.VLAN_VID,
+                            OFVlanVidMatch.ofVlanVid(VlanVid.ofVlan(vid.vlanId().toShort())));
+                }
                 break;
             case TCP_DST:
                 tp = (TcpPortCriterion) c;