BUG 6389: ServChain not applied to VMs in VPN 62/43862/4
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Fri, 12 Aug 2016 14:15:29 +0000 (19:45 +0530)
committerSuraj Ranjan <suraj.ranjan@ericsson.com>
Fri, 19 Aug 2016 16:50:42 +0000 (22:20 +0530)
Service Chaining Traffic should be forwarded to the DPN connected to
the Fist VM of SC Path.

Aprt from fixing above bug, this review also deals with the following:

1> Fixes bug in InterVpnLink static route provision
2> Removes NPE protection from NeutronVpnmanager

Change-Id: Ic31e0399e5684d7512571a4d63f4ab01fd3400a3
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
vpnservice/fibmanager/fibmanager-impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/vpnmanager/vpnmanager-api/src/main/java/org/opendaylight/netvirt/vpnmanager/api/IVpnManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnConstants.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnManagerImpl.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkListener.java

index f3abb0249a7055f75426df9acde1ef73e09b572c..80f256701bea38e2925c06b17ed3cfeca6d32631 100644 (file)
@@ -348,15 +348,16 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
                     });
         }
 
-        Optional<String> vpnUuid = FibUtil.getVpnNameFromRd(dataBroker, rd);
-        if ( vpnUuid.isPresent() ) {
-            Optional<InterVpnLink> interVpnLink = FibUtil.getInterVpnLinkByVpnUuid(dataBroker, vpnUuid.get());
+        Optional<String> optVpnUuid = FibUtil.getVpnNameFromRd(dataBroker, rd);
+        if ( optVpnUuid.isPresent() ) {
+            Optional<InterVpnLink> interVpnLink = FibUtil.getInterVpnLinkByVpnUuid(dataBroker, optVpnUuid.get());
             if ( interVpnLink.isPresent() ) {
+                String vpnUuid = optVpnUuid.get();
                 String routeNexthop = vrfEntry.getNextHopAddressList().get(0);
-                if ( isNexthopTheOtherVpnLinkEndpoint(routeNexthop, vpnUuid.get(), interVpnLink.get()) ) {
+                if ( isNexthopTheOtherVpnLinkEndpoint(routeNexthop, vpnUuid, interVpnLink.get()) ) {
                     // This is an static route that points to the other endpoint of an InterVpnLink
                     // In that case, we should add another entry in FIB table pointing to LPortDispatcher table.
-                    installRouteInInterVpnLink(interVpnLink.get(), rd, vrfEntry, vpnId);
+                    installRouteInInterVpnLink(interVpnLink.get(), vpnUuid, vrfEntry, vpnId);
                 }
             }
         }
@@ -611,6 +612,8 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
         Preconditions.checkNotNull(interVpnLink, "InterVpnLink cannot be null");
         Preconditions.checkArgument(vrfEntry.getNextHopAddressList() != null
                 && vrfEntry.getNextHopAddressList().size() == 1);
+        String destination = vrfEntry.getDestPrefix();
+        String nextHop = vrfEntry.getNextHopAddressList().get(0);
 
         // After having received a static route, we should check if the vpn is part of an inter-vpn-link.
         // In that case, we should populate the FIB table of the VPN pointing to LPortDisptacher table
@@ -622,7 +625,7 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
         }
         if ( ! interVpnLinkState.get().getState().equals(InterVpnLinkState.State.Active) ) {
             LOG.warn("Route to {} with nexthop={} cannot be installed because the interVpnLink {} is not active",
-                    vrfEntry.getDestPrefix(), vrfEntry.getNextHopAddressList().get(0), interVpnLink.getName());
+                    destination, nextHop, interVpnLink.getName());
             return;
         }
 
@@ -642,12 +645,13 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
                         ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
                 MetaDataUtil.getMetaDataMaskForLPortDispatcher()
         };
+        int instIdx = 0;
         List<Instruction> instructions =
                 Arrays.asList(new InstructionInfo(InstructionType.write_metadata, metadata).buildInstruction(0),
                         new InstructionInfo(InstructionType.goto_table,
                                 new long[] { NwConstants.L3_INTERFACE_TABLE }).buildInstruction(1));
 
