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