Bug 4917 For fixing SG dangling flows. Extended port cache logic to 10/34410/5
authorAswin Suryanarayanan <aswin.suryanarayanan@hp.com>
Thu, 11 Feb 2016 01:22:42 +0000 (06:52 +0530)
committerSam Hague <shague@redhat.com>
Thu, 11 Feb 2016 23:37:07 +0000 (23:37 +0000)
TenantNetworkManagerImpl and SouthboundHandler.

Added cache for NeutronNetwork. Changed the portcLeanUpCache from set to
map as the entries were not getting cleaned up from the cache.

Change-Id: Id02f2ff85d3d67845d8b618fbcdfded1f7958553
Signed-off-by: Aswin Suryanarayanan <aswin.suryanarayanan@hp.com>
(cherry picked from commit c619afb3a9f8d93b05225daf0b257c28079d4216)

openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/SouthboundHandler.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/DistributedArpService.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3Adapter.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImpl.java
openstack/net-virt/src/main/java/org/opendaylight/ovsdb/openstack/netvirt/impl/TenantNetworkManagerImpl.java
openstack/net-virt/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/impl/NeutronL3AdapterTest.java
openstack/net-virt/src/test/java/org/opendaylight/ovsdb/openstack/netvirt/impl/SecurityServicesImplTest.java

index 628e99d6805ceb79d2432bb694de687a95a22281..02d0ea75471a65fef07f582169ec1fd1de256400 100644 (file)
@@ -186,6 +186,7 @@ public class SouthboundHandler extends AbstractHandler
         if (neutronPort != null) {
             LOG.debug("Clean up the NeutronPortCache ");
             neutronL3Adapter.removePortFromCleanupCache(neutronPort);
+            neutronL3Adapter.removeNetworkFromCleanupCache(neutronPort.getNetworkUUID());
         } else {
             LOG.trace("Nothing to Clean up in the NeutronPortCache ");
         }
index ea894a0f46c0ba7645d87a288a8b24a77beb3749..301e3ef22afab5cfcad333c8c1092e3f84903c56 100644 (file)
@@ -13,6 +13,7 @@ import java.net.UnknownHostException;
 import java.util.List;
 
 import com.google.common.base.Preconditions;
+
 import org.opendaylight.ovsdb.openstack.netvirt.api.Action;
 import org.opendaylight.ovsdb.openstack.netvirt.api.ArpProvider;
 import org.opendaylight.ovsdb.openstack.netvirt.api.Southbound;
