diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 42002bd378..375a2272e1 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -69,6 +69,10 @@ #define BGP_PREFIX_SID_IPV6_LENGTH 19 #define BGP_PREFIX_SID_ORIGINATOR_SRGB_LENGTH 6 +#define BGP_ATTR_NH_AFI(afi, attr) \ + ((afi != AFI_L2VPN) ? afi : \ + ((attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV4) ? AFI_IP : AFI_IP6)) + /* PMSI tunnel types (RFC 6514) */ struct bgp_attr_encap_subtlv { diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 625b13a941..35d54983dc 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -6030,3 +6030,26 @@ int bgp_evpn_get_type5_prefixlen(struct prefix *pfx) return evp->prefix.prefix_addr.ip_prefix_length; } + +/* + * Should we register nexthop for this EVPN prefix for nexthop tracking? + */ +bool bgp_evpn_is_prefix_nht_supported(struct prefix *pfx) +{ + struct prefix_evpn *evp = (struct prefix_evpn *)pfx; + + /* + * EVPN RT-5 should not be marked as valid and imported to vrfs if the + * BGP nexthop is not reachable. To check for the nexthop reachability, + * Add nexthop for EVPN RT-5 for nexthop tracking. + * + * Ideally, a BGP route should be marked as valid only if the + * nexthop is reachable. Thus, other EVPN route types also should be + * added here after testing is performed for them. + */ + if (pfx && pfx->family == AF_EVPN && + evp->prefix.route_type == BGP_EVPN_IP_PREFIX_ROUTE) + return true; + + return false; +} diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h index 6d1e8cd31b..798c3e59bc 100644 --- a/bgpd/bgp_evpn.h +++ b/bgpd/bgp_evpn.h @@ -191,5 +191,6 @@ extern void bgp_evpn_cleanup_on_disable(struct bgp *bgp); extern void bgp_evpn_cleanup(struct bgp *bgp); extern void bgp_evpn_init(struct bgp *bgp); extern int bgp_evpn_get_type5_prefixlen(struct prefix *pfx); +extern bool bgp_evpn_is_prefix_nht_supported(struct prefix *pfx); #endif /* _QUAGGA_BGP_EVPN_H */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 6be08efb21..0969c8e77e 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -43,6 +43,7 @@ #include "bgpd/bgp_fsm.h" #include "bgpd/bgp_zebra.h" #include "bgpd/bgp_flowspec_util.h" +#include "bgpd/bgp_evpn.h" extern struct zclient *zclient; @@ -773,6 +774,16 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) || CHECK_FLAG(bnc->change_flags, BGP_NEXTHOP_CHANGED)) SET_FLAG(path->flags, BGP_PATH_IGP_CHANGED); + if (safi == SAFI_EVPN && + bgp_evpn_is_prefix_nht_supported(&rn->p)) { + if (CHECK_FLAG(path->flags, BGP_PATH_VALID)) + bgp_evpn_import_route(bgp_path, afi, safi, + &rn->p, path); + else + bgp_evpn_unimport_route(bgp_path, afi, safi, + &rn->p, path); + } + bgp_process(bgp_path, rn, afi, safi); } diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 8e0a758259..a0e85eab4f 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -3041,6 +3041,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, int connected = 0; int do_loop_check = 1; int has_valid_label = 0; + afi_t nh_afi; #if ENABLE_BGP_VNC int vnc_implicit_withdraw = 0; #endif @@ -3436,8 +3437,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, /* Nexthop reachability check - for unicast and * labeled-unicast.. */ - if ((afi == AFI_IP || afi == AFI_IP6) - && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) + || (safi == SAFI_EVPN && + bgp_evpn_is_prefix_nht_supported(p))) { if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) @@ -3452,8 +3455,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, if (pi->extra && pi->extra->bgp_orig) bgp_nexthop = pi->extra->bgp_orig; - if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, afi, pi, - NULL, connected) + nh_afi = BGP_ATTR_NH_AFI(afi, pi->attr); + + if (bgp_find_or_add_nexthop(bgp, bgp_nexthop, nh_afi, + pi, NULL, connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(rn, pi, BGP_PATH_VALID); else { @@ -3501,7 +3506,8 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, * updating * the attributes for the route in the VNI(s). */ - if (safi == SAFI_EVPN && !same_attr) + if (safi == SAFI_EVPN && !same_attr && + CHECK_FLAG(pi->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, pi); /* Process change. */ @@ -3574,8 +3580,9 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, evpn == NULL ? NULL : &evpn->gw_ip); } /* Nexthop reachability check. */ - if ((afi == AFI_IP || afi == AFI_IP6) - && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) { + if (((afi == AFI_IP || afi == AFI_IP6) + && (safi == SAFI_UNICAST || safi == SAFI_LABELED_UNICAST)) + || (safi == SAFI_EVPN && bgp_evpn_is_prefix_nht_supported(p))) { if (peer->sort == BGP_PEER_EBGP && peer->ttl == 1 && !CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) @@ -3584,7 +3591,10 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, else connected = 0; - if (bgp_find_or_add_nexthop(bgp, bgp, afi, new, NULL, connected) + nh_afi = BGP_ATTR_NH_AFI(afi, new->attr); + + if (bgp_find_or_add_nexthop(bgp, bgp, nh_afi, new, NULL, + connected) || CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)) bgp_path_info_set_flag(rn, new, BGP_PATH_VALID); else { @@ -3635,7 +3645,7 @@ int bgp_update(struct peer *peer, struct prefix *p, uint32_t addpath_id, return -1; /* If this is an EVPN route, process for import. */ - if (safi == SAFI_EVPN) + if (safi == SAFI_EVPN && CHECK_FLAG(new->flags, BGP_PATH_VALID)) bgp_evpn_import_route(bgp, afi, safi, p, new); hook_call(bgp_process, bgp, afi, safi, rn, peer, false);