From 528cd74fd326517b2c9d941c9e9803c6c8d17515 Mon Sep 17 00:00:00 2001 From: vivek Date: Tue, 8 May 2018 22:16:04 -0700 Subject: [PATCH] bgpd: Update parent entry's refcount for imported routes Imported routes in a VRF routing table have a reference to their parent route entry which resides in the EVPN or IPVPN routing table. Ensure that this reference uses appropriate locking so that the parent entry doesn't get freed prematurely. Signed-off-by: Vivek Venkatraman Reviewed-by: Donald Sharp (cherry picked from commit 13cb6b22ba9d558b1b4a1e8752f63f13242462a7) Conflicts: bgpd/bgp_mplsvpn.c Ticket: CM-20471 Testing Done: a) Ran vrf_route_leak tests without fix and hit crash, ran twice with fix and did not see the crash. b) Ran evpn-smoke and ensured there were no new failures. --- bgpd/bgp_evpn.c | 4 ++-- bgpd/bgp_mplsvpn.c | 2 +- bgpd/bgp_route.c | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ad45da84eb..02dd64f1a3 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1841,7 +1841,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, parent_ri->peer, attr_new, rn); SET_FLAG(ri->flags, BGP_INFO_VALID); bgp_info_extra_get(ri); - ri->extra->parent = parent_ri; + ri->extra->parent = bgp_info_lock(parent_ri); if (parent_ri->extra) { memcpy(&ri->extra->label, &parent_ri->extra->label, sizeof(ri->extra->label)); @@ -1913,7 +1913,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn, parent_ri->peer, attr_new, rn); SET_FLAG(ri->flags, BGP_INFO_VALID); bgp_info_extra_get(ri); - ri->extra->parent = parent_ri; + ri->extra->parent = bgp_info_lock(parent_ri); if (parent_ri->extra) { memcpy(&ri->extra->label, &parent_ri->extra->label, sizeof(ri->extra->label)); diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index 64d12cf607..55365df299 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -569,7 +569,7 @@ leak_update( setlabels(new, label, num_labels); bgp_info_extra_get(new); - new->extra->parent = parent; + new->extra->parent = bgp_info_lock(parent); if (bgp_orig) new->extra->bgp_orig = bgp_orig; diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index cfaa04a8c9..424fc4bc03 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -225,6 +225,11 @@ struct bgp_info *bgp_info_lock(struct bgp_info *binfo) struct bgp_info *bgp_info_unlock(struct bgp_info *binfo) { + /* unlink reference to parent, if any. */ + if (binfo->extra && binfo->extra->parent) { + bgp_info_unlock((struct bgp_info *)binfo->extra->parent); + binfo->extra->parent = NULL; + } assert(binfo && binfo->lock > 0); binfo->lock--; -- 2.39.5