Scale BGP issues & fib shows nexthop as local 04/86404/4
authorzhmxman <manjunathahm@altencalsoftlabs.com>
Thu, 12 Dec 2019 07:23:17 +0000 (12:53 +0530)
committerChetan Arakere Gowdru <chetan.arakere@altencalsoftlabs.com>
Tue, 31 Mar 2020 04:57:43 +0000 (04:57 +0000)
ODL was getting stuck with scale BGP routes.
adding few optimizations
When the setup is scaled upto 10k DC-GW routes the error is seen.
Adding entries to a hashmap to resolve the errors

JIRA: NETVIRT-1649

Change-Id: I55092986eba2e4f1ff93c9033aed5a3cd7f2b136
Signed-off-by: zhmxman <manjunath.hethur@gmail.com>
bgpmanager/impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpConfigurationManager.java
bgpmanager/impl/src/main/java/org/opendaylight/netvirt/bgpmanager/BgpUtil.java
bgpmanager/impl/src/main/java/org/opendaylight/netvirt/bgpmanager/FibDSWriter.java

index 09398dc7fef74b12ebe885f0f3d9aa6a139cd64f..6ddf2370300aef2615d6c9ea1ce91b5018033467 100755 (executable)
@@ -264,6 +264,9 @@ public class BgpConfigurationManager implements EbgpService {
     // map<rd, map<tep-ip, map<mac, l2vni>>>
     private final Map<String, Map<String, Map<String, Uint32>>> rt2TepMap = new ConcurrentHashMap<>();
 
+    //map<rd+prefix/plen, list (nexthop)>
+    private final Map<String,List> fibMap = new HashMap<>();
+
     private final List<AutoCloseable> listeners = new ArrayList<>();
 
     private final EntityOwnershipUtils entityOwnershipUtils;
index 6676ece127f328594fc5bbc986c37b971fe78f03..245850e44eec579920603cfa62a9ce5a3f11f3bb 100755 (executable)
@@ -12,7 +12,9 @@ import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import javax.annotation.PostConstruct;
@@ -265,8 +267,15 @@ public class BgpUtil implements AutoCloseable {
     }
 
     public String getVpnNameFromRd(String rd) {
-        VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
-        return vpnInstanceOpData != null ? vpnInstanceOpData.getVpnInstanceName() : null;
+        final Map<String, String> rdtoVpnMap = new HashMap<>();
+        if (rdtoVpnMap.get(rd) != null) {
+            return rdtoVpnMap.get(rd);
+        } else {
+            VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(rd);
+            String vpnName = vpnInstanceOpData != null ? vpnInstanceOpData.getVpnInstanceName() : null;
+            rdtoVpnMap.put(rd, vpnName);
+            return vpnName;
+        }
     }
 
     /** get the vrf with the RouterDistinguisher pass in param.
index 88dfd9417d95a1326db8f5f27a8d20657e109669..e9d62323e33b69c402a4b1c3c7f51bbea4442ca9 100644 (file)
@@ -7,10 +7,12 @@
  */
 package org.opendaylight.netvirt.bgpmanager;
 
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
-import java.util.Collections;
+
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -45,12 +47,30 @@ public class FibDSWriter {
     private final SingleTransactionDataBroker singleTxDB;
     private final BgpUtil bgpUtil;
 
+    private final Map<String,ArrayList<String>> fibMap = new HashMap<>();
+
     @Inject
     public FibDSWriter(final DataBroker dataBroker, final BgpUtil bgpUtil) {
         this.bgpUtil = bgpUtil;
         this.singleTxDB = new SingleTransactionDataBroker(dataBroker);
     }
 
+    public synchronized void clearFibMap() {
+        fibMap.clear();
+    }
+
+    public synchronized void addEntryToFibMap(String rd, String prefix, String nextHop) {
+        ArrayList<String> temp = new ArrayList<String>();
+        if ((fibMap.get(appendrdtoprefix(rd, prefix)) != null)) {
+            temp.addAll(fibMap.get(appendrdtoprefix(rd, prefix)));
+        }
+        temp.add(nextHop);
+        fibMap.put(appendrdtoprefix(rd, prefix),temp);
+        LOG.debug("addEntryToFibMap rd {} prefix {} nexthop {}",
+                rd, prefix, nextHop);
+
+    }
+
     public synchronized void addFibEntryToDS(String rd, String prefix, List<String> nextHopList,
                                              VrfEntry.EncapType encapType, Uint32 label, Uint32 l3vni,
                                              String gatewayMacAddress, RouteOrigin origin) {
@@ -80,6 +100,10 @@ public class FibDSWriter {
         bgpUtil.update(vrfEntryId, vrfEntryBuilder.build());
     }
 
+    private String appendrdtoprefix(String rd, String prefix) {
+        return rd + "/" + prefix;
+    }
+
     public void addMacEntryToDS(String rd, String macAddress, String prefix,
                                 List<String> nextHopList, VrfEntry.EncapType encapType,
                                 Uint32 l2vni, String gatewayMacAddress, RouteOrigin origin) {
@@ -175,33 +199,31 @@ public class FibDSWriter {
         }
         LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {} and nextHop {}",
                 prefix, rd, nextHop);
-        try {
-            InstanceIdentifier<VrfEntry> vrfEntryId =
-                    InstanceIdentifier.builder(FibEntries.class)
-                    .child(VrfTables.class, new VrfTablesKey(rd))
-                    .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
-            Optional<VrfEntry> existingVrfEntry =
-                    singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, vrfEntryId);
-            List<RoutePaths> routePaths =
-                    existingVrfEntry.toJavaUtil().map(VrfEntry::getRoutePaths).orElse(Collections.emptyList());
-            if (routePaths.size() == 1) {
-                if (routePaths.get(0).getNexthopAddress().equals(nextHop)) {
-                    bgpUtil.delete(vrfEntryId);
-                }
+
+
+        InstanceIdentifier<VrfEntry> vrfEntryId =
+                InstanceIdentifier.builder(FibEntries.class)
+                        .child(VrfTables.class, new VrfTablesKey(rd))
+                        .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
+
+        LOG.debug("removeOrUpdateFibEntryFromDS rd {} prefix {} NH {}",
+                rd, prefix, nextHop);
+
+        if (fibMap.get(appendrdtoprefix(rd,prefix)) != null) { //Key is there
+            // If nexthop is there, delete it from List
+            List<String> list = fibMap.get(appendrdtoprefix(rd,prefix));
+            list.remove(nextHop);
+            if (list.isEmpty()) {
+                fibMap.remove(appendrdtoprefix(rd, prefix));
+                bgpUtil.delete(vrfEntryId);
             } else {
-                routePaths.stream()
-                    .map(RoutePaths::getNexthopAddress)
-                    .filter(nextHopAddress -> nextHopAddress.equals(nextHop))
-                    .findFirst()
-                    .ifPresent(nh -> {
-                        InstanceIdentifier<RoutePaths> routePathId =
-                                FibHelper.buildRoutePathId(rd, prefix, nextHop);
-                        bgpUtil.delete(routePathId);
-                    });
+                InstanceIdentifier<RoutePaths> routePathId =
+                        FibHelper.buildRoutePathId(rd, prefix, nextHop);
+                bgpUtil.delete(routePathId);
             }
-        } catch (ReadFailedException e) {
-            LOG.error("Error while reading vrfEntry for rd {}, prefix {}", rd, prefix);
-            return;
+        } else {
+            LOG.error("Invalid Delete from Quagga, RD {} Prefix {} Nexthop {}  ",
+                    rd,prefix,nextHop);
         }
     }