Merge remote-tracking branch 'origin/master' into dev-karaf-4.2.1

Change-Id: If611105632e508cb17352c6f5b1cbcfd85f716d1
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
index 845c258..0a527e0 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackAddAclCommand.java
@@ -35,7 +35,7 @@
 
 import java.util.Optional;
 
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FORCED_ACL_RULE;
 
@@ -121,7 +121,7 @@
                 sBuilder.build(),
                 treatment,
                 PRIORITY_FORCED_ACL_RULE,
-                DHCP_ARP_TABLE,
+                DHCP_TABLE,
                 true);
     }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
index 37a6b9c..70a2347 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/cli/OpenstackRemoveAclCommand.java
@@ -35,7 +35,7 @@
 
 import java.util.Optional;
 
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_FORCED_ACL_RULE;
 
@@ -118,7 +118,7 @@
                 sBuilder.build(),
                 treatment,
                 PRIORITY_FORCED_ACL_RULE,
-                DHCP_ARP_TABLE,
+                DHCP_TABLE,
                 false);
     }
 }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
index 2ea7400..0dc4db7 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackFlowRuleManager.java
@@ -198,11 +198,18 @@
     protected void initializePipeline(DeviceId deviceId) {
         // for inbound table transition
         connectTables(deviceId, Constants.STAT_INBOUND_TABLE, Constants.VTAP_INBOUND_TABLE);
-        connectTables(deviceId, Constants.VTAP_INBOUND_TABLE, Constants.DHCP_ARP_TABLE);
+        connectTables(deviceId, Constants.VTAP_INBOUND_TABLE, Constants.DHCP_TABLE);
 
-        // for vTag and ACL table transition
-        connectTables(deviceId, Constants.DHCP_ARP_TABLE, Constants.VTAG_TABLE);
-        connectTables(deviceId, Constants.VTAG_TABLE, Constants.ACL_TABLE);
+        // for DHCP and vTag table transition
+        connectTables(deviceId, Constants.DHCP_TABLE, Constants.VTAG_TABLE);
+
+        // for vTag and ARP table transition
+        connectTables(deviceId, Constants.VTAG_TABLE, Constants.ARP_TABLE);
+
+        // for ARP and ACL table transition
+        connectTables(deviceId, Constants.ARP_TABLE, Constants.ACL_TABLE);
+
+        // for ACL and JUMP table transition
         connectTables(deviceId, Constants.ACL_TABLE, Constants.JUMP_TABLE);
 
         // for JUMP table transition
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
index 995bb21..dd476de 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackMetadataProxyHandler.java
@@ -77,7 +77,7 @@
 import java.util.Objects;
 import java.util.Set;
 
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_DHCP_RULE;
 import static org.onosproject.openstacknetworking.impl.OpenstackMetadataProxyHandler.Http.Type.RESPONSE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.hmacEncrypt;
@@ -572,7 +572,7 @@
                     selector,
                     treatment,
                     PRIORITY_DHCP_RULE,
-                    DHCP_ARP_TABLE,
+                    DHCP_TABLE,
                     install);
         }
     }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
index f1f1370..b2cb36e 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingFloatingIpHandler.java
@@ -788,9 +788,9 @@
                     break;
                 case OPENSTACK_INSTANCE_MIGRATION_ENDED:
 
-                    InstancePort revisedInstPort = swapStaleLocation(event.subject());
+                    InstancePort oldInstPort = swapStaleLocation(event.subject());
 
-                    fip = associatedFloatingIp(revisedInstPort, ips);
+                    fip = associatedFloatingIp(oldInstPort, ips);
 
                     if (fip == null) {
                         return;
@@ -805,7 +805,13 @@
                         throw new IllegalStateException(errorFormat);
                     }
 
