bnct->nht_info = to;
}
+/*
+ * Returns the bnc whose bnc->nht_info matches the LL peer by
+ * looping through the IPv6 nexthop table
+ */
+static struct bgp_nexthop_cache *
+bgp_find_ipv6_nexthop_matching_peer(struct peer *peer)
+{
+ struct bgp_nexthop_cache *bnc;
+
+ frr_each (bgp_nexthop_cache, &peer->bgp->nexthop_cache_table[AFI_IP6],
+ bnc) {
+ if (bnc->nht_info == peer) {
+ if (BGP_DEBUG(nht, NHT)) {
+ zlog_debug(
+ "Found bnc: %pFX(%u)(%u)(%p) for peer: %s(%s) %p",
+ &bnc->prefix, bnc->ifindex,
+ bnc->srte_color, bnc, peer->host,
+ peer->bgp->name_pretty, peer);
+ }
+ return bnc;
+ }
+ }
+
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug(
+ "Could not find bnc for peer %s(%s) %p in v6 nexthop table",
+ peer->host, peer->bgp->name_pretty, peer);
+
+ return NULL;
+}
+
void bgp_unlink_nexthop_by_peer(struct peer *peer)
{
struct prefix p;
afi_t afi = family2afi(peer->su.sa.sa_family);
ifindex_t ifindex = 0;
- if (!sockunion2hostprefix(&peer->su, &p))
- return;
- /*
- * Gather the ifindex for if up/down events to be
- * tagged into this fun
- */
- if (afi == AFI_IP6 && IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
- ifindex = peer->su.sin6.sin6_scope_id;
- bnc = bnc_find(&peer->bgp->nexthop_cache_table[afi], &p, 0, ifindex);
+ if (!sockunion2hostprefix(&peer->su, &p)) {
+ /*
+ * In scenarios where unnumbered BGP session is brought
+ * down by shutting down the interface before unconfiguring
+ * the BGP neighbor, neighbor information in peer->su.sa
+ * will be cleared when the interface is shutdown. So
+ * during the deletion of unnumbered bgp peer, above check
+ * will return true. Therefore, in this case,BGP needs to
+ * find the bnc whose bnc->nht_info matches the
+ * peer being deleted and free it.
+ */
+ bnc = bgp_find_ipv6_nexthop_matching_peer(peer);
+ } else {
+ /*
+ * Gather the ifindex for if up/down events to be
+ * tagged into this fun
+ */
+ if (afi == AFI_IP6 &&
+ IN6_IS_ADDR_LINKLOCAL(&peer->su.sin6.sin6_addr))
+ ifindex = peer->su.sin6.sin6_scope_id;
+ bnc = bnc_find(&peer->bgp->nexthop_cache_table[afi], &p, 0,
+ ifindex);
+ }
+
if (!bnc)
return;
if (!peer)
return;
+ /*
+ * In case the below check evaluates true and if
+ * the bnc has not been freed at this point, then
+ * we might have to do something similar to what's
+ * done in bgp_unlink_nexthop_by_peer(). Since
+ * bgp_unlink_nexthop_by_peer() loops through the
+ * nodes of V6 nexthop cache to find the bnc, it is
+ * currently not being called here.
+ */
if (!sockunion2hostprefix(&peer->su, &p))
return;
/*