From 7904e9fdfa66363c516fd2af151a7af2b06805fd Mon Sep 17 00:00:00 2001 From: Anuradha Karuppiah Date: Sat, 28 Mar 2020 09:35:08 -0700 Subject: [PATCH] bgpd: extended-community and attrs for MAC-IP SYNC route handling A new proxy flag has been added to the already existing NA extended community to allow proxy advertisment of a local host by a VTEP that is yet to indpendently establish local reachability. Reference: draft-rbickhart-evpn-ip-mac-proxy-adv The extendend mac-mobility sequence number needs to be synced across the ES peers. However we cannot let a ES-peer path win over a local path on the same ES. To accomplish that some parameters such as the MM seq number are bubbled up from the non-best path to the local path. This mechanism is explained further in the path-selection patch. Signed-off-by: Anuradha Karuppiah --- bgpd/bgp_attr.c | 7 ++++++- bgpd/bgp_attr.h | 31 +++++++++++++++++++++++++++++++ bgpd/bgp_attr_evpn.c | 13 +++++++++---- bgpd/bgp_attr_evpn.h | 3 ++- bgpd/bgp_ecommunity.c | 5 +++++ bgpd/bgp_ecommunity.h | 6 ++++-- bgpd/bgp_evpn_mh.c | 9 +++++++++ bgpd/bgp_evpn_mh.h | 43 +++++++++++++++++++++++++++++++++++++++++-- 8 files changed, 107 insertions(+), 10 deletions(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index 50a2dd3d28..948055e375 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -719,6 +719,8 @@ bool attrhash_cmp(const void *p1, const void *p2) &attr2->originator_id) && overlay_index_same(attr1, attr2) && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) + && attr1->es_flags == attr2->es_flags + && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum && attr1->nh_ifindex == attr2->nh_ifindex && attr1->nh_lla_ifindex == attr2->nh_lla_ifindex && attr1->distance == attr2->distance @@ -2187,6 +2189,7 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) struct attr *const attr = args->attr; const bgp_size_t length = args->length; uint8_t sticky = 0; + bool proxy = false; if (length == 0) { attr->ecommunity = NULL; @@ -2224,7 +2227,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args) attr->router_flag = 1; /* Check EVPN Neighbor advertisement flags, R-bit */ - bgp_attr_evpn_na_flag(attr, &attr->router_flag); + bgp_attr_evpn_na_flag(attr, &attr->router_flag, &proxy); + if (proxy) + attr->es_flags |= ATTR_ES_PROXY_ADVERT; /* Extract the Rmac, if any */ if (bgp_attr_rmac(attr, &attr->rmac)) { diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 4d67194e10..1b2c75fbef 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -215,6 +215,30 @@ struct attr { /* NA router flag (R-bit) support in EVPN */ uint8_t router_flag; + /* ES info */ + uint8_t es_flags; + /* Path is not "locally-active" on the advertising VTEP. This is + * translated into an ARP-ND ECOM. + */ +#define ATTR_ES_PROXY_ADVERT (1 << 0) + /* Destination ES is present locally. This flag is set on local + * paths and sync paths + */ +#define ATTR_ES_IS_LOCAL (1 << 1) + /* There are one or more non-best paths from ES peers. Note that + * this flag is only set on the local MAC-IP paths in the VNI + * route table (not set in the global routing table). And only + * non-proxy advertisements from an ES peer can result in this + * flag being set. + */ +#define ATTR_ES_PEER_ACTIVE (1 << 2) + /* There are one or more non-best proxy paths from ES peers */ +#define ATTR_ES_PEER_PROXY (1 << 3) + /* An ES peer has router bit set - only applicable if + * ATTR_ES_PEER_ACTIVE is set + */ +#define ATTR_ES_PEER_ROUTER (1 << 4) + /* route tag */ route_tag_t tag; @@ -241,6 +265,13 @@ struct attr { /* EVPN MAC Mobility sequence number, if any. */ uint32_t mm_seqnum; + /* highest MM sequence number rxed in a MAC-IP route from an + * ES peer (this includes both proxy and non-proxy MAC-IP + * advertisements from ES peers). + * This is only applicable to local paths in the VNI routing + * table and derived from other imported/non-best paths. + */ + uint32_t mm_sync_seqnum; /* EVPN local router-mac */ struct ethaddr rmac; diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index e81ef79fbb..aa0c59f3a7 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -195,7 +195,8 @@ uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky) /* * return true if attr contains router flag extended community */ -void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag) +void bgp_attr_evpn_na_flag(struct attr *attr, + uint8_t *router_flag, bool *proxy) { struct ecommunity *ecom; int i; @@ -217,10 +218,14 @@ void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag) if (type == ECOMMUNITY_ENCODE_EVPN && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) { val = *pnt++; - if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) { + + if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG) *router_flag = 1; - break; - } + + if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG) + *proxy = true; + + break; } } } diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index e878634610..19c028a826 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -46,7 +46,8 @@ extern uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky); extern uint8_t bgp_attr_default_gw(struct attr *attr); -extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag); +extern void bgp_attr_evpn_na_flag(struct attr *attr, uint8_t *router_flag, + bool *proxy); extern bool is_zero_gw_ip(const union gw_addr *gw_ip, afi_t afi); diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c index 0990d0b872..f2aac3646c 100644 --- a/bgpd/bgp_ecommunity.c +++ b/bgpd/bgp_ecommunity.c @@ -810,6 +810,11 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter) ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)) strlcpy(encbuf, "ND:Router Flag", sizeof(encbuf)); + if (CHECK_FLAG( + flags, + ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)) + strlcpy(encbuf, "ND:Proxy", + sizeof(encbuf)); } else if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_ES_IMPORT_RT) { struct ethaddr mac; diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h index 1e9ffcb678..812bcc46e7 100644 --- a/bgpd/bgp_ecommunity.h +++ b/bgpd/bgp_ecommunity.h @@ -73,8 +73,10 @@ #define ECOMMUNITY_EVPN_SUBTYPE_ND 0x08 #define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY 0x01 -#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01 -#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02 + +#define ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG 0x01 +#define ECOMMUNITY_EVPN_SUBTYPE_ND_OVERRIDE_FLAG 0x02 +#define ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG 0x04 #define ECOMMUNITY_EVPN_SUBTYPE_ESI_SA_FLAG (1 << 0) /* single-active */ diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index 6e6dda7aa7..bb870e04b2 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -1469,6 +1469,15 @@ static void bgp_evpn_local_es_do_del(struct bgp *bgp, struct bgp_evpn_es *es) bgp_evpn_es_local_info_clear(es); } +bool bgp_evpn_is_esi_local(esi_t *esi) +{ + struct bgp_evpn_es *es = NULL; + + /* Lookup ESI hash - should exist. */ + es = bgp_evpn_es_find(esi); + return es ? !!(es->flags & BGP_EVPNES_LOCAL) : false; +} + int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi) { struct bgp_evpn_es *es = NULL; diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h index 1dcdfc3cf1..93355d495a 100644 --- a/bgpd/bgp_evpn_mh.h +++ b/bgpd/bgp_evpn_mh.h @@ -215,15 +215,53 @@ struct bgp_evpn_mh_info { }; /****************************************************************************/ -static inline int is_es_local(struct bgp_evpn_es *es) +static inline int bgp_evpn_is_es_local(struct bgp_evpn_es *es) { return CHECK_FLAG(es->flags, BGP_EVPNES_LOCAL) ? 1 : 0; } extern esi_t *zero_esi; +static inline bool bgp_evpn_is_esi_valid(esi_t *esi) +{ + return !!memcmp(esi, zero_esi, sizeof(esi_t)); +} + static inline esi_t *bgp_evpn_attr_get_esi(struct attr *attr) { - return (attr) ? &attr->esi : zero_esi; + return attr ? &attr->esi : zero_esi; +} + +static inline bool bgp_evpn_attr_is_sync(struct attr *attr) +{ + return attr ? !!(attr->es_flags & + (ATTR_ES_PEER_PROXY | ATTR_ES_PEER_ACTIVE)) : false; +} + +static inline uint32_t bgp_evpn_attr_get_sync_seq(struct attr *attr) +{ + return attr ? attr->mm_sync_seqnum : 0; +} + +static inline bool bgp_evpn_attr_is_active_on_peer(struct attr *attr) +{ + return attr ? + !!(attr->es_flags & ATTR_ES_PEER_ACTIVE) : false; +} + +static inline bool bgp_evpn_attr_is_router_on_peer(struct attr *attr) +{ + return attr ? + !!(attr->es_flags & ATTR_ES_PEER_ROUTER) : false; +} + +static inline bool bgp_evpn_attr_is_proxy(struct attr *attr) +{ + return attr ? !!(attr->es_flags & ATTR_ES_PROXY_ADVERT) : false; +} + +static inline bool bgp_evpn_attr_is_local_es(struct attr *attr) +{ + return attr ? !!(attr->es_flags & ATTR_ES_IS_LOCAL) : false; } /****************************************************************************/ @@ -256,5 +294,6 @@ void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni, bool uj, bool detail); void bgp_evpn_es_evi_show(struct vty *vty, bool uj, bool detail); struct bgp_evpn_es *bgp_evpn_es_find(const esi_t *esi); +extern bool bgp_evpn_is_esi_local(esi_t *esi); #endif /* _FRR_BGP_EVPN_MH_H */ -- 2.39.5