From e37e1e27e4f26d370946bedb9ae0767344fe339d Mon Sep 17 00:00:00 2001 From: Pat Ruddy Date: Fri, 26 Jun 2020 17:37:30 +0100 Subject: [PATCH] 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 --- bgpd/bgp_nexthop.c | 13 +++++++++++++ bgpd/bgp_nexthop.h | 1 + bgpd/bgp_nht.c | 6 ++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c index 6f36fd1394..ed026a2fff 100644 --- a/bgpd/bgp_nexthop.c +++ b/bgpd/bgp_nexthop.c @@ -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); diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h index 356af54002..c4b913faf4 100644 --- a/bgpd/bgp_nexthop.h +++ b/bgpd/bgp_nexthop.h @@ -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, diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 80ee5f5349..9573d118e5 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -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); } }