Support for local and remote ECMP groups 96/74896/9
authoreceghkl <manu.b@ericsson.com>
Sun, 15 Jul 2018 05:06:54 +0000 (10:36 +0530)
committerSam Hague <shague@redhat.com>
Tue, 4 Sep 2018 14:38:03 +0000 (14:38 +0000)
* Table 20 and 36 used to point incorrectly. 20 used to point to ECMP
  select group which has remote buckets. 36 used to point to only one of
  the nexhop among the loadbalancing group
* Fix is added to create local and remote select groups
* Table 20 and 36 will point to local ECMP select group
* Table 21 will point to remote ECMP select group

Change-Id: I5f74b943d8158022cf56d6f7a89be6bc08069f5f
Signed-off-by: eceghkl <manu.b@ericsson.com>
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/BaseVrfEntryHandler.java
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/BgpRouteVrfEntryHandler.java
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/NexthopManager.java
fibmanager/impl/src/main/java/org/opendaylight/netvirt/fibmanager/VrfEntryListener.java

index 506d32dccd73c84dbe5745ef0a2bbea75a78843b..e20e831118e6788ea876b7239d1d229152ad0a9d 100644 (file)
@@ -513,8 +513,7 @@ public class BaseVrfEntryHandler implements AutoCloseable {
         if (localDpnId != null && localDpnId != BigInteger.ZERO) {
             // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
             if (extraRouteOptional.isPresent()) {
-                nextHopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                        Collections.emptyList() /*listBucketInfo*/ , false);
+                nextHopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
             }
             makeConnectedRoute(remoteDpnId, vpnId, vrfEntry, rd, null, NwConstants.DEL_FLOW, tx, null);
             LOG.debug("Successfully delete FIB entry: vrfEntry={}, vpnId={}", vrfEntry.getDestPrefix(), vpnId);
@@ -524,8 +523,7 @@ public class BaseVrfEntryHandler implements AutoCloseable {
         // below two reads are kept as is, until best way is found to identify dpnID
         VpnNexthop localNextHopInfo = nextHopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
         if (extraRouteOptional.isPresent()) {
-            nextHopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                    Collections.emptyList() /*listBucketInfo*/ , false);
+            nextHopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
         } else {
             checkDpnDeleteFibEntry(localNextHopInfo, remoteDpnId, vpnId, vrfEntry, rd, tx, null);
         }
index ca17b15b388a869dc251d17947b5823544737b26..8aa45db86fb21d7f5b750aa634d27e5406264279 100644 (file)
@@ -13,7 +13,6 @@ import com.google.common.base.Optional;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
@@ -350,8 +349,7 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         if (localDpnId != null && localDpnId != BigInteger.ZERO) {
             // localDpnId is not known when clean up happens for last vm for a vpn on a dpn
             if (extraRouteOptional.isPresent()) {
-                nexthopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                        Collections.emptyList() /*listBucketInfo*/ , false);
+                nexthopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
             }
             deleteFibEntryForBgpRoutes(remoteDpnId, vpnId, vrfEntry, rd, tx, subTxns);
             return;
@@ -360,8 +358,7 @@ public class BgpRouteVrfEntryHandler extends BaseVrfEntryHandler
         // below two reads are kept as is, until best way is found to identify dpnID
         VpnNexthop localNextHopInfo = nexthopManager.getVpnNexthop(vpnId, vrfEntry.getDestPrefix());
         if (extraRouteOptional.isPresent()) {
-            nexthopManager.setupLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix(),
-                    Collections.emptyList()  /*listBucketInfo*/ , false);
+            nexthopManager.deleteLoadBalancingNextHop(vpnId, remoteDpnId, vrfEntry.getDestPrefix());
         } else {
             checkDpnDeleteFibEntry(localNextHopInfo, remoteDpnId, vpnId, vrfEntry, rd, tx, subTxns);
         }
index c113f7fa1e2061023bd3a3ee75c508397e17346b..d52b46d0b8e65e8c3b2b8fd7a34f4e947fc6a148 100644 (file)
@@ -213,6 +213,14 @@ public class NexthopManager implements AutoCloseable {
         return "nexthop." + vpnId + ipAddress;
     }
 
