Replace tenantVlanMap with a per Node cache 01/4601/15
authorDave Tucker <dave.j.tucker@hp.com>
Wed, 22 Jan 2014 17:12:33 +0000 (17:12 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 25 Jan 2014 16:45:16 +0000 (16:45 +0000)
Change-Id: I8c2aeb9960443bd9d7e51315f69f499631c91b69
Signed-off-by: Dave Tucker <dave.j.tucker@hp.com>
neutron/src/main/java/org/opendaylight/ovsdb/neutron/NetworkHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/NodeConfiguration.java [new file with mode: 0644]
neutron/src/main/java/org/opendaylight/ovsdb/neutron/SouthboundHandler.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/TenantNetworkManager.java
neutron/src/main/java/org/opendaylight/ovsdb/neutron/provider/OF10ProviderManager.java
neutron/src/test/java/org/opendaylight/ovsdb/neutron/NetworkHandlerTest.java

index ca7a65a059b78f93147940a7c1036dd2d41a1685..8ff8410fa5882971ef82efa5e595699e709c2e9e 100644 (file)
@@ -58,7 +58,7 @@ public class NetworkHandler extends BaseHandler
             return;
         }
 
-        TenantNetworkManager.getManager().networkCreated(network.getID());
+       TenantNetworkManager.getManager().networkCreated(network.getID());
     }
 
     /**
diff --git a/neutron/src/main/java/org/opendaylight/ovsdb/neutron/NodeConfiguration.java b/neutron/src/main/java/org/opendaylight/ovsdb/neutron/NodeConfiguration.java
new file mode 100644 (file)
index 0000000..e0d7677
--- /dev/null
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Dave Tucker (HP) - Replace tenantVlanMap with a per Node cache
+ *******************************************************************************/
+
+package org.opendaylight.ovsdb.neutron;
+
+import org.opendaylight.controller.sal.core.Node;
+import org.opendaylight.controller.sal.utils.ServiceHelper;
+import org.opendaylight.ovsdb.lib.notation.UUID;
+import org.opendaylight.ovsdb.lib.table.Interface;
+import org.opendaylight.ovsdb.lib.table.Port;
+import org.opendaylight.ovsdb.lib.table.internal.Table;
+import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class NodeConfiguration {
+    static final Logger logger = LoggerFactory.getLogger(NodeConfiguration.class);
+    private static final int MAX_VLAN = 4096;
+    private java.util.Queue<Integer> internalVlans = new LinkedList<>();
+    private ConcurrentMap<String, Integer> tenantVlanMap = new ConcurrentHashMap<>();
+
+    public NodeConfiguration(Node node) {
+        for (int i = 1; i < MAX_VLAN ; i++) {
+            internalVlans.add(i);
+        }
+
+        initializeNodeConfiguration(node);
+    }
+
+
+    private void initializeNodeConfiguration(Node node) {
+
+        int vlan = 0;
+        String networkId = new String();
+        OVSDBConfigService ovsdbTable = (OVSDBConfigService) ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+
+        try {
+            Map<String, Table<?>> portRows = ovsdbTable.getRows(node, Port.NAME.getName());
+
+            if (portRows == null){
+                logger.info("Interface table is null for Node {}", node);
+                return;
+            }
+
+            for (Table<?> row : portRows.values()) {
+                Port port = (Port)row;
+
+                BigInteger[] tags = port.getTag().toArray(new BigInteger[0]);
+                if (tags.length == 1)
+                {
+                    //There is only one tag here
+                    vlan = tags[0].intValue();
+                }
+                else {
+                   logger.debug("This port has more {} interfaces", tags.length);
+                   continue;
+                }
+
+                for (UUID ifaceId : port.getInterfaces()) {
+                    Interface iface = (Interface)ovsdbTable.getRow(node, Interface.NAME.getName(), ifaceId.toString());
+
+                    if (iface == null) {
+                        logger.error("Interface table is null for Po");
+                        continue;
+                    }
+
+                    networkId = TenantNetworkManager.getManager().getTenantNetworkForInterface(iface).getNetworkUUID();
+
+                    if (networkId != null) break;
+                }
+
+                if (vlan != 0 && networkId != null) {
+
+                    this.internalVlanInUse(vlan);
+                    this.tenantVlanMap.put(networkId, vlan);
+
+                }
+            }
+        }
+        catch (Exception e) {
+            logger.error("Error getting Port table for Node {}: {}", node, e);
+        }
+    }
+
+    public int assignInternalVlan (String networkId) {
+        Integer mappedVlan = tenantVlanMap.get(networkId);
+        if (mappedVlan != null) return mappedVlan;
+        mappedVlan = internalVlans.poll();
+        if (mappedVlan != null) tenantVlanMap.put(networkId, mappedVlan);
+        return mappedVlan;
+    }
+
+    public void internalVlanInUse (int vlan) {
+        internalVlans.remove(vlan);
+    }
+
+    public int getInternalVlan (String networkId) {
+        Integer vlan = tenantVlanMap.get(networkId);
+        if (vlan == null) return 0;
+        return vlan.intValue();
+    }
+
+}
index 24a06cdd5a71c24739080aa9aff7fcbb4de9af1f..7e0d8bb5884bba950602eed4d66d27a4a7c0c043 100644 (file)
@@ -169,7 +169,7 @@ public class SouthboundHandler extends BaseHandler implements OVSDBInventoryList
             NeutronNetwork network = TenantNetworkManager.getManager().getTenantNetworkForInterface(intf);
             if (network != null && !network.getRouterExternal()) {
                 if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-                    int vlan = TenantNetworkManager.getManager().networkCreated(network.getID());
+                    int vlan = TenantNetworkManager.getManager().networkCreated(node, network.getID());
                     logger.trace("Neutron Network {} Created with Internal Vlan : {}", network.toString(), vlan);
 
                     String portUUID = this.getPortIdForInterface(node, uuid, intf);
index 2cc0f94fb8f2a6b6393ebc757c751fa556eb2daf..b0b98a939c582b8b3b030763662d7ae3da7abb48 100644 (file)
@@ -1,22 +1,21 @@
 /*
- * Copyright (C) 2013 Red Hat, Inc.
+ * Copyright (C) 2013 Red Hat, Inc. and others...
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  *
- * Authors : Madhu Venugopal, Brent Salisbury
+ * Authors : Madhu Venugopal, Brent Salisbury, Dave Tucker
  */
 package org.opendaylight.ovsdb.neutron;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Queue;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.opendaylight.controller.containermanager.ContainerConfig;
 import org.opendaylight.controller.containermanager.ContainerFlowConfig;
@@ -34,9 +33,11 @@ import org.opendaylight.ovsdb.lib.notation.OvsDBSet;
 import org.opendaylight.ovsdb.lib.notation.UUID;
 import org.opendaylight.ovsdb.lib.table.Bridge;
 import org.opendaylight.ovsdb.lib.table.Interface;
+import org.opendaylight.ovsdb.lib.table.Open_vSwitch;
 import org.opendaylight.ovsdb.lib.table.Port;
 import org.opendaylight.ovsdb.lib.table.internal.Table;
 import org.opendaylight.ovsdb.neutron.provider.ProviderNetworkManager;
+import org.opendaylight.ovsdb.plugin.IConnectionServiceInternal;
 import org.opendaylight.ovsdb.plugin.OVSDBConfigService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,18 +45,14 @@ import org.slf4j.LoggerFactory;
 public class TenantNetworkManager {
     static final Logger logger = LoggerFactory.getLogger(TenantNetworkManager.class);
 
-    private static final int MAX_VLAN = 4096;
     public static final String EXTERNAL_ID_VM_ID = "vm-id";
     public static final String EXTERNAL_ID_INTERFACE_ID = "iface-id";
     public static final String EXTERNAL_ID_VM_MAC = "attached-mac";
     private static TenantNetworkManager tenantHelper = new TenantNetworkManager();
-    private Queue<Integer> internalVlans = new LinkedList<Integer>();
-    private Map<String, Integer> tenantVlanMap = new HashMap<String, Integer>();
+    private ConcurrentMap<String, NodeConfiguration> nodeConfigurationCache = new ConcurrentHashMap<>();
+
     private boolean enableContainer = false;
     private TenantNetworkManager() {
-        for (int i = 1; i < MAX_VLAN ; i++) {
-            internalVlans.add(i);
-        }
         String isTenantContainer = System.getProperty("TenantIsContainer");
         if (isTenantContainer != null && isTenantContainer.equalsIgnoreCase("true")) {
             enableContainer =  true;
@@ -66,26 +63,74 @@ public class TenantNetworkManager {
         return tenantHelper;
     }
 
-    private int assignInternalVlan (String networkId) {
-        Integer mappedVlan = tenantVlanMap.get(networkId);
-        if (mappedVlan != null) return mappedVlan;
-        mappedVlan = internalVlans.poll();
-        if (mappedVlan != null) tenantVlanMap.put(networkId, mappedVlan);
-        return mappedVlan;
-    }
+    public int getInternalVlan(Node node, String networkId) {
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return 0;
+        }
 
-    public void internalVlanInUse (int vlan) {
-        internalVlans.remove(vlan);
-    }
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
 
-    public int getInternalVlan (String networkId) {
-        Integer vlan = tenantVlanMap.get(networkId);
+        if (nodeConfiguration == null) {
+            nodeConfiguration = addNodeConfigurationToCache(node);
+        }
+        Integer vlan = nodeConfiguration.getInternalVlan(networkId);
         if (vlan == null) return 0;
         return vlan.intValue();
     }
 
-    public int networkCreated (String networkId) {
-        int internalVlan = this.assignInternalVlan(networkId);
+    private NodeConfiguration addNodeConfigurationToCache(Node node) {
+        NodeConfiguration nodeConfiguration = new NodeConfiguration(node);
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Cannot get Node UUID for Node {}", node);
+            return null;
+        }
+        this.nodeConfigurationCache.put(nodeUuid, nodeConfiguration);
+        return nodeConfigurationCache.get(nodeUuid);
+    }
+
+    public void networkCreated (String networkId) {
+        IConnectionServiceInternal connectionService = (IConnectionServiceInternal)ServiceHelper.getGlobalInstance(IConnectionServiceInternal.class, this);
+        List<Node> nodes = connectionService.getNodes();
+
+        for (Node node : nodes) {
+            this.networkCreated(node, networkId);
+        }
+
+    }
+
+    private String getNodeUUID(Node node) {
+        String nodeUuid = new String();
+        OVSDBConfigService ovsdbConfigService = (OVSDBConfigService)ServiceHelper.getGlobalInstance(OVSDBConfigService.class, this);
+        try {
+            Map<String, Table<?>> ovsTable = ovsdbConfigService.getRows(node, Open_vSwitch.NAME.getName());
+            nodeUuid = (String)ovsTable.keySet().toArray()[0];
+        }
+        catch (Exception e) {
+            logger.error("Unable to get the Open_vSwitch table for Node {}: {}", node, e);
+        }
+
+        return nodeUuid;
+    }
+
+    public int networkCreated (Node node, String networkId) {
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return 0;
+        }
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        // Cache miss
+        if (nodeConfiguration == null)
+        {
+            nodeConfiguration = addNodeConfigurationToCache(node);
+        }
+
+        int internalVlan = nodeConfiguration.assignInternalVlan(networkId);
         if (enableContainer && internalVlan != 0) {
             IContainerManager containerManager = (IContainerManager)ServiceHelper.getGlobalInstance(IContainerManager.class, this);
             if (containerManager == null) {
@@ -118,7 +163,22 @@ public class TenantNetworkManager {
             return false;
         }
         if (ProviderNetworkManager.getManager().hasPerTenantTunneling()) {
-            int internalVlan = this.getInternalVlan(networkId);
+            String nodeUuid = getNodeUUID(node);
+            if (nodeUuid == null) {
+                logger.debug("Unable to get UUID for Node {}", node);
+                return false;
+            }
+
+            NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+            // Cache miss
+            if (nodeConfiguration == null)
+            {
+                logger.error("Configuration data unavailable for Node {} ", node);
+                return false;
+            }
+
+            int internalVlan = nodeConfiguration.getInternalVlan(networkId);
             if (internalVlan == 0) {
                 logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
                 return false;
@@ -156,7 +216,7 @@ public class TenantNetworkManager {
                 Map<String, String> externalIds = intf.getExternal_ids();
                 if (externalIds != null && externalIds.get(EXTERNAL_ID_INTERFACE_ID) != null) {
                     if (this.isInterfacePresentInTenantNetwork(externalIds.get(EXTERNAL_ID_INTERFACE_ID), networkId)) {
-                        logger.debug("Tenant Network {} with Segmenation-id {} is present in Node {} / Interface {}",
+                        logger.debug("Tenant Network {} with Segmentation-id {} is present in Node {} / Interface {}",
                                       networkId, segmentationId, node, intf);
                         return true;
                     }
@@ -209,7 +269,23 @@ public class TenantNetworkManager {
     }
 
     public void programTenantNetworkInternalVlan(Node node, String portUUID, NeutronNetwork network) {
-        int vlan = this.getInternalVlan(network.getID());
+
+        String nodeUuid = getNodeUUID(node);
+        if (nodeUuid == null) {
+            logger.error("Unable to get UUID for Node {}", node);
+            return;
+        }
+
+        NodeConfiguration nodeConfiguration = nodeConfigurationCache.get(nodeUuid);
+
+        // Cache miss
+        if (nodeConfiguration == null)
+        {
+            logger.error("Configuration data unavailable for Node {} ", node);
+            return;
+        }
+
+        int vlan = nodeConfiguration.getInternalVlan(network.getID());
         logger.debug("Programming Vlan {} on {}", vlan, portUUID);
         if (vlan <= 0) {
             logger.error("Unable to get an internalVlan for Network {}", network);
index 016d2aeb6d99d20fee92275ae8c22fe5adcf5f59..6195ded1a30e389a1d5c187734084d11847ad3d3 100644 (file)
@@ -219,7 +219,7 @@ class OF10ProviderManager extends ProviderNetworkManager {
             logger.debug("Tenant Network not found with Segmenation-id {}",segmentationId);
             return;
         }
-        int internalVlan = TenantNetworkManager.getManager().getInternalVlan(networkId);
+        int internalVlan = TenantNetworkManager.getManager().getInternalVlan(node, networkId);
         if (internalVlan == 0) {
             logger.debug("No InternalVlan provisioned for Tenant Network {}",networkId);
             return;
index c753172290f3569a48053d5d5803bd40157f838a..48c70d0ec3bb3e0fe272e8fcfbdfae1db61f8736 100644 (file)
@@ -46,21 +46,6 @@ public class NetworkHandlerTest {
 
     }
 
-    @Test
-    public void testNeutronNetworkCreated() {
-        String netId = "6cfdb7";
-        NeutronNetwork mockNet = mock(NeutronNetwork.class);
-        when(mockNet.isShared()).thenReturn(false);
-        when(mockNet.getID()).thenReturn(netId);
-
-        TenantNetworkManager tenantNetworkManager = mock(TenantNetworkManager.class);
-        Whitebox.setInternalState(TenantNetworkManager.class, "tenantHelper", tenantNetworkManager);
-
-        testNetworkHandler.neutronNetworkCreated(mockNet);
-
-        verify(tenantNetworkManager).networkCreated(netId);
-    }
-
     @Test
     public void testCanUpdateNetwork() {
         NeutronNetwork delta = new NeutronNetwork();