1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Ethernet-VPN Attribute handling file
3 * Copyright (C) 2016 6WIND
16 #include "bgpd/bgpd.h"
17 #include "bgpd/bgp_attr.h"
18 #include "bgpd/bgp_route.h"
19 #include "bgpd/bgp_attr_evpn.h"
20 #include "bgpd/bgp_ecommunity.h"
21 #include "bgpd/bgp_evpn.h"
22 #include "bgpd/bgp_evpn_private.h"
24 bool bgp_route_evpn_same(const struct bgp_route_evpn
*e1
,
25 const struct bgp_route_evpn
*e2
)
27 return (e1
->type
== e2
->type
&&
28 !memcmp(&(e1
->eth_s_id
), &(e2
->eth_s_id
), sizeof(esi_t
)) &&
29 !ipaddr_cmp(&(e1
->gw_ip
), &(e2
->gw_ip
)));
32 void bgp_add_routermac_ecom(struct attr
*attr
, struct ethaddr
*routermac
)
34 struct ecommunity_val routermac_ecom
;
35 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
37 memset(&routermac_ecom
, 0, sizeof(routermac_ecom
));
38 routermac_ecom
.val
[0] = ECOMMUNITY_ENCODE_EVPN
;
39 routermac_ecom
.val
[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
;
40 memcpy(&routermac_ecom
.val
[2], routermac
->octet
, ETH_ALEN
);
42 bgp_attr_set_ecommunity(attr
, ecommunity_new());
43 ecomm
= bgp_attr_get_ecommunity(attr
);
45 ecommunity_add_val(ecomm
, &routermac_ecom
, false, false);
46 ecommunity_str(ecomm
);
50 * returns 1 on success, 0 otherwise
51 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
52 * if id is null, check only is done
54 bool str2esi(const char *str
, esi_t
*id
)
56 unsigned int a
[ESI_BYTES
];
61 if (sscanf(str
, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a
+ 0, a
+ 1,
62 a
+ 2, a
+ 3, a
+ 4, a
+ 5, a
+ 6, a
+ 7, a
+ 8, a
+ 9)
64 /* error in incoming str length */
67 /* valid mac address */
70 for (i
= 0; i
< ESI_BYTES
; ++i
)
71 id
->val
[i
] = a
[i
] & 0xff;
75 char *ecom_mac2str(char *ecom_mac
)
82 return prefix_mac2str((struct ethaddr
*)en
, NULL
, 0);
85 /* Fetch router-mac from extended community */
86 bool bgp_attr_rmac(struct attr
*attr
, struct ethaddr
*rmac
)
89 struct ecommunity
*ecom
;
91 ecom
= bgp_attr_get_ecommunity(attr
);
92 if (!ecom
|| !ecom
->size
)
95 /* If there is a router mac extended community, set RMAC in attr */
96 for (i
= 0; i
< ecom
->size
; i
++) {
101 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
105 if (!(type
== ECOMMUNITY_ENCODE_EVPN
106 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
))
109 memcpy(rmac
, pnt
, ETH_ALEN
);
116 * return true if attr contains default gw extended community
118 uint8_t bgp_attr_default_gw(struct attr
*attr
)
120 struct ecommunity
*ecom
;
123 ecom
= bgp_attr_get_ecommunity(attr
);
124 if (!ecom
|| !ecom
->size
)
127 /* If there is a default gw extendd community return true otherwise
129 for (i
= 0; i
< ecom
->size
; i
++) {
131 uint8_t type
, sub_type
;
133 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
137 if ((type
== ECOMMUNITY_ENCODE_OPAQUE
138 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_DEF_GW
))
146 * Fetch and return the DF preference and algorithm from
147 * DF election extended community, if present, else 0.
149 uint16_t bgp_attr_df_pref_from_ec(struct attr
*attr
, uint8_t *alg
)
151 struct ecommunity
*ecom
;
153 uint16_t df_pref
= 0;
155 *alg
= EVPN_MH_DF_ALG_SERVICE_CARVING
;
156 ecom
= bgp_attr_get_ecommunity(attr
);
157 if (!ecom
|| !ecom
->size
)
160 for (i
= 0; i
< ecom
->size
; i
++) {
162 uint8_t type
, sub_type
;
164 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
167 if (!(type
== ECOMMUNITY_ENCODE_EVPN
168 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION
))
171 *alg
= (*pnt
++) & ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS
;
174 pnt
= ptr_get_be16(pnt
, &df_pref
);
175 (void)pnt
; /* consume value */
183 * Fetch and return the sequence number from MAC Mobility extended
184 * community, if present, else 0.
186 uint32_t bgp_attr_mac_mobility_seqnum(struct attr
*attr
, uint8_t *sticky
)
188 struct ecommunity
*ecom
;
192 ecom
= bgp_attr_get_ecommunity(attr
);
193 if (!ecom
|| !ecom
->size
)
196 /* If there is a MAC Mobility extended community, return its
198 * TODO: RFC is silent on handling of multiple MAC mobility extended
199 * communities for the same route. We will bail out upon the first
202 for (i
= 0; i
< ecom
->size
; i
++) {
204 uint8_t type
, sub_type
;
207 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
210 if (!(type
== ECOMMUNITY_ENCODE_EVPN
211 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
))
215 if (flags
& ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY
)
221 pnt
= ptr_get_be32(pnt
, &seq_num
);
222 (void)pnt
; /* consume value */
230 * return true if attr contains router flag extended community
232 void bgp_attr_evpn_na_flag(struct attr
*attr
,
233 uint8_t *router_flag
, bool *proxy
)
235 struct ecommunity
*ecom
;
239 ecom
= bgp_attr_get_ecommunity(attr
);
240 if (!ecom
|| !ecom
->size
)
243 /* If there is a evpn na extendd community set router_flag */
244 for (i
= 0; i
< ecom
->size
; i
++) {
246 uint8_t type
, sub_type
;
248 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
252 if (type
== ECOMMUNITY_ENCODE_EVPN
&&
253 sub_type
== ECOMMUNITY_EVPN_SUBTYPE_ND
) {
256 if (val
& ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG
)
259 if (val
& ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG
)
267 /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
268 extern int bgp_build_evpn_prefix(int evpn_type
, uint32_t eth_tag
,
271 struct evpn_addr
*p_evpn_p
;
273 struct prefix
*src
= &p2
;
275 if (!dst
|| dst
->family
== 0)
277 /* store initial prefix in src */
278 prefix_copy(src
, dst
);
279 memset(dst
, 0, sizeof(struct prefix
));
280 p_evpn_p
= &(dst
->u
.prefix_evpn
);
281 dst
->family
= AF_EVPN
;
282 p_evpn_p
->route_type
= evpn_type
;
283 if (evpn_type
== BGP_EVPN_IP_PREFIX_ROUTE
) {
284 p_evpn_p
->prefix_addr
.eth_tag
= eth_tag
;
285 p_evpn_p
->prefix_addr
.ip_prefix_length
= p2
.prefixlen
;
286 if (src
->family
== AF_INET
) {
287 SET_IPADDR_V4(&p_evpn_p
->prefix_addr
.ip
);
288 memcpy(&p_evpn_p
->prefix_addr
.ip
.ipaddr_v4
,
290 sizeof(struct in_addr
));
291 dst
->prefixlen
= (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
293 SET_IPADDR_V6(&p_evpn_p
->prefix_addr
.ip
);
294 memcpy(&p_evpn_p
->prefix_addr
.ip
.ipaddr_v6
,
296 sizeof(struct in6_addr
));
297 dst
->prefixlen
= (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6
;