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 <shaw.leon@gmail.com>
This commit is contained in:
Xiao Liang 2025-04-11 18:04:50 +08:00
parent f84e89ec0d
commit b336388d4a
2 changed files with 38 additions and 1 deletions

View file

@ -863,6 +863,9 @@ unsigned int attrhash_key_make(const void *p)
key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key); key = jhash(attr->mp_nexthop_local.s6_addr, IPV6_MAX_BYTELEN, key);
MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance); MIX3(attr->nh_ifindex, attr->nh_lla_ifindex, attr->distance);
MIX3(attr->bh_type, attr->otc, bgp_attr_get_aigp_metric(attr)); 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; return key;
} }
@ -912,6 +915,7 @@ bool attrhash_cmp(const void *p1, const void *p2)
overlay_index_same(attr1, attr2) && overlay_index_same(attr1, attr2) &&
!memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) && !memcmp(&attr1->esi, &attr2->esi, sizeof(esi_t)) &&
attr1->es_flags == attr2->es_flags && attr1->es_flags == attr2->es_flags &&
attr1->mm_seqnum == attr2->mm_seqnum &&
attr1->mm_sync_seqnum == attr2->mm_sync_seqnum && attr1->mm_sync_seqnum == attr2->mm_sync_seqnum &&
attr1->df_pref == attr2->df_pref && attr1->df_pref == attr2->df_pref &&
attr1->df_alg == attr2->df_alg && 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) && srv6_vpn_same(attr1->srv6_vpn, attr2->srv6_vpn) &&
attr1->srte_color == attr2->srte_color && attr1->srte_color == attr2->srte_color &&
attr1->nh_type == attr2->nh_type && 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; return true;
} }

View file

@ -3050,6 +3050,33 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
return 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. * 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; bool is_l3nhg_active = false;
char buf1[INET6_ADDRSTRLEN]; char buf1[INET6_ADDRSTRLEN];
struct bgp_route_evpn *bre; struct bgp_route_evpn *bre;
struct ecommunity *ecom;
memset(pp, 0, sizeof(struct prefix)); memset(pp, 0, sizeof(struct prefix));
ip_prefix_from_evpn_prefix(evp, pp); 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) if (is_l3nhg_active)
SET_FLAG(attr.es_flags, ATTR_ES_L3_NHG_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. */ /* Check if route entry is already present. */
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (pi->extra && pi->extra->vrfleak && if (pi->extra && pi->extra->vrfleak &&