de-static-ify ElanUtils field in ElanServiceProvider
[netvirt.git] / vpnservice / elanmanager / elanmanager-impl / src / main / java / org / opendaylight / netvirt / elan / internal / ElanServiceProvider.java
index e7e2d8f38c0b179df38a0bc970c92f930c9027b8..0c1e70be9dccdd9f5df859b88d18d1c822c5c461 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.netvirt.elan.internal;
 
 import com.google.common.base.Optional;
+
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -20,11 +21,17 @@ import java.util.Set;
 import java.util.concurrent.Future;
 import java.util.function.BiFunction;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.interfacemanager.exceptions.InterfaceAlreadyExistsException;
 import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.utils.ServiceIndex;
+import org.opendaylight.genius.utils.clustering.EntityOwnerUtils;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
 import org.opendaylight.netvirt.elan.statusanddiag.ElanStatusMonitor;
 import org.opendaylight.netvirt.elan.utils.ElanConstants;
 import org.opendaylight.netvirt.elan.utils.ElanUtils;
@@ -46,7 +53,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev16061
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan._interface.forwarding.entries.ElanInterfaceMac;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.dpn.interfaces.elan.dpn.interfaces.list.DpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
@@ -61,6 +67,7 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 public class ElanServiceProvider implements IElanService {
 
     private static final Logger LOG = LoggerFactory.getLogger(ElanServiceProvider.class);
@@ -71,15 +78,17 @@ public class ElanServiceProvider implements IElanService {
     private final ElanBridgeManager bridgeMgr;
     private final DataBroker broker;
     private final ElanStatusMonitor elanStatusMonitor;
-    private static ElanUtils elanUtils;
+    private final ElanUtils elanUtils;
 
     private boolean generateIntBridgeMac = true;
+    private boolean isL2BeforeL3;
 
     public ElanServiceProvider(IdManagerService idManager, IInterfaceManager interfaceManager,
                                ElanInstanceManager elanInstanceManager, ElanBridgeManager bridgeMgr,
                                DataBroker dataBroker,
                                ElanInterfaceManager elanInterfaceManager,
-                               ElanStatusMonitor elanStatusMonitor, ElanUtils elanUtils) {
+                               ElanStatusMonitor elanStatusMonitor, ElanUtils elanUtils,
+                               EntityOwnershipService entityOwnershipService) {
         this.idManager = idManager;
         this.interfaceManager = interfaceManager;
         this.elanInstanceManager = elanInstanceManager;
@@ -88,31 +97,35 @@ public class ElanServiceProvider implements IElanService {
         this.elanStatusMonitor = elanStatusMonitor;
         this.elanUtils = elanUtils;
         elanInterfaceManager.setElanUtils(elanUtils);
+        try {
+            EntityOwnerUtils.registerEntityCandidateForOwnerShip(entityOwnershipService,
+                    HwvtepSouthboundConstants.ELAN_ENTITY_TYPE, HwvtepSouthboundConstants.ELAN_ENTITY_TYPE,
+                    null/*listener*/);
+        } catch (CandidateAlreadyRegisteredException e) {
+            LOG.error("failed to register the entity");
+        }
     }
 
-    public void init() {
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public void init() throws Exception {
         LOG.info("Starting ElnaServiceProvider");
         elanStatusMonitor.reportStatus("STARTING");
+        setIsL2BeforeL3();
         try {
             createIdPool();
-
             elanStatusMonitor.reportStatus("OPERATIONAL");
         } catch (Exception e) {
-            LOG.error("Error initializing services", e);
             elanStatusMonitor.reportStatus("ERROR");
+            throw e;
         }
     }
 
-    private void createIdPool() {
+    private void createIdPool() throws Exception {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(ElanConstants.ELAN_ID_POOL_NAME)
                 .setLow(ElanConstants.ELAN_ID_LOW_VALUE).setHigh(ElanConstants.ELAN_ID_HIGH_VALUE).build();
-        try {
-            Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
-            if (result != null && result.get().isSuccessful()) {
-                LOG.debug("ELAN Id Pool is created successfully");
-            }
-        } catch (Exception e) {
-            LOG.error("Failed to create ELAN Id pool {}", e);
+        Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
+        if (result != null && result.get().isSuccessful()) {
+            LOG.debug("ELAN Id Pool is created successfully");
         }
     }
 
@@ -377,7 +390,6 @@ public class ElanServiceProvider implements IElanService {
                         deleteStaticMacAddress(elanInstanceName, elanInterface, macEntry.getMacAddress().getValue());
                     } catch (MacNotFoundException e) {
                         LOG.error("Mac Not Found Exception {}", e);
-                        e.printStackTrace();
                     }
                 }
             }
@@ -413,15 +425,10 @@ public class ElanServiceProvider implements IElanService {
 
     @Override
     public List<ElanInstance> getElanInstances() {
-        List<ElanInstance> elanList = new ArrayList<>();
         InstanceIdentifier<ElanInstances> elanInstancesIdentifier = InstanceIdentifier.builder(ElanInstances.class)
                 .build();
-        Optional<ElanInstances> elansOptional = elanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
-                elanInstancesIdentifier);
-        if (elansOptional.isPresent()) {
-            elanList.addAll(elansOptional.get().getElanInstance());
-        }
-        return elanList;
+        return elanUtils.read(broker, LogicalDatastoreType.CONFIGURATION, elanInstancesIdentifier).transform(
+                ElanInstances::getElanInstance).or(Collections.emptyList());
     }
 
     @Override
@@ -467,6 +474,16 @@ public class ElanServiceProvider implements IElanService {
         });
     }
 
+    private void createExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
+        if (interfaceName == null) {
+            LOG.trace("No physical interface is attached to {}", elanInstance.getPhysicalNetworkName());
+            return;
+        }
+
+        String elanInterfaceName = createIetfInterfaces(elanInstance, interfaceName);
+        addElanInterface(elanInstance.getElanInstanceName(), elanInterfaceName, null, null);
+    }
+
     @Override
     public void deleteExternalElanNetworks(Node node) {
         handleExternalElanNetworks(node, (elanInstance, interfaceName) -> {
@@ -483,6 +500,21 @@ public class ElanServiceProvider implements IElanService {
         });
     }
 
+    private void deleteExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
+        if (interfaceName == null) {
+            LOG.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
+            return;
+        }
+
+        String elanInstanceName = elanInstance.getElanInstanceName();
+        for (String elanInterface : getExternalElanInterfaces(elanInstanceName)) {
+            if (elanInterface.startsWith(interfaceName)) {
+                deleteIetfInterface(elanInterface);
+                deleteElanInterface(elanInstanceName, elanInterface);
+            }
+        }
+    }
+
     @Override
     public void updateExternalElanNetworks(Node origNode, Node updatedNode) {
         if (!bridgeMgr.isIntegrationBridge(updatedNode)) {
@@ -495,69 +527,48 @@ public class ElanServiceProvider implements IElanService {
             return;
         }
 
-        Optional<Map<String, String>> origProviderMapOpt = bridgeMgr.getOpenvswitchOtherConfigMap(origNode,
+        LOG.debug("updateExternalElanNetworks, orig bridge {} . updated bridge {}", origNode, updatedNode);
+
+        Map<String, String> origProviderMappping = getMapFromOtherConfig(origNode,
                 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
-        Optional<Map<String, String>> updatedProviderMapOpt = bridgeMgr.getOpenvswitchOtherConfigMap(updatedNode,
+        Map<String, String> updatedProviderMappping = getMapFromOtherConfig(updatedNode,
                 ElanBridgeManager.PROVIDER_MAPPINGS_KEY);
-        Map<String, String> origProviderMappping = origProviderMapOpt.or(Collections.emptyMap());
-        Map<String, String> updatedProviderMappping = updatedProviderMapOpt.or(Collections.emptyMap());
+
+        boolean hasDatapathIdOnOrigNode = bridgeMgr.hasDatapathID(origNode);
+        boolean hasDatapathIdOnUpdatedNode = bridgeMgr.hasDatapathID(updatedNode);
 
         for (ElanInstance elanInstance : elanInstances) {
             String physicalNetworkName = elanInstance.getPhysicalNetworkName();
             if (physicalNetworkName != null) {
                 String origPortName = origProviderMappping.get(physicalNetworkName);
                 String updatedPortName = updatedProviderMappping.get(physicalNetworkName);
-                if (origPortName != null && !origPortName.equals(updatedPortName)) {
-                    deleteExternalElanNetwork(elanInstance, getExtInterfaceName(origNode, physicalNetworkName));
+                if (hasPortNameRemoved(origPortName, updatedPortName)) {
+                    deleteExternalElanNetwork(elanInstance,
+                            bridgeMgr.getProviderInterfaceName(origNode, physicalNetworkName));
                 }
-                if (updatedPortName != null && !updatedPortName.equals(origPortName)) {
-                    createExternalElanNetwork(elanInstance, getExtInterfaceName(updatedNode, updatedPortName));
+                if (hasPortNameUpdated(origPortName, updatedPortName)
+                        || hasDatapathIdAdded(hasDatapathIdOnOrigNode, hasDatapathIdOnUpdatedNode)) {
+                    createExternalElanNetwork(elanInstance,
+                            bridgeMgr.getProviderInterfaceName(updatedNode, physicalNetworkName));
                 }
             }
         }
     }
 
-    private void createExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
-        if (interfaceName == null) {
-            LOG.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
-            return;
-        }
-
-        String elanInterfaceName = createIetfInterfaces(elanInstance, interfaceName);
-        addElanInterface(elanInstance.getElanInstanceName(), elanInterfaceName, null, null);
+    private boolean hasDatapathIdAdded(boolean hasDatapathIdOnOrigNode, boolean hasDatapathIdOnUpdatedNode) {
+        return !hasDatapathIdOnOrigNode && hasDatapathIdOnUpdatedNode;
     }
 
-    private void deleteExternalElanNetwork(ElanInstance elanInstance, String interfaceName) {
-        if (interfaceName == null) {
-            LOG.trace("No physial interface is attached to {}", elanInstance.getPhysicalNetworkName());
-            return;
-        }
-
-        String elanInstanceName = elanInstance.getElanInstanceName();
-        for (String elanInterface : getExternalElanInterfaces(elanInstanceName)) {
-            if (elanInterface.startsWith(interfaceName)) {
-                deleteIetfInterface(elanInterface);
-                deleteElanInterface(elanInstanceName, elanInterface);
-            }
-        }
+    private boolean hasPortNameUpdated(String origPortName, String updatedPortName) {
+        return updatedPortName != null && !updatedPortName.equals(origPortName);
     }
 
-    @Override
-    public String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
-        DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanInstanceName, dpnId);
-        if (dpnInterfaces == null || dpnInterfaces.getInterfaces() == null) {
-            LOG.trace("Elan {} does not have interfaces in DPN {}", elanInstanceName, dpnId);
-            return null;
-        }
-
-        for (String dpnInterface : dpnInterfaces.getInterfaces()) {
-            if (elanUtils.isExternal(dpnInterface)) {
-                return dpnInterface;
-            }
-        }
+    private boolean hasPortNameRemoved(String origPortName, String updatedPortName) {
+        return origPortName != null && !origPortName.equals(updatedPortName);
+    }
 
-        LOG.trace("Elan {} does not have any external interace attached to DPN {}", elanInstanceName, dpnId);
-        return null;
+    private Map<String, String> getMapFromOtherConfig(Node node, String otherConfigColumn) {
+        return bridgeMgr.getOpenvswitchOtherConfigMap(node, otherConfigColumn);
     }
 
     @Override
@@ -570,7 +581,7 @@ public class ElanServiceProvider implements IElanService {
 
         Set<String> externalElanInterfaces = new HashSet<>();
         for (String elanInterface : elanInterfaces) {
-            if (elanUtils.isExternal(elanInterface)) {
+            if (interfaceManager.isExternalInterface(elanInterface)) {
                 externalElanInterfaces.add(elanInterface);
             }
         }
@@ -578,9 +589,14 @@ public class ElanServiceProvider implements IElanService {
         return externalElanInterfaces;
     }
 
+    @Override
+    public String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
+        return elanUtils.getExternalElanInterface(elanInstanceName, dpnId);
+    }
+
     @Override
     public boolean isExternalInterface(String interfaceName) {
-        return elanUtils.isExternal(interfaceName);
+        return interfaceManager.isExternalInterface(interfaceName);
     }
 
     @Override
@@ -588,6 +604,28 @@ public class ElanServiceProvider implements IElanService {
         return ElanUtils.getElanInterfaceByElanInterfaceName(broker, interfaceName);
     }
 
+    @Override
+    public void handleKnownL3DmacAddress(String macAddress, String elanInstanceName, int addOrRemove) {
+        if (!isL2BeforeL3) {
+            LOG.trace("ELAN service is after L3VPN in the Netvirt pipeline skip known L3DMAC flows installation");
+            return;
+        }
+        ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanInstanceName);
+        if (elanInstance == null) {
+            LOG.warn("Null elan instance {}", elanInstanceName);
+            return;
+        }
+
+        List<BigInteger> dpnsIdsForElanInstance = elanUtils.getParticipatingDpnsInElanInstance(elanInstanceName);
+        if (dpnsIdsForElanInstance == null || dpnsIdsForElanInstance.isEmpty()) {
+            LOG.warn("No DPNs for elan instance {}", elanInstance);
+            return;
+        }
+
+        elanUtils.handleDmacRedirectToDispatcherFlows(elanInstance.getElanTag(), elanInstanceName, macAddress,
+                addOrRemove, dpnsIdsForElanInstance);
+    }
+
     /**
      * Create ietf-interfaces based on the ELAN segment type.<br>
      * For segment type flat - create transparent interface pointing to the
@@ -617,7 +655,7 @@ public class ElanServiceProvider implements IElanService {
                 interfaceName = parentRef + IfmConstants.OF_URI_SEPARATOR + segmentationId;
                 String trunkName = parentRef + IfmConstants.OF_URI_SEPARATOR + "trunk";
                 // trunk interface may have been created by other vlan network
-                Interface trunkInterface = ElanUtils.getInterfaceFromConfigDS(trunkName, broker);
+                Interface trunkInterface = interfaceManager.getInterfaceInfoFromConfigDataStore(trunkName);
                 if (trunkInterface == null) {
                     interfaceManager.createVLANInterface(trunkName, parentRef, null, null, null,
                             IfL2vlan.L2vlanMode.Trunk, true);
@@ -640,22 +678,6 @@ public class ElanServiceProvider implements IElanService {
         LOG.debug("Deleting IETF interface {}", interfaceName);
     }
 
-    private String getExtInterfaceName(Node node, String physicalNetworkName) {
-        if (physicalNetworkName == null) {
-            return null;
-        }
-
-        String providerMappingValue = bridgeMgr.getProviderMappingValue(node, physicalNetworkName);
-        if (providerMappingValue == null) {
-            LOG.trace("No provider mapping found for physicalNetworkName {} node {}", physicalNetworkName,
-                    node.getNodeId().getValue());
-            return null;
-        }
-
-        return bridgeMgr.southboundUtils.getDataPathId(node) + IfmConstants.OF_URI_SEPARATOR
-                + bridgeMgr.getIntBridgePortNameFor(node, providerMappingValue);
-    }
-
     private void handleExternalElanNetworks(Node node, BiFunction<ElanInstance, String, Void> function) {
         if (!bridgeMgr.isIntegrationBridge(node)) {
             return;
@@ -668,7 +690,7 @@ public class ElanServiceProvider implements IElanService {
         }
 
         for (ElanInstance elanInstance : elanInstances) {
-            String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
+            String interfaceName = bridgeMgr.getProviderInterfaceName(node, elanInstance.getPhysicalNetworkName());
             if (interfaceName != null) {
                 function.apply(elanInstance, interfaceName);
             }
@@ -691,10 +713,23 @@ public class ElanServiceProvider implements IElanService {
 
         for (Node node : nodes) {
             if (bridgeMgr.isIntegrationBridge(node)) {
-                String interfaceName = getExtInterfaceName(node, elanInstance.getPhysicalNetworkName());
+                String interfaceName = bridgeMgr.getProviderInterfaceName(node, elanInstance.getPhysicalNetworkName());
                 function.apply(elanInstance, interfaceName);
             }
         }
     }
 
+    private void setIsL2BeforeL3() {
+        short elanServiceRealIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME,
+                NwConstants.ELAN_SERVICE_INDEX);
+        short l3vpnServiceRealIndex = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
+                NwConstants.L3VPN_SERVICE_INDEX);
+        if (elanServiceRealIndex < l3vpnServiceRealIndex) {
+            LOG.info("ELAN service is set before L3VPN service in the Netvirt pipeline");
+            isL2BeforeL3 = true;
+        } else {
+            LOG.info("ELAN service is set after L3VPN service in the Netvirt pipeline");
+            isL2BeforeL3 = false;
+        }
+    }
 }