[ONOS-4426] [ONOS-4511] [ONOS-4502] Upgrade Vtn Module when access same network segment.

Change-Id: I3afe6b36a44f0eedd642eeadfc23fc3233e7621e
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
index dd27535..74cb756 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java
@@ -23,9 +23,12 @@
 
 import org.onlab.osgi.ServiceDirectory;
 import org.onlab.packet.EthType.EtherType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
 import org.onosproject.net.behaviour.Pipeliner;
 import org.onosproject.net.behaviour.PipelinerContext;
 import org.onosproject.net.device.DeviceService;
@@ -40,6 +43,8 @@
 import org.onosproject.net.flow.TrafficTreatment;
 import org.onosproject.net.flow.criteria.Criteria;
 import org.onosproject.net.flow.criteria.Criterion.Type;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.instructions.Instructions;
 import org.onosproject.net.flowobjective.FilteringObjective;
 import org.onosproject.net.flowobjective.FlowObjectiveStore;
 import org.onosproject.net.flowobjective.ForwardingObjective;
@@ -71,6 +76,7 @@
     private static final int SNAT_TABLE = 40;
     private static final int MAC_TABLE = 50;
     private static final int TABLE_MISS_PRIORITY = 0;
+    private static final String USERDATA_IP = "169.254.169.254";
 
     @Override
     public void init(DeviceId deviceId, PipelinerContext context) {
@@ -213,7 +219,7 @@
         TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
 
         treatment.transition(MAC_TABLE);
-
+        treatment.add(Instructions.createOutput(PortNumber.CONTROLLER));
         FlowRule rule;
         rule = DefaultFlowRule.builder().forDevice(deviceId)
                 .withSelector(selector.build())
@@ -290,8 +296,9 @@
         Integer transition = null;
         Integer forTable = null;
         // MAC table flow rules
-        if (selector.getCriterion(Type.TUNNEL_ID) != null && selector
-                .getCriterion(Type.ETH_DST) != null) {
+        if (selector.getCriterion(Type.TUNNEL_ID) != null
+                && (selector.getCriterion(Type.ETH_DST) != null
+                        || selector.getCriterion(Type.ETH_SRC) != null)) {
             forTable = MAC_TABLE;
             return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
         }
@@ -306,6 +313,10 @@
                 transition = MAC_TABLE;
             } else if (selector.getCriterion(Type.IPV4_DST) != null) {
                 transition = DNAT_TABLE;
+            } else if (selector.getCriterion(Type.ETH_TYPE) != null
+                    && selector.getCriterion(Type.ETH_TYPE).equals(Criteria
+                            .matchEthType(EtherType.ARP.ethType().toShort()))) {
+                transition = ARP_TABLE;
             }
             return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
         }
@@ -315,6 +326,10 @@
                         .matchEthType(EtherType.ARP.ethType().toShort()))) {
             // CLASSIFIER table arp flow rules
             if (selector.getCriterion(Type.TUNNEL_ID) == null) {
+                if (selector.getCriterion(Type.ARP_OP) != null) {
+                    forTable = CLASSIFIER_TABLE;
+                    return reassemblyFlowRule(ruleBuilder, tb, null, forTable);
+                }
                 transition = ARP_TABLE;
                 forTable = CLASSIFIER_TABLE;
                 return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
@@ -322,6 +337,13 @@
             forTable = ARP_TABLE;
             return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
         }
+        // SNAT table flow rules
+        if (selector.getCriterion(Type.TUNNEL_ID) != null
+                && selector.getCriterion(Type.IPV4_SRC) != null) {
+            transition = MAC_TABLE;
+            forTable = SNAT_TABLE;
+            return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
+        }
         // L3FWD table flow rules
         if (selector.getCriterion(Type.TUNNEL_ID) != null
                 && selector.getCriterion(Type.IPV4_DST) != null) {
@@ -331,17 +353,18 @@
         }
         // DNAT table flow rules
         if (selector.getCriterion(Type.IPV4_DST) != null) {
+            IPCriterion ipCriterion = (IPCriterion) selector.getCriterion(Type.IPV4_DST);
+            IpPrefix ipPrefix = ipCriterion.ip();
+            // specific CLASSIFIER table flow rules for userdata
+            if (ipPrefix.address().equals(IpAddress.valueOf(USERDATA_IP))) {
+                forTable = CLASSIFIER_TABLE;
+                transition = MAC_TABLE;
+                return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
+            }
             transition = L3FWD_TABLE;
             forTable = DNAT_TABLE;
             return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
         }
-        // SNAT table flow rules
-        if (selector.getCriterion(Type.TUNNEL_ID) != null
-                && selector.getCriterion(Type.IPV4_SRC) != null) {
-            transition = MAC_TABLE;
-            forTable = SNAT_TABLE;
-            return reassemblyFlowRule(ruleBuilder, tb, transition, forTable);
-        }
         return Collections.singletonList(ruleBuilder.build());
     }
 
@@ -371,4 +394,4 @@
     private void pass(Objective obj) {
         obj.context().ifPresent(context -> context.onSuccess(obj));
     }
-}
+}
\ No newline at end of file
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index cc1f68b..3649866 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -461,6 +461,10 @@
             return;
         }
 
+        Map<String, String> options = new HashMap<>();
+        options.put("disable-in-band", "true");
+        bridge.setOtherConfig(options);
+
         String bridgeUuid = getBridgeUuid(bridgeName);
         if (bridgeUuid == null) {
             log.debug("Create a new bridge");
@@ -525,16 +529,18 @@
             return;
         }
 
+        Map<String, String> options = new HashMap<>();
+        options.put("disable-in-band", "true");
+        if (dpid != null) {
+            options.put("datapath-id", dpid);
+        }
+        bridge.setOtherConfig(options);
+
         String bridgeUuid = getBridgeUuid(bridgeName);
         if (bridgeUuid == null) {
             log.debug("Create a new bridge");
 
             bridge.setName(bridgeName);
-            if (dpid != null) {
-                Map<String, String> options = new HashMap<>();
-                options.put("datapath-id", dpid);
-                bridge.setOtherConfig(options);
-            }
             bridgeUuid = insertConfig(OvsdbConstant.BRIDGE, "_uuid",
                                       OvsdbConstant.DATABASENAME, "bridges",
                                       ovsUuid, bridge.getRow());
@@ -586,7 +592,10 @@
         bridge.setProtocols(protocols);
 
         Map<String, String> options = new HashMap<>();
-        options.put("datapath-id", dpid);
+        options.put("disable-in-band", "true");
+        if (dpid != null) {
+            options.put("datapath-id", dpid);
+        }
         bridge.setOtherConfig(options);
 
         String bridgeUuid = getBridgeUuid(bridgeName);