Fix DMAC flows for Vlan E/W provider 19/44619/10
authorJosh <jhershbe@redhat.com>
Wed, 24 Aug 2016 18:30:09 +0000 (20:30 +0200)
committerSam Hague <shague@redhat.com>
Wed, 31 Aug 2016 20:04:30 +0000 (20:04 +0000)
This fix addresses two bugs related only in that
they both prevent vlan provider networks from
working:

1) Wrong (remote) dmac flows generated for Vlan provider networks
https://bugs.opendaylight.org/show_bug.cgi?id=6583

2) Mac learning in vlan provider networks clobbers static flows with wrong flows
https://bugs.opendaylight.org/show_bug.cgi?id=6584

The fix for the (1) is to test if the net is
of type vlan and then retrieve the correct action.

The fix for (2) is to simply disable configuration
of remote dmac flows when the interface from whence
entered the unknown smac is a vlan or flat network
provider interface.

Change-Id: Id3431e94d96dac5230679fcb70fe0a79efbd96a4
Signed-off-by: Josh <jhershbe@redhat.com>
vpnservice/elanmanager/elanmanager-api/src/main/java/org/opendaylight/netvirt/elanmanager/api/IElanService.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanBridgeManager.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanPacketInHandler.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanServiceProvider.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/resources/org/opendaylight/blueprint/elanmanager.xml

index 4d986709d1a678d90ff2af2fd23beb6e322a307b..84f276ec1bebcb80cde4d8b31c4d40797ac77190 100644 (file)
@@ -8,7 +8,6 @@
 
 package org.opendaylight.netvirt.elanmanager.api;
 
-import java.math.BigInteger;
 import java.util.Collection;
 import java.util.List;
 import org.opendaylight.netvirt.elanmanager.exceptions.MacNotFoundException;
@@ -58,8 +57,6 @@ public interface IElanService extends IEtreeService {
 
     void deleteExternalElanNetworks(Node node);
 
-    String getExternalElanInterface(String elanInstanceName, BigInteger dpnId);
-
     Collection<String> getExternalElanInterfaces(String elanInstanceName);
 
     boolean isExternalInterface(String interfaceName);
index 4873994b1ad77f3556708449ec69d5cf9174ac7e..10a8209bd753025a4152135e69a655bd3d190527 100644 (file)
@@ -10,11 +10,15 @@ package org.opendaylight.netvirt.elan.internal;
 import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
 import com.google.common.base.Strings;
+
+import java.math.BigInteger;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Random;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.ovsdb.utils.config.ConfigProperties;
 import org.opendaylight.ovsdb.utils.mdsal.utils.MdsalUtils;
 import org.opendaylight.ovsdb.utils.southbound.utils.SouthboundUtils;
@@ -369,4 +373,53 @@ public class ElanBridgeManager {
 
         return Optional.of(valueMap);
     }
+
+    public Node getBridgeNode(BigInteger dpId) {
+        List<Node> ovsdbNodes = southboundUtils.getOvsdbNodes();
+        if (null == ovsdbNodes) {
+            LOG.debug("Could not find any (?) ovsdb nodes");
+            return null;
+        }
+
+        for (Node node : ovsdbNodes) {
+            if(!isIntegrationBridge(node)) {
+                continue;
+            }
+
+            long nodeDpid = southboundUtils.getDataPathId(node);
+            if (dpId.equals(BigInteger.valueOf(nodeDpid))) {
+                return node;
+            }
+        }
+
+        return null;
+    }
+
+    public String getProviderInterfaceName(BigInteger dpId, String physicalNetworkName) {
+        Node brNode;
+
+        brNode = getBridgeNode(dpId);
+        if (brNode == null) {
+            LOG.debug("Could not find bridge node for {}", dpId);
+            return null;
+        }
+
+        return getProviderInterfaceName(brNode, physicalNetworkName);
+    }
+
+    public String getProviderInterfaceName(Node bridgeNode, String physicalNetworkName) {
+        if (physicalNetworkName == null) {
+            return null;
+        }
+
+        String providerMappingValue = getProviderMappingValue(bridgeNode, physicalNetworkName);
+        if (providerMappingValue == null) {
+            LOG.trace("No provider mapping found for physicalNetworkName {} node {}", physicalNetworkName,
+                    bridgeNode.getNodeId().getValue());
+            return null;
+        }
+
+        return southboundUtils.getDataPathId(bridgeNode) + IfmConstants.OF_URI_SEPARATOR
+                + getIntBridgePortNameFor(bridgeNode, providerMappingValue);
+    }
 }