-        String values[] = vrfEntry.getDestPrefix().split("/");
+        String values[] = destination.split("/");
         String destPrefixIpAddress = values[0];
         int prefixLength = (values.length == 1) ? 0 : Integer.parseInt(values[1]);
 
@@ -663,8 +667,7 @@ public class VrfEntryListener extends AbstractDataChangeListener<VrfEntry> imple
         }
 
         int priority = DEFAULT_FIB_FLOW_PRIORITY + prefixLength;
-        String nextHop = vrfEntry.getNextHopAddressList().get(0);
-        String flowRef = getInterVpnFibFlowRef(interVpnLink.getName(), vrfEntry.getDestPrefix(), nextHop);
+        String flowRef = getInterVpnFibFlowRef(interVpnLink.getName(), destination, nextHop);
         Flow flowEntity = MDSALUtil.buildFlowNew(NwConstants.L3_FIB_TABLE, flowRef, priority, flowRef, 0, 0,
                 COOKIE_VM_FIB_TABLE, matches, instructions);
 
index ee04c514d7d32a12726c608fbc5a4c81dd998273..2da1a38ff37f7782525e944e7a95c654bae71541 100644 (file)
@@ -1228,21 +1228,17 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             sn = optSn.get();
             oldVpnId = sn.getVpnId();
             List<String> ips = sn.getRouterInterfaceFixedIps();
-            if ( ips != null ) {
-                for (String ipValue : ips) {
-                    IpAddress ip = new IpAddress(ipValue.toCharArray());
-                    if (oldVpnId != null) {
-                        InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), ipValue);
-                        Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
-                        if (optionalVpnPort.isPresent()) {
-                            removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue);
-                        }
+            for (String ipValue : ips) {
+                IpAddress ip = new IpAddress(ipValue.toCharArray());
+                if (oldVpnId != null) {
+                    InstanceIdentifier<VpnPortipToPort> id = NeutronvpnUtils.buildVpnPortipToPortIdentifier(oldVpnId.getValue(), ipValue);
+                    Optional<VpnPortipToPort> optionalVpnPort = NeutronvpnUtils.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
+                    if (optionalVpnPort.isPresent()) {
+                        removeVpnPortFixedIpToPort(oldVpnId.getValue(), ipValue);
                     }
-                    createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, sn.getRouterInterfaceName().getValue(),
-                            sn.getRouterIntfMacAddress(), true, true, false);
                 }
-            } else {
-                LOG.warn("No fixed IPs configured for router interface. VpnId={}  subnetId={}", vpnId, subnet);
+                createVpnPortFixedIpToPort(vpnId.getValue(), ipValue, sn.getRouterInterfaceName().getValue(),
+                        sn.getRouterIntfMacAddress(), true, true, false);
             }
 
         }
index 97a774790c66bcb4b03487e99532432fc91714a9..86e36880b5267ec20125c51858b91aa42aa0f1be 100644 (file)
@@ -10,6 +10,9 @@ package org.opendaylight.netvirt.vpnmanager.api;
 
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 
+import java.math.BigInteger;
+import java.util.List;
+
 public interface IVpnManager {
     void setFibManager(IFibManager fibManager);
     void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label);
@@ -26,4 +29,11 @@ public interface IVpnManager {
     boolean isVPNConfigured();
 
     long getArpCacheTimeoutMillis();
+    /**
+     * Retrieves the list of DPNs where the specified VPN has footprint
+     *
+     * @param vpnInstanceName The name of the Vpn instance
+     * @return The list of DPNs
+     */
+    List<BigInteger> getDpnsOnVpn(String vpnInstanceName);
 }