-                    // If we only have one gateway, we simply do not remove any
+                    eventExecutor.execute(() -> {
+                        // We need to remove the old ComputeNodeToGateway rules from
+                        // original compute node
+                        setComputeNodeToGatewayHelper(oldInstPort, osNet, gateways, false);
+                    });
+
+                        // If we only have one gateway, we simply do not remove any
                     // flow rules from either gateway or compute node
                     if (gateways.size() == 1) {
                         return;
@@ -817,7 +823,7 @@
                     // it has been overwritten at port detention event
                     // if it is false, we will remove the rules
                     DeviceId newDeviceId = event.subject().deviceId();
-                    DeviceId oldDeviceId = revisedInstPort.deviceId();
+                    DeviceId oldDeviceId = oldInstPort.deviceId();
 
                     OpenstackNode oldGateway = getGwByComputeDevId(gateways, oldDeviceId);
                     OpenstackNode newGateway = getGwByComputeDevId(gateways, newDeviceId);
@@ -827,15 +833,10 @@
                     }
 
                     eventExecutor.execute(() -> {
-
-                        // We need to remove the old ComputeNodeToGateway rules from
-                        // original compute node
-                        setComputeNodeToGatewayHelper(revisedInstPort, osNet, gateways, false);
-
                         // Since DownstreamExternal rules should only be placed in
                         // corresponding gateway node, we need to remove old rule from
                         // the corresponding gateway node
-                        setDownstreamExternalRulesHelper(fip, osNet, revisedInstPort,
+                        setDownstreamExternalRulesHelper(fip, osNet, oldInstPort,
                                 externalPeerRouter, gateways, false);
                     });
                     break;
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
index c1ea3cd..c78134d 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingArpHandler.java
@@ -74,15 +74,15 @@
 import static com.google.common.base.Preconditions.checkNotNull;
 import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
 import static org.onosproject.openstacknetworking.api.Constants.ARP_PROXY_MODE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_ARP_MODE_STR;
 import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_CONTROL_RULE;
+import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_FLOOD_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_GATEWAY_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REPLY_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_REQUEST_RULE;
-import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ARP_SUBNET_RULE;
 import static org.onosproject.openstacknetworking.api.InstancePort.State.ACTIVE;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
@@ -323,7 +323,7 @@
                                 selector,
                                 treatment,
                                 PRIORITY_ARP_GATEWAY_RULE,
-                                DHCP_ARP_TABLE,
+                                ARP_TABLE,
                                 install
                         )
                 );
@@ -334,7 +334,7 @@
                         selector,
                         treatment,
                         PRIORITY_ARP_GATEWAY_RULE,
-                        DHCP_ARP_TABLE,
+                        ARP_TABLE,
                         install
                 );
             }
@@ -395,10 +395,13 @@
 
         OpenstackNode localNode = osNodeService.node(port.deviceId());
 
+        String segId = osNetworkService.segmentId(port.networkId());
+
         TrafficSelector selector = DefaultTrafficSelector.builder()
                 .matchEthType(EthType.EtherType.ARP.ethType().toShort())
                 .matchArpOp(ARP.OP_REQUEST)
                 .matchArpTpa(port.ipAddress().getIp4Address())
+                .matchTunnelId(Long.valueOf(segId))
                 .build();
 
         setRemoteArpTreatmentForVxlan(selector, port, localNode, install);
@@ -449,7 +452,7 @@
                 selector,
                 treatment,
                 PRIORITY_ARP_REPLY_RULE,
-                DHCP_ARP_TABLE,
+                ARP_TABLE,
                 install
         );
 
@@ -478,7 +481,7 @@
                         selector,
                         treatmentToRemote,
                         PRIORITY_ARP_REQUEST_RULE,
-                        DHCP_ARP_TABLE,
+                        ARP_TABLE,
                         install
                 );
             }
@@ -501,7 +504,7 @@
                         selector,
                         treatmentToRemote,
                         PRIORITY_ARP_REQUEST_RULE,
-                        DHCP_ARP_TABLE,
+                        ARP_TABLE,
                         install);
             }
         }
@@ -674,7 +677,7 @@
                     selector,
                     treatment,
                     PRIORITY_ARP_CONTROL_RULE,
-                    DHCP_ARP_TABLE,
+                    ARP_TABLE,
                     install
             );
         }
@@ -694,8 +697,8 @@
                     osNode.intgBridge(),
                     selector,
                     treatment,