index 0a0fe0ca75052ae07a710507af67d3c329cffbaf..d445694c9963533dd5d0763f69e8a63563c6590e 100644 (file)
@@ -539,7 +539,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                         PhysAddress physAddress = macEntry.getMacAddress();
                         elanUtils.setupRemoteDmacFlow(interfaceInfo.getDpId(), remoteInterface.getDpId(),
                                 remoteInterface.getInterfaceTag(), elanInstance.getElanTag(), physAddress.getValue(),
-                                elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf);
+                                elanInstance.getElanInstanceName(), writeFlowGroupTx, remoteIf, elanInstance);
                     }
                 }
             }
index 541886de17377f80bffd6e76c933c3f2355f99f8..6554d67649b06a88044c3d65fbf007ac1288db11 100755 (executable)
@@ -143,9 +143,14 @@ public class ElanPacketInHandler implements PacketProcessingListener {
                         macEntry);
                 ElanInstance elanInstance = ElanUtils.getElanInstanceByName(broker, elanName);
                 WriteTransaction flowWritetx = broker.newWriteOnlyTransaction();
-                elanUtils.setupMacFlows(elanInstance,
-                        interfaceManager.getInterfaceInfo(interfaceName),
-                        elanInstance.getMacTimeout(), macAddress, flowWritetx);
+
+                boolean isVlanOrFlatProviderIface = ( ElanUtils.isVlan(elanInstance)
+                                                && interfaceName.endsWith(":" + elanInstance.getSegmentationId()) )
+                                             || ( ElanUtils.isFlat(elanInstance) && interfaceName.endsWith(":flat") );
+
+                elanUtils.setupMacFlows(elanInstance, interfaceManager.getInterfaceInfo(interfaceName),
+                                        elanInstance.getMacTimeout(), macAddress,
+                                        !isVlanOrFlatProviderIface, flowWritetx);
                 flowWritetx.submit();
 
                 BigInteger dpId = interfaceManager.getDpnForInterface(interfaceName);
index e8f7d19f344316f4766ed96194330b1eec85d53f..9c61b8c21010e4c88a584a100fe09a3737b4cc8e 100644 (file)
@@ -540,33 +540,15 @@ public class ElanServiceProvider implements IElanService {
                 String origPortName = origProviderMappping.get(physicalNetworkName);
                 String updatedPortName = updatedProviderMappping.get(physicalNetworkName);
                 if (origPortName != null && !origPortName.equals(updatedPortName)) {
-                    deleteExternalElanNetwork(elanInstance, getExtInterfaceName(origNode, physicalNetworkName));
+                    deleteExternalElanNetwork(elanInstance, bridgeMgr.getProviderInterfaceName(origNode, physicalNetworkName));
                 }
                 if (updatedPortName != null && !updatedPortName.equals(origPortName)) {
-                    createExternalElanNetwork(elanInstance, getExtInterfaceName(updatedNode, updatedPortName));
+                    createExternalElanNetwork(elanInstance, bridgeMgr.getProviderInterfaceName(updatedNode, updatedPortName));
                 }
             }
         }
     }
 
-    @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;
-            }
-        }
-
-        LOG.trace("Elan {} does not have any external interace attached to DPN {}", elanInstanceName, dpnId);
-        return null;
-    }
-
     @Override
     public Collection<String> getExternalElanInterfaces(String elanInstanceName) {
         List<String> elanInterfaces = getElanInterfaces(elanInstanceName);
@@ -647,22 +629,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;
@@ -675,7 +641,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);
             }
@@ -698,7 +664,7 @@ 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);
             }
         }
index 44868e82d8062928db661d731bbb35069aff16ad..ba55cf6e3bb9340c475e2277cd3611217c393f97 100644 (file)
@@ -17,6 +17,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
@@ -28,6 +29,7 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipS
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.genius.interfacemanager.globals.IfmConstants;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceInfo;
 import org.opendaylight.genius.interfacemanager.globals.InterfaceServiceUtil;
 import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
