From 2b83602b24a76dee76b96d63758d9e4455a9cc86 Mon Sep 17 00:00:00 2001 From: vivek Date: Wed, 27 Feb 2019 12:54:24 +0000 Subject: [PATCH] *: Explicitly mark nexthop of EVPN-sourced routes as onlink In the case of EVPN symmetric routing, the tenant VRF is associated with a VNI that is used for routing and commonly referred to as the L3 VNI or VRF VNI. Corresponding to this VNI is a VLAN and its associated L3 (IP) interface (SVI). Overlay next hops (i.e., next hops for routes in the tenant VRF) are reachable over this interface. Howver, in the model that is supported in the implementation and commonly deployed, there is no explicit Overlay IP address associated with the next hop in the tenant VRF; the underlay IP is used if (since) the forwarding plane requires a next hop IP. Therefore, the next hop has to be explicit flagged as onlink to cause any next hop reachability checks in the forwarding plane to be skipped. https://tools.ietf.org/html/draft-ietf-bess-evpn-prefix-advertisement section 4.4 provides additional description of the above constructs. Use existing mechanism to specify the nexthops as onlink when installing these routes from bgpd to zebra and get rid of a special flag that was introduced for EVPN-sourced routes. Also, use the onlink flag during next hop validation in zebra and eliminate other special checks. Signed-off-by: Vivek Venkatraman Reviewed-by: Anuradha Karuppiah Reviewed-by: Donald Sharp --- bgpd/bgp_zebra.c | 2 ++ lib/nexthop.h | 1 - zebra/zapi_msg.c | 12 ++++-------- zebra/zebra_rib.c | 17 ++++++++--------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index a19821cac0..da068a115a 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1126,6 +1126,7 @@ static int update_ipv4nh_for_route_install(int nh_othervrf, */ if (is_evpn) { api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; + api_nh->onlink = true; api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; } else if (nh_othervrf && api_nh->gate.ipv4.s_addr == INADDR_ANY) { @@ -1151,6 +1152,7 @@ update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, if (is_evpn) { api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; + api_nh->onlink = true; api_nh->ifindex = nh_bgp->l3vni_svi_ifindex; } else if (nh_othervrf) { if (IN6_IS_ADDR_UNSPECIFIED(nexthop)) { diff --git a/lib/nexthop.h b/lib/nexthop.h index c79ec590a8..fd27ca207b 100644 --- a/lib/nexthop.h +++ b/lib/nexthop.h @@ -83,7 +83,6 @@ struct nexthop { #define NEXTHOP_FLAG_MATCHED (1 << 4) /* Already matched vs a nexthop */ #define NEXTHOP_FLAG_FILTERED (1 << 5) /* rmap filtered, used by static only */ #define NEXTHOP_FLAG_DUPLICATE (1 << 6) /* nexthop duplicates another active one */ -#define NEXTHOP_FLAG_EVPN_RVTEP (1 << 7) /* EVPN remote vtep nexthop */ #define NEXTHOP_IS_ACTIVE(flags) \ (CHECK_FLAG(flags, NEXTHOP_FLAG_ACTIVE) \ && !CHECK_FLAG(flags, NEXTHOP_FLAG_DUPLICATE)) diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c index 8b3382dba8..9f2bbcf426 100644 --- a/zebra/zapi_msg.c +++ b/zebra/zapi_msg.c @@ -1447,12 +1447,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) re, &api_nh->gate.ipv4, NULL, ifindex, api_nh->vrf_id); - /* if this an EVPN route entry, - * program the nh as neigh + /* Special handling for IPv4 routes sourced from EVPN: + * the nexthop and associated MAC need to be installed. */ if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { - SET_FLAG(nexthop->flags, - NEXTHOP_FLAG_EVPN_RVTEP); vtep_ip.ipa_type = IPADDR_V4; memcpy(&(vtep_ip.ipaddr_v4), &(api_nh->gate.ipv4), @@ -1473,12 +1471,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS) re, &api_nh->gate.ipv6, ifindex, api_nh->vrf_id); - /* if this an EVPN route entry, - * program the nh as neigh + /* Special handling for IPv6 routes sourced from EVPN: + * the nexthop and associated MAC need to be installed. */ if (CHECK_FLAG(api.flags, ZEBRA_FLAG_EVPN_ROUTE)) { - SET_FLAG(nexthop->flags, - NEXTHOP_FLAG_EVPN_RVTEP); vtep_ip.ipa_type = IPADDR_V6; memcpy(&vtep_ip.ipaddr_v6, &(api_nh->gate.ipv6), sizeof(struct in6_addr)); diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 5f9210109d..de1aa7d6d8 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -276,10 +276,8 @@ struct nexthop *route_entry_nexthop_ipv4_ifindex_add(struct route_entry *re, /*Pending: need to think if null ifp here is ok during bootup? There was a crash because ifp here was coming to be NULL */ if (ifp) - if (connected_is_unnumbered(ifp) - || CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) { + if (connected_is_unnumbered(ifp)) SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); - } route_entry_nexthop_add(re, nexthop); @@ -314,8 +312,6 @@ struct nexthop *route_entry_nexthop_ipv6_ifindex_add(struct route_entry *re, nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX; nexthop->gate.ipv6 = *ipv6; nexthop->ifindex = ifindex; - if (CHECK_FLAG(re->flags, ZEBRA_FLAG_EVPN_ROUTE)) - SET_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK); route_entry_nexthop_add(re, nexthop); @@ -433,10 +429,6 @@ static int nexthop_active(afi_t afi, struct route_entry *re, re->nexthop_mtu = 0; } - /* Next hops (remote VTEPs) for EVPN routes are fully resolved. */ - if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_EVPN_RVTEP)) - return 1; - /* * If the kernel has sent us a route, then * by golly gee whiz it's a good route. @@ -459,6 +451,9 @@ static int nexthop_active(afi_t afi, struct route_entry *re, * Check to see if we should trust the passed in information * for UNNUMBERED interfaces as that we won't find the GW * address in the routing table. + * This check should suffice to handle IPv4 or IPv6 routes + * sourced from EVPN routes which are installed with the + * next hop as the remote VTEP IP. */ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK)) { ifp = if_lookup_by_index(nexthop->ifindex, nexthop->vrf_id); @@ -2937,6 +2932,10 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type, return; } + /* Special handling for IPv4 or IPv6 routes sourced from + * EVPN - the nexthop (and associated MAC) need to be + * uninstalled if no more refs. + */ if (CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE)) { struct nexthop *tmp_nh;