VMs on tennant vlan network not getting an IP when spwaned after 91/70991/4
authorAswin Suryanarayanan <asuryana@redhat.com>
Fri, 13 Apr 2018 15:34:30 +0000 (21:04 +0530)
committerSam Hague <shague@redhat.com>
Fri, 27 Apr 2018 11:14:20 +0000 (11:14 +0000)
the networks are added to the router.

The router port elandpnlist didn't have a state. So when the first port
is router port in the list, the elan flows fails.

Check is added to skip router port while checking if a port is the first
one in the list.

NETVIRT-1208 An Instance doesn't get an IP after when a network is added
to a router

Change-Id: I25ea20759eefc3043f1616e7907b0c6916fe90e5
Signed-off-by: Aswin Suryanarayanan <asuryana@redhat.com>
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/internal/ElanInterfaceManager.java
elanmanager/impl/src/main/java/org/opendaylight/netvirt/elan/utils/ElanUtils.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetmapChangeListener.java

index e2094ec9808d92fde51e52b455b85d2b67fd5e12..9780285bafe9818ab4bacc79763330e3d910c8b8 100644 (file)
@@ -679,10 +679,22 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                     .getElanDpnInterfaceOperationalDataPath(elanInstanceName, dpId);
             Optional<DpnInterfaces> existingElanDpnInterfaces = ElanUtils.read(broker,
                     LogicalDatastoreType.OPERATIONAL, elanDpnInterfaces);
-            if (!existingElanDpnInterfaces.isPresent()) {
-                isFirstInterfaceInDpn = true;
+            if (ElanUtils.isVlan(elanInstance)) {
+                isFirstInterfaceInDpn =  checkIfFirstInterface(interfaceName,
+                        elanInstanceName, existingElanDpnInterfaces);
+            } else {
+                isFirstInterfaceInDpn = !existingElanDpnInterfaces.isPresent();
+            }
+            if (isFirstInterfaceInDpn) {
                 // ELAN's 1st ElanInterface added to this DPN
-                dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
+                if (!existingElanDpnInterfaces.isPresent()) {
+                    dpnInterfaces = createElanInterfacesList(elanInstanceName, interfaceName, dpId, tx);
+                } else {
+                    List<String> elanInterfaces = existingElanDpnInterfaces.get().getInterfaces();
+                    elanInterfaces.add(interfaceName);
+                    dpnInterfaces = updateElanDpnInterfacesList(elanInstanceName, dpId,
+                            elanInterfaces, tx);
+                }
                 // The 1st ElanInterface in a DPN must program the Ext Tunnel
                 // table, but only if Elan has VNI
                 if (isVxlanNetworkOrVxlanSegment(elanInstance)) {
@@ -816,6 +828,21 @@ public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanIn
                 elanInstanceCache.get(elanInstanceName).orNull(), interfaceInfo, macEntry);
     }
 
+    private boolean checkIfFirstInterface(String elanInterface, String elanInstanceName,
+            Optional<DpnInterfaces> existingElanDpnInterfaces) {
+        String routerPortUuid = ElanUtils.getRouterPordIdFromElanInstance(broker, elanInstanceName);
+        if (!existingElanDpnInterfaces.isPresent()) {
+            return true;
+        }
+        DpnInterfaces dpnInterfaces = existingElanDpnInterfaces.get();
+
+        if (dpnInterfaces.getInterfaces().size() ==  0 || (dpnInterfaces.getInterfaces().size() == 1
+                && dpnInterfaces.getInterfaces().contains(routerPortUuid))) {
+            return true;
+        }
+        return false;
+    }
+
     private InstanceIdentifier<MacEntry> getMacEntryOperationalDataPath(String elanName, PhysAddress physAddress) {
         return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class, new MacTableKey(elanName))
                 .child(MacEntry.class, new MacEntryKey(physAddress)).build();
index 5502c76e2295091052f46ce1d8880610b682d8ca..80186bf335909fb7ed60c626ce93a39fe4a1b15b 100755 (executable)
@@ -165,6 +165,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.forwarding.entries.MacEntryKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
@@ -1651,6 +1653,28 @@ public class ElanUtils {
                 ipAddress);
         ArpResponderUtil.removeFlow(mdsalManager, dpnId, ArpResponderUtil.getFlowId(lportTag, ipAddress));
     }