-                    PRIORITY_ARP_SUBNET_RULE,
-                    DHCP_ARP_TABLE,
+                    PRIORITY_ARP_FLOOD_RULE,
+                    ARP_TABLE,
                     install
             );
         }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
index efd10d9..ca322ea 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingDhcpHandler.java
@@ -85,7 +85,7 @@
 import static org.onlab.packet.DHCP.MsgType.DHCPACK;
 import static org.onlab.packet.DHCP.MsgType.DHCPOFFER;
 import static org.onosproject.openstacknetworking.api.Constants.DEFAULT_GATEWAY_MAC_STR;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_DHCP_RULE;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -577,7 +577,7 @@
                     selector,
                     treatment,
                     PRIORITY_DHCP_RULE,
-                    DHCP_ARP_TABLE,
+                    DHCP_TABLE,
                     install);
         }
     }
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
index 3ac981a..b348d49 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingHandler.java
@@ -24,6 +24,8 @@
 import org.osgi.service.component.annotations.ReferenceCardinality;
 import org.onlab.packet.Ethernet;
 import org.onlab.packet.VlanId;
+import org.onosproject.cfg.ComponentConfigService;
+import org.onosproject.cfg.ConfigProperty;
 import org.onosproject.cluster.ClusterService;
 import org.onosproject.cluster.LeadershipService;
 import org.onosproject.cluster.NodeId;
@@ -56,12 +58,15 @@
 import org.slf4j.Logger;
 
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ExecutorService;
 
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.onlab.util.Tools.groupedThreads;
 import static org.onosproject.openstacknetworking.api.Constants.ACL_TABLE;
-import static org.onosproject.openstacknetworking.api.Constants.DHCP_ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_BROADCAST_MODE;
+import static org.onosproject.openstacknetworking.api.Constants.ARP_TABLE;
+import static org.onosproject.openstacknetworking.api.Constants.DHCP_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.FLAT_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.FORWARDING_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.OPENSTACK_NETWORKING_APP_ID;
@@ -74,6 +79,7 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_TUNNEL_TAG_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.STAT_FLAT_OUTBOUND_TABLE;
 import static org.onosproject.openstacknetworking.api.Constants.VTAG_TABLE;
+import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValue;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.swapStaleLocation;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.buildExtension;
 import static org.onosproject.openstacknode.api.OpenstackNode.NodeType.COMPUTE;
@@ -89,6 +95,7 @@
 
     private final Logger log = getLogger(getClass());
 
+    private static final String ARP_MODE = "arpMode";
     private static final String ERR_SET_FLOWS_VNI = "Failed to set flows for %s: Failed to get VNI for %s";
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -107,6 +114,10 @@
     protected ClusterService clusterService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected ComponentConfigService configService;
+
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+
     protected LeadershipService leadershipService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
@@ -162,12 +173,22 @@
         NetworkType type = osNetworkService.network(instPort.networkId()).getNetworkType();
         switch (type) {
             case VXLAN:
-                setTunnelTagFlowRules(instPort, install);
+                setTunnelTagIpFlowRules(instPort, install);
                 setForwardingRulesForVxlan(instPort, install);
+
+                if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+                    setTunnelTagArpFlowRules(instPort, install);
+                }
+
                 break;
             case VLAN:
-                setVlanTagFlowRules(instPort, install);
+                setVlanTagIpFlowRules(instPort, install);
                 setForwardingRulesForVlan(instPort, install);
+
+                if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+                    setVlanTagArpFlowRules(instPort, install);
+                }
+
                 break;
             case FLAT:
                 setFlatJumpRules(instPort, install);
@@ -190,10 +211,20 @@
 
         switch (type) {
             case VXLAN:
-                setTunnelTagFlowRules(instPort, false);
+                setTunnelTagIpFlowRules(instPort, false);
+
+                if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+                    setTunnelTagArpFlowRules(instPort, false);
+                }
+
                 break;
             case VLAN:
-                setVlanTagFlowRules(instPort, false);
+                setVlanTagIpFlowRules(instPort, false);
+
+                if (ARP_BROADCAST_MODE.equals(getArpMode())) {
+                    setVlanTagArpFlowRules(instPort, false);
+                }
+
                 break;
             case FLAT:
                 setFlatJumpRules(instPort, false);
