Bug 7333: Fix for Arp flows were not deleted for DHCP port in Control node. 94/49194/2
authorhari.pr <hari.pr@hcl.com>
Fri, 9 Dec 2016 19:03:55 +0000 (00:33 +0530)
committerSam Hague <shague@redhat.com>
Sun, 11 Dec 2016 17:25:45 +0000 (17:25 +0000)
    * Problem: when network is removed, arp flows were not deleted for DHCP port in control node.
    * Fix: fixed Ips for Dhcp port has been retrieved from local cache and used for deletion.

Change-Id: I6617a9a29f6be5e77d0362f112e38cb74c08df48
Signed-off-by: hari.pr <hari.pr@hcl.com>
openstack/net-virt/src/main/java/org/opendaylight/netvirt/openstack/netvirt/impl/DistributedArpService.java

index 9c48e1aba35d7d05af4bd7a5a367e175a240a9b3..f9b661a4528dca5ec1ef4ec084cdce9b6ace8a30 100644 (file)
@@ -63,6 +63,8 @@ public class DistributedArpService implements ConfigInterface {
     private Southbound southbound;
     private Boolean flgDistributedARPEnabled = true;
 
+    private HashMap<String, List<Neutron_IPs>> dhcpPortIpCache = new HashMap();
+
     static ThreadFactory threadFactory = new ThreadFactoryBuilder()
             .setNameFormat("DistributedArp-%d").build();
     static ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS, threadFactory);
