ELAN: VNI support in datapath for VxLAN networks 96/55696/5
authorAbhinav Gupta <abhinav.gupta@ericsson.com>
Thu, 12 Jan 2017 11:11:49 +0000 (16:41 +0530)
committerSam Hague <shague@redhat.com>
Fri, 21 Apr 2017 18:53:12 +0000 (18:53 +0000)
This commit adds support for VNI based datapath forwarding for VxLAN
based provider networks.
Spec: https://git.opendaylight.org/gerrit/#/c/48640/

a. Unicast
  1. Table 51 now sets VNI in tun_id field for packets egressing on
     tunnel ports
  2. On egress, table 36 now matches on VNI in tun_id field, sets the
     ELAN tag in metadata, and forwards the traffic to table 51

b. Broadcast
  1. Remote broadcast group now sets VNI in tun_id field for packets
     egressing on tunnel ports
  2. On egress, table 36 now matches on VNI in tun_id field, sets the
     ELAN tag in metadata, and forwards the traffic to table 51

Also, integrates the openstack-vni-semantics-enforced flag to enable
easier turning on/off of the feature

Change-Id: I7a6b14897344a8d00cb19291602d92cf586f15f7
Signed-off-by: Abhinav Gupta <abhinav.gupta@ericsson.com>
20 files changed:
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/ElanInterfaceManager.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/l2gw/utils/L2GatewayConnectionUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java
vpnservice/elanmanager/elanmanager-impl/src/main/resources/initial/netvirt-elanmanager-config.xml
vpnservice/elanmanager/elanmanager-impl/src/main/resources/org/opendaylight/blueprint/elanmanager.xml
vpnservice/elanmanager/elanmanager-impl/src/main/yang/elanmanager-config.yang
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/ExternalRoutersListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NaptEventHandler.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NaptSwitchHA.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatTunnelInterfaceStateListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/NatUtil.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/RouterDpnChangeListener.java
vpnservice/natservice/natservice-impl/src/main/java/org/opendaylight/netvirt/natservice/internal/VpnFloatingIpHandler.java
vpnservice/neutronvpn/neutronvpn-api/src/main/java/org/opendaylight/netvirt/neutronvpn/interfaces/INeutronVpnManager.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManagerImpl.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/resources/initial/netvirt-neutronvpn-config.xml
vpnservice/neutronvpn/neutronvpn-impl/src/main/yang/neutronvpn-config.yang

index b18fdbba64b907b3ab3c5d4db42cc52448770001..9dd220d9ffce80676caa17de591a12655b20b737 100644 (file)
@@ -72,4 +72,6 @@ public interface IElanService extends IEtreeService {
 
     List<MatchInfoBase> getEgressMatchesForElanInstance(String elanInstanceName);
 
+    Boolean isOpenStackVniSemanticsEnforced();
+
 }
index 6ff8f66a2e549738dbdbfa486f24917b14d917ab..039b856245fb39d0a2085defaa32dba140baae51 100644 (file)
@@ -7,6 +7,9 @@
  */
 package org.opendaylight.netvirt.elan.internal;
 
+import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlan;
+import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
+
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
@@ -40,6 +43,7 @@ import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.InstructionInfo;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MatchInfoBase;
 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
 import org.opendaylight.genius.mdsalutil.NwConstants;
 import org.opendaylight.genius.mdsalutil.actions.ActionDrop;
@@ -48,6 +52,7 @@ import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
 import org.opendaylight.genius.mdsalutil.actions.ActionRegLoad;
 import org.opendaylight.genius.mdsalutil.actions.ActionSetFieldTunnelId;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
+import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteActions;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
@@ -132,10 +137,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
 
     @Inject
