]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_attr_evpn.c
Merge pull request #10447 from ton31337/fix/json_with_whitespaces
[mirror_frr.git] / bgpd / bgp_attr_evpn.c
CommitLineData
212f5cbc 1/* Ethernet-VPN Attribute handling file
896014f4
DL
2 * Copyright (C) 2016 6WIND
3 *
4 * This file is part of FRRouting.
5 *
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
9 * later version.
10 *
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.
15 *
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
19 */
212f5cbc
PG
20
21#include <zebra.h>
22
23#include "command.h"
7ef5a232 24#include "filter.h"
212f5cbc
PG
25#include "prefix.h"
26#include "log.h"
27#include "memory.h"
28#include "stream.h"
74e2bd89 29#include "vxlan.h"
212f5cbc 30
dfa42ea3
PG
31#include "bgpd/bgpd.h"
32#include "bgpd/bgp_attr.h"
33#include "bgpd/bgp_route.h"
212f5cbc 34#include "bgpd/bgp_attr_evpn.h"
dfa42ea3 35#include "bgpd/bgp_ecommunity.h"
3da6fcd5 36#include "bgpd/bgp_evpn.h"
128ea8ab 37#include "bgpd/bgp_evpn_private.h"
dfa42ea3 38
761cc919
IS
39bool bgp_route_evpn_same(const struct bgp_route_evpn *e1,
40 const struct bgp_route_evpn *e2)
41{
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)));
45}
46
31689a53 47void bgp_add_routermac_ecom(struct attr *attr, struct ethaddr *routermac)
dfa42ea3 48{
d62a17ae 49 struct ecommunity_val routermac_ecom;
b53e67a3 50 struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
d62a17ae 51
52 memset(&routermac_ecom, 0, sizeof(struct ecommunity_val));
53 routermac_ecom.val[0] = ECOMMUNITY_ENCODE_EVPN;
54 routermac_ecom.val[1] = ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC;
28328ea9 55 memcpy(&routermac_ecom.val[2], routermac->octet, ETH_ALEN);
cfe4dce9 56 if (!ecomm) {
b53e67a3 57 bgp_attr_set_ecommunity(attr, ecommunity_new());
cfe4dce9
IR
58 ecomm = bgp_attr_get_ecommunity(attr);
59 }
b53e67a3
DA
60 ecommunity_add_val(ecomm, &routermac_ecom, false, false);
61 ecommunity_str(ecomm);
dfa42ea3 62}
212f5cbc 63
212f5cbc
PG
64/* converts to an esi
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
68 */
0a50c248 69bool str2esi(const char *str, esi_t *id)
212f5cbc 70{
0a50c248 71 unsigned int a[ESI_BYTES];
d62a17ae 72 int i;
73
74 if (!str)
3dc339cd 75 return false;
d62a17ae 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)
0a50c248 78 != ESI_BYTES) {
d62a17ae 79 /* error in incoming str length */
3dc339cd 80 return false;
d62a17ae 81 }
82 /* valid mac address */
83 if (!id)
3dc339cd 84 return true;
0a50c248 85 for (i = 0; i < ESI_BYTES; ++i)
d62a17ae 86 id->val[i] = a[i] & 0xff;
3dc339cd 87 return true;
212f5cbc
PG
88}
89
212f5cbc
PG
90char *ecom_mac2str(char *ecom_mac)
91{
d62a17ae 92 char *en;
212f5cbc 93
d62a17ae 94 en = ecom_mac;
95 en += 2;
128ea8ab 96
d62a17ae 97 return prefix_mac2str((struct ethaddr *)en, NULL, 0);
128ea8ab 98}
99
bc59a672 100/* Fetch router-mac from extended community */
eee353c5 101bool bgp_attr_rmac(struct attr *attr, struct ethaddr *rmac)
bc59a672 102{
f6e07e1b 103 uint32_t i = 0;
bc59a672
MK
104 struct ecommunity *ecom;
105
b53e67a3 106 ecom = bgp_attr_get_ecommunity(attr);
bc59a672 107 if (!ecom || !ecom->size)
eee353c5 108 return false;
bc59a672
MK
109
110 /* If there is a router mac extended community, set RMAC in attr */
111 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
112 uint8_t *pnt = NULL;
113 uint8_t type = 0;
114 uint8_t sub_type = 0;
bc59a672
MK
115
116 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
117 type = *pnt++;
118 sub_type = *pnt++;
119
996c9314
LB
120 if (!(type == ECOMMUNITY_ENCODE_EVPN
121 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_ROUTERMAC))
bc59a672
MK
122 continue;
123
124 memcpy(rmac, pnt, ETH_ALEN);
eee353c5 125 return true;
bc59a672 126 }
eee353c5 127 return false;
bc59a672
MK
128}
129
ead40654
MK
130/*
131 * return true if attr contains default gw extended community
132 */
133uint8_t bgp_attr_default_gw(struct attr *attr)
134{
996c9314 135 struct ecommunity *ecom;
f6e07e1b 136 uint32_t i;
ead40654 137
b53e67a3 138 ecom = bgp_attr_get_ecommunity(attr);
ead40654
MK
139 if (!ecom || !ecom->size)
140 return 0;
141
142 /* If there is a default gw extendd community return true otherwise
143 * return 0 */
144 for (i = 0; i < ecom->size; i++) {
d7c0a89a
QY
145 uint8_t *pnt;
146 uint8_t type, sub_type;
ead40654
MK
147
148 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
149 type = *pnt++;
150 sub_type = *pnt++;
151
152 if ((type == ECOMMUNITY_ENCODE_OPAQUE
996c9314 153 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DEF_GW))
ead40654
MK
154 return 1;
155 }
156
157 return 0;
158}
159
74e2bd89
AK
160/*
161 * Fetch and return the DF preference and algorithm from
162 * DF election extended community, if present, else 0.
163 */
164uint16_t bgp_attr_df_pref_from_ec(struct attr *attr, uint8_t *alg)
165{
166 struct ecommunity *ecom;
f6e07e1b 167 uint32_t i;
74e2bd89
AK
168 uint16_t df_pref = 0;
169
170 *alg = EVPN_MH_DF_ALG_SERVICE_CARVING;
b53e67a3 171 ecom = bgp_attr_get_ecommunity(attr);
74e2bd89
AK
172 if (!ecom || !ecom->size)
173 return 0;
174
175 for (i = 0; i < ecom->size; i++) {
176 uint8_t *pnt;
177 uint8_t type, sub_type;
178
179 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
180 type = *pnt++;
181 sub_type = *pnt++;
182 if (!(type == ECOMMUNITY_ENCODE_EVPN
183 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_DF_ELECTION))
184 continue;
185
186 *alg = (*pnt++) & ECOMMUNITY_EVPN_SUBTYPE_DF_ALG_BITS;
187
188 pnt += 3;
189 pnt = ptr_get_be16(pnt, &df_pref);
190 (void)pnt; /* consume value */
191 break;
192 }
193
194 return df_pref;
195}
196
128ea8ab 197/*
198 * Fetch and return the sequence number from MAC Mobility extended
199 * community, if present, else 0.
200 */
d7c0a89a 201uint32_t bgp_attr_mac_mobility_seqnum(struct attr *attr, uint8_t *sticky)
128ea8ab 202{
d62a17ae 203 struct ecommunity *ecom;
f6e07e1b 204 uint32_t i;
d7c0a89a 205 uint8_t flags = 0;
d62a17ae 206
b53e67a3 207 ecom = bgp_attr_get_ecommunity(attr);
d62a17ae 208 if (!ecom || !ecom->size)
209 return 0;
210
211 /* If there is a MAC Mobility extended community, return its
212 * sequence number.
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
215 * one.
216 */
217 for (i = 0; i < ecom->size; i++) {
1be1693e 218 const uint8_t *pnt;
d7c0a89a
QY
219 uint8_t type, sub_type;
220 uint32_t seq_num;
d62a17ae 221
222 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
223 type = *pnt++;
224 sub_type = *pnt++;
225 if (!(type == ECOMMUNITY_ENCODE_EVPN
226 && sub_type == ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY))
227 continue;
228 flags = *pnt++;
229
230 if (flags & ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY_FLAG_STICKY)
231 *sticky = 1;
232 else
233 *sticky = 0;
234
235 pnt++;
937652c6
DL
236 pnt = ptr_get_be32(pnt, &seq_num);
237 (void)pnt; /* consume value */
d62a17ae 238 return seq_num;
239 }
240
241 return 0;
212f5cbc 242}
3da6fcd5 243
68e33151
CS
244/*
245 * return true if attr contains router flag extended community
246 */
7904e9fd
AK
247void bgp_attr_evpn_na_flag(struct attr *attr,
248 uint8_t *router_flag, bool *proxy)
68e33151
CS
249{
250 struct ecommunity *ecom;
f6e07e1b 251 uint32_t i;
68e33151
CS
252 uint8_t val;
253
b53e67a3 254 ecom = bgp_attr_get_ecommunity(attr);
68e33151
CS
255 if (!ecom || !ecom->size)
256 return;
257
258 /* If there is a evpn na extendd community set router_flag */
259 for (i = 0; i < ecom->size; i++) {
260 uint8_t *pnt;
261 uint8_t type, sub_type;
262
263 pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
264 type = *pnt++;
265 sub_type = *pnt++;
266
267 if (type == ECOMMUNITY_ENCODE_EVPN &&
268 sub_type == ECOMMUNITY_EVPN_SUBTYPE_ND) {
269 val = *pnt++;
7904e9fd
AK
270
271 if (val & ECOMMUNITY_EVPN_SUBTYPE_ND_ROUTER_FLAG)
68e33151 272 *router_flag = 1;
7904e9fd
AK
273
274 if (val & ECOMMUNITY_EVPN_SUBTYPE_PROXY_FLAG)
275 *proxy = true;
276
277 break;
68e33151
CS
278 }
279 }
280}
281
3da6fcd5 282/* dst prefix must be AF_INET or AF_INET6 prefix, to forge EVPN prefix */
d62a17ae 283extern int bgp_build_evpn_prefix(int evpn_type, uint32_t eth_tag,
284 struct prefix *dst)
3da6fcd5 285{
d62a17ae 286 struct evpn_addr *p_evpn_p;
287 struct prefix p2;
288 struct prefix *src = &p2;
289
290 if (!dst || dst->family == 0)
291 return -1;
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);
b03b8898 296 dst->family = AF_EVPN;
d62a17ae 297 p_evpn_p->route_type = evpn_type;
298 if (evpn_type == BGP_EVPN_IP_PREFIX_ROUTE) {
3714a385 299 p_evpn_p->prefix_addr.eth_tag = eth_tag;
300 p_evpn_p->prefix_addr.ip_prefix_length = p2.prefixlen;
d62a17ae 301 if (src->family == AF_INET) {
3714a385 302 SET_IPADDR_V4(&p_evpn_p->prefix_addr.ip);
303 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v4,
304 &src->u.prefix4,
d62a17ae 305 sizeof(struct in_addr));
61be6e94 306 dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV4;
d62a17ae 307 } else {
3714a385 308 SET_IPADDR_V6(&p_evpn_p->prefix_addr.ip);
309 memcpy(&p_evpn_p->prefix_addr.ip.ipaddr_v6,
310 &src->u.prefix6,
d62a17ae 311 sizeof(struct in6_addr));
61be6e94 312 dst->prefixlen = (uint16_t)PREFIX_LEN_ROUTE_TYPE_5_IPV6;
d62a17ae 313 }
314 } else
315 return -1;
316 return 0;
3da6fcd5 317}