attr->mm_seqnum = bgp_attr_mac_mobility_seqnum(attr, &sticky);
attr->sticky = sticky;
+ /* Extract the Rmac, if any */
+ bgp_attr_rmac(attr, &attr->rmac);
+
return BGP_ATTR_PARSE_PROCEED;
}
/* EVPN MAC Mobility sequence number, if any. */
u_int32_t mm_seqnum;
+
+ /* EVPN local router-mac */
+ struct ethaddr rmac;
};
/* rmap_change_flags definition */
return prefix_mac2str((struct ethaddr *)en, NULL, 0);
}
+/* Fetch router-mac from extended community */
+void bgp_attr_rmac(struct attr *attr,
+ struct ethaddr *rmac)
+{
+ int i = 0;
+ struct ecommunity *ecom;
+
+ ecom = attr->ecommunity;
+ if (!ecom || !ecom->size)
+ return;
+
+ /* If there is a router mac extended community, set RMAC in attr */
+ for (i = 0; i < ecom->size; i++) {
+ u_char *pnt = NULL;
+ u_char type = 0;
+ u_char sub_type = 0;
+
+ pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
+ type = *pnt++;
+ sub_type = *pnt++;
+
+ if (!(type == ECOMMUNITY_ENCODE_EVPN &&
+ sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
+ continue;
+
+ memcpy(rmac, pnt, ETH_ALEN);
+ }
+}
+
/*
* Fetch and return the sequence number from MAC Mobility extended
* community, if present, else 0.
struct ethaddr *routermac);
extern int bgp_build_evpn_prefix(int type, uint32_t eth_tag,
struct prefix *dst);
-
+extern void bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac);
extern u_int32_t bgp_attr_mac_mobility_seqnum(struct attr *attr,
u_char *sticky);
} else if (type == ECOMMUNITY_ENCODE_EVPN) {
if (filter == ECOMMUNITY_ROUTE_TARGET)
continue;
- if (*pnt == ECOMMUNITY_SITE_ORIGIN) {
- char macaddr[6];
+ if (*pnt == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC) {
+ struct ethaddr rmac;
pnt++;
- memcpy(&macaddr, pnt, 6);
+ memcpy(&rmac, pnt, ETH_ALEN);
len = sprintf(
str_buf + str_pnt,
- "EVPN:%02x:%02x:%02x:%02x:%02x:%02x",
- (uint8_t)macaddr[0],
- (uint8_t)macaddr[1],
- (uint8_t)macaddr[2],
- (uint8_t)macaddr[3],
- (uint8_t)macaddr[4],
- (uint8_t)macaddr[5]);
+ "Rmac:%02x:%02x:%02x:%02x:%02x:%02x",
+ (uint8_t)rmac.octet[0],
+ (uint8_t)rmac.octet[1],
+ (uint8_t)rmac.octet[2],
+ (uint8_t)rmac.octet[3],
+ (uint8_t)rmac.octet[4],
+ (uint8_t)rmac.octet[5]);
} else if (*pnt
== ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY) {
u_int32_t seqnum;
{
struct ecommunity ecom_encap;
struct ecommunity ecom_sticky;
+ struct ecommunity ecom_rmac;
struct ecommunity_val eval;
struct ecommunity_val eval_sticky;
+ struct ecommunity_val eval_rmac;
bgp_encap_types tnl_type;
struct listnode *node, *nnode;
struct ecommunity *ecom;
ecommunity_merge(attr->ecommunity, &ecom_sticky);
}
+ if (!is_zero_mac(&attr->rmac)) {
+ memset(&ecom_rmac, 0, sizeof(ecom_rmac));
+ encode_rmac_extcomm(&eval_rmac, &attr->rmac);
+ ecom_rmac.size = 1;
+ ecom_rmac.val = (uint8_t *)eval_rmac.val;
+ attr->ecommunity = ecommunity_merge(attr->ecommunity,
+ &ecom_rmac);
+ }
+
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES);
}
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr.sticky = CHECK_FLAG(flags, ZEBRA_MAC_TYPE_STICKY) ? 1 : 0;
+ bgpevpn_get_rmac(vpn, &attr.rmac);
/* Set up RT and ENCAP extended community. */
build_evpn_route_extcomm(vpn, &attr);
attr.nexthop = vpn->originator_ip;
attr.mp_nexthop_global_in = vpn->originator_ip;
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+ bgpevpn_get_rmac(vpn, &attr.rmac);
attr_sticky.nexthop = vpn->originator_ip;
attr_sticky.mp_nexthop_global_in = vpn->originator_ip;
attr_sticky.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
attr_sticky.sticky = 1;
+ bgpevpn_get_rmac(vpn, &attr_sticky.rmac);
/* Set up RT, ENCAP and sticky MAC extended community. */
build_evpn_route_extcomm(vpn, &attr);
return vni;
}
+static inline void encode_rmac_extcomm(struct ecommunity_val *eval,
+ struct ethaddr *rmac)
+{
+ memset(eval, 0, sizeof(*eval));
+ eval->val[0] = ECOMMUNITY_ENCODE_EVPN;
+ eval->val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
+ memcpy(&eval->val[2], rmac, ETH_ALEN);
+}
+
static inline void encode_mac_mobility_extcomm(int static_mac, u_int32_t seq,
struct ecommunity_val *eval)
{