@@ -44,8 +46,10 @@ import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.netvirt.elan.ElanException;
+import org.opendaylight.netvirt.elan.internal.ElanBridgeManager;
 import org.opendaylight.netvirt.elan.internal.ElanInstanceManager;
 import org.opendaylight.netvirt.elan.internal.ElanInterfaceManager;
+import org.opendaylight.netvirt.elan.internal.ElanServiceProvider;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayMulticastUtils;
 import org.opendaylight.netvirt.elan.l2gw.utils.ElanL2GatewayUtils;
 import org.opendaylight.netvirt.elan.l2gw.utils.L2GatewayConnectionUtils;
@@ -169,6 +173,7 @@ public class ElanUtils {
     private ElanL2GatewayUtils elanL2GatewayUtils;
     private ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
     private L2GatewayConnectionUtils l2GatewayConnectionUtils;
+    private ElanBridgeManager bridgeManager;
 
     public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
         @Override
@@ -185,12 +190,13 @@ public class ElanUtils {
     public ElanUtils(DataBroker dataBroker, IMdsalApiManager mdsalManager, ElanInstanceManager elanInstanceManager,
                      OdlInterfaceRpcService interfaceManagerRpcService, ItmRpcService itmRpcService,
                      ElanInterfaceManager elanInterfaceManager,
-                     EntityOwnershipService entityOwnershipService) {
+                     EntityOwnershipService entityOwnershipService, ElanBridgeManager bridgeManager) {
         this.broker = dataBroker;
         this.mdsalManager = mdsalManager;
         this.elanInstanceManager = elanInstanceManager;
         this.interfaceManagerRpcService = interfaceManagerRpcService;
         this.itmRpcService = itmRpcService;
+        this.bridgeManager = bridgeManager;
 
         elanL2GatewayMulticastUtils =
                 new ElanL2GatewayMulticastUtils(broker, elanInstanceManager, elanInterfaceManager, this);
@@ -699,8 +705,7 @@ public class ElanUtils {
     }
 
     /**
-     * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and also in
-     * other DPNs.
+     * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and optionally in other DPNs.
      *
      * @param elanInfo
      *            the elan info
@@ -710,21 +715,43 @@ public class ElanUtils {
      *            the mac timeout
      * @param macAddress
      *            the mac address
+     * @param configureRemoteFlows
+     *            true if remote dmac flows should be configured as well
      * @param writeFlowGroupTx
      *            the flow group tx
      * @throws ElanException in case of issues creating the flow objects
      */
     public void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
-            String macAddress, WriteTransaction writeFlowGroupTx) throws ElanException {
+            String macAddress, boolean configureRemoteFlows, WriteTransaction writeFlowGroupTx) throws ElanException {
         synchronized (macAddress) {
             LOG.debug("Acquired lock for mac : " + macAddress + ". Proceeding with install operation.");
             setupKnownSmacFlow(elanInfo, interfaceInfo, macTimeout, macAddress, mdsalManager,
                     writeFlowGroupTx);
-            setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, mdsalManager,
+            setupOrigDmacFlows(elanInfo, interfaceInfo, macAddress, configureRemoteFlows, mdsalManager,
                     broker, writeFlowGroupTx);
         }
     }
 
+    /**
+     * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and on other DPNs.
+     *
+     * @param elanInfo
+     *            the elan info
+     * @param interfaceInfo
+     *            the interface info
+     * @param macTimeout
+     *            the mac timeout
+     * @param macAddress
+     *            the mac address
+     * @param writeFlowGroupTx
+     *            the flow group tx
+     * @throws ElanException in case of issues creating the flow objects
+     */
+    public void setupMacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, long macTimeout,
+                              String macAddress, WriteTransaction writeFlowGroupTx) throws ElanException {
+        setupMacFlows(elanInfo, interfaceInfo, macTimeout, macAddress, true, writeFlowGroupTx);
+    }
+
     public void setupDMacFlowonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId,
             String macAddress, WriteTransaction writeFlowTx) throws ElanException {
         synchronized (macAddress) {
@@ -900,51 +927,56 @@ public class ElanUtils {
     }
 
     private void setupOrigDmacFlows(ElanInstance elanInfo, InterfaceInfo interfaceInfo, String macAddress,
-            IMdsalApiManager mdsalApiManager, DataBroker broker, WriteTransaction writeFlowGroupTx)
-            throws ElanException {
+                                    boolean configureRemoteFlows, IMdsalApiManager mdsalApiManager,
+                                    DataBroker broker, WriteTransaction writeFlowGroupTx)
+                                    throws ElanException {
         BigInteger dpId = interfaceInfo.getDpId();
         String ifName = interfaceInfo.getInterfaceName();
         long ifTag = interfaceInfo.getInterfaceTag();
         String elanInstanceName = elanInfo.getElanInstanceName();
+
+        Long elanTag = getElanTag(broker, elanInfo, interfaceInfo);
+
+        setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag,
+                writeFlowGroupTx);
+        LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} mand mac address:{} "
+                                    + "on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
+
+        if (!configureRemoteFlows) {
+            return;
+        }
+
         List<DpnInterfaces> elanDpns = getInvolvedDpnsInElan(elanInstanceName);
-        if (elanDpns != null) {
-            // TODO might be bug and should call here just elanInfo.getElanTag()
-            Long elanTag = getElanTag(broker, elanInfo, interfaceInfo);
-            for (DpnInterfaces elanDpn : elanDpns) {
-                if (elanDpn.getDpId().equals(dpId)) {
-                    // On the local DPN set up a direct output flow
-                    setupLocalDmacFlow(elanTag, dpId, ifName, macAddress, elanInstanceName, mdsalApiManager, ifTag,
-                            writeFlowGroupTx);
-                    LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} mand mac address:{} "
-                            + "on dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, dpId);
-                } else {
-                    // Check for the Remote DPN present in Inventory Manager
-                    if (isDpnPresent(elanDpn.getDpId())) {
-                        // For remote DPNs a flow is needed to indicate that
-                        // packets of this ELAN going to this MAC
-                        // need to be forwarded through the appropiated ITM
-                        // tunnel
-                        setupRemoteDmacFlow(elanDpn.getDpId(), // srcDpn (the
-                                                               // remote DPN in
-                                                               // this case)
-                                dpId, // dstDpn (the local DPN)
-                                interfaceInfo.getInterfaceTag(), // lportTag of
-                                                                 // the local
-                                                                 // interface
-                                elanTag, // identifier of the Elan
-                                macAddress, // MAC to be programmed in remote
-                                            // DPN
-                                elanInstanceName, writeFlowGroupTx, ifName);
-                        LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on"
-                                + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress,
-                                elanDpn.getDpId());
-                    }
-                }
+        if (elanDpns == null) {
+            return;
+        }
+
+        for (DpnInterfaces elanDpn : elanDpns) {
+
+            if (elanDpn.getDpId().equals(dpId)) {
+                continue;
+            }
+
+            // Check for the Remote DPN present in Inventory Manager
+            if (!isDpnPresent(elanDpn.getDpId())) {
+                continue;
             }
 
-            // TODO: Make sure that the same is performed against the
-            // ElanDevices.
+            // For remote DPNs a flow is needed to indicate that
+            // packets of this ELAN going to this MAC
+            // need to be forwarded through the appropiated ITM
+            // tunnel
+            setupRemoteDmacFlow(elanDpn.getDpId(), // srcDpn (the remote DPN in this case)
+                    dpId, // dstDpn (the local DPN)
+                    interfaceInfo.getInterfaceTag(), // lportTag of the local interface
+                    elanTag, // identifier of the Elan
+                    macAddress, // MAC to be programmed in remote DPN
+                    elanInstanceName, writeFlowGroupTx, ifName, elanInfo);
+            LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on"
+                        + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, elanDpn.getDpId());
         }
