Enhance the RM logic for Kubevirt Networking App

Change-Id: I84fa678c75ba1e738c68c72ffbc89c54e5309997
(cherry picked from commit 842b3031e5b82a95d1f292fc952e8f091cc1e20b)
diff --git a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtRouter.java b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtRouter.java
index 84a5998..43c9c88 100644
--- a/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtRouter.java
+++ b/apps/kubevirt-networking/api/src/main/java/org/onosproject/kubevirtnetworking/api/DefaultKubevirtRouter.java
@@ -165,8 +165,7 @@
 
     @Override
     public int hashCode() {
-        return Objects.hash(name, description, mac, enableSnat,
-                internal, external, peerRouter, gateway);
+        return Objects.hash(name, description, mac);
     }
 
     @Override
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
index d59a260..419672f 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtFloatingIpHandler.java
@@ -398,48 +398,41 @@
         }
 
         private void processRouterGatewayNodeChanged(KubevirtRouter router, String disAssociatedGateway) {
-
-            kubevirtRouterService.floatingIps()
-                    .stream()
-                    .filter(fip -> fip.routerName().equals(router.name())).forEach(fip -> {
-                        KubevirtNode oldGw = kubevirtNodeService.node(disAssociatedGateway);
-                        if (oldGw == null) {
-                            return;
-                        }
-
+            kubevirtRouterService.floatingIpsByRouter(router.name())
+                    .forEach(fip -> {
                         KubevirtNode newGw = kubevirtNodeService.node(router.electedGateway());
                         if (newGw == null) {
                             return;
                         }
-
-                        setFloatingIpRulesForFip(router, fip, oldGw, false);
-
                         setFloatingIpRulesForFip(router, fip, newGw, true);
                         processGarpPacketForFloatingIp(fip, newGw);
+                        KubevirtNode oldGw = kubevirtNodeService.node(disAssociatedGateway);
 
-            });
+                        if (oldGw == null) {
+                            return;
+                        }
+                        setFloatingIpRulesForFip(router, fip, oldGw, false);
+                    });
         }
 
         private void processGatewayNodeAttachment(KubevirtRouter router, String gatewayName) {
-            kubevirtRouterService.floatingIps().forEach(fip -> {
-                if (fip.routerName().equals(router.name())) {
-                    KubevirtNode gw = kubevirtNodeService.node(gatewayName);
-                    if (gw != null) {
-                        setFloatingIpRulesForFip(router, fip, gw, true);
-                    }
-                }
-            });
+            kubevirtRouterService.floatingIpsByRouter(router.name())
+                    .forEach(fip -> {
+                        KubevirtNode gw = kubevirtNodeService.node(gatewayName);
+                        if (gw != null) {
+                            setFloatingIpRulesForFip(router, fip, gw, true);
+                        }
+                    });
         }
 
         private void processGatewayNodeDetachment(KubevirtRouter router, String gatewayName) {
-            kubevirtRouterService.floatingIps().forEach(fip -> {
-                if (fip.routerName().equals(router.name())) {
-                    KubevirtNode gw = kubevirtNodeService.node(gatewayName);
-                    if (gw != null) {
-                        setFloatingIpRulesForFip(router, fip, gw, false);
-                    }
-                }
-            });
+            kubevirtRouterService.floatingIpsByRouter(router.name())
+                    .forEach(fip -> {
+                        KubevirtNode gw = kubevirtNodeService.node(gatewayName);
+                        if (gw != null) {
+                            setFloatingIpRulesForFip(router, fip, gw, false);
+                        }
+                    });
         }
 
         private void processFloatingIpAssociation(KubevirtRouter router, KubevirtFloatingIp floatingIp) {
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
index b829980..c3ba661 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtNetworkHandler.java
@@ -1088,6 +1088,8 @@
             if (!isRelevantHelper()) {
                 return;
             }
+            log.info("###### processRouterGatewayNodeAttached called for router {} and new router is {}",
+                    router.name(), associatedGateway);
 
             KubevirtNode gatewayNode = nodeService.node(associatedGateway);
             if (gatewayNode == null) {
@@ -1151,7 +1153,7 @@
                 KubevirtNetwork network = networkService.network(networkName);
 
                 if (network != null) {
-                    initGatewayNodeForInternalNetwork(network, router, oldGatewayNode, true);
+                    initGatewayNodeForInternalNetwork(network, router, newGatewayNode, true);
                 }
             });
         }
@@ -1263,10 +1265,10 @@
                 case KUBEVIRT_NODE_COMPLETE:
                     eventExecutor.execute(() -> processNodeCompletion(event.subject()));
                     break;
+                case KUBEVIRT_NODE_INCOMPLETE:
                 case KUBEVIRT_NODE_REMOVED:
                     eventExecutor.execute(() -> processNodeDeletion(event.subject()));
                     break;
-                case KUBEVIRT_NODE_INCOMPLETE:
                 case KUBEVIRT_NODE_UPDATED:
                 default:
                     // do nothing
@@ -1304,19 +1306,6 @@
                 }
             } else if (node.type().equals(GATEWAY)) {
                 updateGatewayNodeForRouter();
-                for (KubevirtNetwork network : networkService.networks()) {
-                    switch (network.type()) {
-                        case FLAT:
-                        case VLAN:
-                            break;
-                        case VXLAN:
-                        case GRE:
-                        case GENEVE:
-                        default:
-                            // do nothing
-                            break;
-                    }
-                }
             }
         }
 
@@ -1324,22 +1313,20 @@
             if (!isRelevantHelper()) {
                 return;
             }
