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