+
+        // TODO: Make sure that the same is performed against the ElanDevices.
     }
 
     private void setupOrigDmacFlowsonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo,
@@ -957,7 +989,7 @@ public class ElanUtils {
             if (remoteFE.getDpId().equals(dstDpId)) {
                 // Check for the Remote DPN present in Inventory Manager
                 setupRemoteDmacFlow(dstDpId, dpId, interfaceInfo.getInterfaceTag(), elanTag, macAddress,
-                        elanInstanceName, writeFlowTx, interfaceInfo.getInterfaceName());
+                        elanInstanceName, writeFlowTx, interfaceInfo.getInterfaceName(), elanInfo);
                 if (LOG.isDebugEnabled()) {
                     LOG.debug("Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address {} on"
                             + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, remoteFE.getDpId());
@@ -1061,17 +1093,17 @@ public class ElanUtils {
     }
 
     public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-            String macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName)
+            String macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName, ElanInstance elanInstance)
             throws ElanException {
-        Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName);
+        Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName, elanInstance);
         mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
         setupEtreeRemoteDmacFlow(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName, interfaceName,
-                writeFlowGroupTx);
+                writeFlowGroupTx, elanInstance);
     }
 
     private void setupEtreeRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-            String macAddress, String displayName, String interfaceName, WriteTransaction writeFlowGroupTx)
