*: 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 <vivek@cumulusnetworks.com>
Reviewed-by:   Anuradha Karuppiah <anuradhak@cumulusnetworks.com>
Reviewed-by:   Donald Sharp <sharpd@cumulusnetworks.com>
This commit is contained in:
vivek 2019-02-27 12:54:24 +00:00
parent e1e71450a0
commit 2b83602b24
4 changed files with 14 additions and 18 deletions

View File

@ -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)) {

View File

@ -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))

View File

@ -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));

View File

@ -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;