+// SPDX-License-Identifier: GPL-2.0-or-later
/* BGP Nexthop tracking
* Copyright (C) 2013 Cumulus Networks, Inc.
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
*/
return (bgp_zebra_num_connects() == 0 ||
(bnc && (bnc->nexthop_num > 0 &&
- (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
+ (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) ||
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
bnc->bgp->srv6_enabled ||
bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
bgp_isvalid_nexthop_for_mplsovergre(bnc, path)))));
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;
{
struct bgp_nexthop_cache_head *tree = NULL;
struct bgp_nexthop_cache *bnc;
+ struct bgp_path_info *bpi_ultimate;
struct prefix p;
uint32_t srte_color = 0;
int is_bgp_static_route = 0;
/* updates NHT pi list reference */
path_nh_map(pi, bnc, true);
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(pi);
if (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID) && bnc->metric)
- (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
- else if (pi->extra)
- pi->extra->igpmetric = 0;
+ (bgp_path_info_extra_get(bpi_ultimate))->igpmetric =
+ bnc->metric;
+ else if (bpi_ultimate->extra)
+ bpi_ultimate->extra->igpmetric = 0;
} else if (peer) {
/*
* Let's not accidentally save the peer data for a peer
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;
/*
{
struct bgp_dest *dest;
struct bgp_path_info *path;
+ struct bgp_path_info *bpi_ultimate;
int afi;
struct peer *peer = (struct peer *)bnc->nht_info;
struct bgp_table *table;
}
if (BGP_DEBUG(nht, NHT)) {
- if (dest->pdest)
- zlog_debug(
- "... eval path %d/%d %pBD RD %pRD %s flags 0x%x",
- afi, safi, dest,
+
+ if (dest->pdest) {
+ char rd_buf[RD_ADDRSTRLEN];
+
+ prefix_rd2str(
(struct prefix_rd *)bgp_dest_get_prefix(
dest->pdest),
+ rd_buf, sizeof(rd_buf),
+ bgp_get_asnotation(bnc->bgp));
+ zlog_debug(
+ "... eval path %d/%d %pBD RD %s %s flags 0x%x",
+ afi, safi, dest, rd_buf,
bgp_path->name_pretty, path->flags);
- else
+ } else
zlog_debug(
"... eval path %d/%d %pBD %s flags 0x%x",
afi, safi, dest, bgp_path->name_pretty,
/* Copy the metric to the path. Will be used for bestpath
* computation */
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(path);
if (bgp_isvalid_nexthop(bnc) && bnc->metric)
- (bgp_path_info_extra_get(path))->igpmetric =
+ (bgp_path_info_extra_get(bpi_ultimate))->igpmetric =
bnc->metric;
- else if (path->extra)
- path->extra->igpmetric = 0;
+ else if (bpi_ultimate->extra)
+ bpi_ultimate->extra->igpmetric = 0;
if (CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_METRIC_CHANGED)
|| CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)
static void bgp_l3nhg_add_cb(const char *name)
{
}
+
+static void bgp_l3nhg_modify_cb(const struct nexthop_group_cmd *nhgc)
+{
+}
+
static void bgp_l3nhg_add_nexthop_cb(const struct nexthop_group_cmd *nhgc,
const struct nexthop *nhop)
{
}
+
static void bgp_l3nhg_del_nexthop_cb(const struct nexthop_group_cmd *nhgc,
const struct nexthop *nhop)
{
}
+
static void bgp_l3nhg_del_cb(const char *name)
{
}
bgp_l3nhg_zebra_inited = true;
bgp_l3nhg_start = zclient_get_nhg_start(ZEBRA_ROUTE_BGP);
- nexthop_group_init(bgp_l3nhg_add_cb, bgp_l3nhg_add_nexthop_cb,
- bgp_l3nhg_del_nexthop_cb, bgp_l3nhg_del_cb);
+ nexthop_group_init(bgp_l3nhg_add_cb, bgp_l3nhg_modify_cb,
+ bgp_l3nhg_add_nexthop_cb, bgp_l3nhg_del_nexthop_cb,
+ bgp_l3nhg_del_cb);
}