From b336388d4afa2ab1e39cb130ffde0a85e87f13e3 Mon Sep 17 00:00:00 2001 From: Xiao Liang Date: Fri, 11 Apr 2025 18:04:50 +0800 Subject: [PATCH] bgpd: Clean extended communities for VRF routes imported from EVPN According to draft-ietf-bess-evpn-ipvpn-interworking-13, strip the following extended communities for VRF routes imported from EVPN. a. BGP Encapsulation extended communities. b. Route Target extended communities. c. All the extended communities of type EVPN. As the corresponding fields will not be always covered by extended communities, add them to attr hash key directly. Signed-off-by: Xiao Liang --- bgpd/bgp_attr.c | 8 +++++++- bgpd/bgp_evpn.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index b4adf47eb0..8b6bfd3254 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -863,6 +863,9 @@ unsigned int attrhash_key_make(const void *p) key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance); MIX3(attr->bh_type, attr->otc, bgp_attr_get_aigp_metric(attr)); + MIX3(attr->mm_seqnum, attr->df_alg, attr->df_pref); + MIX(attr->encap_tunneltype); + key = jhash(&attr->rmac, sizeof(attr->rmac), key); return key; } @@ -912,6 +915,7 @@ bool attrhash_cmp(const void *p1, const void *p2) overlay_index_same(attr1, attr2) && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) && attr1->es_flags == attr2->es_flags && + attr1->mm_seqnum == attr2->mm_seqnum && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum && attr1->df_pref == attr2->df_pref && attr1->df_alg == attr2->df_alg && @@ -923,7 +927,9 @@ bool attrhash_cmp(const void *p1, const void *p2) srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) && attr1->srte_color == attr2->srte_color && attr1->nh_type == attr2->nh_type && - attr1->bh_type == attr2->bh_type && attr1->otc == attr2->otc) + attr1->bh_type == attr2->bh_type && + attr1->otc == attr2->otc && + !memcmp(&attr1->rmac, &attr2->rmac, sizeof(struct ethaddr))) return true; } diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 0ebef2ecfe..9209be3ca9 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -3050,6 +3050,33 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi, return pi; } +/* + * According to draft-ietf-bess-evpn-ipvpn-interworking-13, strip the following + * extended communities for VRF routes imported from EVPN. + * + * a. BGP Encapsulation extended communities. + * b. Route Target extended communities. + * c. All the extended communities of type EVPN. + */ +static bool bgp_evpn_filter_ecommunity(uint8_t *val, uint8_t size, void *arg) +{ + switch (val[0]) { + case ECOMMUNITY_ENCODE_AS: + case ECOMMUNITY_ENCODE_IP: + case ECOMMUNITY_ENCODE_AS4: + if (val[1] == ECOMMUNITY_ROUTE_TARGET) + return false; + break; + case ECOMMUNITY_ENCODE_OPAQUE: + if (val[1] == ECOMMUNITY_OPAQUE_SUBTYPE_ENCAP) + return false; + break; + case ECOMMUNITY_ENCODE_EVPN: + return false; + } + return true; +} + /* * Install route entry into the VRF routing table and invoke route selection. */ @@ -3071,6 +3098,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, bool is_l3nhg_active = false; char buf1[INET6_ADDRSTRLEN]; struct bgp_route_evpn *bre; + struct ecommunity *ecom; memset(pp, 0, sizeof(struct prefix)); ip_prefix_from_evpn_prefix(evp, pp); @@ -3142,6 +3170,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, if (is_l3nhg_active) SET_FLAG(attr.es_flags, ATTR_ES_L3_NHG_ACTIVE); + ecom = ecommunity_filter(bgp_attr_get_ecommunity(&attr), bgp_evpn_filter_ecommunity, NULL); + bgp_attr_set_ecommunity(&attr, ecom); + /* Check if route entry is already present. */ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (pi->extra && pi->extra->vrfleak && -- 2.39.5