]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
bgpd, lib, zebra: fix style problems
[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_ecommunity.h"
39
40 #define SHOW_DISPLAY_STANDARD 0
41 #define SHOW_DISPLAY_TAGS 1
42 #define SHOW_DISPLAY_OVERLAY 2
43 #define VNI_STR_LEN 32
44
45 /*
46 * Context for VNI hash walk - used by callbacks.
47 */
48 struct vni_walk_ctx {
49 struct bgp *bgp;
50 struct vty *vty;
51 struct in_addr vtep_ip;
52 json_object *json;
53 };
54
55 #if defined(HAVE_CUMULUS)
56 static void display_vrf_import_rt(struct vty *vty,
57 struct vrf_irt_node *irt,
58 json_object *json)
59 {
60 u_char *pnt;
61 u_char type, sub_type;
62 struct ecommunity_as eas;
63 struct ecommunity_ip eip;
64 struct listnode *node, *nnode;
65 struct bgp *tmp_bgp_vrf = NULL;
66 json_object *json_rt = NULL;
67 json_object *json_vrfs = NULL;
68 char rt_buf[RT_ADDRSTRLEN];
69
70 if (json) {
71 json_rt = json_object_new_object();
72 json_vrfs = json_object_new_array();
73 }
74
75 pnt = (u_char *)&irt->rt.val;
76 type = *pnt++;
77 sub_type = *pnt++;
78 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
79 return;
80
81 memset(&eas, 0, sizeof(eas));
82 switch (type) {
83 case ECOMMUNITY_ENCODE_AS:
84 eas.as = (*pnt++ << 8);
85 eas.as |= (*pnt++);
86 pnt = ptr_get_be32(pnt, &eas.val);
87
88 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
89
90 if (json)
91 json_object_string_add(json_rt, "rt", rt_buf);
92 else
93 vty_out(vty, "Route-target: %s", rt_buf);
94
95 break;
96
97 case ECOMMUNITY_ENCODE_IP:
98 memcpy(&eip.ip, pnt, 4);
99 pnt += 4;
100 eip.val = (*pnt++ << 8);
101 eip.val |= (*pnt++);
102
103 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
104 eip.val);
105
106 if (json)
107 json_object_string_add(json_rt, "rt", rt_buf);
108 else
109 vty_out(vty, "Route-target: %s", rt_buf);
110
111 break;
112
113 case ECOMMUNITY_ENCODE_AS4:
114 pnt = ptr_get_be32(pnt, &eas.val);
115 eas.val = (*pnt++ << 8);
116 eas.val |= (*pnt++);
117
118 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
119
120 if (json)
121 json_object_string_add(json_rt, "rt", rt_buf);
122 else
123 vty_out(vty, "Route-target: %s", rt_buf);
124
125 break;
126
127 default:
128 return;
129 }
130
131 if (!json) {
132 vty_out(vty,
133 "\nList of VRFs importing routes with this route-target:\n");
134 }
135
136 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
137 if (json)
138 json_object_array_add(
139 json_vrfs,
140 json_object_new_string(
141 vrf_id_to_name(
142 tmp_bgp_vrf->vrf_id)));
143 else
144 vty_out(vty, " %s\n",
145 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
146 }
147
148 if (json) {
149 json_object_object_add(json_rt, "vrfs", json_vrfs);
150 json_object_object_add(json, rt_buf, json_rt);
151 }
152 }
153
154 static void show_vrf_import_rt_entry(struct hash_backet *backet,
155 void *args[])
156 {
157 json_object *json = NULL;
158 struct vty *vty = NULL;
159 struct vrf_irt_node *irt = (struct vrf_irt_node *)backet->data;
160
161 vty = (struct vty *)args[0];
162 json = (struct json_object *)args[1];
163
164 display_vrf_import_rt(vty, irt, json);
165 }
166
167 static void display_import_rt(struct vty *vty, struct irt_node *irt,
168 json_object *json)
169 {
170 u_char *pnt;
171 u_char type, sub_type;
172 struct ecommunity_as eas;
173 struct ecommunity_ip eip;
174 struct listnode *node, *nnode;
175 struct bgpevpn *tmp_vpn;
176 json_object *json_rt = NULL;
177 json_object *json_vnis = NULL;
178 char rt_buf[RT_ADDRSTRLEN];
179
180 if (json) {
181 json_rt = json_object_new_object();
182 json_vnis = json_object_new_array();
183 }
184
185 /* TODO: This needs to go into a function */
186
187 pnt = (u_char *)&irt->rt.val;
188 type = *pnt++;
189 sub_type = *pnt++;
190 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191 return;
192
193 memset(&eas, 0, sizeof(eas));
194 switch (type) {
195 case ECOMMUNITY_ENCODE_AS:
196 eas.as = (*pnt++ << 8);
197 eas.as |= (*pnt++);
198 pnt = ptr_get_be32(pnt, &eas.val);
199
200 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
201
202 if (json)
203 json_object_string_add(json_rt, "rt", rt_buf);
204 else
205 vty_out(vty, "Route-target: %s", rt_buf);
206
207 break;
208
209 case ECOMMUNITY_ENCODE_IP:
210 memcpy(&eip.ip, pnt, 4);
211 pnt += 4;
212 eip.val = (*pnt++ << 8);
213 eip.val |= (*pnt++);
214
215 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
216 eip.val);
217
218 if (json)
219 json_object_string_add(json_rt, "rt", rt_buf);
220 else
221 vty_out(vty, "Route-target: %s", rt_buf);
222
223 break;
224
225 case ECOMMUNITY_ENCODE_AS4:
226 pnt = ptr_get_be32(pnt, &eas.val);
227 eas.val = (*pnt++ << 8);
228 eas.val |= (*pnt++);
229
230 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
231
232 if (json)
233 json_object_string_add(json_rt, "rt", rt_buf);
234 else
235 vty_out(vty, "Route-target: %s", rt_buf);
236
237 break;
238
239 default:
240 return;
241 }
242
243 if (!json) {
244 vty_out(vty,
245 "\nList of VNIs importing routes with this route-target:\n");
246 }
247
248 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
249 if (json)
250 json_object_array_add(
251 json_vnis, json_object_new_int64(tmp_vpn->vni));
252 else
253 vty_out(vty, " %u\n", tmp_vpn->vni);
254 }
255
256 if (json) {
257 json_object_object_add(json_rt, "vnis", json_vnis);
258 json_object_object_add(json, rt_buf, json_rt);
259 }
260 }
261
262 static void show_import_rt_entry(struct hash_backet *backet, void *args[])
263 {
264 json_object *json = NULL;
265 struct vty *vty = NULL;
266 struct irt_node *irt = (struct irt_node *)backet->data;
267
268 vty = args[0];
269 json = args[1];
270
271 display_import_rt(vty, irt, json);
272
273 return;
274 }
275
276 static void bgp_evpn_show_route_rd_header(struct vty *vty,
277 struct bgp_node *rd_rn,
278 json_object *json)
279 {
280 u_int16_t type;
281 struct rd_as rd_as;
282 struct rd_ip rd_ip;
283 u_char *pnt;
284 char rd_str[RD_ADDRSTRLEN];
285
286 pnt = rd_rn->p.u.val;
287
288 /* Decode RD type. */
289 type = decode_rd_type(pnt);
290
291 if (json)
292 return;
293
294 vty_out(vty, "Route Distinguisher: ");
295
296 switch (type) {
297 case RD_TYPE_AS:
298 decode_rd_as(pnt + 2, &rd_as);
299 snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
300 break;
301
302 case RD_TYPE_IP:
303 decode_rd_ip(pnt + 2, &rd_ip);
304 snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
305 rd_ip.val);
306 break;
307
308 default:
309 snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
310 break;
311 }
312
313 vty_out(vty, "%s\n", rd_str);
314 }
315
316 static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
317 json_object *json)
318 {
319 char ri_header[] =
320 " Network Next Hop Metric LocPrf Weight Path\n";
321
322 if (json)
323 return;
324
325
326 vty_out(vty, "BGP table version is 0, local router ID is %s\n",
327 inet_ntoa(bgp->router_id));
328 vty_out(vty,
329 "Status codes: s suppressed, d damped, h history, "
330 "* valid, > best, i - internal\n");
331 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
332 vty_out(vty,
333 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
334 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
335 vty_out(vty, "%s", ri_header);
336 }
337
338 static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
339 {
340 char buf1[RD_ADDRSTRLEN];
341 char *ecom_str;
342 struct listnode *node, *nnode;
343 struct ecommunity *ecom;
344 json_object *json_import_rtl = NULL;
345 json_object *json_export_rtl = NULL;
346
347 if (json) {
348 json_import_rtl = json_object_new_array();
349 json_export_rtl = json_object_new_array();
350 json_object_int_add(json, "vni", vpn->vni);
351 json_object_string_add(json, "kernelFlag",
352 is_vni_live(vpn) ? "Yes" : "No");
353 json_object_string_add(
354 json, "rd",
355 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
356 json_object_string_add(json, "originatorIp",
357 inet_ntoa(vpn->originator_ip));
358 json_object_string_add(json, "advertiseGatewayMacip",
359 vpn->advertise_gw_macip ? "Yes" : "No");
360 } else {
361 vty_out(vty, "VNI: %d", vpn->vni);
362 if (is_vni_live(vpn))
363 vty_out(vty, " (known to the kernel)");
364 vty_out(vty, "\n");
365
366 vty_out(vty, " Tenant-Vrf: %s\n",
367 vrf_id_to_name(vpn->tenant_vrf_id));
368 vty_out(vty, " RD: %s\n",
369 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
370 vty_out(vty, " Originator IP: %s\n",
371 inet_ntoa(vpn->originator_ip));
372 vty_out(vty, " Advertise-gw-macip : %s\n",
373 vpn->advertise_gw_macip ? "Yes" : "No");
374 }
375
376 if (!json)
377 vty_out(vty, " Import Route Target:\n");
378
379 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
380 ecom_str = ecommunity_ecom2str(ecom,
381 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
382
383 if (json)
384 json_object_array_add(json_import_rtl,
385 json_object_new_string(ecom_str));
386 else
387 vty_out(vty, " %s\n", ecom_str);
388
389 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
390 }
391
392 if (json)
393 json_object_object_add(json, "importRts", json_import_rtl);
394 else
395 vty_out(vty, " Export Route Target:\n");
396
397 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
398 ecom_str = ecommunity_ecom2str(ecom,
399 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
400
401 if (json)
402 json_object_array_add(json_export_rtl,
403 json_object_new_string(ecom_str));
404 else
405 vty_out(vty, " %s\n", ecom_str);
406
407 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
408 }
409
410 if (json)
411 json_object_object_add(json, "exportRts", json_export_rtl);
412 }
413
414 static void evpn_show_vrf_routes(struct vty *vty,
415 struct bgp *bgp_vrf)
416 {
417 struct bgp *bgp_def = NULL;
418 struct bgp_node *rn;
419 struct bgp_info *ri;
420 int header = 1;
421 u_int32_t prefix_cnt, path_cnt;
422 struct bgp_table *table;
423
424 prefix_cnt = path_cnt = 0;
425 bgp_def = bgp_get_default();
426 if (!bgp_def)
427 return;
428
429 table = (struct bgp_table *)bgp_vrf->rib[AFI_L2VPN][SAFI_EVPN];
430 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
431 char prefix_str[BUFSIZ];
432
433 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
434 sizeof(prefix_str));
435
436 if (rn->info) {
437 /* Overall header/legend displayed once. */
438 if (header) {
439 bgp_evpn_show_route_header(vty, bgp_def, NULL);
440 header = 0;
441 }
442 prefix_cnt++;
443 }
444
445 /* For EVPN, the prefix is displayed for each path (to fit in
446 * with code that already exists).
447 */
448 for (ri = rn->info; ri; ri = ri->next) {
449 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, NULL);
450 path_cnt++;
451 }
452 }
453
454 if (prefix_cnt == 0)
455 vty_out(vty, "No EVPN prefixes exist for this VRF");
456 else
457 vty_out(vty, "\nDisplayed %u prefixes (%u paths)",
458 prefix_cnt, path_cnt);
459 }
460
461 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
462 struct vty *vty, struct in_addr vtep_ip,
463 json_object *json)
464 {
465 struct bgp_node *rn;
466 struct bgp_info *ri;
467 int header = 1;
468 u_int32_t prefix_cnt, path_cnt;
469
470 prefix_cnt = path_cnt = 0;
471
472 for (rn = bgp_table_top(vpn->route_table); rn;
473 rn = bgp_route_next(rn)) {
474 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
475 int add_prefix_to_json = 0;
476 char prefix_str[BUFSIZ];
477 json_object *json_paths = NULL;
478 json_object *json_prefix = NULL;
479
480 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
481 sizeof(prefix_str));
482
483 if (type && evp->prefix.route_type != type)
484 continue;
485
486 if (json)
487 json_prefix = json_object_new_object();
488
489 if (rn->info) {
490 /* Overall header/legend displayed once. */
491 if (header) {
492 bgp_evpn_show_route_header(vty, bgp, json);
493 header = 0;
494 }
495
496 prefix_cnt++;
497 }
498
499 if (json)
500 json_paths = json_object_new_array();
501
502 /* For EVPN, the prefix is displayed for each path (to fit in
503 * with code that already exists).
504 */
505 for (ri = rn->info; ri; ri = ri->next) {
506 json_object *json_path = NULL;
507
508 if (vtep_ip.s_addr
509 && !IPV4_ADDR_SAME(&(vtep_ip),
510 &(ri->attr->nexthop)))
511 continue;
512
513 if (json)
514 json_path = json_object_new_array();
515
516 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN, json_path);
517
518 if (json)
519 json_object_array_add(json_paths, json_path);
520
521 path_cnt++;
522 add_prefix_to_json = 1;
523 }
524
525 if (json && add_prefix_to_json) {
526 json_object_string_add(json_prefix, "prefix",
527 prefix_str);
528 json_object_int_add(json_prefix, "prefixLen",
529 rn->p.prefixlen);
530 json_object_object_add(json_prefix, "paths",
531 json_paths);
532 json_object_object_add(json, prefix_str, json_prefix);
533 }
534 }
535
536 if (json) {
537 json_object_int_add(json, "numPrefix", prefix_cnt);
538 json_object_int_add(json, "numPaths", path_cnt);
539 } else {
540 if (prefix_cnt == 0)
541 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
542 type ? "(of requested type) " : "");
543 else
544 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s",
545 prefix_cnt, path_cnt,
546 type ? " (of requested type)" : "");
547 }
548 }
549
550 static void show_vni_routes_hash(struct hash_backet *backet, void *arg)
551 {
552 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
553 struct vni_walk_ctx *wctx = arg;
554 struct vty *vty = wctx->vty;
555 json_object *json = wctx->json;
556 json_object *json_vni = NULL;
557 char vni_str[VNI_STR_LEN];
558
559 snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
560 if (json) {
561 json_vni = json_object_new_object();
562 json_object_int_add(json_vni, "vni", vpn->vni);
563 } else {
564 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
565 }
566
567 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni);
568
569 if (json)
570 json_object_object_add(json, vni_str, json_vni);
571 }
572
573 static void show_vni_entry(struct hash_backet *backet, void *args[])
574 {
575 struct vty *vty;
576 json_object *json;
577 json_object *json_vni;
578 json_object *json_import_rtl;
579 json_object *json_export_rtl;
580 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
581 char buf1[10];
582 char buf2[RD_ADDRSTRLEN];
583 char rt_buf[25];
584 char *ecom_str;
585 struct listnode *node, *nnode;
586 struct ecommunity *ecom;
587
588 vty = args[0];
589 json = args[1];
590
591 if (json) {
592 json_vni = json_object_new_object();
593 json_import_rtl = json_object_new_array();
594 json_export_rtl = json_object_new_array();
595 }
596
597 buf1[0] = '\0';
598 if (is_vni_live(vpn))
599 sprintf(buf1, "*");
600
601 if (json) {
602 json_object_int_add(json_vni, "vni", vpn->vni);
603 json_object_string_add(json_vni, "inKernel",
604 is_vni_live(vpn) ? "True" : "False");
605 json_object_string_add(json_vni, "originatorIp",
606 inet_ntoa(vpn->originator_ip));
607 json_object_string_add(
608 json_vni, "rd",
609 prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
610 } else {
611 vty_out(vty, "%-1s %-10u %-15s %-21s", buf1, vpn->vni,
612 inet_ntoa(vpn->originator_ip),
613 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
614 }
615
616 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
617 ecom_str = ecommunity_ecom2str(ecom,
618 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
619
620 if (json) {
621 json_object_array_add(json_import_rtl,
622 json_object_new_string(ecom_str));
623 } else {
624 if (listcount(vpn->import_rtl) > 1)
625 sprintf(rt_buf, "%s, ...", ecom_str);
626 else
627 sprintf(rt_buf, "%s", ecom_str);
628 vty_out(vty, " %-25s", rt_buf);
629 }
630
631 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
632
633 /* If there are multiple import RTs we break here and show only
634 * one */
635 if (!json)
636 break;
637 }
638
639 if (json)
640 json_object_object_add(json_vni, "importRTs", json_import_rtl);
641
642 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
643 ecom_str = ecommunity_ecom2str(ecom,
644 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
645
646 if (json) {
647 json_object_array_add(json_export_rtl,
648 json_object_new_string(ecom_str));
649 } else {
650 if (listcount(vpn->export_rtl) > 1)
651 sprintf(rt_buf, "%s, ...", ecom_str);
652 else
653 sprintf(rt_buf, "%s", ecom_str);
654 vty_out(vty, " %-25s", rt_buf);
655 }
656
657 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
658
659 /* If there are multiple export RTs we break here and show only
660 * one */
661 if (!json)
662 break;
663 }
664
665 if (!json)
666 vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
667
668 if (json) {
669 char vni_str[VNI_STR_LEN];
670
671 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
672 snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
673 json_object_object_add(json, vni_str, json_vni);
674 } else {
675 vty_out(vty, "\n");
676 }
677 }
678 #endif /* HAVE_CUMULUS */
679
680 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
681 enum bgp_show_type type, void *output_arg,
682 int option, u_char use_json)
683 {
684 afi_t afi = AFI_L2VPN;
685 struct bgp *bgp;
686 struct bgp_table *table;
687 struct bgp_node *rn;
688 struct bgp_node *rm;
689 struct bgp_info *ri;
690 int rd_header;
691 int header = 1;
692
693 unsigned long output_count = 0;
694 unsigned long total_count = 0;
695 json_object *json = NULL;
696 json_object *json_nroute = NULL;
697 json_object *json_array = NULL;
698 json_object *json_scode = NULL;
699 json_object *json_ocode = NULL;
700
701 bgp = bgp_get_default();
702 if (bgp == NULL) {
703 if (!use_json)
704 vty_out(vty, "No BGP process is configured\n");
705 else
706 vty_out(vty, "{}\n");
707 return CMD_WARNING;
708 }
709
710 if (use_json) {
711 json_scode = json_object_new_object();
712 json_ocode = json_object_new_object();
713 json = json_object_new_object();
714 json_nroute = json_object_new_object();
715
716 json_object_string_add(json_scode, "suppressed", "s");
717 json_object_string_add(json_scode, "damped", "d");
718 json_object_string_add(json_scode, "history", "h");
719 json_object_string_add(json_scode, "valid", "*");
720 json_object_string_add(json_scode, "best", ">");
721 json_object_string_add(json_scode, "internal", "i");
722
723 json_object_string_add(json_ocode, "igp", "i");
724 json_object_string_add(json_ocode, "egp", "e");
725 json_object_string_add(json_ocode, "incomplete", "?");
726 }
727
728 for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
729 rn = bgp_route_next(rn)) {
730 if (use_json)
731 continue; /* XXX json TODO */
732
733 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
734 continue;
735
736 if ((table = rn->info) == NULL)
737 continue;
738
739 rd_header = 1;
740
741 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm))
742 for (ri = rm->info; ri; ri = ri->next) {
743 total_count++;
744 if (type == bgp_show_type_neighbor) {
745 union sockunion *su = output_arg;
746
747 if (ri->peer->su_remote == NULL
748 || !sockunion_same(
749 ri->peer->su_remote, su))
750 continue;
751 }
752 if (header == 0) {
753 if (use_json) {
754 if (option
755 == SHOW_DISPLAY_TAGS) {
756 json_object_int_add(
757 json,
758 "bgpTableVersion",
759 0);
760 json_object_string_add(
761 json,
762 "bgpLocalRouterId",
763 inet_ntoa(
764 bgp->router_id));
765 json_object_object_add(
766 json,
767 "bgpStatusCodes",
768 json_scode);
769 json_object_object_add(
770 json,
771 "bgpOriginCodes",
772 json_ocode);
773 }
774 } else {
775 if (option == SHOW_DISPLAY_TAGS)
776 vty_out(vty,
777 V4_HEADER_TAG);
778 else if (
779 option
780 == SHOW_DISPLAY_OVERLAY)
781 vty_out(vty,
782 V4_HEADER_OVERLAY);
783 else {
784 vty_out(vty,
785 "BGP table version is 0, local router ID is %s\n",
786 inet_ntoa(
787 bgp->router_id));
788 vty_out(vty,
789 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
790 vty_out(vty,
791 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
792 vty_out(vty, V4_HEADER);
793 }
794 }
795 header = 0;
796 }
797 if (rd_header) {
798 u_int16_t type;
799 struct rd_as rd_as;
800 struct rd_ip rd_ip;
801 u_char *pnt;
802
803 pnt = rn->p.u.val;
804
805 /* Decode RD type. */
806 type = decode_rd_type(pnt);
807 /* Decode RD value. */
808 if (type == RD_TYPE_AS)
809 decode_rd_as(pnt + 2, &rd_as);
810 else if (type == RD_TYPE_AS4)
811 decode_rd_as4(pnt + 2, &rd_as);
812 else if (type == RD_TYPE_IP)
813 decode_rd_ip(pnt + 2, &rd_ip);
814 if (use_json) {
815 char buffer[BUFSIZ];
816 if (type == RD_TYPE_AS
817 || type == RD_TYPE_AS4)
818 sprintf(buffer, "%u:%d",
819 rd_as.as,
820 rd_as.val);
821 else if (type == RD_TYPE_IP)
822 sprintf(buffer, "%s:%d",
823 inet_ntoa(
824 rd_ip.ip),
825 rd_ip.val);
826 json_object_string_add(
827 json_nroute,
828 "routeDistinguisher",
829 buffer);
830 } else {
831 vty_out(vty,
832 "Route Distinguisher: ");
833 if (type == RD_TYPE_AS)
834 vty_out(vty,
835 "as2 %u:%d",
836 rd_as.as,
837 rd_as.val);
838 else if (type == RD_TYPE_AS4)
839 vty_out(vty,
840 "as4 %u:%d",
841 rd_as.as,
842 rd_as.val);
843 else if (type == RD_TYPE_IP)
844 vty_out(vty, "ip %s:%d",
845 inet_ntoa(
846 rd_ip.ip),
847 rd_ip.val);
848 vty_out(vty, "\n\n");
849 }
850 rd_header = 0;
851 }
852 if (use_json)
853 json_array = json_object_new_array();
854 else
855 json_array = NULL;
856 if (option == SHOW_DISPLAY_TAGS)
857 route_vty_out_tag(vty, &rm->p, ri, 0,
858 SAFI_EVPN,
859 json_array);
860 else if (option == SHOW_DISPLAY_OVERLAY)
861 route_vty_out_overlay(vty, &rm->p, ri,
862 0, json_array);
863 else
864 route_vty_out(vty, &rm->p, ri, 0,
865 SAFI_EVPN, json_array);
866 output_count++;
867 }
868 /* XXX json */
869 }
870 if (output_count == 0)
871 vty_out(vty, "No prefixes displayed, %ld exist\n", total_count);
872 else
873 vty_out(vty, "\nDisplayed %ld out of %ld total prefixes\n",
874 output_count, total_count);
875 return CMD_SUCCESS;
876 }
877
878 DEFUN(show_ip_bgp_l2vpn_evpn,
879 show_ip_bgp_l2vpn_evpn_cmd,
880 "show [ip] bgp l2vpn evpn [json]",
881 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
882 {
883 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
884 use_json(argc, argv));
885 }
886
887 DEFUN(show_ip_bgp_l2vpn_evpn_rd,
888 show_ip_bgp_l2vpn_evpn_rd_cmd,
889 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
890 SHOW_STR
891 IP_STR
892 BGP_STR
893 L2VPN_HELP_STR
894 EVPN_HELP_STR
895 "Display information for a route distinguisher\n"
896 "VPN Route Distinguisher\n" JSON_STR)
897 {
898 int idx_ext_community = 0;
899 int ret;
900 struct prefix_rd prd;
901
902 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
903
904 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
905 if (!ret) {
906 vty_out(vty, "%% Malformed Route Distinguisher\n");
907 return CMD_WARNING;
908 }
909 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
910 use_json(argc, argv));
911 }
912
913 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
914 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
915 "show [ip] bgp l2vpn evpn all tags",
916 SHOW_STR
917 IP_STR
918 BGP_STR
919 L2VPN_HELP_STR
920 EVPN_HELP_STR
921 "Display information about all EVPN NLRIs\n"
922 "Display BGP tags for prefixes\n")
923 {
924 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
925 0);
926 }
927
928 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
929 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
930 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
931 SHOW_STR
932 IP_STR
933 BGP_STR
934 L2VPN_HELP_STR
935 EVPN_HELP_STR
936 "Display information for a route distinguisher\n"
937 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
938 {
939 int idx_ext_community = 0;
940 int ret;
941 struct prefix_rd prd;
942
943 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
944
945 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
946 if (!ret) {
947 vty_out(vty, "%% Malformed Route Distinguisher\n");
948 return CMD_WARNING;
949 }
950 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
951 0);
952 }
953
954 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes,
955 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd,
956 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
957 SHOW_STR
958 IP_STR
959 BGP_STR
960 L2VPN_HELP_STR
961 EVPN_HELP_STR
962 "Display information about all EVPN NLRIs\n"
963 "Detailed information on TCP and BGP neighbor connections\n"
964 "Neighbor to display information about\n"
965 "Display routes learned from neighbor\n" JSON_STR)
966 {
967 int idx_ipv4 = 0;
968 union sockunion su;
969 struct peer *peer;
970 int ret;
971 u_char uj = use_json(argc, argv);
972
973 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
974
975 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
976 if (ret < 0) {
977 if (uj) {
978 json_object *json_no = NULL;
979 json_no = json_object_new_object();
980 json_object_string_add(json_no, "warning",
981 "Malformed address");
982 vty_out(vty, "%s\n",
983 json_object_to_json_string(json_no));
984 json_object_free(json_no);
985 } else
986 vty_out(vty, "Malformed address: %s\n",
987 argv[idx_ipv4]->arg);
988 return CMD_WARNING;
989 }
990
991 peer = peer_lookup(NULL, &su);
992 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
993 if (uj) {
994 json_object *json_no = NULL;
995 json_no = json_object_new_object();
996 json_object_string_add(
997 json_no, "warning",
998 "No such neighbor or address family");
999 vty_out(vty, "%s\n",
1000 json_object_to_json_string(json_no));
1001 json_object_free(json_no);
1002 } else
1003 vty_out(vty, "%% No such neighbor or address family\n");
1004 return CMD_WARNING;
1005 }
1006
1007 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, &su, 0,
1008 uj);
1009 }
1010
1011 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1012 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1013 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1014 SHOW_STR
1015 IP_STR
1016 BGP_STR
1017 L2VPN_HELP_STR
1018 EVPN_HELP_STR
1019 "Display information for a route distinguisher\n"
1020 "VPN Route Distinguisher\n"
1021 "Detailed information on TCP and BGP neighbor connections\n"
1022 "Neighbor to display information about\n"
1023 "Display routes learned from neighbor\n" JSON_STR)
1024 {
1025 int idx_ext_community = 0;
1026 int idx_ipv4 = 0;
1027 int ret;
1028 union sockunion su;
1029 struct peer *peer;
1030 struct prefix_rd prd;
1031 u_char uj = use_json(argc, argv);
1032
1033 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1034 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1035
1036 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1037 if (!ret) {
1038 if (uj) {
1039 json_object *json_no = NULL;
1040 json_no = json_object_new_object();
1041 json_object_string_add(json_no, "warning",
1042 "Malformed Route Distinguisher");
1043 vty_out(vty, "%s\n",
1044 json_object_to_json_string(json_no));
1045 json_object_free(json_no);
1046 } else
1047 vty_out(vty, "%% Malformed Route Distinguisher\n");
1048 return CMD_WARNING;
1049 }
1050
1051 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1052 if (ret < 0) {
1053 if (uj) {
1054 json_object *json_no = NULL;
1055 json_no = json_object_new_object();
1056 json_object_string_add(json_no, "warning",
1057 "Malformed address");
1058 vty_out(vty, "%s\n",
1059 json_object_to_json_string(json_no));
1060 json_object_free(json_no);
1061 } else
1062 vty_out(vty, "Malformed address: %s\n",
1063 argv[idx_ext_community]->arg);
1064 return CMD_WARNING;
1065 }
1066
1067 peer = peer_lookup(NULL, &su);
1068 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1069 if (uj) {
1070 json_object *json_no = NULL;
1071 json_no = json_object_new_object();
1072 json_object_string_add(
1073 json_no, "warning",
1074 "No such neighbor or address family");
1075 vty_out(vty, "%s\n",
1076 json_object_to_json_string(json_no));
1077 json_object_free(json_no);
1078 } else
1079 vty_out(vty, "%% No such neighbor or address family\n");
1080 return CMD_WARNING;
1081 }
1082
1083 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, &su, 0,
1084 uj);
1085 }
1086
1087 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes,
1088 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd,
1089 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1090 SHOW_STR
1091 IP_STR
1092 BGP_STR
1093 L2VPN_HELP_STR
1094 EVPN_HELP_STR
1095 "Display information about all EVPN NLRIs\n"
1096 "Detailed information on TCP and BGP neighbor connections\n"
1097 "Neighbor to display information about\n"
1098 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1099 {
1100 int idx_ipv4 = 0;
1101 int ret;
1102 struct peer *peer;
1103 union sockunion su;
1104 u_char uj = use_json(argc, argv);
1105
1106 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1107
1108 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1109 if (ret < 0) {
1110 if (uj) {
1111 json_object *json_no = NULL;
1112 json_no = json_object_new_object();
1113 json_object_string_add(json_no, "warning",
1114 "Malformed address");
1115 vty_out(vty, "%s\n",
1116 json_object_to_json_string(json_no));
1117 json_object_free(json_no);
1118 } else
1119 vty_out(vty, "Malformed address: %s\n",
1120 argv[idx_ipv4]->arg);
1121 return CMD_WARNING;
1122 }
1123 peer = peer_lookup(NULL, &su);
1124 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1125 if (uj) {
1126 json_object *json_no = NULL;
1127 json_no = json_object_new_object();
1128 json_object_string_add(
1129 json_no, "warning",
1130 "No such neighbor or address family");
1131 vty_out(vty, "%s\n",
1132 json_object_to_json_string(json_no));
1133 json_object_free(json_no);
1134 } else
1135 vty_out(vty, "%% No such neighbor or address family\n");
1136 return CMD_WARNING;
1137 }
1138
1139 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1140 }
1141
1142 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1143 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1144 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1145 SHOW_STR
1146 IP_STR
1147 BGP_STR
1148 L2VPN_HELP_STR
1149 EVPN_HELP_STR
1150 "Display information for a route distinguisher\n"
1151 "VPN Route Distinguisher\n"
1152 "Detailed information on TCP and BGP neighbor connections\n"
1153 "Neighbor to display information about\n"
1154 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1155 {
1156 int idx_ext_community = 0;
1157 int idx_ipv4 = 0;
1158 int ret;
1159 struct peer *peer;
1160 struct prefix_rd prd;
1161 union sockunion su;
1162 u_char uj = use_json(argc, argv);
1163
1164 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1165 argv_find(argv, argc, "A.B.C.D", &idx_ipv4);
1166
1167 ret = str2sockunion(argv[idx_ipv4]->arg, &su);
1168 if (ret < 0) {
1169 if (uj) {
1170 json_object *json_no = NULL;
1171 json_no = json_object_new_object();
1172 json_object_string_add(json_no, "warning",
1173 "Malformed address");
1174 vty_out(vty, "%s\n",
1175 json_object_to_json_string(json_no));
1176 json_object_free(json_no);
1177 } else
1178 vty_out(vty, "Malformed address: %s\n",
1179 argv[idx_ext_community]->arg);
1180 return CMD_WARNING;
1181 }
1182 peer = peer_lookup(NULL, &su);
1183 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1184 if (uj) {
1185 json_object *json_no = NULL;
1186 json_no = json_object_new_object();
1187 json_object_string_add(
1188 json_no, "warning",
1189 "No such neighbor or address family");
1190 vty_out(vty, "%s\n",
1191 json_object_to_json_string(json_no));
1192 json_object_free(json_no);
1193 } else
1194 vty_out(vty, "%% No such neighbor or address family\n");
1195 return CMD_WARNING;
1196 }
1197
1198 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1199 if (!ret) {
1200 if (uj) {
1201 json_object *json_no = NULL;
1202 json_no = json_object_new_object();
1203 json_object_string_add(json_no, "warning",
1204 "Malformed Route Distinguisher");
1205 vty_out(vty, "%s\n",
1206 json_object_to_json_string(json_no));
1207 json_object_free(json_no);
1208 } else
1209 vty_out(vty, "%% Malformed Route Distinguisher\n");
1210 return CMD_WARNING;
1211 }
1212
1213 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1214 }
1215
1216 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1217 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1218 "show [ip] bgp l2vpn evpn all overlay",
1219 SHOW_STR
1220 IP_STR
1221 BGP_STR
1222 L2VPN_HELP_STR
1223 EVPN_HELP_STR
1224 "Display information about all EVPN NLRIs\n"
1225 "Display BGP Overlay Information for prefixes\n")
1226 {
1227 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1228 SHOW_DISPLAY_OVERLAY,
1229 use_json(argc, argv));
1230 }
1231
1232 DEFUN(show_ip_bgp_evpn_rd_overlay,
1233 show_ip_bgp_evpn_rd_overlay_cmd,
1234 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1235 SHOW_STR
1236 IP_STR
1237 BGP_STR
1238 L2VPN_HELP_STR
1239 EVPN_HELP_STR
1240 "Display information for a route distinguisher\n"
1241 "VPN Route Distinguisher\n"
1242 "Display BGP Overlay Information for prefixes\n")
1243 {
1244 int idx_ext_community = 0;
1245 int ret;
1246 struct prefix_rd prd;
1247
1248 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1249
1250 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1251 if (!ret) {
1252 vty_out(vty, "%% Malformed Route Distinguisher\n");
1253 return CMD_WARNING;
1254 }
1255 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1256 SHOW_DISPLAY_OVERLAY,
1257 use_json(argc, argv));
1258 }
1259
1260 /* For testing purpose, static route of MPLS-VPN. */
1261 DEFUN(evpnrt5_network,
1262 evpnrt5_network_cmd,
1263 "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]",
1264 "Specify a network to announce via BGP\n"
1265 "IP prefix\n"
1266 "IPv6 prefix\n"
1267 "Specify Route Distinguisher\n"
1268 "VPN Route Distinguisher\n"
1269 "Ethernet Tag\n"
1270 "Ethernet Tag Value\n"
1271 "BGP label\n"
1272 "label value\n"
1273 "Ethernet Segment Identifier\n"
1274 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1275 "Gateway IP\n"
1276 "Gateway IP ( A.B.C.D )\n"
1277 "Gateway IPv6 ( X:X::X:X )\n"
1278 "Router Mac Ext Comm\n"
1279 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1280 "Route-map to modify the attributes\n"
1281 "Name of the route map\n")
1282 {
1283 int idx_ipv4_prefixlen = 1;
1284 int idx_route_distinguisher = 3;
1285 int idx_label = 7;
1286 int idx_esi = 9;
1287 int idx_gwip = 11;
1288 int idx_ethtag = 5;
1289 int idx_routermac = 13;
1290
1291 return bgp_static_set_safi(
1292 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1293 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg,
1294 NULL,
1295 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1296 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1297 argv[idx_routermac]->arg);
1298 }
1299
1300 /* For testing purpose, static route of MPLS-VPN. */
1301 DEFUN(no_evpnrt5_network,
1302 no_evpnrt5_network_cmd,
1303 "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>",
1304 NO_STR
1305 "Specify a network to announce via BGP\n"
1306 "IP prefix\n"
1307 "IPv6 prefix\n"
1308 "Specify Route Distinguisher\n"
1309 "VPN Route Distinguisher\n"
1310 "Ethernet Tag\n"
1311 "Ethernet Tag Value\n"
1312 "BGP label\n"
1313 "label value\n"
1314 "Ethernet Segment Identifier\n"
1315 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1316 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1317 {
1318 int idx_ipv4_prefixlen = 2;
1319 int idx_ext_community = 4;
1320 int idx_label = 8;
1321 int idx_ethtag = 6;
1322 int idx_esi = 10;
1323 int idx_gwip = 12;
1324 return bgp_static_unset_safi(
1325 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1326 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1327 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1328 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
1329 }
1330
1331 #if defined(HAVE_CUMULUS)
1332
1333 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1334 {
1335 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
1336 }
1337
1338 static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1339 {
1340 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl);
1341 }
1342
1343 /*
1344 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1345 * check that this is a change.
1346 */
1347 static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1348 struct ecommunity *ecomadd)
1349 {
1350 /* If the VNI is "live", we need to uninstall routes using the current
1351 * import RT(s) first before we update the import RT, and subsequently
1352 * install routes.
1353 */
1354 if (is_vni_live(vpn))
1355 bgp_evpn_uninstall_routes(bgp, vpn);
1356
1357 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1358 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1359
1360 /* If the auto route-target is in use we must remove it */
1361 evpn_import_rt_delete_auto(bgp, vpn);
1362
1363 /* Add new RT and rebuild the RT to VNI mapping */
1364 listnode_add_sort(vpn->import_rtl, ecomadd);
1365
1366 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1367 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1368
1369 /* Install routes that match new import RT */
1370 if (is_vni_live(vpn))
1371 bgp_evpn_install_routes(bgp, vpn);
1372 }
1373
1374 /*
1375 * Unconfigure Import RT(s) for a VNI (vty handler).
1376 */
1377 static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1378 struct ecommunity *ecomdel)
1379 {
1380 struct listnode *node, *nnode, *node_to_del;
1381 struct ecommunity *ecom;
1382
1383 /* Along the lines of "configure" except we have to reset to the
1384 * automatic value.
1385 */
1386 if (is_vni_live(vpn))
1387 bgp_evpn_uninstall_routes(bgp, vpn);
1388
1389 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1390 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1391
1392 /* Delete all import RTs */
1393 if (ecomdel == NULL) {
1394 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom))
1395 ecommunity_free(&ecom);
1396
1397 list_delete_all_node(vpn->import_rtl);
1398 }
1399
1400 /* Delete a specific import RT */
1401 else {
1402 node_to_del = NULL;
1403
1404 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1405 if (ecommunity_match(ecom, ecomdel)) {
1406 ecommunity_free(&ecom);
1407 node_to_del = node;
1408 break;
1409 }
1410 }
1411
1412 if (node_to_del)
1413 list_delete_node(vpn->import_rtl, node_to_del);
1414 }
1415
1416 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1417 if (list_isempty(vpn->import_rtl)) {
1418 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1419 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1420 }
1421 /* Rebuild the RT to VNI mapping */
1422 else
1423 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1424
1425 /* Install routes that match new import RT */
1426 if (is_vni_live(vpn))
1427 bgp_evpn_install_routes(bgp, vpn);
1428 }
1429
1430 /*
1431 * Configure the Export RT for a VNI (vty handler). Caller expected to
1432 * check that this is a change. Note that only a single export RT is
1433 * allowed for a VNI and any change to configuration is implemented as
1434 * a "replace" (similar to other configuration).
1435 */
1436 static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1437 struct ecommunity *ecomadd)
1438 {
1439 /* If the auto route-target is in use we must remove it */
1440 evpn_export_rt_delete_auto(bgp, vpn);
1441
1442 listnode_add_sort(vpn->export_rtl, ecomadd);
1443 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1444
1445 if (is_vni_live(vpn))
1446 bgp_evpn_handle_export_rt_change(bgp, vpn);
1447 }
1448
1449 /*
1450 * Unconfigure the Export RT for a VNI (vty handler)
1451 */
1452 static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1453 struct ecommunity *ecomdel)
1454 {
1455 struct listnode *node, *nnode, *node_to_del;
1456 struct ecommunity *ecom;
1457
1458 /* Delete all export RTs */
1459 if (ecomdel == NULL) {
1460 /* Reset to default and process all routes. */
1461 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom))
1462 ecommunity_free(&ecom);
1463
1464 list_delete_all_node(vpn->export_rtl);
1465 }
1466
1467 /* Delete a specific export RT */
1468 else {
1469 node_to_del = NULL;
1470
1471 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1472 if (ecommunity_match(ecom, ecomdel)) {
1473 ecommunity_free(&ecom);
1474 node_to_del = node;
1475 break;
1476 }
1477 }
1478
1479 if (node_to_del)
1480 list_delete_node(vpn->export_rtl, node_to_del);
1481 }
1482
1483 if (list_isempty(vpn->export_rtl)) {
1484 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1485 bgp_evpn_derive_auto_rt_export(bgp, vpn);
1486 }
1487
1488 if (is_vni_live(vpn))
1489 bgp_evpn_handle_export_rt_change(bgp, vpn);
1490 }
1491
1492 /*
1493 * Configure RD for VRF
1494 */
1495 static void evpn_configure_vrf_rd(struct bgp *bgp_vrf,
1496 struct prefix_rd *rd)
1497 {
1498 /* If we have already advertise type-5 routes with a diffrent RD, we
1499 * have to delete and withdraw them firs
1500 */
1501 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1502
1503 /* update RD */
1504 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
1505 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
1506
1507 /* We have a new RD for VRF.
1508 * Advertise all type-5 routes again with the new RD
1509 */
1510 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1511 }
1512
1513 /*
1514 * Unconfigure RD for VRF
1515 */
1516 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
1517 {
1518 /* If we have already advertise type-5 routes with a diffrent RD, we
1519 * have to delete and withdraw them firs
1520 */
1521 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1522
1523 /* fall back to default RD */
1524 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
1525
1526 /* We have a new RD for VRF.
1527 * Advertise all type-5 routes again with the new RD
1528 */
1529 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1530 }
1531
1532 /*
1533 * Configure RD for a VNI (vty handler)
1534 */
1535 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
1536 struct prefix_rd *rd)
1537 {
1538 /* If the VNI is "live", we need to delete and withdraw this VNI's
1539 * local routes with the prior RD first. Then, after updating RD,
1540 * need to re-advertise.
1541 */
1542 if (is_vni_live(vpn))
1543 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1544
1545 /* update RD */
1546 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
1547 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
1548
1549 if (is_vni_live(vpn))
1550 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1551 }
1552
1553 /*
1554 * Unconfigure RD for a VNI (vty handler)
1555 */
1556 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
1557 {
1558 /* If the VNI is "live", we need to delete and withdraw this VNI's
1559 * local routes with the prior RD first. Then, after resetting RD
1560 * to automatic value, need to re-advertise.
1561 */
1562 if (is_vni_live(vpn))
1563 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1564
1565 /* reset RD to default */
1566 bgp_evpn_derive_auto_rd(bgp, vpn);
1567
1568 if (is_vni_live(vpn))
1569 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1570 }
1571
1572 /*
1573 * Create VNI, if not already present (VTY handler). Mark as configured.
1574 */
1575 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
1576 {
1577 struct bgpevpn *vpn;
1578
1579 if (!bgp->vnihash)
1580 return NULL;
1581
1582 vpn = bgp_evpn_lookup_vni(bgp, vni);
1583 if (!vpn) {
1584 /* tenant vrf will be updated when we get local_vni_add from
1585 * zebra
1586 */
1587 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0);
1588 if (!vpn) {
1589 zlog_err(
1590 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1591 bgp->vrf_id, vni);
1592 return NULL;
1593 }
1594 }
1595
1596 /* Mark as configured. */
1597 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1598 return vpn;
1599 }
1600
1601 /*
1602 * Delete VNI. If VNI does not exist in the system (i.e., just
1603 * configuration), all that is needed is to free it. Otherwise,
1604 * any parameters configured for the VNI need to be reset (with
1605 * appropriate action) and the VNI marked as unconfigured; the
1606 * VNI will continue to exist, purely as a "learnt" entity.
1607 */
1608 static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
1609 {
1610 assert(bgp->vnihash);
1611
1612 if (!is_vni_live(vpn)) {
1613 bgp_evpn_free(bgp, vpn);
1614 return 0;
1615 }
1616
1617 /* We need to take the unconfigure action for each parameter of this VNI
1618 * that is configured. Some optimization is possible, but not worth the
1619 * additional code for an operation that should be pretty rare.
1620 */
1621 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1622
1623 /* First, deal with the export side - RD and export RT changes. */
1624 if (is_rd_configured(vpn))
1625 evpn_unconfigure_rd(bgp, vpn);
1626 if (is_export_rt_configured(vpn))
1627 evpn_unconfigure_export_rt(bgp, vpn, NULL);
1628
1629 /* Next, deal with the import side. */
1630 if (is_import_rt_configured(vpn))
1631 evpn_unconfigure_import_rt(bgp, vpn, NULL);
1632
1633 return 0;
1634 }
1635
1636 /*
1637 * Display import RT mapping to VRFs (vty handler)
1638 * bgp_def: default bgp instance
1639 */
1640 static void evpn_show_vrf_import_rts(struct vty *vty,
1641 struct bgp *bgp_def,
1642 json_object *json)
1643 {
1644 void *args[2];
1645
1646 args[0] = vty;
1647 args[1] = json;
1648
1649 hash_iterate(bgp_def->vrf_import_rt_hash,
1650 (void (*)(struct hash_backet *, void *))
1651 show_vrf_import_rt_entry,
1652 args);
1653 }
1654
1655 /*
1656 * Display import RT mapping to VNIs (vty handler)
1657 */
1658 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
1659 json_object *json)
1660 {
1661 void *args[2];
1662
1663 args[0] = vty;
1664 args[1] = json;
1665
1666 hash_iterate(
1667 bgp->import_rt_hash,
1668 (void (*)(struct hash_backet *, void *))show_import_rt_entry,
1669 args);
1670 }
1671
1672 /*
1673 * Display EVPN routes for all VNIs - vty handler.
1674 */
1675 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
1676 struct in_addr vtep_ip, json_object *json)
1677 {
1678 u_int32_t num_vnis;
1679 struct vni_walk_ctx wctx;
1680
1681 num_vnis = hashcount(bgp->vnihash);
1682 if (!num_vnis)
1683 return;
1684 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
1685 wctx.bgp = bgp;
1686 wctx.vty = vty;
1687 wctx.vtep_ip = vtep_ip;
1688 wctx.json = json;
1689 hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
1690 void *))show_vni_routes_hash,
1691 &wctx);
1692 }
1693
1694 /*
1695 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1696 */
1697 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
1698 vni_t vni, struct in_addr orig_ip,
1699 json_object *json)
1700 {
1701 struct bgpevpn *vpn;
1702 struct prefix_evpn p;
1703 struct bgp_node *rn;
1704 struct bgp_info *ri;
1705 u_int32_t path_cnt = 0;
1706 afi_t afi;
1707 safi_t safi;
1708 json_object *json_paths = NULL;
1709
1710 afi = AFI_L2VPN;
1711 safi = SAFI_EVPN;
1712
1713 /* Locate VNI. */
1714 vpn = bgp_evpn_lookup_vni(bgp, vni);
1715 if (!vpn) {
1716 vty_out(vty, "VNI not found\n");
1717 return;
1718 }
1719
1720 /* See if route exists. */
1721 build_evpn_type3_prefix(&p, orig_ip);
1722 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1723 if (!rn || !rn->info) {
1724 if (!json)
1725 vty_out(vty, "%% Network not in table\n");
1726 return;
1727 }
1728
1729 if (json)
1730 json_paths = json_object_new_array();
1731
1732 /* Prefix and num paths displayed once per prefix. */
1733 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
1734
1735 /* Display each path for this prefix. */
1736 for (ri = rn->info; ri; ri = ri->next) {
1737 json_object *json_path = NULL;
1738
1739 if (json)
1740 json_path = json_object_new_array();
1741
1742 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1743 json_path);
1744
1745 if (json)
1746 json_object_array_add(json_paths, json_path);
1747
1748 path_cnt++;
1749 }
1750
1751 if (json) {
1752 if (path_cnt)
1753 json_object_object_add(json, "paths", json_paths);
1754
1755 json_object_int_add(json, "numPaths", path_cnt);
1756 } else {
1757 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1758 path_cnt);
1759 }
1760 }
1761
1762 /*
1763 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1764 * By definition, only matching type-2 route will be displayed.
1765 */
1766 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
1767 vni_t vni, struct ethaddr *mac,
1768 struct ipaddr *ip, json_object *json)
1769 {
1770 struct bgpevpn *vpn;
1771 struct prefix_evpn p;
1772 struct bgp_node *rn;
1773 struct bgp_info *ri;
1774 u_int32_t path_cnt = 0;
1775 afi_t afi;
1776 safi_t safi;
1777 json_object *json_paths = NULL;
1778
1779 afi = AFI_L2VPN;
1780 safi = SAFI_EVPN;
1781
1782 /* Locate VNI. */
1783 vpn = bgp_evpn_lookup_vni(bgp, vni);
1784 if (!vpn) {
1785 if (!json)
1786 vty_out(vty, "VNI not found\n");
1787 return;
1788 }
1789
1790 /* See if route exists. Look for both non-sticky and sticky. */
1791 build_evpn_type2_prefix(&p, mac, ip);
1792 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1793 if (!rn || !rn->info) {
1794 if (!json)
1795 vty_out(vty, "%% Network not in table\n");
1796 return;
1797 }
1798
1799 if (json)
1800 json_paths = json_object_new_array();
1801
1802 /* Prefix and num paths displayed once per prefix. */
1803 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
1804
1805 /* Display each path for this prefix. */
1806 for (ri = rn->info; ri; ri = ri->next) {
1807 json_object *json_path = NULL;
1808
1809 if (json)
1810 json_path = json_object_new_array();
1811
1812 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1813 json_path);
1814
1815 if (json)
1816 json_object_array_add(json_paths, json_path);
1817
1818 path_cnt++;
1819 }
1820
1821 if (json) {
1822 if (path_cnt)
1823 json_object_object_add(json, "paths", json_paths);
1824
1825 json_object_int_add(json, "numPaths", path_cnt);
1826 } else {
1827 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1828 path_cnt);
1829 }
1830 }
1831
1832 /*
1833 * Display EVPN routes for a VNI - vty handler.
1834 * If 'type' is non-zero, only routes matching that type are shown.
1835 * If the vtep_ip is non zero, only routes behind that vtep are shown
1836 */
1837 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
1838 int type, struct in_addr vtep_ip,
1839 json_object *json)
1840 {
1841 struct bgpevpn *vpn;
1842
1843 /* Locate VNI. */
1844 vpn = bgp_evpn_lookup_vni(bgp, vni);
1845 if (!vpn) {
1846 if (!json)
1847 vty_out(vty, "VNI not found\n");
1848 return;
1849 }
1850
1851 /* Walk this VNI's route table and display appropriate routes. */
1852 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
1853 }
1854
1855 /*
1856 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1857 * IP (vty handler). By definition, only matching type-2 route will be
1858 * displayed.
1859 */
1860 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
1861 struct prefix_rd *prd, struct ethaddr *mac,
1862 struct ipaddr *ip, json_object *json)
1863 {
1864 struct prefix_evpn p;
1865 struct bgp_node *rn;
1866 struct bgp_info *ri;
1867 afi_t afi;
1868 safi_t safi;
1869 u_int32_t path_cnt = 0;
1870 json_object *json_paths = NULL;
1871 char prefix_str[BUFSIZ];
1872
1873 afi = AFI_L2VPN;
1874 safi = SAFI_EVPN;
1875
1876 /* See if route exists. Look for both non-sticky and sticky. */
1877 build_evpn_type2_prefix(&p, mac, ip);
1878 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
1879 (struct prefix *)&p, prd);
1880 if (!rn || !rn->info) {
1881 if (!json)
1882 vty_out(vty, "%% Network not in table\n");
1883 return;
1884 }
1885
1886 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
1887 sizeof(prefix_str));
1888
1889 /* Prefix and num paths displayed once per prefix. */
1890 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
1891
1892 if (json)
1893 json_paths = json_object_new_array();
1894
1895 /* Display each path for this prefix. */
1896 for (ri = rn->info; ri; ri = ri->next) {
1897 json_object *json_path = NULL;
1898
1899 if (json)
1900 json_path = json_object_new_array();
1901
1902 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1903 json_path);
1904
1905 if (json)
1906 json_object_array_add(json_paths, json_path);
1907
1908 path_cnt++;
1909 }
1910
1911 if (json && path_cnt) {
1912 if (path_cnt)
1913 json_object_object_add(json, prefix_str, json_paths);
1914 json_object_int_add(json, "numPaths", path_cnt);
1915 } else {
1916 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1917 path_cnt);
1918 }
1919 }
1920
1921 /*
1922 * Display BGP EVPN routing table -- for specific RD (vty handler)
1923 * If 'type' is non-zero, only routes matching that type are shown.
1924 */
1925 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
1926 struct prefix_rd *prd, int type,
1927 json_object *json)
1928 {
1929 struct bgp_node *rd_rn;
1930 struct bgp_table *table;
1931 struct bgp_node *rn;
1932 struct bgp_info *ri;
1933 int rd_header = 1;
1934 afi_t afi;
1935 safi_t safi;
1936 u_int32_t prefix_cnt, path_cnt;
1937 char rd_str[RD_ADDRSTRLEN];
1938 json_object *json_rd = NULL;
1939 int add_rd_to_json = 0;
1940
1941 afi = AFI_L2VPN;
1942 safi = SAFI_EVPN;
1943 prefix_cnt = path_cnt = 0;
1944
1945 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
1946
1947 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
1948 if (!rd_rn)
1949 return;
1950
1951 table = (struct bgp_table *)rd_rn->info;
1952 if (table == NULL)
1953 return;
1954
1955 if (json) {
1956 json_rd = json_object_new_object();
1957 json_object_string_add(json_rd, "rd", rd_str);
1958 }
1959
1960 /* Display all prefixes with this RD. */
1961 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
1962 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
1963 json_object *json_prefix = NULL;
1964 json_object *json_paths = NULL;
1965 char prefix_str[BUFSIZ];
1966 int add_prefix_to_json = 0;
1967
1968 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
1969 sizeof(prefix_str));
1970
1971 if (type && evp->prefix.route_type != type)
1972 continue;
1973
1974 if (json)
1975 json_prefix = json_object_new_object();
1976
1977 if (rn->info) {
1978 /* RD header and legend - once overall. */
1979 if (rd_header && !json) {
1980 vty_out(vty,
1981 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]\n");
1982 vty_out(vty,
1983 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
1984 vty_out(vty,
1985 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
1986 rd_header = 0;
1987 }
1988
1989 /* Prefix and num paths displayed once per prefix. */
1990 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
1991 safi, json_prefix);
1992
1993 prefix_cnt++;
1994 }
1995
1996 if (json)
1997 json_paths = json_object_new_array();
1998
1999 /* Display each path for this prefix. */
2000 for (ri = rn->info; ri; ri = ri->next) {
2001 json_object *json_path = NULL;
2002
2003 if (json)
2004 json_path = json_object_new_array();
2005
2006 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
2007 json_path);
2008
2009 if (json)
2010 json_object_array_add(json_paths, json_path);
2011
2012 path_cnt++;
2013 add_prefix_to_json = 1;
2014 add_rd_to_json = 1;
2015 }
2016
2017 if (json && add_prefix_to_json) {
2018 json_object_object_add(json_prefix, "paths",
2019 json_paths);
2020 json_object_object_add(json_rd, prefix_str,
2021 json_prefix);
2022 }
2023 }
2024
2025 if (json && add_rd_to_json)
2026 json_object_object_add(json, rd_str, json_rd);
2027
2028 if (json) {
2029 json_object_int_add(json, "numPrefix", prefix_cnt);
2030 json_object_int_add(json, "numPaths", path_cnt);
2031 } else {
2032 if (prefix_cnt == 0)
2033 vty_out(vty, "No prefixes exist with this RD%s\n",
2034 type ? " (of requested type)" : "");
2035 else
2036 vty_out(vty,
2037 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2038 prefix_cnt, path_cnt,
2039 type ? " (of requested type)" : "");
2040 }
2041 }
2042
2043 /*
2044 * Display BGP EVPN routing table - all routes (vty handler).
2045 * If 'type' is non-zero, only routes matching that type are shown.
2046 */
2047 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2048 json_object *json)
2049 {
2050 struct bgp_node *rd_rn;
2051 struct bgp_table *table;
2052 struct bgp_node *rn;
2053 struct bgp_info *ri;
2054 int header = 1;
2055 int rd_header;
2056 afi_t afi;
2057 safi_t safi;
2058 u_int32_t prefix_cnt, path_cnt;
2059
2060 afi = AFI_L2VPN;
2061 safi = SAFI_EVPN;
2062 prefix_cnt = path_cnt = 0;
2063
2064 /* EVPN routing table is a 2-level table with the first level being
2065 * the RD.
2066 */
2067 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2068 rd_rn = bgp_route_next(rd_rn)) {
2069 char rd_str[RD_ADDRSTRLEN];
2070 json_object *json_rd = NULL; /* contains routes for an RD */
2071 int add_rd_to_json = 0;
2072
2073 table = (struct bgp_table *)rd_rn->info;
2074 if (table == NULL)
2075 continue;
2076
2077 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2078 sizeof(rd_str));
2079
2080 if (json) {
2081 json_rd = json_object_new_object();
2082 json_object_string_add(json_rd, "rd", rd_str);
2083 }
2084
2085 rd_header = 1;
2086
2087 /* Display all prefixes for an RD */
2088 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2089 json_object *json_prefix =
2090 NULL; /* contains prefix under a RD */
2091 json_object *json_paths =
2092 NULL; /* array of paths under a prefix*/
2093 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2094 char prefix_str[BUFSIZ];
2095 int add_prefix_to_json = 0;
2096
2097 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2098 prefix_str, sizeof(prefix_str));
2099
2100 if (type && evp->prefix.route_type != type)
2101 continue;
2102
2103 if (rn->info) {
2104 /* Overall header/legend displayed once. */
2105 if (header) {
2106 bgp_evpn_show_route_header(vty, bgp,
2107 json);
2108 header = 0;
2109 }
2110
2111 /* RD header - per RD. */
2112 if (rd_header) {
2113 bgp_evpn_show_route_rd_header(
2114 vty, rd_rn, json);
2115 rd_header = 0;
2116 }
2117
2118 prefix_cnt++;
2119 }
2120
2121 if (json) {
2122 json_prefix = json_object_new_object();
2123 json_paths = json_object_new_array();
2124 json_object_string_add(json_prefix, "prefix",
2125 prefix_str);
2126 json_object_int_add(json_prefix, "prefixLen",
2127 rn->p.prefixlen);
2128 }
2129
2130 /* For EVPN, the prefix is displayed for each path (to
2131 * fit in
2132 * with code that already exists).
2133 */
2134 for (ri = rn->info; ri; ri = ri->next) {
2135 json_object *json_path = NULL;
2136 path_cnt++;
2137 add_prefix_to_json = 1;
2138 add_rd_to_json = 1;
2139
2140 if (json)
2141 json_path = json_object_new_array();
2142
2143 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
2144 json_path);
2145
2146 if (json)
2147 json_object_array_add(json_paths,
2148 json_path);
2149 }
2150
2151 if (json && add_prefix_to_json) {
2152 json_object_object_add(json_prefix, "paths",
2153 json_paths);
2154 json_object_object_add(json_rd, prefix_str,
2155 json_prefix);
2156 }
2157 }
2158
2159 if (json && add_rd_to_json)
2160 json_object_object_add(json, rd_str, json_rd);
2161 }
2162
2163 if (json) {
2164 json_object_int_add(json, "numPrefix", prefix_cnt);
2165 json_object_int_add(json, "numPaths", path_cnt);
2166 } else {
2167 if (prefix_cnt == 0) {
2168 vty_out(vty, "No EVPN prefixes %sexist\n",
2169 type ? "(of requested type) " : "");
2170 } else {
2171 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2172 prefix_cnt, path_cnt,
2173 type ? " (of requested type)" : "");
2174 }
2175 }
2176 }
2177
2178 /*
2179 * Display specified VNI (vty handler)
2180 */
2181 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2182 json_object *json)
2183 {
2184 struct bgpevpn *vpn;
2185
2186 vpn = bgp_evpn_lookup_vni(bgp, vni);
2187 if (!vpn) {
2188 if (json) {
2189 vty_out(vty, "{}\n");
2190 } else {
2191 vty_out(vty, "VNI not found\n");
2192 return;
2193 }
2194 }
2195
2196 display_vni(vty, vpn, json);
2197 }
2198
2199 /*
2200 * Display a VNI (upon user query).
2201 */
2202 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2203 json_object *json)
2204 {
2205 u_int32_t num_vnis;
2206 void *args[2];
2207
2208 num_vnis = hashcount(bgp->vnihash);
2209 if (!num_vnis)
2210 return;
2211
2212 if (json) {
2213 json_object_int_add(json, "numVnis", num_vnis);
2214 } else {
2215 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
2216 vty_out(vty, "Flags: * - Kernel\n");
2217 vty_out(vty, " %-10s %-15s %-21s %-25s %-25s %-37s\n", "VNI",
2218 "Orig IP", "RD", "Import RT",
2219 "Export RT", "Tenant-Vrf");
2220 }
2221
2222 args[0] = vty;
2223 args[1] = json;
2224 hash_iterate(bgp->vnihash,
2225 (void (*)(struct hash_backet *, void *))show_vni_entry,
2226 args);
2227 }
2228
2229 /*
2230 * evpn - enable advertisement of default g/w
2231 */
2232 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2233 {
2234 if (!vpn) {
2235 if (bgp->advertise_gw_macip)
2236 return;
2237
2238 bgp->advertise_gw_macip = 1;
2239 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2240 } else {
2241 if (vpn->advertise_gw_macip)
2242 return;
2243
2244 vpn->advertise_gw_macip = 1;
2245 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2246 vpn->vni);
2247 }
2248 return;
2249 }
2250
2251 /*
2252 * evpn - disable advertisement of default g/w
2253 */
2254 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2255 struct bgpevpn *vpn)
2256 {
2257 if (!vpn) {
2258 if (!bgp->advertise_gw_macip)
2259 return;
2260
2261 bgp->advertise_gw_macip = 0;
2262 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2263 } else {
2264 if (!vpn->advertise_gw_macip)
2265 return;
2266
2267 vpn->advertise_gw_macip = 0;
2268 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2269 vpn->vni);
2270 }
2271 return;
2272 }
2273
2274 /*
2275 * EVPN (VNI advertisement) enabled. Register with zebra.
2276 */
2277 static void evpn_set_advertise_all_vni(struct bgp *bgp)
2278 {
2279 bgp->advertise_all_vni = 1;
2280 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2281 }
2282
2283 /*
2284 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2285 * cache, EVPN routes (delete and withdraw from peers).
2286 */
2287 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
2288 {
2289 bgp->advertise_all_vni = 0;
2290 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2291 bgp_evpn_cleanup_on_disable(bgp);
2292 }
2293 #endif /* HAVE_CUMULUS */
2294
2295 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
2296 {
2297 char buf1[RD_ADDRSTRLEN];
2298 char *ecom_str;
2299 struct listnode *node, *nnode;
2300 struct ecommunity *ecom;
2301
2302 if (is_vni_configured(vpn)) {
2303 vty_out(vty, " vni %d\n", vpn->vni);
2304 if (is_rd_configured(vpn))
2305 vty_out(vty, " rd %s\n",
2306 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
2307
2308 if (is_import_rt_configured(vpn)) {
2309 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2310 ecom)) {
2311 ecom_str = ecommunity_ecom2str(
2312 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2313 vty_out(vty, " route-target import %s\n",
2314 ecom_str);
2315 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2316 }
2317 }
2318
2319 if (is_export_rt_configured(vpn)) {
2320 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2321 ecom)) {
2322 ecom_str = ecommunity_ecom2str(
2323 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2324 vty_out(vty, " route-target export %s\n",
2325 ecom_str);
2326 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2327 }
2328 }
2329
2330 if (vpn->advertise_gw_macip)
2331 vty_out(vty, " advertise-default-gw\n");
2332
2333 vty_out(vty, " exit-vni\n");
2334 }
2335 }
2336
2337 static void write_vni_config_for_entry(struct hash_backet *backet,
2338 struct vty *vty)
2339 {
2340 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
2341 write_vni_config(vty, vpn);
2342 }
2343
2344 #if defined(HAVE_CUMULUS)
2345 DEFUN (bgp_evpn_advertise_default_gw_vni,
2346 bgp_evpn_advertise_default_gw_vni_cmd,
2347 "advertise-default-gw",
2348 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2349 {
2350 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2351 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2352
2353 if (!bgp)
2354 return CMD_WARNING;
2355
2356 if (!vpn)
2357 return CMD_WARNING;
2358
2359 evpn_set_advertise_default_gw(bgp, vpn);
2360
2361 return CMD_SUCCESS;
2362 }
2363
2364 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2365 no_bgp_evpn_advertise_default_gw_vni_cmd,
2366 "no advertise-default-gw",
2367 NO_STR
2368 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2369 {
2370 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2371 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2372
2373 if (!bgp)
2374 return CMD_WARNING;
2375
2376 if (!vpn)
2377 return CMD_WARNING;
2378
2379 evpn_unset_advertise_default_gw(bgp, vpn);
2380
2381 return CMD_SUCCESS;
2382 }
2383
2384
2385 DEFUN (bgp_evpn_advertise_default_gw,
2386 bgp_evpn_advertise_default_gw_cmd,
2387 "advertise-default-gw",
2388 "Advertise All default g/w mac-ip routes in EVPN\n")
2389 {
2390 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2391
2392 if (!bgp)
2393 return CMD_WARNING;
2394
2395 evpn_set_advertise_default_gw(bgp, NULL);
2396
2397 return CMD_SUCCESS;
2398 }
2399
2400 DEFUN (no_bgp_evpn_advertise_default_gw,
2401 no_bgp_evpn_advertise_default_gw_cmd,
2402 "no advertise-default-gw",
2403 NO_STR
2404 "Withdraw All default g/w mac-ip routes from EVPN\n")
2405 {
2406 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2407
2408 if (!bgp)
2409 return CMD_WARNING;
2410
2411 evpn_unset_advertise_default_gw(bgp, NULL);
2412
2413 return CMD_SUCCESS;
2414 }
2415
2416 DEFUN (bgp_evpn_advertise_all_vni,
2417 bgp_evpn_advertise_all_vni_cmd,
2418 "advertise-all-vni",
2419 "Advertise All local VNIs\n")
2420 {
2421 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2422
2423 if (!bgp)
2424 return CMD_WARNING;
2425 evpn_set_advertise_all_vni(bgp);
2426 return CMD_SUCCESS;
2427 }
2428
2429 DEFUN (no_bgp_evpn_advertise_all_vni,
2430 no_bgp_evpn_advertise_all_vni_cmd,
2431 "no advertise-all-vni",
2432 NO_STR
2433 "Advertise All local VNIs\n")
2434 {
2435 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2436
2437 if (!bgp)
2438 return CMD_WARNING;
2439 evpn_unset_advertise_all_vni(bgp);
2440 return CMD_SUCCESS;
2441 }
2442
2443 DEFUN (bgp_evpn_advertise_type5,
2444 bgp_evpn_advertise_type5_cmd,
2445 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
2446 "Advertise prefix routes\n"
2447 BGP_AFI_HELP_STR
2448 BGP_SAFI_HELP_STR)
2449 {
2450 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
2451 int idx_afi = 0;
2452 int idx_safi = 0;
2453 afi_t afi = 0;
2454 safi_t safi = 0;
2455
2456 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2457 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
2458
2459 if (!(afi == AFI_IP) || (afi == AFI_IP6)) {
2460 vty_out(vty,
2461 "%%only ipv4 or ipv6 address families are supported");
2462 return CMD_WARNING;
2463 }
2464
2465 if (safi != SAFI_UNICAST) {
2466 vty_out(vty,
2467 "%%only ipv4 unicast or ipv6 unicast are supported");
2468 return CMD_WARNING;
2469 }
2470
2471 if (afi == AFI_IP) {
2472
2473 /* if we are already advertising ipv4 prefix as type-5
2474 * nothing to do
2475 */
2476 if (!CHECK_FLAG(bgp_vrf->vrf_flags,
2477 BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
2478 SET_FLAG(bgp_vrf->vrf_flags,
2479 BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
2480 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
2481 }
2482 } else {
2483
2484 /* if we are already advertising ipv6 prefix as type-5
2485 * nothing to do
2486 */
2487 if (!CHECK_FLAG(bgp_vrf->vrf_flags,
2488 BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
2489 SET_FLAG(bgp_vrf->vrf_flags,
2490 BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
2491 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
2492 }
2493 }
2494 return CMD_SUCCESS;
2495 }
2496
2497 DEFUN (no_bgp_evpn_advertise_type5,
2498 no_bgp_evpn_advertise_type5_cmd,
2499 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
2500 NO_STR
2501 "Advertise prefix routes\n"
2502 BGP_AFI_HELP_STR
2503 BGP_SAFI_HELP_STR)
2504 {
2505 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
2506 int idx_afi = 0;
2507 int idx_safi = 0;
2508 afi_t afi = 0;
2509 safi_t safi = 0;
2510
2511 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2512 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
2513
2514 if (!(afi == AFI_IP) || (afi == AFI_IP6)) {
2515 vty_out(vty,
2516 "%%only ipv4 or ipv6 address families are supported");
2517 return CMD_WARNING;
2518 }
2519
2520 if (safi != SAFI_UNICAST) {
2521 vty_out(vty,
2522 "%%only ipv4 unicast or ipv6 unicast are supported");
2523 return CMD_WARNING;
2524 }
2525
2526 if (afi == AFI_IP) {
2527
2528 /* if we are already advertising ipv4 prefix as type-5
2529 * nothing to do
2530 */
2531 if (CHECK_FLAG(bgp_vrf->vrf_flags,
2532 BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
2533 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
2534 UNSET_FLAG(bgp_vrf->vrf_flags,
2535 BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
2536 }
2537 } else {
2538
2539 /* if we are already advertising ipv6 prefix as type-5
2540 * nothing to do
2541 */
2542 if (CHECK_FLAG(bgp_vrf->vrf_flags,
2543 BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
2544 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
2545 UNSET_FLAG(bgp_vrf->vrf_flags,
2546 BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
2547 }
2548 }
2549 return CMD_SUCCESS;
2550 }
2551
2552 /*
2553 * Display VNI information - for all or a specific VNI
2554 */
2555 DEFUN(show_bgp_l2vpn_evpn_vni,
2556 show_bgp_l2vpn_evpn_vni_cmd,
2557 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2558 SHOW_STR
2559 BGP_STR
2560 L2VPN_HELP_STR
2561 EVPN_HELP_STR
2562 "Show VNI\n"
2563 "VNI number\n"
2564 JSON_STR)
2565 {
2566 struct bgp *bgp;
2567 vni_t vni;
2568 int idx = 0;
2569 u_char uj = 0;
2570 json_object *json = NULL;
2571
2572 uj = use_json(argc, argv);
2573
2574 bgp = bgp_get_default();
2575 if (!bgp)
2576 return CMD_WARNING;
2577
2578 if (!argv_find(argv, argc, "evpn", &idx))
2579 return CMD_WARNING;
2580
2581 if (uj)
2582 json = json_object_new_object();
2583
2584 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
2585 if (uj) {
2586 json_object_string_add(json, "advertiseGatewayMacip",
2587 bgp->advertise_gw_macip
2588 ? "Enabled"
2589 : "Disabled");
2590 json_object_string_add(json, "advertiseAllVnis",
2591 is_evpn_enabled()
2592 ? "Enabled"
2593 : "Disabled");
2594 } else {
2595 vty_out(vty, "Advertise Gateway Macip: %s\n",
2596 bgp->advertise_gw_macip ? "Enabled"
2597 : "Disabled");
2598
2599 /* Display all VNIs */
2600 vty_out(vty, "Advertise All VNI flag: %s\n",
2601 is_evpn_enabled() ? "Enabled" : "Disabled");
2602 }
2603
2604 evpn_show_all_vnis(vty, bgp, json);
2605 } else {
2606 int vni_idx = 0;
2607
2608 if (!argv_find(argv, argc, "vni", &vni_idx))
2609 return CMD_WARNING;
2610
2611 /* Display specific VNI */
2612 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
2613 evpn_show_vni(vty, bgp, vni, json);
2614 }
2615
2616 if (uj) {
2617 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2618 json, JSON_C_TO_STRING_PRETTY));
2619 json_object_free(json);
2620 }
2621
2622 return CMD_SUCCESS;
2623 }
2624
2625 /*
2626 * Display EVPN neighbor summary.
2627 */
2628 DEFUN(show_bgp_l2vpn_evpn_summary,
2629 show_bgp_l2vpn_evpn_summary_cmd,
2630 "show bgp l2vpn evpn summary [json]",
2631 SHOW_STR
2632 BGP_STR
2633 L2VPN_HELP_STR
2634 EVPN_HELP_STR
2635 "Summary of BGP neighbor status\n"
2636 JSON_STR)
2637 {
2638 u_char uj = use_json(argc, argv);
2639 return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
2640 }
2641
2642 /*
2643 * Display global EVPN routing table.
2644 */
2645 DEFUN(show_bgp_l2vpn_evpn_route,
2646 show_bgp_l2vpn_evpn_route_cmd,
2647 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2648 SHOW_STR
2649 BGP_STR
2650 L2VPN_HELP_STR
2651 EVPN_HELP_STR
2652 "EVPN route information\n"
2653 "Specify Route type\n"
2654 "MAC-IP (Type-2) route\n"
2655 "Multicast (Type-3) route\n"
2656 JSON_STR)
2657 {
2658 struct bgp *bgp;
2659 int type_idx = 0;
2660 int type = 0;
2661 u_char uj = 0;
2662 json_object *json = NULL;
2663
2664 uj = use_json(argc, argv);
2665
2666 bgp = bgp_get_default();
2667 if (!bgp)
2668 return CMD_WARNING;
2669
2670 if (uj)
2671 json = json_object_new_object();
2672
2673 /* get the type */
2674 if (argv_find(argv, argc, "type", &type_idx)) {
2675 /* Specific type is requested */
2676 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
2677 type = BGP_EVPN_MAC_IP_ROUTE;
2678 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
2679 type = BGP_EVPN_IMET_ROUTE;
2680 else
2681 return CMD_WARNING;
2682 }
2683
2684 evpn_show_all_routes(vty, bgp, type, json);
2685
2686 if (uj) {
2687 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2688 json, JSON_C_TO_STRING_PRETTY));
2689 json_object_free(json);
2690 }
2691
2692 return CMD_SUCCESS;
2693 }
2694
2695 /*
2696 * Display global EVPN routing table for specific RD.
2697 */
2698 DEFUN(show_bgp_l2vpn_evpn_route_rd,
2699 show_bgp_l2vpn_evpn_route_rd_cmd,
2700 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]",
2701 SHOW_STR
2702 BGP_STR
2703 L2VPN_HELP_STR
2704 EVPN_HELP_STR
2705 "EVPN route information\n"
2706 "Route Distinguisher\n"
2707 "ASN:XX or A.B.C.D:XX\n"
2708 "Specify Route type\n"
2709 "MAC-IP (Type-2) route\n"
2710 "Multicast (Type-3) route\n"
2711 JSON_STR)
2712 {
2713 struct bgp *bgp;
2714 int ret;
2715 struct prefix_rd prd;
2716 int type = 0;
2717 int rd_idx = 0;
2718 int type_idx = 0;
2719 int uj = 0;
2720 json_object *json = NULL;
2721
2722 bgp = bgp_get_default();
2723 if (!bgp)
2724 return CMD_WARNING;
2725
2726 /* check if we need json output */
2727 uj = use_json(argc, argv);
2728 if (uj)
2729 json = json_object_new_object();
2730
2731 /* get the RD */
2732 if (argv_find(argv, argc, "rd", &rd_idx)) {
2733 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2734
2735 if (!ret) {
2736 vty_out(vty, "%% Malformed Route Distinguisher\n");
2737 return CMD_WARNING;
2738 }
2739 }
2740
2741 /* get the type */
2742 if (argv_find(argv, argc, "type", &type_idx)) {
2743 /* Specific type is requested */
2744 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
2745 type = BGP_EVPN_MAC_IP_ROUTE;
2746 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
2747 type = BGP_EVPN_IMET_ROUTE;
2748 else
2749 return CMD_WARNING;
2750 }
2751
2752 evpn_show_route_rd(vty, bgp, &prd, type, json);
2753
2754 if (uj) {
2755 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2756 json, JSON_C_TO_STRING_PRETTY));
2757 json_object_free(json);
2758 }
2759
2760 return CMD_SUCCESS;
2761 }
2762
2763 /*
2764 * Display global EVPN routing table for specific RD and MACIP.
2765 */
2766 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
2767 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
2768 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
2769 SHOW_STR
2770 BGP_STR
2771 L2VPN_HELP_STR
2772 EVPN_HELP_STR
2773 "EVPN route information\n"
2774 "Route Distinguisher\n"
2775 "ASN:XX or A.B.C.D:XX\n"
2776 "MAC\n"
2777 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2778 "IP\n"
2779 "IP address (IPv4 or IPv6)\n"
2780 JSON_STR)
2781 {
2782 struct bgp *bgp;
2783 int ret;
2784 struct prefix_rd prd;
2785 struct ethaddr mac;
2786 struct ipaddr ip;
2787 int rd_idx = 0;
2788 int mac_idx = 0;
2789 int ip_idx = 0;
2790 int uj = 0;
2791 json_object *json = NULL;
2792
2793 memset(&mac, 0, sizeof(struct ethaddr));
2794 memset(&ip, 0, sizeof(struct ipaddr));
2795
2796 bgp = bgp_get_default();
2797 if (!bgp)
2798 return CMD_WARNING;
2799
2800 /* check if we need json output */
2801 uj = use_json(argc, argv);
2802 if (uj)
2803 json = json_object_new_object();
2804
2805 /* get the prd */
2806 if (argv_find(argv, argc, "rd", &rd_idx)) {
2807 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2808 if (!ret) {
2809 vty_out(vty, "%% Malformed Route Distinguisher\n");
2810 return CMD_WARNING;
2811 }
2812 }
2813
2814 /* get the mac */
2815 if (argv_find(argv, argc, "mac", &mac_idx)) {
2816 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
2817 vty_out(vty, "%% Malformed MAC address\n");
2818 return CMD_WARNING;
2819 }
2820 }
2821
2822 /* get the ip if specified */
2823 if (argv_find(argv, argc, "ip", &ip_idx)) {
2824 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
2825 vty_out(vty, "%% Malformed IP address\n");
2826 return CMD_WARNING;
2827 }
2828 }
2829
2830 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
2831
2832 if (uj) {
2833 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2834 json, JSON_C_TO_STRING_PRETTY));
2835 json_object_free(json);
2836 }
2837
2838 return CMD_SUCCESS;
2839 }
2840
2841 /*
2842 * Display per-VRF EVPN routing table.
2843 */
2844 DEFUN(show_bgp_l2vpn_evpn_route_vrf, show_bgp_l2vpn_evpn_route_vrf_cmd,
2845 "show bgp l2vpn evpn route vrf VRFNAME",
2846 SHOW_STR
2847 BGP_STR
2848 L2VPN_HELP_STR
2849 EVPN_HELP_STR
2850 "EVPN route information\n"
2851 "VRF\n"
2852 "VRF Name\n")
2853 {
2854 int vrf_idx = 6;
2855 char *vrf_name = NULL;
2856 struct bgp *bgp_vrf = NULL;
2857
2858 vrf_name = argv[vrf_idx]->arg;
2859 bgp_vrf = bgp_lookup_by_name(vrf_name);
2860 if (!bgp_vrf)
2861 return CMD_WARNING;
2862
2863 evpn_show_vrf_routes(vty, bgp_vrf);
2864
2865 return CMD_SUCCESS;
2866 }
2867
2868 /*
2869 * Display per-VNI EVPN routing table.
2870 */
2871 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
2872 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2873 SHOW_STR
2874 BGP_STR
2875 L2VPN_HELP_STR
2876 EVPN_HELP_STR
2877 "EVPN route information\n"
2878 "VXLAN Network Identifier\n"
2879 "VNI number\n"
2880 "Specify Route type\n"
2881 "MAC-IP (Type-2) route\n"
2882 "Multicast (Type-3) route\n"
2883 "Remote VTEP\n"
2884 "Remote VTEP IP address\n"
2885 JSON_STR)
2886 {
2887 vni_t vni;
2888 struct bgp *bgp;
2889 struct in_addr vtep_ip;
2890 int type = 0;
2891 int idx = 0;
2892 int uj = 0;
2893 json_object *json = NULL;
2894
2895 bgp = bgp_get_default();
2896 if (!bgp)
2897 return CMD_WARNING;
2898
2899 /* check if we need json output */
2900 uj = use_json(argc, argv);
2901 if (uj)
2902 json = json_object_new_object();
2903
2904 if (!argv_find(argv, argc, "evpn", &idx))
2905 return CMD_WARNING;
2906
2907 vtep_ip.s_addr = 0;
2908
2909 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
2910
2911 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
2912 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
2913 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
2914 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
2915 type = BGP_EVPN_MAC_IP_ROUTE;
2916 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
2917 type = BGP_EVPN_IMET_ROUTE;
2918 else
2919 return CMD_WARNING;
2920 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
2921 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
2922 vty_out(vty, "%% Malformed VTEP IP address\n");
2923 return CMD_WARNING;
2924 }
2925 } else
2926 return CMD_WARNING;
2927 }
2928
2929 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
2930
2931 if (uj) {
2932 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2933 json, JSON_C_TO_STRING_PRETTY));
2934 json_object_free(json);
2935 }
2936
2937 return CMD_SUCCESS;
2938 }
2939
2940 /*
2941 * Display per-VNI EVPN routing table for specific MACIP.
2942 */
2943 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
2944 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
2945 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2946 SHOW_STR
2947 BGP_STR
2948 L2VPN_HELP_STR
2949 EVPN_HELP_STR
2950 "EVPN route information\n"
2951 "VXLAN Network Identifier\n"
2952 "VNI number\n"
2953 "MAC\n"
2954 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2955 "IP\n"
2956 "IP address (IPv4 or IPv6)\n"
2957 JSON_STR)
2958 {
2959 vni_t vni;
2960 struct bgp *bgp;
2961 struct ethaddr mac;
2962 struct ipaddr ip;
2963 int idx = 0;
2964 int uj = 0;
2965 json_object *json = NULL;
2966
2967 bgp = bgp_get_default();
2968 if (!bgp)
2969 return CMD_WARNING;
2970
2971 /* check if we need json output */
2972 uj = use_json(argc, argv);
2973 if (uj)
2974 json = json_object_new_object();
2975
2976 if (!argv_find(argv, argc, "evpn", &idx))
2977 return CMD_WARNING;
2978
2979 /* get the VNI */
2980 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
2981
2982 /* get the mac */
2983 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
2984 vty_out(vty, "%% Malformed MAC address\n");
2985 return CMD_WARNING;
2986 }
2987
2988 /* get the ip */
2989 memset(&ip, 0, sizeof(ip));
2990 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
2991 || (uj
2992 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
2993 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
2994 vty_out(vty, "%% Malformed IP address\n");
2995 return CMD_WARNING;
2996 }
2997 }
2998
2999 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
3000
3001 if (uj) {
3002 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3003 json, JSON_C_TO_STRING_PRETTY));
3004 json_object_free(json);
3005 }
3006
3007 return CMD_SUCCESS;
3008 }
3009
3010 /*
3011 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3012 */
3013 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3014 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3015 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3016 SHOW_STR
3017 BGP_STR
3018 L2VPN_HELP_STR
3019 EVPN_HELP_STR
3020 "EVPN route information\n"
3021 "VXLAN Network Identifier\n"
3022 "VNI number\n"
3023 "Multicast (Type-3) route\n"
3024 "Originating Router IP address\n"
3025 JSON_STR)
3026 {
3027 vni_t vni;
3028 struct bgp *bgp;
3029 int ret;
3030 struct in_addr orig_ip;
3031 int idx = 0;
3032 int uj = 0;
3033 json_object *json = NULL;
3034
3035 bgp = bgp_get_default();
3036 if (!bgp)
3037 return CMD_WARNING;
3038
3039 /* check if we need json output */
3040 uj = use_json(argc, argv);
3041 if (uj)
3042 json = json_object_new_object();
3043
3044 if (!argv_find(argv, argc, "evpn", &idx))
3045 return CMD_WARNING;
3046
3047 /* get the VNI */
3048 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
3049
3050 /* get the ip */
3051 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
3052 if (!ret) {
3053 vty_out(vty, "%% Malformed Originating Router IP address\n");
3054 return CMD_WARNING;
3055 }
3056
3057 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3058
3059 if (uj) {
3060 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3061 json, JSON_C_TO_STRING_PRETTY));
3062 json_object_free(json);
3063 }
3064
3065 return CMD_SUCCESS;
3066 }
3067
3068 /*
3069 * Display per-VNI EVPN routing table - for all VNIs.
3070 */
3071 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3072 show_bgp_l2vpn_evpn_route_vni_all_cmd,
3073 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3074 SHOW_STR
3075 BGP_STR
3076 L2VPN_HELP_STR
3077 EVPN_HELP_STR
3078 "EVPN route information\n"
3079 "VXLAN Network Identifier\n"
3080 "All VNIs\n"
3081 "Remote VTEP\n"
3082 "Remote VTEP IP address\n"
3083 JSON_STR)
3084 {
3085 struct bgp *bgp;
3086 struct in_addr vtep_ip;
3087 int idx = 0;
3088 int uj = 0;
3089 json_object *json = NULL;
3090
3091 bgp = bgp_get_default();
3092 if (!bgp)
3093 return CMD_WARNING;
3094
3095 /* check if we need json output */
3096 uj = use_json(argc, argv);
3097 if (uj)
3098 json = json_object_new_object();
3099
3100 if (!argv_find(argv, argc, "evpn", &idx))
3101 return CMD_WARNING;
3102
3103 vtep_ip.s_addr = 0;
3104 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3105 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
3106 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
3107 vty_out(vty, "%% Malformed VTEP IP address\n");
3108 return CMD_WARNING;
3109 }
3110 }
3111
3112 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3113
3114 if (uj) {
3115 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3116 json, JSON_C_TO_STRING_PRETTY));
3117 json_object_free(json);
3118 }
3119
3120 return CMD_SUCCESS;
3121 }
3122
3123 /*
3124 * Display EVPN import route-target hash table
3125 */
3126 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3127 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3128 "show bgp l2vpn evpn vrf-import-rt [json]",
3129 SHOW_STR
3130 BGP_STR
3131 L2VPN_HELP_STR
3132 EVPN_HELP_STR
3133 "Show vrf import route target\n"
3134 JSON_STR)
3135 {
3136 u_char uj = 0;
3137 struct bgp *bgp_def = NULL;
3138 json_object *json = NULL;
3139
3140 bgp_def = bgp_get_default();
3141 if (!bgp_def)
3142 return CMD_WARNING;
3143
3144 uj = use_json(argc, argv);
3145 if (uj)
3146 json = json_object_new_object();
3147
3148 evpn_show_vrf_import_rts(vty, bgp_def, json);
3149
3150 if (uj) {
3151 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3152 json, JSON_C_TO_STRING_PRETTY));
3153 json_object_free(json);
3154 }
3155
3156 return CMD_SUCCESS;
3157 }
3158
3159 /*
3160 * Display EVPN import route-target hash table
3161 */
3162 DEFUN(show_bgp_l2vpn_evpn_import_rt,
3163 show_bgp_l2vpn_evpn_import_rt_cmd,
3164 "show bgp l2vpn evpn import-rt [json]",
3165 SHOW_STR
3166 BGP_STR
3167 L2VPN_HELP_STR
3168 EVPN_HELP_STR
3169 "Show import route target\n"
3170 JSON_STR)
3171 {
3172 struct bgp *bgp;
3173 u_char uj = 0;
3174 json_object *json = NULL;
3175
3176 bgp = bgp_get_default();
3177 if (!bgp)
3178 return CMD_WARNING;
3179
3180 uj = use_json(argc, argv);
3181 if (uj)
3182 json = json_object_new_object();
3183
3184 evpn_show_import_rts(vty, bgp, json);
3185
3186 if (uj) {
3187 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3188 json, JSON_C_TO_STRING_PRETTY));
3189 json_object_free(json);
3190 }
3191
3192 return CMD_SUCCESS;
3193 }
3194
3195 #if defined(HAVE_CUMULUS)
3196 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3197 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3198 "Show VNI\n"
3199 "VNI number\n")
3200
3201 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3202 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3203 "Summary of BGP neighbor status\n"
3204 JSON_STR)
3205
3206 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3207 "show bgp evpn route [type <macip|multicast>]",
3208 SHOW_STR BGP_STR EVPN_HELP_STR
3209 "EVPN route information\n"
3210 "Specify Route type\n"
3211 "MAC-IP (Type-2) route\n"
3212 "Multicast (Type-3) route\n")
3213
3214 ALIAS_HIDDEN(
3215 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
3216 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3217 SHOW_STR BGP_STR EVPN_HELP_STR
3218 "EVPN route information\n"
3219 "Route Distinguisher\n"
3220 "ASN:XX or A.B.C.D:XX\n"
3221 "Specify Route type\n"
3222 "MAC-IP (Type-2) route\n"
3223 "Multicast (Type-3) route\n")
3224
3225 ALIAS_HIDDEN(
3226 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
3227 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
3228 SHOW_STR BGP_STR EVPN_HELP_STR
3229 "EVPN route information\n"
3230 "Route Distinguisher\n"
3231 "ASN:XX or A.B.C.D:XX\n"
3232 "MAC\n"
3233 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3234 "IP\n"
3235 "IP address (IPv4 or IPv6)\n")
3236
3237 ALIAS_HIDDEN(
3238 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
3239 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3240 SHOW_STR BGP_STR EVPN_HELP_STR
3241 "EVPN route information\n"
3242 "VXLAN Network Identifier\n"
3243 "VNI number\n"
3244 "Specify Route type\n"
3245 "MAC-IP (Type-2) route\n"
3246 "Multicast (Type-3) route\n"
3247 "Remote VTEP\n"
3248 "Remote VTEP IP address\n")
3249
3250 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
3251 show_bgp_evpn_route_vni_macip_cmd,
3252 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3253 SHOW_STR BGP_STR EVPN_HELP_STR
3254 "EVPN route information\n"
3255 "VXLAN Network Identifier\n"
3256 "VNI number\n"
3257 "MAC\n"
3258 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3259 "IP\n"
3260 "IP address (IPv4 or IPv6)\n")
3261
3262 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
3263 show_bgp_evpn_route_vni_multicast_cmd,
3264 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3265 SHOW_STR BGP_STR EVPN_HELP_STR
3266 "EVPN route information\n"
3267 "VXLAN Network Identifier\n"
3268 "VNI number\n"
3269 "Multicast (Type-3) route\n"
3270 "Originating Router IP address\n")
3271
3272 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
3273 "show bgp evpn route vni all [vtep A.B.C.D]",
3274 SHOW_STR BGP_STR EVPN_HELP_STR
3275 "EVPN route information\n"
3276 "VXLAN Network Identifier\n"
3277 "All VNIs\n"
3278 "Remote VTEP\n"
3279 "Remote VTEP IP address\n")
3280
3281 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
3282 "show bgp evpn import-rt",
3283 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
3284 #endif
3285
3286 DEFUN_NOSH (bgp_evpn_vni,
3287 bgp_evpn_vni_cmd,
3288 "vni (1-16777215)",
3289 "VXLAN Network Identifier\n"
3290 "VNI number\n")
3291 {
3292 vni_t vni;
3293 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3294 struct bgpevpn *vpn;
3295
3296 if (!bgp)
3297 return CMD_WARNING;
3298
3299 vni = strtoul(argv[1]->arg, NULL, 10);
3300
3301 /* Create VNI, or mark as configured. */
3302 vpn = evpn_create_update_vni(bgp, vni);
3303 if (!vpn) {
3304 vty_out(vty, "%% Failed to create VNI \n");
3305 return CMD_WARNING;
3306 }
3307
3308 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
3309 return CMD_SUCCESS;
3310 }
3311
3312 DEFUN (no_bgp_evpn_vni,
3313 no_bgp_evpn_vni_cmd,
3314 "no vni (1-16777215)",
3315 NO_STR
3316 "VXLAN Network Identifier\n"
3317 "VNI number\n")
3318 {
3319 vni_t vni;
3320 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3321 struct bgpevpn *vpn;
3322
3323 if (!bgp)
3324 return CMD_WARNING;
3325
3326 vni = strtoul(argv[2]->arg, NULL, 10);
3327
3328 /* Check if we should disallow. */
3329 vpn = bgp_evpn_lookup_vni(bgp, vni);
3330 if (!vpn) {
3331 vty_out(vty, "%% Specified VNI does not exist\n");
3332 return CMD_WARNING;
3333 }
3334 if (!is_vni_configured(vpn)) {
3335 vty_out(vty, "%% Specified VNI is not configured\n");
3336 return CMD_WARNING;
3337 }
3338
3339 evpn_delete_vni(bgp, vpn);
3340 return CMD_SUCCESS;
3341 }
3342
3343 DEFUN_NOSH (exit_vni,
3344 exit_vni_cmd,
3345 "exit-vni",
3346 "Exit from VNI mode\n")
3347 {
3348 if (vty->node == BGP_EVPN_VNI_NODE)
3349 vty->node = BGP_EVPN_NODE;
3350 return CMD_SUCCESS;
3351 }
3352
3353 DEFUN (bgp_evpn_vrf_rd,
3354 bgp_evpn_vrf_rd_cmd,
3355 "rd ASN:NN_OR_IP-ADDRESS:NN",
3356 "Route Distinguisher\n"
3357 "ASN:XX or A.B.C.D:XX\n")
3358 {
3359 int ret;
3360 struct prefix_rd prd;
3361 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3362
3363 if (!bgp_vrf)
3364 return CMD_WARNING;
3365
3366 ret = str2prefix_rd(argv[1]->arg, &prd);
3367 if (!ret) {
3368 vty_out(vty, "%% Malformed Route Distinguisher\n");
3369 return CMD_WARNING;
3370 }
3371
3372 /* If same as existing value, there is nothing more to do. */
3373 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
3374 return CMD_SUCCESS;
3375
3376 /* Configure or update the RD. */
3377 evpn_configure_vrf_rd(bgp_vrf, &prd);
3378 return CMD_SUCCESS;
3379 }
3380
3381 DEFUN (no_bgp_evpn_vrf_rd,
3382 no_bgp_evpn_vrf_rd_cmd,
3383 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3384 NO_STR
3385 "Route Distinguisher\n"
3386 "ASN:XX or A.B.C.D:XX\n")
3387 {
3388 int ret;
3389 struct prefix_rd prd;
3390 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3391
3392 if (!bgp_vrf)
3393 return CMD_WARNING;
3394
3395 ret = str2prefix_rd(argv[2]->arg, &prd);
3396 if (!ret) {
3397 vty_out(vty, "%% Malformed Route Distinguisher\n");
3398 return CMD_WARNING;
3399 }
3400
3401 /* Check if we should disallow. */
3402 if (!is_vrf_rd_configured(bgp_vrf)) {
3403 vty_out(vty, "%% RD is not configured for this VRF\n");
3404 return CMD_WARNING;
3405 }
3406
3407 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
3408 vty_out(vty,
3409 "%% RD specified does not match configuration for this VRF\n");
3410 return CMD_WARNING;
3411 }
3412
3413 evpn_unconfigure_vrf_rd(bgp_vrf);
3414 return CMD_SUCCESS;
3415 }
3416
3417 DEFUN (no_bgp_evpn_vrf_rd_without_val,
3418 no_bgp_evpn_vrf_rd_without_val_cmd,
3419 "no rd",
3420 NO_STR
3421 "Route Distinguisher\n")
3422 {
3423 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3424
3425 if (!bgp_vrf)
3426 return CMD_WARNING;
3427
3428 /* Check if we should disallow. */
3429 if (!is_vrf_rd_configured(bgp_vrf)) {
3430 vty_out(vty, "%% RD is not configured for this VRF\n");
3431 return CMD_WARNING;
3432 }
3433
3434 evpn_unconfigure_vrf_rd(bgp_vrf);
3435 return CMD_SUCCESS;
3436 }
3437
3438 DEFUN (bgp_evpn_vni_rd,
3439 bgp_evpn_vni_rd_cmd,
3440 "rd ASN:NN_OR_IP-ADDRESS:NN",
3441 "Route Distinguisher\n"
3442 "ASN:XX or A.B.C.D:XX\n")
3443 {
3444 struct prefix_rd prd;
3445 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3446 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3447 int ret;
3448
3449 if (!bgp || !vpn)
3450 return CMD_WARNING;
3451
3452 ret = str2prefix_rd(argv[1]->arg, &prd);
3453 if (!ret) {
3454 vty_out(vty, "%% Malformed Route Distinguisher\n");
3455 return CMD_WARNING;
3456 }
3457
3458 /* If same as existing value, there is nothing more to do. */
3459 if (bgp_evpn_rd_matches_existing(vpn, &prd))
3460 return CMD_SUCCESS;
3461
3462 /* Configure or update the RD. */
3463 evpn_configure_rd(bgp, vpn, &prd);
3464 return CMD_SUCCESS;
3465 }
3466
3467 DEFUN (no_bgp_evpn_vni_rd,
3468 no_bgp_evpn_vni_rd_cmd,
3469 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3470 NO_STR
3471 "Route Distinguisher\n"
3472 "ASN:XX or A.B.C.D:XX\n")
3473 {
3474 struct prefix_rd prd;
3475 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3476 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3477 int ret;
3478
3479 if (!bgp || !vpn)
3480 return CMD_WARNING;
3481
3482 ret = str2prefix_rd(argv[2]->arg, &prd);
3483 if (!ret) {
3484 vty_out(vty, "%% Malformed Route Distinguisher\n");
3485 return CMD_WARNING;
3486 }
3487
3488 /* Check if we should disallow. */
3489 if (!is_rd_configured(vpn)) {
3490 vty_out(vty, "%% RD is not configured for this VNI\n");
3491 return CMD_WARNING;
3492 }
3493
3494 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
3495 vty_out(vty,
3496 "%% RD specified does not match configuration for this VNI\n");
3497 return CMD_WARNING;
3498 }
3499
3500 evpn_unconfigure_rd(bgp, vpn);
3501 return CMD_SUCCESS;
3502 }
3503
3504 DEFUN (no_bgp_evpn_vni_rd_without_val,
3505 no_bgp_evpn_vni_rd_without_val_cmd,
3506 "no rd",
3507 NO_STR
3508 "Route Distinguisher\n")
3509 {
3510 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3511 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3512
3513 if (!bgp || !vpn)
3514 return CMD_WARNING;
3515
3516 /* Check if we should disallow. */
3517 if (!is_rd_configured(vpn)) {
3518 vty_out(vty, "%% RD is not configured for this VNI\n");
3519 return CMD_WARNING;
3520 }
3521
3522 evpn_unconfigure_rd(bgp, vpn);
3523 return CMD_SUCCESS;
3524 }
3525
3526 /*
3527 * Loop over all extended-communities in the route-target list rtl and
3528 * return 1 if we find ecomtarget
3529 */
3530 static int bgp_evpn_rt_matches_existing(struct list *rtl,
3531 struct ecommunity *ecomtarget)
3532 {
3533 struct listnode *node, *nnode;
3534 struct ecommunity *ecom;
3535
3536 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
3537 if (ecommunity_match(ecom, ecomtarget))
3538 return 1;
3539 }
3540
3541 return 0;
3542 }
3543
3544 /* display L3VNI related info for a VRF instance */
3545 DEFUN (show_bgp_vrf_l3vni_info,
3546 show_bgp_vrf_l3vni_info_cmd,
3547 "show bgp vrf VRFNAME l3vni info [json]",
3548 SHOW_STR
3549 BGP_STR
3550 "show bgp vrf\n"
3551 "VRF Name\n"
3552 "L3-VNI\n"
3553 "L3-VNI info\n"
3554 JSON_STR)
3555 {
3556 char buf[ETHER_ADDR_STRLEN];
3557 char buf1[INET6_ADDRSTRLEN];
3558 int idx_vrf = 3;
3559 const char *name = NULL;
3560 struct bgp *bgp = NULL;
3561 struct listnode *node = NULL;
3562 struct bgpevpn *vpn = NULL;
3563 struct ecommunity *ecom = NULL;
3564 json_object *json = NULL;
3565 json_object *json_vnis = NULL;
3566 json_object *json_export_rts = NULL;
3567 json_object *json_import_rts = NULL;
3568 u_char uj = use_json(argc, argv);
3569
3570 if (uj) {
3571 json = json_object_new_object();
3572 json_vnis = json_object_new_array();
3573 json_export_rts = json_object_new_array();
3574 json_import_rts = json_object_new_array();
3575 }
3576
3577 name = argv[idx_vrf]->arg;
3578 bgp = bgp_lookup_by_name(name);
3579 if (!bgp) {
3580 if (!uj)
3581 vty_out(vty, "BGP instance for VRF %s not found",
3582 name);
3583 else {
3584 json_object_string_add(json, "warning",
3585 "BGP instance not found");
3586 vty_out(vty, "%s\n",
3587 json_object_to_json_string(json));
3588 json_object_free(json);
3589 }
3590 return CMD_WARNING;
3591 }
3592
3593 if (!json) {
3594 vty_out(vty, "BGP VRF: %s\n", name);
3595 vty_out(vty, " Local-Ip: %s\n",
3596 inet_ntoa(bgp->originator_ip));
3597 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
3598 vty_out(vty, " Rmac: %s\n",
3599 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
3600 vty_out(vty, " L2-VNI List:\n");
3601 vty_out(vty, " ");
3602 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3603 vty_out(vty, "%u ", vpn->vni);
3604 vty_out(vty, "\n");
3605 vty_out(vty, " Export-RTs:\n");
3606 vty_out(vty, " ");
3607 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3608 vty_out(vty, "%s ", ecommunity_str(ecom));
3609 vty_out(vty, "\n");
3610 vty_out(vty, " Import-RTs:\n");
3611 vty_out(vty, " ");
3612 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3613 vty_out(vty, "%s ", ecommunity_str(ecom));
3614 vty_out(vty, "\n");
3615 vty_out(vty, " RD: %s\n",
3616 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
3617 } else {
3618 json_object_string_add(json, "vrf", name);
3619 json_object_string_add(json, "local-ip",
3620 inet_ntoa(bgp->originator_ip));
3621 json_object_int_add(json, "l3vni", bgp->l3vni);
3622 json_object_string_add(json, "rmac",
3623 prefix_mac2str(&bgp->rmac, buf,
3624 sizeof(buf)));
3625 /* list of l2vnis */
3626 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3627 json_object_array_add(json_vnis,
3628 json_object_new_int(vpn->vni));
3629 json_object_object_add(json, "l2vnis", json_vnis);
3630
3631 /* export rts */
3632 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3633 json_object_array_add(json_export_rts,
3634 json_object_new_string(
3635 ecommunity_str(ecom)));
3636 json_object_object_add(json, "export-rts", json_export_rts);
3637
3638 /* import rts */
3639 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3640 json_object_array_add(json_import_rts,
3641 json_object_new_string(
3642 ecommunity_str(ecom)));
3643 json_object_object_add(json, "import-rts", json_import_rts);
3644 json_object_string_add(
3645 json, "rd",
3646 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
3647
3648 }
3649
3650 if (uj) {
3651 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3652 json, JSON_C_TO_STRING_PRETTY));
3653 json_object_free(json);
3654 }
3655 return CMD_SUCCESS;
3656 }
3657
3658 /* import/export rt for l3vni-vrf */
3659 DEFUN (bgp_evpn_vrf_rt,
3660 bgp_evpn_vrf_rt_cmd,
3661 "route-target <both|import|export> RT",
3662 "Route Target\n"
3663 "import and export\n"
3664 "import\n"
3665 "export\n"
3666 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3667 {
3668 int rt_type;
3669 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3670 struct ecommunity *ecomadd = NULL;
3671
3672 if (!bgp)
3673 return CMD_WARNING;
3674
3675 if (!strcmp(argv[1]->arg, "import"))
3676 rt_type = RT_TYPE_IMPORT;
3677 else if (!strcmp(argv[1]->arg, "export"))
3678 rt_type = RT_TYPE_EXPORT;
3679 else if (!strcmp(argv[1]->arg, "both"))
3680 rt_type = RT_TYPE_BOTH;
3681 else {
3682 vty_out(vty, "%% Invalid Route Target type\n");
3683 return CMD_WARNING;
3684 }
3685
3686 /* Add/update the import route-target */
3687 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3688 ecomadd = ecommunity_str2com(argv[2]->arg,
3689 ECOMMUNITY_ROUTE_TARGET, 0);
3690 if (!ecomadd) {
3691 vty_out(vty, "%% Malformed Route Target list\n");
3692 return CMD_WARNING;
3693 }
3694 ecommunity_str(ecomadd);
3695
3696 /* Do nothing if we already have this import route-target */
3697 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3698 ecomadd))
3699 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
3700 }
3701
3702 /* Add/update the export route-target */
3703 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3704 ecomadd = ecommunity_str2com(argv[2]->arg,
3705 ECOMMUNITY_ROUTE_TARGET, 0);
3706 if (!ecomadd) {
3707 vty_out(vty, "%% Malformed Route Target list\n");
3708 return CMD_WARNING;
3709 }
3710 ecommunity_str(ecomadd);
3711
3712 /* Do nothing if we already have this export route-target */
3713 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3714 ecomadd))
3715 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
3716 }
3717
3718 return CMD_SUCCESS;
3719 }
3720
3721 DEFUN (no_bgp_evpn_vrf_rt,
3722 no_bgp_evpn_vrf_rt_cmd,
3723 "no route-target <both|import|export> RT",
3724 NO_STR
3725 "Route Target\n"
3726 "import and export\n"
3727 "import\n"
3728 "export\n"
3729 "ASN:XX or A.B.C.D:XX\n")
3730 {
3731 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3732 int rt_type, found_ecomdel;
3733 struct ecommunity *ecomdel = NULL;
3734
3735 if (!bgp)
3736 return CMD_WARNING;
3737
3738 if (!strcmp(argv[2]->arg, "import"))
3739 rt_type = RT_TYPE_IMPORT;
3740 else if (!strcmp(argv[2]->arg, "export"))
3741 rt_type = RT_TYPE_EXPORT;
3742 else if (!strcmp(argv[2]->arg, "both"))
3743 rt_type = RT_TYPE_BOTH;
3744 else {
3745 vty_out(vty, "%% Invalid Route Target type\n");
3746 return CMD_WARNING;
3747 }
3748
3749 if (rt_type == RT_TYPE_IMPORT) {
3750 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
3751 vty_out(vty,
3752 "%% Import RT is not configured for this VRF\n");
3753 return CMD_WARNING;
3754 }
3755 } else if (rt_type == RT_TYPE_EXPORT) {
3756 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
3757 vty_out(vty,
3758 "%% Export RT is not configured for this VRF\n");
3759 return CMD_WARNING;
3760 }
3761 } else if (rt_type == RT_TYPE_BOTH) {
3762 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
3763 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
3764 vty_out(vty,
3765 "%% Import/Export RT is not configured for this VRF\n");
3766 return CMD_WARNING;
3767 }
3768 }
3769
3770 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
3771 if (!ecomdel) {
3772 vty_out(vty, "%% Malformed Route Target list\n");
3773 return CMD_WARNING;
3774 }
3775 ecommunity_str(ecomdel);
3776
3777 if (rt_type == RT_TYPE_IMPORT) {
3778 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3779 ecomdel)) {
3780 vty_out(vty,
3781 "%% RT specified does not match configuration for this VRF\n");
3782 return CMD_WARNING;
3783 }
3784 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
3785 } else if (rt_type == RT_TYPE_EXPORT) {
3786 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3787 ecomdel)) {
3788 vty_out(vty,
3789 "%% RT specified does not match configuration for this VRF\n");
3790 return CMD_WARNING;
3791 }
3792 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
3793 } else if (rt_type == RT_TYPE_BOTH) {
3794 found_ecomdel = 0;
3795
3796 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3797 ecomdel)) {
3798 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
3799 found_ecomdel = 1;
3800 }
3801
3802 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3803 ecomdel)) {
3804 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
3805 found_ecomdel = 1;
3806 }
3807
3808 if (!found_ecomdel) {
3809 vty_out(vty,
3810 "%% RT specified does not match configuration for this VRF\n");
3811 return CMD_WARNING;
3812 }
3813 }
3814
3815 return CMD_SUCCESS;
3816 }
3817
3818 DEFUN (bgp_evpn_vni_rt,
3819 bgp_evpn_vni_rt_cmd,
3820 "route-target <both|import|export> RT",
3821 "Route Target\n"
3822 "import and export\n"
3823 "import\n"
3824 "export\n"
3825 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3826 {
3827 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3828 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3829 int rt_type;
3830 struct ecommunity *ecomadd = NULL;
3831
3832 if (!bgp || !vpn)
3833 return CMD_WARNING;
3834
3835 if (!strcmp(argv[1]->text, "import"))
3836 rt_type = RT_TYPE_IMPORT;
3837 else if (!strcmp(argv[1]->text, "export"))
3838 rt_type = RT_TYPE_EXPORT;
3839 else if (!strcmp(argv[1]->text, "both"))
3840 rt_type = RT_TYPE_BOTH;
3841 else {
3842 vty_out(vty, "%% Invalid Route Target type\n");
3843 return CMD_WARNING;
3844 }
3845
3846 /* Add/update the import route-target */
3847 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3848 ecomadd = ecommunity_str2com(argv[2]->arg,
3849 ECOMMUNITY_ROUTE_TARGET, 0);
3850 if (!ecomadd) {
3851 vty_out(vty, "%% Malformed Route Target list\n");
3852 return CMD_WARNING;
3853 }
3854 ecommunity_str(ecomadd);
3855
3856 /* Do nothing if we already have this import route-target */
3857 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
3858 evpn_configure_import_rt(bgp, vpn, ecomadd);
3859 }
3860
3861 /* Add/update the export route-target */
3862 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3863 ecomadd = ecommunity_str2com(argv[2]->arg,
3864 ECOMMUNITY_ROUTE_TARGET, 0);
3865 if (!ecomadd) {
3866 vty_out(vty, "%% Malformed Route Target list\n");
3867 return CMD_WARNING;
3868 }
3869 ecommunity_str(ecomadd);
3870
3871 /* Do nothing if we already have this export route-target */
3872 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
3873 evpn_configure_export_rt(bgp, vpn, ecomadd);
3874 }
3875
3876 return CMD_SUCCESS;
3877 }
3878
3879 DEFUN (no_bgp_evpn_vni_rt,
3880 no_bgp_evpn_vni_rt_cmd,
3881 "no route-target <both|import|export> RT",
3882 NO_STR
3883 "Route Target\n"
3884 "import and export\n"
3885 "import\n"
3886 "export\n"
3887 "ASN:XX or A.B.C.D:XX\n")
3888 {
3889 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3890 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3891 int rt_type, found_ecomdel;
3892 struct ecommunity *ecomdel = NULL;
3893
3894 if (!bgp || !vpn)
3895 return CMD_WARNING;
3896
3897 if (!strcmp(argv[2]->text, "import"))
3898 rt_type = RT_TYPE_IMPORT;
3899 else if (!strcmp(argv[2]->text, "export"))
3900 rt_type = RT_TYPE_EXPORT;
3901 else if (!strcmp(argv[2]->text, "both"))
3902 rt_type = RT_TYPE_BOTH;
3903 else {
3904 vty_out(vty, "%% Invalid Route Target type\n");
3905 return CMD_WARNING;
3906 }
3907
3908 /* The user did "no route-target import", check to see if there are any
3909 * import route-targets configured. */
3910 if (rt_type == RT_TYPE_IMPORT) {
3911 if (!is_import_rt_configured(vpn)) {
3912 vty_out(vty,
3913 "%% Import RT is not configured for this VNI\n");
3914 return CMD_WARNING;
3915 }
3916 } else if (rt_type == RT_TYPE_EXPORT) {
3917 if (!is_export_rt_configured(vpn)) {
3918 vty_out(vty,
3919 "%% Export RT is not configured for this VNI\n");
3920 return CMD_WARNING;
3921 }
3922 } else if (rt_type == RT_TYPE_BOTH) {
3923 if (!is_import_rt_configured(vpn)
3924 && !is_export_rt_configured(vpn)) {
3925 vty_out(vty,
3926 "%% Import/Export RT is not configured for this VNI\n");
3927 return CMD_WARNING;
3928 }
3929 }
3930
3931 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
3932 if (!ecomdel) {
3933 vty_out(vty, "%% Malformed Route Target list\n");
3934 return CMD_WARNING;
3935 }
3936 ecommunity_str(ecomdel);
3937
3938 if (rt_type == RT_TYPE_IMPORT) {
3939 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3940 vty_out(vty,
3941 "%% RT specified does not match configuration for this VNI\n");
3942 return CMD_WARNING;
3943 }
3944 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3945 } else if (rt_type == RT_TYPE_EXPORT) {
3946 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3947 vty_out(vty,
3948 "%% RT specified does not match configuration for this VNI\n");
3949 return CMD_WARNING;
3950 }
3951 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3952 } else if (rt_type == RT_TYPE_BOTH) {
3953 found_ecomdel = 0;
3954
3955 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3956 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3957 found_ecomdel = 1;
3958 }
3959
3960 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3961 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3962 found_ecomdel = 1;
3963 }
3964
3965 if (!found_ecomdel) {
3966 vty_out(vty,
3967 "%% RT specified does not match configuration for this VNI\n");
3968 return CMD_WARNING;
3969 }
3970 }
3971
3972 return CMD_SUCCESS;
3973 }
3974
3975 DEFUN (no_bgp_evpn_vni_rt_without_val,
3976 no_bgp_evpn_vni_rt_without_val_cmd,
3977 "no route-target <import|export>",
3978 NO_STR
3979 "Route Target\n"
3980 "import\n"
3981 "export\n")
3982 {
3983 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3984 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3985 int rt_type;
3986
3987 if (!bgp || !vpn)
3988 return CMD_WARNING;
3989
3990 if (!strcmp(argv[2]->text, "import")) {
3991 rt_type = RT_TYPE_IMPORT;
3992 } else if (!strcmp(argv[2]->text, "export")) {
3993 rt_type = RT_TYPE_EXPORT;
3994 } else {
3995 vty_out(vty, "%% Invalid Route Target type\n");
3996 return CMD_WARNING;
3997 }
3998
3999 /* Check if we should disallow. */
4000 if (rt_type == RT_TYPE_IMPORT) {
4001 if (!is_import_rt_configured(vpn)) {
4002 vty_out(vty,
4003 "%% Import RT is not configured for this VNI\n");
4004 return CMD_WARNING;
4005 }
4006 } else {
4007 if (!is_export_rt_configured(vpn)) {
4008 vty_out(vty,
4009 "%% Export RT is not configured for this VNI\n");
4010 return CMD_WARNING;
4011 }
4012 }
4013
4014 /* Unconfigure the RT. */
4015 if (rt_type == RT_TYPE_IMPORT)
4016 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4017 else
4018 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4019 return CMD_SUCCESS;
4020 }
4021 #endif
4022 /*
4023 * Output EVPN configuration information.
4024 */
4025 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
4026 safi_t safi)
4027 {
4028 if (bgp->vnihash)
4029 hash_iterate(bgp->vnihash,
4030 (void (*)(struct hash_backet *,
4031 void *))write_vni_config_for_entry,
4032 vty);
4033
4034 if (bgp->advertise_all_vni)
4035 vty_out(vty, " advertise-all-vni\n");
4036
4037 if (bgp->advertise_gw_macip)
4038 vty_out(vty, " advertise-default-gw\n");
4039
4040 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV4_IN_EVPN))
4041 vty_out(vty, " advertise ipv4 unicast\n");
4042
4043 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_ADVERTISE_IPV6_IN_EVPN))
4044 vty_out(vty, " advertise ipv6 unicast\n");
4045 }
4046
4047 void bgp_ethernetvpn_init(void)
4048 {
4049 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4050 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4051 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4052 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4053 install_element(VIEW_NODE,
4054 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4055 install_element(VIEW_NODE,
4056 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4057 install_element(
4058 VIEW_NODE,
4059 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4060 install_element(
4061 VIEW_NODE,
4062 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4063 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4064 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4065 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4066 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
4067 #if defined(HAVE_CUMULUS)
4068 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4069 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
4070 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4071 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
4072 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4073 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
4074
4075 /* "show bgp l2vpn evpn" commands. */
4076 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4077 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4078 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4079 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4080 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
4081 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
4082 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vrf_cmd);
4083 install_element(VIEW_NODE,
4084 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4085 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4086 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4087 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
4088 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
4089
4090 /* "show bgp evpn" commands. */
4091 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4092 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4093 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4094 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4095 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4096 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4097 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4098 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4099 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4100 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
4101 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
4102
4103 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4104 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
4105 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4106 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
4107 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
4108 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
4109 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
4110 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
4111 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
4112 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
4113 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
4114 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
4115 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
4116 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
4117 install_element(BGP_EVPN_VNI_NODE,
4118 &bgp_evpn_advertise_default_gw_vni_cmd);
4119 install_element(BGP_EVPN_VNI_NODE,
4120 &no_bgp_evpn_advertise_default_gw_vni_cmd);
4121 #endif
4122 }