Subport: Ping failed after cluster reboot 42/83042/4
authorShashidhar Raja <shashidharr@altencalsoftlabs.com>
Mon, 15 Jul 2019 10:29:12 +0000 (15:59 +0530)
committerFaseela K <faseela.k@ericsson.com>
Tue, 27 Aug 2019 05:26:03 +0000 (05:26 +0000)
With cluster reboot, subport interfaces some times gets created as Trunk
interfaces. This is mainly because of port and trunk replay executing in
irregular order after reboot sometimes.

Below changes are done to fix above problem:
(a) New yang container as shown below is introduced to save subport details
needed for creating subport-interface in CONFIG DS (this is defined in neutronvpn.yang)

    container neutron-vpn-port-id-subport-data {
        config true;
        list port-id-to-subport {
            key port-id;
            leaf port-id { type yang:uuid; }
            leaf vlan-id { type uint32; }
            leaf trunk-port-id { type yang:uuid; }
        }
    }

(b) After cluster restart, get details about subport from config DS using neutron port id.
If data is present, create interface as subport interface (trunk-member) otherwise create
it as trunk interface.

Change-Id: I8a7baf868ef51c1f8264d79020564e2e89207bfa
Signed-off-by: Shashidhar Raja <shashidharr@altencalsoftlabs.com>
neutronvpn/api/src/main/yang/neutronvpn.yang
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronPortChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronTrunkChangeListener.java
neutronvpn/impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnUtils.java

index 8753f191ec8ada6f3364b02c625e30dcc7492826..74bd4a4b5aa615e83b81d069069ed6044617c909 100644 (file)
@@ -209,6 +209,16 @@ module neutronvpn {
         }
     }
 
+    container neutron-vpn-port-id-subport-data {
+        config true;
+        list port-id-to-subport {
+            key port-id;
+            leaf port-id { type yang:uuid; }
+            leaf vlan-id { type uint32; }
+            leaf trunk-port-id { type yang:uuid; }
+        }
+    }
+
     container router-interfaces-map {
         list router-interfaces {
             key router-id;
index 329198594831fb3787ca4bc5ea15c9711fdf59b1..edd85c14709abf0093e9a434a36225e508744b33 100644 (file)
@@ -52,6 +52,11 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 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.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizon;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizonBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAcl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.InterfaceAclBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.aclservice.rev160608.interfaces._interface.AllowedAddressPairs;
@@ -64,6 +69,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers.RoutersBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubport;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.subnetmaps.Subnetmap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.binding.rev150712.PortBindingExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.hostconfig.rev150712.hostconfig.attributes.hostconfigs.Hostconfig;
@@ -880,6 +886,18 @@ public class NeutronPortChangeListener extends AsyncDataTreeChangeListenerBase<P
         Boolean isVlanTransparent = network.isVlanTransparent();
         if (isVlanTransparent != null && isVlanTransparent) {
             l2VlanMode = IfL2vlan.L2vlanMode.Transparent;
+        } else {
+            PortIdToSubport portIdToSubport = neutronvpnUtils.getPortIdToSubport(port.getUuid());
+            if (portIdToSubport != null) {
+                l2VlanMode = IfL2vlan.L2vlanMode.TrunkMember;
+                ifL2vlanBuilder.setVlanId(new VlanId(portIdToSubport.getVlanId().intValue()));
+                String parentRefName = portIdToSubport.getTrunkPortId().getValue();
+                ParentRefsBuilder parentRefsBuilder = new ParentRefsBuilder().setParentInterface(parentRefName);
+                interfaceBuilder.addAugmentation(ParentRefs.class, parentRefsBuilder.build());
+                SplitHorizon splitHorizon =
+                        new SplitHorizonBuilder().setOverrideSplitHorizonProtection(true).build();
+                interfaceBuilder.addAugmentation(SplitHorizon.class, splitHorizon);
+            }
         }
 
         ifL2vlanBuilder.setL2vlanMode(l2VlanMode);
index 9cd4cb87695d5d0cce3d19de7f4dec0effc3663a..6e337932d6820e0fc4571cc95879f8591c4fae09 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.netvirt.neutronvpn;
 import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 
 import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.ListenableFuture;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -26,6 +27,7 @@ import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev170119.L2vlan;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceBuilder;
+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.interfacemanager.rev160406.IfL2vlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfL2vlanBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
@@ -33,6 +35,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizon;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.SplitHorizonBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l2.types.rev130827.VlanId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubportBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubportKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.NetworkTypeVlan;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.trunks.rev170118.trunk.attributes.SubPorts;
@@ -128,6 +132,21 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
 
         // Should we use parentName?
         jobCoordinator.enqueueJob("PORT- " + portName, () -> {
+            /*
+            *  Build Port-to-Subport details first, irrespective of port being available or not.
+            */
+            PortIdToSubportBuilder portIdToSubportBuilder = new PortIdToSubportBuilder();
+            Uuid subPortUuid = subPort.getPortId();
+            portIdToSubportBuilder.withKey(new PortIdToSubportKey(subPortUuid)).setPortId(subPortUuid)
+                    .setTrunkPortId(trunk.getPortId()).setVlanId(subPort.getSegmentationId());
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                CONFIGURATION, tx -> {
+                    tx.merge(NeutronvpnUtils.buildPortIdSubportMappingIdentifier(subPortUuid),
+                            portIdToSubportBuilder.build());
+                    LOG.trace("Creating PortIdSubportMapping for port{}", portName);
+                }));
+
             Interface iface = ifMgr.getInterfaceInfoFromConfigDataStore(portName);
             if (iface == null) {
                 /*
@@ -138,7 +157,7 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
                  *      node as this one. Use of DSJC helps ensure the order.
                  */
                 LOG.warn("Interface not present for Trunk SubPort: {}", subPort);
-                return Collections.emptyList();
+                return futures;
             }
             InterfaceBuilder interfaceBuilder = new InterfaceBuilder();
             IfL2vlan ifL2vlan = new IfL2vlanBuilder().setL2vlanMode(IfL2vlan.L2vlanMode.TrunkMember)
@@ -152,11 +171,12 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
              * Interface is already created for parent NeutronPort. We're updating parent refs
              * and VLAN Information
              */
-            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
                 CONFIGURATION, tx -> {
                     tx.merge(interfaceIdentifier, newIface);
                     LOG.trace("Creating trunk member interface {}", newIface);
                 }));
