Skip to content

Commit f24948a

Browse files
committed
bgpd: fix valgrind memory leaks on daemon shutdown
During daemon termination, the default BGP instance leaks due to two issues: First, bgp_cleanup_routes() skips EVPN and ENCAP two-level table cleanup for hidden instances, leaving route entries. Add a terminating check so these tables are always cleaned during shutdown. Second, a circular dependency exists between bgp_free() and VNI lock release: each L2VNI holds a bgp_lock on the default instance via bgpevpn_link_to_l3vni(), but the only code that releases these locks (bgp_evpn_cleanup -> free_vni_entry -> bgpevpn_unlink_from_l3vni) lives inside bgp_free(), which only runs when the lock count reaches zero. Break this cycle by calling bgp_evpn_cleanup() from bgp_delete() during termination, before the final bgp_unlock(). This releases VNI-held locks so the refcount can reach zero and bgp_free() actually executes. Signed-off-by: Soumya Roy <souroy@nvidia.com>
1 parent 93ad76e commit f24948a

3 files changed

Lines changed: 15 additions & 2 deletions

File tree

bgpd/bgp_evpn.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5377,7 +5377,8 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
53775377
*
53785378
* NOTE: NO need to pop the VPN routes in two cases
53795379
* 1) In free_vni_entry
5380-
* - Called by bgp_free()->bgp_evpn_cleanup().
5380+
* - Called by bgp_free()->bgp_evpn_cleanup() or
5381+
* bgp_delete()->bgp_evpn_cleanup() when terminating.
53815382
* - Since bgp_delete is called before bgp_free and we pop all the dest
53825383
* pertaining to bgp under delete.
53835384
* 2) evpn_delete_vni() when user configures "no vni" since the withdraw
@@ -7770,6 +7771,10 @@ void bgp_evpn_cleanup_on_disable(struct bgp *bgp)
77707771
*/
77717772
void bgp_evpn_cleanup(struct bgp *bgp)
77727773
{
7774+
/* Guard against double-call during termination */
7775+
if (!bgp->vnihash)
7776+
return;
7777+
77737778
hash_iterate(bgp->vnihash,
77747779
(void (*)(struct hash_bucket *, void *))free_vni_entry,
77757780
bgp);

bgpd/bgp_route.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8030,7 +8030,7 @@ void bgp_cleanup_routes(struct bgp *bgp)
80308030
/*
80318031
* VPN and ENCAP and EVPN tables are two-level (RD is top level)
80328032
*/
8033-
if (safi != SAFI_MPLS_VPN && IS_BGP_INSTANCE_HIDDEN(bgp))
8033+
if (safi != SAFI_MPLS_VPN && IS_BGP_INSTANCE_HIDDEN(bgp) && !bm->terminating)
80348034
continue;
80358035

80368036
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest; dest = bgp_route_next(dest)) {

bgpd/bgpd.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4590,6 +4590,14 @@ int bgp_delete(struct bgp *bgp)
45904590

45914591
bgp_cleanup_routes(bgp);
45924592

4593+
if (bm->terminating)
4594+
/*
4595+
* Release EVPN VNI bgp_lock references so the
4596+
* subsequent bgp_unlock() can drive refcount to
4597+
* zero and trigger bgp_free().
4598+
*/
4599+
bgp_evpn_cleanup(bgp);
4600+
45934601
for (afi = 0; afi < AFI_MAX; ++afi) {
45944602
if (!bgp->vpn_policy[afi].import_redirect_rtlist)
45954603
continue;

0 commit comments

Comments
 (0)