-    public ElanInterfaceManager(final DataBroker dataBroker,
-                                final IdManagerService managerService,
-                                final IMdsalApiManager mdsalApiManager,
-                                IInterfaceManager interfaceManager,
+    public ElanInterfaceManager(final DataBroker dataBroker, final IdManagerService managerService,
+                                final IMdsalApiManager mdsalApiManager, IInterfaceManager interfaceManager,
                                 final ElanForwardingEntriesHandler elanForwardingEntriesHandler) {
         super(ElanInterface.class, ElanInterfaceManager.class);
         this.broker = dataBroker;
@@ -207,8 +210,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
         if (interfaceInfo != null) {
             dpId = interfaceInfo.getDpId();
-            DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId, interfaceName,
-                    elanTag, tx);
+            DpnInterfaces dpnInterfaces = removeElanDpnInterfaceFromOperationalDataStore(elanName, dpId,
+                    interfaceName, elanTag, tx);
             /*
              * If there are not elan ports, remove the unknown dmac, terminating
              * service table flows, remote/local bc group
@@ -217,13 +220,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                     || dpnInterfaces.getInterfaces().isEmpty()) {
                 // No more Elan Interfaces in this DPN
                 LOG.debug("deleting the elan: {} present on dpId: {}", elanInfo.getElanInstanceName(), dpId);
-                removeDefaultTermFlow(dpId, elanInfo.getElanTag());
+                if (!elanUtils.isOpenStackVniSemanticsEnforced()) {
+                    removeDefaultTermFlow(dpId, elanInfo.getElanTag());
+                }
                 removeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx, elanInfo.getElanTag());
                 removeEtreeUnknownDmacFlow(dpId, elanInfo, deleteFlowGroupTx);
                 removeElanBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
                 removeLocalBroadcastGroup(elanInfo, interfaceInfo, deleteFlowGroupTx);
                 removeEtreeBroadcastGrups(elanInfo, interfaceInfo, deleteFlowGroupTx);
-                if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVxlanSegment(elanInfo)) {
+                if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
+                    if (elanUtils.isOpenStackVniSemanticsEnforced()) {
+                        elanUtils.removeTerminatingServiceAction(dpId, elanInfo.getSegmentationId().intValue());
+                    }
                     unsetExternalTunnelTable(dpId, elanInfo);
                 }
                 isLastInterfaceOnDpn = true;
@@ -233,8 +241,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
         futures.add(ElanUtils.waitForTransactionToComplete(tx));
         futures.add(ElanUtils.waitForTransactionToComplete(deleteFlowGroupTx));
-        if (isLastInterfaceOnDpn && dpId != null
-                && (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVxlanSegment(elanInfo))) {
+
+        if (isLastInterfaceOnDpn && dpId != null && isVxlanNetworkOrVxlanSegment(elanInfo)) {
             setElanAndEtreeBCGrouponOtherDpns(elanInfo, dpId);
         }
         DataStoreJobCoordinator coordinator = DataStoreJobCoordinator.getInstance();
@@ -333,9 +341,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         }
     }
 
-    void removeEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo,
-            InterfaceInfo interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved,
-            boolean isLastElanInterface) {
+    void removeEntriesForElanInterface(List<ListenableFuture<Void>> futures, ElanInstance elanInfo, InterfaceInfo
+            interfaceInfo, String interfaceName, boolean isInterfaceStateRemoved, boolean isLastElanInterface) {
         String elanName = elanInfo.getElanInstanceName();
         WriteTransaction tx = broker.newWriteOnlyTransaction();
         WriteTransaction deleteFlowGroupTx = broker.newWriteOnlyTransaction();
@@ -367,7 +374,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
                 // Removing all those MACs from External Devices belonging
                 // to this ELAN
-                if ((ElanUtils.isVxlan(elanInfo) || (ElanUtils.isVxlanSegment(elanInfo))) && ! macAddresses.isEmpty()) {
+                if ((isVxlanNetworkOrVxlanSegment(elanInfo)) && ! macAddresses.isEmpty()) {
                     elanL2GatewayUtils.removeMacsFromElanExternalDevices(elanInfo, macAddresses);
                 }
             }
@@ -391,7 +398,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             tx.delete(LogicalDatastoreType.OPERATIONAL, elanInterfaceId);
         }
         if (!isInterfaceStateRemoved) {
-            unbindService(elanInfo, interfaceName, tx);
+            unbindService(interfaceName, tx);
         }
         deleteElanInterfaceFromConfigDS(interfaceName, tx);
         futures.add(ElanUtils.waitForTransactionToComplete(tx));
@@ -399,7 +406,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     private DpnInterfaces removeElanDpnInterfaceFromOperationalDataStore(String elanName, BigInteger dpId,
-            String interfaceName, long elanTag, WriteTransaction tx) {
+                                                                         String interfaceName, long elanTag,
+                                                                         WriteTransaction tx) {
         DpnInterfaces dpnInterfaces = elanUtils.getElanInterfaceInfoByElanDpn(elanName, dpId);
         if (dpnInterfaces != null) {
             List<String> interfaceLists = dpnInterfaces.getInterfaces();
@@ -632,7 +640,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
                 // The 1st ElanInterface in a DPN must program the Ext Tunnel
                 // table, but only if Elan has VNI
-                if ((ElanUtils.isVxlan(elanInstance) || (ElanUtils.isVxlanSegment(elanInstance)))) {
+                if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
                     setExternalTunnelTable(dpId, elanInstance);
                 }
                 elanL2GatewayUtils.installElanL2gwDevicesLocalMacsInDpn(dpId, elanInstance, interfaceName);
@@ -656,7 +664,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             installEntriesForFirstInterfaceonDpn(elanInstance, interfaceInfo, dpnInterfaces, isFirstInterfaceInDpn, tx);
         }
         futures.add(ElanUtils.waitForTransactionToComplete(tx));
-        if (isFirstInterfaceInDpn && (ElanUtils.isVxlan(elanInstance) || ElanUtils.isVxlanSegment(elanInstance))) {
+        if (isFirstInterfaceInDpn && isVxlanNetworkOrVxlanSegment(elanInstance)) {
             //update the remote-DPNs remoteBC group entry with Tunnels
             LOG.trace("update remote bc group for elan {} on other DPNs for newly added dpn {}", elanInstance, dpId);
             setElanAndEtreeBCGrouponOtherDpns(elanInstance, dpId);
@@ -754,11 +762,17 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             return;
         }
         BigInteger dpId = interfaceInfo.getDpId();
-        elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx);
+        if (!elanUtils.isOpenStackVniSemanticsEnforced()) {
+            elanUtils.setupTermDmacFlows(interfaceInfo, mdsalManager, writeFlowGroupTx);
+        }
         setupFilterEqualsTable(elanInstance, interfaceInfo, writeFlowGroupTx);
         if (isFirstInterfaceInDpn) {
             // Terminating Service , UnknownDMAC Table.
-            setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
+            // The 1st ELAN Interface in a DPN must program the INTERNAL_TUNNEL_TABLE, but only if the network type
+            // for ELAN Instance is VxLAN
+            if (isVxlan(elanInstance)) {
+                setupTerminateServiceTable(elanInstance, dpId, writeFlowGroupTx);
+            }
             setupUnknownDMacTable(elanInstance, dpId, writeFlowGroupTx);
             /*
              * Install remote DMAC flow. This is required since this DPN is
@@ -807,7 +821,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
                 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
-                getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
+                elanUtils.getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
                 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
 
         mdsalManager.addFlowToTx(interfaceInfo.getDpId(), flow, writeFlowGroupTx);
@@ -826,7 +840,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_FILTER_EQUALS_TABLE,
                 getFlowRef(NwConstants.ELAN_FILTER_EQUALS_TABLE, ifTag), 9, elanInfo.getElanInstanceName(), 0, 0,
                 ElanConstants.COOKIE_ELAN_FILTER_EQUALS.add(BigInteger.valueOf(ifTag)),
-                getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
+                elanUtils.getTunnelIdMatchForFilterEqualsLPortTag(ifTag),
                 elanUtils.getInstructionsInPortForOutGroup(interfaceInfo.getInterfaceName()));
 
         mdsalManager.removeFlowToTx(interfaceInfo.getDpId(), flow, deleteFlowGroupTx);
@@ -840,7 +854,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     private List<Bucket> getRemoteBCGroupBucketInfos(ElanInstance elanInfo, int bucketKeyStart,
-            InterfaceInfo interfaceInfo, long elanTag) {
+                                                     InterfaceInfo interfaceInfo, long elanTag) {
         return getRemoteBCGroupBuckets(elanInfo, null, interfaceInfo.getDpId(), bucketKeyStart, elanTag);
     }
 
@@ -848,8 +862,10 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                                                 int bucketId, long elanTag) {
         List<Bucket> listBucketInfo = new ArrayList<>();
         ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
-        if (ElanUtils.isVxlan(elanInfo)) {
-            listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId, elanTag));
+
+        if (isVxlan(elanInfo)) {
+            listBucketInfo.addAll(getRemoteBCGroupTunnelBuckets(elanDpns, dpnId, bucketId,
+                    elanUtils.isOpenStackVniSemanticsEnforced() ? elanInfo.getSegmentationId() : elanTag));
         }
         listBucketInfo.addAll(getRemoteBCGroupExternalPortBuckets(elanDpns, dpnInterfaces, dpnId,
             getNextAvailableBucketId(listBucketInfo.size())));
@@ -864,7 +880,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     @SuppressWarnings("checkstyle:IllegalCatch")
     private List<Bucket> getRemoteBCGroupTunnelBuckets(ElanDpnInterfacesList elanDpns, BigInteger dpnId, int bucketId,
-            long elanTag) {
+            long elanTagOrVni) {
         List<Bucket> listBucketInfo = new ArrayList<>();
         if (elanDpns != null) {
             for (DpnInterfaces dpnInterface : elanDpns.getDpnInterfaces()) {
@@ -872,7 +888,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                         && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
                     try {
                         List<Action> listActionInfo = elanUtils.getInternalTunnelItmEgressAction(dpnId,
-                                dpnInterface.getDpId(), elanTag);
+                                dpnInterface.getDpId(), elanTagOrVni);
                         if (listActionInfo.isEmpty()) {
                             continue;
                         }
@@ -896,7 +912,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 || currDpnInterfaces.getInterfaces() == null || currDpnInterfaces.getInterfaces().isEmpty()) {
             return Collections.emptyList();
         }
-
         List<Bucket> listBucketInfo = new ArrayList<>();
         for (String interfaceName : currDpnInterfaces.getInterfaces()) {
             if (interfaceManager.isExternalInterface(interfaceName)) {
@@ -932,7 +947,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
             long etreeLeafGroupId = ElanUtils.getEtreeLeafRemoteBCGId(etreeLeafTag);
             setBCGrouponOtherDpns(elanInfo, dpId, etreeLeafTag, etreeLeafGroupId);
         }
-
     }
 
     @SuppressWarnings("checkstyle:IllegalCatch")
@@ -940,8 +954,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         int bucketId = 0;
         ElanDpnInterfacesList elanDpns = elanUtils.getElanDpnInterfacesList(elanInfo.getElanInstanceName());
         if (elanDpns != null) {
-            List<DpnInterfaces> dpnInterfaceses = elanDpns.getDpnInterfaces();
-            for (DpnInterfaces dpnInterface : dpnInterfaceses) {
+            List<DpnInterfaces> dpnInterfaces = elanDpns.getDpnInterfaces();
+            for (DpnInterfaces dpnInterface : dpnInterfaces) {
                 List<Bucket> remoteListBucketInfo = new ArrayList<>();
                 if (elanUtils.isDpnPresent(dpnInterface.getDpId()) && !Objects.equals(dpnInterface.getDpId(), dpId)
                         && dpnInterface.getInterfaces() != null && !dpnInterface.getInterfaces().isEmpty()) {
@@ -951,17 +965,18 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                     remoteListBucketInfo.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId,
                             MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
                     bucketId++;
-                    for (DpnInterfaces otherFes : dpnInterfaceses) {
+                    for (DpnInterfaces otherFes : dpnInterfaces) {
                         if (elanUtils.isDpnPresent(otherFes.getDpId()) && !Objects.equals(otherFes.getDpId(),
                             dpnInterface.getDpId()) && otherFes.getInterfaces() != null
                             && !otherFes.getInterfaces().isEmpty()) {
                             try {
                                 List<Action> remoteListActionInfo = elanUtils.getInternalTunnelItmEgressAction(
-                                        dpnInterface.getDpId(), otherFes.getDpId(), elanTag);
+                                        dpnInterface.getDpId(), otherFes.getDpId(),
+                                        elanUtils.isOpenStackVniSemanticsEnforced() ? elanInfo.getSegmentationId()
+                                                : elanTag);
                                 if (!remoteListActionInfo.isEmpty()) {
-                                    remoteListBucketInfo
-                                            .add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil.GROUP_WEIGHT,
-                                                    bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
+                                    remoteListBucketInfo.add(MDSALUtil.buildBucket(remoteListActionInfo, MDSALUtil
+                                            .GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT, MDSALUtil.WATCH_GROUP));
                                     bucketId++;
                                 }
                             } catch (Exception ex) {
@@ -1010,11 +1025,9 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return mkMatches;
     }
 
-    private List<Instruction> getInstructionsForOutGroup(long groupId) {
-        List<Instruction> mkInstructions = new ArrayList<>();
-        List<Action> actions = new ArrayList<>();
-        actions.add(new ActionGroup(groupId).buildAction());
-        mkInstructions.add(MDSALUtil.getWriteActionsInstruction(actions, 0));
+    private List<InstructionInfo> getInstructionsForOutGroup(long groupId) {
+        List<InstructionInfo> mkInstructions = new ArrayList<>();
+        mkInstructions.add(new InstructionWriteActions(Collections.singletonList(new ActionGroup(groupId))));
         return mkInstructions;
     }
 
@@ -1027,21 +1040,21 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
     }
 
     /**
-     * Builds the list of instructions to be installed in the External Tunnel
-     * table (38), which so far consists in writing the elanTag in metadata and
-     * send packet to the new DHCP table.
+     * Builds the list of instructions to be installed in the INTERNAL_TUNNEL_TABLE (36) / EXTERNAL_TUNNEL_TABLE (38)
+     * which so far consists of writing the elanTag in metadata and send the packet to ELAN_DMAC_TABLE.
      *
      * @param elanTag
      *            elanTag to be written in metadata when flow is selected
      * @return the instructions ready to be installed in a flow
      */
-    private List<InstructionInfo> getInstructionsExtTunnelTable(Long elanTag) {
+    private List<InstructionInfo> getInstructionsIntOrExtTunnelTable(Long elanTag) {
         List<InstructionInfo> mkInstructions = new ArrayList<>();
-        mkInstructions.add(
-                new InstructionWriteMetadata(ElanUtils.getElanMetadataLabel(elanTag), ElanUtils.getElanMetadataMask()));
-        // TODO: We should point to SMAC or DMAC depending on a configuration property to enable MAC learning
+        mkInstructions.add(new InstructionWriteMetadata(ElanUtils.getElanMetadataLabel(elanTag), ElanUtils
+                .getElanMetadataMask()));
+        /* applicable for EXTERNAL_TUNNEL_TABLE only
+        * TODO: We should point to SMAC or DMAC depending on a configuration property to enable mac learning
+        */
         mkInstructions.add(new InstructionGotoTable(NwConstants.ELAN_DMAC_TABLE));
-
         return mkInstructions;
     }
 
@@ -1060,7 +1073,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                         interfaceInfo.getDpId())) {
                     LOG.info("Acquired lock for mac : " + macAddress + ". Proceeding with remote dmac"
                             + " install operation.");
-                    elanUtils.setupDMacFlowonRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress,
+                    elanUtils.setupDMacFlowOnRemoteDpn(elanInfo, interfaceInfo, dstDpId, macAddress,
                             writeFlowTx);
                 }
             }
