bgpd: fix crash in the MH cleanup handling

The MH datastructures were being released before the paths that were
referencing them. Fix is to do the MH cleanup last.

The MH finish function has also been stripped down to only do a
datastructure cleanup i.e. avoid sending route updates etc.

Ticket: 31376

Signed-off-by: Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
This commit is contained in:
Anuradha Karuppiah 2020-10-20 09:26:51 -07:00
parent dad65cbe73
commit 45a859f1c3
3 changed files with 16 additions and 13 deletions

View File

@ -1316,11 +1316,14 @@ static struct bgp_evpn_es *bgp_evpn_es_new(struct bgp *bgp, const esi_t *esi)
* This just frees appropriate memory, caller should have taken other * This just frees appropriate memory, caller should have taken other
* needed actions. * needed actions.
*/ */
static void bgp_evpn_es_free(struct bgp_evpn_es *es) static void bgp_evpn_es_free(struct bgp_evpn_es *es, const char *caller)
{ {
if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE))
return; return;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("%s: es %s free", caller, es->esi_str);
/* cleanup resources maintained against the ES */ /* cleanup resources maintained against the ES */
list_delete(&es->es_evi_list); list_delete(&es->es_evi_list);
list_delete(&es->es_vtep_list); list_delete(&es->es_vtep_list);
@ -1367,7 +1370,7 @@ static void bgp_evpn_es_local_info_clear(struct bgp_evpn_es *es)
bf_release_index(bm->rd_idspace, es->rd_id); bf_release_index(bm->rd_idspace, es->rd_id);
bgp_evpn_es_free(es); bgp_evpn_es_free(es, __func__);
} }
/* eval remote info associated with the ES */ /* eval remote info associated with the ES */
@ -1378,7 +1381,7 @@ static void bgp_evpn_es_remote_info_re_eval(struct bgp_evpn_es *es)
} else { } else {
if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE)) { if (CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE)) {
UNSET_FLAG(es->flags, BGP_EVPNES_REMOTE); UNSET_FLAG(es->flags, BGP_EVPNES_REMOTE);
bgp_evpn_es_free(es); bgp_evpn_es_free(es, __func__);
} }
} }
} }
@ -2320,7 +2323,7 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
if (!es_evi) { if (!es_evi) {
es_evi = bgp_evpn_es_evi_new(es, vpn); es_evi = bgp_evpn_es_evi_new(es, vpn);
if (!es_evi) { if (!es_evi) {
bgp_evpn_es_free(es); bgp_evpn_es_free(es, __func__);
return -1; return -1;
} }
} }
@ -2903,15 +2906,13 @@ void bgp_evpn_mh_finish(void)
{ {
struct bgp_evpn_es *es; struct bgp_evpn_es *es;
struct bgp_evpn_es *es_next; struct bgp_evpn_es *es_next;
struct bgp *bgp;
bgp = bgp_get_evpn(); if (BGP_DEBUG(evpn_mh, EVPN_MH_RT))
if (bgp) { zlog_debug("evpn mh finish");
RB_FOREACH_SAFE(es, bgp_es_rb_head,
&bgp_mh_info->es_rb_tree, es_next) { RB_FOREACH_SAFE (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree,
/* XXX - need to force free remote ESs here */ es_next) {
bgp_evpn_local_es_do_del(bgp, es); bgp_evpn_es_local_info_clear(es);
}
} }
thread_cancel(bgp_mh_info->t_cons_check); thread_cancel(bgp_mh_info->t_cons_check);
list_delete(&bgp_mh_info->local_es_list); list_delete(&bgp_mh_info->local_es_list);

View File

@ -62,6 +62,7 @@
#include "bgpd/bgp_errors.h" #include "bgpd/bgp_errors.h"
#include "lib/routing_nb.h" #include "lib/routing_nb.h"
#include "bgpd/bgp_nb.h" #include "bgpd/bgp_nb.h"
#include "bgpd/bgp_evpn_mh.h"
#ifdef ENABLE_BGP_VNC #ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h" #include "bgpd/rfapi/rfapi_backend.h"
@ -207,6 +208,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
if (bgp_default) if (bgp_default)
bgp_delete(bgp_default); bgp_delete(bgp_default);
bgp_evpn_mh_finish();
/* reverse bgp_dump_init */ /* reverse bgp_dump_init */
bgp_dump_finish(); bgp_dump_finish();

View File

@ -7298,7 +7298,6 @@ void bgp_terminate(void)
BGP_TIMER_OFF(bm->t_rmap_update); BGP_TIMER_OFF(bm->t_rmap_update);
bgp_mac_finish(); bgp_mac_finish();
bgp_evpn_mh_finish();
} }
struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp, struct peer *peer_lookup_in_view(struct vty *vty, struct bgp *bgp,