+    String getRemoteSelectGroupKey(long vpnId, String ipAddress) {
+        return "remote.ecmp.nexthop." + vpnId + ipAddress;
+    }
+
+    String getLocalSelectGroupKey(long vpnId, String ipAddress) {
+        return "local.ecmp.nexthop." + vpnId + ipAddress;
+    }
+
     public ItmRpcService getItmManager() {
         return itmManager;
     }
@@ -363,6 +371,15 @@ public class NexthopManager implements AutoCloseable {
         return groupId;
     }
 
+    public long getLocalSelectGroup(long vpnId,
+            String ipNextHopAddress) {
+        long groupId = createNextHopPointer(getLocalSelectGroupKey(vpnId, ipNextHopAddress));
+        if (groupId == FibConstants.INVALID_GROUP_ID) {
+            LOG.error("Unable to allocate groupId for vpnId {} , prefix {}", vpnId, ipNextHopAddress);
+        }
+        return groupId;
+    }
+
     public long createLocalNextHop(long vpnId, BigInteger dpnId, String ifName,
                                    String primaryIpAddress, String currDestIpPrefix,
                                    String gwMacAddress) {
@@ -818,46 +835,78 @@ public class NexthopManager implements AutoCloseable {
     }
 
     protected long setupLoadBalancingNextHop(Long parentVpnId, BigInteger dpnId,
-            String destPrefix, List<BucketInfo> listBucketInfo, boolean addOrRemove) {
-        long groupId = createNextHopPointer(getNextHopKey(parentVpnId, destPrefix));
-        if (groupId == FibConstants.INVALID_GROUP_ID) {
-            LOG.error("Unable to allocate/retrieve groupId for vpnId {} , prefix {}", parentVpnId, destPrefix);
-            return groupId;
+            String destPrefix, List<BucketInfo> localBucketInfo, List<BucketInfo> remoteBucketInfo) {
+        long remoteGroupId = createNextHopPointer(getRemoteSelectGroupKey(parentVpnId, destPrefix));
+        if (remoteGroupId == FibConstants.INVALID_GROUP_ID) {
+            LOG.error("Unable to allocate/retrieve remote groupId for vpnId {} , prefix {}", parentVpnId, destPrefix);
+            return remoteGroupId;
+        }
+        long localGroupId = FibConstants.INVALID_GROUP_ID;
+        if (!localBucketInfo.isEmpty() && !remoteBucketInfo.isEmpty()) {
+            localGroupId = createNextHopPointer(getLocalSelectGroupKey(parentVpnId, destPrefix));
+            if (localGroupId == FibConstants.INVALID_GROUP_ID) {
+                LOG.error("Unable to allocate/retrieve local groupId for vpnId {} , prefix {}",
+                    parentVpnId, destPrefix);
+                return remoteGroupId;
+            }
         }
-        GroupEntity groupEntity = MDSALUtil.buildGroupEntity(
-                dpnId, groupId, destPrefix, GroupTypes.GroupSelect, listBucketInfo);
+        List<BucketInfo> combinedBucketInfo = new ArrayList<>();
+        combinedBucketInfo.addAll(localBucketInfo);
+        combinedBucketInfo.addAll(remoteBucketInfo);
+        GroupEntity remoteGroupEntity = MDSALUtil.buildGroupEntity(
+                dpnId, remoteGroupId, destPrefix, GroupTypes.GroupSelect, combinedBucketInfo);
+        GroupEntity localGroupEntity = MDSALUtil.buildGroupEntity(
+                dpnId, localGroupId, destPrefix, GroupTypes.GroupSelect, localBucketInfo);
         String jobKey = FibUtil.getCreateLocalNextHopJobKey(parentVpnId, dpnId, destPrefix);
         jobCoordinator.enqueueJob(jobKey, () -> {
-            if (addOrRemove) {
-                mdsalApiManager.syncInstallGroup(groupEntity);
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Finished installing GroupEntity with jobCoordinator key {} groupEntity.groupId {}"
-                            + "  groupEntity.groupType {}", jobKey, groupEntity.getGroupId(),
-                            groupEntity.getGroupType());
-                }
-            } else {
-                mdsalApiManager.removeGroup(groupEntity);
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Finished removing GroupEntity with jobCoordinator key {} groupEntity.groupId {}"
-                            + "  groupEntity.groupType {}", jobKey, groupEntity.getGroupId(),
-                            groupEntity.getGroupType());
-                }
+            mdsalApiManager.syncInstallGroup(remoteGroupEntity);
+            if (!localBucketInfo.isEmpty() && !remoteBucketInfo.isEmpty()) {
+                mdsalApiManager.syncInstallGroup(localGroupEntity);
+            }
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Finished installing GroupEntity with jobCoordinator key {} remoteGroupEntity.groupId {}"
+                        + "localGroupEntity.groupId {}  groupEntity.groupType {}", jobKey,
+                        remoteGroupEntity.getGroupId(), localGroupEntity.getGroupId(),
+                        remoteGroupEntity.getGroupType());
+            }
+            return Collections.emptyList();
+        });
+        return remoteGroupId;
+    }
+
+    protected void deleteLoadBalancingNextHop(Long parentVpnId, BigInteger dpnId, String destPrefix) {
+        long remoteGroupId = createNextHopPointer(getRemoteSelectGroupKey(parentVpnId, destPrefix));
+        if (remoteGroupId == FibConstants.INVALID_GROUP_ID) {
+            LOG.error("Unable to allocate/retrieve remote groupId for vpnId {} , prefix {}", parentVpnId, destPrefix);
+        }
+        long localGroupId = createNextHopPointer(getLocalSelectGroupKey(parentVpnId, destPrefix));
+        if (localGroupId == FibConstants.INVALID_GROUP_ID) {
+            LOG.error("Unable to allocate/retrieve local groupId for vpnId {} , prefix {}", parentVpnId, destPrefix);
+        }
+        String jobKey = FibUtil.getCreateLocalNextHopJobKey(parentVpnId, dpnId, destPrefix);
+        jobCoordinator.enqueueJob(jobKey, () -> {
+            mdsalApiManager.removeGroup(dpnId, remoteGroupId);
+            mdsalApiManager.removeGroup(dpnId, localGroupId);
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Finished removing GroupEntity with jobCoordinator key {} remoteGroupEntity.groupId {}"
+                    + "localGroupEntity.groupId {}", jobKey, remoteGroupId, localGroupId);
             }
             return Collections.emptyList();
         });
