Fix NPE triggered after disabling SG on a port
[netvirt.git] / openstack / net-virt / src / main / java / org / opendaylight / netvirt / openstack / netvirt / impl / BridgeConfigurationManagerImpl.java
index d3b3578e1f19e3f9b23de2b15b4c65c5d752010f..95459cefb7b10a9dee1ea9e9d96c4ba8efceb2ff 100644 (file)
@@ -8,15 +8,30 @@
 
 package org.opendaylight.netvirt.openstack.netvirt.impl;
 
+import com.google.common.base.Preconditions;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.opendaylight.netvirt.openstack.netvirt.NetworkHandler;
+import org.opendaylight.netvirt.openstack.netvirt.VLANProvider;
 import org.opendaylight.netvirt.openstack.netvirt.api.OvsdbTables;
 import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
 import org.opendaylight.netvirt.openstack.netvirt.ConfigInterface;
+import org.opendaylight.netvirt.openstack.netvirt.MdsalHelper;
+import org.opendaylight.netvirt.openstack.netvirt.NetworkHandler;
 import org.opendaylight.netvirt.openstack.netvirt.api.BridgeConfigurationManager;
 import org.opendaylight.netvirt.openstack.netvirt.api.ConfigurationService;
 import org.opendaylight.netvirt.openstack.netvirt.api.Constants;
 import org.opendaylight.netvirt.openstack.netvirt.api.NetworkingProviderManager;
+import org.opendaylight.netvirt.openstack.netvirt.api.OvsdbTables;
 import org.opendaylight.netvirt.openstack.netvirt.api.Southbound;
+import org.opendaylight.netvirt.openstack.netvirt.translator.NeutronNetwork;
 import org.opendaylight.netvirt.utils.config.ConfigProperties;
 import org.opendaylight.netvirt.utils.servicehelper.ServiceHelper;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.DatapathTypeBase;
