From 8f303e1b0ea0d35ae33d9b8c2d6b790b6485c1c0 Mon Sep 17 00:00:00 2001 From: Deepak Singhal Date: Thu, 25 Jun 2026 05:16:18 +0000 Subject: [PATCH] [frr]: Fix zebra NB RIB route lookup_next route_node lock under-run Add FRR patch 0115 to drop the erroneous route_unlock_node() in the zebra northbound oper-state RIB route iterator (lib_vrf_zebra_ribs_rib_route_ lookup_next). The node returned by lookup_next() seeds the get_next -> route_next() iteration, which unlocks its input; releasing the lock in lookup_next() under-runs the route_node lock to zero and aborts zebra (assertion node->lock > 0) during the post-restart RIB sweep, wedging vtysh and stalling bgpd. Fixes: https://github.com/sonic-net/sonic-buildimage/issues/27788 Signed-off-by: Deepak Singhal (cherry picked from commit 0361265da273e4a08d03831c1515e041e4ba3de6) --- ...ode-lock-in-NB-RIB-route-lookup_next.patch | 60 +++++++++++++++++++ src/sonic-frr/patch/series | 1 + 2 files changed, 61 insertions(+) create mode 100644 src/sonic-frr/patch/0115-zebra-keep-route_node-lock-in-NB-RIB-route-lookup_next.patch diff --git a/src/sonic-frr/patch/0115-zebra-keep-route_node-lock-in-NB-RIB-route-lookup_next.patch b/src/sonic-frr/patch/0115-zebra-keep-route_node-lock-in-NB-RIB-route-lookup_next.patch new file mode 100644 index 0000000000..bda5b9d36e --- /dev/null +++ b/src/sonic-frr/patch/0115-zebra-keep-route_node-lock-in-NB-RIB-route-lookup_next.patch @@ -0,0 +1,60 @@ +From 19e6c1b652a4fb7263108d3b65b9b84d2b3f2d31 Mon Sep 17 00:00:00 2001 +From: Deepak Singhal +Date: Wed, 1 Jul 2026 18:07:22 +0000 +Subject: [PATCH] zebra: keep route_node lock in NB RIB route lookup_next + +The northbound oper-state iterator for the +/frr-vrf:lib/vrf/frr-zebra:zebra/ribs/rib/route list uses lookup_next() +to resume a yielded walk. lookup_next() calls route_table_get_next(), +which returns a route_node with the lock it acquired held, and then +immediately released it with route_unlock_node() before returning the +node. + +That node is carried back into the walk as args->list_entry and passed +to lib_vrf_zebra_ribs_rib_route_get_next() -> srcdest_route_next() -> +route_next(), which unlocks its input node as part of advancing. Because +lookup_next() had already dropped the lock, route_next() under-runs the +lock count to zero and trips: + + zebra: assertion (node->lock > 0) failed + +aborting zebra. This is hit when the oper-state notification walk (on by +default since the FRR VRF YANG state was added) traverses a large RIB +and yields, then resumes through lookup_next(). + +lookup_entry() is a self-contained point lookup and correctly unlocks +the node it returns. lookup_next(), by contrast, seeds an iteration +whose first step (route_next) expects the carried node to still be +locked. Remove the erroneous route_unlock_node() so the iterator lock +contract holds. + +Link: https://github.com/sonic-net/sonic-buildimage/issues/27788 +Signed-off-by: Deepak Singhal +--- + zebra/zebra_nb_state.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c +index 543d4b38b3..d1d214281f 100644 +--- a/zebra/zebra_nb_state.c ++++ b/zebra/zebra_nb_state.c +@@ -399,8 +399,14 @@ lib_vrf_zebra_ribs_rib_route_lookup_next(struct nb_cb_lookup_entry_args *args) + if (!rn) + return NULL; + +- route_unlock_node(rn); +- ++ /* ++ * Unlike lib_vrf_zebra_ribs_rib_route_lookup_entry() (a self-contained ++ * point lookup), this function seeds the get_next iteration: the ++ * returned node is carried as args->list_entry into ++ * lib_vrf_zebra_ribs_rib_route_get_next() -> srcdest_route_next() -> ++ * route_next(), which unlocks its input node. The node returned by ++ * route_table_get_next() must therefore keep the lock it carries. ++ */ + return rn; + } + +-- +2.34.1 + diff --git a/src/sonic-frr/patch/series b/src/sonic-frr/patch/series index 9baa6a7adb..93232333a8 100644 --- a/src/sonic-frr/patch/series +++ b/src/sonic-frr/patch/series @@ -82,3 +82,4 @@ 0112-SONiC-ONLY-lib-build-add-configure-check-for-tc_mallinfo2-and-fallback.patch 0113-zebra-Refactor-SRv6-netlink-code-to-remove-duplication.patch 0114-Provide-interface-when-installing-uninstalling-SRv6-uA-SIDs.patch +0115-zebra-keep-route_node-lock-in-NB-RIB-route-lookup_next.patch