summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_nht.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--bgpd/bgp_nht.c139
1 files changed, 76 insertions, 63 deletions
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index e2c103b..8ce4555 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -116,24 +116,36 @@ static int bgp_isvalid_nexthop_for_mplsovergre(struct bgp_nexthop_cache *bnc,
static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,
struct bgp_path_info *path)
{
+ return (bnc && (bnc->nexthop_num > 0 &&
+ (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) ||
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
+ bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
+ bgp_isvalid_nexthop_for_mplsovergre(bnc, path))));
+}
+
+static bool bgp_isvalid_nexthop_for_l3vpn(struct bgp_nexthop_cache *bnc,
+ struct bgp_path_info *path)
+{
+ if (bgp_zebra_num_connects() == 0)
+ return 1;
+
+ if (path->attr->srv6_l3vpn || path->attr->srv6_vpn) {
+ /* In the case of SRv6-VPN, we need to track the reachability to the
+ * SID (in other words, IPv6 address). We check that the SID is
+ * available in the BGP update; then if it is available, we check
+ * for the nexthop reachability.
+ */
+ if (bnc && (bnc->nexthop_num > 0 && bgp_isvalid_nexthop(bnc)))
+ return 1;
+ return 0;
+ }
/*
- * - In the case of MPLS-VPN, the label is learned from LDP or other
+ * In the case of MPLS-VPN, the label is learned from LDP or other
* protocols, and nexthop tracking is enabled for the label.
* The value is recorded as BGP_NEXTHOP_LABELED_VALID.
- * - In the case of SRv6-VPN, we need to track the reachability to the
- * SID (in other words, IPv6 address). As in MPLS, we need to record
- * the value as BGP_NEXTHOP_SID_VALID. However, this function is
- * currently not implemented, and this function assumes that all
- * Transit routes for SRv6-VPN are valid.
* - Otherwise check for mpls-gre acceptance
*/
- return (bgp_zebra_num_connects() == 0 ||
- (bnc && (bnc->nexthop_num > 0 &&
- (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)))));
+ return bgp_isvalid_nexthop_for_mpls(bnc, path);
}
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
@@ -308,11 +320,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
afi = BGP_ATTR_MP_NEXTHOP_LEN_IP6(pi->attr) ? AFI_IP6
: AFI_IP;
- /* Validation for the ipv4 mapped ipv6 nexthop. */
- if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
- afi = AFI_IP;
- }
-
/* This will return true if the global IPv6 NH is a link local
* addr */
if (make_prefix(afi, pi, &p) < 0)
@@ -345,9 +352,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
return 0;
}
- if (CHECK_FLAG(pi->attr->flag,
- ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- srte_color = bgp_attr_get_color(pi->attr);
+ srte_color = bgp_attr_get_color(pi->attr);
} else if (peer) {
/*
@@ -494,9 +499,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
return 1;
else if (safi == SAFI_UNICAST && pi &&
- pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra &&
- pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop)
- return bgp_isvalid_nexthop_for_mpls(bnc, pi);
+ pi->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(pi) && !bnc->is_evpn_gwip_nexthop)
+ return bgp_isvalid_nexthop_for_l3vpn(bnc, pi);
else if (safi == SAFI_MPLS_VPN && pi &&
pi->sub_type != BGP_ROUTE_IMPORTED)
/* avoid not redistributing mpls vpn routes */
@@ -614,6 +619,8 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
} else if (nhr->nexthop_num) {
struct peer *peer = bnc->nht_info;
+ prefix_copy(&bnc->resolved_prefix, &nhr->prefix);
+
/* notify bgp fsm if nbr ip goes from invalid->valid */
if (!bnc->nexthop_num)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
@@ -719,6 +726,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
}
}
} else {
+ memset(&bnc->resolved_prefix, 0, sizeof(bnc->resolved_prefix));
bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
bnc->flags &= ~BGP_NEXTHOP_VALID;
bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
@@ -964,14 +972,13 @@ void bgp_nexthop_update(struct vrf *vrf, struct prefix *match,
* which should provide a better infrastructure to solve this issue in
* a more efficient and elegant way.
*/
- if (nhr->srte_color == 0 && bnc_nhc) {
+ if (nhr->srte_color == 0) {
struct bgp_nexthop_cache *bnc_iter;
frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
bnc_iter) {
- if (!prefix_same(&bnc_nhc->prefix, &bnc_iter->prefix) ||
- bnc_iter->srte_color == 0 ||
- CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID))
+ if (!prefix_same(match, &bnc_iter->prefix) ||
+ bnc_iter->srte_color == 0)
continue;
bgp_process_nexthop_update(bnc_iter, nhr, false);
@@ -1028,52 +1035,57 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
p->u.prefix4 = p_orig->u.prefix4;
p->prefixlen = p_orig->prefixlen;
} else {
- if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
- ipv4_mapped_ipv6_to_ipv4(
- &pi->attr->mp_nexthop_global, &ipv4);
- p->u.prefix4 = ipv4;
- p->prefixlen = IPV4_MAX_BITLEN;
- } else {
- if (p_orig->family == AF_EVPN)
- p->u.prefix4 =
- pi->attr->mp_nexthop_global_in;
- else
- p->u.prefix4 = pi->attr->nexthop;
- p->prefixlen = IPV4_MAX_BITLEN;
- }
+ if (p_orig->family == AF_EVPN)
+ p->u.prefix4 = pi->attr->mp_nexthop_global_in;
+ else
+ p->u.prefix4 = pi->attr->nexthop;
+ p->prefixlen = IPV4_MAX_BITLEN;
}
break;
case AFI_IP6:
p->family = AF_INET6;
-
- if (is_bgp_static) {
+ if (pi->attr->srv6_l3vpn) {
+ IPV6_ADDR_COPY(&(p->u.prefix6),
+ &(pi->attr->srv6_l3vpn->sid));
+ p->prefixlen = IPV6_MAX_BITLEN;
+ } else if (is_bgp_static) {
p->u.prefix6 = p_orig->u.prefix6;
p->prefixlen = p_orig->prefixlen;
} else {
/* If we receive MP_REACH nexthop with ::(LL)
* or LL(LL), use LL address as nexthop cache.
*/
- if (pi->attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
- && (IN6_IS_ADDR_UNSPECIFIED(
- &pi->attr->mp_nexthop_global)
- || IN6_IS_ADDR_LINKLOCAL(
- &pi->attr->mp_nexthop_global)))
+ p->prefixlen = IPV6_MAX_BITLEN;
+ if (pi->attr &&
+ pi->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
+ (IN6_IS_ADDR_UNSPECIFIED(
+ &pi->attr->mp_nexthop_global) ||
+ IN6_IS_ADDR_LINKLOCAL(&pi->attr->mp_nexthop_global)))
p->u.prefix6 = pi->attr->mp_nexthop_local;
/* If we receive MR_REACH with (GA)::(LL)
* then check for route-map to choose GA or LL
*/
- else if (pi->attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
- if (pi->attr->mp_nexthop_prefer_global)
- p->u.prefix6 =
- pi->attr->mp_nexthop_global;
- else
+ else if (pi->attr &&
+ pi->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (CHECK_FLAG(pi->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
+ if (IS_MAPPED_IPV6(
+ &pi->attr->mp_nexthop_global)) {
+ ipv4_mapped_ipv6_to_ipv4(
+ &pi->attr->mp_nexthop_global,
+ &ipv4);
+ p->u.prefix4 = ipv4;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ } else
+ p->u.prefix6 =
+ pi->attr->mp_nexthop_global;
+ } else
p->u.prefix6 =
pi->attr->mp_nexthop_local;
} else
p->u.prefix6 = pi->attr->mp_nexthop_global;
- p->prefixlen = IPV6_MAX_BITLEN;
}
break;
default:
@@ -1289,13 +1301,14 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
bool bnc_is_valid_nexthop = false;
bool path_valid = false;
- if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED
- && path->extra && path->extra->num_labels
- && (path->attr->evpn_overlay.type
- != OVERLAY_INDEX_GATEWAY_IP)) {
+ if (safi == SAFI_UNICAST &&
+ path->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(path) &&
+ (path->attr->evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
- bgp_isvalid_nexthop_for_mpls(bnc, path) ? true
- : false;
+ bgp_isvalid_nexthop_for_l3vpn(bnc, path)
+ ? true
+ : false;
} else if (safi == SAFI_MPLS_VPN &&
path->sub_type != BGP_ROUTE_IMPORTED) {
/* avoid not redistributing mpls vpn routes */
@@ -1414,7 +1427,7 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
}
}
- bgp_process(bgp_path, dest, afi, safi);
+ bgp_process(bgp_path, dest, path, afi, safi);
}
if (peer) {