From d071f237150289a1176cdf3ae128ffb6fcb91688 Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Sat, 28 Mar 2020 09:51:14 -0700 Subject: [PATCH] bgpd: evpn path selection changes for MAC-IP SYNC route handling When a SYNC route i.e. a route with a local ES as destination is rxed on a switch (say L11) from an ES peer (say L12) a local MAC/neigh entry is created on L11 with the local access port as dest port. Creation of the local entry triggers a local path advertisement from L11. This could be a "locally-active" path or a "locally-inactive" path. Inactive paths are advertised with the proxy bit. To ensure that the local entry is not deleted by a SYNC route it is given absolute precedence over peer-paths. If there are two non-local paths with the same dest ES and same MM seq number the non-proxy path is preferred. This is done to ensure that we don't lose track of the peer-activity. Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_route.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++-- bgpd/bgp_route.h | 2 ++ bgpd/bgp_table.h | 2 ++ 3 files changed, 91 insertions(+), 2 deletions(-) diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index d931b128e3..37a98c10ce 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -545,6 +545,11 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, uint32_t new_mm_seq; uint32_t exist_mm_seq; int nh_cmp; + esi_t *exist_esi; + esi_t *new_esi; + bool same_esi; + bool old_proxy; + bool new_proxy; *paths_eq = 0; @@ -621,6 +626,47 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, } } + new_esi = bgp_evpn_attr_get_esi(newattr); + exist_esi = bgp_evpn_attr_get_esi(existattr); + if (bgp_evpn_is_esi_valid(new_esi) && + !memcmp(new_esi, exist_esi, sizeof(esi_t))) { + same_esi = true; + } else { + same_esi = false; + } + + /* If both paths have the same non-zero ES and + * one path is local it wins. + * PS: Note the local path wins even if the remote + * has the higher MM seq. The local path's + * MM seq will be fixed up to match the highest + * rem seq, subsequently. + */ + if (same_esi) { + char esi_buf[ESI_STR_LEN]; + + if (bgp_evpn_is_path_local(bgp, new)) { + *reason = bgp_path_selection_evpn_local_path; + if (debug) + zlog_debug( + "%s: %s wins over %s as ES %s is same and local", + pfx_buf, new_buf, exist_buf, + esi_to_str(new_esi, esi_buf, + sizeof(esi_buf))); + return 1; + } + if (bgp_evpn_is_path_local(bgp, exist)) { + *reason = bgp_path_selection_evpn_local_path; + if (debug) + zlog_debug( + "%s: %s loses to %s as ES %s is same and local", + pfx_buf, new_buf, exist_buf, + esi_to_str(new_esi, esi_buf, + sizeof(esi_buf))); + return 0; + } + } + new_mm_seq = mac_mobility_seqnum(newattr); exist_mm_seq = mac_mobility_seqnum(existattr); @@ -644,6 +690,30 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 0; } + /* if the sequence numbers and ESI are the same and one path + * is non-proxy it wins (over proxy) + */ + new_proxy = bgp_evpn_attr_is_proxy(newattr); + old_proxy = bgp_evpn_attr_is_proxy(existattr); + if (same_esi && bgp_evpn_attr_is_local_es(newattr) && + old_proxy != new_proxy) { + if (!new_proxy) { + *reason = bgp_path_selection_evpn_non_proxy; + if (debug) + zlog_debug( + "%s: %s wins over %s, same seq/es and non-proxy", + pfx_buf, new_buf, exist_buf); + return 1; + } + + *reason = bgp_path_selection_evpn_non_proxy; + if (debug) + zlog_debug( + "%s: %s loses to %s, same seq/es and non-proxy", + pfx_buf, new_buf, exist_buf); + return 0; + } + /* * if sequence numbers are the same path with the lowest IP * wins @@ -1176,6 +1246,17 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, return 1; } + +int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, + struct bgp_path_info *exist, int *paths_eq) +{ + enum bgp_path_selection_reason reason; + char pfx_buf[PREFIX2STR_BUFFER]; + + return bgp_path_info_cmp(bgp, new, exist, paths_eq, NULL, 0, pfx_buf, + AFI_L2VPN, SAFI_EVPN, &reason); +} + /* Compare two bgp route entity. Return -1 if new is preferred, 1 if exist * is preferred, or 0 if they are the same (usually will only occur if * multipath is enabled @@ -7938,7 +8019,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, vty_out(vty, "%s", bgp_origin_str[attr->origin]); if (json_paths) { - if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) { + if (bgp_evpn_is_esi_valid(&attr->esi)) { json_object_string_add(json_path, "esi", esi_to_str(&attr->esi, esi_buf, sizeof(esi_buf))); @@ -7989,7 +8070,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p, vty_out(vty, "\n"); if (safi == SAFI_EVPN) { - if (memcmp(&attr->esi, zero_esi, sizeof(esi_t))) { + if (bgp_evpn_is_esi_valid(&attr->esi)) { vty_out(vty, "%*s", 20, " "); vty_out(vty, "ESI:%s\n", esi_to_str(&attr->esi, @@ -8615,6 +8696,10 @@ static const char *bgp_path_selection_reason2str( return "EVPN sequence number"; case bgp_path_selection_evpn_lower_ip: return "EVPN lower IP"; + case bgp_path_selection_evpn_local_path: + return "EVPN local ES path"; + case bgp_path_selection_evpn_non_proxy: + return "EVPN non proxy"; case bgp_path_selection_weight: return "Weight"; case bgp_path_selection_local_pref: diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 691d5cdec2..3f734d2672 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -682,4 +682,6 @@ extern int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi); extern bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi, uint8_t type, uint8_t stype, struct attr *attr, struct bgp_dest *dest); +extern int bgp_evpn_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new, + struct bgp_path_info *exist, int *paths_eq); #endif /* _QUAGGA_BGP_ROUTE_H */ diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h index a9ec36d29b..cf0086b52e 100644 --- a/bgpd/bgp_table.h +++ b/bgpd/bgp_table.h @@ -51,6 +51,8 @@ enum bgp_path_selection_reason { bgp_path_selection_first, bgp_path_selection_evpn_sticky_mac, bgp_path_selection_evpn_seq, + bgp_path_selection_evpn_local_path, + bgp_path_selection_evpn_non_proxy, bgp_path_selection_evpn_lower_ip, bgp_path_selection_weight, bgp_path_selection_local_pref, -- 2.39.5