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 <vivek@cumulusnetworks.com>
Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
(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.
This commit is contained in:
vivek 2018-05-08 22:16:04 -07:00 committed by Donald Sharp
parent 3dc755e492
commit 528cd74fd3
3 changed files with 8 additions and 3 deletions

View File

@ -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));

View File

@ -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;

View File

@ -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--;