Skip to content

Commit 6a6860b

Browse files
authored
Merge pull request #19383 from FRRouting/mergify/bp/stable/10.0/pr-19334
bgpd: fix memory leak in evpn mh (backport #19334)
2 parents 502fce4 + fefd8b4 commit 6a6860b

File tree

1 file changed

+64
-6
lines changed

1 file changed

+64
-6
lines changed

bgpd/bgp_evpn_mh.c

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
6868
static void bgp_evpn_run_consistency_checks(struct event *t);
6969
static void bgp_evpn_path_nh_info_free(struct bgp_path_evpn_nh_info *nh_info);
7070
static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info);
71+
static void bgp_evpn_es_vrf_delete(struct bgp_evpn_es_vrf *es_vrf);
72+
static struct bgp_evpn_es_evi *bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi);
7173

7274
/******************************************************************************
7375
* per-ES (Ethernet Segment) routing table
@@ -1948,9 +1950,33 @@ static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
19481950
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
19491951
zlog_debug("%s: es %s free", caller, es->esi_str);
19501952

1951-
/* cleanup resources maintained against the ES */
1952-
list_delete(&es->es_evi_list);
1953-
list_delete(&es->es_vrf_list);
1953+
/* Clean up any remaining ES-VRFs */
1954+
if (es->es_vrf_list) {
1955+
struct listnode *node, *next;
1956+
struct bgp_evpn_es_vrf *es_vrf;
1957+
1958+
for (ALL_LIST_ELEMENTS(es->es_vrf_list, node, next, es_vrf)) {
1959+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1960+
zlog_debug("es %s vrf %u cleanup with evi ref_cnt %d", es->esi_str,
1961+
es_vrf->bgp_vrf->vrf_id, es_vrf->ref_cnt);
1962+
bgp_evpn_es_vrf_delete(es_vrf);
1963+
}
1964+
list_delete(&es->es_vrf_list);
1965+
}
1966+
1967+
/* Clean up any remaining ES-EVIs */
1968+
if (es->es_evi_list) {
1969+
struct listnode *node, *next;
1970+
struct bgp_evpn_es_evi *es_evi;
1971+
1972+
for (ALL_LIST_ELEMENTS(es->es_evi_list, node, next, es_evi)) {
1973+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
1974+
zlog_debug("es %s cleanup ES-EVI VNI %u flags 0x%x", es->esi_str,
1975+
es_evi->vpn->vni, es_evi->flags);
1976+
bgp_evpn_es_evi_free(es_evi);
1977+
}
1978+
list_delete(&es->es_evi_list);
1979+
}
19541980
list_delete(&es->es_vtep_list);
19551981
list_delete(&es->macip_evi_path_list);
19561982
list_delete(&es->macip_global_path_list);
@@ -2996,6 +3022,8 @@ static struct bgp_evpn_es_vrf *bgp_evpn_es_vrf_create(struct bgp_evpn_es *es,
29963022

29973023
es_vrf->es = es;
29983024
es_vrf->bgp_vrf = bgp_vrf;
3025+
es_vrf->ref_cnt = 0;
3026+
es_vrf->flags = 0;
29993027

30003028
/* insert into the VRF-ESI rb tree */
30013029
RB_INSERT(bgp_es_vrf_rb_head, &bgp_vrf->es_vrf_rb_tree, es_vrf);
@@ -3068,7 +3096,7 @@ void bgp_evpn_es_vrf_deref(struct bgp_evpn_es_evi *es_evi)
30683096
es_vrf->bgp_vrf->vrf_id);
30693097

30703098
es_evi->es_vrf = NULL;
3071-
if (es_vrf->ref_cnt)
3099+
if (es_vrf->ref_cnt > 0)
30723100
--es_vrf->ref_cnt;
30733101

30743102
if (!es_vrf->ref_cnt)
@@ -3105,6 +3133,10 @@ void bgp_evpn_es_vrf_ref(struct bgp_evpn_es_evi *es_evi, struct bgp *bgp_vrf)
31053133