-            throws ElanException {
+                                String macAddress, String displayName, String interfaceName,
+                                WriteTransaction writeFlowGroupTx, ElanInstance elanInstance) throws ElanException {
         Flow flowEntity;
         EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
         if (etreeInterface != null) {
@@ -1082,7 +1114,7 @@ public class ElanUtils {
                             + " seems like it belongs to Etree but etreeTagName from elanTag " + elanTag + " is null.");
                 } else {
                     flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag,
-                            etreeTagName.getEtreeLeafTag().getValue(), macAddress, displayName);
+                            etreeTagName.getEtreeLeafTag().getValue(), macAddress, displayName, elanInstance);
                     mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
                 }
             }
@@ -1112,7 +1144,7 @@ public class ElanUtils {
      */
     @SuppressWarnings("checkstyle:IllegalCatch")
     public Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-            String macAddress, String displayName) throws ElanException {
+            String macAddress, String displayName, ElanInstance elanInstance) throws ElanException {
         List<MatchInfo> mkMatches = new ArrayList<>();
         mkMatches.add(new MatchInfo(MatchFieldType.metadata,
                 new BigInteger[] { getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE }));
@@ -1122,7 +1154,16 @@ public class ElanUtils {
 
         // List of Action for the provided Source and Destination DPIDs
         try {
-            List<Action> actions = getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTag);
+            List<Action> actions = null;
+            if(isVlan(elanInstance) || isFlat(elanInstance)) {
+                String interfaceName = getExternalElanInterface(elanInstance.getElanInstanceName(), srcDpId);
+                if (null == interfaceName) {
+                    LOG.error("buildRemoteDmacFlowEntry: Could not find interfaceName for {} {}", srcDpId, elanInstance);
+                }
+                actions = getEgressActionsForInterface(interfaceName, null);
+            } else {
+                actions = getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTag);
+            }
             mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
         } catch (Exception e) {
             LOG.error("Could not get egress actions to add to flow for srcDpId=" + srcDpId + ", destDpId=" + destDpId
@@ -2178,4 +2219,20 @@ public class ElanUtils {
                 ElanUtils.getMacEntryOperationalDataPath(elanName, physAddress));
     }
 
+    public String getExternalElanInterface(String elanInstanceName, BigInteger dpnId) {
+        DpnInterfaces dpnInterfaces = 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 (isExternal(dpnInterface)) {
+                return dpnInterface;
+            }
+        }
+
+        LOG.trace("Elan {} does not have any external interace attached to DPN {}", elanInstanceName, dpnId);
+        return null;
+    }
 }
index bd4f8f79de51baa0513bd8e7378736df69fc2656..0d5879d4657bffc5f67d9083889b33f0c932e74d 100644 (file)
@@ -82,6 +82,7 @@
     <argument ref="itmRpcService" />
     <argument ref="elanInterfaceManager" />
     <argument ref="entityOwnershipService" />
+    <argument ref="elanBridgeManager" />
   </bean>
 
   <bean id="elanStatisticsImpl" class="org.opendaylight.netvirt.elan.statisitcs.ElanStatisticsImpl">