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