1 /* Ethernet-VPN Attribute handling file
2 * Copyright (C) 2016 6WIND
4 * This file is part of FRRouting.
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
31 #include "bgpd/bgpd.h"
32 #include "bgpd/bgp_attr.h"
33 #include "bgpd/bgp_route.h"
34 #include "bgpd/bgp_attr_evpn.h"
35 #include "bgpd/bgp_ecommunity.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
39 bool bgp_route_evpn_same(const struct bgp_route_evpn
*e1
,
40 const struct bgp_route_evpn
*e2
)
42 return (e1
->type
== e2
->type
&&
43 !memcmp(&(e1
->eth_s_id
), &(e2
->eth_s_id
), sizeof(esi_t
)) &&
44 !ipaddr_cmp(&(e1
->gw_ip
), &(e2
->gw_ip
)));
47 void bgp_add_routermac_ecom(struct attr
*attr
, struct ethaddr
*routermac
)
49 struct ecommunity_val routermac_ecom
;
50 struct ecommunity
*ecomm
= bgp_attr_get_ecommunity(attr
);
52 memset(&routermac_ecom
, 0, sizeof(routermac_ecom
));
53 routermac_ecom
.val
[0] = ECOMMUNITY_ENCODE_EVPN
;
54 routermac_ecom
.val
[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
;
55 memcpy(&routermac_ecom
.val
[2], routermac
->octet
, ETH_ALEN
);
57 bgp_attr_set_ecommunity(attr
, ecommunity_new());
58 ecomm
= bgp_attr_get_ecommunity(attr
);
60 ecommunity_add_val(ecomm
, &routermac_ecom
, false, false);
61 ecommunity_str(ecomm
);
65 * returns 1 on success, 0 otherwise
66 * format accepted: AA:BB:CC:DD:EE:FF:GG:HH:II:JJ
67 * if id is null, check only is done
69 bool str2esi(const char *str
, esi_t
*id
)
71 unsigned int a
[ESI_BYTES
];
76 if (sscanf(str
, "%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x", a
+ 0, a
+ 1,
77 a
+ 2, a
+ 3, a
+ 4, a
+ 5, a
+ 6, a
+ 7, a
+ 8, a
+ 9)
79 /* error in incoming str length */
82 /* valid mac address */
85 for (i
= 0; i
< ESI_BYTES
; ++i
)
86 id
->val
[i
] = a
[i
] & 0xff;
90 char *ecom_mac2str(char *ecom_mac
)
97 return prefix_mac2str((struct ethaddr
*)en
, NULL
, 0);
100 /* Fetch router-mac from extended community */
101 bool bgp_attr_rmac(struct attr
*attr
, struct ethaddr
*rmac
)
104 struct ecommunity
*ecom
;
106 ecom
= bgp_attr_get_ecommunity(attr
);
107 if (!ecom
|| !ecom
->size
)
110 /* If there is a router mac extended community, set RMAC in attr */
111 for (i
= 0; i
< ecom
->size
; i
++) {
114 uint8_t sub_type
= 0;
116 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
120 if (!(type
== ECOMMUNITY_ENCODE_EVPN
121 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC
))
124 memcpy(rmac
, pnt
, ETH_ALEN
);
131 * return true if attr contains default gw extended community
133 uint8_t bgp_attr_default_gw(struct attr
*attr
)
135 struct ecommunity
*ecom
;
138 ecom
= bgp_attr_get_ecommunity(attr
);
139 if (!ecom
|| !ecom
->size
)
142 /* If there is a default gw extendd community return true otherwise
144 for (i
= 0; i
< ecom
->size
; i
++) {
146 uint8_t type
, sub_type
;
148 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
152 if ((type
== ECOMMUNITY_ENCODE_OPAQUE
153 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_DEF_GW
))
161 * Fetch and return the DF preference and algorithm from
162 * DF election extended community, if present, else 0.
164 uint16_t bgp_attr_df_pref_from_ec(struct attr
*attr
, uint8_t *alg
)
166 struct ecommunity
*ecom
;
168 uint16_t df_pref
= 0;
170 *alg
= EVPN_MH_DF_ALG_SERVICE_CARVING
;
171 ecom
= bgp_attr_get_ecommunity(attr
);
172 if (!ecom
|| !ecom
->size
)
175 for (i
= 0; i
< ecom
->size
; i
++) {
177 uint8_t type
, sub_type
;
179 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
182 if (!(type
== ECOMMUNITY_ENCODE_EVPN
183 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION
))
186 *alg
= (*pnt
++) & ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS
;
189 pnt
= ptr_get_be16(pnt
, &df_pref
);
190 (void)pnt
; /* consume value */
198 * Fetch and return the sequence number from MAC Mobility extended
199 * community, if present, else 0.
201 uint32_t bgp_attr_mac_mobility_seqnum(struct attr
*attr
, uint8_t *sticky
)
203 struct ecommunity
*ecom
;
207 ecom
= bgp_attr_get_ecommunity(attr
);
208 if (!ecom
|| !ecom
->size
)
211 /* If there is a MAC Mobility extended community, return its
213 * TODO: RFC is silent on handling of multiple MAC mobility extended
214 * communities for the same route. We will bail out upon the first
217 for (i
= 0; i
< ecom
->size
; i
++) {
219 uint8_t type
, sub_type
;
222 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
225 if (!(type
== ECOMMUNITY_ENCODE_EVPN
226 && sub_type
== ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY
))
230 if (flags
& ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY
)
236 pnt
= ptr_get_be32(pnt
, &seq_num
);
237 (void)pnt
; /* consume value */
245 * return true if attr contains router flag extended community
247 void bgp_attr_evpn_na_flag(struct attr
*attr
,
248 uint8_t *router_flag
, bool *proxy
)
250 struct ecommunity
*ecom
;
254 ecom
= bgp_attr_get_ecommunity(attr
);
255 if (!ecom
|| !ecom
->size
)
258 /* If there is a evpn na extendd community set router_flag */
259 for (i
= 0; i
< ecom
->size
; i
++) {
261 uint8_t type
, sub_type
;
263 pnt
= (ecom
->val
+ (i
* ECOMMUNITY_SIZE
));
267 if (type
== ECOMMUNITY_ENCODE_EVPN
&&
268 sub_type
== ECOMMUNITY_EVPN_SUBTYPE_ND
) {
271 if (val
& ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG
)
274 if (val
& ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG
)
282 /* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
283 extern int bgp_build_evpn_prefix(int evpn_type
, uint32_t eth_tag
,
286 struct evpn_addr
*p_evpn_p
;
288 struct prefix
*src
= &p2
;
290 if (!dst
|| dst
->family
== 0)
292 /* store initial prefix in src */
293 prefix_copy(src
, dst
);
294 memset(dst
, 0, sizeof(struct prefix
));
295 p_evpn_p
= &(dst
->u
.prefix_evpn
);
296 dst
->family
= AF_EVPN
;
297 p_evpn_p
->route_type
= evpn_type
;
298 if (evpn_type
== BGP_EVPN_IP_PREFIX_ROUTE
) {
299 p_evpn_p
->prefix_addr
.eth_tag
= eth_tag
;
300 p_evpn_p
->prefix_addr
.ip_prefix_length
= p2
.prefixlen
;
301 if (src
->family
== AF_INET
) {
302 SET_IPADDR_V4(&p_evpn_p
->prefix_addr
.ip
);
303 memcpy(&p_evpn_p
->prefix_addr
.ip
.ipaddr_v4
,
305 sizeof(struct in_addr
));
306 dst
->prefixlen
= (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4
;
308 SET_IPADDR_V6(&p_evpn_p
->prefix_addr
.ip
);
309 memcpy(&p_evpn_p
->prefix_addr
.ip
.ipaddr_v6
,
311 sizeof(struct in6_addr
));
312 dst
->prefixlen
= (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6
;