@@ -219,7 +250,7 @@
                 selector.build(),
                 treatment.build(),
                 PRIORITY_FLAT_JUMP_UPSTREAM_RULE,
-                DHCP_ARP_TABLE,
+                DHCP_TABLE,
                 install);
 
         Network network = osNetworkService.network(port.networkId());
@@ -247,7 +278,7 @@
                 selector.build(),
                 treatment.build(),
                 PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
-                DHCP_ARP_TABLE,
+                DHCP_TABLE,
                 install);
 
         selector = DefaultTrafficSelector.builder();
@@ -261,7 +292,7 @@
                 selector.build(),
                 treatment.build(),
                 PRIORITY_FLAT_JUMP_DOWNSTREAM_RULE,
-                DHCP_ARP_TABLE,
+                DHCP_TABLE,
                 install);
     }
 
@@ -446,18 +477,27 @@
                 });
     }
 
+    private void setTunnelTagArpFlowRules(InstancePort instPort, boolean install) {
+        setTunnelTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
+    }
+
+    private void setTunnelTagIpFlowRules(InstancePort instPort, boolean install) {
+        setTunnelTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
+    }
+
     /**
      * Configures the flow rule which is for using VXLAN to tag the packet
      * based on the in_port number of a virtual instance.
-     * Note that this rule will be inserted in VNI table (table 0).
+     * Note that this rule will be inserted in vTag table.
      *
      * @param instPort instance port object
      * @param install install flag, add the rule if true, remove it otherwise
      */
-    private void setTunnelTagFlowRules(InstancePort instPort, boolean install) {
+    private void setTunnelTagFlowRules(InstancePort instPort,
+                                       short ethType,
+                                       boolean install) {
         TrafficSelector selector = DefaultTrafficSelector.builder()
-                // TODO: need to handle IPv6 in near future
-                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchEthType(ethType)
                 .matchInPort(instPort.portNumber())
                 .build();
 
@@ -469,9 +509,9 @@
 
         TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder()
                 .setTunnelId(getVni(instPort))
-                .transition(ACL_TABLE);
+                .transition(ARP_TABLE);
 
-        if (securityGroupService.isSecurityGroupEnabled()) {
+        if (securityGroupService.isSecurityGroupEnabled() && ethType == Ethernet.TYPE_IPV4) {
             tb.extension(ctTreatment, instPort.deviceId());
         }
 
@@ -485,18 +525,27 @@
                 install);
     }
 
+    private void setVlanTagIpFlowRules(InstancePort instPort, boolean install) {
+        setVlanTagFlowRules(instPort, Ethernet.TYPE_IPV4, install);
+    }
+
+    private void setVlanTagArpFlowRules(InstancePort instPort, boolean install) {
+        setVlanTagFlowRules(instPort, Ethernet.TYPE_ARP, install);
+    }
+
     /**
      * Configures the flow rule which is for using VLAN to tag the packet
      * based on the in_port number of a virtual instance.
-     * Note that this rule will be inserted in VNI table (table 0).
+     * Note that this rule will be inserted in vTag table.
      *
      * @param instPort instance port object
      * @param install install flag, add the rule if true, remove it otherwise
      */
-    private void setVlanTagFlowRules(InstancePort instPort, boolean install) {
+    private void setVlanTagFlowRules(InstancePort instPort,
+                                     short ethType,
+                                     boolean install) {
         TrafficSelector selector = DefaultTrafficSelector.builder()
-                // TODO: need to handle IPv6 in near future
-                .matchEthType(Ethernet.TYPE_IPV4)
+                .matchEthType(ethType)
                 .matchInPort(instPort.portNumber())
                 .build();
 
@@ -637,6 +686,11 @@
         return Long.valueOf(osNet.getProviderSegID());
     }
 
+    private String getArpMode() {
+        Set<ConfigProperty> properties = configService.getProperties(OpenstackSwitchingArpHandler.class.getName());
+        return getPropertyValue(properties, ARP_MODE);
+    }
+
     /**
      * An internal instance port listener which listens the port events generated
      * from VM. The corresponding L2 forwarding rules will be generated and