From 67759f2be90df7900efd26759aaf056267cd9cf8 Mon Sep 17 00:00:00 2001 From: Nikhil Kelapure Date: Wed, 7 Apr 2021 12:31:45 -0700 Subject: [PATCH 1/3] Extending eoiu script to handle evpn af --- fpmsyncd/bgp_eoiu_marker.py | 43 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/fpmsyncd/bgp_eoiu_marker.py b/fpmsyncd/bgp_eoiu_marker.py index 83051d7878..c0e59e0fe5 100644 --- a/fpmsyncd/bgp_eoiu_marker.py +++ b/fpmsyncd/bgp_eoiu_marker.py @@ -40,9 +40,12 @@ def __init__(self): self.ipv4_neigh_eor_status = {} self.ipv6_neighbors = [] self.ipv6_neigh_eor_status = {} + self.evpn_neighbors = [] + self.evpn_neigh_eor_status = {} self.keepalivesRecvCnt = {} self.bgp_ipv4_eoiu = False self.bgp_ipv6_eoiu = False + self.bgp_evpn_eoiu = False self.get_peers_wt = self.DEF_TIME_OUT def get_all_peers(self): @@ -57,8 +60,12 @@ def get_all_peers(self): if "ipv6Unicast" in peer_info and "peers" in peer_info["ipv6Unicast"]: self.ipv6_neighbors = peer_info["ipv6Unicast"]["peers"].keys() + if "l2VpnEvpn" in peer_info and "peers" in peer_info["l2VpnEvpn"]: + self.evpn_neighbors = peer_info["l2VpnEvpn"]["peers"].keys() + syslog.syslog('BGP ipv4 neighbors: {}'.format(self.ipv4_neighbors)) - syslog.syslog('BGP ipv4 neighbors: {}'.format(self.ipv6_neighbors)) + syslog.syslog('BGP ipv6 neighbors: {}'.format(self.ipv6_neighbors)) + syslog.syslog('BGP evpn neighbors: {}'.format(self.evpn_neighbors)) return except Exception: @@ -75,6 +82,8 @@ def init_peers_eor_status(self): self.ipv4_neigh_eor_status[neigh] = "unknown" for neigh in self.ipv6_neighbors: self.ipv6_neigh_eor_status[neigh] = "unknown" + for neigh in self.evpn_neighbors: + self.evpn_neigh_eor_status[neigh] = "unknown" # Set the statedb "BGP_STATE_TABLE|eoiu", so fpmsyncd can get the bgp eoiu signal # Only two families: 'ipv4' and 'ipv6' @@ -94,13 +103,15 @@ def clean_bgp_eoiu_marker(self): db.connect(db.STATE_DB, False) db.delete(db.STATE_DB, "BGP_STATE_TABLE|IPv4|eoiu") db.delete(db.STATE_DB, "BGP_STATE_TABLE|IPv6|eoiu") + db.delete(db.STATE_DB, "BGP_STATE_TABLE|Evpn|eoiu") db.close(db.STATE_DB) - syslog.syslog('Cleaned ipv4 and ipv6 eoiu marker flags') + syslog.syslog('Cleaned ipv4 evpn and ipv6 eoiu marker flags') return - def bgp_eor_received(self, neigh, is_ipv4): + def bgp_eor_received(self, neigh, af): try: neighstr = "%s" % neigh + af_str = "%s" % af eor_received = False cmd = "vtysh -c 'show bgp neighbors %s json'" % neighstr output = commands.getoutput(cmd) @@ -109,9 +120,11 @@ def bgp_eor_received(self, neigh, is_ipv4): if "gracefulRestartInfo" in neig_status[neighstr]: if "endOfRibRecv" in neig_status[neighstr]["gracefulRestartInfo"]: eor_info = neig_status[neighstr]["gracefulRestartInfo"]["endOfRibRecv"] - if is_ipv4 and "IPv4 Unicast" in eor_info and eor_info["IPv4 Unicast"] == True: + if af_str == "Ipv4" and "ipv4Unicast" in eor_info and eor_info["ipv4Unicast"] == True: + eor_received = True + elif af_str == "Ipv6" and "ipv6Unicast" in eor_info and eor_info["ipv6Unicast"] == True: eor_received = True - elif not is_ipv4 and "IPv6 Unicast" in eor_info and eor_info["IPv6 Unicast"] == True: + elif af_str == "Evpn" and "l2VpnEvpn" in eor_info and eor_info["l2VpnEvpn"] == True: eor_received = True if eor_received: syslog.syslog('BGP eor received for neighbors: {}'.format(neigh)) @@ -150,7 +163,7 @@ def wait_for_bgp_eoiu(self): while wait_time >= 0: if not self.bgp_ipv4_eoiu: for neigh, eor_status in self.ipv4_neigh_eor_status.items(): - if eor_status == "unknown" and self.bgp_eor_received(neigh, True): + if eor_status == "unknown" and self.bgp_eor_received(neigh, "Ipv4"): self.ipv4_neigh_eor_status[neigh] = "rcvd" if "unknown" not in self.ipv4_neigh_eor_status.values(): self.bgp_ipv4_eoiu = True @@ -158,13 +171,21 @@ def wait_for_bgp_eoiu(self): if not self.bgp_ipv6_eoiu: for neigh, eor_status in self.ipv6_neigh_eor_status.items(): - if eor_status == "unknown" and self.bgp_eor_received(neigh, False): + if eor_status == "unknown" and self.bgp_eor_received(neigh, "Ipv6"): self.ipv6_neigh_eor_status[neigh] = "rcvd" if "unknown" not in self.ipv6_neigh_eor_status.values(): self.bgp_ipv6_eoiu = True syslog.syslog('BGP ipv6 eoiu reached') - if self.bgp_ipv6_eoiu and self.bgp_ipv4_eoiu: + if not self.bgp_evpn_eoiu: + for neigh, eor_status in self.evpn_neigh_eor_status.items(): + if eor_status == "unknown" and self.bgp_eor_received(neigh, "Evpn"): + self.evpn_neigh_eor_status[neigh] = "rcvd" + if "unknown" not in self.evpn_neigh_eor_status.values(): + self.bgp_evpn_eoiu = True + syslog.syslog("BGP evpn eoiu reached") + + if self.bgp_ipv6_eoiu and self.bgp_ipv4_eoiu and self.bgp_evpn_eoiu: break; time.sleep(self.CHECK_INTERVAL) wait_time -= self.CHECK_INTERVAL @@ -175,6 +196,9 @@ def wait_for_bgp_eoiu(self): if not self.bgp_ipv4_eoiu: syslog.syslog(syslog.LOG_ERR, "BGP ipv4 eoiu not reached: {}".format(self.ipv4_neigh_eor_status)); + if not self.bgp_evpn_eoiu: + syslog.syslog(syslog.LOG_ERR, "BGP evpn eoiu not reached: {}".format(self.evpn_neigh_eor_status)); + def main(): print "bgp_eoiu_marker service is started" @@ -200,6 +224,7 @@ def main(): bgp_state_check.set_bgp_eoiu_marker("IPv4", "unknown") bgp_state_check.set_bgp_eoiu_marker("IPv6", "unknown") + bgp_state_check.set_bgp_eoiu_marker("Evpn", "unknown") bgp_state_check.get_all_peers() bgp_state_check.init_peers_eor_status() try: @@ -213,6 +238,8 @@ def main(): bgp_state_check.set_bgp_eoiu_marker("IPv4", "reached") if bgp_state_check.bgp_ipv6_eoiu: bgp_state_check.set_bgp_eoiu_marker("IPv6", "reached") + if bgp_state_check.bgp_evpn_eoiu: + bgp_state_check.set_bgp_eoiu_marker("Evpn", "reached") print "bgp_eoiu_marker service is done" return From 6b99ffefa8ec04582bbbed8002d9b78b531775d4 Mon Sep 17 00:00:00 2001 From: Nikhil Kelapure Date: Thu, 8 Apr 2021 00:35:03 -0700 Subject: [PATCH 2/3] Adapting fdbsyncd to make use of eoiu feature to optimize the reconcillation time --- fdbsyncd/fdbsyncd.cpp | 79 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/fdbsyncd/fdbsyncd.cpp b/fdbsyncd/fdbsyncd.cpp index dac4bb85e5..2b3a7fdcd3 100644 --- a/fdbsyncd/fdbsyncd.cpp +++ b/fdbsyncd/fdbsyncd.cpp @@ -12,6 +12,36 @@ using namespace std; using namespace swss; +// Wait 3 seconds after detecting EOIU reached state +const uint32_t DEFAULT_EOIU_HOLD_INTERVAL = 3; + +// Check if eoiu state reached by ipv4 ipv6 and evpn +static bool eoiuFlagsSet(Table &bgpStateTable) +{ + string value; + + bgpStateTable.hget("IPv4|eoiu", "state", value); + if (value != "reached") + { + SWSS_LOG_DEBUG("IPv4|eoiu state: %s", value.c_str()); + return false; + } + bgpStateTable.hget("IPv6|eoiu", "state", value); + if (value != "reached") + { + SWSS_LOG_DEBUG("IPv6|eoiu state: %s", value.c_str()); + return false; + } + bgpStateTable.hget("Evpn|eoiu", "state", value); + if (value != "reached") + { + SWSS_LOG_DEBUG("Evpn|eoiu state: %s", value.c_str()); + return false; + } + SWSS_LOG_NOTICE("Warm-Restart bgp eoiu reached for ipv4 Evpn and ipv6"); + return true; +} + int main(int argc, char **argv) { Logger::linkToDbNative("fdbsyncd"); @@ -21,6 +51,8 @@ int main(int argc, char **argv) DBConnector stateDb(STATE_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); DBConnector log_db(LOGLEVEL_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); DBConnector config_db(CONFIG_DB, DBConnector::DEFAULT_UNIXSOCKET, 0); + Table bgpStateTable(&stateDb, STATE_BGP_TABLE_NAME); + FdbSync sync(&pipelineAppDB, &stateDb, &config_db); @@ -37,6 +69,10 @@ int main(int argc, char **argv) int ret; Select s; SelectableTimer replayCheckTimer(timespec{0, 0}); + // Before eoiu flags detected, check them periodically. It also stop upon detection of reconciliation done. + SelectableTimer eoiuCheckTimer(timespec{0, 0}); + // After eoiu flags are detected, start a hold timer before starting reconciliation. + SelectableTimer eoiuHoldTimer(timespec{0, 0}); using namespace std::chrono; @@ -115,9 +151,14 @@ int main(int argc, char **argv) } //Else the interval is already set to default value - //TODO: Optimise the reconcillation time using eoiu - issue#1657 SWSS_LOG_NOTICE("Starting ReconcileTimer"); sync.getRestartAssist()->startReconcileTimer(s); + + // Also start periodic eoiu check timer, first wait 5 seconds, then check every 1 second + eoiuCheckTimer.setInterval(timespec{5, 0}); + eoiuCheckTimer.start(); + s.addSelectable(&eoiuCheckTimer); + SWSS_LOG_NOTICE("Warm-Restart eoiuCheckTimer timer started."); } else { @@ -126,6 +167,39 @@ int main(int argc, char **argv) replayCheckTimer.start(); } } + else if (temps == &eoiuCheckTimer) + { + if (sync.getRestartAssist()->isWarmStartInProgress()) + { + if (eoiuFlagsSet(bgpStateTable)) + { + /* Obtain eoiu hold timer defined for bgp docker */ + uintmax_t eoiuHoldIval = WarmStart::getWarmStartTimer("eoiu_hold", "bgp"); + if (!eoiuHoldIval) + { + eoiuHoldTimer.setInterval(timespec{DEFAULT_EOIU_HOLD_INTERVAL, 0}); + eoiuHoldIval = DEFAULT_EOIU_HOLD_INTERVAL; + } + else + { + eoiuHoldTimer.setInterval(timespec{(time_t)eoiuHoldIval, 0}); + } + eoiuHoldTimer.start(); + s.addSelectable(&eoiuHoldTimer); + SWSS_LOG_NOTICE("Warm-Restart started EOIU hold timer which is to expire in %" PRIuMAX " seconds.", eoiuHoldIval); + s.removeSelectable(&eoiuCheckTimer); + continue; + } + eoiuCheckTimer.setInterval(timespec{1, 0}); + // re-start eoiu check timer + eoiuCheckTimer.start(); + SWSS_LOG_DEBUG("Warm-Restart eoiuCheckTimer restarted"); + } + else + { + s.removeSelectable(&eoiuCheckTimer); + } + } else { /* @@ -134,11 +208,12 @@ int main(int argc, char **argv) */ if (sync.getRestartAssist()->isWarmStartInProgress()) { - if (sync.getRestartAssist()->checkReconcileTimer(temps)) + if (sync.getRestartAssist()->checkReconcileTimer(temps) || temps == &eoiuHoldTimer) { sync.m_reconcileDone = true; sync.getRestartAssist()->stopReconcileTimer(s); sync.getRestartAssist()->reconcile(); + s.removeSelectable(&eoiuHoldTimer); SWSS_LOG_NOTICE("VXLAN FDB VNI Reconcillation Complete"); } } From 20bcc2bede912333298b15b4f9fe359902a3524a Mon Sep 17 00:00:00 2001 From: Nikhil Kelapure Date: Thu, 8 Apr 2021 01:40:24 -0700 Subject: [PATCH 3/3] Adapting fdbsyncd to make use of eoiu feature to optimize the reconcillation time --- fdbsyncd/fdbsyncd.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdbsyncd/fdbsyncd.cpp b/fdbsyncd/fdbsyncd.cpp index 2b3a7fdcd3..37a0bdd1f3 100644 --- a/fdbsyncd/fdbsyncd.cpp +++ b/fdbsyncd/fdbsyncd.cpp @@ -174,7 +174,7 @@ int main(int argc, char **argv) if (eoiuFlagsSet(bgpStateTable)) { /* Obtain eoiu hold timer defined for bgp docker */ - uintmax_t eoiuHoldIval = WarmStart::getWarmStartTimer("eoiu_hold", "bgp"); + uint32_t eoiuHoldIval = WarmStart::getWarmStartTimer("eoiu_hold", "bgp"); if (!eoiuHoldIval) { eoiuHoldTimer.setInterval(timespec{DEFAULT_EOIU_HOLD_INTERVAL, 0}); @@ -186,7 +186,7 @@ int main(int argc, char **argv) } eoiuHoldTimer.start(); s.addSelectable(&eoiuHoldTimer); - SWSS_LOG_NOTICE("Warm-Restart started EOIU hold timer which is to expire in %" PRIuMAX " seconds.", eoiuHoldIval); + SWSS_LOG_NOTICE("Warm-Restart started EOIU hold timer which is to expire in %d seconds.", eoiuHoldIval); s.removeSelectable(&eoiuCheckTimer); continue; }