Fixes setFakeGatewayArpRule called with in case of openstack node event.

Change-Id: I5b3177b8d41342e1adef4b700f02fc8555039fb1
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
index 76f164f..fe5f483 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackNetworkManager.java
@@ -438,6 +438,10 @@
 
     @Override
     public void deleteExternalPeerRouter(ExternalGateway externalGateway) {
+        if (externalGateway == null) {
+            return;
+        }
+
         IpAddress targetIp = getExternalPeerRouterIp(externalGateway);
         if (targetIp == null) {
             return;
@@ -555,6 +559,9 @@
     }
 
     private IpAddress getExternalPeerRouterIp(ExternalGateway externalGateway) {
+        if (externalGateway == null) {
+            return null;
+        }
         Optional<Subnet> externalSubnet = subnets(externalGateway.getNetworkId())
                 .stream()
                 .findFirst();
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
index d089ae6..45928ba 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingHandler.java
@@ -17,6 +17,7 @@
 
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Deactivate;
@@ -217,7 +218,7 @@
         VlanId vlanId = externalPeerRouter == null ? VlanId.NONE : externalPeerRouter.externalPeerRouterVlanId();
 
         if (exGateway == null) {
-            osNetworkAdminService.deleteExternalPeerRouter(exGateway);
+            deleteUnassociatedExternalPeerRouter();
             osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> setSourceNat(iface, false));
         } else {
             osNetworkAdminService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
@@ -226,6 +227,31 @@
         }
     }
 
+    private void deleteUnassociatedExternalPeerRouter() {
+        log.trace("Deleting unassociated external peer router");
+
+        try {
+            Set<String> routerIps = Sets.newConcurrentHashSet();
+
+            osRouterService.routers().stream()
+                    .filter(router -> getGatewayIpAddress(router) != null)
+                    .map(router -> getGatewayIpAddress(router).toString())
+                    .forEach(routerIps::add);
+
+            osNetworkAdminService.externalPeerRouters().stream()
+                    .filter(externalPeerRouter ->
+                            !routerIps.contains(externalPeerRouter.externalPeerRouterIp().toString()))
+                    .forEach(externalPeerRouter -> {
+                        osNetworkAdminService
+                                .deleteExternalPeerRouter(externalPeerRouter.externalPeerRouterIp().toString());
+                        log.trace("Deleted unassociated external peer router {}",
+                                externalPeerRouter.externalPeerRouterIp().toString());
+                    });
+        } catch (Exception e) {
+            log.error("Exception occurred because of {}", e.toString());
+        }
+    }
+
     private void routerRemove(Router osRouter) {
         osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
             Network network = osNetworkAdminService.network(osNetworkAdminService.subnet(iface.getSubnetId())
@@ -357,6 +383,9 @@
 
     private IpAddress getGatewayIpAddress(Router osRouter) {
 
+        if (osRouter.getExternalGatewayInfo() == null) {
+            return null;
+        }
         String extNetId = osNetworkAdminService.network(osRouter.getExternalGatewayInfo().getNetworkId()).getId();
         Optional<Subnet> extSubnet = osNetworkAdminService.subnets().stream()
                 .filter(subnet -> subnet.getNetworkId().equals(extNetId))
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 837c891..03af72e 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
@@ -296,6 +296,58 @@
     }
 
     /**
+     * Installs flow rules which convert ARP request packet into ARP reply
+     * by adding a fake gateway MAC address as Source Hardware Address.
+     *
+     * @param osSubnet  openstack subnet
+     * @param install   flag which indicates whether to install rule or remove rule
+     */
+    private void setFakeGatewayArpRule(Subnet osSubnet, boolean install, OpenstackNode osNode) {
+
+        if (arpMode.equals(ARP_BROADCAST_MODE)) {
+            String gateway = osSubnet.getGateway();
+
+            TrafficSelector selector = DefaultTrafficSelector.builder()
+                    .matchEthType(EthType.EtherType.ARP.ethType().toShort())
+                    .matchArpOp(ARP.OP_REQUEST)
+                    .matchArpTpa(Ip4Address.valueOf(gateway))
+                    .build();
+
+            TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+                    .setArpOp(ARP.OP_REPLY)
+                    .setArpSha(MacAddress.valueOf(gatewayMac))
+                    .setArpSpa(Ip4Address.valueOf(gateway))
+                    .setOutput(PortNumber.IN_PORT)
+                    .build();
+
+            if (osNode == null) {
+                osNodeService.completeNodes(COMPUTE).forEach(n ->
+                        osFlowRuleService.setRule(
+                                appId,
+                                n.intgBridge(),
+                                selector,
+                                treatment,
+                                PRIORITY_ARP_GATEWAY_RULE,
+                                DHCP_ARP_TABLE,
+                                install
+                        )
+                );
+            } else {
+                osFlowRuleService.setRule(
+                        appId,
+                        osNode.intgBridge(),
+                        selector,
+                        treatment,
+                        PRIORITY_ARP_GATEWAY_RULE,
+                        DHCP_ARP_TABLE,
+                        install
+                );
+            }
+
+        }
+    }
+
+    /**
      * An internal packet processor which processes ARP request, and results in
      * packet-out ARP reply.
      */
@@ -355,11 +407,11 @@
                 case OPENSTACK_SUBNET_CREATED:
                 case OPENSTACK_SUBNET_UPDATED:
                     addSubnetGateway(event.subnet());
-                    setFakeGatewayArpRule(event.subnet(), true);
+                    setFakeGatewayArpRule(event.subnet(), true, null);
                     break;
                 case OPENSTACK_SUBNET_REMOVED:
                     removeSubnetGateway(event.subnet());
-                    setFakeGatewayArpRule(event.subnet(), false);
+                    setFakeGatewayArpRule(event.subnet(), false, null);
                     break;
                 case OPENSTACK_NETWORK_CREATED:
                 case OPENSTACK_NETWORK_UPDATED:
@@ -372,45 +424,6 @@
                     break;
             }
         }
