diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c index ac5d08b6fe..e85918bf53 100644 --- a/bgpd/bgp_attr.c +++ b/bgpd/bgp_attr.c @@ -198,6 +198,7 @@ static struct hash *vnc_hash = NULL; #endif static struct hash *srv6_l3vpn_hash; static struct hash *srv6_vpn_hash; +static struct hash *evpn_overlay_hash; struct bgp_attr_encap_subtlv *encap_tlv_dup(struct bgp_attr_encap_subtlv *orig) { @@ -549,6 +550,81 @@ static bool bgp_attr_aigp_valid(uint8_t *pnt, int length) return true; } +static void *evpn_overlay_hash_alloc(void *p) +{ + return p; +} + +static void evpn_overlay_free(struct bgp_route_evpn *bre) +{ + XFREE(MTYPE_BGP_EVPN_OVERLAY, bre); +} + +static struct bgp_route_evpn *evpn_overlay_intern(struct bgp_route_evpn *bre) +{ + struct bgp_route_evpn *find; + + find = hash_get(evpn_overlay_hash, bre, evpn_overlay_hash_alloc); + if (find != bre) + evpn_overlay_free(bre); + find->refcnt++; + return find; +} + +static void evpn_overlay_unintern(struct bgp_route_evpn **brep) +{ + struct bgp_route_evpn *bre = *brep; + + if (!*brep) + return; + + if (bre->refcnt) + bre->refcnt--; + + if (bre->refcnt == 0) { + hash_release(evpn_overlay_hash, bre); + evpn_overlay_free(bre); + *brep = NULL; + } +} + +static uint32_t evpn_overlay_hash_key_make(const void *p) +{ + const struct bgp_route_evpn *bre = p; + uint32_t key = 0; + + if (IS_IPADDR_V4(&bre->gw_ip)) + key = jhash_1word(bre->gw_ip.ipaddr_v4.s_addr, 0); + else + key = jhash2(bre->gw_ip.ipaddr_v6.s6_addr32, + array_size(bre->gw_ip.ipaddr_v6.s6_addr32), 0); + + key = jhash_1word(bre->type, key); + key = jhash(bre->eth_s_id.val, sizeof(bre->eth_s_id.val), 0); + return key; +} + +static bool evpn_overlay_hash_cmp(const void *p1, const void *p2) +{ + const struct bgp_route_evpn *bre1 = p1; + const struct bgp_route_evpn *bre2 = p2; + + return bgp_route_evpn_same(bre1, bre2); +} + +static void evpn_overlay_init(void) +{ + evpn_overlay_hash = hash_create(evpn_overlay_hash_key_make, + evpn_overlay_hash_cmp, + "BGP EVPN Overlay"); +} + +static void evpn_overlay_finish(void) +{ + hash_clean_and_free(&evpn_overlay_hash, + (void (*)(void *))evpn_overlay_free); +} + static void *srv6_l3vpn_hash_alloc(void *p) { return p; @@ -788,6 +864,8 @@ unsigned int attrhash_key_make(const void *p) MIX(encap_hash_key_make(attr->encap_subtlvs)); if (attr->srv6_l3vpn) MIX(srv6_l3vpn_hash_key_make(attr->srv6_l3vpn)); + if (bgp_attr_get_evpn_overlay(attr)) + MIX(evpn_overlay_hash_key_make(bgp_attr_get_evpn_overlay(attr))); if (attr->srv6_vpn) MIX(srv6_vpn_hash_key_make(attr->srv6_vpn)); #ifdef ENABLE_BGP_VNC @@ -961,6 +1039,7 @@ struct attr *bgp_attr_intern(struct attr *attr) struct ecommunity *ipv6_ecomm = NULL; struct lcommunity *lcomm = NULL; struct community *comm = NULL; + struct bgp_route_evpn *bre = NULL; /* Intern referenced structure. */ if (attr->aspath) { @@ -1027,6 +1106,16 @@ struct attr *bgp_attr_intern(struct attr *attr) else attr->encap_subtlvs->refcnt++; } + + bre = bgp_attr_get_evpn_overlay(attr); + if (bre) { + if (!bre->refcnt) + bgp_attr_set_evpn_overlay(attr, + evpn_overlay_intern(bre)); + else + bre->refcnt++; + } + if (attr->srv6_l3vpn) { if (!attr->srv6_l3vpn->refcnt) attr->srv6_l3vpn = srv6_l3vpn_intern(attr->srv6_l3vpn); @@ -1216,6 +1305,7 @@ void bgp_attr_unintern_sub(struct attr *attr) struct lcommunity *lcomm = NULL; struct community *comm = NULL; struct transit *transit; + struct bgp_route_evpn *bre; /* aspath refcount shoud be decrement. */ aspath_unintern(&attr->aspath); @@ -1257,6 +1347,10 @@ void bgp_attr_unintern_sub(struct attr *attr) srv6_l3vpn_unintern(&attr->srv6_l3vpn); srv6_vpn_unintern(&attr->srv6_vpn); + + bre = bgp_attr_get_evpn_overlay(attr); + evpn_overlay_unintern(&bre); + bgp_attr_set_evpn_overlay(attr, NULL); } /* Free bgp attribute and aspath. */ @@ -1289,6 +1383,7 @@ void bgp_attr_flush(struct attr *attr) struct cluster_list *cluster; struct lcommunity *lcomm; struct community *comm; + struct bgp_route_evpn *bre; if (attr->aspath && !attr->aspath->refcnt) { aspath_free(attr->aspath); @@ -1347,6 +1442,11 @@ void bgp_attr_flush(struct attr *attr) bgp_attr_set_vnc_subtlvs(attr, NULL); } #endif + bre = bgp_attr_get_evpn_overlay(attr); + if (bre && !bre->refcnt) { + evpn_overlay_free(bre); + bgp_attr_set_evpn_overlay(attr, NULL); + } } /* Implement draft-scudder-idr-optional-transitive behaviour and @@ -5006,6 +5106,7 @@ void bgp_attr_init(void) transit_init(); encap_init(); srv6_init(); + evpn_overlay_init(); } void bgp_attr_finish(void) @@ -5019,6 +5120,7 @@ void bgp_attr_finish(void) transit_finish(); encap_finish(); srv6_finish(); + evpn_overlay_finish(); } /* Make attribute packet. */ diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h index 561024e7c8..f4b800737e 100644 --- a/bgpd/bgp_attr.h +++ b/bgpd/bgp_attr.h @@ -278,7 +278,7 @@ struct attr { struct bgp_attr_encap_subtlv *vnc_subtlvs; /* VNC-specific */ #endif /* EVPN */ - struct bgp_route_evpn evpn_overlay; + struct bgp_route_evpn *evpn_overlay; /* EVPN MAC Mobility sequence number, if any. */ uint32_t mm_seqnum; @@ -614,16 +614,16 @@ static inline void bgp_attr_set_cluster(struct attr *attr, UNSET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_CLUSTER_LIST)); } -static inline const struct bgp_route_evpn * +static inline struct bgp_route_evpn * bgp_attr_get_evpn_overlay(const struct attr *attr) { - return &attr->evpn_overlay; + return attr->evpn_overlay; } static inline void bgp_attr_set_evpn_overlay(struct attr *attr, - struct bgp_route_evpn *eo) + struct bgp_route_evpn *bre) { - memcpy(&attr->evpn_overlay, eo, sizeof(struct bgp_route_evpn)); + attr->evpn_overlay = bre; } static inline struct bgp_attr_encap_subtlv * diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c index 086c36f36c..fc7548d9bf 100644 --- a/bgpd/bgp_attr_evpn.c +++ b/bgpd/bgp_attr_evpn.c @@ -24,6 +24,13 @@ bool bgp_route_evpn_same(const struct bgp_route_evpn *e1, const struct bgp_route_evpn *e2) { + if (!e1 && e2) + return false; + if (!e2 && e1) + return false; + if (!e1 && !e2) + return true; + return (e1->type == e2->type && !memcmp(&(e1->eth_s_id), &(e2->eth_s_id), sizeof(esi_t)) && !ipaddr_cmp(&(e1->gw_ip), &(e2->gw_ip))); diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h index e12fc3a86c..cc0e3e4400 100644 --- a/bgpd/bgp_attr_evpn.h +++ b/bgpd/bgp_attr_evpn.h @@ -23,6 +23,7 @@ enum overlay_index_type { * MAC overlay index is stored in the RMAC attribute. */ struct bgp_route_evpn { + unsigned long refcnt; enum overlay_index_type type; esi_t eth_s_id; struct ipaddr gw_ip; diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c index 55896ee7ea..fc54babaa3 100644 --- a/bgpd/bgp_evpn.c +++ b/bgpd/bgp_evpn.c @@ -1741,20 +1741,30 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp, BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) { if (src_attr && !IN6_IS_ADDR_UNSPECIFIED(&src_attr->mp_nexthop_global)) { - attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP; - SET_IPADDR_V6(&attr.evpn_overlay.gw_ip); - memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6, + struct bgp_route_evpn *bre = + XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); + + bre->type = OVERLAY_INDEX_GATEWAY_IP; + SET_IPADDR_V6(&bre->gw_ip); + memcpy(&bre->gw_ip.ipaddr_v6, &src_attr->mp_nexthop_global, sizeof(struct in6_addr)); + bgp_attr_set_evpn_overlay(&attr, bre); } } else if (src_afi == AFI_IP && CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN], BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) { if (src_attr && src_attr->nexthop.s_addr != 0) { - attr.evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP; - SET_IPADDR_V4(&attr.evpn_overlay.gw_ip); - memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4, - &src_attr->nexthop, sizeof(struct in_addr)); + struct bgp_route_evpn *bre = + XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); + + bre->type = OVERLAY_INDEX_GATEWAY_IP; + SET_IPADDR_V4(&bre->gw_ip); + memcpy(&bre->gw_ip.ipaddr_v4, &src_attr->nexthop, + sizeof(struct in_addr)); + bgp_attr_set_evpn_overlay(&attr, bre); } } @@ -3031,6 +3041,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, bool use_l3nhg = false; bool is_l3nhg_active = false; char buf1[INET6_ADDRSTRLEN]; + struct bgp_route_evpn *bre; memset(pp, 0, sizeof(struct prefix)); ip_prefix_from_evpn_prefix(evp, pp); @@ -3064,35 +3075,33 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, * make sure to set the flag for next hop attribute. */ attr = *parent_pi->attr; - if (attr.evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP) { - if (afi == AFI_IP6) - evpn_convert_nexthop_to_ipv6(&attr); - else { - attr.nexthop = attr.mp_nexthop_global_in; - attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); - } - } else { - + bre = bgp_attr_get_evpn_overlay(&attr); + if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) { /* * If gateway IP overlay index is specified in the NLRI of * EVPN RT-5, this gateway IP should be used as the nexthop * for the prefix in the VRF */ if (bgp_debug_zebra(NULL)) { - zlog_debug( - "Install gateway IP %s as nexthop for prefix %pFX in vrf %s", - inet_ntop(pp->family, &attr.evpn_overlay.gw_ip, - buf1, sizeof(buf1)), pp, - vrf_id_to_name(bgp_vrf->vrf_id)); + zlog_debug("Install gateway IP %s as nexthop for prefix %pFX in vrf %s", + inet_ntop(pp->family, &bre->gw_ip, buf1, + sizeof(buf1)), + pp, vrf_id_to_name(bgp_vrf->vrf_id)); } if (afi == AFI_IP6) { - memcpy(&attr.mp_nexthop_global, - &attr.evpn_overlay.gw_ip.ipaddr_v6, + memcpy(&attr.mp_nexthop_global, &bre->gw_ip.ipaddr_v6, sizeof(struct in6_addr)); attr.mp_nexthop_len = IPV6_MAX_BYTELEN; } else { - attr.nexthop = attr.evpn_overlay.gw_ip.ipaddr_v4; + attr.nexthop = bre->gw_ip.ipaddr_v4; + attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); + } + } else { + if (afi == AFI_IP6) + evpn_convert_nexthop_to_ipv6(&attr); + else { + attr.nexthop = attr.mp_nexthop_global_in; attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP); } } @@ -3144,22 +3153,20 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf, } /* Gateway IP nexthop should be resolved */ - if (attr.evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) { + if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) { if (bgp_find_or_add_nexthop(bgp_vrf, bgp_vrf, afi, safi, pi, NULL, 0, NULL)) bgp_path_info_set_flag(dest, pi, BGP_PATH_VALID); else { if (BGP_DEBUG(nht, NHT)) { - inet_ntop(pp->family, - &attr.evpn_overlay.gw_ip, - buf1, sizeof(buf1)); + inet_ntop(pp->family, &bre->gw_ip, buf1, + sizeof(buf1)); zlog_debug("%s: gateway IP NH unresolved", buf1); } bgp_path_info_unset_flag(dest, pi, BGP_PATH_VALID); } } else { - /* as it is an importation, change nexthop */ bgp_path_info_set_flag(dest, pi, BGP_PATH_ANNC_NH_SELF); } @@ -4690,7 +4697,6 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, { struct prefix_rd prd; struct prefix_evpn p = {}; - struct bgp_route_evpn evpn = {}; uint8_t ipaddr_len; uint8_t macaddr_len; /* holds the VNI(s) as in packet */ @@ -4792,11 +4798,11 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi, if (attr) bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, - &label[0], num_labels, 0, &evpn); + &label[0], num_labels, 0, NULL); else bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label[0], - num_labels, &evpn); + num_labels); goto done; fail: @@ -4886,8 +4892,7 @@ static int process_type3_route(struct peer *peer, afi_t afi, safi_t safi, 0, 0, NULL); else bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, - NULL); + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0); return 0; } @@ -4900,7 +4905,8 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, { struct prefix_rd prd; struct prefix_evpn p; - struct bgp_route_evpn evpn; + struct bgp_route_evpn *evpn = XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); uint8_t ippfx_len; uint32_t eth_tag; mpls_label_t label; /* holds the VNI as in the packet */ @@ -4930,12 +4936,9 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, p.prefixlen = EVPN_ROUTE_PREFIXLEN; p.prefix.route_type = BGP_EVPN_IP_PREFIX_ROUTE; - /* Additional information outside of prefix - ESI and GW IP */ - memset(&evpn, 0, sizeof(evpn)); - /* Fetch ESI overlay index */ if (attr) - memcpy(&evpn.eth_s_id, pfx, sizeof(esi_t)); + memcpy(&evpn->eth_s_id, pfx, sizeof(esi_t)); pfx += ESI_BYTES; /* Fetch Ethernet Tag. */ @@ -4962,16 +4965,16 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, SET_IPADDR_V4(&p.prefix.prefix_addr.ip); memcpy(&p.prefix.prefix_addr.ip.ipaddr_v4, pfx, 4); pfx += 4; - SET_IPADDR_V4(&evpn.gw_ip); - memcpy(&evpn.gw_ip.ipaddr_v4, pfx, 4); + SET_IPADDR_V4(&evpn->gw_ip); + memcpy(&evpn->gw_ip.ipaddr_v4, pfx, 4); pfx += 4; } else { SET_IPADDR_V6(&p.prefix.prefix_addr.ip); memcpy(&p.prefix.prefix_addr.ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN); pfx += IPV6_MAX_BYTELEN; - SET_IPADDR_V6(&evpn.gw_ip); - memcpy(&evpn.gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN); + SET_IPADDR_V6(&evpn->gw_ip); + memcpy(&evpn->gw_ip.ipaddr_v6, pfx, IPV6_MAX_BYTELEN); pfx += IPV6_MAX_BYTELEN; } @@ -4989,20 +4992,20 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, * An update containing a non-zero gateway IP and a non-zero ESI * at the same time is should be treated as withdraw */ - if (bgp_evpn_is_esi_valid(&evpn.eth_s_id) && - !ipaddr_is_zero(&evpn.gw_ip)) { + if (bgp_evpn_is_esi_valid(&evpn->eth_s_id) && + !ipaddr_is_zero(&evpn->gw_ip)) { flog_err(EC_BGP_EVPN_ROUTE_INVALID, "%s - Rx EVPN Type-5 ESI and gateway-IP both non-zero.", peer->host); is_valid_update = false; - } else if (bgp_evpn_is_esi_valid(&evpn.eth_s_id)) - evpn.type = OVERLAY_INDEX_ESI; - else if (!ipaddr_is_zero(&evpn.gw_ip)) - evpn.type = OVERLAY_INDEX_GATEWAY_IP; + } else if (bgp_evpn_is_esi_valid(&evpn->eth_s_id)) + evpn->type = OVERLAY_INDEX_ESI; + else if (!ipaddr_is_zero(&evpn->gw_ip)) + evpn->type = OVERLAY_INDEX_GATEWAY_IP; if (attr) { if (is_zero_mac(&attr->rmac) && - !bgp_evpn_is_esi_valid(&evpn.eth_s_id) && - ipaddr_is_zero(&evpn.gw_ip) && label == 0) { + !bgp_evpn_is_esi_valid(&evpn->eth_s_id) && + ipaddr_is_zero(&evpn->gw_ip) && label == 0) { flog_err(EC_BGP_EVPN_ROUTE_INVALID, "%s - Rx EVPN Type-5 ESI, gateway-IP, RMAC and label all zero", peer->host); @@ -5017,7 +5020,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, if (attr && is_valid_update) bgp_update(peer, (struct prefix *)&p, addpath_id, attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, - &label, 1, 0, &evpn); + &label, 1, 0, evpn); else { if (!is_valid_update) { char attr_str[BUFSIZ] = {0}; @@ -5029,8 +5032,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi, attr_str); } bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 1, - &evpn); + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, &label, 1); } return 0; @@ -5044,12 +5046,16 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, int len; char temp[16]; const struct evpn_addr *p_evpn_p; + struct bgp_route_evpn *bre = NULL; memset(&temp, 0, sizeof(temp)); if (p->family != AF_EVPN) return; p_evpn_p = &(p->u.prefix_evpn); + if (attr) + bre = bgp_attr_get_evpn_overlay(attr); + /* len denites the total len of IP and GW-IP in the route IP and GW-IP have to be both ipv4 or ipv6 */ @@ -5060,7 +5066,7 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, /* Prefix contains RD, ESI, EthTag, IP length, IP, GWIP and VNI */ stream_putc(s, 8 + 10 + 4 + 1 + len + 3); stream_put(s, prd->val, 8); - if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_ESI) + if (attr && bre && bre->type == OVERLAY_INDEX_ESI) stream_put(s, &attr->esi, sizeof(esi_t)); else stream_put(s, 0, sizeof(esi_t)); @@ -5070,15 +5076,11 @@ static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p, stream_put_ipv4(s, p_evpn_p->prefix_addr.ip.ipaddr_v4.s_addr); else stream_put(s, &p_evpn_p->prefix_addr.ip.ipaddr_v6, 16); - if (attr && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) { - const struct bgp_route_evpn *evpn_overlay = - bgp_attr_get_evpn_overlay(attr); - + if (attr && bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) { if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip)) - stream_put_ipv4(s, - evpn_overlay->gw_ip.ipaddr_v4.s_addr); + stream_put_ipv4(s, bre->gw_ip.ipaddr_v4.s_addr); else - stream_put(s, &(evpn_overlay->gw_ip.ipaddr_v6), 16); + stream_put(s, &(bre->gw_ip.ipaddr_v6), 16); } else { if (IS_IPADDR_V4(&p_evpn_p->prefix_addr.ip)) stream_put_ipv4(s, 0); diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c index d723a2b1be..f4528defc2 100644 --- a/bgpd/bgp_evpn_mh.c +++ b/bgpd/bgp_evpn_mh.c @@ -770,8 +770,7 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi, 0, 0, NULL); } else { bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, - NULL); + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0); } return 0; } @@ -1239,8 +1238,7 @@ int bgp_evpn_type1_route_process(struct peer *peer, afi_t afi, safi_t safi, 0, 0, NULL); } else { bgp_withdraw(peer, (struct prefix *)&p, addpath_id, afi, safi, - ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0, - NULL); + ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, &prd, NULL, 0); } return 0; } diff --git a/bgpd/bgp_flowspec.c b/bgpd/bgp_flowspec.c index 6165bf892e..bd04970fd5 100644 --- a/bgpd/bgp_flowspec.c +++ b/bgpd/bgp_flowspec.c @@ -195,7 +195,7 @@ int bgp_nlri_parse_flowspec(struct peer *peer, struct attr *attr, NULL, 0, 0, NULL); } else { bgp_withdraw(peer, &p, 0, afi, safi, ZEBRA_ROUTE_BGP, - BGP_ROUTE_NORMAL, NULL, NULL, 0, NULL); + BGP_ROUTE_NORMAL, NULL, NULL, 0); } XFREE(MTYPE_TMP, temp); diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c index 839437e120..ad40fef62c 100644 --- a/bgpd/bgp_label.c +++ b/bgpd/bgp_label.c @@ -576,7 +576,7 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr, } else { bgp_withdraw(peer, &p, addpath_id, packet->afi, SAFI_UNICAST, ZEBRA_ROUTE_BGP, - BGP_ROUTE_NORMAL, NULL, &label, 1, NULL); + BGP_ROUTE_NORMAL, NULL, &label, 1); } } diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c index 31e84d13c4..bc44a212cd 100644 --- a/bgpd/bgp_mac.c +++ b/bgpd/bgp_mac.c @@ -143,7 +143,6 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer, const struct prefix *p = bgp_dest_get_prefix(dest); struct prefix_evpn *pevpn = (struct prefix_evpn *)dest; struct prefix_rd prd; - struct bgp_route_evpn *evpn; if (pevpn->family == AF_EVPN && pevpn->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE @@ -195,12 +194,10 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer, continue; } - memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr), - sizeof(evpn)); bgp_update(peer, p, pi->addpath_rx_id, pi->attr, AFI_L2VPN, SAFI_EVPN, ZEBRA_ROUTE_BGP, - BGP_ROUTE_NORMAL, &prd, label_pnt, - num_labels, 1, evpn); + BGP_ROUTE_NORMAL, &prd, label_pnt, num_labels, + 1, bgp_attr_get_evpn_overlay(pi->attr)); } } } diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c index c1804fb70a..c2599ade58 100644 --- a/bgpd/bgp_memory.c +++ b/bgpd/bgp_memory.c @@ -135,3 +135,5 @@ DEFINE_MTYPE(BGPD, EVPN_REMOTE_IP, "BGP EVPN Remote IP hash entry"); DEFINE_MTYPE(BGPD, BGP_NOTIFICATION, "BGP Notification Message"); DEFINE_MTYPE(BGPD, BGP_SOFT_VERSION, "Software Version"); + +DEFINE_MTYPE(BGPD, BGP_EVPN_OVERLAY, "BGP EVPN Overlay"); diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h index 4ae49a2c17..1f76945da3 100644 --- a/bgpd/bgp_memory.h +++ b/bgpd/bgp_memory.h @@ -134,4 +134,6 @@ DECLARE_MTYPE(BGP_NOTIFICATION); DECLARE_MTYPE(BGP_SOFT_VERSION); +DECLARE_MTYPE(BGP_EVPN_OVERLAY); + #endif /* _QUAGGA_BGP_MEMORY_H */ diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c index b03171b4c8..9de1c5f4c2 100644 --- a/bgpd/bgp_mplsvpn.c +++ b/bgpd/bgp_mplsvpn.c @@ -245,7 +245,7 @@ int bgp_nlri_parse_vpn(struct peer *peer, struct attr *attr, } else { bgp_withdraw(peer, &p, addpath_id, packet->afi, SAFI_MPLS_VPN, ZEBRA_ROUTE_BGP, - BGP_ROUTE_NORMAL, &prd, &label, 1, NULL); + BGP_ROUTE_NORMAL, &prd, &label, 1); } } /* Packet length consistency check. */ diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c index 67e7463fe4..8da7521ffc 100644 --- a/bgpd/bgp_nht.c +++ b/bgpd/bgp_nht.c @@ -1313,11 +1313,13 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc) bool bnc_is_valid_nexthop = false; bool path_valid = false; + struct bgp_route_evpn *bre = + bgp_attr_get_evpn_overlay(path->attr); if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED && bgp_path_info_num_labels(path) && - (path->attr->evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP)) { + !(bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)) { bnc_is_valid_nexthop = bgp_isvalid_nexthop_for_l3vpn(bnc, path) ? true diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c index 5b5c0fa6d4..9cc9803175 100644 --- a/bgpd/bgp_route.c +++ b/bgpd/bgp_route.c @@ -4608,10 +4608,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * will not be interned. In which case, it is ok to update the * attr->evpn_overlay, so that, this can be stored in adj_in. */ - if ((afi == AFI_L2VPN) && evpn) { - memcpy(&attr->evpn_overlay, evpn, - sizeof(struct bgp_route_evpn)); - } + if ((afi == AFI_L2VPN) && evpn) + bgp_attr_set_evpn_overlay(attr, evpn); bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels); } @@ -4773,8 +4771,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, * evpn to new_atr.evpn_overlay before it is interned. */ if (soft_reconfig && (afi == AFI_L2VPN) && evpn) - memcpy(&new_attr.evpn_overlay, evpn, - sizeof(struct bgp_route_evpn)); + bgp_attr_set_evpn_overlay(&new_attr, evpn); /* Apply incoming route-map. * NB: new_attr may now contain newly allocated values from route-map @@ -5450,7 +5447,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id, void bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id, afi_t afi, safi_t safi, int type, int sub_type, struct prefix_rd *prd, mpls_label_t *label, - uint8_t num_labels, struct bgp_route_evpn *evpn) + uint8_t num_labels) { struct bgp *bgp; char pfx_buf[BGP_PRD_PATH_STRLEN]; @@ -5679,7 +5676,7 @@ static void bgp_soft_reconfig_table_update(struct peer *peer, struct bgp_path_info *pi; uint8_t num_labels; mpls_label_t *label_pnt; - struct bgp_route_evpn evpn; + struct bgp_route_evpn *bre = NULL; for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) if (pi->peer == peer) @@ -5687,15 +5684,13 @@ static void bgp_soft_reconfig_table_update(struct peer *peer, num_labels = ain->labels ? ain->labels->num_labels : 0; label_pnt = num_labels ? &ain->labels->label[0] : NULL; + if (pi) - memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr), - sizeof(evpn)); - else - memset(&evpn, 0, sizeof(evpn)); + bre = bgp_attr_get_evpn_overlay(pi->attr); bgp_update(peer, bgp_dest_get_prefix(dest), ain->addpath_rx_id, ain->attr, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, prd, - label_pnt, num_labels, 1, &evpn); + label_pnt, num_labels, 1, bre); } static void bgp_soft_reconfig_table(struct peer *peer, afi_t afi, safi_t safi, @@ -6614,7 +6609,7 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr, else bgp_withdraw(peer, &p, addpath_id, afi, safi, ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, - NULL, 0, NULL); + NULL, 0); /* Do not send BGP notification twice when maximum-prefix count * overflow. */ @@ -6745,15 +6740,25 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p, if (afi == AFI_L2VPN) { if (bgp_static->gatewayIp.family == AF_INET) { - SET_IPADDR_V4(&attr.evpn_overlay.gw_ip); - memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v4, + struct bgp_route_evpn *bre = + XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); + + SET_IPADDR_V4(&bre->gw_ip); + memcpy(&bre->gw_ip.ipaddr_v4, &bgp_static->gatewayIp.u.prefix4, IPV4_MAX_BYTELEN); + bgp_attr_set_evpn_overlay(&attr, bre); } else if (bgp_static->gatewayIp.family == AF_INET6) { - SET_IPADDR_V6(&attr.evpn_overlay.gw_ip); - memcpy(&attr.evpn_overlay.gw_ip.ipaddr_v6, + struct bgp_route_evpn *bre = + XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); + + SET_IPADDR_V6(&bre->gw_ip); + memcpy(&bre->gw_ip.ipaddr_v6, &bgp_static->gatewayIp.u.prefix6, IPV6_MAX_BYTELEN); + bgp_attr_set_evpn_overlay(&attr, bre); } memcpy(&attr.esi, bgp_static->eth_s_id, sizeof(esi_t)); if (bgp_static->encap_tunneltype == BGP_ENCAP_TYPE_VXLAN) { @@ -10114,6 +10119,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, json_object *json_path = NULL; json_object *json_nexthop = NULL; json_object *json_overlay = NULL; + struct bgp_route_evpn *bre = NULL; if (!path->extra) return; @@ -10179,12 +10185,14 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p, } } - const struct bgp_route_evpn *eo = bgp_attr_get_evpn_overlay(attr); - - if (!json_path) - vty_out(vty, "/%pIA", &eo->gw_ip); - else - json_object_string_addf(json_overlay, "gw", "%pIA", &eo->gw_ip); + bre = bgp_attr_get_evpn_overlay(attr); + if (bre) { + if (!json_path) + vty_out(vty, "/%pIA", &bre->gw_ip); + else + json_object_string_addf(json_overlay, "gw", "%pIA", + &bre->gw_ip); + } if (bgp_attr_get_ecommunity(attr)) { char *mac = NULL; @@ -10519,6 +10527,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, mpls_label_t label = MPLS_INVALID_LABEL; struct bgp_path_info *bpi_ultimate = bgp_get_imported_bpi_ultimate(path); + struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr); if (json_paths) { json_path = json_object_new_object(); @@ -10545,12 +10554,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn, } } - if (safi == SAFI_EVPN - && attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) { + if (safi == SAFI_EVPN && bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) { char gwip_buf[INET6_ADDRSTRLEN]; - ipaddr2str(&attr->evpn_overlay.gw_ip, gwip_buf, - sizeof(gwip_buf)); + ipaddr2str(&bre->gw_ip, gwip_buf, sizeof(gwip_buf)); if (json_paths) json_object_string_add(json_path, "gatewayIP", diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h index 89449ac5b9..5b433b5558 100644 --- a/bgpd/bgp_route.h +++ b/bgpd/bgp_route.h @@ -798,8 +798,7 @@ extern void bgp_update(struct peer *peer, const struct prefix *p, extern void bgp_withdraw(struct peer *peer, const struct prefix *p, uint32_t addpath_id, afi_t afi, safi_t safi, int type, int sub_type, struct prefix_rd *prd, - mpls_label_t *label, uint8_t num_labels, - struct bgp_route_evpn *evpn); + mpls_label_t *label, uint8_t num_labels); /* for bgp_nexthop and bgp_damp */ extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest, diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c index 3ba368aaf7..79c61e2ee2 100644 --- a/bgpd/bgp_routemap.c +++ b/bgpd/bgp_routemap.c @@ -1236,6 +1236,8 @@ route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object) struct ipaddr *gw_ip = rule; struct bgp_path_info *path; struct prefix_evpn *evp; + struct bgp_route_evpn *bre = XCALLOC(MTYPE_BGP_EVPN_OVERLAY, + sizeof(struct bgp_route_evpn)); if (prefix->family != AF_EVPN) return RMAP_OKAY; @@ -1251,9 +1253,9 @@ route_set_evpn_gateway_ip(void *rule, const struct prefix *prefix, void *object) path = object; /* Set gateway-ip value. */ - path->attr->evpn_overlay.type = OVERLAY_INDEX_GATEWAY_IP; - memcpy(&path->attr->evpn_overlay.gw_ip, &gw_ip->ip.addr, - IPADDRSZ(gw_ip)); + bre->type = OVERLAY_INDEX_GATEWAY_IP; + memcpy(&bre->gw_ip, &gw_ip->ip.addr, IPADDRSZ(gw_ip)); + bgp_attr_set_evpn_overlay(path->attr, bre); return RMAP_OKAY; } diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c index 12feac8353..0f47388389 100644 --- a/bgpd/bgp_updgrp_packet.c +++ b/bgpd/bgp_updgrp_packet.c @@ -880,7 +880,8 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp) bgp_debug_rdpfxpath2str(afi, safi, prd, dest_p, label_pnt, num_labels, addpath_capable, addpath_tx_id, - &adv->baa->attr->evpn_overlay, + bgp_attr_get_evpn_overlay( + adv->baa->attr), pfx_buf, sizeof(pfx_buf)); zlog_debug("u%" PRIu64 ":s%" PRIu64 " send UPDATE %s", subgrp->update_group->id, subgrp->id, diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index 006d46d843..52c5f5129d 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -1128,6 +1128,8 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, struct attr *attr, bool is_evpn, struct zapi_nexthop *api_nh) { + struct bgp_route_evpn *bre = bgp_attr_get_evpn_overlay(attr); + api_nh->gate.ipv4 = *nexthop; api_nh->vrf_id = nh_bgp->vrf_id; @@ -1144,7 +1146,7 @@ static bool update_ipv4nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, * treat the nexthop as NEXTHOP_TYPE_IPV4 * Else, mark the nexthop as onlink. */ - if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) + if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) api_nh->type = NEXTHOP_TYPE_IPV4; else { api_nh->type = NEXTHOP_TYPE_IPV4_IFINDEX; @@ -1170,9 +1172,11 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, struct zapi_nexthop *api_nh) { struct attr *attr; + struct bgp_route_evpn *bre; attr = pi->attr; api_nh->vrf_id = nh_bgp->vrf_id; + bre = bgp_attr_get_evpn_overlay(attr); if (attr->nh_type == NEXTHOP_TYPE_BLACKHOLE) { api_nh->type = attr->nh_type; @@ -1183,7 +1187,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp, * treat the nexthop as NEXTHOP_TYPE_IPV4 * Else, mark the nexthop as onlink. */ - if (attr->evpn_overlay.type == OVERLAY_INDEX_GATEWAY_IP) + if (bre && bre->type == OVERLAY_INDEX_GATEWAY_IP) api_nh->type = NEXTHOP_TYPE_IPV6; else { api_nh->type = NEXTHOP_TYPE_IPV6_IFINDEX; @@ -1281,6 +1285,7 @@ static void bgp_zebra_announce_parse_nexthop( uint32_t ttl = 0; uint32_t bos = 0; uint32_t exp = 0; + struct bgp_route_evpn *bre = NULL; /* Determine if we're doing weighted ECMP or not */ do_wt_ecmp = bgp_path_info_mpath_chkwtd(bgp, info); @@ -1395,6 +1400,7 @@ static void bgp_zebra_announce_parse_nexthop( } is_evpn = !!CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN); + bre = bgp_attr_get_evpn_overlay(mpinfo->attr); /* Did we get proper nexthop info to update zebra? */ if (!nh_updated) @@ -1430,9 +1436,7 @@ static void bgp_zebra_announce_parse_nexthop( api_nh->labels[0] = nh_label; } - if (is_evpn - && mpinfo->attr->evpn_overlay.type - != OVERLAY_INDEX_GATEWAY_IP) + if (is_evpn && !(bre && bre->type == OVERLAY_INDEX_GATEWAY_IP)) memcpy(&api_nh->rmac, &(mpinfo->attr->rmac), sizeof(struct ethaddr)); diff --git a/bgpd/rfapi/vnc_export_bgp.c b/bgpd/rfapi/vnc_export_bgp.c index 7decb75782..4de2306609 100644 --- a/bgpd/rfapi/vnc_export_bgp.c +++ b/bgpd/rfapi/vnc_export_bgp.c @@ -388,7 +388,7 @@ void vnc_direct_bgp_del_route_ce(struct bgp *bgp, struct agg_node *rn, bgp_withdraw(bpi->peer, p, 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, 0, NULL); /* tag not used for unicast */ + NULL, 0); /* tag not used for unicast */ } static void vnc_direct_bgp_vpn_enable_ce(struct bgp *bgp, afi_t afi) @@ -473,16 +473,14 @@ static void vnc_direct_bgp_vpn_disable_ce(struct bgp *bgp, afi_t afi) if (ri->type == ZEBRA_ROUTE_VNC_DIRECT && ri->sub_type == BGP_ROUTE_REDISTRIBUTE) { - - bgp_withdraw( - ri->peer, bgp_dest_get_prefix(dest), - 0, /* addpath_id */ - AFI_IP, SAFI_UNICAST, - ZEBRA_ROUTE_VNC_DIRECT, - BGP_ROUTE_REDISTRIBUTE, - NULL, /* RD not used for unicast */ - NULL, 0, - NULL); /* tag not used for unicast */ + bgp_withdraw(ri->peer, bgp_dest_get_prefix(dest), + 0, /* addpath_id */ + AFI_IP, SAFI_UNICAST, + ZEBRA_ROUTE_VNC_DIRECT, + BGP_ROUTE_REDISTRIBUTE, + NULL, /* RD not used for unicast */ + NULL, + 0); /* tag not used for unicast */ } } } @@ -863,9 +861,8 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp, 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, - NULL, /* RD not used for unicast */ - NULL, 0, - NULL); /* tag not used for unicast */ + NULL, /* RD not used for unicast */ + NULL, 0); /* tag not used for unicast */ /* * yuck! * - but consistent with rest of function @@ -892,9 +889,8 @@ void vnc_direct_bgp_del_prefix(struct bgp *bgp, 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, - NULL, /* RD not used for unicast */ - NULL, 0, - NULL); /* tag not used for unicast */ + NULL, /* RD not used for unicast */ + NULL, 0); /* tag not used for unicast */ } } } @@ -1125,13 +1121,13 @@ void vnc_direct_bgp_del_nve(struct bgp *bgp, struct rfapi_descriptor *rfd) continue; bgp_withdraw(irfd->peer, p, /* prefix */ - 0, /* addpath_id */ + 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, 0, NULL); /* tag not + NULL, 0); /* tag not used for unicast */ } @@ -1359,7 +1355,7 @@ static void vnc_direct_del_rn_group_rd(struct bgp *bgp, 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, 0, NULL); /* tag not used for unicast */ + NULL, 0); /* tag not used for unicast */ return; } @@ -1471,16 +1467,15 @@ static void vnc_direct_bgp_unexport_table(afi_t afi, struct agg_table *rt, for (ALL_LIST_ELEMENTS_RO(nve_list, hln, irfd)) { - bgp_withdraw(irfd->peer, agg_node_get_prefix(rn), - 0, /* addpath_id */ + 0, /* addpath_id */ afi, SAFI_UNICAST, ZEBRA_ROUTE_VNC_DIRECT, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, 0, NULL); /* tag not + NULL, 0); /* tag not used for unicast, EVPN @@ -1715,8 +1710,7 @@ static void vncExportWithdrawTimer(struct event *t) bgp_withdraw(eti->peer, p, 0, /* addpath_id */ family2afi(p->family), SAFI_UNICAST, eti->type, eti->subtype, NULL, /* RD not used for unicast */ - NULL, 0, - NULL); /* tag not used for unicast, EVPN neither */ + NULL, 0); /* tag not used for unicast, EVPN neither */ /* * Free the eti @@ -2001,7 +1995,7 @@ void vnc_direct_bgp_rh_vpn_disable(struct bgp *bgp, afi_t afi) ZEBRA_ROUTE_VNC_DIRECT_RH, BGP_ROUTE_REDISTRIBUTE, NULL, /* RD not used for unicast */ - NULL, 0, NULL); /* tag not used for + NULL, 0); /* tag not used for unicast, EVPN neither */ }