Only flood the ARP traffic to virtual network to avoid network loop

1. Purge unnecessary phyIntfPort method from openstacknode.
2. Update setUpstreamRulesForFlat method to reflect multi-br change

Change-Id: I6d70702d2aac2a067577635fada06c8eb21b56ae
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 3b805e8..a4e817f 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
@@ -55,7 +55,9 @@
 import org.onosproject.openstacknode.api.OpenstackNodeEvent;
 import org.onosproject.openstacknode.api.OpenstackNodeListener;
 import org.onosproject.openstacknode.api.OpenstackNodeService;
+import org.openstack4j.model.common.IdEntity;
 import org.openstack4j.model.network.Network;
+import org.openstack4j.model.network.NetworkType;
 import org.openstack4j.model.network.Subnet;
 import org.osgi.service.component.ComponentContext;
 import org.osgi.service.component.annotations.Activate;
@@ -72,6 +74,7 @@
 import java.util.Objects;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
+import java.util.stream.Collectors;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
@@ -792,6 +795,35 @@
         }
     }
 
+    private void setBaseVnetArpRuleForBroadcastMode(OpenstackNode osNode,
+                                                    String segId,
+                                                    boolean isTunnel,
+                                                    boolean install) {
+        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder()
+                .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+                .matchArpOp(ARP.OP_REQUEST);
+
+        if (isTunnel) {
+            sBuilder.matchTunnelId(Long.valueOf(segId));
+        } else {
+            sBuilder.matchVlanId(VlanId.vlanId(segId));
+        }
+
+        TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                .setOutput(PortNumber.FLOOD)
+                .build();
+
+        osFlowRuleService.setRule(
+                appId,
+                osNode.intgBridge(),
+                sBuilder.build(),
+                treatment,
+                PRIORITY_ARP_FLOOD_RULE,
+                ARP_TABLE,
+                install
+        );
+    }
+
     /**
      * An internal network listener which listens to openstack network event,
      * manages the gateway collection and installs flow rule that handles
@@ -827,7 +859,11 @@
                     break;
                 case OPENSTACK_NETWORK_CREATED:
                 case OPENSTACK_NETWORK_UPDATED:
+                    eventExecutor.execute(() -> processNetworkCreation(event));
+                    break;
                 case OPENSTACK_NETWORK_REMOVED:
+                    eventExecutor.execute(() -> processNetworkRemoval(event));
+                    break;
                 case OPENSTACK_PORT_CREATED:
                 case OPENSTACK_PORT_UPDATED:
                 case OPENSTACK_PORT_REMOVED:
@@ -854,6 +890,41 @@
             setFakeGatewayArpRule(event.subnet(), event.subject(),
                     false, null);
         }
+
+        private void processNetworkCreation(OpenstackNetworkEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            setVnetArpRule(event.subject(), true);
+        }
+
+        private void processNetworkRemoval(OpenstackNetworkEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            setVnetArpRule(event.subject(), false);
+        }
+
+        private void setVnetArpRule(Network network, boolean install) {
+            String netId = network.getId();
+            NetworkType netType = network.getNetworkType();
+
+            if (netType != NetworkType.LOCAL && netType != NetworkType.FLAT
+                    && netType != NetworkType.VLAN) {
+                String segId = osNetworkService.segmentId(netId);
+                osNodeService.completeNodes(COMPUTE)
+                        .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
+                                node, segId, true, install));
+            }
+            if (netType == NetworkType.VLAN) {
+                String segId = osNetworkService.segmentId(netId);
+                osNodeService.completeNodes(COMPUTE)
+                        .forEach(node -> setBaseVnetArpRuleForBroadcastMode(
+                                node, segId, false, install));
+            }
+        }
     }
 
     /**
@@ -926,7 +997,7 @@
 
         private void processDefaultArpRuleForBroadcastMode(OpenstackNode osNode,
                                                            boolean install) {
-            setDefaultArpRuleForBroadcastMode(osNode, install);
+            setVnetArpRuleForBroadcastMode(osNode, install);
 
             // we do not add fake gateway ARP rules for FLAT network
             // ARP packets generated by FLAT typed VM should not be
@@ -961,27 +1032,29 @@
             );
         }
 
-        private void setDefaultArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
-            TrafficSelector selector = DefaultTrafficSelector.builder()
-                    .matchEthType(EthType.EtherType.ARP.ethType().toShort())
-                    .matchArpOp(ARP.OP_REQUEST)
-                    .build();
+        private void setVnetArpRuleForBroadcastMode(OpenstackNode osNode, boolean install) {
+            Set<String> netIds = osNetworkService.networks().stream()
+                    .map(IdEntity::getId).collect(Collectors.toSet());
 
-            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                    .setOutput(PortNumber.FLOOD)
-                    .build();
+            netIds.stream()
+                    .filter(nid -> osNetworkService.networkType(nid) == VXLAN ||
+                                    osNetworkService.networkType(nid) == GRE ||
+                                    osNetworkService.networkType(nid) == GENEVE)
+                    .forEach(nid -> {
+                        String segId = osNetworkService.segmentId(nid);
+                        setBaseVnetArpRuleForBroadcastMode(osNode, segId, true, install);
+                    });
 
-            osFlowRuleService.setRule(
-                    appId,
-                    osNode.intgBridge(),
-                    selector,
-                    treatment,
-                    PRIORITY_ARP_FLOOD_RULE,
-                    ARP_TABLE,
-                    install
-            );
+            netIds.stream()
+                    .filter(nid -> osNetworkService.networkType(nid) == VLAN)
+                    .forEach(nid -> {
+                        String segId = osNetworkService.segmentId(nid);
+                        setBaseVnetArpRuleForBroadcastMode(osNode, segId, false, install);
+                    });
         }
 
+
+
         private void setAllArpRules(OpenstackNode osNode, boolean install) {
             if (ARP_BROADCAST_MODE.equals(getArpMode())) {
                 instancePortService.instancePorts().stream()