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