@@ -47,6 +48,7 @@ public class DistributedArpService implements ConfigInterface {
     private volatile INeutronNetworkCRUD neutronNetworkCache;
     private volatile INeutronPortCRUD neutronPortCache;
     private volatile ArpProvider arpProvider;
+    private volatile NeutronL3Adapter neutronL3Adapter;
 
     private Southbound southbound;
     private Boolean flgDistributedARPEnabled = true;
@@ -138,7 +140,10 @@ public class DistributedArpService implements ConfigInterface {
     private void handleNeutornPortForArp(NeutronPort neutronPort, Action action) {
 
         final String networkUUID = neutronPort.getNetworkUUID();
-        final NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
+        NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(networkUUID);
+        if (null == neutronNetwork) {
+            neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(networkUUID);
+        }
         final String providerSegmentationId = neutronNetwork != null ?
                                               neutronNetwork.getProviderSegmentationID() : null;
         final String tenantMac = neutronPort.getMacAddress();
@@ -223,6 +228,8 @@ public class DistributedArpService implements ConfigInterface {
                 (NodeCacheManager) ServiceHelper.getGlobalInstance(NodeCacheManager.class, this);
         southbound =
                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
+        neutronL3Adapter =
+                (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
         initMembers();
     }
 
index 37321159912cdd68279275a0408cb452cc06f4b4..6696b269653f7369b819fb7b4dd015516e667e43 100644 (file)
@@ -134,7 +134,8 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
     private String externalRouterMac;
     private Boolean enabled = false;
     private Boolean isCachePopulationDone = false;
-    private Set<NeutronPort> portCleanupCache;
+    private Map<String, NeutronPort> portCleanupCache;
+    private Map<String, NeutronNetwork> networkCleanupCache;
 
     private Southbound southbound;
     private DistributedArpService distributedArpService;
@@ -170,7 +171,8 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
         } else {
             LOG.debug("OVSDB L3 forwarding is disabled");
         }
-        this.portCleanupCache = new HashSet<>();
+        this.portCleanupCache = new HashMap<>();
+        this.networkCleanupCache = new HashMap<>();
     }
 
     //
@@ -404,6 +406,9 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
      */
     public void handleNeutronSubnetEvent(final NeutronSubnet subnet, Action action) {
         LOG.debug("Neutron subnet {} event : {}", action, subnet.toString());
+        if (action == Action.ADD) {
+            this.storeNetworkInCleanupCache(neutronNetworkCache.getNetwork(subnet.getNetworkUUID()));
+        }
     }
 
     /**
@@ -436,6 +441,9 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
                 this.triggerGatewayMacResolver(neutronPort);
             }else{
                 NeutronNetwork externalNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
+                if (null == externalNetwork) {
+                    externalNetwork = this.getNetworkFromCleanupCache(neutronPort.getNetworkUUID());
+                }
 
                 if (externalNetwork != null && externalNetwork.isRouterExternal()) {
                     final NeutronSubnet externalSubnet = getExternalNetworkSubnet(neutronPort);
@@ -752,6 +760,9 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
      */
     public void handleNeutronNetworkEvent(final NeutronNetwork neutronNetwork, Action action) {
         LOG.debug("neutronNetwork {}: network: {}", action, neutronNetwork);
+        if (action == Action.UPDATE) {
+            this.updateNetworkInCleanupCache(neutronNetwork);
+        }
     }
 
     //
@@ -1482,7 +1493,7 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
 
 
     private void storePortInCleanupCache(NeutronPort port) {
-        this.portCleanupCache.add(port);
+        this.portCleanupCache.put(port.getPortUUID(),port);
     }
 
 
@@ -1492,25 +1503,69 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
     }
 
     public void removePortFromCleanupCache(NeutronPort port) {
-        this.portCleanupCache.remove(port);
+        this.portCleanupCache.remove(port.getPortUUID());
     }
 
-    public Set<NeutronPort> getPortCleanupCache() {
+    public Map<String, NeutronPort> getPortCleanupCache() {
         return this.portCleanupCache;
     }
 
     public NeutronPort getPortFromCleanupCache(String portid) {
-        for (NeutronPort neutronPort : this.portCleanupCache) {
-            if (neutronPort.getPortUUID() != null ) {
-                if (neutronPort.getPortUUID().equals(portid)) {
-                    LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", portid);
-                    return neutronPort;
-                }
+        for (String neutronPortUuid : this.portCleanupCache.keySet()) {
+            if (neutronPortUuid.equals(portid)) {
+                LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", portid);
+                return this.portCleanupCache.get(neutronPortUuid);
             }
         }
         return null;
     }
 
+    private void storeNetworkInCleanupCache(NeutronNetwork network) {
+        this.networkCleanupCache.put(network.getNetworkUUID(), network);
+    }
+
+
+    private void updateNetworkInCleanupCache(NeutronNetwork network) {
+        for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
+            if (neutronNetworkUuid.equals(network.getNetworkUUID())) {
+                this.networkCleanupCache.remove(neutronNetworkUuid);
+            }
+        }
+        this.networkCleanupCache.put(network.getNetworkUUID(), network);
+    }
+
+    public void removeNetworkFromCleanupCache(String networkid) {
+        NeutronNetwork network = null;
+        for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
+            if (neutronNetworkUuid.equals(networkid)) {
+                network = networkCleanupCache.get(neutronNetworkUuid);
+                break;
+            }
+        }
+        if (network != null) {
+            for (String neutronPortUuid:this.portCleanupCache.keySet()) {
+                if (this.portCleanupCache.get(neutronPortUuid).getNetworkUUID().equals(network.getNetworkUUID())) {
+                    LOG.info("This network is used by another port", network);
+                    return;
+                }
+            }
+            this.networkCleanupCache.remove(network.getNetworkUUID());
+        }
+    }
+
+    public Map<String, NeutronNetwork> getNetworkCleanupCache() {
+        return this.networkCleanupCache;
+    }
+
+    public NeutronNetwork getNetworkFromCleanupCache(String networkid) {
+        for (String neutronNetworkUuid:this.networkCleanupCache.keySet()) {
+            if (neutronNetworkUuid.equals(networkid)) {
+                LOG.info("getPortFromCleanupCache: Matching NeutronPort found {}", networkid);
+                return networkCleanupCache.get(neutronNetworkUuid);
+            }
+        }
+        return null;
+    }
     /**
      * Return String that represents OF port with marker explicitly provided (reverse of MatchUtils:parseExplicitOFPort)
      *
@@ -1520,7 +1575,20 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
     public static String encodeExcplicitOFPort(Long ofPort) {
         return "OFPort|" + ofPort.toString();
     }
-
+    private void initNetworkCleanUpCache() {
+        if (this.neutronNetworkCache != null) {
+            for (NeutronNetwork neutronNetwork : neutronNetworkCache.getAllNetworks()) {
+                networkCleanupCache.put(neutronNetwork.getNetworkUUID(), neutronNetwork);
+            }
+        }
+    }
+    private void initPortCleanUpCache() {
+        if (this.neutronPortCache != null) {
+            for (NeutronPort neutronPort : neutronPortCache.getAllPorts()) {
+                portCleanupCache.put(neutronPort.getPortUUID(), neutronPort);
+            }
+        }
+    }
     @Override
     public void setDependencies(ServiceReference serviceReference) {
         eventDispatcher =
@@ -1558,8 +1626,10 @@ public class NeutronL3Adapter extends AbstractHandler implements GatewayMacResol
     public void setDependencies(Object impl) {
         if (impl instanceof INeutronNetworkCRUD) {
             neutronNetworkCache = (INeutronNetworkCRUD)impl;
+            initNetworkCleanUpCache();
         } else if (impl instanceof INeutronPortCRUD) {
             neutronPortCache = (INeutronPortCRUD)impl;
+            initPortCleanUpCache();
         } else if (impl instanceof INeutronSubnetCRUD) {
             neutronSubnetCache = (INeutronSubnetCRUD)impl;
         } else if (impl instanceof INeutronFloatingIPCRUD) {
index f6bcd574655c636e46f2ac7fa95bdf00f40f7b65..11e8943a1d8d04fe0e465d7c5629a47d633649a9 100644 (file)
@@ -397,7 +397,8 @@ public class SecurityServicesImpl implements ConfigInterface, SecurityServicesMa
         /*For every port check whether security grouplist contains the current
          * security group.*/
         try {
-            for (NeutronPort neutronPort:neutronL3Adapter.getPortCleanupCache()) {
+            for (String neutronPortUuid:neutronL3Adapter.getPortCleanupCache().keySet()) {
+                NeutronPort neutronPort = neutronL3Adapter.getPortCleanupCache().get(neutronPortUuid);
                 if (!neutronPort.getDeviceOwner().contains("compute")) {
                     LOG.debug("getVMListForSecurityGroup : the port {} is not "
                             + "compute port belongs to {}", neutronPort.getID(), neutronPort.getDeviceOwner());
@@ -438,6 +439,9 @@ public class SecurityServicesImpl implements ConfigInterface, SecurityServicesMa
                 return;
             }
             NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
+            if (null == neutronNetwork) {
+                neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(port.getNetworkUUID());
+            }
             if (neutronNetwork == null) {
                 return;
             }
@@ -480,6 +484,9 @@ public class SecurityServicesImpl implements ConfigInterface, SecurityServicesMa
                 return;
             }
             NeutronNetwork neutronNetwork = neutronNetworkCache.getNetwork(port.getNetworkUUID());
+            if (null == neutronNetwork) {
+                neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(port.getNetworkUUID());
+            }
             if (neutronNetwork == null) {
                 return;
             }
index e9ac3fe0ab2bfe8b10e9b8827d7cb7ea8889a565..5ca124df5e8c2905bdeab83f37bc976403b12a76 100644 (file)
@@ -24,7 +24,6 @@ import org.opendaylight.ovsdb.openstack.netvirt.api.VlanConfigurationCache;
 import org.opendaylight.ovsdb.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -35,6 +34,7 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
     private INeutronPortCRUD neutronPortCache;
     private VlanConfigurationCache vlanConfigurationCache;
     private Southbound southbound;
+    private volatile NeutronL3Adapter neutronL3Adapter;
 
     @Override
     public int getInternalVlan(Node node, String networkId) {
@@ -108,6 +108,13 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
                 return network.getNetworkUUID();
             }
         }
+        for (String networkUuid : neutronL3Adapter.getNetworkCleanupCache().keySet()) {
+            NeutronNetwork network = neutronL3Adapter.getNetworkFromCleanupCache(networkUuid);
+            if (network.getProviderSegmentationID() != null &&
+                    network.getProviderSegmentationID().equalsIgnoreCase(segmentationId)) {
+                return network.getNetworkUUID();
+            }
+        }
         return null;
     }
 
@@ -122,8 +129,15 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
                 Constants.EXTERNAL_ID_INTERFACE_ID);
         if (neutronPortId != null) {
             NeutronPort neutronPort = neutronPortCache.getPort(neutronPortId);
+            if ( null == neutronPort) {
+                LOG.debug("neutronPort is null, checking the clean up cache.");
+                neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
+            }
             if (neutronPort != null) {
                 neutronNetwork = neutronNetworkCache.getNetwork(neutronPort.getNetworkUUID());
+                if (null == neutronNetwork) {
+                    neutronNetwork = neutronL3Adapter.getNetworkFromCleanupCache(neutronPort.getNetworkUUID());
+                }
                 if (neutronNetwork != null) {
                     LOG.debug("mapped to {}", neutronNetwork);
                 } else {
@@ -150,6 +164,10 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
                 Constants.EXTERNAL_ID_INTERFACE_ID);
         if (neutronPortId != null) {
             neutronPort = neutronPortCache.getPort(neutronPortId);
+            if (null == neutronPort) {
+                LOG.debug("neutronPort is null checking the clean up cache.");
+                neutronPort = neutronL3Adapter.getPortFromCleanupCache(neutronPortId);
+            }
         }
         if (neutronPort != null) {
             LOG.debug("mapped to {}", neutronPort);
@@ -172,6 +190,10 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
 
     private boolean isInterfacePresentInTenantNetwork (String portId, String networkId) {
         NeutronPort neutronPort = neutronPortCache.getPort(portId);
+        if (null == neutronPort) {
+            LOG.debug("neutronPort is null checking the clean up cache.");
+            neutronPort = neutronL3Adapter.getPortFromCleanupCache(portId);
+        }
         return neutronPort != null && neutronPort.getNetworkUUID().equalsIgnoreCase(networkId);
     }
 
@@ -181,6 +203,8 @@ public class TenantNetworkManagerImpl implements ConfigInterface, TenantNetworkM
                 (VlanConfigurationCache) ServiceHelper.getGlobalInstance(VlanConfigurationCache.class, this);
         southbound =
                 (Southbound) ServiceHelper.getGlobalInstance(Southbound.class, this);
+        neutronL3Adapter =
+                (NeutronL3Adapter) ServiceHelper.getGlobalInstance(NeutronL3Adapter.class, this);
     }
 
     @Override
index cf6545d9fb53a6a9191979d39a8269017e972877..3e1dffdf89be0ab5bd0199a003d0559f17756588 100644 (file)
@@ -132,14 +132,20 @@ public class NeutronL3AdapterTest {
 
     @Test
     public void testhandleNeutronSubnetEvent() throws Exception {
-        // Nothing to be done here
+        Map<String,NeutronNetwork> networkCleanupCache = new HashMap<>();
+        INeutronNetworkCRUD neutronNetworkCache = mock(INeutronNetworkCRUD.class);
+        NeutronNetwork neutronNetwork = mock(NeutronNetwork.class);
+        when(neutronNetworkCache.getNetwork(anyString())).thenReturn(neutronNetwork);
+        // Mock variables
+        MemberModifier.field(NeutronL3Adapter.class, "networkCleanupCache").set(neutronL3Adapter , networkCleanupCache);
+        MemberModifier.field(NeutronL3Adapter.class, "neutronNetworkCache").set(neutronL3Adapter , neutronNetworkCache);
         neutronL3Adapter.handleNeutronSubnetEvent(mock(NeutronSubnet.class), Action.ADD);
     }
 
     @Test
     public void testHandleNeutronPortEvent() throws Exception {
         Map<String, NeutronRouter_Interface> subnetIdToRouterInterfaceCache = new HashMap<>();
-        Set<NeutronPort> portCleanupCache = new HashSet<>();
+        Map<String,NeutronPort> portCleanupCache = new HashMap<>();
         // Mock variables
         Neutron_IPs neutronIP = mock(Neutron_IPs.class);
         when(neutronIP.getSubnetUUID()).thenReturn(UUID);
@@ -399,6 +405,9 @@ public class NeutronL3AdapterTest {
     @Test
     public void testHandleNeutronNetworkEvent() throws Exception {
         // Nothing to be done here
+        Map<String,NeutronNetwork> networkCleanupCache = new HashMap<>();
+        // Mock variables
+        MemberModifier.field(NeutronL3Adapter.class, "networkCleanupCache").set(neutronL3Adapter , networkCleanupCache);
         Whitebox.invokeMethod(neutronL3Adapter, "handleNeutronNetworkEvent", mock(NeutronNetwork.class), Action.ADD);
     }
 
@@ -858,6 +867,31 @@ public class NeutronL3AdapterTest {
 
     @Test
     public void testSetDependencies() throws Exception {
+        Map<String,NeutronNetwork> networkCleanupCache = new HashMap<>();
+        INeutronNetworkCRUD neutronNetworkCache = mock(INeutronNetworkCRUD.class);
+        NeutronNetwork neutronNetwork = mock(NeutronNetwork.class);
+        List <NeutronNetwork> neutronNetworkList = new ArrayList<NeutronNetwork>();
+        neutronNetworkList.add(neutronNetwork);
+        when(neutronNetworkCache.getAllNetworks()).thenReturn(neutronNetworkList);
+
+        Map<String,NeutronPort> portCleanupCache = new HashMap<>();
+        INeutronPortCRUD neutronPortCache = mock(INeutronPortCRUD.class);
+        NeutronPort neutronPort = mock(NeutronPort.class);
+        List <NeutronPort> neutronPortList = new ArrayList<NeutronPort>();
+        neutronPortList.add(neutronPort);
+        when(neutronPortCache.getAllPorts()).thenReturn(neutronPortList);
+        // Mock variables
+        MemberModifier.field(NeutronL3Adapter.class, "networkCleanupCache").set(neutronL3Adapter , networkCleanupCache);
+        MemberModifier.field(NeutronL3Adapter.class, "neutronNetworkCache").set(neutronL3Adapter , neutronNetworkCache);
+        MemberModifier.field(NeutronL3Adapter.class, "portCleanupCache").set(neutronL3Adapter , portCleanupCache);
+        MemberModifier.field(NeutronL3Adapter.class, "neutronPortCache").set(neutronL3Adapter , neutronPortCache);
+
+
+        when(neutronPort.getDeviceOwner()).thenReturn(OWNER_ROUTER_INTERFACE);
+        MemberModifier.field(NeutronL3Adapter.class, "portCleanupCache").set(neutronL3Adapter , portCleanupCache);
+
+
+
         EventDispatcher eventDispatcher = mock(EventDispatcher.class);
         TenantNetworkManager tenantNetworkManager = mock(TenantNetworkManager.class);
         ConfigurationService configurationService = mock(ConfigurationService.class);
index 6506431d2731d73d340c3f6b139fe3c3c6e1cfdf..cc60edff81b99b4b1c8409222ff6a68fc9f3e7e2 100644 (file)
@@ -19,8 +19,10 @@ import static org.mockito.Mockito.when;
 
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -363,12 +365,12 @@ public class SecurityServicesImplTest {
      */
     @Test
     public void testGetVmListForSecurityGroup() {
-        List<NeutronPort> portList = new ArrayList<>();
-        portList.add(neutronPort_Vm1);
-        portList.add(neutronPort_Vm2);
-        portList.add(neutronPort_Vm3);
-        portList.add(neutronPort_Dhcp);
-        when(neutronL3Adapter.getPortCleanupCache()).thenReturn(new HashSet<NeutronPort>(portList));
+        Map<String,NeutronPort> portMap = new HashMap<>();
+        portMap.put("Uuid1",neutronPort_Vm1);
+        portMap.put("Uuid2",neutronPort_Vm2);
+        portMap.put("Uuid3",neutronPort_Vm3);
+        portMap.put("Uuid4",neutronPort_Dhcp);
+        when(neutronL3Adapter.getPortCleanupCache()).thenReturn(portMap);
         List<Neutron_IPs> ipList = securityServicesImpl.getVmListForSecurityGroup(NEUTRON_PORT_ID_VM_1, SECURITY_GROUP_ID_2);
         assertEquals(ipList,neutron_IPs_2);
     }