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