]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
bgpd: follow AFI/SAFI style for advertising/withdrawing type-5 routes
[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 first*/
1500 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1501
1502 /* update RD */
1503 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
1504 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
1505
1506 /* We have a new RD for VRF.
1507 * Advertise all type-5 routes again with the new RD */
1508 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1509 }
1510
1511 /*
1512 * Unconfigure RD for VRF
1513 */
1514 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
1515 {
1516 /* If we have already advertise type-5 routes with a diffrent RD, we
1517 * have to delete and withdraw them first*/
1518 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
1519
1520 /* fall back to default RD */
1521 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
1522
1523 /* We have a new RD for VRF.
1524 * Advertise all type-5 routes again with the new RD */
1525 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
1526 }
1527
1528 /*
1529 * Configure RD for a VNI (vty handler)
1530 */
1531 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
1532 struct prefix_rd *rd)
1533 {
1534 /* If the VNI is "live", we need to delete and withdraw this VNI's
1535 * local routes with the prior RD first. Then, after updating RD,
1536 * need to re-advertise.
1537 */
1538 if (is_vni_live(vpn))
1539 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1540
1541 /* update RD */
1542 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
1543 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
1544
1545 if (is_vni_live(vpn))
1546 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1547 }
1548
1549 /*
1550 * Unconfigure RD for a VNI (vty handler)
1551 */
1552 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
1553 {
1554 /* If the VNI is "live", we need to delete and withdraw this VNI's
1555 * local routes with the prior RD first. Then, after resetting RD
1556 * to automatic value, need to re-advertise.
1557 */
1558 if (is_vni_live(vpn))
1559 bgp_evpn_handle_rd_change(bgp, vpn, 1);
1560
1561 /* reset RD to default */
1562 bgp_evpn_derive_auto_rd(bgp, vpn);
1563
1564 if (is_vni_live(vpn))
1565 bgp_evpn_handle_rd_change(bgp, vpn, 0);
1566 }
1567
1568 /*
1569 * Create VNI, if not already present (VTY handler). Mark as configured.
1570 */
1571 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
1572 {
1573 struct bgpevpn *vpn;
1574
1575 if (!bgp->vnihash)
1576 return NULL;
1577
1578 vpn = bgp_evpn_lookup_vni(bgp, vni);
1579 if (!vpn) {
1580 /* tenant vrf will be updated when we get local_vni_add from
1581 * zebra */
1582 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0);
1583 if (!vpn) {
1584 zlog_err(
1585 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1586 bgp->vrf_id, vni);
1587 return NULL;
1588 }
1589 }
1590
1591 /* Mark as configured. */
1592 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1593 return vpn;
1594 }
1595
1596 /*
1597 * Delete VNI. If VNI does not exist in the system (i.e., just
1598 * configuration), all that is needed is to free it. Otherwise,
1599 * any parameters configured for the VNI need to be reset (with
1600 * appropriate action) and the VNI marked as unconfigured; the
1601 * VNI will continue to exist, purely as a "learnt" entity.
1602 */
1603 static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
1604 {
1605 assert(bgp->vnihash);
1606
1607 if (!is_vni_live(vpn)) {
1608 bgp_evpn_free(bgp, vpn);
1609 return 0;
1610 }
1611
1612 /* We need to take the unconfigure action for each parameter of this VNI
1613 * that is configured. Some optimization is possible, but not worth the
1614 * additional code for an operation that should be pretty rare.
1615 */
1616 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
1617
1618 /* First, deal with the export side - RD and export RT changes. */
1619 if (is_rd_configured(vpn))
1620 evpn_unconfigure_rd(bgp, vpn);
1621 if (is_export_rt_configured(vpn))
1622 evpn_unconfigure_export_rt(bgp, vpn, NULL);
1623
1624 /* Next, deal with the import side. */
1625 if (is_import_rt_configured(vpn))
1626 evpn_unconfigure_import_rt(bgp, vpn, NULL);
1627
1628 return 0;
1629 }
1630
1631 /*
1632 * Display import RT mapping to VRFs (vty handler)
1633 * bgp_def: default bgp instance
1634 */
1635 static void evpn_show_vrf_import_rts(struct vty *vty,
1636 struct bgp *bgp_def,
1637 json_object *json)
1638 {
1639 void *args[2];
1640
1641 args[0] = vty;
1642 args[1] = json;
1643
1644 hash_iterate(bgp_def->vrf_import_rt_hash,
1645 (void (*)(struct hash_backet *, void *))
1646 show_vrf_import_rt_entry,
1647 args);
1648 }
1649
1650 /*
1651 * Display import RT mapping to VNIs (vty handler)
1652 */
1653 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
1654 json_object *json)
1655 {
1656 void *args[2];
1657
1658 args[0] = vty;
1659 args[1] = json;
1660
1661 hash_iterate(
1662 bgp->import_rt_hash,
1663 (void (*)(struct hash_backet *, void *))show_import_rt_entry,
1664 args);
1665 }
1666
1667 /*
1668 * Display EVPN routes for all VNIs - vty handler.
1669 */
1670 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
1671 struct in_addr vtep_ip, json_object *json)
1672 {
1673 u_int32_t num_vnis;
1674 struct vni_walk_ctx wctx;
1675
1676 num_vnis = hashcount(bgp->vnihash);
1677 if (!num_vnis)
1678 return;
1679 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
1680 wctx.bgp = bgp;
1681 wctx.vty = vty;
1682 wctx.vtep_ip = vtep_ip;
1683 wctx.json = json;
1684 hash_iterate(bgp->vnihash, (void (*)(struct hash_backet *,
1685 void *))show_vni_routes_hash,
1686 &wctx);
1687 }
1688
1689 /*
1690 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1691 */
1692 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
1693 vni_t vni, struct in_addr orig_ip,
1694 json_object *json)
1695 {
1696 struct bgpevpn *vpn;
1697 struct prefix_evpn p;
1698 struct bgp_node *rn;
1699 struct bgp_info *ri;
1700 u_int32_t path_cnt = 0;
1701 afi_t afi;
1702 safi_t safi;
1703 json_object *json_paths = NULL;
1704
1705 afi = AFI_L2VPN;
1706 safi = SAFI_EVPN;
1707
1708 /* Locate VNI. */
1709 vpn = bgp_evpn_lookup_vni(bgp, vni);
1710 if (!vpn) {
1711 vty_out(vty, "VNI not found\n");
1712 return;
1713 }
1714
1715 /* See if route exists. */
1716 build_evpn_type3_prefix(&p, orig_ip);
1717 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1718 if (!rn || !rn->info) {
1719 if (!json)
1720 vty_out(vty, "%% Network not in table\n");
1721 return;
1722 }
1723
1724 if (json)
1725 json_paths = json_object_new_array();
1726
1727 /* Prefix and num paths displayed once per prefix. */
1728 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
1729
1730 /* Display each path for this prefix. */
1731 for (ri = rn->info; ri; ri = ri->next) {
1732 json_object *json_path = NULL;
1733
1734 if (json)
1735 json_path = json_object_new_array();
1736
1737 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1738 json_path);
1739
1740 if (json)
1741 json_object_array_add(json_paths, json_path);
1742
1743 path_cnt++;
1744 }
1745
1746 if (json) {
1747 if (path_cnt)
1748 json_object_object_add(json, "paths", json_paths);
1749
1750 json_object_int_add(json, "numPaths", path_cnt);
1751 } else {
1752 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1753 path_cnt);
1754 }
1755 }
1756
1757 /*
1758 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1759 * By definition, only matching type-2 route will be displayed.
1760 */
1761 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
1762 vni_t vni, struct ethaddr *mac,
1763 struct ipaddr *ip, json_object *json)
1764 {
1765 struct bgpevpn *vpn;
1766 struct prefix_evpn p;
1767 struct bgp_node *rn;
1768 struct bgp_info *ri;
1769 u_int32_t path_cnt = 0;
1770 afi_t afi;
1771 safi_t safi;
1772 json_object *json_paths = NULL;
1773
1774 afi = AFI_L2VPN;
1775 safi = SAFI_EVPN;
1776
1777 /* Locate VNI. */
1778 vpn = bgp_evpn_lookup_vni(bgp, vni);
1779 if (!vpn) {
1780 if (!json)
1781 vty_out(vty, "VNI not found\n");
1782 return;
1783 }
1784
1785 /* See if route exists. Look for both non-sticky and sticky. */
1786 build_evpn_type2_prefix(&p, mac, ip);
1787 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
1788 if (!rn || !rn->info) {
1789 if (!json)
1790 vty_out(vty, "%% Network not in table\n");
1791 return;
1792 }
1793
1794 if (json)
1795 json_paths = json_object_new_array();
1796
1797 /* Prefix and num paths displayed once per prefix. */
1798 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
1799
1800 /* Display each path for this prefix. */
1801 for (ri = rn->info; ri; ri = ri->next) {
1802 json_object *json_path = NULL;
1803
1804 if (json)
1805 json_path = json_object_new_array();
1806
1807 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1808 json_path);
1809
1810 if (json)
1811 json_object_array_add(json_paths, json_path);
1812
1813 path_cnt++;
1814 }
1815
1816 if (json) {
1817 if (path_cnt)
1818 json_object_object_add(json, "paths", json_paths);
1819
1820 json_object_int_add(json, "numPaths", path_cnt);
1821 } else {
1822 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1823 path_cnt);
1824 }
1825 }
1826
1827 /*
1828 * Display EVPN routes for a VNI - vty handler.
1829 * If 'type' is non-zero, only routes matching that type are shown.
1830 * If the vtep_ip is non zero, only routes behind that vtep are shown
1831 */
1832 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
1833 int type, struct in_addr vtep_ip,
1834 json_object *json)
1835 {
1836 struct bgpevpn *vpn;
1837
1838 /* Locate VNI. */
1839 vpn = bgp_evpn_lookup_vni(bgp, vni);
1840 if (!vpn) {
1841 if (!json)
1842 vty_out(vty, "VNI not found\n");
1843 return;
1844 }
1845
1846 /* Walk this VNI's route table and display appropriate routes. */
1847 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json);
1848 }
1849
1850 /*
1851 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1852 * IP (vty handler). By definition, only matching type-2 route will be
1853 * displayed.
1854 */
1855 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
1856 struct prefix_rd *prd, struct ethaddr *mac,
1857 struct ipaddr *ip, json_object *json)
1858 {
1859 struct prefix_evpn p;
1860 struct bgp_node *rn;
1861 struct bgp_info *ri;
1862 afi_t afi;
1863 safi_t safi;
1864 u_int32_t path_cnt = 0;
1865 json_object *json_paths = NULL;
1866 char prefix_str[BUFSIZ];
1867
1868 afi = AFI_L2VPN;
1869 safi = SAFI_EVPN;
1870
1871 /* See if route exists. Look for both non-sticky and sticky. */
1872 build_evpn_type2_prefix(&p, mac, ip);
1873 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
1874 (struct prefix *)&p, prd);
1875 if (!rn || !rn->info) {
1876 if (!json)
1877 vty_out(vty, "%% Network not in table\n");
1878 return;
1879 }
1880
1881 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
1882 sizeof(prefix_str));
1883
1884 /* Prefix and num paths displayed once per prefix. */
1885 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
1886
1887 if (json)
1888 json_paths = json_object_new_array();
1889
1890 /* Display each path for this prefix. */
1891 for (ri = rn->info; ri; ri = ri->next) {
1892 json_object *json_path = NULL;
1893
1894 if (json)
1895 json_path = json_object_new_array();
1896
1897 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
1898 json_path);
1899
1900 if (json)
1901 json_object_array_add(json_paths, json_path);
1902
1903 path_cnt++;
1904 }
1905
1906 if (json && path_cnt) {
1907 if (path_cnt)
1908 json_object_object_add(json, prefix_str, json_paths);
1909 json_object_int_add(json, "numPaths", path_cnt);
1910 } else {
1911 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
1912 path_cnt);
1913 }
1914 }
1915
1916 /*
1917 * Display BGP EVPN routing table -- for specific RD (vty handler)
1918 * If 'type' is non-zero, only routes matching that type are shown.
1919 */
1920 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
1921 struct prefix_rd *prd, int type,
1922 json_object *json)
1923 {
1924 struct bgp_node *rd_rn;
1925 struct bgp_table *table;
1926 struct bgp_node *rn;
1927 struct bgp_info *ri;
1928 int rd_header = 1;
1929 afi_t afi;
1930 safi_t safi;
1931 u_int32_t prefix_cnt, path_cnt;
1932 char rd_str[RD_ADDRSTRLEN];
1933 json_object *json_rd = NULL;
1934 int add_rd_to_json = 0;
1935
1936 afi = AFI_L2VPN;
1937 safi = SAFI_EVPN;
1938 prefix_cnt = path_cnt = 0;
1939
1940 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
1941
1942 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
1943 if (!rd_rn)
1944 return;
1945
1946 table = (struct bgp_table *)rd_rn->info;
1947 if (table == NULL)
1948 return;
1949
1950 if (json) {
1951 json_rd = json_object_new_object();
1952 json_object_string_add(json_rd, "rd", rd_str);
1953 }
1954
1955 /* Display all prefixes with this RD. */
1956 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
1957 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
1958 json_object *json_prefix = NULL;
1959 json_object *json_paths = NULL;
1960 char prefix_str[BUFSIZ];
1961 int add_prefix_to_json = 0;
1962
1963 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
1964 sizeof(prefix_str));
1965
1966 if (type && evp->prefix.route_type != type)
1967 continue;
1968
1969 if (json)
1970 json_prefix = json_object_new_object();
1971
1972 if (rn->info) {
1973 /* RD header and legend - once overall. */
1974 if (rd_header && !json) {
1975 vty_out(vty,
1976 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]\n");
1977 vty_out(vty,
1978 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
1979 vty_out(vty,
1980 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
1981 rd_header = 0;
1982 }
1983
1984 /* Prefix and num paths displayed once per prefix. */
1985 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
1986 safi, json_prefix);
1987
1988 prefix_cnt++;
1989 }
1990
1991 if (json)
1992 json_paths = json_object_new_array();
1993
1994 /* Display each path for this prefix. */
1995 for (ri = rn->info; ri; ri = ri->next) {
1996 json_object *json_path = NULL;
1997
1998 if (json)
1999 json_path = json_object_new_array();
2000
2001 route_vty_out_detail(vty, bgp, &rn->p, ri, afi, safi,
2002 json_path);
2003
2004 if (json)
2005 json_object_array_add(json_paths, json_path);
2006
2007 path_cnt++;
2008 add_prefix_to_json = 1;
2009 add_rd_to_json = 1;
2010 }
2011
2012 if (json && add_prefix_to_json) {
2013 json_object_object_add(json_prefix, "paths",
2014 json_paths);
2015 json_object_object_add(json_rd, prefix_str,
2016 json_prefix);
2017 }
2018 }
2019
2020 if (json && add_rd_to_json)
2021 json_object_object_add(json, rd_str, json_rd);
2022
2023 if (json) {
2024 json_object_int_add(json, "numPrefix", prefix_cnt);
2025 json_object_int_add(json, "numPaths", path_cnt);
2026 } else {
2027 if (prefix_cnt == 0)
2028 vty_out(vty, "No prefixes exist with this RD%s\n",
2029 type ? " (of requested type)" : "");
2030 else
2031 vty_out(vty,
2032 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2033 prefix_cnt, path_cnt,
2034 type ? " (of requested type)" : "");
2035 }
2036 }
2037
2038 /*
2039 * Display BGP EVPN routing table - all routes (vty handler).
2040 * If 'type' is non-zero, only routes matching that type are shown.
2041 */
2042 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2043 json_object *json)
2044 {
2045 struct bgp_node *rd_rn;
2046 struct bgp_table *table;
2047 struct bgp_node *rn;
2048 struct bgp_info *ri;
2049 int header = 1;
2050 int rd_header;
2051 afi_t afi;
2052 safi_t safi;
2053 u_int32_t prefix_cnt, path_cnt;
2054
2055 afi = AFI_L2VPN;
2056 safi = SAFI_EVPN;
2057 prefix_cnt = path_cnt = 0;
2058
2059 /* EVPN routing table is a 2-level table with the first level being
2060 * the RD.
2061 */
2062 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2063 rd_rn = bgp_route_next(rd_rn)) {
2064 char rd_str[RD_ADDRSTRLEN];
2065 json_object *json_rd = NULL; /* contains routes for an RD */
2066 int add_rd_to_json = 0;
2067
2068 table = (struct bgp_table *)rd_rn->info;
2069 if (table == NULL)
2070 continue;
2071
2072 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2073 sizeof(rd_str));
2074
2075 if (json) {
2076 json_rd = json_object_new_object();
2077 json_object_string_add(json_rd, "rd", rd_str);
2078 }
2079
2080 rd_header = 1;
2081
2082 /* Display all prefixes for an RD */
2083 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2084 json_object *json_prefix =
2085 NULL; /* contains prefix under a RD */
2086 json_object *json_paths =
2087 NULL; /* array of paths under a prefix*/
2088 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2089 char prefix_str[BUFSIZ];
2090 int add_prefix_to_json = 0;
2091
2092 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2093 prefix_str, sizeof(prefix_str));
2094
2095 if (type && evp->prefix.route_type != type)
2096 continue;
2097
2098 if (rn->info) {
2099 /* Overall header/legend displayed once. */
2100 if (header) {
2101 bgp_evpn_show_route_header(vty, bgp,
2102 json);
2103 header = 0;
2104 }
2105
2106 /* RD header - per RD. */
2107 if (rd_header) {
2108 bgp_evpn_show_route_rd_header(
2109 vty, rd_rn, json);
2110 rd_header = 0;
2111 }
2112
2113 prefix_cnt++;
2114 }
2115
2116 if (json) {
2117 json_prefix = json_object_new_object();
2118 json_paths = json_object_new_array();
2119 json_object_string_add(json_prefix, "prefix",
2120 prefix_str);
2121 json_object_int_add(json_prefix, "prefixLen",
2122 rn->p.prefixlen);
2123 }
2124
2125 /* For EVPN, the prefix is displayed for each path (to
2126 * fit in
2127 * with code that already exists).
2128 */
2129 for (ri = rn->info; ri; ri = ri->next) {
2130 json_object *json_path = NULL;
2131 path_cnt++;
2132 add_prefix_to_json = 1;
2133 add_rd_to_json = 1;
2134
2135 if (json)
2136 json_path = json_object_new_array();
2137
2138 route_vty_out(vty, &rn->p, ri, 0, SAFI_EVPN,
2139 json_path);
2140
2141 if (json)
2142 json_object_array_add(json_paths,
2143 json_path);
2144 }
2145
2146 if (json && add_prefix_to_json) {
2147 json_object_object_add(json_prefix, "paths",
2148 json_paths);
2149 json_object_object_add(json_rd, prefix_str,
2150 json_prefix);
2151 }
2152 }
2153
2154 if (json && add_rd_to_json)
2155 json_object_object_add(json, rd_str, json_rd);
2156 }
2157
2158 if (json) {
2159 json_object_int_add(json, "numPrefix", prefix_cnt);
2160 json_object_int_add(json, "numPaths", path_cnt);
2161 } else {
2162 if (prefix_cnt == 0) {
2163 vty_out(vty, "No EVPN prefixes %sexist\n",
2164 type ? "(of requested type) " : "");
2165 } else {
2166 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2167 prefix_cnt, path_cnt,
2168 type ? " (of requested type)" : "");
2169 }
2170 }
2171 }
2172
2173 /*
2174 * Display specified VNI (vty handler)
2175 */
2176 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2177 json_object *json)
2178 {
2179 struct bgpevpn *vpn;
2180
2181 vpn = bgp_evpn_lookup_vni(bgp, vni);
2182 if (!vpn) {
2183 if (json) {
2184 vty_out(vty, "{}\n");
2185 } else {
2186 vty_out(vty, "VNI not found\n");
2187 return;
2188 }
2189 }
2190
2191 display_vni(vty, vpn, json);
2192 }
2193
2194 /*
2195 * Display a VNI (upon user query).
2196 */
2197 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2198 json_object *json)
2199 {
2200 u_int32_t num_vnis;
2201 void *args[2];
2202
2203 num_vnis = hashcount(bgp->vnihash);
2204 if (!num_vnis)
2205 return;
2206
2207 if (json) {
2208 json_object_int_add(json, "numVnis", num_vnis);
2209 } else {
2210 vty_out(vty, "Number of VNIs: %u\n", num_vnis);
2211 vty_out(vty, "Flags: * - Kernel\n");
2212 vty_out(vty, " %-10s %-15s %-21s %-25s %-25s %-37s\n", "VNI",
2213 "Orig IP", "RD", "Import RT",
2214 "Export RT", "Tenant-Vrf");
2215 }
2216
2217 args[0] = vty;
2218 args[1] = json;
2219 hash_iterate(bgp->vnihash,
2220 (void (*)(struct hash_backet *, void *))show_vni_entry,
2221 args);
2222 }
2223
2224 /*
2225 * evpn - enable advertisement of default g/w
2226 */
2227 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2228 {
2229 if (!vpn) {
2230 if (bgp->advertise_gw_macip)
2231 return;
2232
2233 bgp->advertise_gw_macip = 1;
2234 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2235 } else {
2236 if (vpn->advertise_gw_macip)
2237 return;
2238
2239 vpn->advertise_gw_macip = 1;
2240 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2241 vpn->vni);
2242 }
2243 return;
2244 }
2245
2246 /*
2247 * evpn - disable advertisement of default g/w
2248 */
2249 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2250 struct bgpevpn *vpn)
2251 {
2252 if (!vpn) {
2253 if (!bgp->advertise_gw_macip)
2254 return;
2255
2256 bgp->advertise_gw_macip = 0;
2257 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2258 } else {
2259 if (!vpn->advertise_gw_macip)
2260 return;
2261
2262 vpn->advertise_gw_macip = 0;
2263 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2264 vpn->vni);
2265 }
2266 return;
2267 }
2268
2269 /*
2270 * EVPN (VNI advertisement) enabled. Register with zebra.
2271 */
2272 static void evpn_set_advertise_all_vni(struct bgp *bgp)
2273 {
2274 bgp->advertise_all_vni = 1;
2275 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2276 }
2277
2278 /*
2279 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2280 * cache, EVPN routes (delete and withdraw from peers).
2281 */
2282 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
2283 {
2284 bgp->advertise_all_vni = 0;
2285 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
2286 bgp_evpn_cleanup_on_disable(bgp);
2287 }
2288 #endif /* HAVE_CUMULUS */
2289
2290 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
2291 {
2292 char buf1[RD_ADDRSTRLEN];
2293 char *ecom_str;
2294 struct listnode *node, *nnode;
2295 struct ecommunity *ecom;
2296
2297 if (is_vni_configured(vpn)) {
2298 vty_out(vty, " vni %d\n", vpn->vni);
2299 if (is_rd_configured(vpn))
2300 vty_out(vty, " rd %s\n",
2301 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
2302
2303 if (is_import_rt_configured(vpn)) {
2304 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
2305 ecom)) {
2306 ecom_str = ecommunity_ecom2str(
2307 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2308 vty_out(vty, " route-target import %s\n",
2309 ecom_str);
2310 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2311 }
2312 }
2313
2314 if (is_export_rt_configured(vpn)) {
2315 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
2316 ecom)) {
2317 ecom_str = ecommunity_ecom2str(
2318 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
2319 vty_out(vty, " route-target export %s\n",
2320 ecom_str);
2321 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
2322 }
2323 }
2324
2325 if (vpn->advertise_gw_macip)
2326 vty_out(vty, " advertise-default-gw\n");
2327
2328 vty_out(vty, " exit-vni\n");
2329 }
2330 }
2331
2332 static void write_vni_config_for_entry(struct hash_backet *backet,
2333 struct vty *vty)
2334 {
2335 struct bgpevpn *vpn = (struct bgpevpn *)backet->data;
2336 write_vni_config(vty, vpn);
2337 }
2338
2339 #if defined(HAVE_CUMULUS)
2340 DEFUN (bgp_evpn_advertise_default_gw_vni,
2341 bgp_evpn_advertise_default_gw_vni_cmd,
2342 "advertise-default-gw",
2343 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2344 {
2345 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2346 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2347
2348 if (!bgp)
2349 return CMD_WARNING;
2350
2351 if (!vpn)
2352 return CMD_WARNING;
2353
2354 evpn_set_advertise_default_gw(bgp, vpn);
2355
2356 return CMD_SUCCESS;
2357 }
2358
2359 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
2360 no_bgp_evpn_advertise_default_gw_vni_cmd,
2361 "no advertise-default-gw",
2362 NO_STR
2363 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2364 {
2365 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2366 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
2367
2368 if (!bgp)
2369 return CMD_WARNING;
2370
2371 if (!vpn)
2372 return CMD_WARNING;
2373
2374 evpn_unset_advertise_default_gw(bgp, vpn);
2375
2376 return CMD_SUCCESS;
2377 }
2378
2379
2380 DEFUN (bgp_evpn_advertise_default_gw,
2381 bgp_evpn_advertise_default_gw_cmd,
2382 "advertise-default-gw",
2383 "Advertise All default g/w mac-ip routes in EVPN\n")
2384 {
2385 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2386
2387 if (!bgp)
2388 return CMD_WARNING;
2389
2390 evpn_set_advertise_default_gw(bgp, NULL);
2391
2392 return CMD_SUCCESS;
2393 }
2394
2395 DEFUN (no_bgp_evpn_advertise_default_gw,
2396 no_bgp_evpn_advertise_default_gw_cmd,
2397 "no advertise-default-gw",
2398 NO_STR
2399 "Withdraw All default g/w mac-ip routes from EVPN\n")
2400 {
2401 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2402
2403 if (!bgp)
2404 return CMD_WARNING;
2405
2406 evpn_unset_advertise_default_gw(bgp, NULL);
2407
2408 return CMD_SUCCESS;
2409 }
2410
2411 DEFUN (bgp_evpn_advertise_all_vni,
2412 bgp_evpn_advertise_all_vni_cmd,
2413 "advertise-all-vni",
2414 "Advertise All local VNIs\n")
2415 {
2416 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2417
2418 if (!bgp)
2419 return CMD_WARNING;
2420 evpn_set_advertise_all_vni(bgp);
2421 return CMD_SUCCESS;
2422 }
2423
2424 DEFUN (no_bgp_evpn_advertise_all_vni,
2425 no_bgp_evpn_advertise_all_vni_cmd,
2426 "no advertise-all-vni",
2427 NO_STR
2428 "Advertise All local VNIs\n")
2429 {
2430 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
2431
2432 if (!bgp)
2433 return CMD_WARNING;
2434 evpn_unset_advertise_all_vni(bgp);
2435 return CMD_SUCCESS;
2436 }
2437
2438 DEFUN (bgp_evpn_advertise_type5,
2439 bgp_evpn_advertise_type5_cmd,
2440 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
2441 "Advertise prefix routes\n"
2442 BGP_AFI_HELP_STR
2443 BGP_SAFI_HELP_STR)
2444 {
2445 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
2446 int idx_afi = 0;
2447 int idx_safi = 0;
2448 afi_t afi = 0;
2449 safi_t safi = 0;
2450
2451 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2452 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
2453
2454 if (!(afi == AFI_IP) || (afi == AFI_IP6)) {
2455 vty_out(vty,
2456 "%%only ipv4 or ipv6 address families are supported");
2457 return CMD_WARNING;
2458 }
2459
2460 if (safi != SAFI_UNICAST) {
2461 vty_out(vty,
2462 "%%only ipv4 unicast or ipv6 unicast are supported");
2463 return CMD_WARNING;
2464 }
2465
2466 if (afi == AFI_IP) {
2467
2468 /* if we are already advertising ipv4 prefix as type-5
2469 * nothing to do */
2470 if (!CHECK_FLAG(bgp_vrf->vrf_flags,
2471 BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
2472 SET_FLAG(bgp_vrf->vrf_flags,
2473 BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
2474 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
2475 }
2476 } else {
2477
2478 /* if we are already advertising ipv6 prefix as type-5
2479 * nothing to do */
2480 if (!CHECK_FLAG(bgp_vrf->vrf_flags,
2481 BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
2482 SET_FLAG(bgp_vrf->vrf_flags,
2483 BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
2484 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
2485 }
2486 }
2487 return CMD_SUCCESS;
2488 }
2489
2490 DEFUN (no_bgp_evpn_advertise_type5,
2491 no_bgp_evpn_advertise_type5_cmd,
2492 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
2493 NO_STR
2494 "Advertise prefix routes\n"
2495 BGP_AFI_HELP_STR
2496 BGP_SAFI_HELP_STR)
2497 {
2498 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
2499 int idx_afi = 0;
2500 int idx_safi = 0;
2501 afi_t afi = 0;
2502 safi_t safi = 0;
2503
2504 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
2505 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
2506
2507 if (!(afi == AFI_IP) || (afi == AFI_IP6)) {
2508 vty_out(vty,
2509 "%%only ipv4 or ipv6 address families are supported");
2510 return CMD_WARNING;
2511 }
2512
2513 if (safi != SAFI_UNICAST) {
2514 vty_out(vty,
2515 "%%only ipv4 unicast or ipv6 unicast are supported");
2516 return CMD_WARNING;
2517 }
2518
2519 if (afi == AFI_IP) {
2520
2521 /* if we are already advertising ipv4 prefix as type-5
2522 * nothing to do */
2523 if (CHECK_FLAG(bgp_vrf->vrf_flags,
2524 BGP_VRF_ADVERTISE_IPV4_IN_EVPN)) {
2525 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
2526 UNSET_FLAG(bgp_vrf->vrf_flags,
2527 BGP_VRF_ADVERTISE_IPV4_IN_EVPN);
2528 }
2529 } else {
2530
2531 /* if we are already advertising ipv6 prefix as type-5
2532 * nothing to do */
2533 if (CHECK_FLAG(bgp_vrf->vrf_flags,
2534 BGP_VRF_ADVERTISE_IPV6_IN_EVPN)) {
2535 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
2536 UNSET_FLAG(bgp_vrf->vrf_flags,
2537 BGP_VRF_ADVERTISE_IPV6_IN_EVPN);
2538 }
2539 }
2540 return CMD_SUCCESS;
2541 }
2542
2543 /*
2544 * Display VNI information - for all or a specific VNI
2545 */
2546 DEFUN(show_bgp_l2vpn_evpn_vni,
2547 show_bgp_l2vpn_evpn_vni_cmd,
2548 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2549 SHOW_STR
2550 BGP_STR
2551 L2VPN_HELP_STR
2552 EVPN_HELP_STR
2553 "Show VNI\n"
2554 "VNI number\n"
2555 JSON_STR)
2556 {
2557 struct bgp *bgp;
2558 vni_t vni;
2559 int idx = 0;
2560 u_char uj = 0;
2561 json_object *json = NULL;
2562
2563 uj = use_json(argc, argv);
2564
2565 bgp = bgp_get_default();
2566 if (!bgp)
2567 return CMD_WARNING;
2568
2569 if (!argv_find(argv, argc, "evpn", &idx))
2570 return CMD_WARNING;
2571
2572 if (uj)
2573 json = json_object_new_object();
2574
2575 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
2576 if (uj) {
2577 json_object_string_add(json, "advertiseGatewayMacip",
2578 bgp->advertise_gw_macip
2579 ? "Enabled"
2580 : "Disabled");
2581 json_object_string_add(json, "advertiseAllVnis",
2582 is_evpn_enabled()
2583 ? "Enabled"
2584 : "Disabled");
2585 } else {
2586 vty_out(vty, "Advertise Gateway Macip: %s\n",
2587 bgp->advertise_gw_macip ? "Enabled"
2588 : "Disabled");
2589
2590 /* Display all VNIs */
2591 vty_out(vty, "Advertise All VNI flag: %s\n",
2592 is_evpn_enabled() ? "Enabled" : "Disabled");
2593 }
2594
2595 evpn_show_all_vnis(vty, bgp, json);
2596 } else {
2597 int vni_idx = 0;
2598
2599 if (!argv_find(argv, argc, "vni", &vni_idx))
2600 return CMD_WARNING;
2601
2602 /* Display specific VNI */
2603 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
2604 evpn_show_vni(vty, bgp, vni, json);
2605 }
2606
2607 if (uj) {
2608 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2609 json, JSON_C_TO_STRING_PRETTY));
2610 json_object_free(json);
2611 }
2612
2613 return CMD_SUCCESS;
2614 }
2615
2616 /*
2617 * Display EVPN neighbor summary.
2618 */
2619 DEFUN(show_bgp_l2vpn_evpn_summary,
2620 show_bgp_l2vpn_evpn_summary_cmd,
2621 "show bgp l2vpn evpn summary [json]",
2622 SHOW_STR
2623 BGP_STR
2624 L2VPN_HELP_STR
2625 EVPN_HELP_STR
2626 "Summary of BGP neighbor status\n"
2627 JSON_STR)
2628 {
2629 u_char uj = use_json(argc, argv);
2630 return bgp_show_summary_vty(vty, NULL, AFI_L2VPN, SAFI_EVPN, uj);
2631 }
2632
2633 /*
2634 * Display global EVPN routing table.
2635 */
2636 DEFUN(show_bgp_l2vpn_evpn_route,
2637 show_bgp_l2vpn_evpn_route_cmd,
2638 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2639 SHOW_STR
2640 BGP_STR
2641 L2VPN_HELP_STR
2642 EVPN_HELP_STR
2643 "EVPN route information\n"
2644 "Specify Route type\n"
2645 "MAC-IP (Type-2) route\n"
2646 "Multicast (Type-3) route\n"
2647 JSON_STR)
2648 {
2649 struct bgp *bgp;
2650 int type_idx = 0;
2651 int type = 0;
2652 u_char uj = 0;
2653 json_object *json = NULL;
2654
2655 uj = use_json(argc, argv);
2656
2657 bgp = bgp_get_default();
2658 if (!bgp)
2659 return CMD_WARNING;
2660
2661 if (uj)
2662 json = json_object_new_object();
2663
2664 /* get the type */
2665 if (argv_find(argv, argc, "type", &type_idx)) {
2666 /* Specific type is requested */
2667 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
2668 type = BGP_EVPN_MAC_IP_ROUTE;
2669 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
2670 type = BGP_EVPN_IMET_ROUTE;
2671 else
2672 return CMD_WARNING;
2673 }
2674
2675 evpn_show_all_routes(vty, bgp, type, json);
2676
2677 if (uj) {
2678 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2679 json, JSON_C_TO_STRING_PRETTY));
2680 json_object_free(json);
2681 }
2682
2683 return CMD_SUCCESS;
2684 }
2685
2686 /*
2687 * Display global EVPN routing table for specific RD.
2688 */
2689 DEFUN(show_bgp_l2vpn_evpn_route_rd,
2690 show_bgp_l2vpn_evpn_route_rd_cmd,
2691 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]",
2692 SHOW_STR
2693 BGP_STR
2694 L2VPN_HELP_STR
2695 EVPN_HELP_STR
2696 "EVPN route information\n"
2697 "Route Distinguisher\n"
2698 "ASN:XX or A.B.C.D:XX\n"
2699 "Specify Route type\n"
2700 "MAC-IP (Type-2) route\n"
2701 "Multicast (Type-3) route\n"
2702 JSON_STR)
2703 {
2704 struct bgp *bgp;
2705 int ret;
2706 struct prefix_rd prd;
2707 int type = 0;
2708 int rd_idx = 0;
2709 int type_idx = 0;
2710 int uj = 0;
2711 json_object *json = NULL;
2712
2713 bgp = bgp_get_default();
2714 if (!bgp)
2715 return CMD_WARNING;
2716
2717 /* check if we need json output */
2718 uj = use_json(argc, argv);
2719 if (uj)
2720 json = json_object_new_object();
2721
2722 /* get the RD */
2723 if (argv_find(argv, argc, "rd", &rd_idx)) {
2724 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2725
2726 if (!ret) {
2727 vty_out(vty, "%% Malformed Route Distinguisher\n");
2728 return CMD_WARNING;
2729 }
2730 }
2731
2732 /* get the type */
2733 if (argv_find(argv, argc, "type", &type_idx)) {
2734 /* Specific type is requested */
2735 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
2736 type = BGP_EVPN_MAC_IP_ROUTE;
2737 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
2738 type = BGP_EVPN_IMET_ROUTE;
2739 else
2740 return CMD_WARNING;
2741 }
2742
2743 evpn_show_route_rd(vty, bgp, &prd, type, json);
2744
2745 if (uj) {
2746 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2747 json, JSON_C_TO_STRING_PRETTY));
2748 json_object_free(json);
2749 }
2750
2751 return CMD_SUCCESS;
2752 }
2753
2754 /*
2755 * Display global EVPN routing table for specific RD and MACIP.
2756 */
2757 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
2758 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
2759 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
2760 SHOW_STR
2761 BGP_STR
2762 L2VPN_HELP_STR
2763 EVPN_HELP_STR
2764 "EVPN route information\n"
2765 "Route Distinguisher\n"
2766 "ASN:XX or A.B.C.D:XX\n"
2767 "MAC\n"
2768 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2769 "IP\n"
2770 "IP address (IPv4 or IPv6)\n"
2771 JSON_STR)
2772 {
2773 struct bgp *bgp;
2774 int ret;
2775 struct prefix_rd prd;
2776 struct ethaddr mac;
2777 struct ipaddr ip;
2778 int rd_idx = 0;
2779 int mac_idx = 0;
2780 int ip_idx = 0;
2781 int uj = 0;
2782 json_object *json = NULL;
2783
2784 memset(&mac, 0, sizeof(struct ethaddr));
2785 memset(&ip, 0, sizeof(struct ipaddr));
2786
2787 bgp = bgp_get_default();
2788 if (!bgp)
2789 return CMD_WARNING;
2790
2791 /* check if we need json output */
2792 uj = use_json(argc, argv);
2793 if (uj)
2794 json = json_object_new_object();
2795
2796 /* get the prd */
2797 if (argv_find(argv, argc, "rd", &rd_idx)) {
2798 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
2799 if (!ret) {
2800 vty_out(vty, "%% Malformed Route Distinguisher\n");
2801 return CMD_WARNING;
2802 }
2803 }
2804
2805 /* get the mac */
2806 if (argv_find(argv, argc, "mac", &mac_idx)) {
2807 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
2808 vty_out(vty, "%% Malformed MAC address\n");
2809 return CMD_WARNING;
2810 }
2811 }
2812
2813 /* get the ip if specified */
2814 if (argv_find(argv, argc, "ip", &ip_idx)) {
2815 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
2816 vty_out(vty, "%% Malformed IP address\n");
2817 return CMD_WARNING;
2818 }
2819 }
2820
2821 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
2822
2823 if (uj) {
2824 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2825 json, JSON_C_TO_STRING_PRETTY));
2826 json_object_free(json);
2827 }
2828
2829 return CMD_SUCCESS;
2830 }
2831
2832 /*
2833 * Display per-VRF EVPN routing table.
2834 */
2835 DEFUN(show_bgp_l2vpn_evpn_route_vrf, show_bgp_l2vpn_evpn_route_vrf_cmd,
2836 "show bgp l2vpn evpn route vrf VRFNAME",
2837 SHOW_STR
2838 BGP_STR
2839 L2VPN_HELP_STR
2840 EVPN_HELP_STR
2841 "EVPN route information\n"
2842 "VRF\n"
2843 "VRF Name\n")
2844 {
2845 int vrf_idx = 6;
2846 char *vrf_name = NULL;
2847 struct bgp *bgp_vrf = NULL;
2848
2849 vrf_name = argv[vrf_idx]->arg;
2850 bgp_vrf = bgp_lookup_by_name(vrf_name);
2851 if (!bgp_vrf)
2852 return CMD_WARNING;
2853
2854 evpn_show_vrf_routes(vty, bgp_vrf);
2855
2856 return CMD_SUCCESS;
2857 }
2858
2859 /*
2860 * Display per-VNI EVPN routing table.
2861 */
2862 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
2863 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2864 SHOW_STR
2865 BGP_STR
2866 L2VPN_HELP_STR
2867 EVPN_HELP_STR
2868 "EVPN route information\n"
2869 "VXLAN Network Identifier\n"
2870 "VNI number\n"
2871 "Specify Route type\n"
2872 "MAC-IP (Type-2) route\n"
2873 "Multicast (Type-3) route\n"
2874 "Remote VTEP\n"
2875 "Remote VTEP IP address\n"
2876 JSON_STR)
2877 {
2878 vni_t vni;
2879 struct bgp *bgp;
2880 struct in_addr vtep_ip;
2881 int type = 0;
2882 int idx = 0;
2883 int uj = 0;
2884 json_object *json = NULL;
2885
2886 bgp = bgp_get_default();
2887 if (!bgp)
2888 return CMD_WARNING;
2889
2890 /* check if we need json output */
2891 uj = use_json(argc, argv);
2892 if (uj)
2893 json = json_object_new_object();
2894
2895 if (!argv_find(argv, argc, "evpn", &idx))
2896 return CMD_WARNING;
2897
2898 vtep_ip.s_addr = 0;
2899
2900 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
2901
2902 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
2903 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
2904 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
2905 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
2906 type = BGP_EVPN_MAC_IP_ROUTE;
2907 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
2908 type = BGP_EVPN_IMET_ROUTE;
2909 else
2910 return CMD_WARNING;
2911 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
2912 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
2913 vty_out(vty, "%% Malformed VTEP IP address\n");
2914 return CMD_WARNING;
2915 }
2916 } else
2917 return CMD_WARNING;
2918 }
2919
2920 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
2921
2922 if (uj) {
2923 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2924 json, JSON_C_TO_STRING_PRETTY));
2925 json_object_free(json);
2926 }
2927
2928 return CMD_SUCCESS;
2929 }
2930
2931 /*
2932 * Display per-VNI EVPN routing table for specific MACIP.
2933 */
2934 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
2935 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
2936 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2937 SHOW_STR
2938 BGP_STR
2939 L2VPN_HELP_STR
2940 EVPN_HELP_STR
2941 "EVPN route information\n"
2942 "VXLAN Network Identifier\n"
2943 "VNI number\n"
2944 "MAC\n"
2945 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2946 "IP\n"
2947 "IP address (IPv4 or IPv6)\n"
2948 JSON_STR)
2949 {
2950 vni_t vni;
2951 struct bgp *bgp;
2952 struct ethaddr mac;
2953 struct ipaddr ip;
2954 int idx = 0;
2955 int uj = 0;
2956 json_object *json = NULL;
2957
2958 bgp = bgp_get_default();
2959 if (!bgp)
2960 return CMD_WARNING;
2961
2962 /* check if we need json output */
2963 uj = use_json(argc, argv);
2964 if (uj)
2965 json = json_object_new_object();
2966
2967 if (!argv_find(argv, argc, "evpn", &idx))
2968 return CMD_WARNING;
2969
2970 /* get the VNI */
2971 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
2972
2973 /* get the mac */
2974 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
2975 vty_out(vty, "%% Malformed MAC address\n");
2976 return CMD_WARNING;
2977 }
2978
2979 /* get the ip */
2980 memset(&ip, 0, sizeof(ip));
2981 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
2982 || (uj
2983 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
2984 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
2985 vty_out(vty, "%% Malformed IP address\n");
2986 return CMD_WARNING;
2987 }
2988 }
2989
2990 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
2991
2992 if (uj) {
2993 vty_out(vty, "%s\n", json_object_to_json_string_ext(
2994 json, JSON_C_TO_STRING_PRETTY));
2995 json_object_free(json);
2996 }
2997
2998 return CMD_SUCCESS;
2999 }
3000
3001 /*
3002 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3003 */
3004 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
3005 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
3006 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3007 SHOW_STR
3008 BGP_STR
3009 L2VPN_HELP_STR
3010 EVPN_HELP_STR
3011 "EVPN route information\n"
3012 "VXLAN Network Identifier\n"
3013 "VNI number\n"
3014 "Multicast (Type-3) route\n"
3015 "Originating Router IP address\n"
3016 JSON_STR)
3017 {
3018 vni_t vni;
3019 struct bgp *bgp;
3020 int ret;
3021 struct in_addr orig_ip;
3022 int idx = 0;
3023 int uj = 0;
3024 json_object *json = NULL;
3025
3026 bgp = bgp_get_default();
3027 if (!bgp)
3028 return CMD_WARNING;
3029
3030 /* check if we need json output */
3031 uj = use_json(argc, argv);
3032 if (uj)
3033 json = json_object_new_object();
3034
3035 if (!argv_find(argv, argc, "evpn", &idx))
3036 return CMD_WARNING;
3037
3038 /* get the VNI */
3039 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
3040
3041 /* get the ip */
3042 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
3043 if (!ret) {
3044 vty_out(vty, "%% Malformed Originating Router IP address\n");
3045 return CMD_WARNING;
3046 }
3047
3048 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
3049
3050 if (uj) {
3051 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3052 json, JSON_C_TO_STRING_PRETTY));
3053 json_object_free(json);
3054 }
3055
3056 return CMD_SUCCESS;
3057 }
3058
3059 /*
3060 * Display per-VNI EVPN routing table - for all VNIs.
3061 */
3062 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
3063 show_bgp_l2vpn_evpn_route_vni_all_cmd,
3064 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3065 SHOW_STR
3066 BGP_STR
3067 L2VPN_HELP_STR
3068 EVPN_HELP_STR
3069 "EVPN route information\n"
3070 "VXLAN Network Identifier\n"
3071 "All VNIs\n"
3072 "Remote VTEP\n"
3073 "Remote VTEP IP address\n"
3074 JSON_STR)
3075 {
3076 struct bgp *bgp;
3077 struct in_addr vtep_ip;
3078 int idx = 0;
3079 int uj = 0;
3080 json_object *json = NULL;
3081
3082 bgp = bgp_get_default();
3083 if (!bgp)
3084 return CMD_WARNING;
3085
3086 /* check if we need json output */
3087 uj = use_json(argc, argv);
3088 if (uj)
3089 json = json_object_new_object();
3090
3091 if (!argv_find(argv, argc, "evpn", &idx))
3092 return CMD_WARNING;
3093
3094 vtep_ip.s_addr = 0;
3095 if ((!uj && (argc == (idx + 1 + 5) && argv[idx + 5]->arg))
3096 || (uj && (argc == (idx + 1 + 6) && argv[idx + 5]->arg))) {
3097 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
3098 vty_out(vty, "%% Malformed VTEP IP address\n");
3099 return CMD_WARNING;
3100 }
3101 }
3102
3103 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json);
3104
3105 if (uj) {
3106 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3107 json, JSON_C_TO_STRING_PRETTY));
3108 json_object_free(json);
3109 }
3110
3111 return CMD_SUCCESS;
3112 }
3113
3114 /*
3115 * Display EVPN import route-target hash table
3116 */
3117 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
3118 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
3119 "show bgp l2vpn evpn vrf-import-rt [json]",
3120 SHOW_STR
3121 BGP_STR
3122 L2VPN_HELP_STR
3123 EVPN_HELP_STR
3124 "Show vrf import route target\n"
3125 JSON_STR)
3126 {
3127 u_char uj = 0;
3128 struct bgp *bgp_def = NULL;
3129 json_object *json = NULL;
3130
3131 bgp_def = bgp_get_default();
3132 if (!bgp_def)
3133 return CMD_WARNING;
3134
3135 uj = use_json(argc, argv);
3136 if (uj)
3137 json = json_object_new_object();
3138
3139 evpn_show_vrf_import_rts(vty, bgp_def, json);
3140
3141 if (uj) {
3142 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3143 json, JSON_C_TO_STRING_PRETTY));
3144 json_object_free(json);
3145 }
3146
3147 return CMD_SUCCESS;
3148 }
3149
3150 /*
3151 * Display EVPN import route-target hash table
3152 */
3153 DEFUN(show_bgp_l2vpn_evpn_import_rt,
3154 show_bgp_l2vpn_evpn_import_rt_cmd,
3155 "show bgp l2vpn evpn import-rt [json]",
3156 SHOW_STR
3157 BGP_STR
3158 L2VPN_HELP_STR
3159 EVPN_HELP_STR
3160 "Show import route target\n"
3161 JSON_STR)
3162 {
3163 struct bgp *bgp;
3164 u_char uj = 0;
3165 json_object *json = NULL;
3166
3167 bgp = bgp_get_default();
3168 if (!bgp)
3169 return CMD_WARNING;
3170
3171 uj = use_json(argc, argv);
3172 if (uj)
3173 json = json_object_new_object();
3174
3175 evpn_show_import_rts(vty, bgp, json);
3176
3177 if (uj) {
3178 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3179 json, JSON_C_TO_STRING_PRETTY));
3180 json_object_free(json);
3181 }
3182
3183 return CMD_SUCCESS;
3184 }
3185
3186 #if defined(HAVE_CUMULUS)
3187 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
3188 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3189 "Show VNI\n"
3190 "VNI number\n")
3191
3192 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
3193 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3194 "Summary of BGP neighbor status\n"
3195 JSON_STR)
3196
3197 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
3198 "show bgp evpn route [type <macip|multicast>]",
3199 SHOW_STR BGP_STR EVPN_HELP_STR
3200 "EVPN route information\n"
3201 "Specify Route type\n"
3202 "MAC-IP (Type-2) route\n"
3203 "Multicast (Type-3) route\n")
3204
3205 ALIAS_HIDDEN(
3206 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
3207 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3208 SHOW_STR BGP_STR EVPN_HELP_STR
3209 "EVPN route information\n"
3210 "Route Distinguisher\n"
3211 "ASN:XX or A.B.C.D:XX\n"
3212 "Specify Route type\n"
3213 "MAC-IP (Type-2) route\n"
3214 "Multicast (Type-3) route\n")
3215
3216 ALIAS_HIDDEN(
3217 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
3218 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
3219 SHOW_STR BGP_STR EVPN_HELP_STR
3220 "EVPN route information\n"
3221 "Route Distinguisher\n"
3222 "ASN:XX or A.B.C.D:XX\n"
3223 "MAC\n"
3224 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3225 "IP\n"
3226 "IP address (IPv4 or IPv6)\n")
3227
3228 ALIAS_HIDDEN(
3229 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
3230 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3231 SHOW_STR BGP_STR EVPN_HELP_STR
3232 "EVPN route information\n"
3233 "VXLAN Network Identifier\n"
3234 "VNI number\n"
3235 "Specify Route type\n"
3236 "MAC-IP (Type-2) route\n"
3237 "Multicast (Type-3) route\n"
3238 "Remote VTEP\n"
3239 "Remote VTEP IP address\n")
3240
3241 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
3242 show_bgp_evpn_route_vni_macip_cmd,
3243 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3244 SHOW_STR BGP_STR EVPN_HELP_STR
3245 "EVPN route information\n"
3246 "VXLAN Network Identifier\n"
3247 "VNI number\n"
3248 "MAC\n"
3249 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3250 "IP\n"
3251 "IP address (IPv4 or IPv6)\n")
3252
3253 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
3254 show_bgp_evpn_route_vni_multicast_cmd,
3255 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3256 SHOW_STR BGP_STR EVPN_HELP_STR
3257 "EVPN route information\n"
3258 "VXLAN Network Identifier\n"
3259 "VNI number\n"
3260 "Multicast (Type-3) route\n"
3261 "Originating Router IP address\n")
3262
3263 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
3264 "show bgp evpn route vni all [vtep A.B.C.D]",
3265 SHOW_STR BGP_STR EVPN_HELP_STR
3266 "EVPN route information\n"
3267 "VXLAN Network Identifier\n"
3268 "All VNIs\n"
3269 "Remote VTEP\n"
3270 "Remote VTEP IP address\n")
3271
3272 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
3273 "show bgp evpn import-rt",
3274 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
3275 #endif
3276
3277 DEFUN_NOSH (bgp_evpn_vni,
3278 bgp_evpn_vni_cmd,
3279 "vni (1-16777215)",
3280 "VXLAN Network Identifier\n"
3281 "VNI number\n")
3282 {
3283 vni_t vni;
3284 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3285 struct bgpevpn *vpn;
3286
3287 if (!bgp)
3288 return CMD_WARNING;
3289
3290 vni = strtoul(argv[1]->arg, NULL, 10);
3291
3292 /* Create VNI, or mark as configured. */
3293 vpn = evpn_create_update_vni(bgp, vni);
3294 if (!vpn) {
3295 vty_out(vty, "%% Failed to create VNI \n");
3296 return CMD_WARNING;
3297 }
3298
3299 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
3300 return CMD_SUCCESS;
3301 }
3302
3303 DEFUN (no_bgp_evpn_vni,
3304 no_bgp_evpn_vni_cmd,
3305 "no vni (1-16777215)",
3306 NO_STR
3307 "VXLAN Network Identifier\n"
3308 "VNI number\n")
3309 {
3310 vni_t vni;
3311 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3312 struct bgpevpn *vpn;
3313
3314 if (!bgp)
3315 return CMD_WARNING;
3316
3317 vni = strtoul(argv[2]->arg, NULL, 10);
3318
3319 /* Check if we should disallow. */
3320 vpn = bgp_evpn_lookup_vni(bgp, vni);
3321 if (!vpn) {
3322 vty_out(vty, "%% Specified VNI does not exist\n");
3323 return CMD_WARNING;
3324 }
3325 if (!is_vni_configured(vpn)) {
3326 vty_out(vty, "%% Specified VNI is not configured\n");
3327 return CMD_WARNING;
3328 }
3329
3330 evpn_delete_vni(bgp, vpn);
3331 return CMD_SUCCESS;
3332 }
3333
3334 DEFUN_NOSH (exit_vni,
3335 exit_vni_cmd,
3336 "exit-vni",
3337 "Exit from VNI mode\n")
3338 {
3339 if (vty->node == BGP_EVPN_VNI_NODE)
3340 vty->node = BGP_EVPN_NODE;
3341 return CMD_SUCCESS;
3342 }
3343
3344 DEFUN (bgp_evpn_vrf_rd,
3345 bgp_evpn_vrf_rd_cmd,
3346 "rd ASN:NN_OR_IP-ADDRESS:NN",
3347 "Route Distinguisher\n"
3348 "ASN:XX or A.B.C.D:XX\n")
3349 {
3350 int ret;
3351 struct prefix_rd prd;
3352 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3353
3354 if (!bgp_vrf)
3355 return CMD_WARNING;
3356
3357 ret = str2prefix_rd(argv[1]->arg, &prd);
3358 if (!ret) {
3359 vty_out(vty, "%% Malformed Route Distinguisher\n");
3360 return CMD_WARNING;
3361 }
3362
3363 /* If same as existing value, there is nothing more to do. */
3364 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
3365 return CMD_SUCCESS;
3366
3367 /* Configure or update the RD. */
3368 evpn_configure_vrf_rd(bgp_vrf, &prd);
3369 return CMD_SUCCESS;
3370 }
3371
3372 DEFUN (no_bgp_evpn_vrf_rd,
3373 no_bgp_evpn_vrf_rd_cmd,
3374 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3375 NO_STR
3376 "Route Distinguisher\n"
3377 "ASN:XX or A.B.C.D:XX\n")
3378 {
3379 int ret;
3380 struct prefix_rd prd;
3381 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3382
3383 if (!bgp_vrf)
3384 return CMD_WARNING;
3385
3386 ret = str2prefix_rd(argv[2]->arg, &prd);
3387 if (!ret) {
3388 vty_out(vty, "%% Malformed Route Distinguisher\n");
3389 return CMD_WARNING;
3390 }
3391
3392 /* Check if we should disallow. */
3393 if (!is_vrf_rd_configured(bgp_vrf)) {
3394 vty_out(vty, "%% RD is not configured for this VRF\n");
3395 return CMD_WARNING;
3396 }
3397
3398 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
3399 vty_out(vty,
3400 "%% RD specified does not match configuration for this VRF\n");
3401 return CMD_WARNING;
3402 }
3403
3404 evpn_unconfigure_vrf_rd(bgp_vrf);
3405 return CMD_SUCCESS;
3406 }
3407
3408 DEFUN (no_bgp_evpn_vrf_rd_without_val,
3409 no_bgp_evpn_vrf_rd_without_val_cmd,
3410 "no rd",
3411 NO_STR
3412 "Route Distinguisher\n")
3413 {
3414 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3415
3416 if (!bgp_vrf)
3417 return CMD_WARNING;
3418
3419 /* Check if we should disallow. */
3420 if (!is_vrf_rd_configured(bgp_vrf)) {
3421 vty_out(vty, "%% RD is not configured for this VRF\n");
3422 return CMD_WARNING;
3423 }
3424
3425 evpn_unconfigure_vrf_rd(bgp_vrf);
3426 return CMD_SUCCESS;
3427 }
3428
3429 DEFUN (bgp_evpn_vni_rd,
3430 bgp_evpn_vni_rd_cmd,
3431 "rd ASN:NN_OR_IP-ADDRESS:NN",
3432 "Route Distinguisher\n"
3433 "ASN:XX or A.B.C.D:XX\n")
3434 {
3435 struct prefix_rd prd;
3436 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3437 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3438 int ret;
3439
3440 if (!bgp || !vpn)
3441 return CMD_WARNING;
3442
3443 ret = str2prefix_rd(argv[1]->arg, &prd);
3444 if (!ret) {
3445 vty_out(vty, "%% Malformed Route Distinguisher\n");
3446 return CMD_WARNING;
3447 }
3448
3449 /* If same as existing value, there is nothing more to do. */
3450 if (bgp_evpn_rd_matches_existing(vpn, &prd))
3451 return CMD_SUCCESS;
3452
3453 /* Configure or update the RD. */
3454 evpn_configure_rd(bgp, vpn, &prd);
3455 return CMD_SUCCESS;
3456 }
3457
3458 DEFUN (no_bgp_evpn_vni_rd,
3459 no_bgp_evpn_vni_rd_cmd,
3460 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3461 NO_STR
3462 "Route Distinguisher\n"
3463 "ASN:XX or A.B.C.D:XX\n")
3464 {
3465 struct prefix_rd prd;
3466 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3467 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3468 int ret;
3469
3470 if (!bgp || !vpn)
3471 return CMD_WARNING;
3472
3473 ret = str2prefix_rd(argv[2]->arg, &prd);
3474 if (!ret) {
3475 vty_out(vty, "%% Malformed Route Distinguisher\n");
3476 return CMD_WARNING;
3477 }
3478
3479 /* Check if we should disallow. */
3480 if (!is_rd_configured(vpn)) {
3481 vty_out(vty, "%% RD is not configured for this VNI\n");
3482 return CMD_WARNING;
3483 }
3484
3485 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
3486 vty_out(vty,
3487 "%% RD specified does not match configuration for this VNI\n");
3488 return CMD_WARNING;
3489 }
3490
3491 evpn_unconfigure_rd(bgp, vpn);
3492 return CMD_SUCCESS;
3493 }
3494
3495 DEFUN (no_bgp_evpn_vni_rd_without_val,
3496 no_bgp_evpn_vni_rd_without_val_cmd,
3497 "no rd",
3498 NO_STR
3499 "Route Distinguisher\n")
3500 {
3501 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3502 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3503
3504 if (!bgp || !vpn)
3505 return CMD_WARNING;
3506
3507 /* Check if we should disallow. */
3508 if (!is_rd_configured(vpn)) {
3509 vty_out(vty, "%% RD is not configured for this VNI\n");
3510 return CMD_WARNING;
3511 }
3512
3513 evpn_unconfigure_rd(bgp, vpn);
3514 return CMD_SUCCESS;
3515 }
3516
3517 /*
3518 * Loop over all extended-communities in the route-target list rtl and
3519 * return 1 if we find ecomtarget
3520 */
3521 static int bgp_evpn_rt_matches_existing(struct list *rtl,
3522 struct ecommunity *ecomtarget)
3523 {
3524 struct listnode *node, *nnode;
3525 struct ecommunity *ecom;
3526
3527 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
3528 if (ecommunity_match(ecom, ecomtarget))
3529 return 1;
3530 }
3531
3532 return 0;
3533 }
3534
3535 /* display L3VNI related info for a VRF instance */
3536 DEFUN (show_bgp_vrf_l3vni_info,
3537 show_bgp_vrf_l3vni_info_cmd,
3538 "show bgp vrf VRFNAME l3vni info [json]",
3539 SHOW_STR
3540 BGP_STR
3541 "show bgp vrf\n"
3542 "VRF Name\n"
3543 "L3-VNI\n"
3544 "L3-VNI info\n"
3545 JSON_STR)
3546 {
3547 char buf[ETHER_ADDR_STRLEN];
3548 char buf1[INET6_ADDRSTRLEN];
3549 int idx_vrf = 3;
3550 const char *name = NULL;
3551 struct bgp *bgp = NULL;
3552 struct listnode *node = NULL;
3553 struct bgpevpn *vpn = NULL;
3554 struct ecommunity *ecom = NULL;
3555 json_object *json = NULL;
3556 json_object *json_vnis = NULL;
3557 json_object *json_export_rts = NULL;
3558 json_object *json_import_rts = NULL;
3559 u_char uj = use_json(argc, argv);
3560
3561 if (uj) {
3562 json = json_object_new_object();
3563 json_vnis = json_object_new_array();
3564 json_export_rts = json_object_new_array();
3565 json_import_rts = json_object_new_array();
3566 }
3567
3568 name = argv[idx_vrf]->arg;
3569 bgp = bgp_lookup_by_name(name);
3570 if (!bgp) {
3571 if (!uj)
3572 vty_out(vty, "BGP instance for VRF %s not found",
3573 name);
3574 else {
3575 json_object_string_add(json, "warning",
3576 "BGP instance not found");
3577 vty_out(vty, "%s\n",
3578 json_object_to_json_string(json));
3579 json_object_free(json);
3580 }
3581 return CMD_WARNING;
3582 }
3583
3584 if (!json) {
3585 vty_out(vty, "BGP VRF: %s\n", name);
3586 vty_out(vty, " Local-Ip: %s\n",
3587 inet_ntoa(bgp->originator_ip));
3588 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
3589 vty_out(vty, " Rmac: %s\n",
3590 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
3591 vty_out(vty, " L2-VNI List:\n");
3592 vty_out(vty, " ");
3593 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3594 vty_out(vty, "%u ", vpn->vni);
3595 vty_out(vty, "\n");
3596 vty_out(vty, " Export-RTs:\n");
3597 vty_out(vty, " ");
3598 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3599 vty_out(vty, "%s ", ecommunity_str(ecom));
3600 vty_out(vty, "\n");
3601 vty_out(vty, " Import-RTs:\n");
3602 vty_out(vty, " ");
3603 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3604 vty_out(vty, "%s ", ecommunity_str(ecom));
3605 vty_out(vty, "\n");
3606 vty_out(vty, " RD: %s\n",
3607 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
3608 } else {
3609 json_object_string_add(json, "vrf", name);
3610 json_object_string_add(json, "local-ip",
3611 inet_ntoa(bgp->originator_ip));
3612 json_object_int_add(json, "l3vni", bgp->l3vni);
3613 json_object_string_add(json, "rmac",
3614 prefix_mac2str(&bgp->rmac, buf,
3615 sizeof(buf)));
3616 /* list of l2vnis */
3617 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
3618 json_object_array_add(json_vnis,
3619 json_object_new_int(vpn->vni));
3620 json_object_object_add(json, "l2vnis", json_vnis);
3621
3622 /* export rts */
3623 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
3624 json_object_array_add(json_export_rts,
3625 json_object_new_string(
3626 ecommunity_str(ecom)));
3627 json_object_object_add(json, "export-rts", json_export_rts);
3628
3629 /* import rts */
3630 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
3631 json_object_array_add(json_import_rts,
3632 json_object_new_string(
3633 ecommunity_str(ecom)));
3634 json_object_object_add(json, "import-rts", json_import_rts);
3635 json_object_string_add(
3636 json, "rd",
3637 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
3638
3639 }
3640
3641 if (uj) {
3642 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3643 json, JSON_C_TO_STRING_PRETTY));
3644 json_object_free(json);
3645 }
3646 return CMD_SUCCESS;
3647 }
3648
3649 /* import/export rt for l3vni-vrf */
3650 DEFUN (bgp_evpn_vrf_rt,
3651 bgp_evpn_vrf_rt_cmd,
3652 "route-target <both|import|export> RT",
3653 "Route Target\n"
3654 "import and export\n"
3655 "import\n"
3656 "export\n"
3657 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3658 {
3659 int rt_type;
3660 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3661 struct ecommunity *ecomadd = NULL;
3662
3663 if (!bgp)
3664 return CMD_WARNING;
3665
3666 if (!strcmp(argv[1]->arg, "import"))
3667 rt_type = RT_TYPE_IMPORT;
3668 else if (!strcmp(argv[1]->arg, "export"))
3669 rt_type = RT_TYPE_EXPORT;
3670 else if (!strcmp(argv[1]->arg, "both"))
3671 rt_type = RT_TYPE_BOTH;
3672 else {
3673 vty_out(vty, "%% Invalid Route Target type\n");
3674 return CMD_WARNING;
3675 }
3676
3677 /* Add/update the import route-target */
3678 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3679 ecomadd = ecommunity_str2com(argv[2]->arg,
3680 ECOMMUNITY_ROUTE_TARGET, 0);
3681 if (!ecomadd) {
3682 vty_out(vty, "%% Malformed Route Target list\n");
3683 return CMD_WARNING;
3684 }
3685 ecommunity_str(ecomadd);
3686
3687 /* Do nothing if we already have this import route-target */
3688 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3689 ecomadd))
3690 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
3691 }
3692
3693 /* Add/update the export route-target */
3694 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3695 ecomadd = ecommunity_str2com(argv[2]->arg,
3696 ECOMMUNITY_ROUTE_TARGET, 0);
3697 if (!ecomadd) {
3698 vty_out(vty, "%% Malformed Route Target list\n");
3699 return CMD_WARNING;
3700 }
3701 ecommunity_str(ecomadd);
3702
3703 /* Do nothing if we already have this export route-target */
3704 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3705 ecomadd))
3706 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
3707 }
3708
3709 return CMD_SUCCESS;
3710 }
3711
3712 DEFUN (no_bgp_evpn_vrf_rt,
3713 no_bgp_evpn_vrf_rt_cmd,
3714 "no route-target <both|import|export> RT",
3715 NO_STR
3716 "Route Target\n"
3717 "import and export\n"
3718 "import\n"
3719 "export\n"
3720 "ASN:XX or A.B.C.D:XX\n")
3721 {
3722 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3723 int rt_type, found_ecomdel;
3724 struct ecommunity *ecomdel = NULL;
3725
3726 if (!bgp)
3727 return CMD_WARNING;
3728
3729 if (!strcmp(argv[2]->arg, "import"))
3730 rt_type = RT_TYPE_IMPORT;
3731 else if (!strcmp(argv[2]->arg, "export"))
3732 rt_type = RT_TYPE_EXPORT;
3733 else if (!strcmp(argv[2]->arg, "both"))
3734 rt_type = RT_TYPE_BOTH;
3735 else {
3736 vty_out(vty, "%% Invalid Route Target type\n");
3737 return CMD_WARNING;
3738 }
3739
3740 if (rt_type == RT_TYPE_IMPORT) {
3741 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
3742 vty_out(vty,
3743 "%% Import RT is not configured for this VRF\n");
3744 return CMD_WARNING;
3745 }
3746 } else if (rt_type == RT_TYPE_EXPORT) {
3747 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
3748 vty_out(vty,
3749 "%% Export RT is not configured for this VRF\n");
3750 return CMD_WARNING;
3751 }
3752 } else if (rt_type == RT_TYPE_BOTH) {
3753 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
3754 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
3755 vty_out(vty,
3756 "%% Import/Export RT is not configured for this VRF\n");
3757 return CMD_WARNING;
3758 }
3759 }
3760
3761 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
3762 if (!ecomdel) {
3763 vty_out(vty, "%% Malformed Route Target list\n");
3764 return CMD_WARNING;
3765 }
3766 ecommunity_str(ecomdel);
3767
3768 if (rt_type == RT_TYPE_IMPORT) {
3769 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3770 ecomdel)) {
3771 vty_out(vty,
3772 "%% RT specified does not match configuration for this VRF\n");
3773 return CMD_WARNING;
3774 }
3775 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
3776 } else if (rt_type == RT_TYPE_EXPORT) {
3777 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3778 ecomdel)) {
3779 vty_out(vty,
3780 "%% RT specified does not match configuration for this VRF\n");
3781 return CMD_WARNING;
3782 }
3783 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
3784 } else if (rt_type == RT_TYPE_BOTH) {
3785 found_ecomdel = 0;
3786
3787 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
3788 ecomdel)) {
3789 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
3790 found_ecomdel = 1;
3791 }
3792
3793 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
3794 ecomdel)) {
3795 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
3796 found_ecomdel = 1;
3797 }
3798
3799 if (!found_ecomdel) {
3800 vty_out(vty,
3801 "%% RT specified does not match configuration for this VRF\n");
3802 return CMD_WARNING;
3803 }
3804 }
3805
3806 return CMD_SUCCESS;
3807 }
3808
3809 DEFUN (bgp_evpn_vni_rt,
3810 bgp_evpn_vni_rt_cmd,
3811 "route-target <both|import|export> RT",
3812 "Route Target\n"
3813 "import and export\n"
3814 "import\n"
3815 "export\n"
3816 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3817 {
3818 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3819 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3820 int rt_type;
3821 struct ecommunity *ecomadd = NULL;
3822
3823 if (!bgp || !vpn)
3824 return CMD_WARNING;
3825
3826 if (!strcmp(argv[1]->text, "import"))
3827 rt_type = RT_TYPE_IMPORT;
3828 else if (!strcmp(argv[1]->text, "export"))
3829 rt_type = RT_TYPE_EXPORT;
3830 else if (!strcmp(argv[1]->text, "both"))
3831 rt_type = RT_TYPE_BOTH;
3832 else {
3833 vty_out(vty, "%% Invalid Route Target type\n");
3834 return CMD_WARNING;
3835 }
3836
3837 /* Add/update the import route-target */
3838 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
3839 ecomadd = ecommunity_str2com(argv[2]->arg,
3840 ECOMMUNITY_ROUTE_TARGET, 0);
3841 if (!ecomadd) {
3842 vty_out(vty, "%% Malformed Route Target list\n");
3843 return CMD_WARNING;
3844 }
3845 ecommunity_str(ecomadd);
3846
3847 /* Do nothing if we already have this import route-target */
3848 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
3849 evpn_configure_import_rt(bgp, vpn, ecomadd);
3850 }
3851
3852 /* Add/update the export route-target */
3853 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
3854 ecomadd = ecommunity_str2com(argv[2]->arg,
3855 ECOMMUNITY_ROUTE_TARGET, 0);
3856 if (!ecomadd) {
3857 vty_out(vty, "%% Malformed Route Target list\n");
3858 return CMD_WARNING;
3859 }
3860 ecommunity_str(ecomadd);
3861
3862 /* Do nothing if we already have this export route-target */
3863 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
3864 evpn_configure_export_rt(bgp, vpn, ecomadd);
3865 }
3866
3867 return CMD_SUCCESS;
3868 }
3869
3870 DEFUN (no_bgp_evpn_vni_rt,
3871 no_bgp_evpn_vni_rt_cmd,
3872 "no route-target <both|import|export> RT",
3873 NO_STR
3874 "Route Target\n"
3875 "import and export\n"
3876 "import\n"
3877 "export\n"
3878 "ASN:XX or A.B.C.D:XX\n")
3879 {
3880 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3881 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3882 int rt_type, found_ecomdel;
3883 struct ecommunity *ecomdel = NULL;
3884
3885 if (!bgp || !vpn)
3886 return CMD_WARNING;
3887
3888 if (!strcmp(argv[2]->text, "import"))
3889 rt_type = RT_TYPE_IMPORT;
3890 else if (!strcmp(argv[2]->text, "export"))
3891 rt_type = RT_TYPE_EXPORT;
3892 else if (!strcmp(argv[2]->text, "both"))
3893 rt_type = RT_TYPE_BOTH;
3894 else {
3895 vty_out(vty, "%% Invalid Route Target type\n");
3896 return CMD_WARNING;
3897 }
3898
3899 /* The user did "no route-target import", check to see if there are any
3900 * import route-targets configured. */
3901 if (rt_type == RT_TYPE_IMPORT) {
3902 if (!is_import_rt_configured(vpn)) {
3903 vty_out(vty,
3904 "%% Import RT is not configured for this VNI\n");
3905 return CMD_WARNING;
3906 }
3907 } else if (rt_type == RT_TYPE_EXPORT) {
3908 if (!is_export_rt_configured(vpn)) {
3909 vty_out(vty,
3910 "%% Export RT is not configured for this VNI\n");
3911 return CMD_WARNING;
3912 }
3913 } else if (rt_type == RT_TYPE_BOTH) {
3914 if (!is_import_rt_configured(vpn)
3915 && !is_export_rt_configured(vpn)) {
3916 vty_out(vty,
3917 "%% Import/Export RT is not configured for this VNI\n");
3918 return CMD_WARNING;
3919 }
3920 }
3921
3922 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
3923 if (!ecomdel) {
3924 vty_out(vty, "%% Malformed Route Target list\n");
3925 return CMD_WARNING;
3926 }
3927 ecommunity_str(ecomdel);
3928
3929 if (rt_type == RT_TYPE_IMPORT) {
3930 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3931 vty_out(vty,
3932 "%% RT specified does not match configuration for this VNI\n");
3933 return CMD_WARNING;
3934 }
3935 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3936 } else if (rt_type == RT_TYPE_EXPORT) {
3937 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3938 vty_out(vty,
3939 "%% RT specified does not match configuration for this VNI\n");
3940 return CMD_WARNING;
3941 }
3942 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3943 } else if (rt_type == RT_TYPE_BOTH) {
3944 found_ecomdel = 0;
3945
3946 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
3947 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
3948 found_ecomdel = 1;
3949 }
3950
3951 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
3952 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
3953 found_ecomdel = 1;
3954 }
3955
3956 if (!found_ecomdel) {
3957 vty_out(vty,
3958 "%% RT specified does not match configuration for this VNI\n");
3959 return CMD_WARNING;
3960 }
3961 }
3962
3963 return CMD_SUCCESS;
3964 }
3965
3966 DEFUN (no_bgp_evpn_vni_rt_without_val,
3967 no_bgp_evpn_vni_rt_without_val_cmd,
3968 "no route-target <import|export>",
3969 NO_STR
3970 "Route Target\n"
3971 "import\n"
3972 "export\n")
3973 {
3974 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3975 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3976 int rt_type;
3977
3978 if (!bgp || !vpn)
3979 return CMD_WARNING;
3980
3981 if (!strcmp(argv[2]->text, "import")) {
3982 rt_type = RT_TYPE_IMPORT;
3983 } else if (!strcmp(argv[2]->text, "export")) {
3984 rt_type = RT_TYPE_EXPORT;
3985 } else {
3986 vty_out(vty, "%% Invalid Route Target type\n");
3987 return CMD_WARNING;
3988 }
3989
3990 /* Check if we should disallow. */
3991 if (rt_type == RT_TYPE_IMPORT) {
3992 if (!is_import_rt_configured(vpn)) {
3993 vty_out(vty,
3994 "%% Import RT is not configured for this VNI\n");
3995 return CMD_WARNING;
3996 }
3997 } else {
3998 if (!is_export_rt_configured(vpn)) {
3999 vty_out(vty,
4000 "%% Export RT is not configured for this VNI\n");
4001 return CMD_WARNING;
4002 }
4003 }
4004
4005 /* Unconfigure the RT. */
4006 if (rt_type == RT_TYPE_IMPORT)
4007 evpn_unconfigure_import_rt(bgp, vpn, NULL);
4008 else
4009 evpn_unconfigure_export_rt(bgp, vpn, NULL);
4010 return CMD_SUCCESS;
4011 }
4012 #endif
4013 /*
4014 * Output EVPN configuration information.
4015 */
4016 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
4017 safi_t safi)
4018 {
4019 if (bgp->vnihash)
4020 hash_iterate(bgp->vnihash,
4021 (void (*)(struct hash_backet *,
4022 void *))write_vni_config_for_entry,
4023 vty);
4024
4025 if (bgp->advertise_all_vni)
4026 vty_out(vty, " advertise-all-vni\n");
4027
4028 if (bgp->advertise_gw_macip)
4029 vty_out(vty, " advertise-default-gw\n");
4030 }
4031
4032 void bgp_ethernetvpn_init(void)
4033 {
4034 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
4035 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
4036 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
4037 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
4038 install_element(VIEW_NODE,
4039 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd);
4040 install_element(VIEW_NODE,
4041 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
4042 install_element(
4043 VIEW_NODE,
4044 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd);
4045 install_element(
4046 VIEW_NODE,
4047 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
4048 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
4049 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
4050 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
4051 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
4052 #if defined(HAVE_CUMULUS)
4053 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
4054 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
4055 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
4056 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
4057 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
4058 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
4059
4060 /* "show bgp l2vpn evpn" commands. */
4061 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
4062 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
4063 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
4064 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
4065 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
4066 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
4067 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vrf_cmd);
4068 install_element(VIEW_NODE,
4069 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
4070 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
4071 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
4072 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
4073 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
4074
4075 /* "show bgp evpn" commands. */
4076 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
4077 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
4078 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
4079 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
4080 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
4081 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
4082 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
4083 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
4084 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
4085 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
4086 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
4087
4088 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
4089 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
4090 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
4091 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
4092 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
4093 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
4094 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
4095 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
4096 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
4097 install_element(BGP_NODE, &bgp_evpn_vrf_rd_cmd);
4098 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_cmd);
4099 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
4100 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
4101 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
4102 install_element(BGP_EVPN_VNI_NODE,
4103 &bgp_evpn_advertise_default_gw_vni_cmd);
4104 install_element(BGP_EVPN_VNI_NODE,
4105 &no_bgp_evpn_advertise_default_gw_vni_cmd);
4106 #endif
4107 }