-
-        /**
-         * Installs flow rules which convert ARP request packet into ARP reply
-         * by adding a fake gateway MAC address as Source Hardware Address.
-         *
-         * @param osSubnet  openstack subnet
-         * @param install   flag which indicates whether to install rule or remove rule
-         */
-        private void setFakeGatewayArpRule(Subnet osSubnet, boolean install) {
-
-            if (arpMode.equals(ARP_BROADCAST_MODE)) {
-                String gateway = osSubnet.getGateway();
-
-                TrafficSelector selector = DefaultTrafficSelector.builder()
-                        .matchEthType(EthType.EtherType.ARP.ethType().toShort())
-                        .matchArpOp(ARP.OP_REQUEST)
-                        .matchArpTpa(Ip4Address.valueOf(gateway))
-                        .build();
-
-                TrafficTreatment treatment = DefaultTrafficTreatment.builder()
-                        .setArpOp(ARP.OP_REPLY)
-                        .setArpSha(MacAddress.valueOf(gatewayMac))
-                        .setArpSpa(Ip4Address.valueOf(gateway))
-                        .setOutput(PortNumber.IN_PORT)
-                        .build();
-
-                osNodeService.completeNodes(COMPUTE).forEach(n ->
-                    osFlowRuleService.setRule(
-                            appId,
-                            n.intgBridge(),
-                            selector,
-                            treatment,
-                            PRIORITY_ARP_GATEWAY_RULE,
-                            DHCP_ARP_TABLE,
-                            install
-                    )
-                );
-            }
-        }
     }
 
     /**
@@ -449,6 +462,7 @@
                     break;
                 case ARP_BROADCAST_MODE:
                     setDefaultArpRuleForBroadcastMode(osNode, install);
+                    osNetworkService.subnets().forEach(subnet -> setFakeGatewayArpRule(subnet, install, osNode));
                     break;
                 default:
                     log.warn("Invalid ARP mode {}. Please use either " +