@@ -1087,8 +1100,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         listBucket.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
                 MDSALUtil.WATCH_GROUP));
         bucketId++;
-        List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId,
-                elanInfo.getElanTag());
+        List<Bucket> listBucketInfoRemote = getRemoteBCGroupBuckets(elanInfo, dpnInterfaces, dpnId, bucketId, elanTag);
         listBucket.addAll(listBucketInfoRemote);
         long groupId = ElanUtils.getElanRemoteBCGId(elanTag);
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
@@ -1246,7 +1258,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         listBuckets.add(MDSALUtil.buildBucket(listAction, MDSALUtil.GROUP_WEIGHT, bucketId, MDSALUtil.WATCH_PORT,
                 MDSALUtil.WATCH_GROUP));
         bucketId++;
-        listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanInfo.getElanTag()));
+        listBuckets.addAll(getRemoteBCGroupBucketInfos(elanInfo, bucketId, interfaceInfo, elanTag));
         BigInteger dpnId = interfaceInfo.getDpId();
         long groupId = ElanUtils.getElanRemoteBCGId(elanInfo.getElanTag());
         Group group = MDSALUtil.buildGroup(groupId, elanInfo.getElanInstanceName(), GroupTypes.GroupAll,
@@ -1273,7 +1285,8 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 0, // idleTimeout
                 0, // hardTimeout
                 ITMConstants.COOKIE_ITM_EXTERNAL.add(BigInteger.valueOf(elanTag)),
-                buildMatchesForVni(ElanUtils.getVxlanSegmentationId(elanInfo)), getInstructionsExtTunnelTable(elanTag));
+                buildMatchesForVni(ElanUtils.getVxlanSegmentationId(elanInfo)),
+                getInstructionsIntOrExtTunnelTable(elanTag));
 
         mdsalManager.installFlow(flowEntity);
     }
@@ -1308,14 +1321,20 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     public void setupTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId, long elanTag,
             WriteTransaction writeFlowGroupTx) {
-        Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
-                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), 5,
-                String.format("%s:%d", "ITM Flow Entry ", elanTag), 0, 0,
-                ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)),
-                ElanUtils.getTunnelMatchesForServiceId((int) elanTag),
-                getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
-
-        mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
+        List<? extends MatchInfoBase> listMatchInfoBase;
+        List<InstructionInfo> instructionInfos;
+        if (!elanUtils.isOpenStackVniSemanticsEnforced()) {
+            listMatchInfoBase = ElanUtils.getTunnelMatchesForServiceId((int) elanTag);
+            instructionInfos = getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag));
+        } else {
+            listMatchInfoBase = buildMatchesForVni(elanInfo.getSegmentationId());
+            instructionInfos = getInstructionsIntOrExtTunnelTable(elanTag);
+        }
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.INTERNAL_TUNNEL_TABLE,
+                getFlowRef(NwConstants.INTERNAL_TUNNEL_TABLE, elanTag), 5, String.format("%s:%d", "ITM Flow Entry ",
+                elanTag), 0, 0, ITMConstants.COOKIE_ITM.add(BigInteger.valueOf(elanTag)), listMatchInfoBase,
+                instructionInfos);
+        mdsalManager.addFlowToTx(flowEntity, writeFlowGroupTx);
     }
 
     private void setupEtreeTerminateServiceTable(ElanInstance elanInfo, BigInteger dpId,
@@ -1345,30 +1364,28 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
 
     private void installLocalUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
             WriteTransaction writeFlowGroupTx) {
-        Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
-                getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
-                        /* SH flag */false),
+        FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
+                getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,/* SH flag */false),
                 5, elanInfo.getElanInstanceName(), 0, 0,
                 ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
                 getMatchesForElanTag(elanTag, /* SH flag */false),
                 getInstructionsForOutGroup(ElanUtils.getElanRemoteBCGId(elanTag)));
 
-        mdsalManager.addFlowToTx(dpId, flowEntity, writeFlowGroupTx);
+        mdsalManager.addFlowToTx(flowEntity, writeFlowGroupTx);
     }
 
     private void installRemoteUnknownFlow(ElanInstance elanInfo, BigInteger dpId, long elanTag,
             WriteTransaction writeFlowGroupTx) {
         // only if ELAN can connect to external network, perform the following
-        if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVxlanSegment(elanInfo)
-                || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
-            Flow flowEntity2 = MDSALUtil.buildFlowNew(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
-                    getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,
-                            /* SH flag */true),
+
+        if (isVxlanNetworkOrVxlanSegment(elanInfo) || ElanUtils.isVlan(elanInfo) || ElanUtils.isFlat(elanInfo)) {
+            FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
+                    getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE, elanTag,/* SH flag */true),
                     5, elanInfo.getElanInstanceName(), 0, 0,
                     ElanConstants.COOKIE_ELAN_UNKNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
                     getMatchesForElanTag(elanTag, /* SH flag */true),
                     getInstructionsForOutGroup(ElanUtils.getElanLocalBCGId(elanTag)));
-            mdsalManager.addFlowToTx(dpId, flowEntity2, writeFlowGroupTx);
+            mdsalManager.addFlowToTx(flowEntity, writeFlowGroupTx);
         }
     }
 
@@ -1379,7 +1396,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 elanTag, /* SH flag */ false))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE).build();
         mdsalManager.removeFlowToTx(dpId, flow, deleteFlowGroupTx);
 