@@ -156,15 +158,12 @@ public class DistributedArpService implements ConfigInterface {
 
         final String networkUUID = neutronPort.getNetworkUUID();
         NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
-        String owner = neutronPort.getDeviceOwner();
         if (null == neutronNetwork) {
             neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(networkUUID);
         }
         final String providerSegmentationId = neutronNetwork != null ?
                                               neutronNetwork.getProviderSegmentationID() : null;
-        final String macAddress = neutronPort.getMacAddress();
-        if (providerSegmentationId == null || providerSegmentationId.isEmpty() ||
-            macAddress == null || macAddress.isEmpty()) {
+        if (providerSegmentationId == null || providerSegmentationId.isEmpty()) {
             // done: go no further w/out all the info needed...
             return;
         }
@@ -182,6 +181,15 @@ public class DistributedArpService implements ConfigInterface {
                 String providerSegmentationId, Action actionToPerform) {
         String owner = neutronPort.getDeviceOwner();
         boolean isRouterInterface = owner != null && owner.equals(ROUTER_INTERFACE_DEVICE_OWNER);
+        boolean isDhcpPort = owner != null && owner.equals(DHCP_DEVICE_OWNER);
+        List<Neutron_IPs> fixedIps = neutronPort.getFixedIPs();
+        if((null == fixedIps || fixedIps.isEmpty())
+                        && actionToPerform == Action.DELETE && isDhcpPort){
+            fixedIps = dhcpPortIpCache.get(neutronPort.getPortUUID());
+            if(fixedIps == null) {
+                return;
+            }
+        }
         List <NeutronPort> neutronPortList = new ArrayList();
         // Arp rule is only needed when segmentation exists in the given node (bug 4752)
         // or in case the port is a router interface
@@ -192,12 +200,17 @@ public class DistributedArpService implements ConfigInterface {
         if (neutronPortList.size() == 1) {
             existingPort = neutronPortList.get(0);
         }
+        final String macAddress = neutronPort.getMacAddress();
+        if (macAddress == null || macAddress.isEmpty()) {
+            // done: go no further w/out all the info needed...
+            return;
+        }
         final Long dpid = getDatapathIdIntegrationBridge(node);
         if (dpid == null) {
             return;
         }
         if (arpNeeded) {
-            // For a node Arp rule is added for all ports only when the list of NeutronPort List size is 1.
+            // For a node Arp rule is added for all ports only when the list of NeutronPorts size is 1.
             // If not Arp is added for the current port only (bug 6998)
             if (neutronPortList.size() == 1 && neutronPort.getPortUUID().equalsIgnoreCase(existingPort.getPortUUID())) {
                 for (NeutronPort port : neutronPortCache.getAllPorts()) {
@@ -209,14 +222,13 @@ public class DistributedArpService implements ConfigInterface {
                                     programStaticRuleStage1(dpid, providerSegmentationId, portMacAddress,
                                             portIpAddress, actionForNode));
                         } catch (RejectedExecutionException ex) {
-                            LOG.error("handleArpRule : unable to accept execution.", ex);
+                            LOG.error("handleArpRule : unable to accept execution." + ex);
                             programStaticRuleStage1(dpid, providerSegmentationId, portMacAddress,
                                     portIpAddress, actionForNode);
                         }
                     }
                 }
             } else {
-                final String macAddress = neutronPort.getMacAddress();
                 for (Neutron_IPs neutronIPAddr : neutronPort.getFixedIPs()) {
                     final String ipAddress = neutronIPAddr.getIpAddress();
                     try {
@@ -224,14 +236,33 @@ public class DistributedArpService implements ConfigInterface {
                                 programStaticRuleStage1(dpid, providerSegmentationId, macAddress,
                                         ipAddress, actionForNode));
                     } catch (RejectedExecutionException ex) {
-                        LOG.error("handleArpRule : unable to accept execution.", ex);
+                        LOG.error("handleArpRule : unable to accept execution." + ex);
                         programStaticRuleStage1(dpid, providerSegmentationId, macAddress,
                                 ipAddress, actionForNode);
                     }
                 }
             }
         } else {
-            if (neutronPortList.size() == 0 || neutronPortList.isEmpty()) {
+            if (actionToPerform == Action.DELETE) {
+                // Arp flows for DHCP port should remove from control node
+                // when network removed (bug 7333).
+                if (isDhcpPort) {
+                    for (Neutron_IPs neutronIP : fixedIps) {
+                        final String dhcpIpAddress = neutronIP.getIpAddress();
+                        if (dhcpIpAddress.isEmpty()) {
+                          continue;
+                        }
+                        try {
+                                executor.submit(() ->
+                                        programStaticRuleStage1(dpid, providerSegmentationId, macAddress,
+                                                dhcpIpAddress, actionToPerform));
+                            } catch (RejectedExecutionException ex) {
+                                LOG.error("handleArpRule : unable to accept execution." + ex);
+                                programStaticRuleStage1(dpid, providerSegmentationId, macAddress,
+                                        dhcpIpAddress, actionToPerform);
+                            }
+                    }
+                }
                 for (NeutronPort delPort : neutronPortCache.getAllPorts()) {
                     if (!delPort.getDeviceOwner().equalsIgnoreCase(ROUTER_INTERFACE_DEVICE_OWNER)) {
                         final String delMacAddress = delPort.getMacAddress();
@@ -246,17 +277,22 @@ public class DistributedArpService implements ConfigInterface {
                             try {
                                 executor.submit(() ->
                                         programStaticRuleStage1(dpid, providerSegmentationId, delMacAddress,
-                                                delIpAddress, Action.DELETE));
-                            } catch (RejectedExecutionException ree2) {
-                                LOG.error("handleArpRule : unable to accept execution.", ree2);
+                                                delIpAddress, actionToPerform));
+                            } catch (RejectedExecutionException ex) {
+                                LOG.error("handleArpRule : unable to accept execution." + ex);
                                 programStaticRuleStage1(dpid, providerSegmentationId, delMacAddress,
-                                        delIpAddress, Action.DELETE);
+                                        delIpAddress, actionToPerform);
                             }
                         }
                     }
                 }
             }
         }
+        if(isDhcpPort && actionToPerform == Action.ADD){
+            dhcpPortIpCache.put(neutronPort.getPortUUID(), fixedIps);
+        } else if (isDhcpPort && actionToPerform == Action.DELETE) {
+            dhcpPortIpCache.remove(neutronPort.getPortUUID());
+        }
     }
 
     /**