In some cases BGP can be monitoring the same prefix
in both the nexthop and import check tables. If this
is the case, when unregistering one bnc from one table
make sure we are not still registered in the other
Example of the problem:
r1(config-router)# address-family ipv4 uni
r1(config-router-af)# no network 192.168.100.41/32
r1(config-router-af)# exit
r1# show bgp import-check-table
Current BGP import check cache:
r1# show bgp nexthop
Current BGP nexthop cache:
192.168.100.41 valid [IGP metric 0], #paths 1, peer 192.168.100.41
if r1-eth0
Last update: Wed Dec 6 11:01:40 2023
BGP now believes it is only watching 192.168.100.41 in the nexthop
cache, but zebra doesn't have anything:
r1# show ip import-check
VRF default:
Resolve via default: on
r1# show ip nht
VRF default:
Resolve via default: on
So if anything happens to the route that is being matched for
192.168.100.41 bgp is no longer going to be notified about this.
The source of this problem is that zebra has dropped the two different
tables into 1 table, while bgp has 2 tables to track this. The solution
to this problem (other than the rewrite that is being done ) is to have
BGP have a bit of smarts about looking in both tables for the bnc and
if found in both don't send the delete of the prefix tracking to zebra.
Signed-off-by: Donald Sharp <sharpd@nvidia.com>
(cherry picked from commit
40dd3946a664695396b471a4dc4e03272a0e7739)
/* BGP nexthop cache value structure. */
struct bgp_nexthop_cache {
+ afi_t afi;
+
/* The ifindex of the outgoing interface *if* it's a v6 LL */
ifindex_t ifindex_ipv6_ll;
bnc = bnc_find(tree, &p, srte_color, ifindex);
if (!bnc) {
bnc = bnc_new(tree, &p, srte_color, ifindex);
+ bnc->afi = afi;
bnc->bgp = bgp_nexthop;
if (BGP_DEBUG(nht, NHT))
zlog_debug("Allocated bnc %pFX(%d)(%u)(%s) peer %p",
*/
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc)
{
+ struct bgp_nexthop_cache *import;
+ struct bgp_nexthop_cache *nexthop;
+
+ struct bgp *bgp = bnc->bgp;
+
/* Check if we have already registered */
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
return;
return;
}
+ import = bnc_find(&bgp->import_check_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+ nexthop = bnc_find(&bgp->nexthop_cache_table[bnc->afi], &bnc->prefix, 0,
+ 0);
+
+ /*
+ * If this entry has both a import and a nexthop entry
+ * then let's not send the unregister quite as of yet
+ * wait until we only have 1 left
+ */
+ if (import && nexthop)
+ return;
+
sendmsg_zebra_rnh(bnc, ZEBRA_NEXTHOP_UNREGISTER);
}