#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)
{
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;
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
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) {
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);
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);
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. */
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);
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
transit_init();
encap_init();
srv6_init();
+ evpn_overlay_init();
}
void bgp_attr_finish(void)
transit_finish();
encap_finish();
srv6_finish();
+ evpn_overlay_finish();
}
/* Make attribute packet. */
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;
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 *
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)));
* 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;
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);
}
}
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);
* 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);
}
}
}
/* 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);
}
{
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 */
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:
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;
}
{
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 */
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. */
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;
}
* 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);
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};
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;
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
*/
/* 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));
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);
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;
}
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;
}
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);
} 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);
}
}
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
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));
}
}
}
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");
DECLARE_MTYPE(BGP_SOFT_VERSION);
+DECLARE_MTYPE(BGP_EVPN_OVERLAY);
+
#endif /* _QUAGGA_BGP_MEMORY_H */
} 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. */
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
* 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);
}
* 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
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];
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)
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,
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. */
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) {
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;
}
}
- 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;
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();
}
}
- 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",
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,
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;
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;
}
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,
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;
* 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;
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;
* 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;
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);
}
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)
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));
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)
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 */
}
}
}
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
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 */
}
}
}
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 */
}
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;
}
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
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
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 */
}