summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bgpd/bgp_attr.c3
-rw-r--r--bgpd/bgp_attr.h3
-rw-r--r--bgpd/bgp_attr_evpn.c29
-rw-r--r--bgpd/bgp_attr_evpn.h2
-rw-r--r--bgpd/bgp_ecommunity.c20
-rw-r--r--bgpd/bgp_evpn.c14
-rw-r--r--bgpd/bgp_evpn_private.h9
7 files changed, 69 insertions, 11 deletions
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index e80889500f..da6042d340 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -1879,6 +1879,9 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
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;
}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index f694f01adb..1de1bee0f9 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -182,6 +182,9 @@ struct attr {
/* EVPN MAC Mobility sequence number, if any. */
u_int32_t mm_seqnum;
+
+ /* EVPN local router-mac */
+ struct ethaddr rmac;
};
/* rmap_change_flags definition */
diff --git a/bgpd/bgp_attr_evpn.c b/bgpd/bgp_attr_evpn.c
index 300c9ddb50..eaa4e329d4 100644
--- a/bgpd/bgp_attr_evpn.c
+++ b/bgpd/bgp_attr_evpn.c
@@ -105,6 +105,35 @@ char *ecom_mac2str(char *ecom_mac)
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.
diff --git a/bgpd/bgp_attr_evpn.h b/bgpd/bgp_attr_evpn.h
index 15d9e126e4..8b55cb3002 100644
--- a/bgpd/bgp_attr_evpn.h
+++ b/bgpd/bgp_attr_evpn.h
@@ -59,7 +59,7 @@ extern void bgp_add_routermac_ecom(struct attr *attr,
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);
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index e19f516505..9caf38d569 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -695,19 +695,19 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
} 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;
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index b625297ac1..64b2501705 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -433,8 +433,10 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr)
{
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;
@@ -473,6 +475,15 @@ static void build_evpn_route_extcomm(struct bgpevpn *vpn, struct attr *attr)
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);
}
@@ -843,6 +854,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
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);
@@ -989,10 +1001,12 @@ static int update_all_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
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);
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index e11f99f099..b983a00a76 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -222,6 +222,15 @@ static inline vni_t label2vni(mpls_label_t *label)
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)
{