+
+    public static String getRouterPordIdFromElanInstance(DataBroker dataBroker, String elanInstanceName) {
+        Optional<Subnetmaps> subnetMapsData =
+                read(dataBroker, LogicalDatastoreType.CONFIGURATION, buildSubnetMapsWildCardPath());
+        if (subnetMapsData.isPresent()) {
+            List<Subnetmap> subnetMapList = subnetMapsData.get().getSubnetmap();
+            if (subnetMapList != null && !subnetMapList.isEmpty()) {
+                for (Subnetmap subnet : subnetMapList) {
+                    if (subnet.getNetworkId().getValue().equals(elanInstanceName)) {
+                        if (subnet.getRouterInterfacePortId() != null) {
+                            return subnet.getRouterInterfacePortId().getValue();
+                        }
+                    }
+                }
+            }
+        }
+        return null;
+    }
+
+    static InstanceIdentifier<Subnetmaps> buildSubnetMapsWildCardPath() {
+        return InstanceIdentifier.create(Subnetmaps.class);
+    }
 }
 
 
index aac45ea9efe68dae5b22a934a4e708198b1cd94d..28e25cdfe3f5551b7bb53bfb77683435328ca9f3 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanInstances;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkAttributes.NetworkType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
@@ -73,6 +74,11 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
             LOG.error("SubnetMapChangeListener:add: network was not found for subnetId {}", subnetId.getValue());
             return;
         }
+        if (subnetmap.getVpnId() != null) {
+            if (subnetmap.getNetworkType().equals(NetworkType.VLAN)) {
+                VpnUtil.addRouterPortToElanDpnListForVlaninAllDpn(subnetmap.getVpnId().getValue(), dataBroker);
+            }
+        }
         if (VpnUtil.getIsExternal(network)) {
             LOG.debug("SubnetmapListener:add: provider subnetwork {} is handling in "
                       + "ExternalSubnetVpnInstanceListener", subnetId.getValue());
@@ -111,11 +117,6 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
             LOG.error("SubnetMapChangeListener:update: network was not found for subnetId {}", subnetId.getValue());
             return;
         }
-        if (VpnUtil.getIsExternal(network)) {
-            LOG.debug("SubnetMapChangeListener:update: provider subnetwork {} is handling in "
-                      + "ExternalSubnetVpnInstanceListener", subnetId.getValue());
-            return;
-        }
         String elanInstanceName = subnetmapUpdate.getNetworkId().getValue();
         long elanTag = getElanTag(elanInstanceName);
         if (elanTag == 0L) {
@@ -123,6 +124,13 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
                       elanInstanceName, subnetId);
             return;
         }
+        updateVlanDataEntry(subnetmapOriginal.getVpnId(), subnetmapUpdate.getVpnId(), subnetmapUpdate,
+                subnetmapOriginal, elanTag, elanInstanceName);
+        if (VpnUtil.getIsExternal(network)) {
+            LOG.debug("SubnetMapChangeListener:update: provider subnetwork {} is handling in "
+                      + "ExternalSubnetVpnInstanceListener", subnetId.getValue());
+            return;
+        }
         // update on BGPVPN or InternalVPN change
         Uuid vpnIdOld = subnetmapOriginal.getVpnId();
         Uuid vpnIdNew = subnetmapUpdate.getVpnId();
@@ -189,6 +197,21 @@ public class SubnetmapChangeListener extends AsyncDataTreeChangeListenerBase<Sub
         }
     }
 
+    private void updateVlanDataEntry(Uuid vpnIdOld, Uuid vpnIdNew, Subnetmap subnetmapUpdate,
+            Subnetmap subnetmapOriginal, Long elanTag, String  elanInstanceName) {
+        if (vpnIdNew != null && vpnIdOld == null) {
+            if (elanInstanceName != null && subnetmapUpdate.getNetworkType().equals(NetworkType.VLAN)) {
+                VpnUtil.addRouterPortToElanDpnListForVlaninAllDpn(vpnIdNew.getValue(), dataBroker);
+            }
+        }
+        if (vpnIdOld != null && vpnIdNew == null) {
+            if (subnetmapOriginal.getNetworkType().equals(NetworkType.VLAN)) {
+                VpnUtil.removeRouterPortFromElanDpnListForVlanInAllDpn(elanInstanceName, subnetmapOriginal
+                        .getRouterInterfacePortId().getValue(), vpnIdOld.getValue(), dataBroker);
+            }
+        }
+    }
+
     @Override
     protected SubnetmapChangeListener getDataTreeChangeListener() {
         return this;