@@ -25,19 +40,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ConnectionInfo;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.node.attributes.ManagerEntry;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-
-import java.net.InetAddress;
-import java.net.NetworkInterface;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.Random;
-
-import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -166,6 +168,47 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
         try {
             if (configurationService.isL3ForwardingEnabled()) {
                 createExternalBridge(ovsdbNode);
+            } else if (configurationService.isL3MultipleExternalNetworkEnabled()) {
+                String brExt = getMultipleExternalBridge(ovsdbNode);
+                if (brExt == null) {
+                    LOG.warn("The provider mapping external network bridge name is null");
+                    return;
+                }
+                //get external bridge
+                Node extBridgeNode = southbound.readBridgeNode(ovsdbNode, brExt);
+                LOG.trace("External bridge details in operational data store:extBridgeNode:{}", extBridgeNode);
+                if (extBridgeNode == null) {
+                    LOG.warn("External bridge is not created:{}", brExt);
+                    return;
+                }
+                //get internal bridge
+                String brInt = configurationService.getIntegrationBridgeName();
+                if (!addBridge(ovsdbNode, brExt, null)) {
+                    LOG.warn("Multiple External Bridge Creation failed");
+                    return;
+                }
+                configurationService.setExternalBridgeName(brExt);
+                Node internalOvsdbNode = southbound.readConfigBridge(ovsdbNode, brInt);
+                LOG.trace("Internal bridge details in config data store:internalOvsdbNode:{}", internalOvsdbNode);
+                if (internalOvsdbNode == null) {
+                    LOG.warn("Internal Bridge is null in config datastore:{}", brInt);
+                    return;
+                }
+                //Processing an external bridge
+                String portNameExt = VLANProvider.getPatchPortName(brExt);
+                LOG.trace("prepareNode: portNameExt:{}", portNameExt);
+                final String portNameInt = Constants.PATCH_PORT_TO_INTEGRATION_BRIDGE_NAME;
+                Preconditions.checkNotNull(portNameInt);
+                Preconditions.checkNotNull(portNameExt);
+                if (!addPatchPort(internalOvsdbNode, brInt, portNameExt, portNameInt)) {
+                    LOG.error("Add Port {} to Bridge {} failed", portNameInt, brInt);
+                    return;
+                }
+                if (!addPatchPort(extBridgeNode, brExt, portNameInt, portNameExt)) {
+                    LOG.error("Add Port {} to Bridge {} failed", portNameExt, brExt);
+                    return;
+                }
+                LOG.info("Multiple external bridge is successfully created:{}", brExt);
             }
         } catch (Exception e) {
             LOG.error("Error creating External Bridge on {}", ovsdbNode, e);
@@ -271,21 +314,24 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
 
     @Override
     public List<String> getAllPhysicalInterfaceNames(Node node) {
-        List<String> phyIfName = Lists.newArrayList();
+        List<String> phyIfNames = new ArrayList<>();
         String providerMaps = southbound.getOtherConfig(node, OvsdbTables.OPENVSWITCH,
                 configurationService.getProviderMappingsKey());
         if (providerMaps == null) {
+            if (configurationService.isL3MultipleExternalNetworkEnabled()) {
+                return phyIfNames;
+            }
             providerMaps = configurationService.getDefaultProviderMapping();
         }
 
         if (providerMaps != null) {
             for (String map : providerMaps.split(",")) {
                 String[] pair = map.split(":");
-                phyIfName.add(pair[1]);
+                phyIfNames.add(pair[1]);
             }
         }
 
-        return phyIfName;
+        return phyIfNames;
     }
 
     /**
@@ -491,10 +537,9 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
      */
     private boolean addPatchPort (Node node, String bridgeName, String portName, String peerPortName) {
         boolean rv = true;
-
-        if (southbound.extractTerminationPointAugmentation(node, portName) == null) {
+        if (configurationService.isL3MultipleExternalNetworkEnabled() ||
+                southbound.extractTerminationPointAugmentation(node, portName) == null) {
             rv = southbound.addPatchTerminationPoint(node, bridgeName, portName, peerPortName);
-
             if (rv) {
                 LOG.info("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: success",
                         node.getNodeId().getValue(), bridgeName, portName, peerPortName);
@@ -506,7 +551,6 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
             LOG.trace("addPatchPort: node: {}, bridge: {}, portname: {} peer: {} status: not_needed",
                     node.getNodeId().getValue(), bridgeName, portName, peerPortName);
         }
-
         return rv;
     }
 
@@ -515,13 +559,20 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
      */
     private boolean addBridge(Node ovsdbNode, String bridgeName, String mac) {
         boolean rv = true;
-        if ((!southbound.isBridgeOnOvsdbNode(ovsdbNode, bridgeName)) ||
-                (southbound.getBridgeFromConfig(ovsdbNode, bridgeName) == null)) {
+        boolean isBridgeInConfig = (southbound.getBridgeFromConfig(ovsdbNode, bridgeName) != null);
+        Node bridgeNode = southbound.readBridgeNode(ovsdbNode, bridgeName);
+
+        if (bridgeNode == null || !isBridgeInConfig) {
             Class<? extends DatapathTypeBase> dpType = null;
             if (configurationService.isUserSpaceEnabled()) {
                 dpType = DatapathTypeNetdev.class;
             }
-            rv = southbound.addBridge(ovsdbNode, bridgeName, getControllersFromOvsdbNode(ovsdbNode), dpType, mac);
+
+            // if the bridge is already on the OVS node, use the existing MAC address
+            // because changing the MAC causes the dpid to change on the switch, which
+            // in turn causes a connection flap (see bugs 6070, 6944)
+            rv = southbound.addBridge(ovsdbNode, bridgeName, getControllersFromOvsdbNode(ovsdbNode), dpType,
+                    bridgeNode == null ? mac : southbound.getOtherConfig(bridgeNode, OvsdbTables.BRIDGE, MdsalHelper.HWADDR));
         }
         return rv;
     }
@@ -622,11 +673,8 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
         if (controllersStr.isEmpty()) {
             LOG.warn("Failed to determine OpenFlow controller ip address");
         } else if (LOG.isDebugEnabled()) {
-            controllerIpStr = "";
-            for (String currControllerIpStr : controllersStr) {
-                controllerIpStr += " " + currControllerIpStr;
-            }
-            LOG.debug("Found {} OpenFlow Controller(s) :{}", controllersStr.size(), controllerIpStr);
+            LOG.debug("Found {} OpenFlow Controller(s): {}", controllersStr.size(),
+                    controllersStr.stream().collect(Collectors.joining(" ")));
         }
 
         return controllersStr;
@@ -665,4 +713,20 @@ public class BridgeConfigurationManagerImpl implements BridgeConfigurationManage
     @Override
     public void setDependencies(Object impl) {
     }
+
+    @Override
+    public String getMultipleExternalBridge(Node ovsdbNode) {
+        String brExt = null;
+        List<String> phyIfNames = this.getAllPhysicalInterfaceNames(ovsdbNode);
+        LOG.debug("getMultipleExternalBridge phyIfName::{}", phyIfNames);
+        if (phyIfNames.size() > 0) {
+            brExt = phyIfNames.get(0);
+            LOG.debug("Provider Mapping: external bridge name:{}", brExt);
+        }
+        if (brExt == null || brExt.isEmpty()) {
+            LOG.warn("The provider mapping external network bridge name is null");
+            return null;
+        }
+        return brExt;
+    }
 }