From b0bed15eda33d89069695f39d54763a70750f65a Mon Sep 17 00:00:00 2001 From: InspurSDN Date: Thu, 4 Jul 2024 15:57:01 +0800 Subject: [PATCH] fdb_flush.lua executes so long leading to REDIS BUSY Why I did it mac learning, configure TC1 to send the traffic of smac changes (number 217600). Log error: No More Resources, Orchagent hang Nov 29 17:50:47.706137 NV2 ERR syncd#SDK: [FDB_UC.ERR] Polling enabled on error Nov 29 17:50:47.806214 NV2 ERR syncd#SDK: [FDB_UC.ERR] Failed adding entries to RM (No More Resources) Nov 29 17:50:47.806214 NV2 ERR syncd#SDK: [FDB_UC.ERR] Process polled data failed on SWID - 0, status - No More Resources Nov 29 17:50:47.806214 NV2 ERR syncd#SDK: [FDB_UC.ERR] Polling enabled on error Nov 29 17:50:47.906356 NV2 ERR syncd#SDK: [FDB_UC.ERR] Failed adding entries to RM (No More Resources) What I did Instead of using Lua script to flush, use loop deletion in the code. --- syncd/RedisClient.cpp | 51 +++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/syncd/RedisClient.cpp b/syncd/RedisClient.cpp index 2ce2eac1f..d890ee623 100644 --- a/syncd/RedisClient.cpp +++ b/syncd/RedisClient.cpp @@ -893,17 +893,46 @@ void RedisClient::processFlushEvent( SWSS_LOG_THROW("unknown fdb flush entry type: %d", type); } - for (int flush_static: vals) + // If has a lot of macs(example:217600) and use lua scripts, will cause REDIS BUSY. + // Change to this without atomicity operation. + const auto &keys = m_dbAsic->keys(pattern); + size_t countFlushed = 0; + if (vals.size() == 2 && portStr.empty()) { - swss::RedisCommand command; - - command.format( - "EVALSHA %s 3 %s %s %s", - m_fdbFlushSha.c_str(), - pattern.c_str(), - portStr.c_str(), - std::to_string(flush_static).c_str()); - - swss::RedisReply r(m_dbAsic.get(), command); + for (const auto &it: keys) + { + m_dbAsic->del(it); + countFlushed++; + } + } + else if (vals.size() == 2 && !portStr.empty()) + { + for (const auto &it: keys) + { + auto bridgePortIdFromDb = m_dbAsic->hget(it, "SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"); + if (bridgePortIdFromDb && *bridgePortIdFromDb == portStr) + { + m_dbAsic->del(it); + countFlushed++; + } + } + } + else if (vals.size() == 1) + { + auto typeWants = vals.front() == 0 ? + "SAI_FDB_ENTRY_TYPE_DYNAMIC" : "SAI_FDB_ENTRY_TYPE_STATIC"; + for (const auto &it: keys) + { + auto bridgePortIdFromDb = m_dbAsic->hget(it, "SAI_FDB_ENTRY_ATTR_BRIDGE_PORT_ID"); + auto typeFromDb = m_dbAsic->hget(it, "SAI_FDB_ENTRY_ATTR_TYPE"); + if ((typeFromDb && *typeFromDb == typeWants) && + (portStr.empty() || (!portStr.empty() && bridgePortIdFromDb && + *bridgePortIdFromDb == portStr))) + { + m_dbAsic->del(it); + countFlushed++; + } + } } + SWSS_LOG_NOTICE("RedisClient have flushed %lu fdb entries.", countFlushed); }