index 1c314111dffcb097433ee5f0e5b4ed690bdfb891..e63dbb33cdf7ae9487ee9dc5531cf8949513e796 100644 (file)
@@ -24,6 +24,15 @@ public class VpnConstants {
     public static final long MAX_WAIT_TIME_IN_MILLISECONDS = 90000;
     public static final long PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS = 10000;
     public static final int ELAN_GID_MIN = 200000;
+
+    // An IdPool for Pseudo LPort tags, that is, lportTags that are no related to an interface.
+    // These lportTags must be higher than 65535 to avoid collision with interface LportTags
+    // TODO: This pool details and creation... should it be located in InterfaceManager?
+    public static final String PSEUDO_LPORT_TAG_ID_POOL_NAME = System.getProperty("lporttag.idpool.name", "lporttag");
+    public static final long LOWER_PSEUDO_LPORT_TAG = Long.getLong("lporttag.range.lower", 170001);
+    // The max value for LPortTag is 1F FF FF => 2097151
+    public static final long UPPER_PSEUDO_LPORT_TAG = Long.getLong("lporttag.range.upper", 2097151);
+
     public static byte[] EthernetDestination_Broadcast = new byte[] { (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
             (byte) 0xFF, (byte) 0xFF, (byte) 0xFF };
     public static byte[] MAC_Broadcast = new byte[] { (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0, (byte) 0 };
index 19805be8df8405884bb2e3792f1c4a5e9947bb81..4170f228a984757c08cfae4efbc17ceff71e9fd0 100644 (file)
@@ -8,6 +8,8 @@
 package org.opendaylight.netvirt.vpnmanager;
 
 import java.math.BigInteger;
+import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -16,6 +18,7 @@ import org.opendaylight.netvirt.vpnmanager.api.IVpnManager;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
+import org.opendaylight.yangtools.yang.common.RpcError;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,6 +59,28 @@ public class VpnManagerImpl implements IVpnManager {
         } catch (InterruptedException | ExecutionException e) {
             LOG.error("Failed to create idPool for VPN Service",e);
         }
+
+        // Now an IdPool for InterVpnLink endpoint's pseudo ports
+        CreateIdPoolInput createPseudoLporTagPool =
+                new CreateIdPoolInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
+                        .setLow(VpnConstants.LOWER_PSEUDO_LPORT_TAG)
+                        .setHigh(VpnConstants.UPPER_PSEUDO_LPORT_TAG)
+                        .build();
+        try {
+            Future<RpcResult<Void>> result = idManager.createIdPool(createPseudoLporTagPool);
+            if (result != null && result.get().isSuccessful()) {
+                LOG.debug("Created IdPool for Pseudo Port tags");
+            } else {
+                Collection<RpcError> errors = result.get().getErrors();
+                StringBuilder errMsg = new StringBuilder();
+                for ( RpcError err : errors ) {
+                    errMsg.append(err.getMessage()).append("\n");
+                }
+                LOG.error("IdPool creation for PseudoPort tags failed. Reasons: {}", errMsg);
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.error("Failed to create idPool for Pseudo Port tags",e);
+        }
     }
 
     @Override
@@ -80,6 +105,11 @@ public class VpnManagerImpl implements IVpnManager {
         return vpnInstanceListener.isVPNConfigured();
     }
 
+    @Override
+    public List<BigInteger> getDpnsOnVpn(String vpnInstanceName) {
+        return VpnUtil.getDpnsOnVpn(dataBroker, vpnInstanceName);
+    }
+
     @Override
     public boolean existsVpn(String vpnName) {
         return VpnUtil.getVpnInstance(dataBroker, vpnName) != null;
index 3fb6db517f1c562e77a2aa49bbf2a653f9e5d315..9b6c282bd52233d27d512c244d257e67b7e23ecb 100644 (file)
@@ -1321,6 +1321,31 @@ public class VpnUtil {
         }
         return null;
     }
+
+    public static List<BigInteger> getDpnsOnVpn(DataBroker dataBroker, String vpnInstanceName) {
+        List<BigInteger> result = new ArrayList<BigInteger>();
+        String rd = getVpnRd(dataBroker, vpnInstanceName);
+        if ( rd == null ) {
+            LOG.debug("Could not find Route-Distinguisher for VpnName={}", vpnInstanceName);
+            return result;
+        }
+
+        VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(dataBroker, rd);
+        if ( vpnInstanceOpData == null ) {
+            LOG.debug("Could not find OpState for VpnName={}", vpnInstanceName);
+            return result;
+        }
+
+        List<VpnToDpnList> vpnToDpnList = vpnInstanceOpData.getVpnToDpnList();
+        if ( vpnToDpnList == null ) {
+            LOG.debug("Could not find DPN footprint for VpnName={}", vpnInstanceName);
+            return result;
+        }
+        for ( VpnToDpnList vpnToDpn : vpnToDpnList) {
+            result.add(vpnToDpn.getDpnId());
+        }
+        return result;
+    }
     
     static String getAssociatedExternalNetwork(DataBroker dataBroker, String routerId) {
         InstanceIdentifier<Routers> id = buildRouterIdentifier(routerId);
index cd63e74de3af485d5fec06d9c8b0f0f3ae4856a9..38d3de3dd9e6902c6a2daf0b47b4880a19646bf1 100644 (file)
@@ -153,14 +153,14 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
                 new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid).setDpId(secondDpnList)
                                                 .setLportTag(secondVpnLportTag).build();
 
-            InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Active, firstEndPointState,
-                                            secondEndPointState);
+            InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Active,
+                                                     firstEndPointState, secondEndPointState);
 
             // Note that in the DPN of the firstEndpoint we install the lportTag of the secondEndpoint and viceversa
             InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, firstDpnList,
-                                                    secondEndpointVpnUuid, secondVpnLportTag);
+                                                             secondEndpointVpnUuid, secondVpnLportTag);
             InterVpnLinkUtil.installLPortDispatcherTableFlow(dataBroker, mdsalManager, add, secondDpnList,
-                                                    firstEndpointVpnUuid, firstVpnLportTag);
+                                                             firstEndpointVpnUuid, firstVpnLportTag);
             // Update the VPN -> DPNs Map.
             // Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
             // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
