bgpd: do not unregister for prefix nexthop updates if nh exists

since the addition of srte_color to the comparison for bgp nexthops
it is possible to have several nexthops per prefix but since zebra
only sores a per prefix registration we should not unregister for
nh notifications for a prefix unti all the nexthops for that prefix
have been deleted. Otherwise we can get into a deadlock situation
where BGP thinks we have registered but we have unregistered from zebra.

Signed-off-by: Pat Ruddy <pat@voltanet.io>
This commit is contained in:
Pat Ruddy 2020-06-26 17:37:30 +01:00 committed by GalaxyGorilla
parent 545aeef1d1
commit e37e1e27e4
3 changed files with 18 additions and 2 deletions

View File

@ -84,6 +84,19 @@ struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
return bnc;
}
bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc)
{
struct bgp_nexthop_cache *bnc_tmp;
frr_each (bgp_nexthop_cache, bnc->tree, bnc_tmp) {
if (bnc_tmp == bnc)
continue;
if (prefix_cmp(&bnc->prefix, &bnc_tmp->prefix) == 0)
return true;
}
return false;
}
void bnc_free(struct bgp_nexthop_cache *bnc)
{
bnc_nexthop_free(bnc);

View File

@ -118,6 +118,7 @@ extern bool bgp_nexthop_self(struct bgp *bgp, afi_t afi, uint8_t type,
extern struct bgp_nexthop_cache *bnc_new(struct bgp_nexthop_cache_head *tree,
struct prefix *prefix,
uint32_t srte_color);
extern bool bnc_existing_for_prefix(struct bgp_nexthop_cache *bnc);
extern void bnc_free(struct bgp_nexthop_cache *bnc);
extern struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
struct prefix *prefix,

View File

@ -76,8 +76,10 @@ static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
bnc_str(bnc, buf, PREFIX2STR_BUFFER),
bnc->srte_color, bnc->bgp->name_pretty);
}
unregister_zebra_rnh(bnc,
CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
/* only unregister if this is the last nh for this prefix*/
if (!bnc_existing_for_prefix(bnc))
unregister_zebra_rnh(
bnc, CHECK_FLAG(bnc->flags, BGP_STATIC_ROUTE));
bnc_free(bnc);
}
}