+            return futures;
         });
     }
 
@@ -189,11 +209,18 @@ public class NeutronTrunkChangeListener extends AsyncDataTreeChangeListenerBase<
              * and this being subport delete path, don't expect any significant changes to
              * corresponding Neutron Port. Deletion of NeutronPort should follow soon enough.
              */
-            return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+            List<ListenableFuture<Void>> futures = new ArrayList<>();
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
                 CONFIGURATION, tx -> {
                     tx.put(interfaceIdentifier, newIface);
                     LOG.trace("Resetting trunk member interface {}", newIface);
                 }));
+            futures.add(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
+                CONFIGURATION, tx -> {
+                    tx.delete(NeutronvpnUtils.buildPortIdSubportMappingIdentifier(subPort.getPortId()));
+                    LOG.trace("Deleting PortIdSubportMapping for portName {}", portName);
+                }));
+            return futures;
         });
 
     }
index 27806c64fc26ae24044fd1a649d371a44e090171..ac4fd13cf04b613f57b32e92ff4906526d17a8c2 100644 (file)
@@ -111,11 +111,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev16011
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMapping;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.floating.ip.port.info.FloatingIpIdToPortMappingKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NetworkMaps;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortIdSubportData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.Subnetmaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.VpnMaps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMap;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.networkmaps.NetworkMapKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubport;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.port.id.subport.data.PortIdToSubportKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
@@ -426,6 +429,17 @@ public class NeutronvpnUtils {
         return prt;
     }
 
+    public PortIdToSubport getPortIdToSubport(Uuid portId) {
+        InstanceIdentifier<PortIdToSubport> portIdToSubportIdentifier = buildPortIdSubportMappingIdentifier(portId);
+        Optional<PortIdToSubport> optionalPortIdToSubport = read(LogicalDatastoreType.CONFIGURATION,
+                portIdToSubportIdentifier);
+        if (optionalPortIdToSubport.isPresent()) {
+            return optionalPortIdToSubport.get();
+        }
+        LOG.error("getPortIdToSubport failed, PortIdToSubport {} not present", portId.getValue());
+        return null;
+    }
+
     /**
      * Returns port_security_enabled status with the port.
      *
@@ -1013,6 +1027,12 @@ public class NeutronvpnUtils {
         return id;
     }
 
+    static InstanceIdentifier<PortIdToSubport> buildPortIdSubportMappingIdentifier(Uuid interfaceName) {
+        InstanceIdentifier<PortIdToSubport> id = InstanceIdentifier.builder(NeutronVpnPortIdSubportData.class)
+                .child(PortIdToSubport.class, new PortIdToSubportKey(interfaceName)).build();
+        return id;
+    }
+
     static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext
             .routers.Routers> buildExtRoutersIdentifier(Uuid routerId) {
         InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.natservice.rev160111.ext.routers