@@ -182,8 +182,8 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
             SecondEndpointState secondEndPointState =
                 new SecondEndpointStateBuilder().setVpnUuid(secondEndpointVpnUuid)
                                                 .setLportTag(secondVpnLportTag).build();
-            InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Error, firstEndPointState,
-                                            secondEndPointState);
+            InterVpnLinkUtil.updateInterVpnLinkState(dataBroker, add.getName(), InterVpnLinkState.State.Error,
+                                                     firstEndPointState, secondEndPointState);
         }
 
 
@@ -363,8 +363,8 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     }
 
     private void releaseVpnLinkLPortTag(String idKey) {
-        ReleaseIdInput releaseIdInput = new ReleaseIdInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME)
-                                                                   .setIdKey(idKey).build();
+        ReleaseIdInput releaseIdInput =
+                new ReleaseIdInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME).setIdKey(idKey).build();
         idManager.releaseId(releaseIdInput);
     }
 
@@ -392,11 +392,13 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
 
     private Integer allocateVpnLinkLportTag(String idKey) {
         AllocateIdInput getIdInput =
-                new AllocateIdInputBuilder().setPoolName(IfmConstants.IFM_IDPOOL_NAME).setIdKey(idKey).build();
+                new AllocateIdInputBuilder().setPoolName(VpnConstants.PSEUDO_LPORT_TAG_ID_POOL_NAME)
+                        .setIdKey(idKey)
+                        .build();
         try {
             Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
             RpcResult<AllocateIdOutput> rpcResult = result.get();
-            if(rpcResult.isSuccessful()) {
+            if (rpcResult.isSuccessful()) {
                 return rpcResult.getResult().getIdValue().intValue();
             } else {
                 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
@@ -412,9 +414,9 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
                               String errorMsg) {
         // Setting InterVPNLink in error state in MDSAL
         InterVpnLinkState vpnLinkErrorState =
-           new InterVpnLinkStateBuilder(vpnLinkState).setState(InterVpnLinkState.State.Error)
-                                                     .setErrorDescription(errorMsg)
-                                                     .build();
+            new InterVpnLinkStateBuilder(vpnLinkState).setState(InterVpnLinkState.State.Error)
+                                                      .setErrorDescription(errorMsg)
+                                                      .build();
         WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
         tx.put(LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkErrorState, true);
         tx.submit();