-
             if (node.type().equals(GATEWAY)) {
+                kubevirtRouterService.routers()
+                        .stream()
+                        .filter(router -> router.electedGateway().equals(node.hostname()))
+                        .forEach(router -> {
+                            router.internal().forEach(networkName -> {
+                                KubevirtNetwork network = networkService.network(networkName);
+
+                                if (network != null) {
+                                    initGatewayNodeForInternalNetwork(network, router, node, false);
+                                }
+                            });
+                        });
                 updateGatewayNodeForRouter();
-                for (KubevirtNetwork network : networkService.networks()) {
-                    switch (network.type()) {
-                        case FLAT:
-                        case VLAN:
-                            break;
-                        case VXLAN:
-                        case GRE:
-                        case GENEVE:
-                        default:
-                            // do nothing
-                            break;
-                    }
-                }
             }
         }
 
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
index 1e5260b..40f492d 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingArpHandler.java
@@ -235,8 +235,10 @@
                     eventExecutor.execute(() -> processRouterExternalNetAttachedOrGwAttached(event.subject()));
                     break;
                 case KUBEVIRT_ROUTER_REMOVED:
+                    eventExecutor.execute(() -> processRouterRemoved(event.subject()));
+                    break;
                 case KUBEVIRT_ROUTER_EXTERNAL_NETWORK_DETACHED:
-                    eventExecutor.execute(() -> processRouterRemovedOrExternalNetDetached(event.subject(),
+                    eventExecutor.execute(() -> processRouterExternalNetDetached(event.subject(),
                             event.externalIp(), event.externalPeerRouterIp()));
                     break;
                 case KUBEVIRT_GATEWAY_NODE_DETACHED:
@@ -273,8 +275,9 @@
             }
         }
 
-        private void processRouterRemovedOrExternalNetDetached(KubevirtRouter router, String routerSnatIp,
-                                                               String peerRouterIp) {
+        private void processRouterExternalNetDetached(KubevirtRouter router, String routerSnatIp,
+                                                      String peerRouterIp) {
+            log.info("processRouterRemovedOrExternalNetDetached called");
             if (!isRelevantHelper()) {
                 return;
             }
@@ -294,13 +297,42 @@
                     IpAddress.valueOf(peerRouterIp), gatewayNode.hostname(), false);
         }
 
+
+        private void processRouterRemoved(KubevirtRouter router) {
+            if (!isRelevantHelper()) {
+                return;
+            }
+            if (router.electedGateway() == null) {
+                return;
+            }
+            KubevirtNode gatewayNode = kubevirtNodeService.node(router.electedGateway());
+            if (gatewayNode == null) {
+                return;
+            }
+
+            String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
+            if (routerSnatIp == null) {
+                return;
+            }
+
+            IpAddress peerRouterIp = router.peerRouter().ipAddress();
+            if (peerRouterIp == null) {
+                return;
+            }
+
+            setRuleArpRequestToController(IpAddress.valueOf(routerSnatIp),
+                    peerRouterIp, gatewayNode.hostname(), false);
+        }
+
         private void processRouterGatewayNodeDetached(KubevirtRouter router, String detachedGatewayNode) {
             if (!isRelevantHelper()) {
                 return;
             }
+
             if (detachedGatewayNode == null) {
                 return;
             }
+
             String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
             if (routerSnatIp == null) {
                 return;
diff --git a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
index 2b99937..5e0aa64 100644
--- a/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
+++ b/apps/kubevirt-networking/app/src/main/java/org/onosproject/kubevirtnetworking/impl/KubevirtRoutingSnatHandler.java
@@ -675,6 +675,23 @@
             if (!router.external().isEmpty() && router.peerRouter() != null) {
                 initGatewayNodeSnatForRouter(router, router.electedGateway(), false);
             }
+            KubevirtNode gatewayNode = kubevirtNodeService.node(router.electedGateway());
+
+            router.internal()
+                    .stream()
+                    .filter(networkId -> kubevirtNetworkService.network(networkId) != null)
+                    .map(kubevirtNetworkService::network)
+                    .forEach(network -> {
+                        String routerSnatIp = router.external().keySet().stream().findAny().orElse(null);
+                        if (routerSnatIp == null) {
+                            return;
+                        }
+
+                        kubevirtPortService.ports(network.networkId()).forEach(kubevirtPort -> {
+                            setStatefulSnatDownStreamRuleForKubevirtPort(router,
+                                    gatewayNode, kubevirtPort, false);
+                        });
+                    });
         }
 
         private void processRouterUpdate(KubevirtRouter router) {
diff --git a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
index e7d3613..de45151 100644
--- a/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
+++ b/apps/kubevirt-node/app/src/main/java/org/onosproject/kubevirtnode/impl/DefaultKubevirtNodeHandler.java
@@ -51,6 +51,7 @@
 import org.onosproject.net.device.DeviceEvent;
 import org.onosproject.net.device.DeviceListener;
 import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.ovsdb.controller.OvsdbClientService;
 import org.onosproject.ovsdb.controller.OvsdbController;
 import org.osgi.service.component.ComponentContext;
@@ -152,6 +153,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected ComponentConfigService componentConfigService;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected FlowRuleService flowRuleService;
+
     /** OVSDB server listen port. */
     private int ovsdbPortNum = OVSDB_PORT_NUM_DEFAULT;
 
@@ -459,6 +463,10 @@
             return;
         }
 
+        // purges all the flow rules installed on the node
+        flowRuleService.purgeFlowRules(node.intgBridge());
+        flowRuleService.purgeFlowRules(node.tunBridge());
+
         // unprovision physical interfaces from the node
         // this procedure includes detaching physical port from physical bridge,
         // remove patch ports from br-int, removing physical bridge