From: Donald Sharp Date: Thu, 9 Jan 2025 17:34:50 +0000 (-0500) Subject: zebra: Fix leaked nhe X-Git-Tag: base_10.3~84^2 X-Git-Url: https://git.puffer.fish/?a=commitdiff_plain;h=97fa24e70b35bdfb99b9efc163dbcb5c09242527;p=matthieu%2Ffrr.git zebra: Fix leaked nhe During route processing in zebra, Zebra will create a nexthop group that matches the nexthops passed down from the routing protocol. Then Zebra will look to see if it can re-use a nhe from a previous version of the route entry( say a interface goes down ). If Zebra decides to re-use an nhe it was just dropping the route entry created. Which led to nexthop group's that had a refcount of 0 and in some cases these nexthop groups were installed into the kernel. Add a bit of code to see if the returned entry is not being used and it has no reference count and if so, properly dispose of it. Signed-off-by: Donald Sharp --- diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c index a32fc2bb14..6a43fe0c84 100644 --- a/zebra/zebra_nhg.c +++ b/zebra/zebra_nhg.c @@ -3089,7 +3089,7 @@ static struct nhg_hash_entry *zebra_nhg_rib_compare_old_nhe( int nexthop_active_update(struct route_node *rn, struct route_entry *re, struct route_entry *old_re) { - struct nhg_hash_entry *curr_nhe; + struct nhg_hash_entry *curr_nhe, *remove; uint32_t curr_active = 0, backup_active = 0; if (PROTO_OWNED(re->nhe)) @@ -3143,16 +3143,25 @@ backups_done: new_nhe = zebra_nhg_rib_find_nhe(curr_nhe, rt_afi); + remove = new_nhe; + if (old_re && old_re->type == re->type && old_re->instance == re->instance) new_nhe = zebra_nhg_rib_compare_old_nhe(rn, re, new_nhe, old_re->nhe); if (IS_ZEBRA_DEBUG_NHG_DETAIL) - zlog_debug( - "%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG)", - __func__, re, re->nhe, re->nhe, new_nhe, - new_nhe); + zlog_debug("%s: re %p CHANGED: nhe %p (%pNG) => new_nhe %p (%pNG) rib_find_nhe returned %p (%pNG) refcnt: %d", + __func__, re, re->nhe, re->nhe, new_nhe, new_nhe, remove, remove, + remove ? remove->refcnt : 0); + + /* + * if the results from zebra_nhg_rib_find_nhe is being + * dropped and it was generated in that function + * (refcnt of 0) then we know we can clean it up + */ + if (remove && remove != new_nhe && remove != re->nhe && remove->refcnt == 0) + zebra_nhg_handle_uninstall(remove); route_entry_update_nhe(re, new_nhe); }