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