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>
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);
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,
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);
}
}