From cd156bd5540e43b05939ed5d951c912ebc6fa795 Mon Sep 17 00:00:00 2001 From: Louis Scalbert Date: Fri, 22 Mar 2024 10:15:45 +0100 Subject: [PATCH] zebra: fix rejected route due to wrong nexthop-group A specific sequence of actions involving the addition and removal of IP routes and network interfaces can lead to a route installation failure. The issue occurs under the following conditions: - Initially, there is no route present via the ens3 interface. - Adds a route: ip route 10.0.0.0/24 192.168.0.100 ens3 - Removes the same route: no ip route 10.0.0.0/24 192.168.0.100 ens3 - Removes the ens3 interface. - Re-adds the ens3 interface. - Again adds the same route: ip route 10.0.0.0/24 192.168.0.100 ens3 - And again removes it: no ip route 10.0.0.0/24 192.168.0.100 ens3 - Shuts down the ens3 interface - Reactivates the interface - Adds the route once more: ip route 10.0.0.0/24 192.168.0.100 ens3 The route appears to be rejected. > # show ip route nexthop > S>r 10.0.0.0/24 [1/0] (6) via 192.168.0.100, ens3, weight 1, 00:00:01 The commit 35729f38fa ("zebra: Add a timer to nexthop group deletion") introduced a feature to keep a nexthop-group in Zebra for a certain period even when it is no longer in use. But if a nexthop-group interface is removed during this period, the association between the nexthop-group and the interface is lost in zebra memory. If the interface is later added back and a route is re-established, the nexthop-group interface dependency is not correctly reestablished. As a consequence, the nexthop-group flags remain unset when the interface is down. Upon the interface's reactivation, zebra does not reinstall the nexthop-group in the kernel because it is marked as valid and installed, but in reality, it does not exist in the kernel (it was removed when the interface was down). Thus, attempts to install a route via this nexthop-group ID fail. Stop maintaining a nexthop-group when its associated interface is no longer present. Signed-off-by: Louis Scalbert --- zebra/interface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zebra/interface.c b/zebra/interface.c index 81118635583d..34adefdc036f 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -176,6 +176,9 @@ static void if_nhg_dependents_release(const struct interface *ifp) frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) { rb_node_dep->nhe->ifp = NULL; /* Null it out */ zebra_nhg_check_valid(rb_node_dep->nhe); + if (CHECK_FLAG(rb_node_dep->nhe->flags, NEXTHOP_GROUP_KEEP_AROUND) && + rb_node_dep->nhe->refcnt == 1) + zebra_nhg_decrement_ref(rb_node_dep->nhe); } }