-        return groupId;
     }
 
     long createNextHopGroups(Long vpnId, String rd, BigInteger dpnId, VrfEntry vrfEntry,
             Routes routes, List<Routes> vpnExtraRoutes) {
-        List<BucketInfo> listBucketInfo = new ArrayList<>();
+        List<BucketInfo> localBucketInfo = new ArrayList<>();
         List<Routes> clonedVpnExtraRoutes  = new ArrayList<>(vpnExtraRoutes);
         if (clonedVpnExtraRoutes.contains(routes)) {
-            listBucketInfo.addAll(getBucketsForLocalNexthop(vpnId, dpnId, vrfEntry, routes));
+            localBucketInfo.addAll(getBucketsForLocalNexthop(vpnId, dpnId, vrfEntry, routes));
             clonedVpnExtraRoutes.remove(routes);
         }
-        listBucketInfo.addAll(getBucketsForRemoteNexthop(vpnId, dpnId, vrfEntry, rd, clonedVpnExtraRoutes));
-        return setupLoadBalancingNextHop(vpnId, dpnId, vrfEntry.getDestPrefix(), listBucketInfo,true);
+        List<BucketInfo> remoteBucketInfo = new ArrayList<>();
+        remoteBucketInfo.addAll(getBucketsForRemoteNexthop(vpnId, dpnId, vrfEntry, rd, clonedVpnExtraRoutes));
+        return setupLoadBalancingNextHop(vpnId, dpnId,
+            vrfEntry.getDestPrefix(), localBucketInfo, remoteBucketInfo);
     }
 
     private List<BucketInfo> getBucketsForLocalNexthop(Long vpnId, BigInteger dpnId,
index 6003a11c26f1530128f54eda0fc9fd3cfb0c7e37..31ed2640e693a7fea89b481d382f358565211725 100755 (executable)
@@ -867,7 +867,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                 }
                 if (vpnExtraRoutes.size() > 1) {
                     groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes);