31063134
es_evi->es_vrf = es_vrf;
31073135
++es_vrf->ref_cnt;
3136+
3137+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3138+
zlog_debug("es-vrf %s vrf %u evi ref_cnt incremented to %d", es_vrf->es->esi_str,
3139+
es_vrf->bgp_vrf->vrf_id, es_vrf->ref_cnt);
31083140
}
31093141

31103142
/* When the L2-VNI is associated with a L3-VNI/VRF update all the
@@ -3535,12 +3567,18 @@ static struct bgp_evpn_es_evi *bgp_evpn_es_evi_new(struct bgp_evpn_es *es,
35353567
struct bgp_evpn_es_evi *es_evi;
35363568

35373569
es_evi = XCALLOC(MTYPE_BGP_EVPN_ES_EVI, sizeof(*es_evi));
3538-
35393570
es_evi->es = es;
35403571
es_evi->vpn = vpn;
3572+
es_evi->flags = 0;
35413573

35423574
/* Initialise the VTEP list */
35433575
es_evi->es_evi_vtep_list = list_new();
3576+
if (!es_evi->es_evi_vtep_list) {
3577+
flog_err(EC_BGP_ES_CREATE, "Failed to create VTEP list for ES-EVI ES %s VNI %u",
3578+
es->esi_str, vpn->vni);
3579+
XFREE(MTYPE_BGP_EVPN_ES_EVI, es_evi);
3580+
return NULL;
3581+
}
35443582
listset_app_node_mem(es_evi->es_evi_vtep_list);
35453583
es_evi->es_evi_vtep_list->cmp = bgp_evpn_es_evi_vtep_cmp;
35463584

@@ -3553,6 +3591,9 @@ static struct bgp_evpn_es_evi *bgp_evpn_es_evi_new(struct bgp_evpn_es *es,
35533591

35543592
bgp_evpn_es_vrf_ref(es_evi, vpn->bgp_vrf);
35553593

3594+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3595+
zlog_debug("Created ES-EVI for ES %s VNI %u", es->esi_str, vpn->vni);
3596+
35563597
return es_evi;
35573598
}
35583599

@@ -3565,6 +3606,10 @@ bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi)
35653606
struct bgp_evpn_es *es = es_evi->es;
35663607
struct bgpevpn *vpn = es_evi->vpn;
35673608

3609+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3610+
zlog_debug("Freeing ES-EVI for ES %s VNI %u flags 0x%x", es->esi_str, vpn->vni,
3611+
es_evi->flags);
3612+
35683613
/* cannot free the element as long as there is a local or remote
35693614
* reference
35703615
*/
@@ -3582,6 +3627,9 @@ bgp_evpn_es_evi_free(struct bgp_evpn_es_evi *es_evi)
35823627
/* free the VTEP list */
35833628
list_delete(&es_evi->es_evi_vtep_list);
35843629

3630+
/* Set flags max value */
3631+
es_evi->flags = 0xFFFF;
3632+
35853633
/* remove from the VNI-ESI rb tree */
35863634
XFREE(MTYPE_BGP_EVPN_ES_EVI, es_evi);
35873635

@@ -3596,6 +3644,10 @@ static void bgp_evpn_es_evi_local_info_set(struct bgp_evpn_es_evi *es_evi)
35963644
if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
35973645
return;
35983646

3647+
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
3648+
zlog_debug("Setting local info for ES-EVI ES %s VNI %u", es_evi->es->esi_str,
3649+
vpn->vni);
3650+
35993651
SET_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL);
36003652
listnode_init(&es_evi->l2vni_listnode, es_evi);
36013653
listnode_add(vpn->local_es_evi_list, &es_evi->l2vni_listnode);
@@ -3758,8 +3810,14 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
37583810
if (CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_LOCAL))
37593811
/* dup */
37603812
return 0;
3761-
} else
3813+
} else {
37623814
es_evi = bgp_evpn_es_evi_new(es, vpn);
3815+
if (!es_evi) {
3816+
flog_err(EC_BGP_ES_CREATE, "%u: Failed to create ES-EVI for ES %s VNI %u",
3817+
bgp->vrf_id, es->esi_str, vni);
3818+
return -1;
3819+
}
3820+
}
37633821

37643822
bgp_evpn_es_evi_local_info_set(es_evi);
37653823

0 commit comments

Comments
 (0)