/* Gateway IP nexthop should be resolved */
if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) {
- if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi,
- NULL, 0, NULL))
+ if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi, NULL, 0, NULL, NULL))
bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID);
else {
if (BGP_DEBUG(nht, NHT)) {
connected = 1;
return bgp_find_or_add_nexthop(peer->bgp, peer->bgp,
- family2afi(
- peer->connection->su.sa.sa_family),
- SAFI_UNICAST, NULL, peer, connected,
- NULL);
+ family2afi(peer->connection->su.sa.sa_family), SAFI_UNICAST,
+ NULL, peer, connected, NULL, NULL);
}
static void peer_xfer_stats(struct peer *peer_dst, struct peer *peer_src)
/* the route is defined with the "network <prefix>" command */
if (CHECK_FLAG(bgp_nexthop->flags, BGP_FLAG_IMPORT_CHECK))
- nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop,
- afi, SAFI_UNICAST,
- bpi_ultimate, NULL,
- 0, p);
+ nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi, SAFI_UNICAST,
+ bpi_ultimate, NULL, 0, p, bpi_ultimate);
else
/* if "no bgp network import-check" is set,
* then mark the nexthop as valid.
* TBD do we need to do anything about the
* 'connected' parameter?
*/
- nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi,
- safi, bpi, NULL, 0, p);
+ /* VPN paths: the new bpi may be altered like
+ * with 'nexthop vpn export' command. Use the bpi_ultimate
+ * to find the original nexthop
+ */
+ nh_valid = bgp_find_or_add_nexthop(to_bgp, bgp_nexthop, afi, safi, bpi, NULL, 0, p,
+ bpi_ultimate);
/*
* If you are using SRv6 VPN instead of MPLS, it need to check
bgp_nexthop = from_bgp;
nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
- nh_valid = bgp_find_or_add_nexthop(from_bgp, bgp_nexthop, nh_afi,
- SAFI_UNICAST, pi, NULL, 0, NULL);
+ nh_valid = bgp_find_or_add_nexthop(from_bgp, bgp_nexthop, nh_afi, SAFI_UNICAST, pi, NULL, 0,
+ NULL, NULL);
if (!nh_valid && is_bgp_static_route &&
!CHECK_FLAG(from_bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
static void register_zebra_rnh(struct bgp_nexthop_cache *bnc);
static void unregister_zebra_rnh(struct bgp_nexthop_cache *bnc);
static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p,
- struct bgp *bgp_nexthop);
+ struct bgp *bgp_nexthop, struct bgp_path_info *pi_source);
static void bgp_nht_ifp_initial(struct event *thread);
DEFINE_HOOK(bgp_nht_path_update, (struct bgp *bgp, struct bgp_path_info *pi, bool valid),
* A route and its nexthop might belong to different VRFs. Therefore,
* we need both the bgp_route and bgp_nexthop pointers.
*/
-int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
- afi_t afi, safi_t safi, struct bgp_path_info *pi,
- struct peer *peer, int connected,
- const struct prefix *orig_prefix)
+int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, afi_t afi, safi_t safi,
+ struct bgp_path_info *pi, struct peer *peer, int connected,
+ const struct prefix *orig_prefix, struct bgp_path_info *source_pi)
{
struct bgp_nexthop_cache_head *tree = NULL;
struct bgp_nexthop_cache *bnc;
/* This will return true if the global IPv6 NH is a link local
* addr */
- if (!make_prefix(afi, pi, &p, bgp_nexthop))
+ if (!make_prefix(afi, pi, &p, bgp_nexthop, source_pi))
return 1;
/*
* make_prefix - make a prefix structure from the path (essentially
* path's node.
*/
-static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p, struct bgp *bgp_nexthop)
+static bool make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p,
+ struct bgp *bgp_nexthop, struct bgp_path_info *source_pi)
{
int is_bgp_static = ((pi->type == ZEBRA_ROUTE_BGP)
struct bgp_dest *net = pi->net;
const struct prefix *p_orig = bgp_dest_get_prefix(net);
struct in_addr ipv4;
- struct peer *peer = pi->peer;
- struct attr *attr = pi->attr;
+ struct peer *peer;
+ struct attr *attr;
bool local_sid = false;
struct bgp *bgp = bgp_get_default();
struct prefix_ipv6 tmp_prefix;
+ if (source_pi) {
+ attr = source_pi->attr;
+ peer = source_pi->peer;
+ } else {
+ peer = pi->peer;
+ attr = pi->attr;
+ }
+
if (p_orig->family == AF_FLOWSPEC) {
if (!peer)
return false;
break;
case AFI_IP6:
p->family = AF_INET6;
- if (bgp && bgp->srv6_locator && bgp->srv6_enabled && attr->srv6_l3vpn) {
+ if (bgp && bgp->srv6_locator && bgp->srv6_enabled && pi->attr->srv6_l3vpn) {
tmp_prefix.family = AF_INET6;
tmp_prefix.prefixlen = IPV6_MAX_BITLEN;
- tmp_prefix.prefix = attr->srv6_l3vpn->sid;
+ tmp_prefix.prefix = pi->attr->srv6_l3vpn->sid;
if (bgp_nexthop->vpn_policy[afi].tovpn_sid_locator &&
bgp_nexthop->vpn_policy[afi].tovpn_sid)
local_sid = prefix_match(&bgp_nexthop->vpn_policy[afi]
local_sid = prefix_match(&bgp_nexthop->tovpn_sid_locator->prefix,
&tmp_prefix);
}
- if (local_sid == false && attr->srv6_l3vpn) {
+ if (local_sid == false && pi->attr->srv6_l3vpn) {
p->prefixlen = IPV6_MAX_BITLEN;
- if (attr->srv6_l3vpn->transposition_len != 0 &&
+ if (pi->attr->srv6_l3vpn->transposition_len != 0 &&
BGP_PATH_INFO_NUM_LABELS(pi)) {
- IPV6_ADDR_COPY(&p->u.prefix6, &attr->srv6_l3vpn->sid);
+ IPV6_ADDR_COPY(&p->u.prefix6, &pi->attr->srv6_l3vpn->sid);
transpose_sid(&p->u.prefix6,
decode_label(&pi->extra->labels->label[0]),
- attr->srv6_l3vpn->transposition_offset,
- attr->srv6_l3vpn->transposition_len);
+ pi->attr->srv6_l3vpn->transposition_offset,
+ pi->attr->srv6_l3vpn->transposition_len);
} else
- IPV6_ADDR_COPY(&(p->u.prefix6), &(attr->srv6_l3vpn->sid));
+ IPV6_ADDR_COPY(&(p->u.prefix6), &(pi->attr->srv6_l3vpn->sid));
} else if (is_bgp_static) {
p->u.prefix6 = p_orig->u.prefix6;
p->prefixlen = p_orig->prefixlen;
* peer - The BGP peer associated with this NHT
* connected - True if NH MUST be a connected route
*/
-extern int bgp_find_or_add_nexthop(struct bgp *bgp_route,
- struct bgp *bgp_nexthop, afi_t a,
- safi_t safi, struct bgp_path_info *p,
- struct peer *peer, int connected,
- const struct prefix *orig_prefix);
+extern int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop, afi_t a,
+ safi_t safi, struct bgp_path_info *p, struct peer *peer,
+ int connected, const struct prefix *orig_prefix,
+ struct bgp_path_info *source_pi);
/**
* bgp_unlink_nexthop() - Unlink the nexthop object from the path structure.
{
bool connected;
afi_t nh_afi;
+ struct bgp_path_info *bpi_ultimate = NULL;
if (((afi == AFI_IP || afi == AFI_IP6) &&
(safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST ||
struct bgp *bgp_nexthop = bgp;
- if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig)
+ if (pi->extra && pi->extra->vrfleak && pi->extra->vrfleak->bgp_orig) {
bgp_nexthop = pi->extra->vrfleak->bgp_orig;
+ if (pi->sub_type == BGP_ROUTE_IMPORTED)
+ bpi_ultimate = bgp_get_imported_bpi_ultimate(pi);
+ }
nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr);
if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi, safi, pi, NULL, connected,
- bgp_nht_param_prefix) ||
+ bgp_nht_param_prefix, bpi_ultimate) ||
CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) {
if (accept_own)
bgp_path_info_set_flag(dest, pi, BGP_PATH_ACCEPT_OWN);
/* Nexthop reachability check. */
if (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST) {
if (CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK)) {
- if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi,
- bpi, NULL, 0, p))
+ if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, safi, bpi, NULL, 0, p,
+ NULL))
bgp_path_info_set_flag(dest, bpi,
BGP_PATH_VALID);
else {