Fix: listen correct openstack event to add/remove ext GW ICMP rule

Change-Id: I1082c9b33d3684ae52251de5395eeef735d20f88
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
index 9769203..b563dc7 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackRoutingSnatHandler.java
@@ -727,6 +727,8 @@
             osNetworkAdminService.deriveExternalPeerRouterMac(exGateway, osRouter, vlanId);
             osRouterService.routerInterfaces(osRouter.getId()).forEach(iface ->
                     setSourceNat(iface, exGateway.isEnableSnat()));
+
+            setStatefulDownstreamRules(osRouter, exGateway.isEnableSnat());
         }
     }
 
@@ -837,9 +839,6 @@
                             .forEach(port -> setGatewayToInstanceDownstreamRule(
                                     gwNode, port, install));
 
-                    setStatefulSnatDownstreamRule(gwNode.intgBridge(),
-                            IpPrefix.valueOf(natAddress, VM_PREFIX), install);
-
                     if (install) {
                         PortRange gwPortRange = gwPortRangeMap.get(gwNode);
 
@@ -862,6 +861,20 @@
                 });
     }
 
+    private void setStatefulDownstreamRules(Router osRouter, boolean install) {
+
+        IpAddress natAddress = getExternalIp(osRouter, osNetworkAdminService);
+        if (natAddress == null) {
+            return;
+        }
+
+        osNodeService.completeNodes(GATEWAY)
+                .forEach(gwNode -> {
+                    setStatefulSnatDownstreamRule(gwNode.intgBridge(),
+                            IpPrefix.valueOf(natAddress, VM_PREFIX), install);
+        });
+    }
+
     private List<String> getNetIdByRouterId(String routerId) {
         return osRouterService.routerInterfaces(routerId)
                 .stream()
@@ -1231,12 +1244,10 @@
                     eventExecutor.execute(() -> processRouterIntfRemoval(event));
                     break;
                 case OPENSTACK_ROUTER_GATEWAY_ADDED:
-                    log.debug("Router external gateway {} added",
-                            event.externalGateway().getNetworkId());
+                    eventExecutor.execute(() -> processRouterGatewayAddition(event));
                     break;
                 case OPENSTACK_ROUTER_GATEWAY_REMOVED:
-                    log.debug("Router external gateway {} removed",
-                            event.externalGateway().getNetworkId());
+                    eventExecutor.execute(() -> processRouterGatewayRemoval(event));
                     break;
                 default:
                     break;
@@ -1290,6 +1301,28 @@
 
             routerIfaceRemoved(event.subject(), event.routerIface());
         }
+
+        private void processRouterGatewayAddition(OpenstackRouterEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            log.debug("Router external gateway {} added",
+                    event.externalGateway().getNetworkId());
+
+            setStatefulDownstreamRules(event.subject(), true);
+        }
+
+        private void processRouterGatewayRemoval(OpenstackRouterEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            log.debug("Router external gateway {} removed",
+                    event.externalGateway().getNetworkId());
+
+            setStatefulDownstreamRules(event.subject(), false);
+        }
     }
 
     private class InternalPacketProcessor implements PacketProcessor {
diff --git a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
index 1ff77a8..d8f5be1 100644
--- a/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
+++ b/apps/openstacknetworking/app/src/main/java/org/onosproject/openstacknetworking/impl/OpenstackSwitchingIcmpHandler.java
@@ -58,7 +58,6 @@
 import org.slf4j.Logger;
 
 import java.util.Objects;
-import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
@@ -73,7 +72,6 @@
 import static org.onosproject.openstacknetworking.api.Constants.PRIORITY_ICMP_RULE;
 import static org.onosproject.openstacknetworking.api.Constants.ROUTING_TABLE;
 import static org.onosproject.openstacknetworking.impl.OsgiPropertyConstants.USE_STATEFUL_SNAT;
-import static org.onosproject.openstacknetworking.api.OpenstackNetwork.Type.FLAT;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getExternalIp;
 import static org.onosproject.openstacknetworking.util.OpenstackNetworkingUtil.getPropertyValueAsBoolean;
 import static org.onosproject.openstacknetworking.util.RulePopulatorUtil.NXM_NX_IP_TTL;
@@ -176,34 +174,31 @@
                 .forEach(cNode -> {
                     setRoutableSubnetsIcmpRules(cNode, segId, osSubnet,
                             routableSubnets, gatewayIp, netType, install);
-                    setExtGatewayIcmpReplyRules(cNode, routerIface,
-                            netType, install);
+                });
+    }
+
+    private void processRouteGatewayEvent(Router osRouter, boolean install) {
+        if (!getStatefulSnatFlag()) {
+            return;
+        }
+
+        osNodeService.completeNodes(COMPUTE).stream()
+                .filter(cNode -> cNode.dataIp() != null)
+                .forEach(cNode -> {
+                    setExtGatewayIcmpReplyRules(cNode, osRouter, install);
                 });
     }
 
     private void setExtGatewayIcmpReplyRules(OpenstackNode osNode,
-                                             RouterInterface routerIface,
-                                             Type networkType, boolean install) {
+                                             Router osRouter,
+                                             boolean install) {
 
-        if (networkType == FLAT) {
-            return;
-        }
-
-        Optional<Router> osRouter = osRouterService.routers().stream()
-                .filter(router -> osRouterService.routerInterfaces(routerIface.getId()) != null)
-                .findAny();
-
-        if (!osRouter.isPresent()) {
-            log.error("Cannot find a router for router interface {} ", routerIface);
-            return;
-        }
-
-        IpAddress natAddress = getExternalIp(osRouter.get(), osNetworkService);
+        IpAddress natAddress = getExternalIp(osRouter, osNetworkService);
         if (natAddress == null) {
             return;
         }
 
-        setGatewayIcmpReplyRule(osNode, null, natAddress, networkType, install);
+        setGatewayIcmpReplyRule(osNode, null, natAddress, null, install);
     }
 
     private void setRoutableSubnetsIcmpRules(OpenstackNode osNode,
@@ -296,6 +291,12 @@
                 case OPENSTACK_ROUTER_INTERFACE_REMOVED:
                     eventExecutor.execute(() -> processRouterIntfRemoval(event));
                     break;
+                case OPENSTACK_ROUTER_GATEWAY_ADDED:
+                    eventExecutor.execute(() -> processRouterGatewayAddition(event));
+                    break;
+                case OPENSTACK_ROUTER_GATEWAY_REMOVED:
+                    eventExecutor.execute(() -> processRouterGatewayRemoval(event));
+                    break;
                 default:
                     // do nothing for the other events
                     break;
@@ -325,6 +326,28 @@
 
             processRouterIntfEvent(event.subject(), event.routerIface(), false);
         }
+
+        private void processRouterGatewayAddition(OpenstackRouterEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            log.debug("Router external gateway {} added",
+                    event.externalGateway().getNetworkId());
+
+            processRouteGatewayEvent(event.subject(), true);
+        }
+
+        private void processRouterGatewayRemoval(OpenstackRouterEvent event) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+
+            log.debug("Router external gateway {} removed",
+                    event.externalGateway().getNetworkId());
+
+            processRouteGatewayEvent(event.subject(), false);
+        }
     }
 
     private class InternalNodeEventListener implements OpenstackNodeListener {
@@ -358,6 +381,7 @@
                 osRouterService.routerInterfaces(osRouter.getId()).forEach(iface -> {
                     processRouterIntfEvent(osRouter, iface, true);
                 });
+                processRouteGatewayEvent(osRouter, true);
             });
             log.info("Reconfigure routers for {}", osNode.hostname());
         }