-                    localGroupId = nextHopManager.getLocalNextHopGroup(vpnId, localNextHopIP);
+                    localGroupId = nextHopManager.getLocalSelectGroup(vpnId, vrfEntry.getDestPrefix());
                 } else if (routes.getNexthopIpList().size() > 1) {
                     groupId = nextHopManager.createNextHopGroups(vpnId, rd, dpnId, vrfEntry, routes, vpnExtraRoutes);
                     localGroupId = groupId;
@@ -891,7 +891,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                             Collections.singletonList(new ActionGroup(groupId))));
             final List<InstructionInfo> lfibinstructions = Collections.singletonList(
                     new InstructionApplyActions(
-                            Arrays.asList(new ActionPopMpls(etherType), new ActionGroup(groupId))));
+                            Arrays.asList(new ActionPopMpls(etherType), new ActionGroup(localGroupId))));
             java.util.Optional<Long> optLabel = FibUtil.getLabelFromRoutePaths(vrfEntry);
             List<String> nextHopAddressList = FibHelper.getNextHopListFromRoutePaths(vrfEntry);
             String jobKey = FibUtil.getCreateLocalNextHopJobKey(vpnId, dpnId, vrfEntry.getDestPrefix());
@@ -909,15 +909,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                                         nextHopAddressList);
                                 makeLFibTableEntry(dpnId, label, lfibinstructions, DEFAULT_FIB_FLOW_PRIORITY,
                                         NwConstants.ADD_FLOW, tx);
-                                // If the extra-route is reachable from VMs attached to the same switch,
-                                // then the tunnel table can point to the load balancing group.
-                                // If it is reachable from VMs attached to different switches,
-                                // then it should be pointing to one of the local group in order to avoid looping.
-                                if (vrfEntry.getRoutePaths().size() == 1) {
-                                    makeTunnelTableEntry(dpnId, label, groupId, tx);
-                                } else {
-                                    makeTunnelTableEntry(dpnId, label, localGroupId, tx);
-                                }
+                                makeTunnelTableEntry(dpnId, label, localGroupId, tx);
                             } else {
                                 LOG.debug("Route with rd {} prefix {} label {} nexthop {} for vpn {} is an imported "
                                                 + "route. LFib and Terminating table entries will not be created.",
@@ -1082,9 +1074,7 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                             vrfEntry, shouldUpdateNonEcmpLocalNextHop);
                     if (!dpnId.equals(BigInteger.ZERO)) {
                         LOG.trace("Deleting ECMP group for prefix {}, dpn {}", vrfEntry.getDestPrefix(), dpnId);
-                        nextHopManager.setupLoadBalancingNextHop(vpnId, dpnId,
-                                vrfEntry.getDestPrefix(), /*listBucketInfo*/ Collections.emptyList(),
-                                /*remove*/ false);
+                        nextHopManager.deleteLoadBalancingNextHop(vpnId, dpnId, vrfEntry.getDestPrefix());
                         returnLocalDpnId.add(dpnId);
                     }
                 } else {
@@ -1385,6 +1375,10 @@ public class VrfEntryListener extends AsyncDataTreeChangeListenerBase<VrfEntry,
                                         vrfEntry.getDestPrefix()));
                         txRunner.callWithNewWriteOnlyTransactionAndSubmit(CONFIGURATION, configTx ->
                             configTx.delete(VpnExtraRouteHelper.getUsedRdsIdentifier(vpnId, vrfEntry.getDestPrefix())));
+                        nextHopManager.removeNextHopPointer(nextHopManager
+                                .getRemoteSelectGroupKey(vpnId, vrfEntry.getDestPrefix()));
+                        nextHopManager.removeNextHopPointer(nextHopManager
+                                .getLocalSelectGroupKey(vpnId, vrfEntry.getDestPrefix()));
                     }
                 }
                 handleAdjacencyAndVpnOpInterfaceDeletion(vrfEntry, ifName, vpnName, tx);