From a2299abae82c41ea7aaa303dde91bfceee1a88b3 Mon Sep 17 00:00:00 2001 From: Ameya Dharkar Date: Sun, 10 Jan 2021 22:32:41 -0800 Subject: [PATCH] bgpd: Import received EVPN RT-5 prefix with gateway IP in BGP VRF The IP/IPv6 prefix carried with EVPN RT-5 is imported in the BGP vrf according to the attached route targets. If the prefix carries a gateway IP overlay index, this gateway IP should be installed as the nexthop of the route imported in the BGP vrf. This route in vrf will be marked as VALID only if the nexthop is resolved in the SVI network. To receive runtime reachability information for the nexthop, register it with the nexthop tracking module. Send this route to zebra after processing. Signed-off-by: Ameya Dharkar --- bgpd/bgp_evpn.c | 59 +++++++++++++++++++++++++++++++++++++++++++----- bgpd/bgp_nht.c | 8 +++++-- bgpd/bgp_zebra.c | 41 ++++++++++++++++++++++++++------- 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index ae365fa13e..d00a882c1a 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -53,6 +53,7 @@ #include "bgpd/bgp_addpath.h" #include "bgpd/bgp_mac.h" #include "bgpd/bgp_vty.h" +#include "bgpd/bgp_nht.h" /* * Definitions and external declarations. @@ -2402,6 +2403,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, bool new_pi = false; bool use_l3nhg = false; bool is_l3nhg_active = false; + char buf1[INET6_ADDRSTRLEN]; memset(pp, 0, sizeof(struct prefix)); ip_prefix_from_evpn_prefix(evp, pp); @@ -2432,10 +2434,36 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * make sure to set the flag for next hop attribute. */ attr = *parent_pi->attr; - if (afi == AFI_IP6) - evpn_convert_nexthop_to_ipv6(&attr); - else - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + if (attr.evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP) { + if (afi == AFI_IP6) + evpn_convert_nexthop_to_ipv6(&attr); + else + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + } else { + + /* + * If gateway IP overlay index is specified in the NLRI of + * EVPN RT-5, this gateway IP should be used as the nexthop + * for the prefix in the VRF + */ + if (bgp_debug_zebra(NULL)) { + zlog_debug( + "Install gateway IP %s as nexthop for prefix %pFX in vrf %s", + inet_ntop(pp->family, &attr.evpn_overlay.gw_ip, + buf1, sizeof(buf1)), pp, + vrf_id_to_name(bgp_vrf->vrf_id)); + } + + if (afi == AFI_IP6) { + memcpy(&attr.mp_nexthop_global, + &attr.evpn_overlay.gw_ip.ipv6, + sizeof(struct in6_addr)); + attr.mp_nexthop_len = IPV6_MAX_BYTELEN; + } else { + attr.nexthop = attr.evpn_overlay.gw_ip.ipv4; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + } + } bgp_evpn_es_vrf_use_nhg(bgp_vrf, &parent_pi->attr->esi, &use_l3nhg, &is_l3nhg_active, NULL); @@ -2481,8 +2509,27 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, pi->attr = attr_new; pi->uptime = bgp_clock(); } - /* as it is an importation, change nexthop */ - bgp_path_info_set_flag(dest, pi, BGP_PATH_ANNC_NH_SELF); + + /* Gateway IP nexthop should be resolved */ + if (attr.evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) { + if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi, + NULL, 0)) + bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID); + else { + if (BGP_DEBUG(nht, NHT)) { + inet_ntop(pp->family, + &attr.evpn_overlay.gw_ip, + buf1, sizeof(buf1)); + zlog_debug("%s: gateway IP NH unresolved", + buf1); + } + bgp_path_info_unset_flag(dest, pi, BGP_PATH_VALID); + } + } else { + + /* as it is an importation, change nexthop */ + bgp_path_info_set_flag(dest, pi, BGP_PATH_ANNC_NH_SELF); + } /* Link path to evpn nexthop */ bgp_evpn_path_nh_add(bgp_vrf, pi); diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 4b4a3716e6..638c72ae67 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -942,6 +942,9 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) * In case of unicast routes that were imported from vpn * and that have labels, they are valid only if there are * nexthops with labels + * + * If the nexthop is EVPN gateway-IP, + * do not check for a valid label. */ bool bnc_is_valid_nexthop = false; @@ -950,8 +953,9 @@ static void evaluate_paths(struct bgp_nexthop_cache *bnc) if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED && path->extra && - path->extra->num_labels) { - + path->extra->num_labels && + path->attr->evpn_overlay.type != + OVERLAY_INDEX_GATEWAY_IP) { bnc_is_valid_nexthop = bgp_isvalid_labeled_nexthop(bnc) ? true : false; } else { diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index c2c114d2c9..b32f319655 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1058,9 +1058,19 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, * connected routes leaked into a VRF. */ if (is_evpn) { - api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; - SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); - api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; + + /* + * If the nexthop is EVPN overlay index gateway IP, + * treat the nexthop as NEXTHOP_TYPE_IPV4 + * Else, mark the nexthop as onlink. + */ + if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) + api_nh->type = NEXTHOP_TYPE_IPV4; + else { + api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); + api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; + } } else if (nh_othervrf && api_nh->gate.ipv4.s_addr == INADDR_ANY) { api_nh->type = NEXTHOP_TYPE_IFINDEX; @@ -1085,9 +1095,19 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, api_nh->vrf_id = nh_bgp->vrf_id; if (is_evpn) { - api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; - SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); - api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; + + /* + * If the nexthop is EVPN overlay index gateway IP, + * treat the nexthop as NEXTHOP_TYPE_IPV4 + * Else, mark the nexthop as onlink. + */ + if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) + api_nh->type = NEXTHOP_TYPE_IPV6; + else { + api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + SET_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_ONLINK); + api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; + } } else if (nh_othervrf) { if (IN6_IS_ADDR_UNSPECIFIED(nexthop)) { api_nh->type = NEXTHOP_TYPE_IFINDEX; @@ -1392,8 +1412,13 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p, api_nh->label_num = 1; api_nh->labels[0] = label; } - memcpy(&api_nh->rmac, &(mpinfo->attr->rmac), - sizeof(struct ethaddr)); + + if (is_evpn + && mpinfo->attr->evpn_overlay.type + != OVERLAY_INDEX_GATEWAY_IP) + memcpy(&api_nh->rmac, &(mpinfo->attr->rmac), + sizeof(struct ethaddr)); + api_nh->weight = nh_weight; if (mpinfo->extra