-        if (ElanUtils.isVxlan(elanInfo) || ElanUtils.isVxlanSegment(elanInfo)) {
+        if (isVxlanNetworkOrVxlanSegment(elanInfo)) {
             Flow flow2 = new FlowBuilder().setId(new FlowId(getUnknownDmacFlowRef(NwConstants.ELAN_UNKNOWN_DMAC_TABLE,
                     elanTag, /* SH flag */ true))).setTableId(NwConstants.ELAN_UNKNOWN_DMAC_TABLE)
                     .build();
@@ -1391,8 +1408,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         elanUtils.removeTerminatingServiceAction(dpId, (int) elanTag);
     }
 
-    private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag,
-            WriteTransaction tx) {
+    private void bindService(ElanInstance elanInfo, ElanInterface elanInterface, int lportTag, WriteTransaction tx) {
         if (isStandardElanService(elanInterface)) {
             bindElanService(elanInfo.getElanTag(), elanInfo.getElanInstanceName(),
                     elanInterface.getName(), lportTag, tx);
@@ -1455,7 +1471,7 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return elanInstance.getAugmentation(EtreeInstance.class) == null;
     }
 
-    private void unbindService(ElanInstance elanInfo, String interfaceName, WriteTransaction tx) {
+    private void unbindService(String interfaceName, WriteTransaction tx) {
         short elanServiceIndex = ServiceIndex.getIndex(NwConstants.ELAN_SERVICE_NAME, NwConstants.ELAN_SERVICE_INDEX);
         InstanceIdentifier<BoundServices> bindServiceId = ElanUtils.buildServiceId(interfaceName, elanServiceIndex);
         Optional<BoundServices> existingElanService = elanUtils.read(broker, LogicalDatastoreType.CONFIGURATION,
@@ -1716,13 +1732,6 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
         return mkMatches;
     }
 
-    private List<MatchInfo> getTunnelIdMatchForFilterEqualsLPortTag(int lportTag) {
-        List<MatchInfo> mkMatches = new ArrayList<>();
-        // Matching metadata
-        mkMatches.add(new MatchTunnelId(BigInteger.valueOf(lportTag)));
-        return mkMatches;
-    }
-
     public void updateRemoteBroadcastGroupForAllElanDpns(ElanInstance elanInfo) {
         List<DpnInterfaces> dpns = elanUtils.getInvolvedDpnsInElan(elanInfo.getElanInstanceName());
         if (dpns == null) {
index 2855abde569395672728831b8ab7b4b0471ebef7..57142ac2090af80a10727fa02a8f8d976235e5e6 100644 (file)
@@ -134,6 +134,11 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
     protected void stop() throws Exception {
     }
 
+    @Override
+    public Boolean isOpenStackVniSemanticsEnforced() {
+        return elanUtils.isOpenStackVniSemanticsEnforced();
+    }
+
     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();
@@ -616,7 +621,6 @@ public class ElanServiceProvider extends AbstractLifecycle implements IElanServi
             LOG.debug("No ELAN tag found for {}", elanInstanceName);
             return Collections.emptyList();
         }
-
         return Collections.singletonList(
                 new NxMatchRegister(ElanConstants.ELAN_REG_ID, elanTag, MetaDataUtil.getElanMaskForReg()));
     }
index 7cf214c40cd1178d38c2bbcc9e5cdbfddeb2d5f1..b39cd151eed49fcafcae87604afe864e3a437738 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.netvirt.elan.l2gw.utils;
 
+import static org.opendaylight.netvirt.elan.utils.ElanUtils.isVxlanNetworkOrVxlanSegment;
+
 import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.Futures;
@@ -161,7 +163,7 @@ public class L2GatewayConnectionUtils {
             });
             return;
         }
-        if (!ElanUtils.isVxlan(elanInstance) && !ElanUtils.isVxlanSegment(elanInstance)) {
+        if (!isVxlanNetworkOrVxlanSegment(elanInstance)) {
             LOG.error("Neutron network with id {} is not VxlanNetwork", networkUuid.getValue());
         } else {
             Uuid l2GatewayId = input.getL2gatewayId();
index f5eb6f07fbaed6da08bcdb65b903e65059defc71..37c9873fd435f3f05681eebf2ea91ce6db2d56f0 100755 (executable)
@@ -111,8 +111,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.ser
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.ExternalTunnelList;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnelKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.CreateTerminatingServiceActionsInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.GetExternalTunnelInterfaceNameOutput;
@@ -126,6 +124,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.config.rev150710.ElanConfig;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInstanceBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.etree.rev160614.EtreeInterface;
@@ -195,6 +194,7 @@ public class ElanUtils {
     private final ElanL2GatewayMulticastUtils elanL2GatewayMulticastUtils;
     private final L2GatewayConnectionUtils l2GatewayConnectionUtils;
     private final IInterfaceManager interfaceManager;
+    private final ElanConfig elanConfig;
 
     public static final FutureCallback<Void> DEFAULT_CALLBACK = new FutureCallback<Void>() {
         @Override
@@ -211,7 +211,7 @@ public class ElanUtils {
     @Inject
     public ElanUtils(DataBroker dataBroker, IMdsalApiManager mdsalManager, ElanInstanceManager elanInstanceManager,
                      OdlInterfaceRpcService interfaceManagerRpcService, ItmRpcService itmRpcService,
-                     ElanInterfaceManager elanInterfaceManager,
+                     ElanInterfaceManager elanInterfaceManager, ElanConfig elanConfig,
                      EntityOwnershipService entityOwnershipService, IInterfaceManager interfaceManager) {
         this.broker = dataBroker;
         this.mdsalManager = mdsalManager;
@@ -219,6 +219,7 @@ public class ElanUtils {
         this.interfaceManagerRpcService = interfaceManagerRpcService;
         this.itmRpcService = itmRpcService;
         this.interfaceManager = interfaceManager;
+        this.elanConfig = elanConfig;
 
         elanL2GatewayMulticastUtils =
                 new ElanL2GatewayMulticastUtils(broker, elanInstanceManager, elanInterfaceManager, this);
@@ -245,6 +246,10 @@ public class ElanUtils {
         return l2GatewayConnectionUtils;
     }
 
+    public final Boolean isOpenStackVniSemanticsEnforced() {
+        return elanConfig.isOpenstackVniSemanticsEnforced();
+    }
+
     public static void addElanInstanceIntoCache(String elanInstanceName, ElanInstance elanInstance) {
         elanInstanceLocalCache.put(elanInstanceName, elanInstance);
     }
@@ -303,7 +308,7 @@ public class ElanUtils {
 
     public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
         ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
-        Future<RpcResult<Void>> result = idManager.releaseId(releaseIdInput);
+        idManager.releaseId(releaseIdInput);
     }
 
     /**
@@ -667,7 +672,7 @@ public class ElanUtils {
     }
 
     /**
-     * Setting INTERNAL_TUNNEL_TABLE, SMAC, DMAC, UDMAC in this DPN and optionally in other DPNs.
+     * Setting SMAC, DMAC, UDMAC in this DPN and optionally in other DPNs.
      *
      * @param elanInfo
      *            the elan info
@@ -694,12 +699,11 @@ public class ElanUtils {
         }
     }
 
-    public void setupDMacFlowonRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId,
-            String macAddress, WriteTransaction writeFlowTx) throws ElanException {
+    public void setupDMacFlowOnRemoteDpn(ElanInstance elanInfo, InterfaceInfo interfaceInfo, BigInteger dstDpId,
+                                         String macAddress, WriteTransaction writeFlowTx) throws ElanException {
         String elanInstanceName = elanInfo.getElanInstanceName();
-        setupRemoteDmacFlow(dstDpId, interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag(),
-                elanInfo.getElanTag(), macAddress, elanInstanceName, writeFlowTx,
-                interfaceInfo.getInterfaceName(), elanInfo);
+        setupRemoteDmacFlow(dstDpId, interfaceInfo.getDpId(), interfaceInfo.getInterfaceTag(), elanInfo.getElanTag(),
+                macAddress, elanInstanceName, writeFlowTx, interfaceInfo.getInterfaceName(), elanInfo);
         LOG.info("Remote Dmac flow entry created for elan Name:{}, logical port Name:{} and"
                 + " mac address {} on dpn:{}", elanInstanceName, interfaceInfo.getPortName(),
                 macAddress, dstDpId);
@@ -726,7 +730,6 @@ public class ElanUtils {
         mkMatches.add(new MatchEthernetSource(new MacAddress(macAddress)));
         List<InstructionInfo> mkInstructions = new ArrayList<>();
         mkInstructions.add(new InstructionGotoTable(NwConstants.ELAN_DMAC_TABLE));
-
         BigInteger dpId = interfaceInfo.getDpId();
         long elanTag = getElanTag(broker, elanInfo, interfaceInfo);
         FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_SMAC_TABLE,
@@ -771,7 +774,7 @@ public class ElanUtils {
      *            the writeFLowGroup tx
      */
     public void setupTermDmacFlows(InterfaceInfo interfaceInfo, IMdsalApiManager mdsalApiManager,
-            WriteTransaction writeFlowGroupTx) {
+                                   WriteTransaction writeFlowGroupTx) {
         BigInteger dpId = interfaceInfo.getDpId();
         int lportTag = interfaceInfo.getInterfaceTag();
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.INTERNAL_TUNNEL_TABLE,
@@ -903,16 +906,15 @@ public class ElanUtils {
                 continue;
             }
 
-            // 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
+            // For remote DPNs a flow is needed to indicate that packets of this ELAN going to this MAC need to be
+            // forwarded through the appropriate 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
+                    elanTag,  // identifier of the Elan
                     macAddress, // MAC to be programmed in remote DPN
-                    elanInstanceName, writeFlowGroupTx, ifName, elanInfo);
+                    elanInstanceName, writeFlowGroupTx, ifName, elanInfo
+            );
             LOG.debug("Remote Dmac flow entry created for elan Name:{}, logical port Name:{} and mac address:{} on"
                         + " dpn:{}", elanInstanceName, interfaceInfo.getPortName(), macAddress, elanDpn.getDpId());
         }
@@ -1017,24 +1019,30 @@ public class ElanUtils {
         return flow;
     }
 
-    public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-            String macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName,
-            ElanInstance elanInstance) throws ElanException {
+    public void setupRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag, String
+            macAddress, String displayName, WriteTransaction writeFlowGroupTx, String interfaceName, ElanInstance
+            elanInstance) throws ElanException {
         if (interfaceManager.isExternalInterface(interfaceName)) {
             LOG.debug("Ignoring install remote DMAC {} flow on provider interface {} elan {}",
                     macAddress, interfaceName, elanInstance.getElanInstanceName());
             return;
         }
-        Flow flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName,
+        Flow flowEntity;
+        // if openstack-vni-semantics are enforced, segmentation ID is passed as network VNI for VxLAN based provider
+        // networks, 0 otherwise
+        long lportTagOrVni = !isOpenStackVniSemanticsEnforced() ? lportTag : ((isVxlan(elanInstance))
+                ? elanInstance.getSegmentationId() : 0);
+        flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTagOrVni, elanTag, macAddress, displayName,
                 elanInstance);
         mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
-        setupEtreeRemoteDmacFlow(srcDpId, destDpId, lportTag, elanTag, macAddress, displayName, interfaceName,
+        setupEtreeRemoteDmacFlow(srcDpId, destDpId, lportTagOrVni, elanTag, macAddress, displayName, interfaceName,
                 writeFlowGroupTx, elanInstance);
     }
 
-    private void setupEtreeRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
-                                String macAddress, String displayName, String interfaceName,
-                                WriteTransaction writeFlowGroupTx, ElanInstance elanInstance) throws ElanException {
+    private void setupEtreeRemoteDmacFlow(BigInteger srcDpId, BigInteger destDpId, long lportTagOrVni, long elanTag,
+                                          String macAddress, String displayName, String interfaceName,
+                                          WriteTransaction writeFlowGroupTx, ElanInstance elanInstance)
+                                          throws ElanException {
         Flow flowEntity;
         EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
         if (etreeInterface != null) {
@@ -1044,7 +1052,7 @@ public class ElanUtils {
                     LOG.warn("Interface " + interfaceName
                             + " seems like it belongs to Etree but etreeTagName from elanTag " + elanTag + " is null.");
                 } else {
-                    flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTag,
+                    flowEntity = buildRemoteDmacFlowEntry(srcDpId, destDpId, lportTagOrVni,
                             etreeTagName.getEtreeLeafTag().getValue(), macAddress, displayName, elanInstance);
                     mdsalManager.addFlowToTx(srcDpId, flowEntity, writeFlowGroupTx);
                 }
@@ -1055,15 +1063,15 @@ public class ElanUtils {
     /**
      * Builds a Flow to be programmed in a remote DPN's DMAC table. This flow
      * consists in: Match: + elanTag in packet's metadata + packet going to a
-     * MAC known to be located in another DPN Actions: + set_tunnel_id(lportTag)
+     * MAC known to be located in another DPN Actions: + set_tunnel_id
      * + output ITM internal tunnel interface with the other DPN
      *
      * @param srcDpId
      *            the src Dpn Id
      * @param destDpId
      *            dest Dp Id
-     * @param lportTag
-     *            lport Tag
+     * @param lportTagOrVni
+     *            lportTag or network VNI
      * @param elanTag
      *            elan Tag
      * @param macAddress
@@ -1074,7 +1082,7 @@ public class ElanUtils {
      * @throws ElanException in case of issues creating the flow objects
      */
     @SuppressWarnings("checkstyle:IllegalCatch")
-    public Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, int lportTag, long elanTag,
+    public Flow buildRemoteDmacFlowEntry(BigInteger srcDpId, BigInteger destDpId, long lportTagOrVni, long elanTag,
             String macAddress, String displayName, ElanInstance elanInstance) throws ElanException {
         List<MatchInfo> mkMatches = new ArrayList<>();
         mkMatches.add(new MatchMetadata(getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
@@ -1092,13 +1100,13 @@ public class ElanUtils {
                             elanInstance);
                 }
                 actions = getEgressActionsForInterface(interfaceName, null);
-            } else {
-                actions = getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTag);
+            } else if (isVxlan(elanInstance)) {
+                actions = getInternalTunnelItmEgressAction(srcDpId, destDpId, lportTagOrVni);
             }
             mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
         } catch (Exception e) {
             LOG.error("Could not get egress actions to add to flow for srcDpId=" + srcDpId + ", destDpId=" + destDpId
-                    + ", lportTag=" + lportTag, e);
+                    + ", lportTag/VNI=" + lportTagOrVni, e);
         }
 
         Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
@@ -1327,9 +1335,8 @@ public class ElanUtils {
     }
 
     /**
-     * Builds the list of actions to be taken when sending the packet over a
-     * VxLan Tunnel Interface, such as setting the tunnel_id field, the vlanId
-     * if proceeds and output the packet over the right port.
+     * Builds the list of actions to be taken when sending the packet over a VxLan Tunnel Interface, such as setting
+     * the network VNI in the tunnel_id field.
      *
      * @param tunnelIfaceName
      *            the tunnel iface name
@@ -1346,8 +1353,8 @@ public class ElanUtils {
     }
 
     /**
-     * Builds the list of actions to be taken when sending the packet over
-     * external port such as tunnel, physical port etc.
+     * Builds the list of actions to be taken when sending the packet over external port such as tunnel, physical
+     * port etc.
      *
      * @param interfaceName
      *            the interface name
@@ -1418,38 +1425,34 @@ public class ElanUtils {
     }
 
     /**
-     * Builds the list of actions to be taken when sending the packet over an
-     * internal VxLan tunnel interface, such as setting the serviceTag on the
-     * VNI field of the VxLAN header, setting the vlanId if it proceeds and
-     * output the packet over the right port.
+     * Builds the list of actions to be taken when sending the packet over an internal VxLAN tunnel interface, such
+     * as setting the serviceTag/segmentationID on the VNI field of the VxLAN header, setting the vlanId if it proceeds
+     * and output the packet over the right port.
      *
      * @param sourceDpnId
      *            Dpn where the tunnelInterface is located
      * @param destinationDpnId
      *            Dpn where the packet must be sent to. It is used here in order
      *            to select the right tunnel interface.
-     * @param serviceTag
-     *            serviceId to be sent on the VxLAN header.
+     * @param tunnelKey
+     *            Tunnel key to be sent on the VxLAN header.
      * @return the internal itm egress action
      */
-    public List<Action> getInternalTunnelItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId,
-            long serviceTag) {
+    public List<Action> getInternalTunnelItmEgressAction(BigInteger sourceDpnId, BigInteger destinationDpnId, long
+            tunnelKey) {
         List<Action> result = Collections.emptyList();
-
-        LOG.trace("In getInternalItmEgressAction Action source {}, destination {}, serviceTag {}", sourceDpnId,
-                destinationDpnId, serviceTag);
+        LOG.trace("In getInternalItmEgressAction Action source {}, destination {}, serviceTag/Vni {}", sourceDpnId,
+                destinationDpnId, tunnelKey);
         Class<? extends TunnelTypeBase> tunType = TunnelTypeVxlan.class;
         GetTunnelInterfaceNameInput input = new GetTunnelInterfaceNameInputBuilder()
                 .setDestinationDpid(destinationDpnId).setSourceDpid(sourceDpnId).setTunnelType(tunType).build();
-        Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService
-                .getTunnelInterfaceName(input);
+        Future<RpcResult<GetTunnelInterfaceNameOutput>> output = itmRpcService.getTunnelInterfaceName(input);
         try {
             if (output.get().isSuccessful()) {
                 GetTunnelInterfaceNameOutput tunnelInterfaceNameOutput = output.get().getResult();
                 String tunnelIfaceName = tunnelInterfaceNameOutput.getInterfaceName();
                 LOG.info("Received tunnelInterfaceName from getTunnelInterfaceName RPC {}", tunnelIfaceName);
-
-                result = buildTunnelItmEgressActions(tunnelIfaceName, serviceTag);
+                result = buildTunnelItmEgressActions(tunnelIfaceName, tunnelKey);
             } else {
                 LOG.trace("Tunnel interface doesn't exist between srcDpId {} dstDpId {}", sourceDpnId,
                         destinationDpnId);
@@ -1457,7 +1460,6 @@ public class ElanUtils {
         } catch (InterruptedException | ExecutionException e) {
             LOG.error("Error in RPC call getTunnelInterfaceName {}", e);
         }
-
         return result;
     }
 
@@ -1484,29 +1486,22 @@ public class ElanUtils {
     public void removeTerminatingServiceAction(BigInteger destDpId, int serviceId) {
         RemoveTerminatingServiceActionsInput input = new RemoveTerminatingServiceActionsInputBuilder()
                 .setDpnId(destDpId).setServiceId(serviceId).build();
-        Future<RpcResult<Void>> futureObject = itmRpcService
-                .removeTerminatingServiceActions(input);
+        Future<RpcResult<Void>> futureObject = itmRpcService.removeTerminatingServiceActions(input);
         try {
             RpcResult<Void> result = futureObject.get();
             if (result.isSuccessful()) {
-                LOG.debug("Successfully completed removeTerminatingServiceActions");
+                LOG.debug("Successfully completed removeTerminatingServiceActions for ELAN with serviceId {} on "
+                                + "dpn {}", serviceId, destDpId);
             } else {
-                LOG.debug("Failure in removeTerminatingServiceAction RPC call");
+                LOG.debug("Failure in removeTerminatingServiceAction RPC call for ELAN with serviceId {} on "
+                        + "dpn {}", serviceId, destDpId);
             }
         } catch (InterruptedException | ExecutionException e) {
-            LOG.error("Error in RPC call removeTerminatingServiceActions {}", e);
+            LOG.error("Error in RPC call removeTerminatingServiceActions for ELAN with serviceId {} on "
+                    + "dpn {}: {}", serviceId, destDpId, e);
         }
     }
 
-    public void createTerminatingServiceActions(BigInteger destDpId, int serviceId, List<Action> actions) {
-        List<Instruction> mkInstructions = new ArrayList<>();
-        mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
-        CreateTerminatingServiceActionsInput input = new CreateTerminatingServiceActionsInputBuilder()
-                .setDpnId(destDpId).setServiceId(serviceId).setInstruction(mkInstructions).build();
-
-        itmRpcService.createTerminatingServiceActions(input);
-    }
-
     /**
      * Gets the external tunnel.
      *
@@ -1560,33 +1555,6 @@ public class ElanUtils {
                 Collections.emptyList());
     }
 
-    /**
-     * Installs a Flow in a DPN's DMAC table. The Flow is for a MAC that is
-     * connected remotely in another CSS and accessible through an internal
-     * tunnel. It also installs the flow for dropping the packet if it came over
-     * an ITM tunnel (that is, if the Split-Horizon flag is set)
-     *
-     * @param localDpId
-     *            Id of the DPN where the MAC Addr is accessible locally
-     * @param remoteDpId
-     *            Id of the DPN where the flow must be installed
-     * @param lportTag
-     *            lportTag of the interface where the mac is connected to.
-     * @param elanTag
-     *            Identifier of the ELAN
-     * @param macAddress
-     *            MAC to be installed in remoteDpId's DMAC table
-     * @param displayName
-     *            the display name
-     * @throws ElanException in case of issues creating the flow objects
-     */
-    public void installDmacFlowsToInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, int lportTag,
-            long elanTag, String macAddress, String displayName) throws ElanException {
-        Flow flow = buildDmacFlowForInternalRemoteMac(localDpId, remoteDpId, lportTag, elanTag, macAddress,
-                displayName);
-        mdsalManager.installFlow(remoteDpId, flow);
-    }
-
     /**
      * Installs a Flow in the specified DPN's DMAC table. The flow is for a MAC
      * that is connected remotely in an External Device (TOR) and that is
@@ -1676,7 +1644,6 @@ public class ElanUtils {
         mkMatches.add(
                 new MatchMetadata(getElanMetadataLabel(elanTag, shFlag), MetaDataUtil.METADATA_MASK_SERVICE_SH_FLAG));
         mkMatches.add(new MatchEthernetDestination(new MacAddress(macAddr)));
-
         return mkMatches;
     }
 
@@ -1757,57 +1724,6 @@ public class ElanUtils {
                 .toString();
     }
 
-    /**
-     * Builds a Flow to be programmed in a remote DPN's DMAC table. This method
-     * must be used when the MAC is located in another CSS.
-     *
-     * <p>This flow consists in: Match: + elanTag in packet's metadata + packet
-     * going to a MAC known to be located in another DPN Actions: +
-     * set_tunnel_id(lportTag) + output on ITM internal tunnel interface with
-     * the other DPN
-     *
-     * @param localDpId
-     *            the local dp id
-     * @param remoteDpId
-     *            the remote dp id
-     * @param lportTag
-     *            the lport tag
-     * @param elanTag
-     *            the elan tag
-     * @param macAddress
-     *            the mac address
-     * @param displayName
-     *            the display name
-     * @return the flow
-     * @throws ElanException in case of issues creating the flow objects
-     */
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    public Flow buildDmacFlowForInternalRemoteMac(BigInteger localDpId, BigInteger remoteDpId, int lportTag,
-            long elanTag, String macAddress, String displayName) throws ElanException {
-        List<MatchInfo> mkMatches = buildMatchesForElanTagShFlagAndDstMac(elanTag, /* shFlag */ false, macAddress);
-
-        List<Instruction> mkInstructions = new ArrayList<>();
-
-        try {
-            // List of Action for the provided Source and Destination DPIDs
-            List<Action> actions = getInternalTunnelItmEgressAction(localDpId, remoteDpId, lportTag);
-            mkInstructions.add(MDSALUtil.buildApplyActionsInstruction(actions));
-        } catch (Exception e) {
-            LOG.error("Could not get Egress Actions for localDpId=" + localDpId + ", remoteDpId="
-                    + remoteDpId + ", lportTag=" + lportTag, e);
-        }
-
-        Flow flow = MDSALUtil.buildFlowNew(NwConstants.ELAN_DMAC_TABLE,
-                getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, localDpId, remoteDpId, macAddress, elanTag),
-                20, /* prio */
-                displayName, 0, /* idleTimeout */
-                0, /* hardTimeout */
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)), mkMatches, mkInstructions);
-
-        return flow;
-
-    }
-
     /**
      * Installs or removes flows in DMAC table for MACs that are/were located in
      * an external Elan Device.
@@ -1989,18 +1905,18 @@ public class ElanUtils {
         return futures;
     }
 
+    public static boolean isVxlanNetwork(DataBroker broker, String elanInstanceName) {
+        ElanInstance elanInstance = getElanInstanceByName(broker, elanInstanceName);
+        return (elanInstance != null && isVxlan(elanInstance));
+    }
+
     public static boolean isVxlan(ElanInstance elanInstance) {
         return elanInstance != null && elanInstance.getSegmentType() != null
                 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeVxlan.class)
                 && elanInstance.getSegmentationId() != null && elanInstance.getSegmentationId() != 0;
     }
 
-    public static boolean isVxlanNetwork(DataBroker broker, String elanInstanceName) {
-        ElanInstance elanInstance = getElanInstanceByName(broker, elanInstanceName);
-        return (elanInstance != null && isVxlan(elanInstance));
-    }
-
-    public static boolean isVxlanSegment(ElanInstance elanInstance) {
+    private static boolean isVxlanSegment(ElanInstance elanInstance) {
         if (elanInstance != null) {
             List<ElanSegments> elanSegments = elanInstance.getElanSegments();
             if (elanSegments != null) {
@@ -2016,6 +1932,10 @@ public class ElanUtils {
         return false;
     }
 
+    public static boolean isVxlanNetworkOrVxlanSegment(ElanInstance elanInstance) {
+        return isVxlan(elanInstance) || isVxlanSegment(elanInstance);
+    }
+
     public static Long getVxlanSegmentationId(ElanInstance elanInstance) {
         Long segmentationId = 0L;
 
@@ -2046,11 +1966,6 @@ public class ElanUtils {
                 && elanInstance.getSegmentType().isAssignableFrom(SegmentTypeFlat.class);
     }
 
-    public static boolean isEtreeRootInterfaceByInterfaceName(DataBroker broker, String interfaceName) {
-        EtreeInterface etreeInterface = getEtreeInterfaceByElanInterfaceName(broker, interfaceName);
-        return etreeInterface != null && etreeInterface.getEtreeInterfaceType() == EtreeInterfaceType.Root;
-    }
-
     public void handleDmacRedirectToDispatcherFlows(Long elanTag, String displayName,
             String macAddress, int addOrRemove, List<BigInteger> dpnIds) {
         for (BigInteger dpId : dpnIds) {
@@ -2083,19 +1998,6 @@ public class ElanUtils {
         return flow;
     }
 
-    public static FlowEntity buildDmacRedirectToDispatcherFlowMacNoActions(BigInteger dpId, String dstMacAddress,
-            String displayName, long elanTag) {
-        List<MatchInfo> matches = new ArrayList<>();
-        matches.add(new MatchMetadata(getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE));
-        matches.add(new MatchEthernetDestination(new MacAddress(dstMacAddress)));
-
-        String flowId = getKnownDynamicmacFlowRef(NwConstants.ELAN_DMAC_TABLE, dpId, dstMacAddress, elanTag);
-        FlowEntity flow  = MDSALUtil.buildFlowEntity(dpId, NwConstants.ELAN_DMAC_TABLE, flowId, 20, displayName, 0, 0,
-                ElanConstants.COOKIE_ELAN_KNOWN_DMAC.add(BigInteger.valueOf(elanTag)),
-                matches, new ArrayList<>());
-        return flow;
-    }
-
     /**
      * Add Mac Address to ElanInterfaceForwardingEntries and ElanForwardingTables
      * Install SMAC and DMAC flows.
index bc3943b2ba332ee3dbd2b4ed874a893f2896d288..01be3bc069a5b376fba84ff52d17132cf7492d50 100644 (file)
@@ -9,4 +9,5 @@
   -->
   <auto-config-transport-zones>true</auto-config-transport-zones>
   <use-of-tunnels>false</use-of-tunnels>
+  <openstack-vni-semantics-enforced>false</openstack-vni-semantics-enforced>
 </elanmanager-config>
index fbb66088e8ed53ba5dcefa1f5b71069f44f8c435..7a543f8d265d75098d71bff66ae8a929f4d793fc 100644 (file)
@@ -95,6 +95,7 @@
     <argument ref="elanInterfaceManager" />
     <argument ref="entityOwnershipService" />
     <argument ref="interfaceManager" />
+    <argument ref="elanConfig" />
   </bean>
 
   <bean id="elanStatisticsImpl"
index c1cbfc0377b5d95a8c64bf4da8cc55fc97d14743..54f4e49bdcd6439329e09c8243bc8dcf48af6cd9 100644 (file)
@@ -56,5 +56,9 @@ module elan-config {
             type boolean;
             default false;
         }
+        leaf openstack-vni-semantics-enforced {
+            type boolean;
+            default false;
+        }
     }
 }
index bb18171ced5fff1111b7525bd838ac2145d89ed7..270673abd5578401715885835588f46ecdf483cd 100644 (file)
@@ -58,6 +58,7 @@ import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.genius.mdsalutil.matches.MatchMplsLabel;
 import org.opendaylight.genius.mdsalutil.matches.MatchTunnelId;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.natservice.api.CentralizedSwitchScheduler;
@@ -152,6 +153,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
     private final CentralizedSwitchScheduler  centralizedSwitchScheduler;
     private NatMode natMode = NatMode.Controller;
     private final INeutronVpnManager nvpnManager;
+    private final IElanService elanManager;
     private static final BigInteger COOKIE_TUNNEL = new BigInteger("9000000", 16);
     static final BigInteger COOKIE_VM_LFIB_TABLE = new BigInteger("8000022", 16);
 
@@ -173,7 +175,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                                    final EvpnSnatFlowProgrammer evpnSnatFlowProgrammer,
                                    final INeutronVpnManager nvpnManager,
                                    final CentralizedSwitchScheduler centralizedSwitchScheduler,
-                                   final NatserviceConfig config) {
+                                   final NatserviceConfig config,
+                                   final IElanService elanManager) {
         super(Routers.class, ExternalRoutersListener.class);
         this.dataBroker = dataBroker;
         this.mdsalManager = mdsalManager;
@@ -192,6 +195,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         this.vpnManager = vpnManager;
         this.evpnSnatFlowProgrammer = evpnSnatFlowProgrammer;
         this.nvpnManager = nvpnManager;
+        this.elanManager = elanManager;
         this.centralizedSwitchScheduler = centralizedSwitchScheduler;
         if (config != null) {
             this.natMode = config.getNatMode();
@@ -318,8 +322,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         }
         // Validating and creating VNI pool during when NAPT switch is selected.
         // With Assumption this might be the first NAT service comes up.
-        NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
-                idManager, NatConstants.ODL_VNI_POOL_NAME);
+        NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager, idManager,
+                NatConstants.ODL_VNI_POOL_NAME);
         primarySwitchId = naptSwitchSelector.selectNewNAPTSwitch(routerName);
         LOG.debug("NAT Service : Primary NAPT switch DPN ID {}", primarySwitchId);
         if (primarySwitchId == null || primarySwitchId.equals(BigInteger.ZERO)) {
@@ -676,8 +680,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(routerId), MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionsInfo = new ArrayList<>();
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, nvpnManager, idManager,
-                                                                    routerId, routerName);
+        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
+                routerName);
         actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
         LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
         actionsInfo.add(new ActionGroup(groupId));
@@ -733,8 +737,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         long routerId = NatUtil.getVpnId(dataBroker, routerName);
         List<MatchInfo> matches = new ArrayList<>();
         matches.add(MatchEthernetType.IPV4);
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, nvpnManager, idManager,
-                            routerId, routerName);
+        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
+                routerName);
         matches.add(new MatchTunnelId(BigInteger.valueOf(tunnelId)));
         String flowRef = getFlowRefTs(dpId, NwConstants.INTERNAL_TUNNEL_TABLE, tunnelId);
         List<InstructionInfo> instructions = new ArrayList<>();
@@ -984,7 +988,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         }
                         //Inform BGP
                         long l3vni = 0;
-                        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                        if (elanManager.isOpenStackVniSemanticsEnforced()) {
                             l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
                         }
                         Routers extRouter = router != null ? router :
@@ -1004,7 +1008,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
                         //Install custom FIB routes - FIB table.
                         List<Instruction> fibTableCustomInstructions = createFibTableCustomInstructions(dataBroker,
                                 tableId, routerName, externalIp);
-                        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                        if (elanManager.isOpenStackVniSemanticsEnforced()) {
                             //Install the flow table 25->44 If there is no FIP Match on table 25 (PDNAT_TABLE)
                             NatUtil.makePreDnatToSnatTableEntry(mdsalManager, dpnId,
                                     NwConstants.INBOUND_NAPT_TABLE);
@@ -1092,7 +1096,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         LOG.debug("NAT Service : Create terminatingServiceAction on DpnId = {} and serviceId = {} and actions = {}",
             dpnId, serviceId, customInstructions);
 
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+        if (elanManager.isOpenStackVniSemanticsEnforced()) {
             mkMatches.add(new MatchTunnelId(BigInteger.valueOf(l3Vni)));
         } else {
             mkMatches.add(new MatchTunnelId(BigInteger.valueOf(serviceId)));
@@ -2448,8 +2452,8 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         matches.add(new MatchMetadata(MetaDataUtil.getVpnIdMetadata(changedVpnId), MetaDataUtil.METADATA_MASK_VRFID));
 
         List<ActionInfo> actionsInfo = new ArrayList<>();
-        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, nvpnManager, idManager,
-                                                        changedVpnId, routerName);
+        long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, changedVpnId,
+                routerName);
         actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
         LOG.debug("NAT Service : Setting the tunnel to the list of action infos {}", actionsInfo);
         actionsInfo.add(new ActionGroup(groupId));
@@ -2502,7 +2506,7 @@ public class ExternalRoutersListener extends AsyncDataTreeChangeListenerBase<Rou
         matches.add(MatchEthernetType.IPV4);
 
         BigInteger tunnelId = BigInteger.valueOf(changedVpnId);
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+        if (elanManager.isOpenStackVniSemanticsEnforced()) {
             tunnelId = NatOverVxlanUtil.getRouterVni(idManager, routerName, changedVpnId);
         }
         matches.add(new MatchTunnelId(tunnelId));
index 2d1c276908acb1d03ff1f85d49e542177a28a3bf..2186ef109304df8d78b9b7300401d236457410a5 100644 (file)
@@ -57,7 +57,7 @@ import org.opendaylight.genius.mdsalutil.packet.Ethernet;
 import org.opendaylight.genius.mdsalutil.packet.IPv4;
 import org.opendaylight.genius.mdsalutil.packet.TCP;
 import org.opendaylight.genius.mdsalutil.packet.UDP;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -83,7 +83,7 @@ public class NaptEventHandler {
     private final PacketProcessingService pktService;
     private final OdlInterfaceRpcService interfaceManagerRpc;
     private final NaptManager naptManager;
-    private final INeutronVpnManager nvpnManager;
+    private final IElanService elanManager;
     private final IdManagerService idManager;
     private IInterfaceManager interfaceManager;
 
@@ -93,7 +93,7 @@ public class NaptEventHandler {
                             final PacketProcessingService pktService,
                             final OdlInterfaceRpcService interfaceManagerRpc,
                             final IInterfaceManager interfaceManager,
-                            final INeutronVpnManager nvpnManager,
+                            final IElanService elanManager,
                             final IdManagerService idManager) {
         this.dataBroker = dataBroker;
         NaptEventHandler.mdsalManager = mdsalManager;
@@ -101,7 +101,7 @@ public class NaptEventHandler {
         this.pktService = pktService;
         this.interfaceManagerRpc = interfaceManagerRpc;
         this.interfaceManager = interfaceManager;
-        this.nvpnManager = nvpnManager;
+        this.elanManager = elanManager;
         this.idManager = idManager;
     }
 
@@ -272,8 +272,8 @@ public class NaptEventHandler {
                 }
                 if (pktOut != null) {
                     String routerName = NatUtil.getRouterName(dataBroker, routerId);
-                    long tunId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker,
-                            nvpnManager, idManager, routerId, routerName);
+                    long tunId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerId,
+                            routerName);
                     sendNaptPacketOut(pktOut, infInfo, actionInfos, tunId);
                 } else {
                     LOG.warn("NAT Service : Unable to send Packet Out");
index 2571e345ce8e14a20253c5f933b90838332dcc00..651af3361b66917e40caeb40504e5490559b6955 100644 (file)
@@ -38,9 +38,9 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelTypeBase;
@@ -96,7 +96,7 @@ public class NaptSwitchHA {
     private final VpnRpcService vpnService;
     private final FibRpcService fibService;
     private final IFibManager fibManager;
-    private final INeutronVpnManager nvpnManager;
+    private final IElanService elanManager;
     private List<String> externalIpsCache;
     private HashMap<String, Long> externalIpsLabel;
     private final EvpnNaptSwitchHA evpnNaptSwitchHA;
@@ -115,7 +115,7 @@ public class NaptSwitchHA {
                         final FibRpcService fibService,
                         final IFibManager fibManager,
                         final EvpnNaptSwitchHA evpnNaptSwitchHA,
-                        final INeutronVpnManager nvpnManager,
+                        final IElanService elanManager,
                         final SnatServiceManager natServiceManager,
                         final NatserviceConfig config) {
         this.dataBroker = dataBroker;
@@ -130,7 +130,7 @@ public class NaptSwitchHA {
         this.fibService = fibService;
         this.fibManager = fibManager;
         this.evpnNaptSwitchHA = evpnNaptSwitchHA;
-        this.nvpnManager = nvpnManager;
+        this.elanManager = elanManager;
         this.natServiceManager = natServiceManager;
         if (config != null) {
             this.natMode = config.getNatMode();
@@ -784,8 +784,8 @@ public class NaptSwitchHA {
 
         if (addordel == NatConstants.ADD_FLOW) {
             List<ActionInfo> actionsInfo = new ArrayList<>();
-            long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, nvpnManager, idManager,
-                                                                        routerVpnId, routerName);
+            long tunnelId = NatUtil.getTunnelIdForNonNaptToNaptFlow(dataBroker, elanManager, idManager, routerVpnId,
+                    routerName);
             actionsInfo.add(new ActionSetFieldTunnelId(BigInteger.valueOf(tunnelId)));
             LOG.debug("Setting the tunnel to the list of action infos {}", actionsInfo);
             actionsInfo.add(new ActionGroup(groupId));
index d1c4c0a929cfe43bf0647eec1c5cc76313e5749b..b9a6dffea2f715573fa0f73a0a8a583b2cfcf731 100644 (file)
@@ -35,10 +35,10 @@ import org.opendaylight.genius.mdsalutil.instructions.InstructionGotoTable;
 import org.opendaylight.genius.mdsalutil.instructions.InstructionWriteMetadata;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
@@ -86,7 +86,7 @@ public class NatTunnelInterfaceStateListener
     private final OdlInterfaceRpcService interfaceService;
     private final FloatingIPListener floatingIPListener;
     private final FibRpcService fibRpcService;
-    private final INeutronVpnManager nvpnManager;
+    private final IElanService elanManager;
     private NatMode natMode = NatMode.Controller;
 
     protected enum TunnelAction {
@@ -109,6 +109,7 @@ public class NatTunnelInterfaceStateListener
      * @param interfaceService       - Interface Service
      * @param floatingIPListener     -  Floating IP Listner
      * @param fibRpcService          - FIB RPC Service
+     * @param elanManager            - Elan Manager
      */
     @Inject
     public NatTunnelInterfaceStateListener(final DataBroker dataBroker,
@@ -123,8 +124,8 @@ public class NatTunnelInterfaceStateListener
                                            final OdlInterfaceRpcService interfaceService,
                                            final FloatingIPListener floatingIPListener,
                                            final FibRpcService fibRpcService,
-                                           final INeutronVpnManager nvpnManager,
-                                           final NatserviceConfig config) {
+                                           final NatserviceConfig config,
+                                           final IElanService elanManager) {
         super(StateTunnelList.class, NatTunnelInterfaceStateListener.class);
         this.dataBroker = dataBroker;
         this.bgpManager = bgpManager;
@@ -138,7 +139,7 @@ public class NatTunnelInterfaceStateListener
         this.interfaceService = interfaceService;
         this.floatingIPListener = floatingIPListener;
         this.fibRpcService = fibRpcService;
-        this.nvpnManager = nvpnManager;
+        this.elanManager = elanManager;
         if (config != null) {
             this.natMode = config.getNatMode();
         }
@@ -671,7 +672,7 @@ public class NatTunnelInterfaceStateListener
                     LOG.debug("NAT Service : SNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
                             externalIp, nextHopIp);
                     long l3vni = 0;
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanManager.isOpenStackVniSemanticsEnforced()) {
                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, externalVpnName, l3vni).longValue();
                     }
                     Uuid externalSubnetId = NatUtil.getExternalSubnetForRouterExternalIp(dataBroker, externalIp,
@@ -816,7 +817,7 @@ public class NatTunnelInterfaceStateListener
                     LOG.debug("NAT Service : DNAT -> Advertise the route to the externalIp {} having nextHopIp {}",
                             externalIp, nextHopIp);
                     long l3vni = 0;
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanManager.isOpenStackVniSemanticsEnforced()) {
                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
                     }
                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, null,
index 42bd9b5f5233e27525fc1bd85f3b1d9ba1684466..297db79dd8cc8e461499ff34d7cc4030e2b000d4 100644 (file)
@@ -50,10 +50,10 @@ import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.mdsalutil.matches.MatchEthernetType;
 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronConstants;
-import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
@@ -1766,9 +1766,9 @@ public class NatUtil {
                 .child(ElanInstance.class, new ElanInstanceKey(elanInstanceName)).build();
     }
 
-    public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, INeutronVpnManager nvpnManager,
+    public static long getTunnelIdForNonNaptToNaptFlow(DataBroker dataBroker, IElanService elanManager,
             IdManagerService idManager, long routerId, String routerName) {
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+        if (elanManager.isOpenStackVniSemanticsEnforced()) {
             // Router VNI will be set as tun_id if OpenStackSemantics is enabled
             return NatOverVxlanUtil.getRouterVni(idManager, routerName, routerId).longValue();
         } else {
index a4d8c45c3c5f337f34e3436e7368d6257dff8d3d..059dfa9f11f56471766b021cdf6fff1f9ed7a17d 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.genius.mdsalutil.FlowEntity;
 import org.opendaylight.genius.mdsalutil.GroupEntity;
 import org.opendaylight.genius.mdsalutil.MDSALUtil;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
 import org.opendaylight.netvirt.natservice.api.SnatServiceManager;
 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
@@ -51,6 +52,7 @@ public class RouterDpnChangeListener
     private final IdManagerService idManager;
     private final INeutronVpnManager nvpnManager;
     private final ExternalNetworkGroupInstaller extNetGroupInstaller;
+    private final IElanService elanManager;
     private SnatServiceManager natServiceManager;
     private NatMode natMode = NatMode.Controller;
 
@@ -62,7 +64,8 @@ public class RouterDpnChangeListener
                                    final ExternalNetworkGroupInstaller extNetGroupInstaller,
                                    final INeutronVpnManager nvpnManager,
                                    final SnatServiceManager natServiceManager,
-                                   final NatserviceConfig config) {
+                                   final NatserviceConfig config,
+                                   final IElanService elanManager) {
         super(DpnVpninterfacesList.class, RouterDpnChangeListener.class);
         this.dataBroker = dataBroker;
         this.mdsalManager = mdsalManager;
@@ -71,6 +74,7 @@ public class RouterDpnChangeListener
         this.idManager = idManager;
         this.extNetGroupInstaller = extNetGroupInstaller;
         this.nvpnManager = nvpnManager;
+        this.elanManager = elanManager;
         this.natServiceManager = natServiceManager;
         if (config != null) {
             this.natMode = config.getNatMode();
@@ -244,7 +248,7 @@ public class RouterDpnChangeListener
                     LOG.debug("Switch {} is elected as NaptSwitch for router {}", dpnId, routerName);
 
                     // When NAPT switch is elected during first VM comes up for the given Router
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanManager.isOpenStackVniSemanticsEnforced()) {
                         NatOverVxlanUtil.validateAndCreateVxlanVniPool(dataBroker, nvpnManager,
                                 idManager, NatConstants.ODL_VNI_POOL_NAME);
                     }
index ee7975c58dbeb7fb6ac289d9c0735a3567336eda..45fc9b743033cc085e39c2914ffe2c9c88e3e9e6 100644 (file)
@@ -172,7 +172,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                         internalIp, externalIp);
                     //Inform BGP
                     long l3vni = 0;
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanService.isOpenStackVniSemanticsEnforced()) {
                         l3vni = NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, l3vni).longValue();
                     }
                     NatUtil.addPrefixToBGP(dataBroker, bgpManager, fibManager, vpnName, rd, subnetId,
@@ -305,7 +305,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
                  *  floating IP then do not remove INTERNAL_TUNNEL_TABLE (table=36) -> PDNAT_TABLE (table=25) flow entry
                  */
                     Boolean removeTunnelFlow = Boolean.TRUE;
-                    if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+                    if (elanService.isOpenStackVniSemanticsEnforced()) {
                         if (NatUtil.isFloatingIpPresentForDpn(dataBroker, dpnId, rd, vpnName, externalIp)) {
                             removeTunnelFlow = Boolean.FALSE;
                         }
@@ -372,7 +372,7 @@ public class VpnFloatingIpHandler implements FloatingIPHandler {
         // Increased the 36->25 flow priority. If SNAT is also configured on the same
         // DPN, then the traffic will be hijacked to DNAT and if there are no DNAT match,
         // then handled back to using using flow 25->44(which will be installed as part of SNAT)
-        if (nvpnManager.getEnforceOpenstackSemanticsConfig()) {
+        if (elanService.isOpenStackVniSemanticsEnforced()) {
             mkMatches.add(new MatchTunnelId(NatOverVxlanUtil.getInternetVpnVni(idManager, vpnName, serviceId)));
             flowPriority = 6;
         } else {
index 270346c5cb57f6f36b4290310e6298681f45d3c0..3c2666c0119980d6da5df52553a9e037e9eb8720 100644 (file)
@@ -163,8 +163,8 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         LOG.info("{} close", getClass().getSimpleName());
     }
 
-    public NeutronvpnConfig getNeutronvpnConfig() {
-        return neutronvpnConfig;
+    public String getOpenDaylightVniRangesConfig() {
+        return neutronvpnConfig.getOpendaylightVniRanges();
     }
 
     // TODO Clean up the exception handling
@@ -1968,14 +1968,6 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
         return result;
     }
 
-    public String getOpenDaylightVniRangesConfig() {
-        return neutronvpnConfig.getOpendaylightVniRanges();
-    }
-
-    public Boolean getEnforceOpenstackSemanticsConfig() {
-        return neutronvpnConfig.isEnforceOpenstackSemantics();
-    }
-
     protected void handleNeutronRouterDeleted(Uuid routerId, List<Uuid> routerSubnetIds) {
         // check if the router is associated to some VPN
         Uuid vpnId = NeutronvpnUtils.getVpnForRouter(dataBroker, routerId, true);
index 0285ac5b08c7a3060bee90234b721c85ccbf66f9..96bb2d0cca933554e37c1d899e937655d1463ef8 100644 (file)
@@ -95,9 +95,4 @@ public class NeutronvpnManagerImpl implements INeutronVpnManager {
     public String getOpenDaylightVniRangesConfig() {
         return nvManager.getOpenDaylightVniRangesConfig();
     }
-
-    @Override
-    public Boolean getEnforceOpenstackSemanticsConfig() {
-        return nvManager.getEnforceOpenstackSemanticsConfig();
-    }
 }
index bd753fdaab684cfffdd94b87597584c705287bd9..bd4c9da574592b0243eee50a6fd034c54db030bc 100644 (file)
@@ -1,4 +1,3 @@
 <neutronvpn-config xmlns="urn:opendaylight:netvirt:neutronvpn:config">
   <opendaylight-vni-ranges>70000:99999</opendaylight-vni-ranges>
-  <enforce-openstack-semantics>false</enforce-openstack-semantics>
 </neutronvpn-config>
index a37a9bef1b168df84779d76562c888079b1b13c2..85064b1ca63e1ead3191b925e077ff2b7bd9afd9 100644 (file)
@@ -17,9 +17,5 @@ module neutronvpn-config {
             type string;
             default "70000:99999";
         }
-        leaf enforce-openstack-semantics {
-            type boolean;
-            default true;
-        }
     }
 }