]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
bgpd, zebra: Rename variables of EVPN instance
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 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 */
20
21 #include <zebra.h>
22 #include "command.h"
23 #include "prefix.h"
24 #include "lib/json.h"
25 #include "stream.h"
26
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40
41 #define SHOW_DISPLAY_STANDARD 0
42 #define SHOW_DISPLAY_TAGS 1
43 #define SHOW_DISPLAY_OVERLAY 2
44 #define VNI_STR_LEN 32
45
46 /*
47 * Context for VNI hash walk - used by callbacks.
48 */
49 struct vni_walk_ctx {
50 struct bgp *bgp;
51 struct vty *vty;
52 struct in_addr vtep_ip;
53 json_object *json;
54 };
55
56 static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
57 json_object *json)
58 {
59 uint8_t *pnt;
60 uint8_t type, sub_type;
61 struct ecommunity_as eas;
62 struct ecommunity_ip eip;
63 struct listnode *node, *nnode;
64 struct bgp *tmp_bgp_vrf = NULL;
65 json_object *json_rt = NULL;
66 json_object *json_vrfs = NULL;
67 char rt_buf[RT_ADDRSTRLEN];
68
69 if (json) {
70 json_rt = json_object_new_object();
71 json_vrfs = json_object_new_array();
72 }
73
74 pnt = (uint8_t *)&irt->rt.val;
75 type = *pnt++;
76 sub_type = *pnt++;
77 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
78 return;
79
80 memset(&eas, 0, sizeof(eas));
81 switch (type) {
82 case ECOMMUNITY_ENCODE_AS:
83 eas.as = (*pnt++ << 8);
84 eas.as |= (*pnt++);
85 ptr_get_be32(pnt, &eas.val);
86
87 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
88
89 if (json)
90 json_object_string_add(json_rt, "rt", rt_buf);
91 else
92 vty_out(vty, "Route-target: %s", rt_buf);
93
94 break;
95
96 case ECOMMUNITY_ENCODE_IP:
97 memcpy(&eip.ip, pnt, 4);
98 pnt += 4;
99 eip.val = (*pnt++ << 8);
100 eip.val |= (*pnt++);
101
102 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
103 eip.val);
104
105 if (json)
106 json_object_string_add(json_rt, "rt", rt_buf);
107 else
108 vty_out(vty, "Route-target: %s", rt_buf);
109
110 break;
111
112 case ECOMMUNITY_ENCODE_AS4:
113 pnt = ptr_get_be32(pnt, &eas.val);
114 eas.val = (*pnt++ << 8);
115 eas.val |= (*pnt++);
116
117 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
118
119 if (json)
120 json_object_string_add(json_rt, "rt", rt_buf);
121 else
122 vty_out(vty, "Route-target: %s", rt_buf);
123
124 break;
125
126 default:
127 return;
128 }
129
130 if (!json) {
131 vty_out(vty,
132 "\nList of VRFs importing routes with this route-target:\n");
133 }
134
135 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
136 if (json)
137 json_object_array_add(
138 json_vrfs,
139 json_object_new_string(
140 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
141 else
142 vty_out(vty, " %s\n",
143 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
144 }
145
146 if (json) {
147 json_object_object_add(json_rt, "vrfs", json_vrfs);
148 json_object_object_add(json, rt_buf, json_rt);
149 }
150 }
151
152 static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
153 {
154 json_object *json = NULL;
155 struct vty *vty = NULL;
156 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
157
158 vty = (struct vty *)args[0];
159 json = (struct json_object *)args[1];
160
161 display_vrf_import_rt(vty, irt, json);
162 }
163
164 static void display_import_rt(struct vty *vty, struct irt_node *irt,
165 json_object *json)
166 {
167 uint8_t *pnt;
168 uint8_t type, sub_type;
169 struct ecommunity_as eas;
170 struct ecommunity_ip eip;
171 struct listnode *node, *nnode;
172 struct bgpevpn *tmp_vpn;
173 json_object *json_rt = NULL;
174 json_object *json_vnis = NULL;
175 char rt_buf[RT_ADDRSTRLEN];
176
177 if (json) {
178 json_rt = json_object_new_object();
179 json_vnis = json_object_new_array();
180 }
181
182 /* TODO: This needs to go into a function */
183
184 pnt = (uint8_t *)&irt->rt.val;
185 type = *pnt++;
186 sub_type = *pnt++;
187 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
188 return;
189
190 memset(&eas, 0, sizeof(eas));
191 switch (type) {
192 case ECOMMUNITY_ENCODE_AS:
193 eas.as = (*pnt++ << 8);
194 eas.as |= (*pnt++);
195 ptr_get_be32(pnt, &eas.val);
196
197 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
198
199 if (json)
200 json_object_string_add(json_rt, "rt", rt_buf);
201 else
202 vty_out(vty, "Route-target: %s", rt_buf);
203
204 break;
205
206 case ECOMMUNITY_ENCODE_IP:
207 memcpy(&eip.ip, pnt, 4);
208 pnt += 4;
209 eip.val = (*pnt++ << 8);
210 eip.val |= (*pnt++);
211
212 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
213 eip.val);
214
215 if (json)
216 json_object_string_add(json_rt, "rt", rt_buf);
217 else
218 vty_out(vty, "Route-target: %s", rt_buf);
219
220 break;
221
222 case ECOMMUNITY_ENCODE_AS4:
223 pnt = ptr_get_be32(pnt, &eas.val);
224 eas.val = (*pnt++ << 8);
225 eas.val |= (*pnt++);
226
227 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
228
229 if (json)
230 json_object_string_add(json_rt, "rt", rt_buf);
231 else
232 vty_out(vty, "Route-target: %s", rt_buf);
233
234 break;
235
236 default:
237 return;
238 }
239
240 if (!json) {
241 vty_out(vty,
242 "\nList of VNIs importing routes with this route-target:\n");
243 }
244
245 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
246 if (json)
247 json_object_array_add(
248 json_vnis, json_object_new_int(tmp_vpn->vni));
249 else
250 vty_out(vty, " %u\n", tmp_vpn->vni);
251 }
252
253 if (json) {
254 json_object_object_add(json_rt, "vnis", json_vnis);
255 json_object_object_add(json, rt_buf, json_rt);
256 }
257 }
258
259 static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
260 {
261 json_object *json = NULL;
262 struct vty *vty = NULL;
263 struct irt_node *irt = (struct irt_node *)bucket->data;
264
265 vty = args[0];
266 json = args[1];
267
268 display_import_rt(vty, irt, json);
269
270 return;
271 }
272
273 static void bgp_evpn_show_route_rd_header(struct vty *vty,
274 struct bgp_node *rd_rn,
275 json_object *json)
276 {
277 uint16_t type;
278 struct rd_as rd_as;
279 struct rd_ip rd_ip;
280 uint8_t *pnt;
281 char rd_str[RD_ADDRSTRLEN];
282
283 pnt = rd_rn->p.u.val;
284
285 /* Decode RD type. */
286 type = decode_rd_type(pnt);
287
288 if (json)
289 return;
290
291 vty_out(vty, "Route Distinguisher: ");
292
293 switch (type) {
294 case RD_TYPE_AS:
295 decode_rd_as(pnt + 2, &rd_as);
296 snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
297 break;
298
299 case RD_TYPE_IP:
300 decode_rd_ip(pnt + 2, &rd_ip);
301 snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
302 rd_ip.val);
303 break;
304
305 default:
306 snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
307 break;
308 }
309
310 vty_out(vty, "%s\n", rd_str);
311 }
312
313 static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
314 uint64_t tbl_ver, json_object *json)
315 {
316 char ri_header[] =
317 " Network Next Hop Metric LocPrf Weight Path\n";
318
319 if (json)
320 return;
321
322 vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n",
323 tbl_ver, inet_ntoa(bgp->router_id));
324 vty_out(vty,
325 "Status codes: s suppressed, d damped, h history, "
326 "* valid, > best, i - internal\n");
327 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
328 vty_out(vty,
329 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
330 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
331 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
332 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
333 vty_out(vty, "%s", ri_header);
334 }
335
336 static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
337 json_object *json)
338 {
339 char buf1[INET6_ADDRSTRLEN];
340 char *ecom_str;
341 struct listnode *node, *nnode;
342 struct ecommunity *ecom;
343 json_object *json_import_rtl = NULL;
344 json_object *json_export_rtl = NULL;
345
346 json_import_rtl = json_export_rtl = 0;
347
348 if (json) {
349 json_import_rtl = json_object_new_array();
350 json_export_rtl = json_object_new_array();
351 json_object_int_add(json, "vni", bgp_vrf->l3vni);
352 json_object_string_add(json, "type", "L3");
353 json_object_string_add(json, "kernelFlag", "Yes");
354 json_object_string_add(
355 json, "rd",
356 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
357 json_object_string_add(json, "originatorIp",
358 inet_ntoa(bgp_vrf->originator_ip));
359 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
360 } else {
361 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
362 vty_out(vty, " (known to the kernel)");
363 vty_out(vty, "\n");
364
365 vty_out(vty, " Type: %s\n", "L3");
366 vty_out(vty, " Tenant VRF: %s\n",
367 vrf_id_to_name(bgp_vrf->vrf_id));
368 vty_out(vty, " RD: %s\n",
369 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
370 vty_out(vty, " Originator IP: %s\n",
371 inet_ntoa(bgp_vrf->originator_ip));
372 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
373 }
374
375 if (!json)
376 vty_out(vty, " Import Route Target:\n");
377
378 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) {
379 ecom_str = ecommunity_ecom2str(ecom,
380 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
381
382 if (json)
383 json_object_array_add(json_import_rtl,
384 json_object_new_string(ecom_str));
385 else
386 vty_out(vty, " %s\n", ecom_str);
387
388 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
389 }
390
391 if (json)
392 json_object_object_add(json, "importRts", json_import_rtl);
393 else
394 vty_out(vty, " Export Route Target:\n");
395
396 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) {
397 ecom_str = ecommunity_ecom2str(ecom,
398 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
399
400 if (json)
401 json_object_array_add(json_export_rtl,
402 json_object_new_string(ecom_str));
403 else
404 vty_out(vty, " %s\n", ecom_str);
405
406 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
407 }
408
409 if (json)
410 json_object_object_add(json, "exportRts", json_export_rtl);
411 }
412
413 static void display_es(struct vty *vty, struct evpnes *es, json_object *json)
414 {
415 struct in_addr *vtep;
416 char buf[ESI_STR_LEN];
417 char buf1[RD_ADDRSTRLEN];
418 char buf2[INET6_ADDRSTRLEN];
419 struct listnode *node = NULL;
420 json_object *json_vteps = NULL;
421
422 if (json) {
423 json_vteps = json_object_new_array();
424 json_object_string_add(json, "esi",
425 esi_to_str(&es->esi, buf, sizeof(buf)));
426 json_object_string_add(json, "rd",
427 prefix_rd2str(&es->prd, buf1,
428 sizeof(buf1)));
429 json_object_string_add(
430 json, "originatorIp",
431 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
432 if (es->vtep_list) {
433 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
434 json_object_array_add(
435 json_vteps, json_object_new_string(
436 inet_ntoa(*vtep)));
437 }
438 json_object_object_add(json, "vteps", json_vteps);
439 } else {
440 vty_out(vty, "ESI: %s\n",
441 esi_to_str(&es->esi, buf, sizeof(buf)));
442 vty_out(vty, " RD: %s\n", prefix_rd2str(&es->prd, buf1,
443 sizeof(buf1)));
444 vty_out(vty, " Originator-IP: %s\n",
445 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
446 if (es->vtep_list) {
447 vty_out(vty, " VTEP List:\n");
448 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
449 vty_out(vty, " %s\n", inet_ntoa(*vtep));
450 }
451 }
452 }
453
454 static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
455 {
456 char buf1[RD_ADDRSTRLEN];
457 char *ecom_str;
458 struct listnode *node, *nnode;
459 struct ecommunity *ecom;
460 json_object *json_import_rtl = NULL;
461 json_object *json_export_rtl = NULL;
462
463 if (json) {
464 json_import_rtl = json_object_new_array();
465 json_export_rtl = json_object_new_array();
466 json_object_int_add(json, "vni", vpn->vni);
467 json_object_string_add(json, "type", "L2");
468 json_object_string_add(json, "kernelFlag",
469 is_vni_live(vpn) ? "Yes" : "No");
470 json_object_string_add(
471 json, "rd",
472 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
473 json_object_string_add(json, "originatorIp",
474 inet_ntoa(vpn->originator_ip));
475 json_object_string_add(json, "advertiseGatewayMacip",
476 vpn->advertise_gw_macip ? "Yes" : "No");
477 } else {
478 vty_out(vty, "VNI: %d", vpn->vni);
479 if (is_vni_live(vpn))
480 vty_out(vty, " (known to the kernel)");
481 vty_out(vty, "\n");
482
483 vty_out(vty, " Type: %s\n", "L2");
484 vty_out(vty, " Tenant-Vrf: %s\n",
485 vrf_id_to_name(vpn->tenant_vrf_id));
486 vty_out(vty, " RD: %s\n",
487 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
488 vty_out(vty, " Originator IP: %s\n",
489 inet_ntoa(vpn->originator_ip));
490 vty_out(vty, " Advertise-gw-macip : %s\n",
491 vpn->advertise_gw_macip ? "Yes" : "No");
492 vty_out(vty, " Advertise-svi-macip : %s\n",
493 vpn->advertise_svi_macip ? "Yes" : "No");
494 }
495
496 if (!json)
497 vty_out(vty, " Import Route Target:\n");
498
499 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
500 ecom_str = ecommunity_ecom2str(ecom,
501 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
502
503 if (json)
504 json_object_array_add(json_import_rtl,
505 json_object_new_string(ecom_str));
506 else
507 vty_out(vty, " %s\n", ecom_str);
508
509 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
510 }
511
512 if (json)
513 json_object_object_add(json, "importRts", json_import_rtl);
514 else
515 vty_out(vty, " Export Route Target:\n");
516
517 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
518 ecom_str = ecommunity_ecom2str(ecom,
519 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
520
521 if (json)
522 json_object_array_add(json_export_rtl,
523 json_object_new_string(ecom_str));
524 else
525 vty_out(vty, " %s\n", ecom_str);
526
527 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
528 }
529
530 if (json)
531 json_object_object_add(json, "exportRts", json_export_rtl);
532 }
533
534 static void show_esi_routes(struct bgp *bgp,
535 struct evpnes *es,
536 struct vty *vty,
537 json_object *json)
538 {
539 int header = 1;
540 struct bgp_node *rn;
541 struct bgp_path_info *pi;
542 uint32_t prefix_cnt, path_cnt;
543 uint64_t tbl_ver;
544
545 prefix_cnt = path_cnt = 0;
546
547 tbl_ver = es->route_table->version;
548 for (rn = bgp_table_top(es->route_table); rn;
549 rn = bgp_route_next(rn)) {
550 int add_prefix_to_json = 0;
551 char prefix_str[BUFSIZ];
552 json_object *json_paths = NULL;
553 json_object *json_prefix = NULL;
554
555 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
556 sizeof(prefix_str));
557
558 if (json)
559 json_prefix = json_object_new_object();
560
561 pi = bgp_node_get_bgp_path_info(rn);
562 if (pi) {
563 /* Overall header/legend displayed once. */
564 if (header) {
565 bgp_evpn_show_route_header(vty, bgp,
566 tbl_ver, json);
567 header = 0;
568 }
569
570 prefix_cnt++;
571 }
572
573 if (json)
574 json_paths = json_object_new_array();
575
576 /* For EVPN, the prefix is displayed for each path (to fit in
577 * with code that already exists).
578 */
579 for (; pi; pi = pi->next) {
580 json_object *json_path = NULL;
581
582 if (json)
583 json_path = json_object_new_array();
584
585 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
586
587 if (json)
588 json_object_array_add(json_paths, json_path);
589
590 path_cnt++;
591 add_prefix_to_json = 1;
592 }
593
594 if (json && add_prefix_to_json) {
595 json_object_string_add(json_prefix, "prefix",
596 prefix_str);
597 json_object_int_add(json_prefix, "prefixLen",
598 rn->p.prefixlen);
599 json_object_object_add(json_prefix, "paths",
600 json_paths);
601 json_object_object_add(json, prefix_str, json_prefix);
602 }
603 }
604
605 if (json) {
606 json_object_int_add(json, "numPrefix", prefix_cnt);
607 json_object_int_add(json, "numPaths", path_cnt);
608 } else {
609 if (prefix_cnt == 0)
610 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
611 else
612 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
613 prefix_cnt, path_cnt);
614 }
615 }
616
617 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
618 struct vty *vty, struct in_addr vtep_ip,
619 json_object *json)
620 {
621 struct bgp_node *rn;
622 struct bgp_path_info *pi;
623 struct bgp_table *table;
624 int header = 1;
625 uint64_t tbl_ver;
626 uint32_t prefix_cnt, path_cnt;
627
628 prefix_cnt = path_cnt = 0;
629
630 table = vpn->route_table;
631 tbl_ver = table->version;
632 for (rn = bgp_table_top(table); rn;
633 rn = bgp_route_next(rn)) {
634 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
635 int add_prefix_to_json = 0;
636 char prefix_str[BUFSIZ];
637 json_object *json_paths = NULL;
638 json_object *json_prefix = NULL;
639
640 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
641 sizeof(prefix_str));
642
643 if (type && evp->prefix.route_type != type)
644 continue;
645
646 if (json)
647 json_prefix = json_object_new_object();
648
649 pi = bgp_node_get_bgp_path_info(rn);
650 if (pi) {
651 /* Overall header/legend displayed once. */
652 if (header) {
653 bgp_evpn_show_route_header(vty, bgp,
654 tbl_ver, json);
655 header = 0;
656 }
657
658 prefix_cnt++;
659 }
660
661 if (json)
662 json_paths = json_object_new_array();
663
664 /* For EVPN, the prefix is displayed for each path (to fit in
665 * with code that already exists).
666 */
667 for (; pi; pi = pi->next) {
668 json_object *json_path = NULL;
669
670 if (vtep_ip.s_addr
671 && !IPV4_ADDR_SAME(&(vtep_ip),
672 &(pi->attr->nexthop)))
673 continue;
674
675 if (json)
676 json_path = json_object_new_array();
677
678 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
679
680 if (json)
681 json_object_array_add(json_paths, json_path);
682
683 path_cnt++;
684 add_prefix_to_json = 1;
685 }
686
687 if (json && add_prefix_to_json) {
688 json_object_string_add(json_prefix, "prefix",
689 prefix_str);
690 json_object_int_add(json_prefix, "prefixLen",
691 rn->p.prefixlen);
692 json_object_object_add(json_prefix, "paths",
693 json_paths);
694 json_object_object_add(json, prefix_str, json_prefix);
695 }
696 }
697
698 if (json) {
699 json_object_int_add(json, "numPrefix", prefix_cnt);
700 json_object_int_add(json, "numPaths", path_cnt);
701 } else {
702 if (prefix_cnt == 0)
703 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
704 type ? "(of requested type) " : "");
705 else
706 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
707 prefix_cnt, path_cnt,
708 type ? " (of requested type)" : "");
709 }
710 }
711
712 static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
713 {
714 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
715 struct vni_walk_ctx *wctx = arg;
716 struct vty *vty = wctx->vty;
717 json_object *json = wctx->json;
718 json_object *json_vni = NULL;
719 char vni_str[VNI_STR_LEN];
720
721 snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
722 if (json) {
723 json_vni = json_object_new_object();
724 json_object_int_add(json_vni, "vni", vpn->vni);
725 } else {
726 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
727 }
728
729 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni);
730
731 if (json)
732 json_object_object_add(json, vni_str, json_vni);
733 }
734
735 static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
736 json_object *json)
737 {
738 json_object *json_vni = NULL;
739 json_object *json_import_rtl = NULL;
740 json_object *json_export_rtl = NULL;
741 char buf1[10];
742 char buf2[INET6_ADDRSTRLEN];
743 char rt_buf[25];
744 char *ecom_str;
745 struct listnode *node, *nnode;
746 struct ecommunity *ecom;
747
748 if (!bgp->l3vni)
749 return;
750
751 if (json) {
752 json_vni = json_object_new_object();
753 json_import_rtl = json_object_new_array();
754 json_export_rtl = json_object_new_array();
755 }
756
757 /* if an l3vni is present in bgp it is live */
758 buf1[0] = '\0';
759 sprintf(buf1, "*");
760
761 if (json) {
762 json_object_int_add(json_vni, "vni", bgp->l3vni);
763 json_object_string_add(json_vni, "type", "L3");
764 json_object_string_add(json_vni, "inKernel", "True");
765 json_object_string_add(json_vni, "originatorIp",
766 inet_ntoa(bgp->originator_ip));
767 json_object_string_add(
768 json_vni, "rd",
769 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
770 } else {
771 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
772 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
773 }
774
775 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
776 ecom_str = ecommunity_ecom2str(ecom,
777 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
778
779 if (json) {
780 json_object_array_add(json_import_rtl,
781 json_object_new_string(ecom_str));
782 } else {
783 if (listcount(bgp->vrf_import_rtl) > 1)
784 sprintf(rt_buf, "%s, ...", ecom_str);
785 else
786 sprintf(rt_buf, "%s", ecom_str);
787 vty_out(vty, " %-25s", rt_buf);
788 }
789
790 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
791
792 /* If there are multiple import RTs we break here and show only
793 * one */
794 if (!json)
795 break;
796 }
797
798 if (json)
799 json_object_object_add(json_vni, "importRTs", json_import_rtl);
800
801 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) {
802 ecom_str = ecommunity_ecom2str(ecom,
803 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
804
805 if (json) {
806 json_object_array_add(json_export_rtl,
807 json_object_new_string(ecom_str));
808 } else {
809 if (listcount(bgp->vrf_export_rtl) > 1)
810 sprintf(rt_buf, "%s, ...", ecom_str);
811 else
812 sprintf(rt_buf, "%s", ecom_str);
813 vty_out(vty, " %-25s", rt_buf);
814 }
815
816 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
817
818 /* If there are multiple export RTs we break here and show only
819 * one */
820 if (!json)
821 break;
822 }
823
824 if (!json)
825 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
826
827 if (json) {
828 char vni_str[VNI_STR_LEN];
829
830 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
831 snprintf(vni_str, VNI_STR_LEN, "%u", bgp->l3vni);
832 json_object_object_add(json, vni_str, json_vni);
833 } else {
834 vty_out(vty, "\n");
835 }
836 }
837
838 static void show_es_entry(struct hash_bucket *bucket, void *args[])
839 {
840 char buf[ESI_STR_LEN];
841 char buf1[RD_ADDRSTRLEN];
842 char buf2[INET6_ADDRSTRLEN];
843 struct in_addr *vtep = NULL;
844 struct vty *vty = args[0];
845 json_object *json = args[1];
846 json_object *json_vteps = NULL;
847 struct listnode *node = NULL;
848 struct evpnes *es = (struct evpnes *)bucket->data;
849
850 if (json) {
851 json_vteps = json_object_new_array();
852 json_object_string_add(json, "esi",
853 esi_to_str(&es->esi, buf, sizeof(buf)));
854 json_object_string_add(json, "type",
855 is_es_local(es) ? "Local" : "Remote");
856 json_object_string_add(json, "rd",
857 prefix_rd2str(&es->prd, buf1,
858 sizeof(buf1)));
859 json_object_string_add(
860 json, "originatorIp",
861 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
862 if (es->vtep_list) {
863 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
864 json_object_array_add(json_vteps,
865 json_object_new_string(
866 inet_ntoa(*vtep)));
867 }
868 json_object_object_add(json, "vteps", json_vteps);
869 } else {
870 vty_out(vty, "%-30s %-6s %-21s %-15s %-6d\n",
871 esi_to_str(&es->esi, buf, sizeof(buf)),
872 is_es_local(es) ? "Local" : "Remote",
873 prefix_rd2str(&es->prd, buf1, sizeof(buf1)),
874 ipaddr2str(&es->originator_ip, buf2,
875 sizeof(buf2)),
876 es->vtep_list ? listcount(es->vtep_list) : 0);
877 }
878 }
879
880 static void show_vni_entry(struct hash_bucket *bucket, void *args[])
881 {
882 struct vty *vty;
883 json_object *json;
884 json_object *json_vni = NULL;
885 json_object *json_import_rtl = NULL;
886 json_object *json_export_rtl = NULL;
887 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
888 char buf1[10];
889 char buf2[RD_ADDRSTRLEN];
890 char rt_buf[25];
891 char *ecom_str;
892 struct listnode *node, *nnode;
893 struct ecommunity *ecom;
894
895 vty = args[0];
896 json = args[1];
897
898 if (json) {
899 json_vni = json_object_new_object();
900 json_import_rtl = json_object_new_array();
901 json_export_rtl = json_object_new_array();
902 }
903
904 buf1[0] = '\0';
905 if (is_vni_live(vpn))
906 sprintf(buf1, "*");
907
908 if (json) {
909 json_object_int_add(json_vni, "vni", vpn->vni);
910 json_object_string_add(json_vni, "type", "L2");
911 json_object_string_add(json_vni, "inKernel",
912 is_vni_live(vpn) ? "True" : "False");
913 json_object_string_add(json_vni, "originatorIp",
914 inet_ntoa(vpn->originator_ip));
915 json_object_string_add(json_vni, "originatorIp",
916 inet_ntoa(vpn->originator_ip));
917 json_object_string_add(
918 json_vni, "rd",
919 prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
920 } else {
921 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
922 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
923 }
924
925 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
926 ecom_str = ecommunity_ecom2str(ecom,
927 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
928
929 if (json) {
930 json_object_array_add(json_import_rtl,
931 json_object_new_string(ecom_str));
932 } else {
933 if (listcount(vpn->import_rtl) > 1)
934 sprintf(rt_buf, "%s, ...", ecom_str);
935 else
936 sprintf(rt_buf, "%s", ecom_str);
937 vty_out(vty, " %-25s", rt_buf);
938 }
939
940 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
941
942 /* If there are multiple import RTs we break here and show only
943 * one */
944 if (!json)
945 break;
946 }
947
948 if (json)
949 json_object_object_add(json_vni, "importRTs", json_import_rtl);
950
951 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
952 ecom_str = ecommunity_ecom2str(ecom,
953 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
954
955 if (json) {
956 json_object_array_add(json_export_rtl,
957 json_object_new_string(ecom_str));
958 } else {
959 if (listcount(vpn->export_rtl) > 1)
960 sprintf(rt_buf, "%s, ...", ecom_str);
961 else
962 sprintf(rt_buf, "%s", ecom_str);
963 vty_out(vty, " %-25s", rt_buf);
964 }
965
966 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
967
968 /* If there are multiple export RTs we break here and show only
969 * one */
970 if (!json)
971 break;
972 }
973
974 if (!json)
975 vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
976
977 if (json) {
978 char vni_str[VNI_STR_LEN];
979
980 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
981 snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
982 json_object_object_add(json, vni_str, json_vni);
983 } else {
984 vty_out(vty, "\n");
985 }
986 }
987
988 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
989 enum bgp_show_type type, void *output_arg,
990 int option, bool use_json)
991 {
992 afi_t afi = AFI_L2VPN;
993 struct bgp *bgp;
994 struct bgp_table *table;
995 struct bgp_node *rn;
996 struct bgp_node *rm;
997 struct bgp_path_info *pi;
998 int rd_header;
999 int header = 1;
1000
1001 unsigned long output_count = 0;
1002 unsigned long total_count = 0;
1003 json_object *json = NULL;
1004 json_object *json_nroute = NULL;
1005 json_object *json_array = NULL;
1006 json_object *json_scode = NULL;
1007 json_object *json_ocode = NULL;
1008
1009 bgp = bgp_get_evpn();
1010 if (bgp == NULL) {
1011 if (!use_json)
1012 vty_out(vty, "No BGP process is configured\n");
1013 else
1014 vty_out(vty, "{}\n");
1015 return CMD_WARNING;
1016 }
1017
1018 if (use_json) {
1019 json_scode = json_object_new_object();
1020 json_ocode = json_object_new_object();
1021 json = json_object_new_object();
1022 json_nroute = json_object_new_object();
1023
1024 json_object_string_add(json_scode, "suppressed", "s");
1025 json_object_string_add(json_scode, "damped", "d");
1026 json_object_string_add(json_scode, "history", "h");
1027 json_object_string_add(json_scode, "valid", "*");
1028 json_object_string_add(json_scode, "best", ">");
1029 json_object_string_add(json_scode, "internal", "i");
1030
1031 json_object_string_add(json_ocode, "igp", "i");
1032 json_object_string_add(json_ocode, "egp", "e");
1033 json_object_string_add(json_ocode, "incomplete", "?");
1034 }
1035
1036 for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
1037 rn = bgp_route_next(rn)) {
1038 uint64_t tbl_ver;
1039
1040 if (use_json)
1041 continue; /* XXX json TODO */
1042
1043 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
1044 continue;
1045
1046 table = bgp_node_get_bgp_table_info(rn);
1047 if (!table)
1048 continue;
1049
1050 rd_header = 1;
1051 tbl_ver = table->version;
1052
1053 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
1054 for (pi = bgp_node_get_bgp_path_info(rm); pi;
1055 pi = pi->next) {
1056 total_count++;
1057 if (type == bgp_show_type_neighbor) {
1058 union sockunion *su = output_arg;
1059
1060 if (pi->peer->su_remote == NULL
1061 || !sockunion_same(
1062 pi->peer->su_remote, su))
1063 continue;
1064 }
1065 if (header == 0) {
1066 if (use_json) {
1067 if (option
1068 == SHOW_DISPLAY_TAGS) {
1069 json_object_int_add(
1070 json,
1071 "bgpTableVersion",
1072 tbl_ver);
1073 json_object_string_add(
1074 json,
1075 "bgpLocalRouterId",
1076 inet_ntoa(
1077 bgp->router_id));
1078 json_object_object_add(
1079 json,
1080 "bgpStatusCodes",
1081 json_scode);
1082 json_object_object_add(
1083 json,
1084 "bgpOriginCodes",
1085 json_ocode);
1086 }
1087 } else {
1088 if (option == SHOW_DISPLAY_TAGS)
1089 vty_out(vty,
1090 V4_HEADER_TAG);
1091 else if (
1092 option
1093 == SHOW_DISPLAY_OVERLAY)
1094 vty_out(vty,
1095 V4_HEADER_OVERLAY);
1096 else {
1097 vty_out(vty,
1098 "BGP table version is %" PRIu64 ", local router ID is %s\n",
1099 tbl_ver,
1100 inet_ntoa(
1101 bgp->router_id));
1102 vty_out(vty,
1103 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1104 vty_out(vty,
1105 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1106 vty_out(vty, V4_HEADER);
1107 }
1108 }
1109 header = 0;
1110 }
1111 if (rd_header) {
1112 uint16_t type;
1113 struct rd_as rd_as;
1114 struct rd_ip rd_ip;
1115 uint8_t *pnt;
1116
1117 pnt = rn->p.u.val;
1118
1119 /* Decode RD type. */
1120 type = decode_rd_type(pnt);
1121 /* Decode RD value. */
1122 if (type == RD_TYPE_AS)
1123 decode_rd_as(pnt + 2, &rd_as);
1124 else if (type == RD_TYPE_AS4)
1125 decode_rd_as4(pnt + 2, &rd_as);
1126 else if (type == RD_TYPE_IP)
1127 decode_rd_ip(pnt + 2, &rd_ip);
1128 if (use_json) {
1129 char buffer[BUFSIZ];
1130 if (type == RD_TYPE_AS
1131 || type == RD_TYPE_AS4)
1132 sprintf(buffer, "%u:%d",
1133 rd_as.as,
1134 rd_as.val);
1135 else if (type == RD_TYPE_IP)
1136 sprintf(buffer, "%s:%d",
1137 inet_ntoa(
1138 rd_ip.ip),
1139 rd_ip.val);
1140 json_object_string_add(
1141 json_nroute,
1142 "routeDistinguisher",
1143 buffer);
1144 } else {
1145 vty_out(vty,
1146 "Route Distinguisher: ");
1147 if (type == RD_TYPE_AS)
1148 vty_out(vty,
1149 "as2 %u:%d",
1150 rd_as.as,
1151 rd_as.val);
1152 else if (type == RD_TYPE_AS4)
1153 vty_out(vty,
1154 "as4 %u:%d",
1155 rd_as.as,
1156 rd_as.val);
1157 else if (type == RD_TYPE_IP)
1158 vty_out(vty, "ip %s:%d",
1159 inet_ntoa(
1160 rd_ip.ip),
1161 rd_ip.val);
1162 vty_out(vty, "\n\n");
1163 }
1164 rd_header = 0;
1165 }
1166 if (use_json)
1167 json_array = json_object_new_array();
1168 else
1169 json_array = NULL;
1170 if (option == SHOW_DISPLAY_TAGS)
1171 route_vty_out_tag(vty, &rm->p, pi, 0,
1172 SAFI_EVPN,
1173 json_array);
1174 else if (option == SHOW_DISPLAY_OVERLAY)
1175 route_vty_out_overlay(vty, &rm->p, pi,
1176 0, json_array);
1177 else
1178 route_vty_out(vty, &rm->p, pi, 0,
1179 SAFI_EVPN, json_array);
1180 output_count++;
1181 }
1182 /* XXX json */
1183 }
1184 if (output_count == 0)
1185 vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
1186 else
1187 vty_out(vty, "\nDisplayed %ld out of %ld total prefixes\n",
1188 output_count, total_count);
1189 return CMD_SUCCESS;
1190 }
1191
1192 DEFUN(show_ip_bgp_l2vpn_evpn,
1193 show_ip_bgp_l2vpn_evpn_cmd,
1194 "show [ip] bgp l2vpn evpn [json]",
1195 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
1196 {
1197 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
1198 use_json(argc, argv));
1199 }
1200
1201 DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1202 show_ip_bgp_l2vpn_evpn_rd_cmd,
1203 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1204 SHOW_STR
1205 IP_STR
1206 BGP_STR
1207 L2VPN_HELP_STR
1208 EVPN_HELP_STR
1209 "Display information for a route distinguisher\n"
1210 "VPN Route Distinguisher\n" JSON_STR)
1211 {
1212 int idx_ext_community = 0;
1213 int ret;
1214 struct prefix_rd prd;
1215
1216 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1217
1218 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1219 if (!ret) {
1220 vty_out(vty, "%% Malformed Route Distinguisher\n");
1221 return CMD_WARNING;
1222 }
1223 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
1224 use_json(argc, argv));
1225 }
1226
1227 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1228 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1229 "show [ip] bgp l2vpn evpn all tags",
1230 SHOW_STR
1231 IP_STR
1232 BGP_STR
1233 L2VPN_HELP_STR
1234 EVPN_HELP_STR
1235 "Display information about all EVPN NLRIs\n"
1236 "Display BGP tags for prefixes\n")
1237 {
1238 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
1239 0);
1240 }
1241
1242 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1243 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
1244 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1245 SHOW_STR
1246 IP_STR
1247 BGP_STR
1248 L2VPN_HELP_STR
1249 EVPN_HELP_STR
1250 "Display information for a route distinguisher\n"
1251 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1252 {
1253 int idx_ext_community = 0;
1254 int ret;
1255 struct prefix_rd prd;
1256
1257 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1258
1259 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1260 if (!ret) {
1261 vty_out(vty, "%% Malformed Route Distinguisher\n");
1262 return CMD_WARNING;
1263 }
1264 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
1265 0);
1266 }
1267
1268 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
1269 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd,
1270 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1271 SHOW_STR
1272 IP_STR
1273 BGP_STR
1274 L2VPN_HELP_STR
1275 EVPN_HELP_STR
1276 "Display information about all EVPN NLRIs\n"
1277 "Detailed information on TCP and BGP neighbor connections\n"
1278 "Neighbor to display information about\n"
1279 "Display routes learned from neighbor\n" JSON_STR)
1280 {
1281 int idx_ipv4 = 0;
1282 union sockunion su;
1283 struct peer *peer;
1284 int ret;
1285 bool uj = use_json(argc, argv);
1286
1287 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1288
1289 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1290 if (ret < 0) {
1291 if (uj) {
1292 json_object *json_no = NULL;
1293 json_no = json_object_new_object();
1294 json_object_string_add(json_no, "warning",
1295 "Malformed address");
1296 vty_out(vty, "%s\n",
1297 json_object_to_json_string(json_no));
1298 json_object_free(json_no);
1299 } else
1300 vty_out(vty, "Malformed address: %s\n",
1301 argv[idx_ipv4]->arg);
1302 return CMD_WARNING;
1303 }
1304
1305 peer = peer_lookup(NULL, &su);
1306 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1307 if (uj) {
1308 json_object *json_no = NULL;
1309 json_no = json_object_new_object();
1310 json_object_string_add(
1311 json_no, "warning",
1312 "No such neighbor or address family");
1313 vty_out(vty, "%s\n",
1314 json_object_to_json_string(json_no));
1315 json_object_free(json_no);
1316 } else
1317 vty_out(vty, "%% No such neighbor or address family\n");
1318 return CMD_WARNING;
1319 }
1320
1321 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, &su, 0,
1322 uj);
1323 }
1324
1325 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1326 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1327 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1328 SHOW_STR
1329 IP_STR
1330 BGP_STR
1331 L2VPN_HELP_STR
1332 EVPN_HELP_STR
1333 "Display information for a route distinguisher\n"
1334 "VPN Route Distinguisher\n"
1335 "Detailed information on TCP and BGP neighbor connections\n"
1336 "Neighbor to display information about\n"
1337 "Display routes learned from neighbor\n" JSON_STR)
1338 {
1339 int idx_ext_community = 0;
1340 int idx_ipv4 = 0;
1341 int ret;
1342 union sockunion su;
1343 struct peer *peer;
1344 struct prefix_rd prd;
1345 bool uj = use_json(argc, argv);
1346
1347 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1348 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1349
1350 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1351 if (!ret) {
1352 if (uj) {
1353 json_object *json_no = NULL;
1354 json_no = json_object_new_object();
1355 json_object_string_add(json_no, "warning",
1356 "Malformed Route Distinguisher");
1357 vty_out(vty, "%s\n",
1358 json_object_to_json_string(json_no));
1359 json_object_free(json_no);
1360 } else
1361 vty_out(vty, "%% Malformed Route Distinguisher\n");
1362 return CMD_WARNING;
1363 }
1364
1365 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1366 if (ret < 0) {
1367 if (uj) {
1368 json_object *json_no = NULL;
1369 json_no = json_object_new_object();
1370 json_object_string_add(json_no, "warning",
1371 "Malformed address");
1372 vty_out(vty, "%s\n",
1373 json_object_to_json_string(json_no));
1374 json_object_free(json_no);
1375 } else
1376 vty_out(vty, "Malformed address: %s\n",
1377 argv[idx_ext_community]->arg);
1378 return CMD_WARNING;
1379 }
1380
1381 peer = peer_lookup(NULL, &su);
1382 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1383 if (uj) {
1384 json_object *json_no = NULL;
1385 json_no = json_object_new_object();
1386 json_object_string_add(
1387 json_no, "warning",
1388 "No such neighbor or address family");
1389 vty_out(vty, "%s\n",
1390 json_object_to_json_string(json_no));
1391 json_object_free(json_no);
1392 } else
1393 vty_out(vty, "%% No such neighbor or address family\n");
1394 return CMD_WARNING;
1395 }
1396
1397 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, &su, 0,
1398 uj);
1399 }
1400
1401 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
1402 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd,
1403 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1404 SHOW_STR
1405 IP_STR
1406 BGP_STR
1407 L2VPN_HELP_STR
1408 EVPN_HELP_STR
1409 "Display information about all EVPN NLRIs\n"
1410 "Detailed information on TCP and BGP neighbor connections\n"
1411 "Neighbor to display information about\n"
1412 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1413 {
1414 int idx_ipv4 = 0;
1415 int ret;
1416 struct peer *peer;
1417 union sockunion su;
1418 bool uj = use_json(argc, argv);
1419
1420 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1421
1422 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1423 if (ret < 0) {
1424 if (uj) {
1425 json_object *json_no = NULL;
1426 json_no = json_object_new_object();
1427 json_object_string_add(json_no, "warning",
1428 "Malformed address");
1429 vty_out(vty, "%s\n",
1430 json_object_to_json_string(json_no));
1431 json_object_free(json_no);
1432 } else
1433 vty_out(vty, "Malformed address: %s\n",
1434 argv[idx_ipv4]->arg);
1435 return CMD_WARNING;
1436 }
1437 peer = peer_lookup(NULL, &su);
1438 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1439 if (uj) {
1440 json_object *json_no = NULL;
1441 json_no = json_object_new_object();
1442 json_object_string_add(
1443 json_no, "warning",
1444 "No such neighbor or address family");
1445 vty_out(vty, "%s\n",
1446 json_object_to_json_string(json_no));
1447 json_object_free(json_no);
1448 } else
1449 vty_out(vty, "%% No such neighbor or address family\n");
1450 return CMD_WARNING;
1451 }
1452
1453 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1454 }
1455
1456 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1457 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1458 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1459 SHOW_STR
1460 IP_STR
1461 BGP_STR
1462 L2VPN_HELP_STR
1463 EVPN_HELP_STR
1464 "Display information for a route distinguisher\n"
1465 "VPN Route Distinguisher\n"
1466 "Detailed information on TCP and BGP neighbor connections\n"
1467 "Neighbor to display information about\n"
1468 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1469 {
1470 int idx_ext_community = 0;
1471 int idx_ipv4 = 0;
1472 int ret;
1473 struct peer *peer;
1474 struct prefix_rd prd;
1475 union sockunion su;
1476 bool uj = use_json(argc, argv);
1477
1478 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1479 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1480
1481 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1482 if (ret < 0) {
1483 if (uj) {
1484 json_object *json_no = NULL;
1485 json_no = json_object_new_object();
1486 json_object_string_add(json_no, "warning",
1487 "Malformed address");
1488 vty_out(vty, "%s\n",
1489 json_object_to_json_string(json_no));
1490 json_object_free(json_no);
1491 } else
1492 vty_out(vty, "Malformed address: %s\n",
1493 argv[idx_ext_community]->arg);
1494 return CMD_WARNING;
1495 }
1496 peer = peer_lookup(NULL, &su);
1497 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1498 if (uj) {
1499 json_object *json_no = NULL;
1500 json_no = json_object_new_object();
1501 json_object_string_add(
1502 json_no, "warning",
1503 "No such neighbor or address family");
1504 vty_out(vty, "%s\n",
1505 json_object_to_json_string(json_no));
1506 json_object_free(json_no);
1507 } else
1508 vty_out(vty, "%% No such neighbor or address family\n");
1509 return CMD_WARNING;
1510 }
1511
1512 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1513 if (!ret) {
1514 if (uj) {
1515 json_object *json_no = NULL;
1516 json_no = json_object_new_object();
1517 json_object_string_add(json_no, "warning",
1518 "Malformed Route Distinguisher");
1519 vty_out(vty, "%s\n",
1520 json_object_to_json_string(json_no));
1521 json_object_free(json_no);
1522 } else
1523 vty_out(vty, "%% Malformed Route Distinguisher\n");
1524 return CMD_WARNING;
1525 }
1526
1527 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1528 }
1529
1530 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1531 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1532 "show [ip] bgp l2vpn evpn all overlay",
1533 SHOW_STR
1534 IP_STR
1535 BGP_STR
1536 L2VPN_HELP_STR
1537 EVPN_HELP_STR
1538 "Display information about all EVPN NLRIs\n"
1539 "Display BGP Overlay Information for prefixes\n")
1540 {
1541 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1542 SHOW_DISPLAY_OVERLAY,
1543 use_json(argc, argv));
1544 }
1545
1546 DEFUN(show_ip_bgp_evpn_rd_overlay,
1547 show_ip_bgp_evpn_rd_overlay_cmd,
1548 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1549 SHOW_STR
1550 IP_STR
1551 BGP_STR
1552 L2VPN_HELP_STR
1553 EVPN_HELP_STR
1554 "Display information for a route distinguisher\n"
1555 "VPN Route Distinguisher\n"
1556 "Display BGP Overlay Information for prefixes\n")
1557 {
1558 int idx_ext_community = 0;
1559 int ret;
1560 struct prefix_rd prd;
1561
1562 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1563
1564 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1565 if (!ret) {
1566 vty_out(vty, "%% Malformed Route Distinguisher\n");
1567 return CMD_WARNING;
1568 }
1569 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1570 SHOW_DISPLAY_OVERLAY,
1571 use_json(argc, argv));
1572 }
1573
1574 /* For testing purpose, static route of MPLS-VPN. */
1575 DEFUN(evpnrt5_network,
1576 evpnrt5_network_cmd,
1577 "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
1578 "Specify a network to announce via BGP\n"
1579 "IP prefix\n"
1580 "IPv6 prefix\n"
1581 "Specify Route Distinguisher\n"
1582 "VPN Route Distinguisher\n"
1583 "Ethernet Tag\n"
1584 "Ethernet Tag Value\n"
1585 "BGP label\n"
1586 "label value\n"
1587 "Ethernet Segment Identifier\n"
1588 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1589 "Gateway IP\n"
1590 "Gateway IP ( A.B.C.D )\n"
1591 "Gateway IPv6 ( X:X::X:X )\n"
1592 "Router Mac Ext Comm\n"
1593 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1594 "Route-map to modify the attributes\n"
1595 "Name of the route map\n")
1596 {
1597 int idx_ipv4_prefixlen = 1;
1598 int idx_route_distinguisher = 3;
1599 int idx_label = 7;
1600 int idx_esi = 9;
1601 int idx_gwip = 11;
1602 int idx_ethtag = 5;
1603 int idx_routermac = 13;
1604
1605 return bgp_static_set_safi(
1606 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1607 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
1608 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1609 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1610 argv[idx_routermac]->arg);
1611 }
1612
1613 /* For testing purpose, static route of MPLS-VPN. */
1614 DEFUN(no_evpnrt5_network,
1615 no_evpnrt5_network_cmd,
1616 "no network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X>",
1617 NO_STR
1618 "Specify a network to announce via BGP\n"
1619 "IP prefix\n"
1620 "IPv6 prefix\n"
1621 "Specify Route Distinguisher\n"
1622 "VPN Route Distinguisher\n"
1623 "Ethernet Tag\n"
1624 "Ethernet Tag Value\n"
1625 "BGP label\n"
1626 "label value\n"
1627 "Ethernet Segment Identifier\n"
1628 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1629 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1630 {
1631 int idx_ipv4_prefixlen = 2;
1632 int idx_ext_community = 4;
1633 int idx_label = 8;
1634 int idx_ethtag = 6;
1635 int idx_esi = 10;
1636 int idx_gwip = 12;
1637 return bgp_static_unset_safi(
1638 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1639 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1640 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1641 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
1642 }
1643
1644 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1645 {
1646 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
1647 }
1648
1649 static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1650 {
1651 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl);
1652 }
1653
1654 /*
1655 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1656 * check that this is a change.
1657 */
1658 static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1659 struct ecommunity *ecomadd)
1660 {
1661 /* If the VNI is "live", we need to uninstall routes using the current
1662 * import RT(s) first before we update the import RT, and subsequently
1663 * install routes.
1664 */
1665 if (is_vni_live(vpn))
1666 bgp_evpn_uninstall_routes(bgp, vpn);
1667
1668 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1669 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1670
1671 /* If the auto route-target is in use we must remove it */
1672 evpn_import_rt_delete_auto(bgp, vpn);
1673
1674 /* Add new RT and rebuild the RT to VNI mapping */
1675 listnode_add_sort(vpn->import_rtl, ecomadd);
1676
1677 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1678 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1679
1680 /* Install routes that match new import RT */
1681 if (is_vni_live(vpn))
1682 bgp_evpn_install_routes(bgp, vpn);
1683 }
1684
1685 /*
1686 * Unconfigure Import RT(s) for a VNI (vty handler).
1687 */
1688 static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1689 struct ecommunity *ecomdel)
1690 {
1691 struct listnode *node, *nnode, *node_to_del;
1692 struct ecommunity *ecom;
1693
1694 /* Along the lines of "configure" except we have to reset to the
1695 * automatic value.
1696 */
1697 if (is_vni_live(vpn))
1698 bgp_evpn_uninstall_routes(bgp, vpn);
1699
1700 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1701 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1702
1703 /* Delete all import RTs */
1704 if (ecomdel == NULL) {
1705 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1706 ecommunity_free(&ecom);
1707 list_delete_node(vpn->import_rtl, node);
1708 }
1709 }
1710
1711 /* Delete a specific import RT */
1712 else {
1713 node_to_del = NULL;
1714
1715 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1716 if (ecommunity_match(ecom, ecomdel)) {
1717 ecommunity_free(&ecom);
1718 node_to_del = node;
1719 break;
1720 }
1721 }
1722
1723 if (node_to_del)
1724 list_delete_node(vpn->import_rtl, node_to_del);
1725 }
1726
1727 assert(vpn->import_rtl);
1728 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1729 if (list_isempty(vpn->import_rtl)) {
1730 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1731 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1732 }
1733 /* Rebuild the RT to VNI mapping */
1734 else
1735 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1736
1737 /* Install routes that match new import RT */
1738 if (is_vni_live(vpn))
1739 bgp_evpn_install_routes(bgp, vpn);
1740 }
1741
1742 /*
1743 * Configure the Export RT for a VNI (vty handler). Caller expected to
1744 * check that this is a change. Note that only a single export RT is
1745 * allowed for a VNI and any change to configuration is implemented as
1746 * a "replace" (similar to other configuration).
1747 */
1748 static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1749 struct ecommunity *ecomadd)
1750 {
1751 /* If the auto route-target is in use we must remove it */
1752 evpn_export_rt_delete_auto(bgp, vpn);
1753
1754 listnode_add_sort(vpn->export_rtl, ecomadd);
1755 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1756
1757 if (is_vni_live(vpn))
1758 bgp_evpn_handle_export_rt_change(bgp, vpn);
1759 }
1760
1761 /*
1762 * Unconfigure the Export RT for a VNI (vty handler)
1763 */
1764 static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1765 struct ecommunity *ecomdel)
1766 {
1767 struct listnode *node, *nnode, *node_to_del;
1768 struct ecommunity *ecom;
1769
1770 /* Delete all export RTs */
1771 if (ecomdel == NULL) {
1772 /* Reset to default and process all routes. */
1773 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1774 ecommunity_free(&ecom);
1775 list_delete_node(vpn->export_rtl, node);
1776 }
1777 }
1778
1779 /* Delete a specific export RT */
1780 else {
1781 node_to_del = NULL;
1782
1783 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1784 if (ecommunity_match(ecom, ecomdel)) {
1785 ecommunity_free(&ecom);
1786 node_to_del = node;
1787 break;
1788 }
1789 }
1790
1791 if (node_to_del)
1792 list_delete_node(vpn->export_rtl, node_to_del);
1793 }
1794
1795 assert(vpn->export_rtl);
1796 if (list_isempty(vpn->export_rtl)) {
1797 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1798 bgp_evpn_derive_auto_rt_export(bgp, vpn);
1799 }
1800
1801 if (is_vni_live(vpn))
1802 bgp_evpn_handle_export_rt_change(bgp, vpn);
1803 }
1804
1805 /*
1806 * Configure RD for VRF
1807 */
1808 static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
1809 {
1810 /* If we have already advertise type-5 routes with a diffrent RD, we
1811 * have to delete and withdraw them firs
1812 */
1813 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1814
1815 /* update RD */
1816 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
1817 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
1818
1819 /* We have a new RD for VRF.
1820 * Advertise all type-5 routes again with the new RD
1821 */
1822 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1823 }
1824
1825 /*
1826 * Unconfigure RD for VRF
1827 */
1828 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
1829 {
1830 /* If we have already advertise type-5 routes with a diffrent RD, we
1831 * have to delete and withdraw them firs
1832 */
1833 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1834
1835 /* fall back to default RD */
1836 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
1837 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
1838
1839 /* We have a new RD for VRF.
1840 * Advertise all type-5 routes again with the new RD
1841 */
1842 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1843 }
1844
1845 /*
1846 * Configure RD for a VNI (vty handler)
1847 */
1848 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
1849 struct prefix_rd *rd)
1850 {
1851 /* If the VNI is "live", we need to delete and withdraw this VNI's
1852 * local routes with the prior RD first. Then, after updating RD,
1853 * need to re-advertise.
1854 */
1855 if (is_vni_live(vpn))
1856 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1857
1858 /* update RD */
1859 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
1860 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
1861
1862 if (is_vni_live(vpn))
1863 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1864 }
1865
1866 /*
1867 * Unconfigure RD for a VNI (vty handler)
1868 */
1869 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
1870 {
1871 /* If the VNI is "live", we need to delete and withdraw this VNI's
1872 * local routes with the prior RD first. Then, after resetting RD
1873 * to automatic value, need to re-advertise.
1874 */
1875 if (is_vni_live(vpn))
1876 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1877
1878 /* reset RD to default */
1879 bgp_evpn_derive_auto_rd(bgp, vpn);
1880
1881 if (is_vni_live(vpn))
1882 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1883 }
1884
1885 /*
1886 * Create VNI, if not already present (VTY handler). Mark as configured.
1887 */
1888 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
1889 {
1890 struct bgpevpn *vpn;
1891
1892 if (!bgp->vnihash)
1893 return NULL;
1894
1895 vpn = bgp_evpn_lookup_vni(bgp, vni);
1896 if (!vpn) {
1897 /* Check if this L2VNI is already configured as L3VNI */
1898 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
1899 flog_err(
1900 EC_BGP_VNI,
1901 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1902 bgp->vrf_id, vni);
1903 return NULL;
1904 }
1905
1906 /* tenant vrf will be updated when we get local_vni_add from
1907 * zebra
1908 */
1909 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0);
1910 if (!vpn) {
1911 flog_err(
1912 EC_BGP_VNI,
1913 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1914 bgp->vrf_id, vni);
1915 return NULL;
1916 }
1917 }
1918
1919 /* Mark as configured. */
1920 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1921 return vpn;
1922 }
1923
1924 /*
1925 * Delete VNI. If VNI does not exist in the system (i.e., just
1926 * configuration), all that is needed is to free it. Otherwise,
1927 * any parameters configured for the VNI need to be reset (with
1928 * appropriate action) and the VNI marked as unconfigured; the
1929 * VNI will continue to exist, purely as a "learnt" entity.
1930 */
1931 static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
1932 {
1933 assert(bgp->vnihash);
1934
1935 if (!is_vni_live(vpn)) {
1936 bgp_evpn_free(bgp, vpn);
1937 return 0;
1938 }
1939
1940 /* We need to take the unconfigure action for each parameter of this VNI
1941 * that is configured. Some optimization is possible, but not worth the
1942 * additional code for an operation that should be pretty rare.
1943 */
1944 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1945
1946 /* First, deal with the export side - RD and export RT changes. */
1947 if (is_rd_configured(vpn))
1948 evpn_unconfigure_rd(bgp, vpn);
1949 if (is_export_rt_configured(vpn))
1950 evpn_unconfigure_export_rt(bgp, vpn, NULL);
1951
1952 /* Next, deal with the import side. */
1953 if (is_import_rt_configured(vpn))
1954 evpn_unconfigure_import_rt(bgp, vpn, NULL);
1955
1956 return 0;
1957 }
1958
1959 /*
1960 * Display import RT mapping to VRFs (vty handler)
1961 * bgp_evpn: evpn bgp instance
1962 */
1963 static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
1964 json_object *json)
1965 {
1966 void *args[2];
1967
1968 args[0] = vty;
1969 args[1] = json;
1970
1971 hash_iterate(bgp_evpn->vrf_import_rt_hash,
1972 (void (*)(struct hash_bucket *,
1973 void *))show_vrf_import_rt_entry,
1974 args);
1975 }
1976
1977 /*
1978 * Display import RT mapping to VNIs (vty handler)
1979 */
1980 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
1981 json_object *json)
1982 {
1983 void *args[2];
1984
1985 args[0] = vty;
1986 args[1] = json;
1987
1988 hash_iterate(
1989 bgp->import_rt_hash,
1990 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
1991 args);
1992 }
1993
1994 /*
1995 * Display EVPN routes for all VNIs - vty handler.
1996 */
1997 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
1998 struct in_addr vtep_ip, json_object *json)
1999 {
2000 uint32_t num_vnis;
2001 struct vni_walk_ctx wctx;
2002
2003 num_vnis = hashcount(bgp->vnihash);
2004 if (!num_vnis)
2005 return;
2006 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2007 wctx.bgp = bgp;
2008 wctx.vty = vty;
2009 wctx.vtep_ip = vtep_ip;
2010 wctx.json = json;
2011 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
2012 void *))show_vni_routes_hash,
2013 &wctx);
2014 }
2015
2016 /*
2017 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2018 */
2019 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
2020 vni_t vni, struct in_addr orig_ip,
2021 json_object *json)
2022 {
2023 struct bgpevpn *vpn;
2024 struct prefix_evpn p;
2025 struct bgp_node *rn;
2026 struct bgp_path_info *pi;
2027 uint32_t path_cnt = 0;
2028 afi_t afi;
2029 safi_t safi;
2030 json_object *json_paths = NULL;
2031
2032 afi = AFI_L2VPN;
2033 safi = SAFI_EVPN;
2034
2035 /* Locate VNI. */
2036 vpn = bgp_evpn_lookup_vni(bgp, vni);
2037 if (!vpn) {
2038 vty_out(vty, "VNI not found\n");
2039 return;
2040 }
2041
2042 /* See if route exists. */
2043 build_evpn_type3_prefix(&p, orig_ip);
2044 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2045 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2046 if (!json)
2047 vty_out(vty, "%% Network not in table\n");
2048 return;
2049 }
2050
2051 if (json)
2052 json_paths = json_object_new_array();
2053
2054 /* Prefix and num paths displayed once per prefix. */
2055 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2056
2057 /* Display each path for this prefix. */
2058 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2059 json_object *json_path = NULL;
2060
2061 if (json)
2062 json_path = json_object_new_array();
2063
2064 route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
2065 json_path);
2066
2067 if (json)
2068 json_object_array_add(json_paths, json_path);
2069
2070 path_cnt++;
2071 }
2072
2073 if (json) {
2074 if (path_cnt)
2075 json_object_object_add(json, "paths", json_paths);
2076
2077 json_object_int_add(json, "numPaths", path_cnt);
2078 } else {
2079 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2080 path_cnt);
2081 }
2082 }
2083
2084 /*
2085 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2086 * By definition, only matching type-2 route will be displayed.
2087 */
2088 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2089 vni_t vni, struct ethaddr *mac,
2090 struct ipaddr *ip, json_object *json)
2091 {
2092 struct bgpevpn *vpn;
2093 struct prefix_evpn p;
2094 struct bgp_node *rn;
2095 struct bgp_path_info *pi;
2096 uint32_t path_cnt = 0;
2097 afi_t afi;
2098 safi_t safi;
2099 json_object *json_paths = NULL;
2100
2101 afi = AFI_L2VPN;
2102 safi = SAFI_EVPN;
2103
2104 /* Locate VNI. */
2105 vpn = bgp_evpn_lookup_vni(bgp, vni);
2106 if (!vpn) {
2107 if (!json)
2108 vty_out(vty, "VNI not found\n");
2109 return;
2110 }
2111
2112 /* See if route exists. Look for both non-sticky and sticky. */
2113 build_evpn_type2_prefix(&p, mac, ip);
2114 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2115 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2116 if (!json)
2117 vty_out(vty, "%% Network not in table\n");
2118 return;
2119 }
2120
2121 if (json)
2122 json_paths = json_object_new_array();
2123
2124 /* Prefix and num paths displayed once per prefix. */
2125 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2126
2127 /* Display each path for this prefix. */
2128 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2129 json_object *json_path = NULL;
2130
2131 if (json)
2132 json_path = json_object_new_array();
2133
2134 route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
2135 json_path);
2136
2137 if (json)
2138 json_object_array_add(json_paths, json_path);
2139
2140 path_cnt++;
2141 }
2142
2143 if (json) {
2144 if (path_cnt)
2145 json_object_object_add(json, "paths", json_paths);
2146
2147 json_object_int_add(json, "numPaths", path_cnt);
2148 } else {
2149 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2150 path_cnt);
2151 }
2152 }
2153
2154 /* Disaplay EVPN routes for a ESI - VTY handler */
2155 static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2156 esi_t *esi, json_object *json)
2157 {
2158 struct evpnes *es = NULL;
2159
2160 /* locate the ES */
2161 es = bgp_evpn_lookup_es(bgp, esi);
2162 if (!es) {
2163 if (!json)
2164 vty_out(vty, "ESI not found\n");
2165 return;
2166 }
2167
2168 show_esi_routes(bgp, es, vty, json);
2169 }
2170
2171 /*
2172 * Display EVPN routes for a VNI - vty handler.
2173 * If 'type' is non-zero, only routes matching that type are shown.
2174 * If the vtep_ip is non zero, only routes behind that vtep are shown
2175 */
2176 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2177 int type, struct in_addr vtep_ip,
2178 json_object *json)
2179 {
2180 struct bgpevpn *vpn;
2181
2182 /* Locate VNI. */
2183 vpn = bgp_evpn_lookup_vni(bgp, vni);
2184 if (!vpn) {
2185 if (!json)
2186 vty_out(vty, "VNI not found\n");
2187 return;
2188 }
2189
2190 /* Walk this VNI's route table and display appropriate routes. */
2191 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
2192 }
2193
2194 /*
2195 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2196 * IP (vty handler). By definition, only matching type-2 route will be
2197 * displayed.
2198 */
2199 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2200 struct prefix_rd *prd, struct ethaddr *mac,
2201 struct ipaddr *ip, json_object *json)
2202 {
2203 struct prefix_evpn p;
2204 struct bgp_node *rn;
2205 struct bgp_path_info *pi;
2206 afi_t afi;
2207 safi_t safi;
2208 uint32_t path_cnt = 0;
2209 json_object *json_paths = NULL;
2210 char prefix_str[BUFSIZ];
2211
2212 afi = AFI_L2VPN;
2213 safi = SAFI_EVPN;
2214
2215 /* See if route exists. Look for both non-sticky and sticky. */
2216 build_evpn_type2_prefix(&p, mac, ip);
2217 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2218 (struct prefix *)&p, prd);
2219 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2220 if (!json)
2221 vty_out(vty, "%% Network not in table\n");
2222 return;
2223 }
2224
2225 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
2226 sizeof(prefix_str));
2227
2228 /* Prefix and num paths displayed once per prefix. */
2229 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
2230
2231 if (json)
2232 json_paths = json_object_new_array();
2233
2234 /* Display each path for this prefix. */
2235 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2236 json_object *json_path = NULL;
2237
2238 if (json)
2239 json_path = json_object_new_array();
2240
2241 route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
2242 json_path);
2243
2244 if (json)
2245 json_object_array_add(json_paths, json_path);
2246
2247 path_cnt++;
2248 }
2249
2250 if (json && path_cnt) {
2251 if (path_cnt)
2252 json_object_object_add(json, prefix_str, json_paths);
2253 json_object_int_add(json, "numPaths", path_cnt);
2254 } else {
2255 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2256 path_cnt);
2257 }
2258 }
2259
2260 /*
2261 * Display BGP EVPN routing table -- for specific RD (vty handler)
2262 * If 'type' is non-zero, only routes matching that type are shown.
2263 */
2264 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
2265 struct prefix_rd *prd, int type,
2266 json_object *json)
2267 {
2268 struct bgp_node *rd_rn;
2269 struct bgp_table *table;
2270 struct bgp_node *rn;
2271 struct bgp_path_info *pi;
2272 int rd_header = 1;
2273 afi_t afi;
2274 safi_t safi;
2275 uint32_t prefix_cnt, path_cnt;
2276 char rd_str[RD_ADDRSTRLEN];
2277 json_object *json_rd = NULL;
2278 int add_rd_to_json = 0;
2279
2280 afi = AFI_L2VPN;
2281 safi = SAFI_EVPN;
2282 prefix_cnt = path_cnt = 0;
2283
2284 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
2285
2286 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2287 if (!rd_rn)
2288 return;
2289
2290 table = bgp_node_get_bgp_table_info(rd_rn);
2291 if (table == NULL)
2292 return;
2293
2294 if (json) {
2295 json_rd = json_object_new_object();
2296 json_object_string_add(json_rd, "rd", rd_str);
2297 }
2298
2299 /* Display all prefixes with this RD. */
2300 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2301 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2302 json_object *json_prefix = NULL;
2303 json_object *json_paths = NULL;
2304 char prefix_str[BUFSIZ];
2305 int add_prefix_to_json = 0;
2306
2307 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
2308 sizeof(prefix_str));
2309
2310 if (type && evp->prefix.route_type != type)
2311 continue;
2312
2313 if (json)
2314 json_prefix = json_object_new_object();
2315
2316 pi = bgp_node_get_bgp_path_info(rn);
2317 if (pi) {
2318 /* RD header and legend - once overall. */
2319 if (rd_header && !json) {
2320 vty_out(vty,
2321 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2322 vty_out(vty,
2323 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2324 vty_out(vty,
2325 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2326 rd_header = 0;
2327 }
2328
2329 /* Prefix and num paths displayed once per prefix. */
2330 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
2331 safi, json_prefix);
2332
2333 prefix_cnt++;
2334 }
2335
2336 if (json)
2337 json_paths = json_object_new_array();
2338
2339 /* Display each path for this prefix. */
2340 for (; pi; pi = pi->next) {
2341 json_object *json_path = NULL;
2342
2343 if (json)
2344 json_path = json_object_new_array();
2345
2346 route_vty_out_detail(vty, bgp, &rn->p, pi, afi, safi,
2347 json_path);
2348
2349 if (json)
2350 json_object_array_add(json_paths, json_path);
2351
2352 path_cnt++;
2353 add_prefix_to_json = 1;
2354 add_rd_to_json = 1;
2355 }
2356
2357 if (json && add_prefix_to_json) {
2358 json_object_object_add(json_prefix, "paths",
2359 json_paths);
2360 json_object_object_add(json_rd, prefix_str,
2361 json_prefix);
2362 }
2363 }
2364
2365 if (json && add_rd_to_json)
2366 json_object_object_add(json, rd_str, json_rd);
2367
2368 if (json) {
2369 json_object_int_add(json, "numPrefix", prefix_cnt);
2370 json_object_int_add(json, "numPaths", path_cnt);
2371 } else {
2372 if (prefix_cnt == 0)
2373 vty_out(vty, "No prefixes exist with this RD%s\n",
2374 type ? " (of requested type)" : "");
2375 else
2376 vty_out(vty,
2377 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2378 prefix_cnt, path_cnt,
2379 type ? " (of requested type)" : "");
2380 }
2381 }
2382
2383 /*
2384 * Display BGP EVPN routing table - all routes (vty handler).
2385 * If 'type' is non-zero, only routes matching that type are shown.
2386 */
2387 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2388 json_object *json)
2389 {
2390 struct bgp_node *rd_rn;
2391 struct bgp_table *table;
2392 struct bgp_node *rn;
2393 struct bgp_path_info *pi;
2394 int header = 1;
2395 int rd_header;
2396 afi_t afi;
2397 safi_t safi;
2398 uint32_t prefix_cnt, path_cnt;
2399
2400 afi = AFI_L2VPN;
2401 safi = SAFI_EVPN;
2402 prefix_cnt = path_cnt = 0;
2403
2404 /* EVPN routing table is a 2-level table with the first level being
2405 * the RD.
2406 */
2407 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2408 rd_rn = bgp_route_next(rd_rn)) {
2409 char rd_str[RD_ADDRSTRLEN];
2410 json_object *json_rd = NULL; /* contains routes for an RD */
2411 int add_rd_to_json = 0;
2412 uint64_t tbl_ver;
2413
2414 table = bgp_node_get_bgp_table_info(rd_rn);
2415 if (table == NULL)
2416 continue;
2417
2418 tbl_ver = table->version;
2419 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2420 sizeof(rd_str));
2421
2422 if (json) {
2423 json_rd = json_object_new_object();
2424 json_object_string_add(json_rd, "rd", rd_str);
2425 }
2426
2427 rd_header = 1;
2428
2429 /* Display all prefixes for an RD */
2430 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2431 json_object *json_prefix =
2432 NULL; /* contains prefix under a RD */
2433 json_object *json_paths =
2434 NULL; /* array of paths under a prefix*/
2435 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2436 char prefix_str[BUFSIZ];
2437 int add_prefix_to_json = 0;
2438
2439 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2440 prefix_str, sizeof(prefix_str));
2441
2442 if (type && evp->prefix.route_type != type)
2443 continue;
2444
2445 pi = bgp_node_get_bgp_path_info(rn);
2446 if (pi) {
2447 /* Overall header/legend displayed once. */
2448 if (header) {
2449 bgp_evpn_show_route_header(vty, bgp,
2450 tbl_ver,
2451 json);
2452 header = 0;
2453 }
2454
2455 /* RD header - per RD. */
2456 if (rd_header) {
2457 bgp_evpn_show_route_rd_header(
2458 vty, rd_rn, json);
2459 rd_header = 0;
2460 }
2461
2462 prefix_cnt++;
2463 }
2464
2465 if (json) {
2466 json_prefix = json_object_new_object();
2467 json_paths = json_object_new_array();
2468 json_object_string_add(json_prefix, "prefix",
2469 prefix_str);
2470 json_object_int_add(json_prefix, "prefixLen",
2471 rn->p.prefixlen);
2472 }
2473
2474 /* For EVPN, the prefix is displayed for each path (to
2475 * fit in
2476 * with code that already exists).
2477 */
2478 for (; pi; pi = pi->next) {
2479 json_object *json_path = NULL;
2480 path_cnt++;
2481 add_prefix_to_json = 1;
2482 add_rd_to_json = 1;
2483
2484 if (json)
2485 json_path = json_object_new_array();
2486
2487 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
2488 json_path);
2489
2490 if (json)
2491 json_object_array_add(json_paths,
2492 json_path);
2493 }
2494
2495 if (json && add_prefix_to_json) {
2496 json_object_object_add(json_prefix, "paths",
2497 json_paths);
2498 json_object_object_add(json_rd, prefix_str,
2499 json_prefix);
2500 }
2501 }
2502
2503 if (json && add_rd_to_json)
2504 json_object_object_add(json, rd_str, json_rd);
2505 }
2506
2507 if (json) {
2508 json_object_int_add(json, "numPrefix", prefix_cnt);
2509 json_object_int_add(json, "numPaths", path_cnt);
2510 } else {
2511 if (prefix_cnt == 0) {
2512 vty_out(vty, "No EVPN prefixes %sexist\n",
2513 type ? "(of requested type) " : "");
2514 } else {
2515 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2516 prefix_cnt, path_cnt,
2517 type ? " (of requested type)" : "");
2518 }
2519 }
2520 }
2521
2522 /* Display specific ES */
2523 static void evpn_show_es(struct vty *vty, struct bgp *bgp, esi_t *esi,
2524 json_object *json)
2525 {
2526 struct evpnes *es = NULL;
2527
2528 es = bgp_evpn_lookup_es(bgp, esi);
2529 if (es) {
2530 display_es(vty, es, json);
2531 } else {
2532 if (json) {
2533 vty_out(vty, "{}\n");
2534 } else {
2535 vty_out(vty, "ESI not found\n");
2536 return;
2537 }
2538 }
2539 }
2540
2541 /* Display all ESs */
2542 static void evpn_show_all_es(struct vty *vty, struct bgp *bgp,
2543 json_object *json)
2544 {
2545 void *args[2];
2546
2547 if (!json)
2548 vty_out(vty, "%-30s %-6s %-21s %-15s %-6s\n",
2549 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2550
2551 /* print all ESs */
2552 args[0] = vty;
2553 args[1] = json;
2554 hash_iterate(bgp->esihash,
2555 (void (*)(struct hash_bucket *, void *))show_es_entry,
2556 args);
2557 }
2558
2559 /*
2560 * Display specified VNI (vty handler)
2561 */
2562 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2563 json_object *json)
2564 {
2565 uint8_t found = 0;
2566 struct bgpevpn *vpn;
2567
2568 vpn = bgp_evpn_lookup_vni(bgp, vni);
2569 if (vpn) {
2570 found = 1;
2571 display_vni(vty, vpn, json);
2572 } else {
2573 struct bgp *bgp_temp;
2574 struct listnode *node = NULL;
2575
2576 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2577 if (bgp_temp->l3vni == vni) {
2578 found = 1;
2579 display_l3vni(vty, bgp_temp, json);
2580 }
2581 }
2582 }
2583
2584 if (!found) {
2585 if (json) {
2586 vty_out(vty, "{}\n");
2587 } else {
2588 vty_out(vty, "VNI not found\n");
2589 return;
2590 }
2591 }
2592 }
2593
2594 /*
2595 * Display a VNI (upon user query).
2596 */
2597 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2598 json_object *json)
2599 {
2600 void *args[2];
2601 struct bgp *bgp_temp = NULL;
2602 struct listnode *node;
2603
2604
2605 if (!json) {
2606 vty_out(vty, "Flags: * - Kernel\n");
2607 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2608 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2609 }
2610
2611 /* print all L2 VNIS */
2612 args[0] = vty;
2613 args[1] = json;
2614 hash_iterate(bgp->vnihash,
2615 (void (*)(struct hash_bucket *, void *))show_vni_entry,
2616 args);
2617
2618 /* print all L3 VNIs */
2619 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
2620 show_l3vni_entry(vty, bgp_temp, json);
2621 }
2622
2623 /*
2624 * evpn - enable advertisement of svi MAC-IP
2625 */
2626 static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
2627 uint32_t set)
2628 {
2629 if (!vpn) {
2630 if (set && bgp->evpn_info->advertise_svi_macip)
2631 return;
2632 else if (!set && !bgp->evpn_info->advertise_svi_macip)
2633 return;
2634
2635 bgp->evpn_info->advertise_svi_macip = set;
2636 bgp_zebra_advertise_svi_macip(bgp,
2637 bgp->evpn_info->advertise_svi_macip, 0);
2638 } else {
2639 if (set && vpn->advertise_svi_macip)
2640 return;
2641 else if (!set && !vpn->advertise_svi_macip)
2642 return;
2643
2644 vpn->advertise_svi_macip = set;
2645 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
2646 vpn->vni);
2647 }
2648 }
2649
2650 /*
2651 * evpn - enable advertisement of default g/w
2652 */
2653 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2654 {
2655 if (!vpn) {
2656 if (bgp->advertise_gw_macip)
2657 return;
2658
2659 bgp->advertise_gw_macip = 1;
2660 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2661 } else {
2662 if (vpn->advertise_gw_macip)
2663 return;
2664
2665 vpn->advertise_gw_macip = 1;
2666 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2667 vpn->vni);
2668 }
2669 return;
2670 }
2671
2672 /*
2673 * evpn - disable advertisement of default g/w
2674 */
2675 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2676 struct bgpevpn *vpn)
2677 {
2678 if (!vpn) {
2679 if (!bgp->advertise_gw_macip)
2680 return;
2681
2682 bgp->advertise_gw_macip = 0;
2683 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2684 } else {
2685 if (!vpn->advertise_gw_macip)
2686 return;
2687
2688 vpn->advertise_gw_macip = 0;
2689 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2690 vpn->vni);
2691 }
2692 return;
2693 }
2694
2695 /*
2696 * evpn - enable advertisement of default g/w
2697 */
2698 static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
2699 afi_t afi, bool add)
2700 {
2701 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
2702
2703 if (add) {
2704 /* bail if we are already advertising default route */
2705 if (evpn_default_originate_set(bgp_vrf, afi, safi))
2706 return;
2707
2708 if (afi == AFI_IP)
2709 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2710 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2711 else if (afi == AFI_IP6)
2712 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2713 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2714 } else {
2715 /* bail out if we havent advertised the default route */
2716 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
2717 return;
2718 if (afi == AFI_IP)
2719 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2720 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2721 else if (afi == AFI_IP6)
2722 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2723 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2724 }
2725
2726 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
2727 }
2728
2729 /*
2730 * evpn - enable advertisement of default g/w
2731 */
2732 static void evpn_set_advertise_subnet(struct bgp *bgp,
2733 struct bgpevpn *vpn)
2734 {
2735 if (vpn->advertise_subnet)
2736 return;
2737
2738 vpn->advertise_subnet = 1;
2739 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2740 }
2741
2742 /*
2743 * evpn - disable advertisement of default g/w
2744 */
2745 static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
2746 {
2747 if (!vpn->advertise_subnet)
2748 return;
2749
2750 vpn->advertise_subnet = 0;
2751 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2752 }
2753
2754 /*
2755 * EVPN (VNI advertisement) enabled. Register with zebra.
2756 */
2757 static void evpn_set_advertise_all_vni(struct bgp *bgp)
2758 {
2759 bgp->advertise_all_vni = 1;
2760 bgp_set_evpn(bgp);
2761 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2762 }
2763
2764 /*
2765 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2766 * cache, EVPN routes (delete and withdraw from peers).
2767 */
2768 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
2769 {
2770 bgp->advertise_all_vni = 0;
2771 bgp_set_evpn(bgp_get_default());
2772 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2773 bgp_evpn_cleanup_on_disable(bgp);
2774 }
2775
2776 /*
2777 * EVPN - use RFC8365 to auto-derive RT
2778 */
2779 static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
2780 {
2781 bgp->advertise_autort_rfc8365 = 1;
2782 bgp_evpn_handle_autort_change(bgp);
2783 }
2784
2785 /*
2786 * EVPN - don't use RFC8365 to auto-derive RT
2787 */
2788 static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
2789 {
2790 bgp->advertise_autort_rfc8365 = 0;
2791 bgp_evpn_handle_autort_change(bgp);
2792 }
2793
2794 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
2795 {
2796 char buf1[RD_ADDRSTRLEN];
2797 char *ecom_str;
2798 struct listnode *node, *nnode;
2799 struct ecommunity *ecom;
2800
2801 if (is_vni_configured(vpn)) {
2802 vty_out(vty, " vni %d\n", vpn->vni);
2803 if (is_rd_configured(vpn))
2804 vty_out(vty, " rd %s\n",
2805 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
2806
2807 if (is_import_rt_configured(vpn)) {
2808 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2809 ecom)) {
2810 ecom_str = ecommunity_ecom2str(
2811 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2812 vty_out(vty, " route-target import %s\n",
2813 ecom_str);
2814 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2815 }
2816 }
2817
2818 if (is_export_rt_configured(vpn)) {
2819 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2820 ecom)) {
2821 ecom_str = ecommunity_ecom2str(
2822 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2823 vty_out(vty, " route-target export %s\n",
2824 ecom_str);
2825 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2826 }
2827 }
2828
2829 if (vpn->advertise_gw_macip)
2830 vty_out(vty, " advertise-default-gw\n");
2831
2832 if (vpn->advertise_svi_macip)
2833 vty_out(vty, " advertise-svi-ip\n");
2834
2835 if (vpn->advertise_subnet)
2836 vty_out(vty, " advertise-subnet\n");
2837
2838 vty_out(vty, " exit-vni\n");
2839 }
2840 }
2841
2842 #ifndef VTYSH_EXTRACT_PL
2843 #include "bgpd/bgp_evpn_vty_clippy.c"
2844 #endif
2845
2846 DEFPY(bgp_evpn_flood_control,
2847 bgp_evpn_flood_control_cmd,
2848 "[no$no] flooding <disable$disable|head-end-replication$her>",
2849 NO_STR
2850 "Specify handling for BUM packets\n"
2851 "Do not flood any BUM packets\n"
2852 "Flood BUM packets using head-end replication\n")
2853 {
2854 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2855 enum vxlan_flood_control flood_ctrl;
2856
2857 if (!bgp)
2858 return CMD_WARNING;
2859
2860 if (disable && !no)
2861 flood_ctrl = VXLAN_FLOOD_DISABLED;
2862 else if (her || no)
2863 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
2864 else
2865 return CMD_WARNING;
2866
2867 if (bgp->vxlan_flood_ctrl == flood_ctrl)
2868 return CMD_SUCCESS;
2869
2870 bgp->vxlan_flood_ctrl = flood_ctrl;
2871 bgp_evpn_flood_control_change(bgp);
2872
2873 return CMD_SUCCESS;
2874 }
2875
2876 DEFUN (bgp_evpn_advertise_default_gw_vni,
2877 bgp_evpn_advertise_default_gw_vni_cmd,
2878 "advertise-default-gw",
2879 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2880 {
2881 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2882 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2883
2884 if (!bgp)
2885 return CMD_WARNING;
2886
2887 evpn_set_advertise_default_gw(bgp, vpn);
2888
2889 return CMD_SUCCESS;
2890 }
2891
2892 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2893 no_bgp_evpn_advertise_default_gw_vni_cmd,
2894 "no advertise-default-gw",
2895 NO_STR
2896 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2897 {
2898 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2899 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2900
2901 if (!bgp)
2902 return CMD_WARNING;
2903
2904 evpn_unset_advertise_default_gw(bgp, vpn);
2905
2906 return CMD_SUCCESS;
2907 }
2908
2909
2910 DEFUN (bgp_evpn_advertise_default_gw,
2911 bgp_evpn_advertise_default_gw_cmd,
2912 "advertise-default-gw",
2913 "Advertise All default g/w mac-ip routes in EVPN\n")
2914 {
2915 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2916
2917 if (!bgp)
2918 return CMD_WARNING;
2919
2920 if (!bgp->advertise_all_vni) {
2921 vty_out(vty,
2922 "This command is only supported under the EVPN VRF\n");
2923 return CMD_WARNING;
2924 }
2925
2926 evpn_set_advertise_default_gw(bgp, NULL);
2927
2928 return CMD_SUCCESS;
2929 }
2930
2931 DEFUN (no_bgp_evpn_advertise_default_gw,
2932 no_bgp_evpn_advertise_default_gw_cmd,
2933 "no advertise-default-gw",
2934 NO_STR
2935 "Withdraw All default g/w mac-ip routes from EVPN\n")
2936 {
2937 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2938
2939 if (!bgp)
2940 return CMD_WARNING;
2941
2942 if (!bgp->advertise_all_vni) {
2943 vty_out(vty,
2944 "This command is only supported under the EVPN VRF\n");
2945 return CMD_WARNING;
2946 }
2947
2948 evpn_unset_advertise_default_gw(bgp, NULL);
2949
2950 return CMD_SUCCESS;
2951 }
2952
2953 DEFUN (bgp_evpn_advertise_all_vni,
2954 bgp_evpn_advertise_all_vni_cmd,
2955 "advertise-all-vni",
2956 "Advertise All local VNIs\n")
2957 {
2958 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2959 struct bgp *bgp_evpn = NULL;
2960
2961 if (!bgp)
2962 return CMD_WARNING;
2963
2964 bgp_evpn = bgp_get_evpn();
2965 if (bgp_evpn && bgp_evpn != bgp) {
2966 vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n",
2967 bgp_evpn->name);
2968 return CMD_WARNING_CONFIG_FAILED;
2969 }
2970
2971 evpn_set_advertise_all_vni(bgp);
2972 return CMD_SUCCESS;
2973 }
2974
2975 DEFUN (no_bgp_evpn_advertise_all_vni,
2976 no_bgp_evpn_advertise_all_vni_cmd,
2977 "no advertise-all-vni",
2978 NO_STR
2979 "Advertise All local VNIs\n")
2980 {
2981 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2982
2983 if (!bgp)
2984 return CMD_WARNING;
2985 evpn_unset_advertise_all_vni(bgp);
2986 return CMD_SUCCESS;
2987 }
2988
2989 DEFUN (bgp_evpn_advertise_autort_rfc8365,
2990 bgp_evpn_advertise_autort_rfc8365_cmd,
2991 "autort rfc8365-compatible",
2992 "Auto-derivation of RT\n"
2993 "Auto-derivation of RT using RFC8365\n")
2994 {
2995 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2996
2997 if (!bgp)
2998 return CMD_WARNING;
2999 evpn_set_advertise_autort_rfc8365(bgp);
3000 return CMD_SUCCESS;
3001 }
3002
3003 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3004 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3005 "no autort rfc8365-compatible",
3006 NO_STR
3007 "Auto-derivation of RT\n"
3008 "Auto-derivation of RT using RFC8365\n")
3009 {
3010 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3011
3012 if (!bgp)
3013 return CMD_WARNING;
3014 evpn_unset_advertise_autort_rfc8365(bgp);
3015 return CMD_SUCCESS;
3016 }
3017
3018 DEFUN (bgp_evpn_default_originate,
3019 bgp_evpn_default_originate_cmd,
3020 "default-originate <ipv4 | ipv6>",
3021 "originate a default route\n"
3022 "ipv4 address family\n"
3023 "ipv6 address family\n")
3024 {
3025 afi_t afi = 0;
3026 int idx_afi = 0;
3027 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3028
3029 if (!bgp_vrf)
3030 return CMD_WARNING;
3031 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3032 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3033 return CMD_SUCCESS;
3034 }
3035
3036 DEFUN (no_bgp_evpn_default_originate,
3037 no_bgp_evpn_default_originate_cmd,
3038 "no default-originate <ipv4 | ipv6>",
3039 NO_STR
3040 "withdraw a default route\n"
3041 "ipv4 address family\n"
3042 "ipv6 address family\n")
3043 {
3044 afi_t afi = 0;
3045 int idx_afi = 0;
3046 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3047
3048 if (!bgp_vrf)
3049 return CMD_WARNING;
3050 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3051 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3052 return CMD_SUCCESS;
3053 }
3054
3055 DEFPY (dup_addr_detection,
3056 dup_addr_detection_cmd,
3057 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3058 "Duplicate address detection\n"
3059 "Max allowed moves before address detected as duplicate\n"
3060 "Num of max allowed moves (2-1000) default 5\n"
3061 "Duplicate address detection time\n"
3062 "Time in seconds (2-1800) default 180\n")
3063 {
3064 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3065
3066 if (!bgp_vrf)
3067 return CMD_WARNING;
3068
3069 if (!bgp_vrf->advertise_all_vni) {
3070 vty_out(vty,
3071 "This command is only supported under the EVPN VRF\n");
3072 return CMD_WARNING;
3073 }
3074
3075 bgp_vrf->evpn_info->dup_addr_detect = true;
3076
3077 if (time_val)
3078 bgp_vrf->evpn_info->dad_time = time_val;
3079 if (max_moves_val)
3080 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3081
3082 bgp_zebra_dup_addr_detection(bgp_vrf);
3083
3084 return CMD_SUCCESS;
3085 }
3086
3087 DEFPY (dup_addr_detection_auto_recovery,
3088 dup_addr_detection_auto_recovery_cmd,
3089 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3090 "Duplicate address detection\n"
3091 "Duplicate address detection freeze\n"
3092 "Duplicate address detection permanent freeze\n"
3093 "Duplicate address detection freeze time (30-3600)\n")
3094 {
3095 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3096 uint32_t freeze_time = freeze_time_val;
3097
3098 if (!bgp_vrf)
3099 return CMD_WARNING;
3100
3101 if (!bgp_vrf->advertise_all_vni) {
3102 vty_out(vty,
3103 "This command is only supported under the EVPN VRF\n");
3104 return CMD_WARNING;
3105 }
3106
3107 bgp_vrf->evpn_info->dup_addr_detect = true;
3108 bgp_vrf->evpn_info->dad_freeze = true;
3109 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3110
3111 bgp_zebra_dup_addr_detection(bgp_vrf);
3112
3113 return CMD_SUCCESS;
3114 }
3115
3116 DEFPY (no_dup_addr_detection,
3117 no_dup_addr_detection_cmd,
3118 "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3119 NO_STR
3120 "Duplicate address detection\n"
3121 "Max allowed moves before address detected as duplicate\n"
3122 "Num of max allowed moves (2-1000) default 5\n"
3123 "Duplicate address detection time\n"
3124 "Time in seconds (2-1800) default 180\n"
3125 "Duplicate address detection freeze\n"
3126 "Duplicate address detection permanent freeze\n"
3127 "Duplicate address detection freeze time (30-3600)\n")
3128 {
3129 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3130 uint32_t max_moves = (uint32_t)max_moves_val;
3131 uint32_t freeze_time = (uint32_t)freeze_time_val;
3132
3133 if (!bgp_vrf)
3134 return CMD_WARNING;
3135
3136 if (!bgp_vrf->advertise_all_vni) {
3137 vty_out(vty,
3138 "This command is only supported under the EVPN VRF\n");
3139 return CMD_WARNING;
3140 }
3141
3142 if (argc == 2) {
3143 if (!bgp_vrf->evpn_info->dup_addr_detect)
3144 return CMD_SUCCESS;
3145 /* Reset all parameters to default. */
3146 bgp_vrf->evpn_info->dup_addr_detect = false;
3147 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3148 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3149 bgp_vrf->evpn_info->dad_freeze = false;
3150 bgp_vrf->evpn_info->dad_freeze_time = 0;
3151 } else {
3152 if (max_moves) {
3153 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3154 vty_out(vty,
3155 "%% Value does not match with config\n");
3156 return CMD_SUCCESS;
3157 }
3158 bgp_vrf->evpn_info->dad_max_moves =
3159 EVPN_DAD_DEFAULT_MAX_MOVES;
3160 }
3161
3162 if (time_val) {
3163 if (bgp_vrf->evpn_info->dad_time != time_val) {
3164 vty_out(vty,
3165 "%% Value does not match with config\n");
3166 return CMD_SUCCESS;
3167 }
3168 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3169 }
3170
3171 if (freeze_time) {
3172 if (bgp_vrf->evpn_info->dad_freeze_time
3173 != freeze_time) {
3174 vty_out(vty,
3175 "%% Value does not match with config\n");
3176 return CMD_SUCCESS;
3177 }
3178 bgp_vrf->evpn_info->dad_freeze_time = 0;
3179 bgp_vrf->evpn_info->dad_freeze = false;
3180 }
3181
3182 if (permanent_val) {
3183 if (bgp_vrf->evpn_info->dad_freeze_time) {
3184 vty_out(vty,
3185 "%% Value does not match with config\n");
3186 return CMD_SUCCESS;
3187 }
3188 bgp_vrf->evpn_info->dad_freeze = false;
3189 }
3190 }
3191
3192 bgp_zebra_dup_addr_detection(bgp_vrf);
3193
3194 return CMD_SUCCESS;
3195 }
3196
3197 DEFPY(bgp_evpn_advertise_svi_ip,
3198 bgp_evpn_advertise_svi_ip_cmd,
3199 "[no$no] advertise-svi-ip",
3200 NO_STR
3201 "Advertise svi mac-ip routes in EVPN\n")
3202 {
3203 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3204
3205 if (!bgp)
3206 return CMD_WARNING;
3207
3208 if (!bgp->advertise_all_vni) {
3209 vty_out(vty,
3210 "This command is only supported under EVPN VRF\n");
3211 return CMD_WARNING;
3212 }
3213
3214 if (no)
3215 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3216 else
3217 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3218
3219 return CMD_SUCCESS;
3220 }
3221
3222 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3223 bgp_evpn_advertise_svi_ip_vni_cmd,
3224 "[no$no] advertise-svi-ip",
3225 NO_STR
3226 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3227 {
3228 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3229 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3230
3231 if (!bgp)
3232 return CMD_WARNING;
3233
3234 if (!vpn)
3235 return CMD_WARNING;
3236
3237 if (no)
3238 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3239 else
3240 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3241
3242 return CMD_SUCCESS;
3243 }
3244
3245 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3246 bgp_evpn_advertise_vni_subnet_cmd,
3247 "advertise-subnet",
3248 "Advertise the subnet corresponding to VNI\n")
3249 {
3250 struct bgp *bgp_vrf = NULL;
3251 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3252 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3253
3254 if (!bgp)
3255 return CMD_WARNING;
3256
3257 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3258 if (!bgp_vrf)
3259 return CMD_WARNING;
3260
3261 evpn_set_advertise_subnet(bgp, vpn);
3262 return CMD_SUCCESS;
3263 }
3264
3265 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3266 no_bgp_evpn_advertise_vni_subnet_cmd,
3267 "no advertise-subnet",
3268 NO_STR
3269 "Advertise All local VNIs\n")
3270 {
3271 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3272 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3273
3274 if (!bgp)
3275 return CMD_WARNING;
3276
3277 evpn_unset_advertise_subnet(bgp, vpn);
3278 return CMD_SUCCESS;
3279 }
3280
3281 DEFUN (bgp_evpn_advertise_type5,
3282 bgp_evpn_advertise_type5_cmd,
3283 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
3284 "Advertise prefix routes\n"
3285 BGP_AFI_HELP_STR
3286 BGP_SAFI_HELP_STR
3287 "route-map for filtering specific routes\n"
3288 "Name of the route map\n")
3289 {
3290 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3291 int idx_afi = 0;
3292 int idx_safi = 0;
3293 int idx_rmap = 0;
3294 afi_t afi = 0;
3295 safi_t safi = 0;
3296 int ret = 0;
3297 int rmap_changed = 0;
3298
3299 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3300 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3301 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3302 if (ret) {
3303 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3304 rmap_changed = 1;
3305 else if (strcmp(argv[idx_rmap + 1]->arg,
3306 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3307 != 0)
3308 rmap_changed = 1;
3309 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3310 rmap_changed = 1;
3311 }
3312
3313 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3314 vty_out(vty,
3315 "%%only ipv4 or ipv6 address families are supported");
3316 return CMD_WARNING;
3317 }
3318
3319 if (safi != SAFI_UNICAST) {
3320 vty_out(vty,
3321 "%%only ipv4 unicast or ipv6 unicast are supported");
3322 return CMD_WARNING;
3323 }
3324
3325 if (afi == AFI_IP) {
3326
3327 /* if we are already advertising ipv4 prefix as type-5
3328 * nothing to do
3329 */
3330 if (!rmap_changed &&
3331 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3332 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
3333 return CMD_WARNING;
3334 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3335 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3336 } else {
3337
3338 /* if we are already advertising ipv6 prefix as type-5
3339 * nothing to do
3340 */
3341 if (!rmap_changed &&
3342 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3343 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
3344 return CMD_WARNING;
3345 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3346 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3347 }
3348
3349 if (rmap_changed) {
3350 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3351 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3352 XFREE(MTYPE_ROUTE_MAP_NAME,
3353 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3354 route_map_counter_decrement(
3355 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3356 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3357 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3358 }
3359 }
3360
3361 /* set the route-map for advertise command */
3362 if (ret && argv[idx_rmap + 1]->arg) {
3363 bgp_vrf->adv_cmd_rmap[afi][safi].name =
3364 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
3365 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3366 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3367 route_map_counter_increment(
3368 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3369 }
3370
3371 /* advertise type-5 routes */
3372 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
3373 return CMD_SUCCESS;
3374 }
3375
3376 DEFUN (no_bgp_evpn_advertise_type5,
3377 no_bgp_evpn_advertise_type5_cmd,
3378 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
3379 NO_STR
3380 "Advertise prefix routes\n"
3381 BGP_AFI_HELP_STR
3382 BGP_SAFI_HELP_STR)
3383 {
3384 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3385 int idx_afi = 0;
3386 int idx_safi = 0;
3387 afi_t afi = 0;
3388 safi_t safi = 0;
3389
3390 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3391 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3392
3393 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3394 vty_out(vty,
3395 "%%only ipv4 or ipv6 address families are supported");
3396 return CMD_WARNING;
3397 }
3398
3399 if (safi != SAFI_UNICAST) {
3400 vty_out(vty,
3401 "%%only ipv4 unicast or ipv6 unicast are supported");
3402 return CMD_WARNING;
3403 }
3404
3405 if (afi == AFI_IP) {
3406
3407 /* if we are not advertising ipv4 prefix as type-5
3408 * nothing to do
3409 */
3410 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3411 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
3412 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3413 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3414 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3415 }
3416 } else {
3417
3418 /* if we are not advertising ipv6 prefix as type-5
3419 * nothing to do
3420 */
3421 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3422 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
3423 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3424 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3425 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3426 }
3427 }
3428
3429 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3430 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3431 XFREE(MTYPE_ROUTE_MAP_NAME,
3432 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3433 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3434 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3435 }
3436
3437 return CMD_SUCCESS;
3438 }
3439
3440 /*
3441 * Display VNI information - for all or a specific VNI
3442 */
3443 DEFUN(show_bgp_l2vpn_evpn_vni,
3444 show_bgp_l2vpn_evpn_vni_cmd,
3445 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
3446 SHOW_STR
3447 BGP_STR
3448 L2VPN_HELP_STR
3449 EVPN_HELP_STR
3450 "Show VNI\n"
3451 "VNI number\n"
3452 JSON_STR)
3453 {
3454 struct bgp *bgp_evpn;
3455 vni_t vni;
3456 int idx = 0;
3457 bool uj = false;
3458 json_object *json = NULL;
3459 uint32_t num_l2vnis = 0;
3460 uint32_t num_l3vnis = 0;
3461 uint32_t num_vnis = 0;
3462 struct listnode *node = NULL;
3463 struct bgp *bgp_temp = NULL;
3464
3465 uj = use_json(argc, argv);
3466
3467 bgp_evpn = bgp_get_evpn();
3468 if (!bgp_evpn)
3469 return CMD_WARNING;
3470
3471 if (!argv_find(argv, argc, "evpn", &idx))
3472 return CMD_WARNING;
3473
3474 if (uj)
3475 json = json_object_new_object();
3476
3477 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
3478
3479 num_l2vnis = hashcount(bgp_evpn->vnihash);
3480
3481 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3482 if (bgp_temp->l3vni)
3483 num_l3vnis++;
3484 }
3485 num_vnis = num_l2vnis + num_l3vnis;
3486 if (uj) {
3487 json_object_string_add(json, "advertiseGatewayMacip",
3488 bgp_evpn->advertise_gw_macip
3489 ? "Enabled"
3490 : "Disabled");
3491 json_object_string_add(json, "advertiseAllVnis",
3492 is_evpn_enabled() ? "Enabled"
3493 : "Disabled");
3494 json_object_string_add(
3495 json, "flooding",
3496 bgp_evpn->vxlan_flood_ctrl
3497 == VXLAN_FLOOD_HEAD_END_REPL
3498 ? "Head-end replication"
3499 : "Disabled");
3500 json_object_int_add(json, "numVnis", num_vnis);
3501 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3502 json_object_int_add(json, "numL3Vnis", num_l3vnis);
3503 } else {
3504 vty_out(vty, "Advertise Gateway Macip: %s\n",
3505 bgp_evpn->advertise_gw_macip ? "Enabled"
3506 : "Disabled");
3507 vty_out(vty, "Advertise SVI Macip: %s\n",
3508 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
3509 : "Disabled");
3510 vty_out(vty, "Advertise All VNI flag: %s\n",
3511 is_evpn_enabled() ? "Enabled" : "Disabled");
3512 vty_out(vty, "BUM flooding: %s\n",
3513 bgp_evpn->vxlan_flood_ctrl
3514 == VXLAN_FLOOD_HEAD_END_REPL
3515 ? "Head-end replication"
3516 : "Disabled");
3517 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3518 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
3519 }
3520 evpn_show_all_vnis(vty, bgp_evpn, json);
3521 } else {
3522 int vni_idx = 0;
3523
3524 if (!argv_find(argv, argc, "vni", &vni_idx))
3525 return CMD_WARNING;
3526
3527 /* Display specific VNI */
3528 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
3529 evpn_show_vni(vty, bgp_evpn, vni, json);
3530 }
3531
3532 if (uj) {
3533 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3534 json, JSON_C_TO_STRING_PRETTY));
3535 json_object_free(json);
3536 }
3537
3538 return CMD_SUCCESS;
3539 }
3540
3541 /* Disaply ES */
3542 DEFUN(show_bgp_l2vpn_evpn_es,
3543 show_bgp_l2vpn_evpn_es_cmd,
3544 "show bgp l2vpn evpn es [ESI] [json]",
3545 SHOW_STR
3546 BGP_STR
3547 L2VPN_HELP_STR
3548 EVPN_HELP_STR
3549 "ethernet-Segment\n"
3550 "Ethernet-Segment Identifier\n"
3551 JSON_STR)
3552 {
3553 int idx = 0;
3554 bool uj = false;
3555 esi_t esi;
3556 json_object *json = NULL;
3557 struct bgp *bgp = NULL;
3558
3559 memset(&esi, 0, sizeof(esi));
3560 uj = use_json(argc, argv);
3561
3562 bgp = bgp_get_evpn();
3563 if (!bgp)
3564 return CMD_WARNING;
3565
3566 if (!argv_find(argv, argc, "evpn", &idx))
3567 return CMD_WARNING;
3568
3569 if ((uj && argc == ((idx + 1) + 2)) ||
3570 (!uj && argc == (idx + 1) + 1)) {
3571
3572 /* show all ESs */
3573 evpn_show_all_es(vty, bgp, json);
3574 } else {
3575
3576 /* show a specific ES */
3577
3578 /* get the ESI - ESI-ID is at argv[5] */
3579 if (!str_to_esi(argv[idx + 2]->arg, &esi)) {
3580 vty_out(vty, "%% Malformed ESI\n");
3581 return CMD_WARNING;
3582 }
3583 evpn_show_es(vty, bgp, &esi, json);
3584 }
3585
3586 if (uj) {
3587 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3588 json, JSON_C_TO_STRING_PRETTY));
3589 json_object_free(json);
3590 }
3591
3592 return CMD_SUCCESS;
3593 }
3594
3595 /*
3596 * Display EVPN neighbor summary.
3597 */
3598 DEFUN(show_bgp_l2vpn_evpn_summary,
3599 show_bgp_l2vpn_evpn_summary_cmd,
3600 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3601 SHOW_STR
3602 BGP_STR
3603 "bgp vrf\n"
3604 "vrf name\n"
3605 L2VPN_HELP_STR
3606 EVPN_HELP_STR
3607 "Summary of BGP neighbor status\n"
3608 JSON_STR)
3609 {
3610 int idx_vrf = 0;
3611 bool uj = use_json(argc, argv);
3612 char *vrf = NULL;
3613
3614 if (argv_find(argv, argc, "vrf", &idx_vrf))
3615 vrf = argv[++idx_vrf]->arg;
3616 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, uj);
3617 }
3618
3619 /*
3620 * Display global EVPN routing table.
3621 */
3622 DEFUN(show_bgp_l2vpn_evpn_route,
3623 show_bgp_l2vpn_evpn_route_cmd,
3624 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3625 SHOW_STR
3626 BGP_STR
3627 L2VPN_HELP_STR
3628 EVPN_HELP_STR
3629 "EVPN route information\n"
3630 "Specify Route type\n"
3631 "MAC-IP (Type-2) route\n"
3632 "Multicast (Type-3) route\n"
3633 "Ethernet Segment (type-4) route \n"
3634 "Prefix (type-5 )route\n"
3635 JSON_STR)
3636 {
3637 struct bgp *bgp;
3638 int type_idx = 0;
3639 int type = 0;
3640 bool uj = false;
3641 json_object *json = NULL;
3642
3643 uj = use_json(argc, argv);
3644
3645 bgp = bgp_get_evpn();
3646 if (!bgp)
3647 return CMD_WARNING;
3648
3649 if (uj)
3650 json = json_object_new_object();
3651
3652 /* get the type */
3653 if (argv_find(argv, argc, "type", &type_idx)) {
3654 /* Specific type is requested */
3655 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3656 type = BGP_EVPN_MAC_IP_ROUTE;
3657 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3658 type = BGP_EVPN_IMET_ROUTE;
3659 else if (strncmp(argv[type_idx + 1]->arg, "es", 2) == 0)
3660 type = BGP_EVPN_ES_ROUTE;
3661 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3662 type = BGP_EVPN_IP_PREFIX_ROUTE;
3663 else
3664 return CMD_WARNING;
3665 }
3666
3667 evpn_show_all_routes(vty, bgp, type, json);
3668
3669 if (uj) {
3670 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3671 json, JSON_C_TO_STRING_PRETTY));
3672 json_object_free(json);
3673 }
3674 return CMD_SUCCESS;
3675 }
3676
3677 /*
3678 * Display global EVPN routing table for specific RD.
3679 */
3680 DEFUN(show_bgp_l2vpn_evpn_route_rd,
3681 show_bgp_l2vpn_evpn_route_rd_cmd,
3682 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3683 SHOW_STR
3684 BGP_STR
3685 L2VPN_HELP_STR
3686 EVPN_HELP_STR
3687 "EVPN route information\n"
3688 "Route Distinguisher\n"
3689 "ASN:XX or A.B.C.D:XX\n"
3690 "Specify Route type\n"
3691 "MAC-IP (Type-2) route\n"
3692 "Multicast (Type-3) route\n"
3693 "Ethernet Segment route\n"
3694 "Prefix route\n"
3695 JSON_STR)
3696 {
3697 struct bgp *bgp;
3698 int ret;
3699 struct prefix_rd prd;
3700 int type = 0;
3701 int rd_idx = 0;
3702 int type_idx = 0;
3703 bool uj = false;
3704 json_object *json = NULL;
3705
3706 bgp = bgp_get_evpn();
3707 if (!bgp)
3708 return CMD_WARNING;
3709
3710 /* check if we need json output */
3711 uj = use_json(argc, argv);
3712 if (uj)
3713 json = json_object_new_object();
3714
3715 /* get the RD */
3716 if (argv_find(argv, argc, "rd", &rd_idx)) {
3717 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3718
3719 if (!ret) {
3720 vty_out(vty, "%% Malformed Route Distinguisher\n");
3721 return CMD_WARNING;
3722 }
3723 }
3724
3725 /* get the type */
3726 if (argv_find(argv, argc, "type", &type_idx)) {
3727 /* Specific type is requested */
3728 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3729 type = BGP_EVPN_MAC_IP_ROUTE;
3730 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3731 type = BGP_EVPN_IMET_ROUTE;
3732 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3733 type = BGP_EVPN_IP_PREFIX_ROUTE;
3734 else
3735 return CMD_WARNING;
3736 }
3737
3738 evpn_show_route_rd(vty, bgp, &prd, type, json);
3739
3740 if (uj) {
3741 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3742 json, JSON_C_TO_STRING_PRETTY));
3743 json_object_free(json);
3744 }
3745
3746 return CMD_SUCCESS;
3747 }
3748
3749 /*
3750 * Display global EVPN routing table for specific RD and MACIP.
3751 */
3752 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
3753 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
3754 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3755 SHOW_STR
3756 BGP_STR
3757 L2VPN_HELP_STR
3758 EVPN_HELP_STR
3759 "EVPN route information\n"
3760 "Route Distinguisher\n"
3761 "ASN:XX or A.B.C.D:XX\n"
3762 "MAC\n"
3763 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3764 "IP\n"
3765 "IP address (IPv4 or IPv6)\n"
3766 JSON_STR)
3767 {
3768 struct bgp *bgp;
3769 int ret;
3770 struct prefix_rd prd;
3771 struct ethaddr mac;
3772 struct ipaddr ip;
3773 int rd_idx = 0;
3774 int mac_idx = 0;
3775 int ip_idx = 0;
3776 bool uj = false;
3777 json_object *json = NULL;
3778
3779 memset(&mac, 0, sizeof(struct ethaddr));
3780 memset(&ip, 0, sizeof(struct ipaddr));
3781
3782 bgp = bgp_get_evpn();
3783 if (!bgp)
3784 return CMD_WARNING;
3785
3786 /* check if we need json output */
3787 uj = use_json(argc, argv);
3788 if (uj)
3789 json = json_object_new_object();
3790
3791 /* get the prd */
3792 if (argv_find(argv, argc, "rd", &rd_idx)) {
3793 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3794 if (!ret) {
3795 vty_out(vty, "%% Malformed Route Distinguisher\n");
3796 return CMD_WARNING;
3797 }
3798 }
3799
3800 /* get the mac */
3801 if (argv_find(argv, argc, "mac", &mac_idx)) {
3802 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
3803 vty_out(vty, "%% Malformed MAC address\n");
3804 return CMD_WARNING;
3805 }
3806 }
3807
3808 /* get the ip if specified */
3809 if (argv_find(argv, argc, "ip", &ip_idx)) {
3810 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
3811 vty_out(vty, "%% Malformed IP address\n");
3812 return CMD_WARNING;
3813 }
3814 }
3815
3816 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
3817
3818 if (uj) {
3819 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3820 json, JSON_C_TO_STRING_PRETTY));
3821 json_object_free(json);
3822 }
3823
3824 return CMD_SUCCESS;
3825 }
3826
3827 /* Display per ESI routing table */
3828 DEFUN(show_bgp_l2vpn_evpn_route_esi,
3829 show_bgp_l2vpn_evpn_route_esi_cmd,
3830 "show bgp l2vpn evpn route esi ESI [json]",
3831 SHOW_STR
3832 BGP_STR
3833 L2VPN_HELP_STR
3834 EVPN_HELP_STR
3835 "EVPN route information\n"
3836 "Ethernet Segment Identifier\n"
3837 "ESI ID\n"
3838 JSON_STR)
3839 {
3840 bool uj = false;
3841 esi_t esi;
3842 struct bgp *bgp = NULL;
3843 json_object *json = NULL;
3844
3845 memset(&esi, 0, sizeof(esi));
3846 bgp = bgp_get_evpn();
3847 if (!bgp)
3848 return CMD_WARNING;
3849
3850 uj = use_json(argc, argv);
3851 if (uj)
3852 json = json_object_new_object();
3853
3854 /* get the ESI - ESI-ID is at argv[6] */
3855 if (!str_to_esi(argv[6]->arg, &esi)) {
3856 vty_out(vty, "%% Malformed ESI\n");
3857 return CMD_WARNING;
3858 }
3859
3860 evpn_show_routes_esi(vty, bgp, &esi, json);
3861
3862 if (uj) {
3863 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3864 json, JSON_C_TO_STRING_PRETTY));
3865 json_object_free(json);
3866 }
3867
3868 return CMD_SUCCESS;
3869 }
3870
3871
3872 /*
3873 * Display per-VNI EVPN routing table.
3874 */
3875 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
3876 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3877 SHOW_STR
3878 BGP_STR
3879 L2VPN_HELP_STR
3880 EVPN_HELP_STR
3881 "EVPN route information\n"
3882 "VXLAN Network Identifier\n"
3883 "VNI number\n"
3884 "Specify Route type\n"
3885 "MAC-IP (Type-2) route\n"
3886 "Multicast (Type-3) route\n"
3887 "Remote VTEP\n"
3888 "Remote VTEP IP address\n"
3889 JSON_STR)
3890 {
3891 vni_t vni;
3892 struct bgp *bgp;
3893 struct in_addr vtep_ip;
3894 int type = 0;
3895 int idx = 0;
3896 bool uj = false;
3897 json_object *json = NULL;
3898
3899 bgp = bgp_get_evpn();
3900 if (!bgp)
3901 return CMD_WARNING;
3902
3903 /* check if we need json output */
3904 uj = use_json(argc, argv);
3905 if (uj)
3906 json = json_object_new_object();
3907
3908 if (!argv_find(argv, argc, "evpn", &idx))
3909 return CMD_WARNING;
3910
3911 vtep_ip.s_addr = 0;
3912
3913 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
3914
3915 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
3916 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
3917 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
3918 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
3919 type = BGP_EVPN_MAC_IP_ROUTE;
3920 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
3921 type = BGP_EVPN_IMET_ROUTE;
3922 else
3923 return CMD_WARNING;
3924 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
3925 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
3926 vty_out(vty, "%% Malformed VTEP IP address\n");
3927 return CMD_WARNING;
3928 }
3929 } else
3930 return CMD_WARNING;
3931 }
3932
3933 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
3934
3935 if (uj) {
3936 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3937 json, JSON_C_TO_STRING_PRETTY));
3938 json_object_free(json);
3939 }
3940
3941 return CMD_SUCCESS;
3942 }
3943
3944 /*
3945 * Display per-VNI EVPN routing table for specific MACIP.
3946 */
3947 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
3948 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
3949 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
3950 SHOW_STR
3951 BGP_STR
3952 L2VPN_HELP_STR
3953 EVPN_HELP_STR
3954 "EVPN route information\n"
3955 "VXLAN Network Identifier\n"
3956 "VNI number\n"
3957 "MAC\n"
3958 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3959 "IP\n"
3960 "IP address (IPv4 or IPv6)\n"
3961 JSON_STR)
3962 {
3963 vni_t vni;
3964 struct bgp *bgp;
3965 struct ethaddr mac;
3966 struct ipaddr ip;
3967 int idx = 0;
3968 bool uj = false;
3969 json_object *json = NULL;
3970
3971 bgp = bgp_get_evpn();
3972 if (!bgp)
3973 return CMD_WARNING;
3974
3975 /* check if we need json output */
3976 uj = use_json(argc, argv);
3977 if (uj)
3978 json = json_object_new_object();
3979
3980 if (!argv_find(argv, argc, "evpn", &idx))
3981 return CMD_WARNING;
3982
3983 /* get the VNI */
3984 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
3985
3986 /* get the mac */
3987 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
3988 vty_out(vty, "%% Malformed MAC address\n");
3989 return CMD_WARNING;
3990 }
3991
3992 /* get the ip */
3993 memset(&ip, 0, sizeof(ip));
3994 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
3995 || (uj
3996 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
3997 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
3998 vty_out(vty, "%% Malformed IP address\n");
3999 return CMD_WARNING;
4000 }
4001 }
4002
4003 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
4004
4005 if (uj) {
4006 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4007 json, JSON_C_TO_STRING_PRETTY));
4008 json_object_free(json);
4009 }
4010
4011 return CMD_SUCCESS;
4012 }
4013
4014 /*
4015 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4016 */
4017 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
4018 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
4019 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
4020 SHOW_STR
4021 BGP_STR
4022 L2VPN_HELP_STR
4023 EVPN_HELP_STR
4024 "EVPN route information\n"
4025 "VXLAN Network Identifier\n"
4026 "VNI number\n"
4027 "Multicast (Type-3) route\n"
4028 "Originating Router IP address\n"
4029 JSON_STR)
4030 {
4031 vni_t vni;
4032 struct bgp *bgp;
4033 int ret;
4034 struct in_addr orig_ip;
4035 int idx = 0;
4036 bool uj = false;
4037 json_object *json = NULL;
4038
4039 bgp = bgp_get_evpn();
4040 if (!bgp)
4041 return CMD_WARNING;
4042
4043 /* check if we need json output */
4044 uj = use_json(argc, argv);
4045 if (uj)
4046 json = json_object_new_object();
4047
4048 if (!argv_find(argv, argc, "evpn", &idx))
4049 return CMD_WARNING;
4050
4051 /* get the VNI */
4052 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4053
4054 /* get the ip */
4055 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
4056 if (!ret) {
4057 vty_out(vty, "%% Malformed Originating Router IP address\n");
4058 return CMD_WARNING;
4059 }
4060
4061 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
4062
4063 if (uj) {
4064 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4065 json, JSON_C_TO_STRING_PRETTY));
4066 json_object_free(json);
4067 }
4068
4069 return CMD_SUCCESS;
4070 }
4071
4072 /*
4073 * Display per-VNI EVPN routing table - for all VNIs.
4074 */
4075 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
4076 show_bgp_l2vpn_evpn_route_vni_all_cmd,
4077 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
4078 SHOW_STR
4079 BGP_STR
4080 L2VPN_HELP_STR
4081 EVPN_HELP_STR
4082 "EVPN route information\n"
4083 "VXLAN Network Identifier\n"
4084 "All VNIs\n"
4085 "Remote VTEP\n"
4086 "Remote VTEP IP address\n"
4087 JSON_STR)
4088 {
4089 struct bgp *bgp;
4090 struct in_addr vtep_ip;
4091 int idx = 0;
4092 bool uj = false;
4093 json_object *json = NULL;
4094
4095 bgp = bgp_get_evpn();
4096 if (!bgp)
4097 return CMD_WARNING;
4098
4099 /* check if we need json output */
4100 uj = use_json(argc, argv);
4101 if (uj)
4102 json = json_object_new_object();
4103
4104 if (!argv_find(argv, argc, "evpn", &idx))
4105 return CMD_WARNING;
4106
4107 vtep_ip.s_addr = 0;
4108 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
4109 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
4110 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
4111 vty_out(vty, "%% Malformed VTEP IP address\n");
4112 return CMD_WARNING;
4113 }
4114 }
4115
4116 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
4117
4118 if (uj) {
4119 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4120 json, JSON_C_TO_STRING_PRETTY));
4121 json_object_free(json);
4122 }
4123
4124 return CMD_SUCCESS;
4125 }
4126
4127 /*
4128 * Display EVPN import route-target hash table
4129 */
4130 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
4131 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
4132 "show bgp l2vpn evpn vrf-import-rt [json]",
4133 SHOW_STR
4134 BGP_STR
4135 L2VPN_HELP_STR
4136 EVPN_HELP_STR
4137 "Show vrf import route target\n"
4138 JSON_STR)
4139 {
4140 bool uj = false;
4141 struct bgp *bgp_evpn = NULL;
4142 json_object *json = NULL;
4143
4144 bgp_evpn = bgp_get_evpn();
4145 if (!bgp_evpn)
4146 return CMD_WARNING;
4147
4148 uj = use_json(argc, argv);
4149 if (uj)
4150 json = json_object_new_object();
4151
4152 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
4153
4154 if (uj) {
4155 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4156 json, JSON_C_TO_STRING_PRETTY));
4157 json_object_free(json);
4158 }
4159
4160 return CMD_SUCCESS;
4161 }
4162
4163 /*
4164 * Display EVPN import route-target hash table
4165 */
4166 DEFUN(show_bgp_l2vpn_evpn_import_rt,
4167 show_bgp_l2vpn_evpn_import_rt_cmd,
4168 "show bgp l2vpn evpn import-rt [json]",
4169 SHOW_STR
4170 BGP_STR
4171 L2VPN_HELP_STR
4172 EVPN_HELP_STR
4173 "Show import route target\n"
4174 JSON_STR)
4175 {
4176 struct bgp *bgp;
4177 bool uj = false;
4178 json_object *json = NULL;
4179
4180 bgp = bgp_get_evpn();
4181 if (!bgp)
4182 return CMD_WARNING;
4183
4184 uj = use_json(argc, argv);
4185 if (uj)
4186 json = json_object_new_object();
4187
4188 evpn_show_import_rts(vty, bgp, json);
4189
4190 if (uj) {
4191 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4192 json, JSON_C_TO_STRING_PRETTY));
4193 json_object_free(json);
4194 }
4195
4196 return CMD_SUCCESS;
4197 }
4198
4199 DEFUN(test_adv_evpn_type4_route,
4200 test_adv_evpn_type4_route_cmd,
4201 "advertise es ESI",
4202 "Advertise EVPN ES route\n"
4203 "Ethernet-segment\n"
4204 "Ethernet-Segment Identifier\n")
4205 {
4206 int ret = 0;
4207 esi_t esi;
4208 struct bgp *bgp;
4209 struct ipaddr vtep_ip;
4210
4211 bgp = bgp_get_evpn();
4212 if (!bgp) {
4213 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4214 return CMD_WARNING;
4215 }
4216
4217 if (!str_to_esi(argv[2]->arg, &esi)) {
4218 vty_out(vty, "%%Malformed ESI\n");
4219 return CMD_WARNING;
4220 }
4221
4222 vtep_ip.ipa_type = IPADDR_V4;
4223 vtep_ip.ipaddr_v4 = bgp->router_id;
4224
4225 ret = bgp_evpn_local_es_add(bgp, &esi, &vtep_ip);
4226 if (ret == -1) {
4227 vty_out(vty, "%%Failed to EVPN advertise type-4 route\n");
4228 return CMD_WARNING;
4229 }
4230 return CMD_SUCCESS;
4231 }
4232
4233 DEFUN(test_withdraw_evpn_type4_route,
4234 test_withdraw_evpn_type4_route_cmd,
4235 "withdraw es ESI",
4236 "Advertise EVPN ES route\n"
4237 "Ethernet-segment\n"
4238 "Ethernet-Segment Identifier\n")
4239 {
4240 int ret = 0;
4241 esi_t esi;
4242 struct bgp *bgp;
4243 struct ipaddr vtep_ip;
4244
4245 bgp = bgp_get_evpn();
4246 if (!bgp) {
4247 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4248 return CMD_WARNING;
4249 }
4250
4251 if (!bgp->peer_self) {
4252 vty_out(vty, "%%BGP instance doesn't have self peer\n");
4253 return CMD_WARNING;
4254 }
4255
4256 if (!str_to_esi(argv[2]->arg, &esi)) {
4257 vty_out(vty, "%%Malformed ESI\n");
4258 return CMD_WARNING;
4259 }
4260
4261 vtep_ip.ipa_type = IPADDR_V4;
4262 vtep_ip.ipaddr_v4 = bgp->router_id;
4263 ret = bgp_evpn_local_es_del(bgp, &esi, &vtep_ip);
4264 if (ret == -1) {
4265 vty_out(vty, "%%Failed to withdraw EVPN type-4 route\n");
4266 return CMD_WARNING;
4267 }
4268 return CMD_SUCCESS;
4269 }
4270
4271 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
4272 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
4273 "Show VNI\n"
4274 "VNI number\n")
4275
4276 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
4277 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4278 "Summary of BGP neighbor status\n" JSON_STR)
4279
4280 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
4281 "show bgp evpn route [type <macip|multicast>]",
4282 SHOW_STR BGP_STR EVPN_HELP_STR
4283 "EVPN route information\n"
4284 "Specify Route type\n"
4285 "MAC-IP (Type-2) route\n"
4286 "Multicast (Type-3) route\n")
4287
4288 ALIAS_HIDDEN(
4289 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
4290 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4291 SHOW_STR BGP_STR EVPN_HELP_STR
4292 "EVPN route information\n"
4293 "Route Distinguisher\n"
4294 "ASN:XX or A.B.C.D:XX\n"
4295 "Specify Route type\n"
4296 "MAC-IP (Type-2) route\n"
4297 "Multicast (Type-3) route\n")
4298
4299 ALIAS_HIDDEN(
4300 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
4301 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4302 SHOW_STR BGP_STR EVPN_HELP_STR
4303 "EVPN route information\n"
4304 "Route Distinguisher\n"
4305 "ASN:XX or A.B.C.D:XX\n"
4306 "MAC\n"
4307 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4308 "IP\n"
4309 "IP address (IPv4 or IPv6)\n")
4310
4311 ALIAS_HIDDEN(
4312 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
4313 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]",
4314 SHOW_STR BGP_STR EVPN_HELP_STR
4315 "EVPN route information\n"
4316 "VXLAN Network Identifier\n"
4317 "VNI number\n"
4318 "Specify Route type\n"
4319 "MAC-IP (Type-2) route\n"
4320 "Multicast (Type-3) route\n"
4321 "Remote VTEP\n"
4322 "Remote VTEP IP address\n")
4323
4324 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4325 show_bgp_evpn_route_vni_macip_cmd,
4326 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
4327 SHOW_STR BGP_STR EVPN_HELP_STR
4328 "EVPN route information\n"
4329 "VXLAN Network Identifier\n"
4330 "VNI number\n"
4331 "MAC\n"
4332 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4333 "IP\n"
4334 "IP address (IPv4 or IPv6)\n")
4335
4336 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4337 show_bgp_evpn_route_vni_multicast_cmd,
4338 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
4339 SHOW_STR BGP_STR EVPN_HELP_STR
4340 "EVPN route information\n"
4341 "VXLAN Network Identifier\n"
4342 "VNI number\n"
4343 "Multicast (Type-3) route\n"
4344 "Originating Router IP address\n")
4345
4346 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
4347 "show bgp evpn route vni all [vtep A.B.C.D]",
4348 SHOW_STR BGP_STR EVPN_HELP_STR
4349 "EVPN route information\n"
4350 "VXLAN Network Identifier\n"
4351 "All VNIs\n"
4352 "Remote VTEP\n"
4353 "Remote VTEP IP address\n")
4354
4355 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4356 "show bgp evpn import-rt",
4357 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
4358
4359 DEFUN_NOSH (bgp_evpn_vni,
4360 bgp_evpn_vni_cmd,
4361 "vni " CMD_VNI_RANGE,
4362 "VXLAN Network Identifier\n"
4363 "VNI number\n")
4364 {
4365 vni_t vni;
4366 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4367 struct bgpevpn *vpn;
4368
4369 if (!bgp)
4370 return CMD_WARNING;
4371
4372 vni = strtoul(argv[1]->arg, NULL, 10);
4373
4374 /* Create VNI, or mark as configured. */
4375 vpn = evpn_create_update_vni(bgp, vni);
4376 if (!vpn) {
4377 vty_out(vty, "%% Failed to create VNI \n");
4378 return CMD_WARNING;
4379 }
4380
4381 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4382 return CMD_SUCCESS;
4383 }
4384
4385 DEFUN (no_bgp_evpn_vni,
4386 no_bgp_evpn_vni_cmd,
4387 "no vni " CMD_VNI_RANGE,
4388 NO_STR
4389 "VXLAN Network Identifier\n"
4390 "VNI number\n")
4391 {
4392 vni_t vni;
4393 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4394 struct bgpevpn *vpn;
4395
4396 if (!bgp)
4397 return CMD_WARNING;
4398
4399 vni = strtoul(argv[2]->arg, NULL, 10);
4400
4401 /* Check if we should disallow. */
4402 vpn = bgp_evpn_lookup_vni(bgp, vni);
4403 if (!vpn) {
4404 vty_out(vty, "%% Specified VNI does not exist\n");
4405 return CMD_WARNING;
4406 }
4407 if (!is_vni_configured(vpn)) {
4408 vty_out(vty, "%% Specified VNI is not configured\n");
4409 return CMD_WARNING;
4410 }
4411
4412 evpn_delete_vni(bgp, vpn);
4413 return CMD_SUCCESS;
4414 }
4415
4416 DEFUN_NOSH (exit_vni,
4417 exit_vni_cmd,
4418 "exit-vni",
4419 "Exit from VNI mode\n")
4420 {
4421 if (vty->node == BGP_EVPN_VNI_NODE)
4422 vty->node = BGP_EVPN_NODE;
4423 return CMD_SUCCESS;
4424 }
4425
4426 DEFUN (bgp_evpn_vrf_rd,
4427 bgp_evpn_vrf_rd_cmd,
4428 "rd ASN:NN_OR_IP-ADDRESS:NN",
4429 "Route Distinguisher\n"
4430 "ASN:XX or A.B.C.D:XX\n")
4431 {
4432 int ret;
4433 struct prefix_rd prd;
4434 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4435
4436 if (!bgp_vrf)
4437 return CMD_WARNING;
4438
4439 ret = str2prefix_rd(argv[1]->arg, &prd);
4440 if (!ret) {
4441 vty_out(vty, "%% Malformed Route Distinguisher\n");
4442 return CMD_WARNING;
4443 }
4444
4445 /* If same as existing value, there is nothing more to do. */
4446 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4447 return CMD_SUCCESS;
4448
4449 /* Configure or update the RD. */
4450 evpn_configure_vrf_rd(bgp_vrf, &prd);
4451 return CMD_SUCCESS;
4452 }
4453
4454 DEFUN (no_bgp_evpn_vrf_rd,
4455 no_bgp_evpn_vrf_rd_cmd,
4456 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4457 NO_STR
4458 "Route Distinguisher\n"
4459 "ASN:XX or A.B.C.D:XX\n")
4460 {
4461 int ret;
4462 struct prefix_rd prd;
4463 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4464
4465 if (!bgp_vrf)
4466 return CMD_WARNING;
4467
4468 ret = str2prefix_rd(argv[2]->arg, &prd);
4469 if (!ret) {
4470 vty_out(vty, "%% Malformed Route Distinguisher\n");
4471 return CMD_WARNING;
4472 }
4473
4474 /* Check if we should disallow. */
4475 if (!is_vrf_rd_configured(bgp_vrf)) {
4476 vty_out(vty, "%% RD is not configured for this VRF\n");
4477 return CMD_WARNING;
4478 }
4479
4480 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4481 vty_out(vty,
4482 "%% RD specified does not match configuration for this VRF\n");
4483 return CMD_WARNING;
4484 }
4485
4486 evpn_unconfigure_vrf_rd(bgp_vrf);
4487 return CMD_SUCCESS;
4488 }
4489
4490 DEFUN (no_bgp_evpn_vrf_rd_without_val,
4491 no_bgp_evpn_vrf_rd_without_val_cmd,
4492 "no rd",
4493 NO_STR
4494 "Route Distinguisher\n")
4495 {
4496 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4497
4498 if (!bgp_vrf)
4499 return CMD_WARNING;
4500
4501 /* Check if we should disallow. */
4502 if (!is_vrf_rd_configured(bgp_vrf)) {
4503 vty_out(vty, "%% RD is not configured for this VRF\n");
4504 return CMD_WARNING;
4505 }
4506
4507 evpn_unconfigure_vrf_rd(bgp_vrf);
4508 return CMD_SUCCESS;
4509 }
4510
4511 DEFUN (bgp_evpn_vni_rd,
4512 bgp_evpn_vni_rd_cmd,
4513 "rd ASN:NN_OR_IP-ADDRESS:NN",
4514 "Route Distinguisher\n"
4515 "ASN:XX or A.B.C.D:XX\n")
4516 {
4517 struct prefix_rd prd;
4518 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4519 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4520 int ret;
4521
4522 if (!bgp)
4523 return CMD_WARNING;
4524
4525 if (!bgp->advertise_all_vni) {
4526 vty_out(vty,
4527 "This command is only supported under EVPN VRF\n");
4528 return CMD_WARNING;
4529 }
4530
4531 ret = str2prefix_rd(argv[1]->arg, &prd);
4532 if (!ret) {
4533 vty_out(vty, "%% Malformed Route Distinguisher\n");
4534 return CMD_WARNING;
4535 }
4536
4537 /* If same as existing value, there is nothing more to do. */
4538 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4539 return CMD_SUCCESS;
4540
4541 /* Configure or update the RD. */
4542 evpn_configure_rd(bgp, vpn, &prd);
4543 return CMD_SUCCESS;
4544 }
4545
4546 DEFUN (no_bgp_evpn_vni_rd,
4547 no_bgp_evpn_vni_rd_cmd,
4548 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4549 NO_STR
4550 "Route Distinguisher\n"
4551 "ASN:XX or A.B.C.D:XX\n")
4552 {
4553 struct prefix_rd prd;
4554 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4555 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4556 int ret;
4557
4558 if (!bgp)
4559 return CMD_WARNING;
4560
4561 if (!bgp->advertise_all_vni) {
4562 vty_out(vty,
4563 "This command is only supported under EVPN VRF\n");
4564 return CMD_WARNING;
4565 }
4566
4567 ret = str2prefix_rd(argv[2]->arg, &prd);
4568 if (!ret) {
4569 vty_out(vty, "%% Malformed Route Distinguisher\n");
4570 return CMD_WARNING;
4571 }
4572
4573 /* Check if we should disallow. */
4574 if (!is_rd_configured(vpn)) {
4575 vty_out(vty, "%% RD is not configured for this VNI\n");
4576 return CMD_WARNING;
4577 }
4578
4579 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
4580 vty_out(vty,
4581 "%% RD specified does not match configuration for this VNI\n");
4582 return CMD_WARNING;
4583 }
4584
4585 evpn_unconfigure_rd(bgp, vpn);
4586 return CMD_SUCCESS;
4587 }
4588
4589 DEFUN (no_bgp_evpn_vni_rd_without_val,
4590 no_bgp_evpn_vni_rd_without_val_cmd,
4591 "no rd",
4592 NO_STR
4593 "Route Distinguisher\n")
4594 {
4595 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4596 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4597
4598 if (!bgp)
4599 return CMD_WARNING;
4600
4601 if (!bgp->advertise_all_vni) {
4602 vty_out(vty,
4603 "This command is only supported under EVPN VRF\n");
4604 return CMD_WARNING;
4605 }
4606
4607 /* Check if we should disallow. */
4608 if (!is_rd_configured(vpn)) {
4609 vty_out(vty, "%% RD is not configured for this VNI\n");
4610 return CMD_WARNING;
4611 }
4612
4613 evpn_unconfigure_rd(bgp, vpn);
4614 return CMD_SUCCESS;
4615 }
4616
4617 /*
4618 * Loop over all extended-communities in the route-target list rtl and
4619 * return 1 if we find ecomtarget
4620 */
4621 static int bgp_evpn_rt_matches_existing(struct list *rtl,
4622 struct ecommunity *ecomtarget)
4623 {
4624 struct listnode *node, *nnode;
4625 struct ecommunity *ecom;
4626
4627 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
4628 if (ecommunity_match(ecom, ecomtarget))
4629 return 1;
4630 }
4631
4632 return 0;
4633 }
4634
4635 /* display L3VNI related info for a VRF instance */
4636 DEFUN (show_bgp_vrf_l3vni_info,
4637 show_bgp_vrf_l3vni_info_cmd,
4638 "show bgp vrf VRFNAME vni [json]",
4639 SHOW_STR
4640 BGP_STR
4641 "show bgp vrf\n"
4642 "VRF Name\n"
4643 "L3-VNI\n"
4644 JSON_STR)
4645 {
4646 char buf[ETHER_ADDR_STRLEN];
4647 char buf1[INET6_ADDRSTRLEN];
4648 int idx_vrf = 3;
4649 const char *name = NULL;
4650 struct bgp *bgp = NULL;
4651 struct listnode *node = NULL;
4652 struct bgpevpn *vpn = NULL;
4653 struct ecommunity *ecom = NULL;
4654 json_object *json = NULL;
4655 json_object *json_vnis = NULL;
4656 json_object *json_export_rts = NULL;
4657 json_object *json_import_rts = NULL;
4658 bool uj = use_json(argc, argv);
4659
4660 if (uj) {
4661 json = json_object_new_object();
4662 json_vnis = json_object_new_array();
4663 json_export_rts = json_object_new_array();
4664 json_import_rts = json_object_new_array();
4665 }
4666
4667 name = argv[idx_vrf]->arg;
4668 bgp = bgp_lookup_by_name(name);
4669 if (!bgp) {
4670 if (!uj)
4671 vty_out(vty, "BGP instance for VRF %s not found", name);
4672 else {
4673 json_object_string_add(json, "warning",
4674 "BGP instance not found");
4675 vty_out(vty, "%s\n", json_object_to_json_string(json));
4676 json_object_free(json);
4677 }
4678 return CMD_WARNING;
4679 }
4680
4681 if (!json) {
4682 vty_out(vty, "BGP VRF: %s\n", name);
4683 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
4684 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
4685 vty_out(vty, " Rmac: %s\n",
4686 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4687 vty_out(vty, " VNI Filter: %s\n",
4688 CHECK_FLAG(bgp->vrf_flags,
4689 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4690 ? "prefix-routes-only"
4691 : "none");
4692 vty_out(vty, " L2-VNI List:\n");
4693 vty_out(vty, " ");
4694 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4695 vty_out(vty, "%u ", vpn->vni);
4696 vty_out(vty, "\n");
4697 vty_out(vty, " Export-RTs:\n");
4698 vty_out(vty, " ");
4699 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4700 vty_out(vty, "%s ", ecommunity_str(ecom));
4701 vty_out(vty, "\n");
4702 vty_out(vty, " Import-RTs:\n");
4703 vty_out(vty, " ");
4704 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4705 vty_out(vty, "%s ", ecommunity_str(ecom));
4706 vty_out(vty, "\n");
4707 vty_out(vty, " RD: %s\n",
4708 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
4709 } else {
4710 json_object_string_add(json, "vrf", name);
4711 json_object_string_add(json, "local-ip",
4712 inet_ntoa(bgp->originator_ip));
4713 json_object_int_add(json, "l3vni", bgp->l3vni);
4714 json_object_string_add(
4715 json, "rmac",
4716 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4717 json_object_string_add(
4718 json, "vniFilter",
4719 CHECK_FLAG(bgp->vrf_flags,
4720 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4721 ? "prefix-routes-only"
4722 : "none");
4723 /* list of l2vnis */
4724 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4725 json_object_array_add(json_vnis,
4726 json_object_new_int(vpn->vni));
4727 json_object_object_add(json, "l2vnis", json_vnis);
4728
4729 /* export rts */
4730 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4731 json_object_array_add(
4732 json_export_rts,
4733 json_object_new_string(ecommunity_str(ecom)));
4734 json_object_object_add(json, "export-rts", json_export_rts);
4735
4736 /* import rts */
4737 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4738 json_object_array_add(
4739 json_import_rts,
4740 json_object_new_string(ecommunity_str(ecom)));
4741 json_object_object_add(json, "import-rts", json_import_rts);
4742 json_object_string_add(
4743 json, "rd",
4744 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
4745 }
4746
4747 if (uj) {
4748 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4749 json, JSON_C_TO_STRING_PRETTY));
4750 json_object_free(json);
4751 }
4752 return CMD_SUCCESS;
4753 }
4754
4755 /* import/export rt for l3vni-vrf */
4756 DEFUN (bgp_evpn_vrf_rt,
4757 bgp_evpn_vrf_rt_cmd,
4758 "route-target <both|import|export> RT",
4759 "Route Target\n"
4760 "import and export\n"
4761 "import\n"
4762 "export\n"
4763 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4764 {
4765 int rt_type;
4766 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4767 struct ecommunity *ecomadd = NULL;
4768
4769 if (!bgp)
4770 return CMD_WARNING;
4771
4772 if (!strcmp(argv[1]->arg, "import"))
4773 rt_type = RT_TYPE_IMPORT;
4774 else if (!strcmp(argv[1]->arg, "export"))
4775 rt_type = RT_TYPE_EXPORT;
4776 else if (!strcmp(argv[1]->arg, "both"))
4777 rt_type = RT_TYPE_BOTH;
4778 else {
4779 vty_out(vty, "%% Invalid Route Target type\n");
4780 return CMD_WARNING;
4781 }
4782
4783 /* Add/update the import route-target */
4784 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4785 ecomadd = ecommunity_str2com(argv[2]->arg,
4786 ECOMMUNITY_ROUTE_TARGET, 0);
4787 if (!ecomadd) {
4788 vty_out(vty, "%% Malformed Route Target list\n");
4789 return CMD_WARNING;
4790 }
4791 ecommunity_str(ecomadd);
4792
4793 /* Do nothing if we already have this import route-target */
4794 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
4795 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
4796 }
4797
4798 /* Add/update the export route-target */
4799 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4800 ecomadd = ecommunity_str2com(argv[2]->arg,
4801 ECOMMUNITY_ROUTE_TARGET, 0);
4802 if (!ecomadd) {
4803 vty_out(vty, "%% Malformed Route Target list\n");
4804 return CMD_WARNING;
4805 }
4806 ecommunity_str(ecomadd);
4807
4808 /* Do nothing if we already have this export route-target */
4809 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
4810 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
4811 }
4812
4813 return CMD_SUCCESS;
4814 }
4815
4816 DEFUN (no_bgp_evpn_vrf_rt,
4817 no_bgp_evpn_vrf_rt_cmd,
4818 "no route-target <both|import|export> RT",
4819 NO_STR
4820 "Route Target\n"
4821 "import and export\n"
4822 "import\n"
4823 "export\n"
4824 "ASN:XX or A.B.C.D:XX\n")
4825 {
4826 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4827 int rt_type, found_ecomdel;
4828 struct ecommunity *ecomdel = NULL;
4829
4830 if (!bgp)
4831 return CMD_WARNING;
4832
4833 if (!strcmp(argv[2]->arg, "import"))
4834 rt_type = RT_TYPE_IMPORT;
4835 else if (!strcmp(argv[2]->arg, "export"))
4836 rt_type = RT_TYPE_EXPORT;
4837 else if (!strcmp(argv[2]->arg, "both"))
4838 rt_type = RT_TYPE_BOTH;
4839 else {
4840 vty_out(vty, "%% Invalid Route Target type\n");
4841 return CMD_WARNING;
4842 }
4843
4844 if (rt_type == RT_TYPE_IMPORT) {
4845 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
4846 vty_out(vty,
4847 "%% Import RT is not configured for this VRF\n");
4848 return CMD_WARNING;
4849 }
4850 } else if (rt_type == RT_TYPE_EXPORT) {
4851 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4852 vty_out(vty,
4853 "%% Export RT is not configured for this VRF\n");
4854 return CMD_WARNING;
4855 }
4856 } else if (rt_type == RT_TYPE_BOTH) {
4857 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
4858 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
4859 vty_out(vty,
4860 "%% Import/Export RT is not configured for this VRF\n");
4861 return CMD_WARNING;
4862 }
4863 }
4864
4865 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
4866 if (!ecomdel) {
4867 vty_out(vty, "%% Malformed Route Target list\n");
4868 return CMD_WARNING;
4869 }
4870 ecommunity_str(ecomdel);
4871
4872 if (rt_type == RT_TYPE_IMPORT) {
4873 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4874 ecomdel)) {
4875 vty_out(vty,
4876 "%% RT specified does not match configuration for this VRF\n");
4877 return CMD_WARNING;
4878 }
4879 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4880 } else if (rt_type == RT_TYPE_EXPORT) {
4881 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4882 ecomdel)) {
4883 vty_out(vty,
4884 "%% RT specified does not match configuration for this VRF\n");
4885 return CMD_WARNING;
4886 }
4887 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4888 } else if (rt_type == RT_TYPE_BOTH) {
4889 found_ecomdel = 0;
4890
4891 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
4892 ecomdel)) {
4893 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
4894 found_ecomdel = 1;
4895 }
4896
4897 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
4898 ecomdel)) {
4899 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
4900 found_ecomdel = 1;
4901 }
4902
4903 if (!found_ecomdel) {
4904 vty_out(vty,
4905 "%% RT specified does not match configuration for this VRF\n");
4906 return CMD_WARNING;
4907 }
4908 }
4909
4910 return CMD_SUCCESS;
4911 }
4912
4913 DEFUN (bgp_evpn_vni_rt,
4914 bgp_evpn_vni_rt_cmd,
4915 "route-target <both|import|export> RT",
4916 "Route Target\n"
4917 "import and export\n"
4918 "import\n"
4919 "export\n"
4920 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4921 {
4922 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4923 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4924 int rt_type;
4925 struct ecommunity *ecomadd = NULL;
4926
4927 if (!bgp)
4928 return CMD_WARNING;
4929
4930 if (!bgp->advertise_all_vni) {
4931 vty_out(vty,
4932 "This command is only supported under EVPN VRF\n");
4933 return CMD_WARNING;
4934 }
4935
4936 if (!strcmp(argv[1]->text, "import"))
4937 rt_type = RT_TYPE_IMPORT;
4938 else if (!strcmp(argv[1]->text, "export"))
4939 rt_type = RT_TYPE_EXPORT;
4940 else if (!strcmp(argv[1]->text, "both"))
4941 rt_type = RT_TYPE_BOTH;
4942 else {
4943 vty_out(vty, "%% Invalid Route Target type\n");
4944 return CMD_WARNING;
4945 }
4946
4947 /* Add/update the import route-target */
4948 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
4949 ecomadd = ecommunity_str2com(argv[2]->arg,
4950 ECOMMUNITY_ROUTE_TARGET, 0);
4951 if (!ecomadd) {
4952 vty_out(vty, "%% Malformed Route Target list\n");
4953 return CMD_WARNING;
4954 }
4955 ecommunity_str(ecomadd);
4956
4957 /* Do nothing if we already have this import route-target */
4958 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
4959 evpn_configure_import_rt(bgp, vpn, ecomadd);
4960 }
4961
4962 /* Add/update the export route-target */
4963 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
4964 ecomadd = ecommunity_str2com(argv[2]->arg,
4965 ECOMMUNITY_ROUTE_TARGET, 0);
4966 if (!ecomadd) {
4967 vty_out(vty, "%% Malformed Route Target list\n");
4968 return CMD_WARNING;
4969 }
4970 ecommunity_str(ecomadd);
4971
4972 /* Do nothing if we already have this export route-target */
4973 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
4974 evpn_configure_export_rt(bgp, vpn, ecomadd);
4975 }
4976
4977 return CMD_SUCCESS;
4978 }
4979
4980 DEFUN (no_bgp_evpn_vni_rt,
4981 no_bgp_evpn_vni_rt_cmd,
4982 "no route-target <both|import|export> RT",
4983 NO_STR
4984 "Route Target\n"
4985 "import and export\n"
4986 "import\n"
4987 "export\n"
4988 "ASN:XX or A.B.C.D:XX\n")
4989 {
4990 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4991 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4992 int rt_type, found_ecomdel;
4993 struct ecommunity *ecomdel = NULL;
4994
4995 if (!bgp)
4996 return CMD_WARNING;
4997
4998 if (!bgp->advertise_all_vni) {
4999 vty_out(vty,
5000 "This command is only supported under EVPN VRF\n");
5001 return CMD_WARNING;
5002 }
5003
5004 if (!strcmp(argv[2]->text, "import"))
5005 rt_type = RT_TYPE_IMPORT;
5006 else if (!strcmp(argv[2]->text, "export"))
5007 rt_type = RT_TYPE_EXPORT;
5008 else if (!strcmp(argv[2]->text, "both"))
5009 rt_type = RT_TYPE_BOTH;
5010 else {
5011 vty_out(vty, "%% Invalid Route Target type\n");
5012 return CMD_WARNING;
5013 }
5014
5015 /* The user did "no route-target import", check to see if there are any
5016 * import route-targets configured. */
5017 if (rt_type == RT_TYPE_IMPORT) {
5018 if (!is_import_rt_configured(vpn)) {
5019 vty_out(vty,
5020 "%% Import RT is not configured for this VNI\n");
5021 return CMD_WARNING;
5022 }
5023 } else if (rt_type == RT_TYPE_EXPORT) {
5024 if (!is_export_rt_configured(vpn)) {
5025 vty_out(vty,
5026 "%% Export RT is not configured for this VNI\n");
5027 return CMD_WARNING;
5028 }
5029 } else if (rt_type == RT_TYPE_BOTH) {
5030 if (!is_import_rt_configured(vpn)
5031 && !is_export_rt_configured(vpn)) {
5032 vty_out(vty,
5033 "%% Import/Export RT is not configured for this VNI\n");
5034 return CMD_WARNING;
5035 }
5036 }
5037
5038 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5039 if (!ecomdel) {
5040 vty_out(vty, "%% Malformed Route Target list\n");
5041 return CMD_WARNING;
5042 }
5043 ecommunity_str(ecomdel);
5044
5045 if (rt_type == RT_TYPE_IMPORT) {
5046 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5047 vty_out(vty,
5048 "%% RT specified does not match configuration for this VNI\n");
5049 return CMD_WARNING;
5050 }
5051 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5052 } else if (rt_type == RT_TYPE_EXPORT) {
5053 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5054 vty_out(vty,
5055 "%% RT specified does not match configuration for this VNI\n");
5056 return CMD_WARNING;
5057 }
5058 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5059 } else if (rt_type == RT_TYPE_BOTH) {
5060 found_ecomdel = 0;
5061
5062 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5063 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5064 found_ecomdel = 1;
5065 }
5066
5067 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5068 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5069 found_ecomdel = 1;
5070 }
5071
5072 if (!found_ecomdel) {
5073 vty_out(vty,
5074 "%% RT specified does not match configuration for this VNI\n");
5075 return CMD_WARNING;
5076 }
5077 }
5078
5079 return CMD_SUCCESS;
5080 }
5081
5082 DEFUN (no_bgp_evpn_vni_rt_without_val,
5083 no_bgp_evpn_vni_rt_without_val_cmd,
5084 "no route-target <import|export>",
5085 NO_STR
5086 "Route Target\n"
5087 "import\n"
5088 "export\n")
5089 {
5090 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5091 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5092 int rt_type;
5093
5094 if (!bgp)
5095 return CMD_WARNING;
5096
5097 if (!bgp->advertise_all_vni) {
5098 vty_out(vty,
5099 "This command is only supported under EVPN VRF\n");
5100 return CMD_WARNING;
5101 }
5102
5103 if (!strcmp(argv[2]->text, "import")) {
5104 rt_type = RT_TYPE_IMPORT;
5105 } else if (!strcmp(argv[2]->text, "export")) {
5106 rt_type = RT_TYPE_EXPORT;
5107 } else {
5108 vty_out(vty, "%% Invalid Route Target type\n");
5109 return CMD_WARNING;
5110 }
5111
5112 /* Check if we should disallow. */
5113 if (rt_type == RT_TYPE_IMPORT) {
5114 if (!is_import_rt_configured(vpn)) {
5115 vty_out(vty,
5116 "%% Import RT is not configured for this VNI\n");
5117 return CMD_WARNING;
5118 }
5119 } else {
5120 if (!is_export_rt_configured(vpn)) {
5121 vty_out(vty,
5122 "%% Export RT is not configured for this VNI\n");
5123 return CMD_WARNING;
5124 }
5125 }
5126
5127 /* Unconfigure the RT. */
5128 if (rt_type == RT_TYPE_IMPORT)
5129 evpn_unconfigure_import_rt(bgp, vpn, NULL);
5130 else
5131 evpn_unconfigure_export_rt(bgp, vpn, NULL);
5132 return CMD_SUCCESS;
5133 }
5134
5135 static int vni_cmp(const void **a, const void **b)
5136 {
5137 const struct bgpevpn *first = *a;
5138 const struct bgpevpn *secnd = *b;
5139
5140 return secnd->vni - first->vni;
5141 }
5142
5143 /*
5144 * Output EVPN configuration information.
5145 */
5146 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
5147 safi_t safi)
5148 {
5149 char buf1[RD_ADDRSTRLEN];
5150
5151 if (bgp->vnihash) {
5152 struct list *vnilist = hash_to_list(bgp->vnihash);
5153 struct listnode *ln;
5154 struct bgpevpn *data;
5155
5156 list_sort(vnilist, vni_cmp);
5157 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
5158 write_vni_config(vty, data);
5159
5160 list_delete(&vnilist);
5161 }
5162
5163 if (bgp->advertise_all_vni)
5164 vty_out(vty, " advertise-all-vni\n");
5165
5166 if (bgp->advertise_autort_rfc8365)
5167 vty_out(vty, " autort rfc8365-compatible\n");
5168
5169 if (bgp->advertise_gw_macip)
5170 vty_out(vty, " advertise-default-gw\n");
5171
5172 if (bgp->evpn_info->advertise_svi_macip)
5173 vty_out(vty, " advertise-svi-ip\n");
5174
5175 if (!bgp->evpn_info->dup_addr_detect)
5176 vty_out(vty, " no dup-addr-detection\n");
5177
5178 if (bgp->evpn_info->dad_max_moves !=
5179 EVPN_DAD_DEFAULT_MAX_MOVES ||
5180 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
5181 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
5182 bgp->evpn_info->dad_max_moves,
5183 bgp->evpn_info->dad_time);
5184
5185 if (bgp->evpn_info->dad_freeze) {
5186 if (bgp->evpn_info->dad_freeze_time)
5187 vty_out(vty,
5188 " dup-addr-detection freeze %u\n",
5189 bgp->evpn_info->dad_freeze_time);
5190 else
5191 vty_out(vty,
5192 " dup-addr-detection freeze permanent\n");
5193 }
5194
5195 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
5196 vty_out(vty, " flooding disable\n");
5197
5198 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5199 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
5200 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
5201 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
5202 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
5203 else
5204 vty_out(vty, " advertise ipv4 unicast\n");
5205 }
5206
5207 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5208 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
5209 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
5210 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
5211 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
5212 else
5213 vty_out(vty, " advertise ipv6 unicast\n");
5214 }
5215
5216 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5217 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
5218 vty_out(vty, " default-originate ipv4\n");
5219
5220 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5221 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
5222 vty_out(vty, " default-originate ipv6\n");
5223
5224 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
5225 vty_out(vty, " rd %s\n",
5226 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
5227
5228 /* import route-target */
5229 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5230 char *ecom_str;
5231 struct listnode *node, *nnode;
5232 struct ecommunity *ecom;
5233
5234 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
5235 ecom)) {
5236 ecom_str = ecommunity_ecom2str(
5237 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5238 vty_out(vty, " route-target import %s\n", ecom_str);
5239 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5240 }
5241 }
5242
5243 /* export route-target */
5244 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5245 char *ecom_str;
5246 struct listnode *node, *nnode;
5247 struct ecommunity *ecom;
5248
5249 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
5250 ecom)) {
5251 ecom_str = ecommunity_ecom2str(
5252 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5253 vty_out(vty, " route-target export %s\n", ecom_str);
5254 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5255 }
5256 }
5257 }
5258
5259 void bgp_ethernetvpn_init(void)
5260 {
5261 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
5262 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
5263 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
5264 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
5265 install_element(VIEW_NODE,
5266 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
5267 install_element(VIEW_NODE,
5268 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
5269 install_element(
5270 VIEW_NODE,
5271 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
5272 install_element(
5273 VIEW_NODE,
5274 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
5275 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
5276 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
5277 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
5278 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
5279 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
5280 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
5281 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
5282 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
5283 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
5284 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
5285 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
5286 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
5287 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
5288 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
5289 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
5290 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
5291 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
5292 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
5293 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5294
5295 /* test commands */
5296 install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
5297 install_element(BGP_EVPN_NODE, &test_withdraw_evpn_type4_route_cmd);
5298
5299 /* "show bgp l2vpn evpn" commands. */
5300 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
5301 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
5302 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
5303 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
5304 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
5305 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
5306 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
5307 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
5308 install_element(VIEW_NODE,
5309 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
5310 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
5311 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
5312 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
5313 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
5314
5315 /* "show bgp evpn" commands. */
5316 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
5317 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
5318 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
5319 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
5320 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
5321 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
5322 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
5323 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
5324 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
5325 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
5326 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5327
5328 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
5329 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
5330 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
5331 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
5332 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
5333 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
5334 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
5335 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
5336 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
5337 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5338 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
5339 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
5340 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5341 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
5342 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
5343 install_element(BGP_EVPN_VNI_NODE,
5344 &bgp_evpn_advertise_default_gw_vni_cmd);
5345 install_element(BGP_EVPN_VNI_NODE,
5346 &no_bgp_evpn_advertise_default_gw_vni_cmd);
5347 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5348 install_element(BGP_EVPN_VNI_NODE,
5349 &no_bgp_evpn_advertise_vni_subnet_cmd);
5350 }