]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
*: auto-convert to SPDX License IDs
[mirror_frr.git] / bgpd / bgp_evpn_vty.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Ethernet-VPN Packet and vty Processing File
3 * Copyright (C) 2017 6WIND
4 *
5 * This file is part of FRRouting
6 */
7
8 #include <zebra.h>
9 #include "command.h"
10 #include "prefix.h"
11 #include "lib/json.h"
12 #include "lib/printfrr.h"
13 #include "lib/vxlan.h"
14 #include "stream.h"
15
16 #include "bgpd/bgpd.h"
17 #include "bgpd/bgp_table.h"
18 #include "bgpd/bgp_attr.h"
19 #include "bgpd/bgp_route.h"
20 #include "bgpd/bgp_mplsvpn.h"
21 #include "bgpd/bgp_vpn.h"
22 #include "bgpd/bgp_evpn_vty.h"
23 #include "bgpd/bgp_evpn.h"
24 #include "bgpd/bgp_evpn_private.h"
25 #include "bgpd/bgp_evpn_mh.h"
26 #include "bgpd/bgp_zebra.h"
27 #include "bgpd/bgp_vty.h"
28 #include "bgpd/bgp_errors.h"
29 #include "bgpd/bgp_ecommunity.h"
30 #include "bgpd/bgp_lcommunity.h"
31 #include "bgpd/bgp_community.h"
32
33 #define SHOW_DISPLAY_STANDARD 0
34 #define SHOW_DISPLAY_TAGS 1
35 #define SHOW_DISPLAY_OVERLAY 2
36 #define VNI_STR_LEN 32
37
38 /*
39 * Context for VNI hash walk - used by callbacks.
40 */
41 struct vni_walk_ctx {
42 struct bgp *bgp;
43 struct vty *vty;
44 struct in_addr vtep_ip;
45 json_object *json;
46 int detail;
47 int type;
48 bool mac_table;
49 };
50
51 int argv_find_and_parse_oly_idx(struct cmd_token **argv, int argc, int *oly_idx,
52 enum overlay_index_type *oly)
53 {
54 *oly = OVERLAY_INDEX_TYPE_NONE;
55 if (argv_find(argv, argc, "gateway-ip", oly_idx))
56 *oly = OVERLAY_INDEX_GATEWAY_IP;
57 return 1;
58 }
59
60 static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
61 json_object *json)
62 {
63 const uint8_t *pnt;
64 uint8_t type, sub_type;
65 struct ecommunity_as eas;
66 struct ecommunity_ip eip;
67 struct listnode *node, *nnode;
68 struct bgp *tmp_bgp_vrf = NULL;
69 json_object *json_rt = NULL;
70 json_object *json_vrfs = NULL;
71 char rt_buf[RT_ADDRSTRLEN];
72
73 if (json) {
74 json_rt = json_object_new_object();
75 json_vrfs = json_object_new_array();
76 }
77
78 pnt = (uint8_t *)&irt->rt.val;
79 type = *pnt++;
80 sub_type = *pnt++;
81 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
82 return;
83
84 memset(&eas, 0, sizeof(eas));
85 switch (type) {
86 case ECOMMUNITY_ENCODE_AS:
87 eas.as = (*pnt++ << 8);
88 eas.as |= (*pnt++);
89 ptr_get_be32(pnt, &eas.val);
90
91 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
92
93 if (json)
94 json_object_string_add(json_rt, "rt", rt_buf);
95 else
96 vty_out(vty, "Route-target: %s", rt_buf);
97
98 break;
99
100 case ECOMMUNITY_ENCODE_IP:
101 memcpy(&eip.ip, pnt, 4);
102 pnt += 4;
103 eip.val = (*pnt++ << 8);
104 eip.val |= (*pnt++);
105
106 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
107
108 if (json)
109 json_object_string_add(json_rt, "rt", rt_buf);
110 else
111 vty_out(vty, "Route-target: %s", rt_buf);
112
113 break;
114
115 case ECOMMUNITY_ENCODE_AS4:
116 pnt = ptr_get_be32(pnt, &eas.val);
117 eas.val = (*pnt++ << 8);
118 eas.val |= (*pnt++);
119
120 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
121
122 if (json)
123 json_object_string_add(json_rt, "rt", rt_buf);
124 else
125 vty_out(vty, "Route-target: %s", rt_buf);
126
127 break;
128
129 default:
130 return;
131 }
132
133 if (!json) {
134 vty_out(vty,
135 "\nList of VRFs importing routes with this route-target:\n");
136 }
137
138 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
139 if (json)
140 json_object_array_add(
141 json_vrfs,
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
144 else
145 vty_out(vty, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
147 }
148
149 if (json) {
150 json_object_object_add(json_rt, "vrfs", json_vrfs);
151 json_object_object_add(json, rt_buf, json_rt);
152 }
153 }
154
155 static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
156 {
157 json_object *json = NULL;
158 struct vty *vty = NULL;
159 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
160
161 vty = (struct vty *)args[0];
162 json = (struct json_object *)args[1];
163
164 display_vrf_import_rt(vty, irt, json);
165 }
166
167 static void display_import_rt(struct vty *vty, struct irt_node *irt,
168 json_object *json)
169 {
170 const uint8_t *pnt;
171 uint8_t type, sub_type;
172 struct ecommunity_as eas;
173 struct ecommunity_ip eip;
174 struct listnode *node, *nnode;
175 struct bgpevpn *tmp_vpn;
176 json_object *json_rt = NULL;
177 json_object *json_vnis = NULL;
178 char rt_buf[RT_ADDRSTRLEN];
179
180 if (json) {
181 json_rt = json_object_new_object();
182 json_vnis = json_object_new_array();
183 }
184
185 /* TODO: This needs to go into a function */
186
187 pnt = (uint8_t *)&irt->rt.val;
188 type = *pnt++;
189 sub_type = *pnt++;
190 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191 return;
192
193 memset(&eas, 0, sizeof(eas));
194 switch (type) {
195 case ECOMMUNITY_ENCODE_AS:
196 eas.as = (*pnt++ << 8);
197 eas.as |= (*pnt++);
198 ptr_get_be32(pnt, &eas.val);
199
200 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
201
202 if (json)
203 json_object_string_add(json_rt, "rt", rt_buf);
204 else
205 vty_out(vty, "Route-target: %s", rt_buf);
206
207 break;
208
209 case ECOMMUNITY_ENCODE_IP:
210 memcpy(&eip.ip, pnt, 4);
211 pnt += 4;
212 eip.val = (*pnt++ << 8);
213 eip.val |= (*pnt++);
214
215 snprintfrr(rt_buf, sizeof(rt_buf), "%pI4:%u", &eip.ip, eip.val);
216
217 if (json)
218 json_object_string_add(json_rt, "rt", rt_buf);
219 else
220 vty_out(vty, "Route-target: %s", rt_buf);
221
222 break;
223
224 case ECOMMUNITY_ENCODE_AS4:
225 pnt = ptr_get_be32(pnt, &eas.val);
226 eas.val = (*pnt++ << 8);
227 eas.val |= (*pnt++);
228
229 snprintf(rt_buf, sizeof(rt_buf), "%u:%u", eas.as, eas.val);
230
231 if (json)
232 json_object_string_add(json_rt, "rt", rt_buf);
233 else
234 vty_out(vty, "Route-target: %s", rt_buf);
235
236 break;
237
238 default:
239 return;
240 }
241
242 if (!json) {
243 vty_out(vty,
244 "\nList of VNIs importing routes with this route-target:\n");
245 }
246
247 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
248 if (json)
249 json_object_array_add(
250 json_vnis, json_object_new_int(tmp_vpn->vni));
251 else
252 vty_out(vty, " %u\n", tmp_vpn->vni);
253 }
254
255 if (json) {
256 json_object_object_add(json_rt, "vnis", json_vnis);
257 json_object_object_add(json, rt_buf, json_rt);
258 }
259 }
260
261 static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
262 {
263 json_object *json = NULL;
264 struct vty *vty = NULL;
265 struct irt_node *irt = (struct irt_node *)bucket->data;
266
267 vty = args[0];
268 json = args[1];
269
270 display_import_rt(vty, irt, json);
271
272 return;
273 }
274
275 static void bgp_evpn_show_route_rd_header(struct vty *vty,
276 struct bgp_dest *rd_dest,
277 json_object *json, char *rd_str,
278 int len)
279 {
280 uint16_t type;
281 struct rd_as rd_as;
282 struct rd_ip rd_ip;
283 const uint8_t *pnt;
284 const struct prefix *p = bgp_dest_get_prefix(rd_dest);
285
286 pnt = p->u.val;
287
288 /* Decode RD type. */
289 type = decode_rd_type(pnt);
290
291 if (!json)
292 vty_out(vty, "Route Distinguisher: ");
293
294 switch (type) {
295 case RD_TYPE_AS:
296 decode_rd_as(pnt + 2, &rd_as);
297 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
298 if (json)
299 json_object_string_add(json, "rd", rd_str);
300 else
301 vty_out(vty, "%s\n", rd_str);
302 break;
303
304 case RD_TYPE_AS4:
305 decode_rd_as4(pnt + 2, &rd_as);
306 snprintf(rd_str, len, "%u:%d", rd_as.as, rd_as.val);
307 if (json)
308 json_object_string_add(json, "rd", rd_str);
309 else
310 vty_out(vty, "%s\n", rd_str);
311 break;
312
313 case RD_TYPE_IP:
314 decode_rd_ip(pnt + 2, &rd_ip);
315 snprintfrr(rd_str, len, "%pI4:%d", &rd_ip.ip, rd_ip.val);
316 if (json)
317 json_object_string_add(json, "rd", rd_str);
318 else
319 vty_out(vty, "%s\n", rd_str);
320 break;
321
322 default:
323 if (json) {
324 snprintf(rd_str, len, "Unknown");
325 json_object_string_add(json, "rd", rd_str);
326 } else {
327 snprintf(rd_str, len, "Unknown RD type");
328 vty_out(vty, "%s\n", rd_str);
329 }
330 break;
331 }
332 }
333
334 static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
335 uint64_t tbl_ver, json_object *json)
336 {
337 char ri_header[] =
338 " Network Next Hop Metric LocPrf Weight Path\n";
339
340 if (json)
341 return;
342
343 vty_out(vty,
344 "BGP table version is %" PRIu64 ", local router ID is %pI4\n",
345 tbl_ver, &bgp->router_id);
346 vty_out(vty,
347 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
348 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
349 vty_out(vty,
350 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
351 vty_out(vty,
352 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
353 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
354 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
355 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
356 vty_out(vty, "%s", ri_header);
357 }
358
359 static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
360 json_object *json)
361 {
362 char *ecom_str;
363 struct listnode *node, *nnode;
364 struct vrf_route_target *l3rt;
365 json_object *json_import_rtl = NULL;
366 json_object *json_export_rtl = NULL;
367 char buf2[ETHER_ADDR_STRLEN];
368
369 json_import_rtl = json_export_rtl = 0;
370
371 if (json) {
372 json_import_rtl = json_object_new_array();
373 json_export_rtl = json_object_new_array();
374 json_object_int_add(json, "vni", bgp_vrf->l3vni);
375 json_object_string_add(json, "type", "L3");
376 json_object_string_add(json, "inKernel", "True");
377 json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
378 json_object_string_addf(json, "originatorIp", "%pI4",
379 &bgp_vrf->originator_ip);
380 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
381 json_object_string_add(json, "advertiseSviMacIp", "n/a");
382 json_object_string_add(json, "advertisePip",
383 bgp_vrf->evpn_info->advertise_pip ?
384 "Enabled" : "Disabled");
385 json_object_string_addf(json, "sysIP", "%pI4",
386 &bgp_vrf->evpn_info->pip_ip);
387 json_object_string_add(json, "sysMac",
388 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
389 buf2, sizeof(buf2)));
390 json_object_string_add(json, "rmac",
391 prefix_mac2str(&bgp_vrf->rmac,
392 buf2, sizeof(buf2)));
393 } else {
394 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
395 vty_out(vty, " (known to the kernel)");
396 vty_out(vty, "\n");
397
398 vty_out(vty, " Type: %s\n", "L3");
399 vty_out(vty, " Tenant VRF: %s\n",
400 vrf_id_to_name(bgp_vrf->vrf_id));
401 vty_out(vty, " RD: %pRD\n", &bgp_vrf->vrf_prd);
402 vty_out(vty, " Originator IP: %pI4\n",
403 &bgp_vrf->originator_ip);
404 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
405 vty_out(vty, " Advertise-svi-macip : %s\n", "n/a");
406 vty_out(vty, " Advertise-pip: %s\n",
407 bgp_vrf->evpn_info->advertise_pip ? "Yes" : "No");
408 vty_out(vty, " System-IP: %pI4\n",
409 &bgp_vrf->evpn_info->pip_ip);
410 vty_out(vty, " System-MAC: %s\n",
411 prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
412 buf2, sizeof(buf2)));
413 vty_out(vty, " Router-MAC: %s\n",
414 prefix_mac2str(&bgp_vrf->rmac,
415 buf2, sizeof(buf2)));
416 }
417
418 if (!json)
419 vty_out(vty, " Import Route Target:\n");
420
421 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, l3rt)) {
422 ecom_str = ecommunity_ecom2str(l3rt->ecom,
423 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
424
425 if (json)
426 json_object_array_add(json_import_rtl,
427 json_object_new_string(ecom_str));
428 else
429 vty_out(vty, " %s\n", ecom_str);
430
431 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
432 }
433
434 if (json)
435 json_object_object_add(json, "importRts", json_import_rtl);
436 else
437 vty_out(vty, " Export Route Target:\n");
438
439 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, l3rt)) {
440 ecom_str = ecommunity_ecom2str(l3rt->ecom,
441 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
442
443 if (json)
444 json_object_array_add(json_export_rtl,
445 json_object_new_string(ecom_str));
446 else
447 vty_out(vty, " %s\n", ecom_str);
448
449 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
450 }
451
452 if (json)
453 json_object_object_add(json, "exportRts", json_export_rtl);
454 }
455
456 static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
457 {
458 char *ecom_str;
459 struct listnode *node, *nnode;
460 struct ecommunity *ecom;
461 json_object *json_import_rtl = NULL;
462 json_object *json_export_rtl = NULL;
463 struct bgp *bgp_evpn;
464
465 bgp_evpn = bgp_get_evpn();
466
467 if (json) {
468 json_import_rtl = json_object_new_array();
469 json_export_rtl = json_object_new_array();
470 json_object_int_add(json, "vni", vpn->vni);
471 json_object_string_add(json, "type", "L2");
472 json_object_string_add(json, "inKernel",
473 is_vni_live(vpn) ? "True" : "False");
474 json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
475 json_object_string_addf(json, "originatorIp", "%pI4",
476 &vpn->originator_ip);
477 json_object_string_addf(json, "mcastGroup", "%pI4",
478 &vpn->mcast_grp);
479 /* per vni knob is enabled -- Enabled
480 * Global knob is enabled -- Active
481 * default -- Disabled
482 */
483 if (!vpn->advertise_gw_macip &&
484 bgp_evpn && bgp_evpn->advertise_gw_macip)
485 json_object_string_add(json, "advertiseGatewayMacip",
486 "Active");
487 else if (vpn->advertise_gw_macip)
488 json_object_string_add(json, "advertiseGatewayMacip",
489 "Enabled");
490 else
491 json_object_string_add(json, "advertiseGatewayMacip",
492 "Disabled");
493 if (!vpn->advertise_svi_macip && bgp_evpn &&
494 bgp_evpn->evpn_info->advertise_svi_macip)
495 json_object_string_add(json, "advertiseSviMacIp",
496 "Active");
497 else if (vpn->advertise_svi_macip)
498 json_object_string_add(json, "advertiseSviMacIp",
499 "Enabled");
500 else
501 json_object_string_add(json, "advertiseSviMacIp",
502 "Disabled");
503 json_object_string_add(
504 json, "sviInterface",
505 ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
506 } else {
507 vty_out(vty, "VNI: %u", vpn->vni);
508 if (is_vni_live(vpn))
509 vty_out(vty, " (known to the kernel)");
510 vty_out(vty, "\n");
511
512 vty_out(vty, " Type: %s\n", "L2");
513 vty_out(vty, " Tenant-Vrf: %s\n",
514 vrf_id_to_name(vpn->tenant_vrf_id));
515 vty_out(vty, " RD: %pRD\n", &vpn->prd);
516 vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip);
517 vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp);
518 if (!vpn->advertise_gw_macip &&
519 bgp_evpn && bgp_evpn->advertise_gw_macip)
520 vty_out(vty, " Advertise-gw-macip : %s\n",
521 "Active");
522 else if (vpn->advertise_gw_macip)
523 vty_out(vty, " Advertise-gw-macip : %s\n",
524 "Enabled");
525 else
526 vty_out(vty, " Advertise-gw-macip : %s\n",
527 "Disabled");
528 if (!vpn->advertise_svi_macip && bgp_evpn &&
529 bgp_evpn->evpn_info->advertise_svi_macip)
530 vty_out(vty, " Advertise-svi-macip : %s\n",
531 "Active");
532 else if (vpn->advertise_svi_macip)
533 vty_out(vty, " Advertise-svi-macip : %s\n",
534 "Enabled");
535 else
536 vty_out(vty, " Advertise-svi-macip : %s\n",
537 "Disabled");
538 vty_out(vty, " SVI interface : %s\n",
539 ifindex2ifname(vpn->svi_ifindex, vpn->tenant_vrf_id));
540 }
541
542 if (!json)
543 vty_out(vty, " Import Route Target:\n");
544
545 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
546 ecom_str = ecommunity_ecom2str(ecom,
547 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
548
549 if (json)
550 json_object_array_add(json_import_rtl,
551 json_object_new_string(ecom_str));
552 else
553 vty_out(vty, " %s\n", ecom_str);
554
555 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
556 }
557
558 if (json)
559 json_object_object_add(json, "importRts", json_import_rtl);
560 else
561 vty_out(vty, " Export Route Target:\n");
562
563 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
564 ecom_str = ecommunity_ecom2str(ecom,
565 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
566
567 if (json)
568 json_object_array_add(json_export_rtl,
569 json_object_new_string(ecom_str));
570 else
571 vty_out(vty, " %s\n", ecom_str);
572
573 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
574 }
575
576 if (json)
577 json_object_object_add(json, "exportRts", json_export_rtl);
578 }
579
580 static void show_esi_routes(struct bgp *bgp,
581 struct bgp_evpn_es *es,
582 struct vty *vty,
583 json_object *json)
584 {
585 int header = 1;
586 struct bgp_dest *dest;
587 struct bgp_path_info *pi;
588 uint32_t prefix_cnt, path_cnt;
589 uint64_t tbl_ver;
590
591 prefix_cnt = path_cnt = 0;
592
593 tbl_ver = es->route_table->version;
594 for (dest = bgp_table_top(es->route_table); dest;
595 dest = bgp_route_next(dest)) {
596 int add_prefix_to_json = 0;
597 json_object *json_paths = NULL;
598 json_object *json_prefix = NULL;
599 const struct prefix *p = bgp_dest_get_prefix(dest);
600
601 if (json)
602 json_prefix = json_object_new_object();
603
604 pi = bgp_dest_get_bgp_path_info(dest);
605 if (pi) {
606 /* Overall header/legend displayed once. */
607 if (header) {
608 bgp_evpn_show_route_header(vty, bgp,
609 tbl_ver, json);
610 header = 0;
611 }
612
613 prefix_cnt++;
614 }
615
616 if (json)
617 json_paths = json_object_new_array();
618
619 /* For EVPN, the prefix is displayed for each path (to fit in
620 * with code that already exists).
621 */
622 for (; pi; pi = pi->next) {
623 json_object *json_path = NULL;
624
625 if (json)
626 json_path = json_object_new_array();
627
628 route_vty_out(vty, p, pi, 0, SAFI_EVPN, json_path,
629 false);
630
631 if (json)
632 json_object_array_add(json_paths, json_path);
633
634 path_cnt++;
635 add_prefix_to_json = 1;
636 }
637
638 if (json) {
639 if (add_prefix_to_json) {
640 json_object_string_addf(json_prefix, "prefix",
641 "%pFX", p);
642 json_object_int_add(json_prefix, "prefixLen",
643 p->prefixlen);
644 json_object_object_add(json_prefix, "paths",
645 json_paths);
646 json_object_object_addf(json, json_prefix,
647 "%pFX", p);
648 } else {
649 json_object_free(json_paths);
650 json_object_free(json_prefix);
651 json_paths = NULL;
652 json_prefix = NULL;
653 }
654 }
655 }
656
657 if (json) {
658 json_object_int_add(json, "numPrefix", prefix_cnt);
659 json_object_int_add(json, "numPaths", path_cnt);
660 } else {
661 if (prefix_cnt == 0)
662 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
663 else
664 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
665 prefix_cnt, path_cnt);
666 }
667 }
668
669 /* Display all MAC-IP VNI routes linked to an ES */
670 static void bgp_evpn_show_routes_mac_ip_es(struct vty *vty, esi_t *esi,
671 json_object *json, int detail,
672 bool global_table)
673 {
674 struct bgp_node *rn;
675 struct bgp_path_info *pi;
676 int header = detail ? 0 : 1;
677 uint32_t path_cnt;
678 struct listnode *node;
679 struct bgp_evpn_es *es;
680 struct bgp_path_es_info *es_info;
681 struct bgp *bgp = bgp_get_evpn();
682 json_object *json_paths = NULL;
683
684 if (!bgp)
685 return;
686
687 path_cnt = 0;
688
689 if (json)
690 json_paths = json_object_new_array();
691
692 RB_FOREACH (es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
693 struct list *es_list;
694
695 if (esi && memcmp(esi, &es->esi, sizeof(*esi)))
696 continue;
697
698 if (global_table)
699 es_list = es->macip_global_path_list;
700 else
701 es_list = es->macip_evi_path_list;
702
703 for (ALL_LIST_ELEMENTS_RO(es_list, node, es_info)) {
704 json_object *json_path = NULL;
705
706 pi = es_info->pi;
707 rn = pi->net;
708
709 if (!CHECK_FLAG(pi->flags, BGP_PATH_VALID))
710 continue;
711
712 /* Overall header/legend displayed once. */
713 if (header) {
714 bgp_evpn_show_route_header(vty, bgp, 0, json);
715 header = 0;
716 }
717
718 path_cnt++;
719
720 if (json)
721 json_path = json_object_new_array();
722
723 if (detail)
724 route_vty_out_detail(
725 vty, bgp, rn, bgp_dest_get_prefix(rn),
726 pi, AFI_L2VPN, SAFI_EVPN,
727 RPKI_NOT_BEING_USED, json_path);
728 else
729 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
730 json_path, false);
731
732 if (json)
733 json_object_array_add(json_paths, json_path);
734 }
735 }
736
737 if (json) {
738 json_object_object_add(json, "paths", json_paths);
739 json_object_int_add(json, "numPaths", path_cnt);
740 } else {
741 if (path_cnt == 0)
742 vty_out(vty, "There are no MAC-IP ES paths");
743 else
744 vty_out(vty, "\nDisplayed %u paths\n", path_cnt);
745 vty_out(vty, "\n");
746 }
747 }
748
749 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty *vty, esi_t *esi,
750 json_object *json, int detail)
751 {
752 bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, false);
753 }
754
755 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty *vty, esi_t *esi,
756 json_object *json, int detail)
757 {
758 bgp_evpn_show_routes_mac_ip_es(vty, esi, json, detail, true);
759 }
760
761 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn,
762 struct vty *vty, int type, bool mac_table,
763 struct in_addr vtep_ip, json_object *json,
764 int detail)
765 {
766 struct bgp_dest *dest;
767 struct bgp_path_info *pi;
768 struct bgp_table *table;
769 int header = detail ? 0 : 1;
770 uint64_t tbl_ver;
771 uint32_t prefix_cnt, path_cnt;
772
773 prefix_cnt = path_cnt = 0;
774
775 if (mac_table)
776 table = vpn->mac_table;
777 else
778 table = vpn->ip_table;
779
780 tbl_ver = table->version;
781 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
782 const struct prefix_evpn *evp =
783 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
784 int add_prefix_to_json = 0;
785 json_object *json_paths = NULL;
786 json_object *json_prefix = NULL;
787 const struct prefix *p = bgp_dest_get_prefix(dest);
788
789 if (type && evp->prefix.route_type != type)
790 continue;
791
792 if (json)
793 json_prefix = json_object_new_object();
794
795 pi = bgp_dest_get_bgp_path_info(dest);
796 if (pi) {
797 /* Overall header/legend displayed once. */
798 if (header) {
799 bgp_evpn_show_route_header(vty, bgp,
800 tbl_ver, json);
801 header = 0;
802 }
803
804 prefix_cnt++;
805 }
806
807 if (json)
808 json_paths = json_object_new_array();
809
810 /* For EVPN, the prefix is displayed for each path (to fit in
811 * with code that already exists).
812 */
813 for (; pi; pi = pi->next) {
814 struct prefix tmp_p;
815 json_object *json_path = NULL;
816
817 if (vtep_ip.s_addr != INADDR_ANY
818 && !IPV4_ADDR_SAME(&(vtep_ip),
819 &(pi->attr->nexthop)))
820 continue;
821
822 if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
823 /*
824 * VNI IP/MAC table prefixes don't have MAC/IP
825 * respectively so make sure it's set from path
826 * info here.
827 */
828 if (is_evpn_prefix_ipaddr_none(evp)) {
829 /* VNI MAC -> Global */
830 evpn_type2_prefix_global_copy(
831 (struct prefix_evpn *)&tmp_p,
832 evp, NULL /* mac */,
833 evpn_type2_path_info_get_ip(
834 pi));
835 } else {
836 /* VNI IP -> Global */
837 evpn_type2_prefix_global_copy(
838 (struct prefix_evpn *)&tmp_p,
839 evp,
840 evpn_type2_path_info_get_mac(
841 pi),
842 NULL /* ip */);
843 }
844 } else
845 memcpy(&tmp_p, p, sizeof(tmp_p));
846
847
848 if (json)
849 json_path = json_object_new_array();
850
851 if (detail)
852 route_vty_out_detail(vty, bgp, dest, &tmp_p, pi,
853 AFI_L2VPN, SAFI_EVPN,
854 RPKI_NOT_BEING_USED,
855 json_path);
856
857 else
858 route_vty_out(vty, &tmp_p, pi, 0, SAFI_EVPN,
859 json_path, false);
860
861 if (json)
862 json_object_array_add(json_paths, json_path);
863
864 path_cnt++;
865 add_prefix_to_json = 1;
866 }
867
868 if (json) {
869 if (add_prefix_to_json) {
870 json_object_string_addf(json_prefix, "prefix",
871 "%pFX", p);
872 json_object_int_add(json_prefix, "prefixLen",
873 p->prefixlen);
874 json_object_object_add(json_prefix, "paths",
875 json_paths);
876 json_object_object_addf(json, json_prefix,
877 "%pFX", p);
878 } else {
879 json_object_free(json_paths);
880 json_object_free(json_prefix);
881 json_paths = NULL;
882 json_prefix = NULL;
883 }
884 }
885 }
886
887 if (json) {
888 json_object_int_add(json, "numPrefix", prefix_cnt);
889 json_object_int_add(json, "numPaths", path_cnt);
890 } else {
891 if (prefix_cnt == 0)
892 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
893 type ? "(of requested type) " : "");
894 else
895 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
896 prefix_cnt, path_cnt,
897 type ? " (of requested type)" : "");
898 vty_out(vty, "\n");
899 }
900 }
901
902 static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
903 {
904 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
905 struct vni_walk_ctx *wctx = arg;
906 struct vty *vty = wctx->vty;
907 json_object *json = wctx->json;
908 json_object *json_vni = NULL;
909 char vni_str[VNI_STR_LEN];
910
911 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
912 if (json) {
913 json_vni = json_object_new_object();
914 json_object_int_add(json_vni, "vni", vpn->vni);
915 } else {
916 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
917 }
918
919 show_vni_routes(wctx->bgp, vpn, wctx->vty, wctx->type, wctx->mac_table,
920 wctx->vtep_ip, json_vni, wctx->detail);
921
922 if (json)
923 json_object_object_add(json, vni_str, json_vni);
924 }
925
926 static void show_vni_routes_all_hash(struct hash_bucket *bucket, void *arg)
927 {
928 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
929 struct vni_walk_ctx *wctx = arg;
930 struct vty *vty = wctx->vty;
931 json_object *json = wctx->json;
932 json_object *json_vni = NULL;
933 json_object *json_vni_mac = NULL;
934 char vni_str[VNI_STR_LEN];
935
936 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
937 if (json) {
938 json_vni = json_object_new_object();
939 json_object_int_add(json_vni, "vni", vpn->vni);
940 } else {
941 vty_out(vty, "\nVNI: %u\n\n", vpn->vni);
942 }
943
944 show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, false, wctx->vtep_ip,
945 json_vni, wctx->detail);
946
947 if (json)
948 json_object_object_add(json, vni_str, json_vni);
949
950 if (json)
951 json_vni_mac = json_object_new_object();
952 else
953 vty_out(vty, "\nVNI: %u MAC Table\n\n", vpn->vni);
954
955 show_vni_routes(wctx->bgp, vpn, wctx->vty, 0, true, wctx->vtep_ip,
956 json_vni_mac, wctx->detail);
957
958 if (json)
959 json_object_object_add(json_vni, "macTable", json_vni_mac);
960 }
961
962 static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
963 json_object *json)
964 {
965 json_object *json_vni = NULL;
966 json_object *json_import_rtl = NULL;
967 json_object *json_export_rtl = NULL;
968 char buf1[10];
969 char buf2[INET6_ADDRSTRLEN];
970 char rt_buf[25];
971 char *ecom_str;
972 struct listnode *node, *nnode;
973 struct vrf_route_target *l3rt;
974
975 if (!bgp->l3vni)
976 return;
977
978 if (json) {
979 json_vni = json_object_new_object();
980 json_import_rtl = json_object_new_array();
981 json_export_rtl = json_object_new_array();
982 }
983
984 /* if an l3vni is present in bgp it is live */
985 buf1[0] = '\0';
986 snprintf(buf1, sizeof(buf1), "*");
987
988 if (json) {
989 json_object_int_add(json_vni, "vni", bgp->l3vni);
990 json_object_string_add(json_vni, "type", "L3");
991 json_object_string_add(json_vni, "inKernel", "True");
992 json_object_string_addf(json_vni, "originatorIp", "%pI4",
993 &bgp->originator_ip);
994 json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
995 json_object_string_add(json_vni, "advertiseGatewayMacip",
996 "n/a");
997 json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
998 json_object_string_add(
999 json_vni, "advertisePip",
1000 bgp->evpn_info->advertise_pip ? "Enabled" : "Disabled");
1001 json_object_string_addf(json_vni, "sysIP", "%pI4",
1002 &bgp->evpn_info->pip_ip);
1003 json_object_string_add(json_vni, "sysMAC",
1004 prefix_mac2str(&bgp->evpn_info->pip_rmac,
1005 buf2, sizeof(buf2)));
1006 json_object_string_add(
1007 json_vni, "rmac",
1008 prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
1009 } else {
1010 vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3",
1011 &bgp->vrf_prd);
1012 }
1013
1014 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, l3rt)) {
1015 ecom_str = ecommunity_ecom2str(l3rt->ecom,
1016 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1017
1018 if (json) {
1019 json_object_array_add(json_import_rtl,
1020 json_object_new_string(ecom_str));
1021 } else {
1022 if (listcount(bgp->vrf_import_rtl) > 1)
1023 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1024 ecom_str);
1025 else
1026 snprintf(rt_buf, sizeof(rt_buf), "%s",
1027 ecom_str);
1028 vty_out(vty, " %-25s", rt_buf);
1029 }
1030
1031 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1032
1033 /* If there are multiple import RTs we break here and show only
1034 * one */
1035 if (!json)
1036 break;
1037 }
1038
1039 if (json)
1040 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1041
1042 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, l3rt)) {
1043 ecom_str = ecommunity_ecom2str(l3rt->ecom,
1044 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1045
1046 if (json) {
1047 json_object_array_add(json_export_rtl,
1048 json_object_new_string(ecom_str));
1049 } else {
1050 if (listcount(bgp->vrf_export_rtl) > 1)
1051 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1052 ecom_str);
1053 else
1054 snprintf(rt_buf, sizeof(rt_buf), "%s",
1055 ecom_str);
1056 vty_out(vty, " %-25s", rt_buf);
1057 }
1058
1059 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1060
1061 /* If there are multiple export RTs we break here and show only
1062 * one */
1063 if (!json) {
1064 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
1065 break;
1066 }
1067 }
1068
1069 if (json) {
1070 char vni_str[VNI_STR_LEN];
1071
1072 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
1073 snprintf(vni_str, sizeof(vni_str), "%u", bgp->l3vni);
1074 json_object_object_add(json, vni_str, json_vni);
1075 } else {
1076 vty_out(vty, "\n");
1077 }
1078 }
1079
1080 static void show_vni_entry(struct hash_bucket *bucket, void *args[])
1081 {
1082 struct vty *vty;
1083 json_object *json;
1084 json_object *json_vni = NULL;
1085 json_object *json_import_rtl = NULL;
1086 json_object *json_export_rtl = NULL;
1087 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
1088 char buf1[10];
1089 char rt_buf[25];
1090 char *ecom_str;
1091 struct listnode *node, *nnode;
1092 struct ecommunity *ecom;
1093 struct bgp *bgp_evpn;
1094
1095 vty = args[0];
1096 json = args[1];
1097
1098 bgp_evpn = bgp_get_evpn();
1099
1100 if (json) {
1101 json_vni = json_object_new_object();
1102 json_import_rtl = json_object_new_array();
1103 json_export_rtl = json_object_new_array();
1104 }
1105
1106 buf1[0] = '\0';
1107 if (is_vni_live(vpn))
1108 snprintf(buf1, sizeof(buf1), "*");
1109
1110 if (json) {
1111 json_object_int_add(json_vni, "vni", vpn->vni);
1112 json_object_string_add(json_vni, "type", "L2");
1113 json_object_string_add(json_vni, "inKernel",
1114 is_vni_live(vpn) ? "True" : "False");
1115 json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
1116 json_object_string_addf(json_vni, "originatorIp", "%pI4",
1117 &vpn->originator_ip);
1118 json_object_string_addf(json_vni, "mcastGroup", "%pI4",
1119 &vpn->mcast_grp);
1120 /* per vni knob is enabled -- Enabled
1121 * Global knob is enabled -- Active
1122 * default -- Disabled
1123 */
1124 if (!vpn->advertise_gw_macip && bgp_evpn
1125 && bgp_evpn->advertise_gw_macip)
1126 json_object_string_add(
1127 json_vni, "advertiseGatewayMacip", "Active");
1128 else if (vpn->advertise_gw_macip)
1129 json_object_string_add(
1130 json_vni, "advertiseGatewayMacip", "Enabled");
1131 else
1132 json_object_string_add(
1133 json_vni, "advertiseGatewayMacip", "Disabled");
1134 if (!vpn->advertise_svi_macip && bgp_evpn
1135 && bgp_evpn->evpn_info->advertise_svi_macip)
1136 json_object_string_add(json_vni, "advertiseSviMacIp",
1137 "Active");
1138 else if (vpn->advertise_svi_macip)
1139 json_object_string_add(json_vni, "advertiseSviMacIp",
1140 "Enabled");
1141 else
1142 json_object_string_add(json_vni, "advertiseSviMacIp",
1143 "Disabled");
1144 } else {
1145 vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2",
1146 &vpn->prd);
1147 }
1148
1149 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1150 ecom_str = ecommunity_ecom2str(ecom,
1151 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1152
1153 if (json) {
1154 json_object_array_add(json_import_rtl,
1155 json_object_new_string(ecom_str));
1156 } else {
1157 if (listcount(vpn->import_rtl) > 1)
1158 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1159 ecom_str);
1160 else
1161 snprintf(rt_buf, sizeof(rt_buf), "%s",
1162 ecom_str);
1163 vty_out(vty, " %-25s", rt_buf);
1164 }
1165
1166 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1167
1168 /* If there are multiple import RTs we break here and show only
1169 * one */
1170 if (!json)
1171 break;
1172 }
1173
1174 if (json)
1175 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1176
1177 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1178 ecom_str = ecommunity_ecom2str(ecom,
1179 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1180
1181 if (json) {
1182 json_object_array_add(json_export_rtl,
1183 json_object_new_string(ecom_str));
1184 } else {
1185 if (listcount(vpn->export_rtl) > 1)
1186 snprintf(rt_buf, sizeof(rt_buf), "%s, ...",
1187 ecom_str);
1188 else
1189 snprintf(rt_buf, sizeof(rt_buf), "%s",
1190 ecom_str);
1191 vty_out(vty, " %-25s", rt_buf);
1192 }
1193
1194 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1195
1196 /* If there are multiple export RTs we break here and show only
1197 * one */
1198 if (!json) {
1199 vty_out(vty, "%-37s",
1200 vrf_id_to_name(vpn->tenant_vrf_id));
1201 break;
1202 }
1203 }
1204
1205 if (json) {
1206 char vni_str[VNI_STR_LEN];
1207
1208 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
1209 snprintf(vni_str, sizeof(vni_str), "%u", vpn->vni);
1210 json_object_object_add(json, vni_str, json_vni);
1211 } else {
1212 vty_out(vty, "\n");
1213 }
1214 }
1215
1216 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1217 enum bgp_show_type type, void *output_arg,
1218 int option, bool use_json)
1219 {
1220 afi_t afi = AFI_L2VPN;
1221 struct bgp *bgp;
1222 struct bgp_table *table;
1223 struct bgp_dest *dest;
1224 struct bgp_dest *rm;
1225 struct bgp_path_info *pi;
1226 int rd_header;
1227 int header = 1;
1228 char rd_str[RD_ADDRSTRLEN];
1229 int no_display;
1230
1231 unsigned long output_count = 0;
1232 unsigned long total_count = 0;
1233 json_object *json = NULL;
1234 json_object *json_array = NULL;
1235 json_object *json_prefix_info = NULL;
1236
1237 memset(rd_str, 0, RD_ADDRSTRLEN);
1238
1239 bgp = bgp_get_evpn();
1240 if (bgp == NULL) {
1241 if (!use_json)
1242 vty_out(vty, "No BGP process is configured\n");
1243 else
1244 vty_out(vty, "{}\n");
1245 return CMD_WARNING;
1246 }
1247
1248 if (use_json)
1249 json = json_object_new_object();
1250
1251 for (dest = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); dest;
1252 dest = bgp_route_next(dest)) {
1253 uint64_t tbl_ver;
1254 json_object *json_nroute = NULL;
1255 const struct prefix *p = bgp_dest_get_prefix(dest);
1256
1257 if (prd && memcmp(p->u.val, prd->val, 8) != 0)
1258 continue;
1259
1260 table = bgp_dest_get_bgp_table_info(dest);
1261 if (!table)
1262 continue;
1263
1264 rd_header = 1;
1265 tbl_ver = table->version;
1266
1267 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
1268 pi = bgp_dest_get_bgp_path_info(rm);
1269 if (pi == NULL)
1270 continue;
1271
1272 no_display = 0;
1273 for (; pi; pi = pi->next) {
1274 struct community *picomm = NULL;
1275
1276 picomm = bgp_attr_get_community(pi->attr);
1277
1278 total_count++;
1279 if (type == bgp_show_type_neighbor) {
1280 struct peer *peer = output_arg;
1281
1282 if (peer_cmp(peer, pi->peer) != 0)
1283 continue;
1284 }
1285 if (type == bgp_show_type_lcommunity_exact) {
1286 struct lcommunity *lcom = output_arg;
1287
1288 if (!bgp_attr_get_lcommunity(
1289 pi->attr) ||
1290 !lcommunity_cmp(
1291 bgp_attr_get_lcommunity(
1292 pi->attr),
1293 lcom))
1294 continue;
1295 }
1296 if (type == bgp_show_type_lcommunity) {
1297 struct lcommunity *lcom = output_arg;
1298
1299 if (!bgp_attr_get_lcommunity(
1300 pi->attr) ||
1301 !lcommunity_match(
1302 bgp_attr_get_lcommunity(
1303 pi->attr),
1304 lcom))
1305 continue;
1306 }
1307 if (type == bgp_show_type_community) {
1308 struct community *com = output_arg;
1309
1310 if (!picomm ||
1311 !community_match(picomm, com))
1312 continue;
1313 }
1314 if (type == bgp_show_type_community_exact) {
1315 struct community *com = output_arg;
1316
1317 if (!picomm ||
1318 !community_cmp(picomm, com))
1319 continue;
1320 }
1321 if (header) {
1322 if (use_json) {
1323 json_object_int_add(
1324 json, "bgpTableVersion",
1325 tbl_ver);
1326 json_object_string_addf(
1327 json,
1328 "bgpLocalRouterId",
1329 "%pI4",
1330 &bgp->router_id);
1331 json_object_int_add(
1332 json,
1333 "defaultLocPrf",
1334 bgp->default_local_pref);
1335 json_object_int_add(
1336 json, "localAS",
1337 bgp->as);
1338 } else {
1339 if (option == SHOW_DISPLAY_TAGS)
1340 vty_out(vty,
1341 V4_HEADER_TAG);
1342 else if (
1343 option
1344 == SHOW_DISPLAY_OVERLAY)
1345 vty_out(vty,
1346 V4_HEADER_OVERLAY);
1347 else {
1348 bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
1349 }
1350 }
1351 header = 0;
1352 }
1353 if (rd_header) {
1354 if (use_json)
1355 json_nroute =
1356 json_object_new_object();
1357 bgp_evpn_show_route_rd_header(
1358 vty, dest, json_nroute, rd_str,
1359 RD_ADDRSTRLEN);
1360 rd_header = 0;
1361 }
1362 if (use_json && !json_array)
1363 json_array = json_object_new_array();
1364
1365 if (option == SHOW_DISPLAY_TAGS)
1366 route_vty_out_tag(
1367 vty, bgp_dest_get_prefix(rm),
1368 pi, no_display, SAFI_EVPN,
1369 json_array);
1370 else if (option == SHOW_DISPLAY_OVERLAY)
1371 route_vty_out_overlay(
1372 vty, bgp_dest_get_prefix(rm),
1373 pi, no_display, json_array);
1374 else
1375 route_vty_out(vty,
1376 bgp_dest_get_prefix(rm),
1377 pi, no_display, SAFI_EVPN,
1378 json_array, false);
1379 no_display = 1;
1380 }
1381
1382 if (no_display)
1383 output_count++;
1384
1385 if (use_json && json_array) {
1386 const struct prefix *p =
1387 bgp_dest_get_prefix(rm);
1388
1389 json_prefix_info = json_object_new_object();
1390
1391 json_object_string_addf(json_prefix_info,
1392 "prefix", "%pFX", p);
1393
1394 json_object_int_add(json_prefix_info,
1395 "prefixLen", p->prefixlen);
1396
1397 json_object_object_add(json_prefix_info,
1398 "paths", json_array);
1399 json_object_object_addf(json_nroute,
1400 json_prefix_info,
1401 "%pFX", p);
1402 json_array = NULL;
1403 }
1404 }
1405
1406 if (use_json && json_nroute)
1407 json_object_object_add(json, rd_str, json_nroute);
1408 }
1409
1410 if (use_json) {
1411 json_object_int_add(json, "numPrefix", output_count);
1412 json_object_int_add(json, "totalPrefix", total_count);
1413 vty_json(vty, json);
1414 } else {
1415 if (output_count == 0)
1416 vty_out(vty, "No prefixes displayed, %ld exist\n",
1417 total_count);
1418 else
1419 vty_out(vty,
1420 "\nDisplayed %ld out of %ld total prefixes\n",
1421 output_count, total_count);
1422 }
1423 return CMD_SUCCESS;
1424 }
1425
1426 DEFUN(show_ip_bgp_l2vpn_evpn,
1427 show_ip_bgp_l2vpn_evpn_cmd,
1428 "show [ip] bgp l2vpn evpn [json]",
1429 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
1430 {
1431 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1432 SHOW_DISPLAY_STANDARD,
1433 use_json(argc, argv));
1434 }
1435
1436 DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1437 show_ip_bgp_l2vpn_evpn_rd_cmd,
1438 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1439 SHOW_STR
1440 IP_STR
1441 BGP_STR
1442 L2VPN_HELP_STR
1443 EVPN_HELP_STR
1444 "Display information for a route distinguisher\n"
1445 "VPN Route Distinguisher\n"
1446 "All VPN Route Distinguishers\n"
1447 JSON_STR)
1448 {
1449 int idx_ext_community = 0;
1450 int ret;
1451 struct prefix_rd prd;
1452 int rd_all = 0;
1453
1454 if (argv_find(argv, argc, "all", &rd_all))
1455 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1456 NULL, SHOW_DISPLAY_STANDARD,
1457 use_json(argc, argv));
1458
1459 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1460 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1461 if (!ret) {
1462 vty_out(vty, "%% Malformed Route Distinguisher\n");
1463 return CMD_WARNING;
1464 }
1465 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1466 SHOW_DISPLAY_STANDARD,
1467 use_json(argc, argv));
1468 }
1469
1470 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1471 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1472 "show [ip] bgp l2vpn evpn all tags",
1473 SHOW_STR
1474 IP_STR
1475 BGP_STR
1476 L2VPN_HELP_STR
1477 EVPN_HELP_STR
1478 "Display information about all EVPN NLRIs\n"
1479 "Display BGP tags for prefixes\n")
1480 {
1481 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1482 SHOW_DISPLAY_TAGS, 0);
1483 }
1484
1485 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1486 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
1487 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1488 SHOW_STR
1489 IP_STR
1490 BGP_STR
1491 L2VPN_HELP_STR
1492 EVPN_HELP_STR
1493 "Display information for a route distinguisher\n"
1494 "VPN Route Distinguisher\n"
1495 "All VPN Route Distinguishers\n"
1496 "Display BGP tags for prefixes\n")
1497 {
1498 int idx_ext_community = 0;
1499 int ret;
1500 struct prefix_rd prd;
1501 int rd_all = 0;
1502
1503 if (argv_find(argv, argc, "all", &rd_all))
1504 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1505 NULL, SHOW_DISPLAY_TAGS, 0);
1506
1507 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1508 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1509 if (!ret) {
1510 vty_out(vty, "%% Malformed Route Distinguisher\n");
1511 return CMD_WARNING;
1512 }
1513 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1514 SHOW_DISPLAY_TAGS, 0);
1515 }
1516
1517 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1518 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1519 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1520 SHOW_STR
1521 IP_STR
1522 BGP_STR
1523 L2VPN_HELP_STR
1524 EVPN_HELP_STR
1525 "Detailed information on TCP and BGP neighbor connections\n"
1526 "IPv4 Neighbor to display information about\n"
1527 "IPv6 Neighbor to display information about\n"
1528 "Neighbor on BGP configured interface\n"
1529 "Display routes learned from neighbor\n" JSON_STR)
1530 {
1531 int idx = 0;
1532 struct peer *peer;
1533 char *peerstr = NULL;
1534 bool uj = use_json(argc, argv);
1535 afi_t afi = AFI_L2VPN;
1536 safi_t safi = SAFI_EVPN;
1537 struct bgp *bgp = NULL;
1538
1539 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1540 &bgp, uj);
1541 if (!idx) {
1542 vty_out(vty, "No index\n");
1543 return CMD_WARNING;
1544 }
1545
1546 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1547 argv_find(argv, argc, "neighbors", &idx);
1548 peerstr = argv[++idx]->arg;
1549
1550 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1551 if (!peer) {
1552 if (uj) {
1553 json_object *json_no = NULL;
1554 json_no = json_object_new_object();
1555 json_object_string_add(json_no, "warning",
1556 "Malformed address");
1557 vty_out(vty, "%s\n",
1558 json_object_to_json_string(json_no));
1559 json_object_free(json_no);
1560 } else
1561 vty_out(vty, "Malformed address: %s\n",
1562 argv[idx]->arg);
1563 return CMD_WARNING;
1564 }
1565 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1566 if (uj) {
1567 json_object *json_no = NULL;
1568 json_no = json_object_new_object();
1569 json_object_string_add(
1570 json_no, "warning",
1571 "No such neighbor or address family");
1572 vty_out(vty, "%s\n",
1573 json_object_to_json_string(json_no));
1574 json_object_free(json_no);
1575 } else
1576 vty_out(vty, "%% No such neighbor or address family\n");
1577 return CMD_WARNING;
1578 }
1579
1580 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer,
1581 SHOW_DISPLAY_STANDARD, uj);
1582 }
1583
1584 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1585 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1586 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1587 SHOW_STR
1588 IP_STR
1589 BGP_STR
1590 L2VPN_HELP_STR
1591 EVPN_HELP_STR
1592 "Display information for a route distinguisher\n"
1593 "VPN Route Distinguisher\n"
1594 "All VPN Route Distinguishers\n"
1595 "Detailed information on TCP and BGP neighbor connections\n"
1596 "IPv4 Neighbor to display information about\n"
1597 "IPv6 Neighbor to display information about\n"
1598 "Neighbor on BGP configured interface\n"
1599 "Display routes learned from neighbor\n" JSON_STR)
1600 {
1601 int idx_ext_community = 0;
1602 int idx = 0;
1603 int ret;
1604 struct peer *peer;
1605 char *peerstr = NULL;
1606 struct prefix_rd prd = {};
1607 bool uj = use_json(argc, argv);
1608 afi_t afi = AFI_L2VPN;
1609 safi_t safi = SAFI_EVPN;
1610 struct bgp *bgp = NULL;
1611 int rd_all = 0;
1612
1613 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1614 &bgp, uj);
1615 if (!idx) {
1616 vty_out(vty, "No index\n");
1617 return CMD_WARNING;
1618 }
1619
1620 if (argv_find(argv, argc, "all", &rd_all)) {
1621 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1622 &idx_ext_community);
1623 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1624 if (!ret) {
1625 if (uj) {
1626 json_object *json_no = NULL;
1627 json_no = json_object_new_object();
1628 json_object_string_add(
1629 json_no, "warning",
1630 "Malformed Route Distinguisher");
1631 vty_out(vty, "%s\n",
1632 json_object_to_json_string(json_no));
1633 json_object_free(json_no);
1634 } else
1635 vty_out(vty,
1636 "%% Malformed Route Distinguisher\n");
1637 return CMD_WARNING;
1638 }
1639 }
1640
1641 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1642 argv_find(argv, argc, "neighbors", &idx);
1643 peerstr = argv[++idx]->arg;
1644
1645 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1646 if (!peer) {
1647 if (uj) {
1648 json_object *json_no = NULL;
1649 json_no = json_object_new_object();
1650 json_object_string_add(json_no, "warning",
1651 "Malformed address");
1652 vty_out(vty, "%s\n",
1653 json_object_to_json_string(json_no));
1654 json_object_free(json_no);
1655 } else
1656 vty_out(vty, "Malformed address: %s\n",
1657 argv[idx]->arg);
1658 return CMD_WARNING;
1659 }
1660 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1661 if (uj) {
1662 json_object *json_no = NULL;
1663 json_no = json_object_new_object();
1664 json_object_string_add(
1665 json_no, "warning",
1666 "No such neighbor or address family");
1667 vty_out(vty, "%s\n",
1668 json_object_to_json_string(json_no));
1669 json_object_free(json_no);
1670 } else
1671 vty_out(vty, "%% No such neighbor or address family\n");
1672 return CMD_WARNING;
1673 }
1674
1675
1676 if (rd_all)
1677 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor,
1678 peer, SHOW_DISPLAY_STANDARD, uj);
1679 else
1680 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor,
1681 peer, SHOW_DISPLAY_STANDARD, uj);
1682 }
1683
1684 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1685 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1686 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1687 SHOW_STR
1688 IP_STR
1689 BGP_STR
1690 L2VPN_HELP_STR
1691 EVPN_HELP_STR
1692 "Detailed information on TCP and BGP neighbor connections\n"
1693 "IPv4 Neighbor to display information about\n"
1694 "IPv6 Neighbor to display information about\n"
1695 "Neighbor on BGP configured interface\n"
1696 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1697 {
1698 int idx = 0;
1699 struct peer *peer;
1700 bool uj = use_json(argc, argv);
1701 struct bgp *bgp = NULL;
1702 afi_t afi = AFI_L2VPN;
1703 safi_t safi = SAFI_EVPN;
1704 char *peerstr = NULL;
1705
1706 if (uj)
1707 argc--;
1708
1709 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1710 &bgp, uj);
1711 if (!idx) {
1712 vty_out(vty, "No index\n");
1713 return CMD_WARNING;
1714 }
1715
1716 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1717 argv_find(argv, argc, "neighbors", &idx);
1718 peerstr = argv[++idx]->arg;
1719
1720 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1721 if (!peer) {
1722 if (uj) {
1723 json_object *json_no = NULL;
1724 json_no = json_object_new_object();
1725 json_object_string_add(json_no, "warning",
1726 "Malformed address");
1727 vty_out(vty, "%s\n",
1728 json_object_to_json_string(json_no));
1729 json_object_free(json_no);
1730 } else
1731 vty_out(vty, "Malformed address: %s\n",
1732 argv[idx]->arg);
1733 return CMD_WARNING;
1734 }
1735 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1736 if (uj) {
1737 json_object *json_no = NULL;
1738 json_no = json_object_new_object();
1739 json_object_string_add(
1740 json_no, "warning",
1741 "No such neighbor or address family");
1742 vty_out(vty, "%s\n",
1743 json_object_to_json_string(json_no));
1744 json_object_free(json_no);
1745 } else
1746 vty_out(vty, "%% No such neighbor or address family\n");
1747 return CMD_WARNING;
1748 }
1749
1750 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1751 }
1752
1753 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1754 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1755 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1756 SHOW_STR
1757 IP_STR
1758 BGP_STR
1759 L2VPN_HELP_STR
1760 EVPN_HELP_STR
1761 "Display information for a route distinguisher\n"
1762 "VPN Route Distinguisher\n"
1763 "All VPN Route Distinguishers\n"
1764 "Detailed information on TCP and BGP neighbor connections\n"
1765 "IPv4 Neighbor to display information about\n"
1766 "IPv6 Neighbor to display information about\n"
1767 "Neighbor on BGP configured interface\n"
1768 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1769 {
1770 int idx_ext_community = 0;
1771 int idx = 0;
1772 int ret;
1773 struct peer *peer;
1774 struct prefix_rd prd;
1775 struct bgp *bgp = NULL;
1776 bool uj = use_json(argc, argv);
1777 char *peerstr = NULL;
1778 afi_t afi = AFI_L2VPN;
1779 safi_t safi = SAFI_EVPN;
1780 int rd_all = 0;
1781
1782 if (uj)
1783 argc--;
1784
1785 if (uj)
1786 argc--;
1787
1788 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1789 &bgp, uj);
1790 if (!idx) {
1791 vty_out(vty, "No index\n");
1792 return CMD_WARNING;
1793 }
1794
1795 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1796 argv_find(argv, argc, "neighbors", &idx);
1797 peerstr = argv[++idx]->arg;
1798
1799 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1800 if (!peer) {
1801 if (uj) {
1802 json_object *json_no = NULL;
1803 json_no = json_object_new_object();
1804 json_object_string_add(json_no, "warning",
1805 "Malformed address");
1806 vty_out(vty, "%s\n",
1807 json_object_to_json_string(json_no));
1808 json_object_free(json_no);
1809 } else
1810 vty_out(vty, "Malformed address: %s\n",
1811 argv[idx]->arg);
1812 return CMD_WARNING;
1813 }
1814 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1815 if (uj) {
1816 json_object *json_no = NULL;
1817 json_no = json_object_new_object();
1818 json_object_string_add(
1819 json_no, "warning",
1820 "No such neighbor or address family");
1821 vty_out(vty, "%s\n",
1822 json_object_to_json_string(json_no));
1823 json_object_free(json_no);
1824 } else
1825 vty_out(vty, "%% No such neighbor or address family\n");
1826 return CMD_WARNING;
1827 }
1828
1829 if (argv_find(argv, argc, "all", &rd_all))
1830 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN,
1831 uj);
1832 else {
1833 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
1834 &idx_ext_community);
1835 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1836 if (!ret) {
1837 if (uj) {
1838 json_object *json_no = NULL;
1839 json_no = json_object_new_object();
1840 json_object_string_add(
1841 json_no, "warning",
1842 "Malformed Route Distinguisher");
1843 vty_out(vty, "%s\n",
1844 json_object_to_json_string(json_no));
1845 json_object_free(json_no);
1846 } else
1847 vty_out(vty,
1848 "%% Malformed Route Distinguisher\n");
1849 return CMD_WARNING;
1850 }
1851 }
1852
1853 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1854 }
1855
1856 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1857 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1858 "show [ip] bgp l2vpn evpn all overlay [json]",
1859 SHOW_STR
1860 IP_STR
1861 BGP_STR
1862 L2VPN_HELP_STR
1863 EVPN_HELP_STR
1864 "Display information about all EVPN NLRIs\n"
1865 "Display BGP Overlay Information for prefixes\n"
1866 JSON_STR)
1867 {
1868 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1869 SHOW_DISPLAY_OVERLAY,
1870 use_json(argc, argv));
1871 }
1872
1873 DEFUN(show_ip_bgp_evpn_rd_overlay,
1874 show_ip_bgp_evpn_rd_overlay_cmd,
1875 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1876 SHOW_STR
1877 IP_STR
1878 BGP_STR
1879 L2VPN_HELP_STR
1880 EVPN_HELP_STR
1881 "Display information for a route distinguisher\n"
1882 "VPN Route Distinguisher\n"
1883 "All VPN Route Distinguishers\n"
1884 "Display BGP Overlay Information for prefixes\n")
1885 {
1886 int idx_ext_community = 0;
1887 int ret;
1888 struct prefix_rd prd;
1889 int rd_all = 0;
1890
1891 if (argv_find(argv, argc, "all", &rd_all))
1892 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal,
1893 NULL, SHOW_DISPLAY_OVERLAY,
1894 use_json(argc, argv));
1895
1896 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1897 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1898 if (!ret) {
1899 vty_out(vty, "%% Malformed Route Distinguisher\n");
1900 return CMD_WARNING;
1901 }
1902 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1903 SHOW_DISPLAY_OVERLAY,
1904 use_json(argc, argv));
1905 }
1906
1907 DEFUN(show_bgp_l2vpn_evpn_com,
1908 show_bgp_l2vpn_evpn_com_cmd,
1909 "show bgp l2vpn evpn \
1910 <community AA:NN|large-community AA:BB:CC> \
1911 [exact-match] [json]",
1912 SHOW_STR
1913 BGP_STR
1914 L2VPN_HELP_STR
1915 EVPN_HELP_STR
1916 "Display routes matching the community\n"
1917 "Community number where AA and NN are (0-65535)\n"
1918 "Display routes matching the large-community\n"
1919 "List of large-community numbers\n"
1920 "Exact match of the communities\n"
1921 JSON_STR)
1922 {
1923 int idx = 0;
1924 int ret = 0;
1925 const char *clist_number_or_name;
1926 int show_type = bgp_show_type_normal;
1927 struct community *com;
1928 struct lcommunity *lcom;
1929
1930 if (argv_find(argv, argc, "large-community", &idx)) {
1931 clist_number_or_name = argv[++idx]->arg;
1932 show_type = bgp_show_type_lcommunity;
1933
1934 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1935 show_type = bgp_show_type_lcommunity_exact;
1936
1937 lcom = lcommunity_str2com(clist_number_or_name);
1938 if (!lcom) {
1939 vty_out(vty, "%% Large-community malformed\n");
1940 return CMD_WARNING;
1941 }
1942
1943 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1944 SHOW_DISPLAY_STANDARD,
1945 use_json(argc, argv));
1946
1947 lcommunity_free(&lcom);
1948 } else if (argv_find(argv, argc, "community", &idx)) {
1949 clist_number_or_name = argv[++idx]->arg;
1950 show_type = bgp_show_type_community;
1951
1952 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1953 show_type = bgp_show_type_community_exact;
1954
1955 com = community_str2com(clist_number_or_name);
1956
1957 if (!com) {
1958 vty_out(vty, "%% Community malformed: %s\n",
1959 clist_number_or_name);
1960 return CMD_WARNING;
1961 }
1962
1963 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1964 SHOW_DISPLAY_STANDARD,
1965 use_json(argc, argv));
1966 community_free(&com);
1967 }
1968
1969 return ret;
1970 }
1971
1972 /* For testing purpose, static route of EVPN RT-5. */
1973 DEFUN(evpnrt5_network,
1974 evpnrt5_network_cmd,
1975 "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 RMAP_NAME]",
1976 "Specify a network to announce via BGP\n"
1977 "IP prefix\n"
1978 "IPv6 prefix\n"
1979 "Specify Route Distinguisher\n"
1980 "VPN Route Distinguisher\n"
1981 "Ethernet Tag\n"
1982 "Ethernet Tag Value\n"
1983 "BGP label\n"
1984 "label value\n"
1985 "Ethernet Segment Identifier\n"
1986 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1987 "Gateway IP\n"
1988 "Gateway IP ( A.B.C.D )\n"
1989 "Gateway IPv6 ( X:X::X:X )\n"
1990 "Router Mac Ext Comm\n"
1991 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1992 "Route-map to modify the attributes\n"
1993 "Name of the route map\n")
1994 {
1995 int idx_ipv4_prefixlen = 1;
1996 int idx_route_distinguisher = 3;
1997 int idx_label = 7;
1998 int idx_esi = 9;
1999 int idx_gwip = 11;
2000 int idx_ethtag = 5;
2001 int idx_routermac = 13;
2002
2003 return bgp_static_set_safi(
2004 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
2005 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
2006 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2007 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
2008 argv[idx_routermac]->arg);
2009 }
2010
2011 /* For testing purpose, static route of EVPN RT-5. */
2012 DEFUN(no_evpnrt5_network,
2013 no_evpnrt5_network_cmd,
2014 "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>",
2015 NO_STR
2016 "Specify a network to announce via BGP\n"
2017 "IP prefix\n"
2018 "IPv6 prefix\n"
2019 "Specify Route Distinguisher\n"
2020 "VPN Route Distinguisher\n"
2021 "Ethernet Tag\n"
2022 "Ethernet Tag Value\n"
2023 "BGP label\n"
2024 "label value\n"
2025 "Ethernet Segment Identifier\n"
2026 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2027 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2028 {
2029 int idx_ipv4_prefixlen = 2;
2030 int idx_ext_community = 4;
2031 int idx_label = 8;
2032 int idx_ethtag = 6;
2033 int idx_esi = 10;
2034 int idx_gwip = 12;
2035 return bgp_static_unset_safi(
2036 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
2037 argv[idx_ext_community]->arg, argv[idx_label]->arg,
2038 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
2039 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
2040 }
2041
2042 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
2043 {
2044 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl, false);
2045 }
2046
2047 static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
2048 {
2049 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl, false);
2050 }
2051
2052 /*
2053 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2054 * check that this is a change.
2055 */
2056 static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2057 struct ecommunity *ecomadd)
2058 {
2059 /* If the VNI is "live", we need to uninstall routes using the current
2060 * import RT(s) first before we update the import RT, and subsequently
2061 * install routes.
2062 */
2063 if (is_vni_live(vpn))
2064 bgp_evpn_uninstall_routes(bgp, vpn);
2065
2066 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2067 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
2068
2069 /* If the auto route-target is in use we must remove it */
2070 evpn_import_rt_delete_auto(bgp, vpn);
2071
2072 /* Add new RT and rebuild the RT to VNI mapping */
2073 listnode_add_sort(vpn->import_rtl, ecomadd);
2074
2075 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2076 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
2077
2078 /* Install routes that match new import RT */
2079 if (is_vni_live(vpn))
2080 bgp_evpn_install_routes(bgp, vpn);
2081 }
2082
2083 /*
2084 * Unconfigure Import RT(s) for a VNI (vty handler).
2085 */
2086 static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
2087 struct ecommunity *ecomdel)
2088 {
2089 struct listnode *node, *nnode, *node_to_del;
2090 struct ecommunity *ecom;
2091
2092 /* Along the lines of "configure" except we have to reset to the
2093 * automatic value.
2094 */
2095 if (is_vni_live(vpn))
2096 bgp_evpn_uninstall_routes(bgp, vpn);
2097
2098 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2099 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
2100
2101 /* Delete all import RTs */
2102 if (ecomdel == NULL) {
2103 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
2104 ecommunity_free(&ecom);
2105 list_delete_node(vpn->import_rtl, node);
2106 }
2107 }
2108
2109 /* Delete a specific import RT */
2110 else {
2111 node_to_del = NULL;
2112
2113 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
2114 if (ecommunity_match(ecom, ecomdel)) {
2115 ecommunity_free(&ecom);
2116 node_to_del = node;
2117 break;
2118 }
2119 }
2120
2121 if (node_to_del)
2122 list_delete_node(vpn->import_rtl, node_to_del);
2123 }
2124
2125 assert(vpn->import_rtl);
2126 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2127 if (list_isempty(vpn->import_rtl)) {
2128 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
2129 bgp_evpn_derive_auto_rt_import(bgp, vpn);
2130 }
2131 /* Rebuild the RT to VNI mapping */
2132 else
2133 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
2134
2135 /* Install routes that match new import RT */
2136 if (is_vni_live(vpn))
2137 bgp_evpn_install_routes(bgp, vpn);
2138 }
2139
2140 /*
2141 * Configure the Export RT for a VNI (vty handler). Caller expected to
2142 * check that this is a change. Note that only a single export RT is
2143 * allowed for a VNI and any change to configuration is implemented as
2144 * a "replace" (similar to other configuration).
2145 */
2146 static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2147 struct ecommunity *ecomadd)
2148 {
2149 /* If the auto route-target is in use we must remove it */
2150 evpn_export_rt_delete_auto(bgp, vpn);
2151
2152 listnode_add_sort(vpn->export_rtl, ecomadd);
2153 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2154
2155 if (is_vni_live(vpn))
2156 bgp_evpn_handle_export_rt_change(bgp, vpn);
2157 }
2158
2159 /*
2160 * Unconfigure the Export RT for a VNI (vty handler)
2161 */
2162 static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
2163 struct ecommunity *ecomdel)
2164 {
2165 struct listnode *node, *nnode, *node_to_del;
2166 struct ecommunity *ecom;
2167
2168 /* Delete all export RTs */
2169 if (ecomdel == NULL) {
2170 /* Reset to default and process all routes. */
2171 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2172 ecommunity_free(&ecom);
2173 list_delete_node(vpn->export_rtl, node);
2174 }
2175 }
2176
2177 /* Delete a specific export RT */
2178 else {
2179 node_to_del = NULL;
2180
2181 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2182 if (ecommunity_match(ecom, ecomdel)) {
2183 ecommunity_free(&ecom);
2184 node_to_del = node;
2185 break;
2186 }
2187 }
2188
2189 if (node_to_del)
2190 list_delete_node(vpn->export_rtl, node_to_del);
2191 }
2192
2193 assert(vpn->export_rtl);
2194 if (list_isempty(vpn->export_rtl)) {
2195 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2196 bgp_evpn_derive_auto_rt_export(bgp, vpn);
2197 }
2198
2199 if (is_vni_live(vpn))
2200 bgp_evpn_handle_export_rt_change(bgp, vpn);
2201 }
2202
2203 /*
2204 * Configure RD for VRF
2205 */
2206 static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
2207 {
2208 /* If we have already advertise type-5 routes with a diffrent RD, we
2209 * have to delete and withdraw them firs
2210 */
2211 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2212
2213 /* update RD */
2214 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
2215 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2216
2217 /* We have a new RD for VRF.
2218 * Advertise all type-5 routes again with the new RD
2219 */
2220 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2221 }
2222
2223 /*
2224 * Unconfigure RD for VRF
2225 */
2226 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2227 {
2228 /* If we have already advertise type-5 routes with a diffrent RD, we
2229 * have to delete and withdraw them firs
2230 */
2231 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2232
2233 /* fall back to default RD */
2234 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
2235 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2236
2237 /* We have a new RD for VRF.
2238 * Advertise all type-5 routes again with the new RD
2239 */
2240 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2241 }
2242
2243 /*
2244 * Configure RD for a VNI (vty handler)
2245 */
2246 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
2247 struct prefix_rd *rd)
2248 {
2249 /* If the VNI is "live", we need to delete and withdraw this VNI's
2250 * local routes with the prior RD first. Then, after updating RD,
2251 * need to re-advertise.
2252 */
2253 if (is_vni_live(vpn))
2254 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2255
2256 /* update RD */
2257 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
2258 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
2259
2260 if (is_vni_live(vpn))
2261 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2262 }
2263
2264 /*
2265 * Unconfigure RD for a VNI (vty handler)
2266 */
2267 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
2268 {
2269 /* If the VNI is "live", we need to delete and withdraw this VNI's
2270 * local routes with the prior RD first. Then, after resetting RD
2271 * to automatic value, need to re-advertise.
2272 */
2273 if (is_vni_live(vpn))
2274 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2275
2276 /* reset RD to default */
2277 bgp_evpn_derive_auto_rd(bgp, vpn);
2278
2279 if (is_vni_live(vpn))
2280 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2281 }
2282
2283 /*
2284 * Create VNI, if not already present (VTY handler). Mark as configured.
2285 */
2286 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
2287 {
2288 struct bgpevpn *vpn;
2289 struct in_addr mcast_grp = {INADDR_ANY};
2290
2291 vpn = bgp_evpn_lookup_vni(bgp, vni);
2292 if (!vpn) {
2293 /* Check if this L2VNI is already configured as L3VNI */
2294 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
2295 flog_err(
2296 EC_BGP_VNI,
2297 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2298 bgp->vrf_id, vni);
2299 return NULL;
2300 }
2301
2302 /* tenant vrf will be updated when we get local_vni_add from
2303 * zebra
2304 */
2305 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp, 0);
2306 }
2307
2308 /* Mark as configured. */
2309 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2310 return vpn;
2311 }
2312
2313 /*
2314 * Delete VNI. If VNI does not exist in the system (i.e., just
2315 * configuration), all that is needed is to free it. Otherwise,
2316 * any parameters configured for the VNI need to be reset (with
2317 * appropriate action) and the VNI marked as unconfigured; the
2318 * VNI will continue to exist, purely as a "learnt" entity.
2319 */
2320 static void evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
2321 {
2322 if (!is_vni_live(vpn)) {
2323 bgp_evpn_free(bgp, vpn);
2324 return;
2325 }
2326
2327 /* We need to take the unconfigure action for each parameter of this VNI
2328 * that is configured. Some optimization is possible, but not worth the
2329 * additional code for an operation that should be pretty rare.
2330 */
2331 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2332
2333 /* First, deal with the export side - RD and export RT changes. */
2334 if (is_rd_configured(vpn))
2335 evpn_unconfigure_rd(bgp, vpn);
2336 if (is_export_rt_configured(vpn))
2337 evpn_unconfigure_export_rt(bgp, vpn, NULL);
2338
2339 /* Next, deal with the import side. */
2340 if (is_import_rt_configured(vpn))
2341 evpn_unconfigure_import_rt(bgp, vpn, NULL);
2342 }
2343
2344 /*
2345 * Display import RT mapping to VRFs (vty handler)
2346 * bgp_evpn: evpn bgp instance
2347 */
2348 static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
2349 json_object *json)
2350 {
2351 void *args[2];
2352
2353 args[0] = vty;
2354 args[1] = json;
2355
2356 hash_iterate(bgp_evpn->vrf_import_rt_hash,
2357 (void (*)(struct hash_bucket *,
2358 void *))show_vrf_import_rt_entry,
2359 args);
2360 }
2361
2362 /*
2363 * Display import RT mapping to VNIs (vty handler)
2364 */
2365 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2366 json_object *json)
2367 {
2368 void *args[2];
2369
2370 args[0] = vty;
2371 args[1] = json;
2372
2373 hash_iterate(
2374 bgp->import_rt_hash,
2375 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
2376 args);
2377 }
2378
2379 /*
2380 * Display EVPN routes for all VNIs - vty handler.
2381 */
2382 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp, int type,
2383 bool mac_table, struct in_addr vtep_ip,
2384 json_object *json, int detail)
2385 {
2386 uint32_t num_vnis;
2387 struct vni_walk_ctx wctx;
2388
2389 num_vnis = hashcount(bgp->vnihash);
2390 if (!num_vnis)
2391 return;
2392 memset(&wctx, 0, sizeof(wctx));
2393 wctx.bgp = bgp;
2394 wctx.vty = vty;
2395 wctx.type = type;
2396 wctx.mac_table = mac_table;
2397 wctx.vtep_ip = vtep_ip;
2398 wctx.json = json;
2399 wctx.detail = detail;
2400 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
2401 void *))show_vni_routes_hash,
2402 &wctx);
2403 }
2404
2405 /*
2406 * Display EVPN routes for all VNIs & all types - vty handler.
2407 */
2408 static void evpn_show_routes_vni_all_type_all(struct vty *vty, struct bgp *bgp,
2409 struct in_addr vtep_ip,
2410 json_object *json, int detail)
2411 {
2412 uint32_t num_vnis;
2413 struct vni_walk_ctx wctx;
2414
2415 num_vnis = hashcount(bgp->vnihash);
2416 if (!num_vnis)
2417 return;
2418
2419 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2420 wctx.bgp = bgp;
2421 wctx.vty = vty;
2422 wctx.vtep_ip = vtep_ip;
2423 wctx.json = json;
2424 wctx.detail = detail;
2425 hash_iterate(bgp->vnihash,
2426 (void (*)(struct hash_bucket *,
2427 void *))show_vni_routes_all_hash,
2428 &wctx);
2429 }
2430
2431 /*
2432 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2433 */
2434 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
2435 vni_t vni, struct in_addr orig_ip,
2436 json_object *json)
2437 {
2438 struct bgpevpn *vpn;
2439 struct prefix_evpn p;
2440 struct bgp_dest *dest;
2441 struct bgp_path_info *pi;
2442 uint32_t path_cnt = 0;
2443 afi_t afi;
2444 safi_t safi;
2445 json_object *json_paths = NULL;
2446
2447 afi = AFI_L2VPN;
2448 safi = SAFI_EVPN;
2449
2450 /* Locate VNI. */
2451 vpn = bgp_evpn_lookup_vni(bgp, vni);
2452 if (!vpn) {
2453 vty_out(vty, "VNI not found\n");
2454 return;
2455 }
2456
2457 /* See if route exists. */
2458 build_evpn_type3_prefix(&p, orig_ip);
2459 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
2460 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2461 if (!json)
2462 vty_out(vty, "%% Network not in table\n");
2463
2464 if (dest)
2465 bgp_dest_unlock_node(dest);
2466
2467 return;
2468 }
2469
2470 if (json)
2471 json_paths = json_object_new_array();
2472
2473 /* Prefix and num paths displayed once per prefix. */
2474 route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
2475 NULL, afi, safi, json);
2476
2477 /* Display each path for this prefix. */
2478 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2479 json_object *json_path = NULL;
2480
2481 if (json)
2482 json_path = json_object_new_array();
2483
2484 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2485 pi, afi, safi, RPKI_NOT_BEING_USED,
2486 json_path);
2487
2488 if (json)
2489 json_object_array_add(json_paths, json_path);
2490
2491 path_cnt++;
2492 }
2493
2494 if (json) {
2495 if (path_cnt)
2496 json_object_object_add(json, "paths", json_paths);
2497
2498 json_object_int_add(json, "numPaths", path_cnt);
2499 } else {
2500 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2501 path_cnt);
2502 }
2503
2504 bgp_dest_unlock_node(dest);
2505 }
2506
2507 /*
2508 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2509 * By definition, only matching type-2 route will be displayed.
2510 */
2511 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2512 vni_t vni, struct ethaddr *mac,
2513 struct ipaddr *ip, json_object *json)
2514 {
2515 struct bgpevpn *vpn;
2516 struct prefix_evpn p;
2517 struct prefix_evpn tmp_p;
2518 struct bgp_dest *dest;
2519 struct bgp_path_info *pi;
2520 uint32_t path_cnt = 0;
2521 afi_t afi;
2522 safi_t safi;
2523 json_object *json_paths = NULL;
2524 struct ethaddr empty_mac = {};
2525 struct ipaddr empty_ip = {};
2526 const struct prefix_evpn *evp;
2527
2528 afi = AFI_L2VPN;
2529 safi = SAFI_EVPN;
2530
2531 /* Locate VNI. */
2532 vpn = bgp_evpn_lookup_vni(bgp, vni);
2533 if (!vpn) {
2534 if (!json)
2535 vty_out(vty, "VNI not found\n");
2536 return;
2537 }
2538
2539 build_evpn_type2_prefix(&p, mac ? mac : &empty_mac,
2540 ip ? ip : &empty_ip);
2541
2542 /* See if route exists. Look for both non-sticky and sticky. */
2543 dest = bgp_evpn_vni_node_lookup(vpn, &p, NULL);
2544 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2545 if (!json)
2546 vty_out(vty, "%% Network not in table\n");
2547
2548 if (dest)
2549 bgp_dest_unlock_node(dest);
2550
2551 return;
2552 }
2553
2554 /*
2555 * MAC is per-path, we have to walk the path_info's and look for it
2556 * first here.
2557 */
2558 if (ip && mac) {
2559 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2560 if (memcmp(mac, evpn_type2_path_info_get_mac(pi),
2561 sizeof(*mac)) == 0)
2562 break;
2563 }
2564
2565 if (!pi) {
2566 if (!json)
2567 vty_out(vty, "%% Network not in table\n");
2568 return;
2569 }
2570 }
2571
2572 if (json)
2573 json_paths = json_object_new_array();
2574
2575 /* Prefix and num paths displayed once per prefix. */
2576 route_vty_out_detail_header(vty, bgp, dest, (struct prefix *)&p, NULL,
2577 afi, safi, json);
2578
2579 evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
2580
2581 /* Display each path for this prefix. */
2582 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2583 json_object *json_path = NULL;
2584
2585 /* skip non-matching MACs */
2586 if (ip && mac &&
2587 memcmp(mac, evpn_type2_path_info_get_mac(pi),
2588 sizeof(*mac)) != 0)
2589 continue;
2590
2591 if (json)
2592 json_path = json_object_new_array();
2593
2594 /*
2595 * VNI table MAC-IP prefixes don't have MAC so
2596 * make sure it's set from path info
2597 * here.
2598 */
2599 if (is_evpn_prefix_ipaddr_none(evp)) {
2600 /* VNI MAC -> Global */
2601 evpn_type2_prefix_global_copy(
2602 (struct prefix_evpn *)&tmp_p, evp,
2603 NULL /* mac */,
2604 evpn_type2_path_info_get_ip(pi));
2605 } else {
2606 /* VNI IP -> Global */
2607 evpn_type2_prefix_global_copy(
2608 (struct prefix_evpn *)&tmp_p, evp,
2609 evpn_type2_path_info_get_mac(pi),
2610 NULL /* ip */);
2611 }
2612
2613 route_vty_out_detail(vty, bgp, dest, (struct prefix *)&tmp_p,
2614 pi, afi, safi, RPKI_NOT_BEING_USED,
2615 json_path);
2616
2617 if (json)
2618 json_object_array_add(json_paths, json_path);
2619
2620 path_cnt++;
2621 }
2622
2623 if (json) {
2624 if (path_cnt)
2625 json_object_object_add(json, "paths", json_paths);
2626
2627 json_object_int_add(json, "numPaths", path_cnt);
2628 } else {
2629 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2630 path_cnt);
2631 }
2632
2633 bgp_dest_unlock_node(dest);
2634 }
2635
2636 /* Disaplay EVPN routes for a ESI - VTY handler */
2637 static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2638 esi_t *esi, json_object *json)
2639 {
2640 struct bgp_evpn_es *es = NULL;
2641
2642 /* locate the ES */
2643 es = bgp_evpn_es_find(esi);
2644 if (!es) {
2645 if (!json)
2646 vty_out(vty, "ESI not found\n");
2647 return;
2648 }
2649
2650 show_esi_routes(bgp, es, vty, json);
2651 }
2652
2653 /*
2654 * Display EVPN routes for a VNI - vty handler.
2655 * If 'type' is non-zero, only routes matching that type are shown.
2656 * If the vtep_ip is non zero, only routes behind that vtep are shown
2657 */
2658 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2659 int type, bool mac_table,
2660 struct in_addr vtep_ip, json_object *json)
2661 {
2662 struct bgpevpn *vpn;
2663
2664 /* Locate VNI. */
2665 vpn = bgp_evpn_lookup_vni(bgp, vni);
2666 if (!vpn) {
2667 if (!json)
2668 vty_out(vty, "VNI not found\n");
2669 return;
2670 }
2671
2672 /* Walk this VNI's route table and display appropriate routes. */
2673 show_vni_routes(bgp, vpn, vty, type, mac_table, vtep_ip, json, 0);
2674 }
2675
2676 /*
2677 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2678 * IP (vty handler). By definition, only matching type-2 route will be
2679 * displayed.
2680 */
2681 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2682 struct prefix_rd *prd, struct ethaddr *mac,
2683 struct ipaddr *ip, json_object *json)
2684 {
2685 struct prefix_evpn p;
2686 struct bgp_dest *dest;
2687 struct bgp_path_info *pi;
2688 afi_t afi;
2689 safi_t safi;
2690 uint32_t path_cnt = 0;
2691 json_object *json_paths = NULL;
2692
2693 afi = AFI_L2VPN;
2694 safi = SAFI_EVPN;
2695
2696 /* See if route exists. Look for both non-sticky and sticky. */
2697 build_evpn_type2_prefix(&p, mac, ip);
2698 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2699 (struct prefix *)&p, prd);
2700 if (!dest || !bgp_dest_has_bgp_path_info_data(dest)) {
2701 if (!json)
2702 vty_out(vty, "%% Network not in table\n");
2703
2704 if (dest)
2705 bgp_dest_unlock_node(dest);
2706
2707 return;
2708 }
2709
2710 /* Prefix and num paths displayed once per prefix. */
2711 route_vty_out_detail_header(vty, bgp, dest, bgp_dest_get_prefix(dest),
2712 prd, afi, safi, json);
2713
2714 if (json)
2715 json_paths = json_object_new_array();
2716
2717 /* Display each path for this prefix. */
2718 for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
2719 json_object *json_path = NULL;
2720
2721 if (json)
2722 json_path = json_object_new_array();
2723
2724 route_vty_out_detail(vty, bgp, dest, bgp_dest_get_prefix(dest),
2725 pi, afi, safi, RPKI_NOT_BEING_USED,
2726 json_path);
2727
2728 if (json)
2729 json_object_array_add(json_paths, json_path);
2730
2731 path_cnt++;
2732 }
2733
2734 if (json && path_cnt) {
2735 if (path_cnt)
2736 json_object_object_addf(json, json_paths, "%pFX", &p);
2737 json_object_int_add(json, "numPaths", path_cnt);
2738 } else {
2739 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2740 path_cnt);
2741 }
2742
2743 bgp_dest_unlock_node(dest);
2744 }
2745
2746 /*
2747 * Display BGP EVPN routing table -- for specific RD (vty handler)
2748 * If 'type' is non-zero, only routes matching that type are shown.
2749 */
2750 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
2751 struct prefix_rd *prd, int type,
2752 json_object *json)
2753 {
2754 struct bgp_dest *rd_dest;
2755 struct bgp_table *table;
2756 struct bgp_dest *dest;
2757 struct bgp_path_info *pi;
2758 int rd_header = 1;
2759 afi_t afi;
2760 safi_t safi;
2761 uint32_t prefix_cnt, path_cnt;
2762 json_object *json_rd = NULL;
2763 int add_rd_to_json = 0;
2764
2765 afi = AFI_L2VPN;
2766 safi = SAFI_EVPN;
2767 prefix_cnt = path_cnt = 0;
2768
2769 rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2770 if (!rd_dest)
2771 return;
2772
2773 table = bgp_dest_get_bgp_table_info(rd_dest);
2774 if (table == NULL) {
2775 bgp_dest_unlock_node(rd_dest);
2776 return;
2777 }
2778
2779 if (json) {
2780 json_rd = json_object_new_object();
2781 json_object_string_addf(json_rd, "rd", "%pRD", prd);
2782 }
2783
2784 bgp_dest_unlock_node(rd_dest);
2785
2786 /* Display all prefixes with this RD. */
2787 for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest)) {
2788 const struct prefix_evpn *evp =
2789 (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
2790 json_object *json_prefix = NULL;
2791 json_object *json_paths = NULL;
2792 int add_prefix_to_json = 0;
2793
2794 if (type && evp->prefix.route_type != type)
2795 continue;
2796
2797 if (json)
2798 json_prefix = json_object_new_object();
2799
2800 pi = bgp_dest_get_bgp_path_info(dest);
2801 if (pi) {
2802 /* RD header and legend - once overall. */
2803 if (rd_header && !json) {
2804 vty_out(vty,
2805 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2806 vty_out(vty,
2807 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2808 vty_out(vty,
2809 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2810 vty_out(vty,
2811 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2812 vty_out(vty,
2813 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2814 rd_header = 0;
2815 }
2816
2817 /* Prefix and num paths displayed once per prefix. */
2818 route_vty_out_detail_header(
2819 vty, bgp, dest, bgp_dest_get_prefix(dest), prd,
2820 afi, safi, json_prefix);
2821
2822 prefix_cnt++;
2823 }
2824
2825 if (json)
2826 json_paths = json_object_new_array();
2827
2828 /* Display each path for this prefix. */
2829 for (; pi; pi = pi->next) {
2830 json_object *json_path = NULL;
2831
2832 if (json)
2833 json_path = json_object_new_array();
2834
2835 route_vty_out_detail(
2836 vty, bgp, dest, bgp_dest_get_prefix(dest), pi,
2837 afi, safi, RPKI_NOT_BEING_USED, json_path);
2838
2839 if (json)
2840 json_object_array_add(json_paths, json_path);
2841
2842 path_cnt++;
2843 add_prefix_to_json = 1;
2844 add_rd_to_json = 1;
2845 }
2846
2847 if (json) {
2848 if (add_prefix_to_json) {
2849 json_object_object_add(json_prefix, "paths",
2850 json_paths);
2851 json_object_object_addf(json_rd, json_prefix,
2852 "%pFX", evp);
2853 } else {
2854 json_object_free(json_paths);
2855 json_object_free(json_prefix);
2856 json_paths = NULL;
2857 json_prefix = NULL;
2858 }
2859 }
2860 }
2861
2862 if (json) {
2863 if (add_rd_to_json)
2864 json_object_object_addf(json, json_rd, "%pRD", prd);
2865 else {
2866 json_object_free(json_rd);
2867 json_rd = NULL;
2868 }
2869
2870 json_object_int_add(json, "numPrefix", prefix_cnt);
2871 json_object_int_add(json, "numPaths", path_cnt);
2872 } else {
2873 if (prefix_cnt == 0)
2874 vty_out(vty, "No prefixes exist with this RD%s\n",
2875 type ? " (of requested type)" : "");
2876 else
2877 vty_out(vty,
2878 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2879 prefix_cnt, path_cnt,
2880 type ? " (of requested type)" : "");
2881 }
2882 }
2883
2884 /*
2885 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2886 * (vty handler). Only matching type-2 routes will be displayed.
2887 */
2888 static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
2889 struct ethaddr *mac, struct ipaddr *ip,
2890 json_object *json)
2891 {
2892 struct bgp_dest *rd_dest;
2893 struct bgp_table *table;
2894 struct bgp_dest *dest;
2895 struct bgp_path_info *pi;
2896 afi_t afi = AFI_L2VPN;
2897 safi_t safi = SAFI_EVPN;
2898 uint32_t prefix_cnt, path_cnt;
2899 prefix_cnt = path_cnt = 0;
2900
2901 /* EVPN routing table is a 2-level table with the first level being
2902 * the RD. We need to look in every RD we know about.
2903 */
2904 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
2905 rd_dest = bgp_route_next(rd_dest)) {
2906 json_object *json_paths = NULL; /* paths array for prefix */
2907 json_object *json_prefix = NULL; /* prefix within an RD */
2908 json_object *json_rd = NULL; /* holds all prefixes for RD */
2909 char rd_str[RD_ADDRSTRLEN];
2910 int add_rd_to_json = 0;
2911 struct prefix_evpn ep;
2912 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
2913
2914 table = bgp_dest_get_bgp_table_info(rd_dest);
2915 if (table == NULL)
2916 continue;
2917
2918 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
2919 sizeof(rd_str));
2920
2921 /* Construct an RT-2 from the user-supplied mac(ip),
2922 * then search the l2vpn evpn table for it.
2923 */
2924 build_evpn_type2_prefix(&ep, mac, ip);
2925 dest = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2926 (struct prefix *)&ep,
2927 (struct prefix_rd *)rd_destp);
2928 if (!dest)
2929 continue;
2930
2931 if (json)
2932 json_rd = json_object_new_object();
2933
2934 const struct prefix *p = bgp_dest_get_prefix(dest);
2935
2936 pi = bgp_dest_get_bgp_path_info(dest);
2937 if (pi) {
2938 /* RD header - per RD. */
2939 bgp_evpn_show_route_rd_header(vty, rd_dest, json_rd,
2940 rd_str, RD_ADDRSTRLEN);
2941 prefix_cnt++;
2942 }
2943
2944 if (json) {
2945 json_prefix = json_object_new_object();
2946 json_paths = json_object_new_array();
2947 json_object_string_addf(json_prefix, "prefix", "%pFX",
2948 p);
2949 json_object_int_add(json_prefix, "prefixLen",
2950 p->prefixlen);
2951 } else
2952 /* Prefix and num paths displayed once per prefix. */
2953 route_vty_out_detail_header(
2954 vty, bgp, dest, p, (struct prefix_rd *)rd_destp,
2955 AFI_L2VPN, SAFI_EVPN, json_prefix);
2956
2957 /* For EVPN, the prefix is displayed for each path (to
2958 * fit in with code that already exists).
2959 */
2960 for (; pi; pi = pi->next) {
2961 json_object *json_path = NULL;
2962
2963 add_rd_to_json = 1;
2964 path_cnt++;
2965
2966 if (json)
2967 json_path = json_object_new_array();
2968
2969 route_vty_out_detail(vty, bgp, dest, p, pi, AFI_L2VPN,
2970 SAFI_EVPN, RPKI_NOT_BEING_USED,
2971 json_path);
2972
2973 if (json)
2974 json_object_array_add(json_paths, json_path);
2975 else
2976 vty_out(vty, "\n");
2977 }
2978
2979 if (json) {
2980 json_object_object_add(json_prefix, "paths",
2981 json_paths);
2982 json_object_object_addf(json_rd, json_prefix, "%pFX",
2983 p);
2984 if (add_rd_to_json)
2985 json_object_object_add(json, rd_str, json_rd);
2986 else {
2987 json_object_free(json_rd);
2988 json_rd = NULL;
2989 }
2990 }
2991
2992 bgp_dest_unlock_node(dest);
2993 }
2994
2995 if (json) {
2996 json_object_int_add(json, "numPrefix", prefix_cnt);
2997 json_object_int_add(json, "numPaths", path_cnt);
2998 } else {
2999 if (prefix_cnt == 0) {
3000 vty_out(vty, "No Matching EVPN prefixes exist\n");
3001 } else {
3002 vty_out(vty, "Displayed %u prefixes (%u paths)\n",
3003 prefix_cnt, path_cnt);
3004 }
3005 }
3006 }
3007
3008 /*
3009 * Display BGP EVPN routing table - all routes (vty handler).
3010 * If 'type' is non-zero, only routes matching that type are shown.
3011 */
3012 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3013 json_object *json, int detail)
3014 {
3015 struct bgp_dest *rd_dest;
3016 struct bgp_table *table;
3017 struct bgp_dest *dest;
3018 struct bgp_path_info *pi;
3019 int header = detail ? 0 : 1;
3020 int rd_header;
3021 afi_t afi;
3022 safi_t safi;
3023 uint32_t prefix_cnt, path_cnt;
3024
3025 afi = AFI_L2VPN;
3026 safi = SAFI_EVPN;
3027 prefix_cnt = path_cnt = 0;
3028
3029 /* EVPN routing table is a 2-level table with the first level being
3030 * the RD.
3031 */
3032 for (rd_dest = bgp_table_top(bgp->rib[afi][safi]); rd_dest;
3033 rd_dest = bgp_route_next(rd_dest)) {
3034 char rd_str[RD_ADDRSTRLEN];
3035 json_object *json_rd = NULL; /* contains routes for an RD */
3036 int add_rd_to_json = 0;
3037 uint64_t tbl_ver;
3038 const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
3039
3040 table = bgp_dest_get_bgp_table_info(rd_dest);
3041 if (table == NULL)
3042 continue;
3043
3044 tbl_ver = table->version;
3045 prefix_rd2str((struct prefix_rd *)rd_destp, rd_str,
3046 sizeof(rd_str));
3047
3048 if (json)
3049 json_rd = json_object_new_object();
3050
3051 rd_header = 1;
3052
3053 /* Display all prefixes for an RD */
3054 for (dest = bgp_table_top(table); dest;
3055 dest = bgp_route_next(dest)) {
3056 json_object *json_prefix =
3057 NULL; /* contains prefix under a RD */
3058 json_object *json_paths =
3059 NULL; /* array of paths under a prefix*/
3060 const struct prefix_evpn *evp =
3061 (const struct prefix_evpn *)bgp_dest_get_prefix(
3062 dest);
3063 int add_prefix_to_json = 0;
3064 const struct prefix *p = bgp_dest_get_prefix(dest);
3065
3066 if (type && evp->prefix.route_type != type)
3067 continue;
3068
3069 pi = bgp_dest_get_bgp_path_info(dest);
3070 if (pi) {
3071 /* Overall header/legend displayed once. */
3072 if (header) {
3073 bgp_evpn_show_route_header(vty, bgp,
3074 tbl_ver,
3075 json);
3076 if (!json)
3077 vty_out(vty,
3078 "%19s Extended Community\n"
3079 , " ");
3080 header = 0;
3081 }
3082
3083 /* RD header - per RD. */
3084 if (rd_header) {
3085 bgp_evpn_show_route_rd_header(
3086 vty, rd_dest, json_rd, rd_str,
3087 RD_ADDRSTRLEN);
3088 rd_header = 0;
3089 }
3090
3091 prefix_cnt++;
3092 }
3093
3094 if (json) {
3095 json_prefix = json_object_new_object();
3096 json_paths = json_object_new_array();
3097 json_object_string_addf(json_prefix, "prefix",
3098 "%pFX", p);
3099 json_object_int_add(json_prefix, "prefixLen",
3100 p->prefixlen);
3101 }
3102
3103 /* Prefix and num paths displayed once per prefix. */
3104 if (detail)
3105 route_vty_out_detail_header(
3106 vty, bgp, dest,
3107 bgp_dest_get_prefix(dest),
3108 (struct prefix_rd *)rd_destp, AFI_L2VPN,
3109 SAFI_EVPN, json_prefix);
3110
3111 /* For EVPN, the prefix is displayed for each path (to
3112 * fit in
3113 * with code that already exists).
3114 */
3115 for (; pi; pi = pi->next) {
3116 json_object *json_path = NULL;
3117
3118 path_cnt++;
3119 add_prefix_to_json = 1;
3120 add_rd_to_json = 1;
3121
3122 if (json)
3123 json_path = json_object_new_array();
3124
3125 if (detail) {
3126 route_vty_out_detail(
3127 vty, bgp, dest,
3128 bgp_dest_get_prefix(dest), pi,
3129 AFI_L2VPN, SAFI_EVPN,
3130 RPKI_NOT_BEING_USED, json_path);
3131 } else
3132 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
3133 json_path, false);
3134
3135 if (json)
3136 json_object_array_add(json_paths,
3137 json_path);
3138 }
3139
3140 if (json) {
3141 if (add_prefix_to_json) {
3142 json_object_object_add(json_prefix,
3143 "paths",
3144 json_paths);
3145 json_object_object_addf(json_rd,
3146 json_prefix,
3147 "%pFX", p);
3148 } else {
3149 json_object_free(json_prefix);
3150 json_object_free(json_paths);
3151 json_prefix = NULL;
3152 json_paths = NULL;
3153 }
3154 }
3155 }
3156
3157 if (json) {
3158 if (add_rd_to_json)
3159 json_object_object_add(json, rd_str, json_rd);
3160 else {
3161 json_object_free(json_rd);
3162 json_rd = NULL;
3163 }
3164 }
3165 }
3166
3167 if (json) {
3168 json_object_int_add(json, "numPrefix", prefix_cnt);
3169 json_object_int_add(json, "numPaths", path_cnt);
3170 } else {
3171 if (prefix_cnt == 0) {
3172 vty_out(vty, "No EVPN prefixes %sexist\n",
3173 type ? "(of requested type) " : "");
3174 } else {
3175 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
3176 prefix_cnt, path_cnt,
3177 type ? " (of requested type)" : "");
3178 }
3179 }
3180 }
3181
3182 int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3183 bool use_json, int detail)
3184 {
3185 json_object *json = NULL;
3186
3187 if (use_json)
3188 json = json_object_new_object();
3189
3190 evpn_show_all_routes(vty, bgp, type, json, detail);
3191
3192 if (use_json)
3193 vty_json(vty, json);
3194 return CMD_SUCCESS;
3195 }
3196
3197 /*
3198 * Display specified VNI (vty handler)
3199 */
3200 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
3201 json_object *json)
3202 {
3203 uint8_t found = 0;
3204 struct bgpevpn *vpn;
3205
3206 vpn = bgp_evpn_lookup_vni(bgp, vni);
3207 if (vpn) {
3208 found = 1;
3209 display_vni(vty, vpn, json);
3210 } else {
3211 struct bgp *bgp_temp;
3212 struct listnode *node = NULL;
3213
3214 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3215 if (bgp_temp->l3vni == vni) {
3216 found = 1;
3217 display_l3vni(vty, bgp_temp, json);
3218 }
3219 }
3220 }
3221
3222 if (!found) {
3223 if (json) {
3224 vty_out(vty, "{}\n");
3225 } else {
3226 vty_out(vty, "VNI not found\n");
3227 return;
3228 }
3229 }
3230 }
3231
3232 /*
3233 * Display a VNI (upon user query).
3234 */
3235 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
3236 json_object *json)
3237 {
3238 void *args[2];
3239 struct bgp *bgp_temp = NULL;
3240 struct listnode *node;
3241
3242
3243 if (!json) {
3244 vty_out(vty, "Flags: * - Kernel\n");
3245 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3246 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3247 }
3248
3249 /* print all L2 VNIS */
3250 args[0] = vty;
3251 args[1] = json;
3252 hash_iterate(bgp->vnihash,
3253 (void (*)(struct hash_bucket *, void *))show_vni_entry,
3254 args);
3255
3256 /* print all L3 VNIs */
3257 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
3258 show_l3vni_entry(vty, bgp_temp, json);
3259 }
3260
3261 /*
3262 * evpn - enable advertisement of svi MAC-IP
3263 */
3264 static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
3265 uint32_t set)
3266 {
3267 if (!vpn) {
3268 if (set && bgp->evpn_info->advertise_svi_macip)
3269 return;
3270 else if (!set && !bgp->evpn_info->advertise_svi_macip)
3271 return;
3272
3273 bgp->evpn_info->advertise_svi_macip = set;
3274 bgp_zebra_advertise_svi_macip(bgp,
3275 bgp->evpn_info->advertise_svi_macip, 0);
3276 } else {
3277 if (set && vpn->advertise_svi_macip)
3278 return;
3279 else if (!set && !vpn->advertise_svi_macip)
3280 return;
3281
3282 vpn->advertise_svi_macip = set;
3283 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
3284 vpn->vni);
3285 }
3286 }
3287
3288 /*
3289 * evpn - enable advertisement of default g/w
3290 */
3291 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
3292 {
3293 if (!vpn) {
3294 if (bgp->advertise_gw_macip)
3295 return;
3296
3297 bgp->advertise_gw_macip = 1;
3298 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3299 } else {
3300 if (vpn->advertise_gw_macip)
3301 return;
3302
3303 vpn->advertise_gw_macip = 1;
3304 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3305 vpn->vni);
3306 }
3307 return;
3308 }
3309
3310 /*
3311 * evpn - disable advertisement of default g/w
3312 */
3313 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
3314 struct bgpevpn *vpn)
3315 {
3316 if (!vpn) {
3317 if (!bgp->advertise_gw_macip)
3318 return;
3319
3320 bgp->advertise_gw_macip = 0;
3321 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3322 } else {
3323 if (!vpn->advertise_gw_macip)
3324 return;
3325
3326 vpn->advertise_gw_macip = 0;
3327 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3328 vpn->vni);
3329 }
3330 return;
3331 }
3332
3333 /*
3334 * evpn - enable advertisement of default g/w
3335 */
3336 static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
3337 afi_t afi, bool add)
3338 {
3339 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
3340
3341 if (add) {
3342 /* bail if we are already advertising default route */
3343 if (evpn_default_originate_set(bgp_vrf, afi, safi))
3344 return;
3345
3346 if (afi == AFI_IP)
3347 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3348 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3349 else if (afi == AFI_IP6)
3350 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3351 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3352 } else {
3353 /* bail out if we havent advertised the default route */
3354 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
3355 return;
3356 if (afi == AFI_IP)
3357 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3358 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3359 else if (afi == AFI_IP6)
3360 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3361 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3362 }
3363
3364 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
3365 }
3366
3367 /*
3368 * evpn - enable advertisement of default g/w
3369 */
3370 static void evpn_set_advertise_subnet(struct bgp *bgp,
3371 struct bgpevpn *vpn)
3372 {
3373 if (vpn->advertise_subnet)
3374 return;
3375
3376 vpn->advertise_subnet = 1;
3377 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3378 }
3379
3380 /*
3381 * evpn - disable advertisement of default g/w
3382 */
3383 static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
3384 {
3385 if (!vpn->advertise_subnet)
3386 return;
3387
3388 vpn->advertise_subnet = 0;
3389 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3390 }
3391
3392 /*
3393 * EVPN (VNI advertisement) enabled. Register with zebra.
3394 */
3395 static void evpn_set_advertise_all_vni(struct bgp *bgp)
3396 {
3397 bgp->advertise_all_vni = 1;
3398 bgp_set_evpn(bgp);
3399 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3400 }
3401
3402 /*
3403 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3404 * cache, EVPN routes (delete and withdraw from peers).
3405 */
3406 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
3407 {
3408 bgp->advertise_all_vni = 0;
3409 bgp_set_evpn(bgp_get_default());
3410 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3411 bgp_evpn_cleanup_on_disable(bgp);
3412 }
3413
3414 /* Set resolve overlay index flag */
3415 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
3416 {
3417 if (set == bgp->resolve_overlay_index)
3418 return;
3419
3420 if (set) {
3421 bgp->resolve_overlay_index = true;
3422 hash_iterate(bgp->vnihash,
3423 (void (*)(struct hash_bucket *, void *))
3424 bgp_evpn_handle_resolve_overlay_index_set,
3425 NULL);
3426 } else {
3427 hash_iterate(
3428 bgp->vnihash,
3429 (void (*)(struct hash_bucket *, void *))
3430 bgp_evpn_handle_resolve_overlay_index_unset,
3431 NULL);
3432 bgp->resolve_overlay_index = false;
3433 }
3434 }
3435
3436 /*
3437 * EVPN - use RFC8365 to auto-derive RT
3438 */
3439 static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3440 {
3441 bgp->advertise_autort_rfc8365 = 1;
3442 bgp_evpn_handle_autort_change(bgp);
3443 }
3444
3445 /*
3446 * EVPN - don't use RFC8365 to auto-derive RT
3447 */
3448 static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3449 {
3450 bgp->advertise_autort_rfc8365 = 0;
3451 bgp_evpn_handle_autort_change(bgp);
3452 }
3453
3454 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
3455 {
3456 char *ecom_str;
3457 struct listnode *node, *nnode;
3458 struct ecommunity *ecom;
3459
3460 if (is_vni_configured(vpn)) {
3461 vty_out(vty, " vni %u\n", vpn->vni);
3462 if (is_rd_configured(vpn))
3463 vty_out(vty, " rd %pRD\n", &vpn->prd);
3464
3465 if (is_import_rt_configured(vpn)) {
3466 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3467 ecom)) {
3468 ecom_str = ecommunity_ecom2str(
3469 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3470 vty_out(vty, " route-target import %s\n",
3471 ecom_str);
3472 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3473 }
3474 }
3475
3476 if (is_export_rt_configured(vpn)) {
3477 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3478 ecom)) {
3479 ecom_str = ecommunity_ecom2str(
3480 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3481 vty_out(vty, " route-target export %s\n",
3482 ecom_str);
3483 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3484 }
3485 }
3486
3487 if (vpn->advertise_gw_macip)
3488 vty_out(vty, " advertise-default-gw\n");
3489
3490 if (vpn->advertise_svi_macip)
3491 vty_out(vty, " advertise-svi-ip\n");
3492
3493 if (vpn->advertise_subnet)
3494 vty_out(vty, " advertise-subnet\n");
3495
3496 vty_out(vty, " exit-vni\n");
3497 }
3498 }
3499
3500 #include "bgpd/bgp_evpn_vty_clippy.c"
3501
3502 DEFPY(bgp_evpn_flood_control,
3503 bgp_evpn_flood_control_cmd,
3504 "[no$no] flooding <disable$disable|head-end-replication$her>",
3505 NO_STR
3506 "Specify handling for BUM packets\n"
3507 "Do not flood any BUM packets\n"
3508 "Flood BUM packets using head-end replication\n")
3509 {
3510 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3511 enum vxlan_flood_control flood_ctrl;
3512
3513 if (!bgp)
3514 return CMD_WARNING;
3515
3516 if (disable && !no)
3517 flood_ctrl = VXLAN_FLOOD_DISABLED;
3518 else if (her || no)
3519 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3520 else
3521 return CMD_WARNING;
3522
3523 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3524 return CMD_SUCCESS;
3525
3526 bgp->vxlan_flood_ctrl = flood_ctrl;
3527 bgp_evpn_flood_control_change(bgp);
3528
3529 return CMD_SUCCESS;
3530 }
3531
3532 DEFUN (bgp_evpn_advertise_default_gw_vni,
3533 bgp_evpn_advertise_default_gw_vni_cmd,
3534 "advertise-default-gw",
3535 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3536 {
3537 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3538 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3539
3540 if (!bgp)
3541 return CMD_WARNING;
3542
3543 evpn_set_advertise_default_gw(bgp, vpn);
3544
3545 return CMD_SUCCESS;
3546 }
3547
3548 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3549 no_bgp_evpn_advertise_default_gw_vni_cmd,
3550 "no advertise-default-gw",
3551 NO_STR
3552 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3553 {
3554 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3555 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3556
3557 if (!bgp)
3558 return CMD_WARNING;
3559
3560 evpn_unset_advertise_default_gw(bgp, vpn);
3561
3562 return CMD_SUCCESS;
3563 }
3564
3565
3566 DEFUN (bgp_evpn_advertise_default_gw,
3567 bgp_evpn_advertise_default_gw_cmd,
3568 "advertise-default-gw",
3569 "Advertise All default g/w mac-ip routes in EVPN\n")
3570 {
3571 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3572
3573 if (!bgp)
3574 return CMD_WARNING;
3575
3576 if (!EVPN_ENABLED(bgp)) {
3577 vty_out(vty,
3578 "This command is only supported under the EVPN VRF\n");
3579 return CMD_WARNING;
3580 }
3581
3582 evpn_set_advertise_default_gw(bgp, NULL);
3583
3584 return CMD_SUCCESS;
3585 }
3586
3587 DEFUN (no_bgp_evpn_advertise_default_gw,
3588 no_bgp_evpn_advertise_default_gw_cmd,
3589 "no advertise-default-gw",
3590 NO_STR
3591 "Withdraw All default g/w mac-ip routes from EVPN\n")
3592 {
3593 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3594
3595 if (!bgp)
3596 return CMD_WARNING;
3597
3598 evpn_unset_advertise_default_gw(bgp, NULL);
3599
3600 return CMD_SUCCESS;
3601 }
3602
3603 DEFUN (bgp_evpn_advertise_all_vni,
3604 bgp_evpn_advertise_all_vni_cmd,
3605 "advertise-all-vni",
3606 "Advertise All local VNIs\n")
3607 {
3608 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3609 struct bgp *bgp_evpn = NULL;
3610
3611 if (!bgp)
3612 return CMD_WARNING;
3613
3614 bgp_evpn = bgp_get_evpn();
3615 if (bgp_evpn && bgp_evpn != bgp) {
3616 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3617 bgp_evpn->name_pretty);
3618 return CMD_WARNING_CONFIG_FAILED;
3619 }
3620
3621 evpn_set_advertise_all_vni(bgp);
3622 return CMD_SUCCESS;
3623 }
3624
3625 DEFUN (no_bgp_evpn_advertise_all_vni,
3626 no_bgp_evpn_advertise_all_vni_cmd,
3627 "no advertise-all-vni",
3628 NO_STR
3629 "Advertise All local VNIs\n")
3630 {
3631 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3632
3633 if (!bgp)
3634 return CMD_WARNING;
3635 evpn_unset_advertise_all_vni(bgp);
3636 return CMD_SUCCESS;
3637 }
3638
3639 DEFUN (bgp_evpn_advertise_autort_rfc8365,
3640 bgp_evpn_advertise_autort_rfc8365_cmd,
3641 "autort rfc8365-compatible",
3642 "Auto-derivation of RT\n"
3643 "Auto-derivation of RT using RFC8365\n")
3644 {
3645 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3646
3647 if (!bgp)
3648 return CMD_WARNING;
3649 evpn_set_advertise_autort_rfc8365(bgp);
3650 return CMD_SUCCESS;
3651 }
3652
3653 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3654 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3655 "no autort rfc8365-compatible",
3656 NO_STR
3657 "Auto-derivation of RT\n"
3658 "Auto-derivation of RT using RFC8365\n")
3659 {
3660 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3661
3662 if (!bgp)
3663 return CMD_WARNING;
3664 evpn_unset_advertise_autort_rfc8365(bgp);
3665 return CMD_SUCCESS;
3666 }
3667
3668 DEFUN (bgp_evpn_default_originate,
3669 bgp_evpn_default_originate_cmd,
3670 "default-originate <ipv4 | ipv6>",
3671 "originate a default route\n"
3672 "ipv4 address family\n"
3673 "ipv6 address family\n")
3674 {
3675 afi_t afi = 0;
3676 int idx_afi = 0;
3677 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3678
3679 if (!bgp_vrf)
3680 return CMD_WARNING;
3681 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3682 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3683 return CMD_SUCCESS;
3684 }
3685
3686 DEFUN (no_bgp_evpn_default_originate,
3687 no_bgp_evpn_default_originate_cmd,
3688 "no default-originate <ipv4 | ipv6>",
3689 NO_STR
3690 "withdraw a default route\n"
3691 "ipv4 address family\n"
3692 "ipv6 address family\n")
3693 {
3694 afi_t afi = 0;
3695 int idx_afi = 0;
3696 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3697
3698 if (!bgp_vrf)
3699 return CMD_WARNING;
3700 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3701 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3702 return CMD_SUCCESS;
3703 }
3704
3705 DEFPY (dup_addr_detection,
3706 dup_addr_detection_cmd,
3707 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3708 "Duplicate address detection\n"
3709 "Max allowed moves before address detected as duplicate\n"
3710 "Num of max allowed moves (2-1000) default 5\n"
3711 "Duplicate address detection time\n"
3712 "Time in seconds (2-1800) default 180\n")
3713 {
3714 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3715
3716 if (!bgp_vrf)
3717 return CMD_WARNING;
3718
3719 if (!EVPN_ENABLED(bgp_vrf)) {
3720 vty_out(vty,
3721 "This command is only supported under the EVPN VRF\n");
3722 return CMD_WARNING;
3723 }
3724
3725 bgp_vrf->evpn_info->dup_addr_detect = true;
3726
3727 if (time_val)
3728 bgp_vrf->evpn_info->dad_time = time_val;
3729 if (max_moves_val)
3730 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3731
3732 bgp_zebra_dup_addr_detection(bgp_vrf);
3733
3734 return CMD_SUCCESS;
3735 }
3736
3737 DEFPY (dup_addr_detection_auto_recovery,
3738 dup_addr_detection_auto_recovery_cmd,
3739 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3740 "Duplicate address detection\n"
3741 "Duplicate address detection freeze\n"
3742 "Duplicate address detection permanent freeze\n"
3743 "Duplicate address detection freeze time (30-3600)\n")
3744 {
3745 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3746 uint32_t freeze_time = freeze_time_val;
3747
3748 if (!bgp_vrf)
3749 return CMD_WARNING;
3750
3751 if (!EVPN_ENABLED(bgp_vrf)) {
3752 vty_out(vty,
3753 "This command is only supported under the EVPN VRF\n");
3754 return CMD_WARNING;
3755 }
3756
3757 bgp_vrf->evpn_info->dup_addr_detect = true;
3758 bgp_vrf->evpn_info->dad_freeze = true;
3759 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3760
3761 bgp_zebra_dup_addr_detection(bgp_vrf);
3762
3763 return CMD_SUCCESS;
3764 }
3765
3766 DEFPY (no_dup_addr_detection,
3767 no_dup_addr_detection_cmd,
3768 "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3769 NO_STR
3770 "Duplicate address detection\n"
3771 "Max allowed moves before address detected as duplicate\n"
3772 "Num of max allowed moves (2-1000) default 5\n"
3773 "Duplicate address detection time\n"
3774 "Time in seconds (2-1800) default 180\n"
3775 "Duplicate address detection freeze\n"
3776 "Duplicate address detection permanent freeze\n"
3777 "Duplicate address detection freeze time (30-3600)\n")
3778 {
3779 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3780 uint32_t max_moves = (uint32_t)max_moves_val;
3781 uint32_t freeze_time = (uint32_t)freeze_time_val;
3782
3783 if (!bgp_vrf)
3784 return CMD_WARNING;
3785
3786 if (!EVPN_ENABLED(bgp_vrf)) {
3787 vty_out(vty,
3788 "This command is only supported under the EVPN VRF\n");
3789 return CMD_WARNING;
3790 }
3791
3792 if (argc == 2) {
3793 if (!bgp_vrf->evpn_info->dup_addr_detect)
3794 return CMD_SUCCESS;
3795 /* Reset all parameters to default. */
3796 bgp_vrf->evpn_info->dup_addr_detect = false;
3797 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3798 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3799 bgp_vrf->evpn_info->dad_freeze = false;
3800 bgp_vrf->evpn_info->dad_freeze_time = 0;
3801 } else {
3802 if (max_moves) {
3803 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3804 vty_out(vty,
3805 "%% Value does not match with config\n");
3806 return CMD_SUCCESS;
3807 }
3808 bgp_vrf->evpn_info->dad_max_moves =
3809 EVPN_DAD_DEFAULT_MAX_MOVES;
3810 }
3811
3812 if (time_val) {
3813 if (bgp_vrf->evpn_info->dad_time != time_val) {
3814 vty_out(vty,
3815 "%% Value does not match with config\n");
3816 return CMD_SUCCESS;
3817 }
3818 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3819 }
3820
3821 if (freeze_time) {
3822 if (bgp_vrf->evpn_info->dad_freeze_time
3823 != freeze_time) {
3824 vty_out(vty,
3825 "%% Value does not match with config\n");
3826 return CMD_SUCCESS;
3827 }
3828 bgp_vrf->evpn_info->dad_freeze_time = 0;
3829 bgp_vrf->evpn_info->dad_freeze = false;
3830 }
3831
3832 if (permanent_val) {
3833 if (bgp_vrf->evpn_info->dad_freeze_time) {
3834 vty_out(vty,
3835 "%% Value does not match with config\n");
3836 return CMD_SUCCESS;
3837 }
3838 bgp_vrf->evpn_info->dad_freeze = false;
3839 }
3840 }
3841
3842 bgp_zebra_dup_addr_detection(bgp_vrf);
3843
3844 return CMD_SUCCESS;
3845 }
3846
3847 DEFPY(bgp_evpn_advertise_svi_ip,
3848 bgp_evpn_advertise_svi_ip_cmd,
3849 "[no$no] advertise-svi-ip",
3850 NO_STR
3851 "Advertise svi mac-ip routes in EVPN\n")
3852 {
3853 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3854
3855 if (!bgp)
3856 return CMD_WARNING;
3857
3858 if (no)
3859 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3860 else {
3861 if (!EVPN_ENABLED(bgp)) {
3862 vty_out(vty,
3863 "This command is only supported under EVPN VRF\n");
3864 return CMD_WARNING;
3865 }
3866 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3867 }
3868
3869 return CMD_SUCCESS;
3870 }
3871
3872 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3873 bgp_evpn_advertise_svi_ip_vni_cmd,
3874 "[no$no] advertise-svi-ip",
3875 NO_STR
3876 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3877 {
3878 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3879 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3880
3881 if (!bgp)
3882 return CMD_WARNING;
3883
3884 if (no)
3885 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3886 else
3887 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3888
3889 return CMD_SUCCESS;
3890 }
3891
3892 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3893 bgp_evpn_advertise_vni_subnet_cmd,
3894 "advertise-subnet",
3895 "Advertise the subnet corresponding to VNI\n")
3896 {
3897 struct bgp *bgp_vrf = NULL;
3898 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3899 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3900
3901 if (!bgp)
3902 return CMD_WARNING;
3903
3904 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3905 if (!bgp_vrf)
3906 return CMD_WARNING;
3907
3908 evpn_set_advertise_subnet(bgp, vpn);
3909 return CMD_SUCCESS;
3910 }
3911
3912 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3913 no_bgp_evpn_advertise_vni_subnet_cmd,
3914 "no advertise-subnet",
3915 NO_STR
3916 "Advertise All local VNIs\n")
3917 {
3918 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3919 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3920
3921 if (!bgp)
3922 return CMD_WARNING;
3923
3924 evpn_unset_advertise_subnet(bgp, vpn);
3925 return CMD_SUCCESS;
3926 }
3927
3928 DEFUN (bgp_evpn_advertise_type5,
3929 bgp_evpn_advertise_type5_cmd,
3930 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
3931 "Advertise prefix routes\n"
3932 BGP_AFI_HELP_STR
3933 BGP_SAFI_HELP_STR
3934 "advertise gateway IP overlay index\n"
3935 "route-map for filtering specific routes\n"
3936 "Name of the route map\n")
3937 {
3938 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3939 int idx_afi = 0;
3940 int idx_safi = 0;
3941 int idx_rmap = 0;
3942 afi_t afi = 0;
3943 safi_t safi = 0;
3944 int ret = 0;
3945 int rmap_changed = 0;
3946 enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3947 int idx_oly = 0;
3948 bool adv_flag_changed = false;
3949
3950 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3951 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3952 argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3953
3954 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3955 if (ret) {
3956 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3957 rmap_changed = 1;
3958 else if (strcmp(argv[idx_rmap + 1]->arg,
3959 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3960 != 0)
3961 rmap_changed = 1;
3962 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3963 rmap_changed = 1;
3964 }
3965
3966 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3967 vty_out(vty,
3968 "%% Only ipv4 or ipv6 address families are supported\n");
3969 return CMD_WARNING;
3970 }
3971
3972 if (safi != SAFI_UNICAST) {
3973 vty_out(vty,
3974 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3975 return CMD_WARNING;
3976 }
3977
3978 if ((oly != OVERLAY_INDEX_TYPE_NONE)
3979 && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
3980 vty_out(vty, "%% Unknown overlay-index type specified\n");
3981 return CMD_WARNING;
3982 }
3983
3984 if (afi == AFI_IP) {
3985 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3986 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
3987 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3988 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
3989
3990 /*
3991 * this is the case for first time ever configuration
3992 * adv ipv4 unicast is enabled for the first time.
3993 * So no need to reset any flag
3994 */
3995 if (oly == OVERLAY_INDEX_TYPE_NONE)
3996 SET_FLAG(
3997 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3998 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
3999 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4000 SET_FLAG(
4001 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4002 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4003 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4004 && (!CHECK_FLAG(
4005 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4006 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
4007
4008 /*
4009 * This is modify case from gateway-ip
4010 * to no overlay index
4011 */
4012 adv_flag_changed = true;
4013 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4014 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4015 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4016 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4017 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4018 && (!CHECK_FLAG(
4019 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4020 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4021
4022 /*
4023 * This is modify case from no overlay index
4024 * to gateway-ip
4025 */
4026 adv_flag_changed = true;
4027 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4028 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4029 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4030 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4031 } else {
4032
4033 /*
4034 * Command is issued with the same option
4035 * (no overlay index or gateway-ip) which was
4036 * already configured. So nothing to do.
4037 * However, route-map may have been modified.
4038 * check if route-map has been modified.
4039 * If not, return an error
4040 */
4041 if (!rmap_changed)
4042 return CMD_WARNING;
4043 }
4044 } else {
4045 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4046 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
4047 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4048 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4049
4050 /*
4051 * this is the case for first time ever configuration
4052 * adv ipv6 unicast is enabled for the first time.
4053 * So no need to reset any flag
4054 */
4055 if (oly == OVERLAY_INDEX_TYPE_NONE)
4056 SET_FLAG(
4057 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4058 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4059 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4060 SET_FLAG(
4061 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4062 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4063 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4064 && (!CHECK_FLAG(
4065 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4066 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
4067
4068 /*
4069 * This is modify case from gateway-ip
4070 * to no overlay index
4071 */
4072 adv_flag_changed = true;
4073 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4074 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4075 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4076 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4077 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4078 && (!CHECK_FLAG(
4079 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4080 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4081
4082 /*
4083 * This is modify case from no overlay index
4084 * to gateway-ip
4085 */
4086 adv_flag_changed = true;
4087 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4088 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4089 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4090 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4091 } else {
4092
4093 /*
4094 * Command is issued with the same option
4095 * (no overlay index or gateway-ip) which was
4096 * already configured. So nothing to do.
4097 * However, route-map may have been modified.
4098 * check if route-map has been modified.
4099 * If not, return an error
4100 */
4101 if (!rmap_changed)
4102 return CMD_WARNING;
4103 }
4104 }
4105
4106 if ((rmap_changed) || (adv_flag_changed)) {
4107
4108 /* If either of these are changed, then FRR needs to
4109 * withdraw already advertised type5 routes.
4110 */
4111 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4112 if (rmap_changed) {
4113 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4114 XFREE(MTYPE_ROUTE_MAP_NAME,
4115 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4116 route_map_counter_decrement(
4117 bgp_vrf->adv_cmd_rmap[afi][safi].map);
4118 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4119 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4120 }
4121 }
4122 }
4123
4124 /* set the route-map for advertise command */
4125 if (ret && argv[idx_rmap + 1]->arg) {
4126 bgp_vrf->adv_cmd_rmap[afi][safi].name =
4127 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
4128 bgp_vrf->adv_cmd_rmap[afi][safi].map =
4129 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
4130 route_map_counter_increment(
4131 bgp_vrf->adv_cmd_rmap[afi][safi].map);
4132 }
4133
4134 /* advertise type-5 routes */
4135 if (advertise_type5_routes(bgp_vrf, afi))
4136 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
4137 return CMD_SUCCESS;
4138 }
4139
4140 DEFUN (no_bgp_evpn_advertise_type5,
4141 no_bgp_evpn_advertise_type5_cmd,
4142 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
4143 NO_STR
4144 "Advertise prefix routes\n"
4145 BGP_AFI_HELP_STR
4146 BGP_SAFI_HELP_STR
4147 "route-map for filtering specific routes\n"
4148 "Name of the route map\n")
4149 {
4150 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4151 int idx_afi = 0;
4152 int idx_safi = 0;
4153 afi_t afi = 0;
4154 safi_t safi = 0;
4155
4156 if (!bgp_vrf)
4157 return CMD_WARNING;
4158
4159 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4160 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4161
4162 if (!(afi == AFI_IP || afi == AFI_IP6)) {
4163 vty_out(vty,
4164 "%% Only ipv4 or ipv6 address families are supported\n");
4165 return CMD_WARNING;
4166 }
4167
4168 if (safi != SAFI_UNICAST) {
4169 vty_out(vty,
4170 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4171 return CMD_WARNING;
4172 }
4173
4174 if (afi == AFI_IP) {
4175
4176 /* if we are not advertising ipv4 prefix as type-5
4177 * nothing to do
4178 */
4179 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4180 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4181 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4182 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4183 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4184 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4185 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4186 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4187 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4188 }
4189 } else {
4190
4191 /* if we are not advertising ipv6 prefix as type-5
4192 * nothing to do
4193 */
4194 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4195 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4196 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4197 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
4198 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4199 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4200 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4201 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4202 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4203 }
4204 }
4205
4206 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4207 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4208 XFREE(MTYPE_ROUTE_MAP_NAME,
4209 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4210 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4211 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4212 }
4213
4214 return CMD_SUCCESS;
4215 }
4216
4217 DEFPY (bgp_evpn_use_es_l3nhg,
4218 bgp_evpn_use_es_l3nhg_cmd,
4219 "[no$no] use-es-l3nhg",
4220 NO_STR
4221 "use L3 nexthop group for host routes with ES destination\n")
4222 {
4223 bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4224 return CMD_SUCCESS;
4225 }
4226
4227 DEFPY (bgp_evpn_ead_evi_rx_disable,
4228 bgp_evpn_ead_evi_rx_disable_cmd,
4229 "[no$no] disable-ead-evi-rx",
4230 NO_STR
4231 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4232 {
4233 bool ead_evi_rx = no? true :false;
4234
4235 if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4236 bgp_mh_info->ead_evi_rx = ead_evi_rx;
4237 bgp_evpn_switch_ead_evi_rx();
4238 }
4239 return CMD_SUCCESS;
4240 }
4241
4242 DEFPY (bgp_evpn_ead_evi_tx_disable,
4243 bgp_evpn_ead_evi_tx_disable_cmd,
4244 "[no$no] disable-ead-evi-tx",
4245 NO_STR
4246 "Don't advertise EAD-EVI for local ESs\n")
4247 {
4248 bgp_mh_info->ead_evi_tx = no? true :false;
4249 return CMD_SUCCESS;
4250 }
4251
4252 DEFPY (bgp_evpn_enable_resolve_overlay_index,
4253 bgp_evpn_enable_resolve_overlay_index_cmd,
4254 "[no$no] enable-resolve-overlay-index",
4255 NO_STR
4256 "Enable Recursive Resolution of type-5 route overlay index\n")
4257 {
4258 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4259
4260 if (bgp != bgp_get_evpn()) {
4261 vty_out(vty, "This command is only supported under EVPN VRF\n");
4262 return CMD_WARNING;
4263 }
4264
4265 bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4266 return CMD_SUCCESS;
4267 }
4268
4269 DEFPY (bgp_evpn_advertise_pip_ip_mac,
4270 bgp_evpn_advertise_pip_ip_mac_cmd,
4271 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4272 NO_STR
4273 "evpn system primary IP\n"
4274 IP_STR
4275 "ip address\n"
4276 MAC_STR MAC_STR MAC_STR)
4277 {
4278 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4279 struct bgp *bgp_evpn = NULL;
4280
4281 if (EVPN_ENABLED(bgp_vrf)) {
4282 vty_out(vty,
4283 "This command is supported under L3VNI BGP EVPN VRF\n");
4284 return CMD_WARNING_CONFIG_FAILED;
4285 }
4286 bgp_evpn = bgp_get_evpn();
4287
4288 if (!no) {
4289 /* pip is already enabled */
4290 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4291 return CMD_SUCCESS;
4292
4293 bgp_vrf->evpn_info->advertise_pip = true;
4294 if (ip.s_addr != INADDR_ANY) {
4295 /* Already configured with same IP */
4296 if (IPV4_ADDR_SAME(&ip,
4297 &bgp_vrf->evpn_info->pip_ip_static))
4298 return CMD_SUCCESS;
4299
4300 bgp_vrf->evpn_info->pip_ip_static = ip;
4301 bgp_vrf->evpn_info->pip_ip = ip;
4302 } else {
4303 bgp_vrf->evpn_info->pip_ip_static.s_addr
4304 = INADDR_ANY;
4305 /* default instance router-id assignemt */
4306 if (bgp_evpn)
4307 bgp_vrf->evpn_info->pip_ip =
4308 bgp_evpn->router_id;
4309 }
4310 /* parse sys mac */
4311 if (!is_zero_mac(&mac->eth_addr)) {
4312 /* Already configured with same MAC */
4313 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4314 &mac->eth_addr, ETH_ALEN) == 0)
4315 return CMD_SUCCESS;
4316
4317 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4318 &mac->eth_addr, ETH_ALEN);
4319 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4320 &bgp_vrf->evpn_info->pip_rmac_static,
4321 ETH_ALEN);
4322 } else {
4323 /* Copy zebra sys mac */
4324 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4325 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4326 &bgp_vrf->evpn_info->pip_rmac_zebra,
4327 ETH_ALEN);
4328 }
4329 } else {
4330 if (argc == 2) {
4331 if (!bgp_vrf->evpn_info->advertise_pip)
4332 return CMD_SUCCESS;
4333 /* Disable PIP feature */
4334 bgp_vrf->evpn_info->advertise_pip = false;
4335 /* copy anycast mac */
4336 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4337 &bgp_vrf->rmac, ETH_ALEN);
4338 } else {
4339 /* remove MAC-IP option retain PIP knob. */
4340 if ((ip.s_addr != INADDR_ANY) &&
4341 !IPV4_ADDR_SAME(&ip,
4342 &bgp_vrf->evpn_info->pip_ip_static)) {
4343 vty_out(vty,
4344 "%% BGP EVPN PIP IP does not match\n");
4345 return CMD_WARNING_CONFIG_FAILED;
4346 }
4347
4348 if (!is_zero_mac(&mac->eth_addr) &&
4349 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4350 &mac->eth_addr, ETH_ALEN) != 0) {
4351 vty_out(vty,
4352 "%% BGP EVPN PIP MAC does not match\n");
4353 return CMD_WARNING_CONFIG_FAILED;
4354 }
4355 /* pip_rmac can carry vrr_rmac reset only if it matches
4356 * with static value.
4357 */
4358 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4359 &bgp_vrf->evpn_info->pip_rmac_static,
4360 ETH_ALEN) == 0) {
4361 /* Copy zebra sys mac */
4362 if (!is_zero_mac(
4363 &bgp_vrf->evpn_info->pip_rmac_zebra))
4364 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4365 &bgp_vrf->evpn_info->pip_rmac_zebra,
4366 ETH_ALEN);
4367 else {
4368 /* copy anycast mac */
4369 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4370 &bgp_vrf->rmac, ETH_ALEN);
4371 }
4372 }
4373 }
4374 /* reset user configured sys MAC */
4375 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4376 /* reset user configured sys IP */
4377 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4378 /* Assign default PIP IP (bgp instance router-id) */
4379 if (bgp_evpn)
4380 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4381 else
4382 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4383 }
4384
4385 if (is_evpn_enabled()) {
4386 struct listnode *node = NULL;
4387 struct bgpevpn *vpn = NULL;
4388
4389 /*
4390 * At this point if bgp_evpn is NULL and evpn is enabled
4391 * something stupid has gone wrong
4392 */
4393 assert(bgp_evpn);
4394
4395 update_advertise_vrf_routes(bgp_vrf);
4396
4397 /* Update (svi) type-2 routes */
4398 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4399 if (!bgp_evpn_is_svi_macip_enabled(vpn))
4400 continue;
4401 update_routes_for_vni(bgp_evpn, vpn);
4402 }
4403 }
4404
4405 return CMD_SUCCESS;
4406 }
4407
4408 /*
4409 * Display VNI information - for all or a specific VNI
4410 */
4411 DEFUN(show_bgp_l2vpn_evpn_vni,
4412 show_bgp_l2vpn_evpn_vni_cmd,
4413 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
4414 SHOW_STR
4415 BGP_STR
4416 L2VPN_HELP_STR
4417 EVPN_HELP_STR
4418 "Show VNI\n"
4419 "VNI number\n"
4420 JSON_STR)
4421 {
4422 struct bgp *bgp_evpn;
4423 vni_t vni;
4424 int idx = 0;
4425 bool uj = false;
4426 json_object *json = NULL;
4427 uint32_t num_l2vnis = 0;
4428 uint32_t num_l3vnis = 0;
4429 uint32_t num_vnis = 0;
4430 struct listnode *node = NULL;
4431 struct bgp *bgp_temp = NULL;
4432
4433 uj = use_json(argc, argv);
4434
4435 bgp_evpn = bgp_get_evpn();
4436 if (!bgp_evpn)
4437 return CMD_WARNING;
4438
4439 if (!argv_find(argv, argc, "evpn", &idx))
4440 return CMD_WARNING;
4441
4442 if (uj)
4443 json = json_object_new_object();
4444
4445 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4446
4447 num_l2vnis = hashcount(bgp_evpn->vnihash);
4448
4449 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4450 if (bgp_temp->l3vni)
4451 num_l3vnis++;
4452 }
4453 num_vnis = num_l2vnis + num_l3vnis;
4454 if (uj) {
4455 json_object_string_add(json, "advertiseGatewayMacip",
4456 bgp_evpn->advertise_gw_macip
4457 ? "Enabled"
4458 : "Disabled");
4459 json_object_string_add(json, "advertiseSviMacIp",
4460 bgp_evpn->evpn_info->advertise_svi_macip
4461 ? "Enabled" : "Disabled");
4462 json_object_string_add(json, "advertiseAllVnis",
4463 is_evpn_enabled() ? "Enabled"
4464 : "Disabled");
4465 json_object_string_add(
4466 json, "flooding",
4467 bgp_evpn->vxlan_flood_ctrl ==
4468 VXLAN_FLOOD_HEAD_END_REPL
4469 ? "Head-end replication"
4470 : "Disabled");
4471 json_object_string_add(
4472 json, "vxlanFlooding",
4473 bgp_evpn->vxlan_flood_ctrl ==
4474 VXLAN_FLOOD_HEAD_END_REPL
4475 ? "Enabled"
4476 : "Disabled");
4477 json_object_int_add(json, "numVnis", num_vnis);
4478 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4479 json_object_int_add(json, "numL3Vnis", num_l3vnis);
4480 } else {
4481 vty_out(vty, "Advertise Gateway Macip: %s\n",
4482 bgp_evpn->advertise_gw_macip ? "Enabled"
4483 : "Disabled");
4484 vty_out(vty, "Advertise SVI Macip: %s\n",
4485 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
4486 : "Disabled");
4487 vty_out(vty, "Advertise All VNI flag: %s\n",
4488 is_evpn_enabled() ? "Enabled" : "Disabled");
4489 vty_out(vty, "BUM flooding: %s\n",
4490 bgp_evpn->vxlan_flood_ctrl ==
4491 VXLAN_FLOOD_HEAD_END_REPL
4492 ? "Head-end replication"
4493 : "Disabled");
4494 vty_out(vty, "VXLAN flooding: %s\n",
4495 bgp_evpn->vxlan_flood_ctrl ==
4496 VXLAN_FLOOD_HEAD_END_REPL
4497 ? "Enabled"
4498 : "Disabled");
4499 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4500 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
4501 }
4502 evpn_show_all_vnis(vty, bgp_evpn, json);
4503 } else {
4504 int vni_idx = 0;
4505
4506 if (!argv_find(argv, argc, "vni", &vni_idx))
4507 return CMD_WARNING;
4508
4509 /* Display specific VNI */
4510 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4511 evpn_show_vni(vty, bgp_evpn, vni, json);
4512 }
4513
4514 if (uj)
4515 vty_json(vty, json);
4516
4517 return CMD_SUCCESS;
4518 }
4519
4520 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4521 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4522 "show bgp l2vpn evpn vni remote-ip-hash",
4523 SHOW_STR
4524 BGP_STR
4525 L2VPN_HELP_STR
4526 EVPN_HELP_STR
4527 "Show VNI\n"
4528 "Remote IP hash\n")
4529 {
4530 struct bgp *bgp_evpn;
4531 int idx = 0;
4532
4533 bgp_evpn = bgp_get_evpn();
4534 if (!bgp_evpn)
4535 return CMD_WARNING;
4536
4537 if (!argv_find(argv, argc, "evpn", &idx))
4538 return CMD_WARNING;
4539
4540 hash_iterate(bgp_evpn->vnihash,
4541 (void (*)(struct hash_bucket *,
4542 void *))bgp_evpn_show_remote_ip_hash,
4543 vty);
4544
4545 return CMD_SUCCESS;
4546 }
4547
4548 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4549 show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4550 "show bgp l2vpn evpn vni-svi-hash",
4551 SHOW_STR
4552 BGP_STR
4553 L2VPN_HELP_STR
4554 EVPN_HELP_STR
4555 "Show vni-svi-hash\n")
4556 {
4557 struct bgp *bgp_evpn;
4558 int idx = 0;
4559
4560 bgp_evpn = bgp_get_evpn();
4561 if (!bgp_evpn)
4562 return CMD_WARNING;
4563
4564 if (!argv_find(argv, argc, "evpn", &idx))
4565 return CMD_WARNING;
4566
4567 hash_iterate(bgp_evpn->vni_svi_hash,
4568 (void (*)(struct hash_bucket *,
4569 void *))bgp_evpn_show_vni_svi_hash,
4570 vty);
4571
4572 return CMD_SUCCESS;
4573 }
4574
4575 DEFPY(show_bgp_l2vpn_evpn_es_evi,
4576 show_bgp_l2vpn_evpn_es_evi_cmd,
4577 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4578 SHOW_STR
4579 BGP_STR
4580 L2VPN_HELP_STR
4581 EVPN_HELP_STR
4582 "ES per EVI\n"
4583 "VxLAN Network Identifier\n"
4584 "VNI\n"
4585 JSON_STR
4586 "Detailed information\n")
4587 {
4588 if (vni)
4589 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4590 else
4591 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4592
4593 return CMD_SUCCESS;
4594 }
4595
4596 DEFPY(show_bgp_l2vpn_evpn_es,
4597 show_bgp_l2vpn_evpn_es_cmd,
4598 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4599 SHOW_STR
4600 BGP_STR
4601 L2VPN_HELP_STR
4602 EVPN_HELP_STR
4603 "Ethernet Segment\n"
4604 "ES ID\n"
4605 "Detailed information\n"
4606 JSON_STR)
4607 {
4608 esi_t esi;
4609
4610 if (esi_str) {
4611 if (!str_to_esi(esi_str, &esi)) {
4612 vty_out(vty, "%% Malformed ESI\n");
4613 return CMD_WARNING;
4614 }
4615 bgp_evpn_es_show_esi(vty, &esi, uj);
4616 } else {
4617
4618 bgp_evpn_es_show(vty, uj, !!detail);
4619 }
4620
4621 return CMD_SUCCESS;
4622 }
4623
4624 DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4625 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4626 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4627 "Ethernet Segment\n"
4628 "ES ID\n" JSON_STR)
4629 {
4630 esi_t esi;
4631
4632 if (esi_str) {
4633 if (!str_to_esi(esi_str, &esi)) {
4634 vty_out(vty, "%% Malformed ESI\n");
4635 return CMD_WARNING;
4636 }
4637 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4638 } else {
4639
4640 bgp_evpn_es_vrf_show(vty, uj, NULL);
4641 }
4642
4643 return CMD_SUCCESS;
4644 }
4645
4646 DEFPY(show_bgp_l2vpn_evpn_nh,
4647 show_bgp_l2vpn_evpn_nh_cmd,
4648 "show bgp l2vpn evpn next-hops [json$uj]",
4649 SHOW_STR
4650 BGP_STR
4651 L2VPN_HELP_STR
4652 EVPN_HELP_STR
4653 "Nexthops\n"
4654 JSON_STR)
4655 {
4656 bgp_evpn_nh_show(vty, uj);
4657
4658 return CMD_SUCCESS;
4659 }
4660
4661 /*
4662 * Display EVPN neighbor summary.
4663 */
4664 DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
4665 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
4666 SHOW_STR BGP_STR
4667 "bgp vrf\n"
4668 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4669 "Summary of BGP neighbor status\n"
4670 "Show only sessions in Established state\n"
4671 "Show only sessions not in Established state\n"
4672 "Show only the specified neighbor session\n"
4673 "Neighbor to display information about\n"
4674 "Neighbor to display information about\n"
4675 "Neighbor on BGP configured interface\n"
4676 "Show only the specified remote AS sessions\n"
4677 "AS number\n"
4678 "Internal (iBGP) AS sessions\n"
4679 "External (eBGP) AS sessions\n"
4680 "Shorten the information on BGP instances\n"
4681 "Increase table width for longer output\n" JSON_STR)
4682 {
4683 int idx_vrf = 0;
4684 int idx = 0;
4685 char *vrf = NULL;
4686 char *neighbor = NULL;
4687 as_t as = 0; /* 0 means AS filter not set */
4688 int as_type = AS_UNSPECIFIED;
4689 uint16_t show_flags = 0;
4690
4691 if (argv_find(argv, argc, "vrf", &idx_vrf))
4692 vrf = argv[++idx_vrf]->arg;
4693
4694 if (argv_find(argv, argc, "failed", &idx))
4695 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4696
4697 if (argv_find(argv, argc, "established", &idx))
4698 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4699
4700
4701 if (argv_find(argv, argc, "neighbor", &idx))
4702 neighbor = argv[idx + 1]->arg;
4703
4704 if (argv_find(argv, argc, "remote-as", &idx)) {
4705 if (argv[idx + 1]->arg[0] == 'i')
4706 as_type = AS_INTERNAL;
4707 else if (argv[idx + 1]->arg[0] == 'e')
4708 as_type = AS_EXTERNAL;
4709 else
4710 as = (as_t)atoi(argv[idx + 1]->arg);
4711 }
4712
4713 if (argv_find(argv, argc, "terse", &idx))
4714 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4715
4716 if (argv_find(argv, argc, "wide", &idx))
4717 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4718
4719 if (use_json(argc, argv))
4720 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4721
4722 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4723 as_type, as, show_flags);
4724 }
4725
4726 static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
4727 {
4728 if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
4729 *type = BGP_EVPN_MAC_IP_ROUTE;
4730 else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
4731 *type = BGP_EVPN_IMET_ROUTE;
4732 else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
4733 *type = BGP_EVPN_ES_ROUTE;
4734 else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
4735 *type = BGP_EVPN_AD_ROUTE;
4736 else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
4737 *type = BGP_EVPN_IP_PREFIX_ROUTE;
4738 else
4739 return -1;
4740
4741 return 0;
4742 }
4743
4744 int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
4745 {
4746 int type_idx = 0;
4747
4748 if (argv_find(argv, argc, "type", &type_idx)) {
4749 /* Specific type is requested */
4750 if (bgp_evpn_cli_parse_type_cmp(type,
4751 argv[type_idx + 1]->arg) != 0)
4752 return -1;
4753 }
4754
4755 return 0;
4756 }
4757
4758 /*
4759 * Display global EVPN routing table.
4760 */
4761 DEFUN(show_bgp_l2vpn_evpn_route,
4762 show_bgp_l2vpn_evpn_route_cmd,
4763 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
4764 SHOW_STR
4765 BGP_STR
4766 L2VPN_HELP_STR
4767 EVPN_HELP_STR
4768 EVPN_RT_HELP_STR
4769 "Display Detailed Information\n"
4770 EVPN_TYPE_HELP_STR
4771 EVPN_TYPE_ALL_LIST_HELP_STR
4772 JSON_STR)
4773 {
4774 struct bgp *bgp;
4775 int detail = 0;
4776 int type = 0;
4777 bool uj = false;
4778 json_object *json = NULL;
4779
4780 uj = use_json(argc, argv);
4781
4782 bgp = bgp_get_evpn();
4783 if (!bgp)
4784 return CMD_WARNING;
4785
4786 if (uj)
4787 json = json_object_new_object();
4788
4789 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4790 return CMD_WARNING;
4791
4792 if (argv_find(argv, argc, "detail", &detail))
4793 detail = 1;
4794
4795 evpn_show_all_routes(vty, bgp, type, json, detail);
4796
4797 /*
4798 * This is an extremely expensive operation at scale
4799 * and as such we need to save as much time as is
4800 * possible.
4801 */
4802 if (uj)
4803 vty_json_no_pretty(vty, json);
4804
4805 return CMD_SUCCESS;
4806 }
4807
4808 /*
4809 * Display global EVPN routing table for specific RD.
4810 */
4811 DEFUN(show_bgp_l2vpn_evpn_route_rd,
4812 show_bgp_l2vpn_evpn_route_rd_cmd,
4813 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
4814 SHOW_STR
4815 BGP_STR
4816 L2VPN_HELP_STR
4817 EVPN_HELP_STR
4818 EVPN_RT_HELP_STR
4819 EVPN_RT_DIST_HELP_STR
4820 EVPN_ASN_IP_HELP_STR
4821 "All VPN Route Distinguishers\n"
4822 EVPN_TYPE_HELP_STR
4823 EVPN_TYPE_ALL_LIST_HELP_STR
4824 JSON_STR)
4825 {
4826 struct bgp *bgp;
4827 int ret = 0;
4828 struct prefix_rd prd;
4829 int type = 0;
4830 bool uj = false;
4831 json_object *json = NULL;
4832 int idx_ext_community = 0;
4833 int rd_all = 0;
4834
4835 bgp = bgp_get_evpn();
4836 if (!bgp)
4837 return CMD_WARNING;
4838
4839 /* check if we need json output */
4840 uj = use_json(argc, argv);
4841 if (uj)
4842 json = json_object_new_object();
4843
4844 if (!argv_find(argv, argc, "all", &rd_all)) {
4845 /* get the RD */
4846 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4847 &idx_ext_community)) {
4848 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4849 if (!ret) {
4850 vty_out(vty,
4851 "%% Malformed Route Distinguisher\n");
4852 return CMD_WARNING;
4853 }
4854 }
4855 }
4856
4857 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4858 return CMD_WARNING;
4859
4860 if (rd_all)
4861 evpn_show_all_routes(vty, bgp, type, json, 1);
4862 else
4863 evpn_show_route_rd(vty, bgp, &prd, type, json);
4864
4865 if (uj)
4866 vty_json(vty, json);
4867
4868 return CMD_SUCCESS;
4869 }
4870
4871 /*
4872 * Display global EVPN routing table for specific RD and MACIP.
4873 */
4874 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4875 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
4876 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4877 SHOW_STR
4878 BGP_STR
4879 L2VPN_HELP_STR
4880 EVPN_HELP_STR
4881 EVPN_RT_HELP_STR
4882 EVPN_RT_DIST_HELP_STR
4883 EVPN_ASN_IP_HELP_STR
4884 "All VPN Route Distinguishers\n"
4885 "MAC\n"
4886 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4887 "IP\n"
4888 "IP address (IPv4 or IPv6)\n"
4889 JSON_STR)
4890 {
4891 struct bgp *bgp;
4892 int ret = 0;
4893 struct prefix_rd prd;
4894 struct ethaddr mac;
4895 struct ipaddr ip;
4896 int idx_ext_community = 0;
4897 int mac_idx = 0;
4898 int ip_idx = 0;
4899 bool uj = false;
4900 json_object *json = NULL;
4901 int rd_all = 0;
4902
4903 memset(&mac, 0, sizeof(struct ethaddr));
4904 memset(&ip, 0, sizeof(struct ipaddr));
4905
4906 bgp = bgp_get_evpn();
4907 if (!bgp)
4908 return CMD_WARNING;
4909
4910 /* check if we need json output */
4911 uj = use_json(argc, argv);
4912 if (uj)
4913 json = json_object_new_object();
4914
4915 /* get the prd */
4916 if (!argv_find(argv, argc, "all", &rd_all)) {
4917 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4918 &idx_ext_community)) {
4919 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4920 if (!ret) {
4921 vty_out(vty,
4922 "%% Malformed Route Distinguisher\n");
4923 return CMD_WARNING;
4924 }
4925 }
4926 }
4927
4928 /* get the mac */
4929 if (argv_find(argv, argc, "mac", &mac_idx)) {
4930 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4931 vty_out(vty, "%% Malformed MAC address\n");
4932 return CMD_WARNING;
4933 }
4934 }
4935
4936 /* get the ip if specified */
4937 if (argv_find(argv, argc, "ip", &ip_idx)) {
4938 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4939 vty_out(vty, "%% Malformed IP address\n");
4940 return CMD_WARNING;
4941 }
4942 }
4943
4944 if (rd_all)
4945 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4946 else
4947 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4948
4949 if (uj)
4950 vty_json(vty, json);
4951
4952 return CMD_SUCCESS;
4953 }
4954
4955 /* Display per ESI routing table */
4956 DEFUN(show_bgp_l2vpn_evpn_route_esi,
4957 show_bgp_l2vpn_evpn_route_esi_cmd,
4958 "show bgp l2vpn evpn route esi ESI [json]",
4959 SHOW_STR
4960 BGP_STR
4961 L2VPN_HELP_STR
4962 EVPN_HELP_STR
4963 EVPN_RT_HELP_STR
4964 "Ethernet Segment Identifier\n"
4965 "ESI ID\n"
4966 JSON_STR)
4967 {
4968 bool uj = false;
4969 esi_t esi;
4970 struct bgp *bgp = NULL;
4971 json_object *json = NULL;
4972
4973 memset(&esi, 0, sizeof(esi));
4974 bgp = bgp_get_evpn();
4975 if (!bgp)
4976 return CMD_WARNING;
4977
4978 uj = use_json(argc, argv);
4979 if (uj)
4980 json = json_object_new_object();
4981
4982 /* get the ESI - ESI-ID is at argv[6] */
4983 if (!str_to_esi(argv[6]->arg, &esi)) {
4984 vty_out(vty, "%% Malformed ESI\n");
4985 return CMD_WARNING;
4986 }
4987
4988 evpn_show_routes_esi(vty, bgp, &esi, json);
4989
4990 if (uj)
4991 vty_json(vty, json);
4992
4993 return CMD_SUCCESS;
4994 }
4995
4996
4997 /*
4998 * Display per-VNI EVPN routing table.
4999 */
5000 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
5001 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5002 SHOW_STR
5003 BGP_STR
5004 L2VPN_HELP_STR
5005 EVPN_HELP_STR
5006 EVPN_RT_HELP_STR
5007 "VXLAN Network Identifier\n"
5008 "VNI number\n"
5009 EVPN_TYPE_HELP_STR
5010 EVPN_TYPE_1_HELP_STR
5011 EVPN_TYPE_1_HELP_STR
5012 EVPN_TYPE_2_HELP_STR
5013 EVPN_TYPE_2_HELP_STR
5014 EVPN_TYPE_3_HELP_STR
5015 EVPN_TYPE_3_HELP_STR
5016 "Remote VTEP\n"
5017 "Remote VTEP IP address\n"
5018 JSON_STR)
5019 {
5020 vni_t vni;
5021 struct bgp *bgp;
5022 struct in_addr vtep_ip;
5023 int type = 0;
5024 int idx = 0;
5025 int vtep_idx = 0;
5026 bool uj = false;
5027 json_object *json = NULL;
5028
5029 bgp = bgp_get_evpn();
5030 if (!bgp)
5031 return CMD_WARNING;
5032
5033 /* check if we need json output */
5034 uj = use_json(argc, argv);
5035 if (uj)
5036 json = json_object_new_object();
5037
5038 if (!argv_find(argv, argc, "evpn", &idx))
5039 return CMD_WARNING;
5040
5041 vtep_ip.s_addr = 0;
5042
5043 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5044
5045 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
5046 return CMD_WARNING;
5047
5048 if (argv_find(argv, argc, "vtep", &vtep_idx)) {
5049 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
5050 vty_out(vty, "%% Malformed VTEP IP address\n");
5051 return CMD_WARNING;
5052 }
5053 }
5054
5055 evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
5056
5057 if (uj)
5058 vty_json(vty, json);
5059
5060 return CMD_SUCCESS;
5061 }
5062
5063 /*
5064 * Display per-VNI EVPN routing table for specific MACIP.
5065 */
5066 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
5067 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
5068 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
5069 SHOW_STR
5070 BGP_STR
5071 L2VPN_HELP_STR
5072 EVPN_HELP_STR
5073 EVPN_RT_HELP_STR
5074 "VXLAN Network Identifier\n"
5075 "VNI number\n"
5076 "MAC\n"
5077 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5078 "IP\n"
5079 "IP address (IPv4 or IPv6)\n"
5080 JSON_STR)
5081 {
5082 vni_t vni;
5083 struct bgp *bgp;
5084 struct ethaddr mac;
5085 struct ipaddr ip;
5086 int idx = 0;
5087 bool uj = false;
5088 json_object *json = NULL;
5089
5090 bgp = bgp_get_evpn();
5091 if (!bgp)
5092 return CMD_WARNING;
5093
5094 /* check if we need json output */
5095 uj = use_json(argc, argv);
5096 if (uj)
5097 json = json_object_new_object();
5098
5099 if (!argv_find(argv, argc, "evpn", &idx))
5100 return CMD_WARNING;
5101
5102 /* get the VNI */
5103 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5104
5105 /* get the mac */
5106 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
5107 vty_out(vty, "%% Malformed MAC address\n");
5108 return CMD_WARNING;
5109 }
5110
5111 /* get the ip */
5112 memset(&ip, 0, sizeof(ip));
5113 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
5114 || (uj
5115 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
5116 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
5117 vty_out(vty, "%% Malformed IP address\n");
5118 return CMD_WARNING;
5119 }
5120 }
5121
5122 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
5123
5124 if (uj)
5125 vty_json(vty, json);
5126
5127 return CMD_SUCCESS;
5128 }
5129
5130 /*
5131 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5132 */
5133 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
5134 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
5135 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
5136 SHOW_STR
5137 BGP_STR
5138 L2VPN_HELP_STR
5139 EVPN_HELP_STR
5140 EVPN_RT_HELP_STR
5141 "VXLAN Network Identifier\n"
5142 "VNI number\n"
5143 EVPN_TYPE_3_HELP_STR
5144 "Originating Router IP address\n"
5145 JSON_STR)
5146 {
5147 vni_t vni;
5148 struct bgp *bgp;
5149 int ret;
5150 struct in_addr orig_ip;
5151 int idx = 0;
5152 bool uj = false;
5153 json_object *json = NULL;
5154
5155 bgp = bgp_get_evpn();
5156 if (!bgp)
5157 return CMD_WARNING;
5158
5159 /* check if we need json output */
5160 uj = use_json(argc, argv);
5161 if (uj)
5162 json = json_object_new_object();
5163
5164 if (!argv_find(argv, argc, "evpn", &idx))
5165 return CMD_WARNING;
5166
5167 /* get the VNI */
5168 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5169
5170 /* get the ip */
5171 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
5172 if (!ret) {
5173 vty_out(vty, "%% Malformed Originating Router IP address\n");
5174 return CMD_WARNING;
5175 }
5176
5177 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5178
5179 if (uj)
5180 vty_json(vty, json);
5181
5182 return CMD_SUCCESS;
5183 }
5184
5185 /*
5186 * Display per-VNI EVPN routing table - for all VNIs.
5187 */
5188 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5189 show_bgp_l2vpn_evpn_route_vni_all_cmd,
5190 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5191 SHOW_STR
5192 BGP_STR
5193 L2VPN_HELP_STR
5194 EVPN_HELP_STR
5195 EVPN_RT_HELP_STR
5196 "VXLAN Network Identifier\n"
5197 "All VNIs\n"
5198 "Print Detailed Output\n"
5199 "Remote VTEP\n"
5200 "Remote VTEP IP address\n"
5201 JSON_STR)
5202 {
5203 struct bgp *bgp;
5204 struct in_addr vtep_ip;
5205 int idx = 0;
5206 bool uj = false;
5207 json_object *json = NULL;
5208 /* Detail Adjust. Adjust indexes according to detail option */
5209 int da = 0;
5210
5211 bgp = bgp_get_evpn();
5212 if (!bgp)
5213 return CMD_WARNING;
5214
5215 /* check if we need json output */
5216 uj = use_json(argc, argv);
5217 if (uj)
5218 json = json_object_new_object();
5219
5220 if (!argv_find(argv, argc, "evpn", &idx))
5221 return CMD_WARNING;
5222
5223 if (argv_find(argv, argc, "detail", &da))
5224 da = 1;
5225
5226 /* vtep-ip position depends on detail option */
5227 vtep_ip.s_addr = 0;
5228 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5229 || (uj
5230 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5231 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
5232 vty_out(vty, "%% Malformed VTEP IP address\n");
5233 return CMD_WARNING;
5234 }
5235 }
5236
5237 evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
5238
5239 if (uj) {
5240 vty_json(vty, json);
5241 json_object_free(json);
5242 }
5243
5244 return CMD_SUCCESS;
5245 }
5246
5247 /*
5248 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5249 */
5250 DEFPY(show_bgp_vni_all,
5251 show_bgp_vni_all_cmd,
5252 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5253 SHOW_STR
5254 BGP_STR
5255 VNI_HELP_STR
5256 VNI_ALL_HELP_STR
5257 VTEP_HELP_STR
5258 VTEP_IP_HELP_STR
5259 DETAIL_HELP_STR
5260 JSON_STR)
5261 {
5262 struct bgp *bgp;
5263 json_object *json = NULL;
5264
5265 bgp = bgp_get_evpn();
5266 if (!bgp)
5267 return CMD_WARNING;
5268
5269 /* check if we need json output */
5270 if (uj)
5271 json = json_object_new_object();
5272
5273 evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
5274
5275 if (uj)
5276 vty_json(vty, json);
5277
5278 return CMD_SUCCESS;
5279 }
5280
5281 /*
5282 * Display per-VNI EVPN EAD routing table - for all VNIs.
5283 */
5284 DEFPY(show_bgp_vni_all_ead,
5285 show_bgp_vni_all_ead_cmd,
5286 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5287 SHOW_STR
5288 BGP_STR
5289 VNI_HELP_STR
5290 VNI_ALL_HELP_STR
5291 EVPN_TYPE_HELP_STR
5292 EVPN_TYPE_1_HELP_STR
5293 EVPN_TYPE_1_HELP_STR
5294 VTEP_HELP_STR
5295 VTEP_IP_HELP_STR
5296 DETAIL_HELP_STR
5297 JSON_STR)
5298 {
5299 struct bgp *bgp;
5300 json_object *json = NULL;
5301
5302 bgp = bgp_get_evpn();
5303 if (!bgp)
5304 return CMD_WARNING;
5305
5306 /* check if we need json output */
5307 if (uj)
5308 json = json_object_new_object();
5309
5310 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
5311 !!detail);
5312
5313 if (uj)
5314 vty_json(vty, json);
5315
5316 return CMD_SUCCESS;
5317 }
5318
5319 /*
5320 * Display per-VNI EVPN MAC routing table - for all VNIs.
5321 */
5322 DEFPY(show_bgp_vni_all_macip_mac,
5323 show_bgp_vni_all_macip_mac_cmd,
5324 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5325 SHOW_STR
5326 BGP_STR
5327 VNI_HELP_STR
5328 VNI_ALL_HELP_STR
5329 EVPN_TYPE_HELP_STR
5330 EVPN_TYPE_2_HELP_STR
5331 EVPN_TYPE_2_HELP_STR
5332 "MAC Table\n"
5333 VTEP_HELP_STR
5334 VTEP_IP_HELP_STR
5335 DETAIL_HELP_STR
5336 JSON_STR)
5337 {
5338 struct bgp *bgp;
5339 json_object *json = NULL;
5340
5341 bgp = bgp_get_evpn();
5342 if (!bgp)
5343 return CMD_WARNING;
5344
5345 /* check if we need json output */
5346 if (uj)
5347 json = json_object_new_object();
5348
5349 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5350 json, !!detail);
5351
5352 if (uj)
5353 vty_json(vty, json);
5354
5355 return CMD_SUCCESS;
5356 }
5357
5358 /*
5359 * Display per-VNI EVPN IP routing table - for all VNIs.
5360 */
5361 DEFPY(show_bgp_vni_all_macip_ip,
5362 show_bgp_vni_all_macip_ip_cmd,
5363 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5364 SHOW_STR
5365 BGP_STR
5366 VNI_HELP_STR
5367 VNI_ALL_HELP_STR
5368 EVPN_TYPE_HELP_STR
5369 EVPN_TYPE_2_HELP_STR
5370 EVPN_TYPE_2_HELP_STR
5371 "IP Table\n"
5372 VTEP_HELP_STR
5373 VTEP_IP_HELP_STR
5374 DETAIL_HELP_STR
5375 JSON_STR)
5376 {
5377 struct bgp *bgp;
5378 json_object *json = NULL;
5379
5380 bgp = bgp_get_evpn();
5381 if (!bgp)
5382 return CMD_WARNING;
5383
5384 /* check if we need json output */
5385 if (uj)
5386 json = json_object_new_object();
5387
5388 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5389 json, !!detail);
5390
5391 if (uj)
5392 vty_json(vty, json);
5393
5394 return CMD_SUCCESS;
5395 }
5396
5397 /*
5398 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5399 */
5400 DEFPY(show_bgp_vni_all_imet,
5401 show_bgp_vni_all_imet_cmd,
5402 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5403 SHOW_STR
5404 BGP_STR
5405 VNI_HELP_STR
5406 VNI_ALL_HELP_STR
5407 EVPN_TYPE_HELP_STR
5408 EVPN_TYPE_3_HELP_STR
5409 EVPN_TYPE_3_HELP_STR
5410 VTEP_HELP_STR
5411 VTEP_IP_HELP_STR
5412 DETAIL_HELP_STR
5413 JSON_STR)
5414 {
5415 struct bgp *bgp;
5416 json_object *json = NULL;
5417
5418 bgp = bgp_get_evpn();
5419 if (!bgp)
5420 return CMD_WARNING;
5421
5422 /* check if we need json output */
5423 if (uj)
5424 json = json_object_new_object();
5425
5426 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
5427 json, !!detail);
5428
5429 if (uj)
5430 vty_json(vty, json);
5431
5432 return CMD_SUCCESS;
5433 }
5434
5435 /*
5436 * Display per-VNI EVPN ALL routing tables - for select VNI
5437 */
5438 DEFPY(show_bgp_vni,
5439 show_bgp_vni_cmd,
5440 "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
5441 SHOW_STR
5442 BGP_STR
5443 VNI_HELP_STR
5444 VNI_NUM_HELP_STR
5445 VTEP_HELP_STR
5446 VTEP_IP_HELP_STR
5447 JSON_STR)
5448 {
5449 struct bgp *bgp;
5450 json_object *json = NULL;
5451 json_object *json_mac = NULL;
5452
5453 bgp = bgp_get_evpn();
5454 if (!bgp)
5455 return CMD_WARNING;
5456
5457 /* check if we need json output */
5458 if (uj) {
5459 json = json_object_new_object();
5460 json_mac = json_object_new_object();
5461 }
5462
5463 evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
5464
5465 if (!uj)
5466 vty_out(vty, "\n\nMAC Table:\n\n");
5467
5468 evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
5469
5470 if (uj) {
5471 json_object_object_add(json, "macTable", json_mac);
5472 vty_json(vty, json);
5473 }
5474
5475 return CMD_SUCCESS;
5476 }
5477
5478 /*
5479 * Display per-VNI EVPN EAD routing table - for select VNI
5480 */
5481 DEFPY(show_bgp_vni_ead,
5482 show_bgp_vni_ead_cmd,
5483 "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5484 SHOW_STR
5485 BGP_STR
5486 VNI_HELP_STR
5487 VNI_NUM_HELP_STR
5488 EVPN_TYPE_HELP_STR
5489 EVPN_TYPE_1_HELP_STR
5490 EVPN_TYPE_1_HELP_STR
5491 VTEP_HELP_STR
5492 VTEP_IP_HELP_STR
5493 JSON_STR)
5494 {
5495 struct bgp *bgp;
5496 json_object *json = NULL;
5497
5498 bgp = bgp_get_evpn();
5499 if (!bgp)
5500 return CMD_WARNING;
5501
5502 /* check if we need json output */
5503 if (uj)
5504 json = json_object_new_object();
5505
5506 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
5507 json);
5508
5509 if (uj)
5510 vty_json(vty, json);
5511
5512 return CMD_SUCCESS;
5513 }
5514
5515 /*
5516 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5517 */
5518 DEFPY(show_bgp_vni_macip_mac,
5519 show_bgp_vni_macip_mac_cmd,
5520 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5521 SHOW_STR
5522 BGP_STR
5523 VNI_HELP_STR
5524 VNI_NUM_HELP_STR
5525 EVPN_TYPE_HELP_STR
5526 EVPN_TYPE_2_HELP_STR
5527 EVPN_TYPE_2_HELP_STR
5528 "MAC Table\n"
5529 VTEP_HELP_STR
5530 VTEP_IP_HELP_STR
5531 JSON_STR)
5532 {
5533 struct bgp *bgp;
5534 json_object *json = NULL;
5535
5536 bgp = bgp_get_evpn();
5537 if (!bgp)
5538 return CMD_WARNING;
5539
5540 /* check if we need json output */
5541 if (uj)
5542 json = json_object_new_object();
5543
5544 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5545 json);
5546
5547 if (uj)
5548 vty_json(vty, json);
5549
5550 return CMD_SUCCESS;
5551 }
5552
5553 /*
5554 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5555 */
5556 DEFPY(show_bgp_vni_macip_ip,
5557 show_bgp_vni_macip_ip_cmd,
5558 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5559 SHOW_STR
5560 BGP_STR
5561 VNI_HELP_STR
5562 VNI_NUM_HELP_STR
5563 EVPN_TYPE_HELP_STR
5564 EVPN_TYPE_2_HELP_STR
5565 EVPN_TYPE_2_HELP_STR
5566 "IP Table\n"
5567 VTEP_HELP_STR
5568 VTEP_IP_HELP_STR
5569 JSON_STR)
5570 {
5571 struct bgp *bgp;
5572 json_object *json = NULL;
5573
5574 bgp = bgp_get_evpn();
5575 if (!bgp)
5576 return CMD_WARNING;
5577
5578 /* check if we need json output */
5579 if (uj)
5580 json = json_object_new_object();
5581
5582 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5583 json);
5584
5585 if (uj)
5586 vty_json(vty, json);
5587
5588 return CMD_SUCCESS;
5589 }
5590
5591 /*
5592 * Display per-VNI EVPN Multicast routing table - for select VNI
5593 */
5594 DEFPY(show_bgp_vni_imet,
5595 show_bgp_vni_imet_cmd,
5596 "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5597 SHOW_STR
5598 BGP_STR
5599 VNI_HELP_STR
5600 VNI_NUM_HELP_STR
5601 EVPN_TYPE_HELP_STR
5602 EVPN_TYPE_3_HELP_STR
5603 EVPN_TYPE_3_HELP_STR
5604 VTEP_HELP_STR
5605 VTEP_IP_HELP_STR
5606 JSON_STR)
5607 {
5608 struct bgp *bgp;
5609 json_object *json = NULL;
5610
5611 bgp = bgp_get_evpn();
5612 if (!bgp)
5613 return CMD_WARNING;
5614
5615 /* check if we need json output */
5616 if (uj)
5617 json = json_object_new_object();
5618
5619 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
5620 json);
5621
5622 if (uj)
5623 vty_json(vty, json);
5624
5625 return CMD_SUCCESS;
5626 }
5627
5628 /*
5629 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5630 */
5631 DEFPY(show_bgp_vni_macip_mac_addr,
5632 show_bgp_vni_macip_mac_addr_cmd,
5633 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5634 SHOW_STR
5635 BGP_STR
5636 VNI_HELP_STR
5637 VNI_NUM_HELP_STR
5638 EVPN_TYPE_HELP_STR
5639 EVPN_TYPE_2_HELP_STR
5640 EVPN_TYPE_2_HELP_STR
5641 "MAC Table\n"
5642 MAC_STR
5643 JSON_STR)
5644 {
5645 struct bgp *bgp;
5646 json_object *json = NULL;
5647
5648 bgp = bgp_get_evpn();
5649 if (!bgp)
5650 return CMD_WARNING;
5651
5652 /* check if we need json output */
5653 if (uj)
5654 json = json_object_new_object();
5655
5656 evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
5657
5658 if (uj)
5659 vty_json(vty, json);
5660
5661 return CMD_SUCCESS;
5662 }
5663
5664 /*
5665 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5666 */
5667 DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
5668 "show bgp vni " CMD_VNI_RANGE
5669 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5670 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5671 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5672 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
5673 {
5674 struct bgp *bgp;
5675 json_object *json = NULL;
5676 struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
5677
5678 bgp = bgp_get_evpn();
5679 if (!bgp)
5680 return CMD_WARNING;
5681
5682 /* check if we need json output */
5683 if (uj)
5684 json = json_object_new_object();
5685
5686 if (sockunion_family(ip) == AF_INET) {
5687 ip_addr.ipa_type = IPADDR_V4;
5688 ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
5689 } else {
5690 ip_addr.ipa_type = IPADDR_V6;
5691 memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
5692 sizeof(struct in6_addr));
5693 }
5694 evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
5695
5696 if (uj)
5697 vty_json(vty, json);
5698
5699 return CMD_SUCCESS;
5700 }
5701
5702 DEFPY_HIDDEN(
5703 show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5704 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5705 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5706 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5707 "EVPN route information\n"
5708 "MAC IP routes in the EVI tables linked to the ES\n"
5709 "ES ID\n"
5710 "Detailed information\n" JSON_STR)
5711 {
5712 esi_t esi;
5713 esi_t *esi_p;
5714 json_object *json = NULL;
5715
5716 if (esi_str) {
5717 if (!str_to_esi(esi_str, &esi)) {
5718 vty_out(vty, "%% Malformed ESI\n");
5719 return CMD_WARNING;
5720 }
5721 esi_p = &esi;
5722 } else {
5723 esi_p = NULL;
5724 }
5725
5726 if (uj)
5727 json = json_object_new_object();
5728 bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
5729 if (uj)
5730 vty_json(vty, json);
5731
5732 return CMD_SUCCESS;
5733 }
5734
5735 DEFPY_HIDDEN(
5736 show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5737 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5738 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5739 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5740 "EVPN route information\n"
5741 "MAC IP routes in the global table linked to the ES\n"
5742 "ES ID\n"
5743 "Detailed information\n" JSON_STR)
5744 {
5745 esi_t esi;
5746 esi_t *esi_p;
5747 json_object *json = NULL;
5748
5749 if (esi_str) {
5750 if (!str_to_esi(esi_str, &esi)) {
5751 vty_out(vty, "%% Malformed ESI\n");
5752 return CMD_WARNING;
5753 }
5754 esi_p = &esi;
5755 } else {
5756 esi_p = NULL;
5757 }
5758
5759 if (uj)
5760 json = json_object_new_object();
5761 bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
5762 if (uj)
5763 vty_json(vty, json);
5764
5765 return CMD_SUCCESS;
5766 }
5767
5768 /*
5769 * Display EVPN import route-target hash table
5770 */
5771 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5772 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5773 "show bgp l2vpn evpn vrf-import-rt [json]",
5774 SHOW_STR
5775 BGP_STR
5776 L2VPN_HELP_STR
5777 EVPN_HELP_STR
5778 "Show vrf import route target\n"
5779 JSON_STR)
5780 {
5781 bool uj = false;
5782 struct bgp *bgp_evpn = NULL;
5783 json_object *json = NULL;
5784
5785 bgp_evpn = bgp_get_evpn();
5786 if (!bgp_evpn)
5787 return CMD_WARNING;
5788
5789 uj = use_json(argc, argv);
5790 if (uj)
5791 json = json_object_new_object();
5792
5793 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
5794
5795 if (uj)
5796 vty_json(vty, json);
5797
5798 return CMD_SUCCESS;
5799 }
5800
5801 /*
5802 * Display EVPN import route-target hash table
5803 */
5804 DEFUN(show_bgp_l2vpn_evpn_import_rt,
5805 show_bgp_l2vpn_evpn_import_rt_cmd,
5806 "show bgp l2vpn evpn import-rt [json]",
5807 SHOW_STR
5808 BGP_STR
5809 L2VPN_HELP_STR
5810 EVPN_HELP_STR
5811 "Show import route target\n"
5812 JSON_STR)
5813 {
5814 struct bgp *bgp;
5815 bool uj = false;
5816 json_object *json = NULL;
5817
5818 bgp = bgp_get_evpn();
5819 if (!bgp)
5820 return CMD_WARNING;
5821
5822 uj = use_json(argc, argv);
5823 if (uj)
5824 json = json_object_new_object();
5825
5826 evpn_show_import_rts(vty, bgp, json);
5827
5828 if (uj)
5829 vty_json(vty, json);
5830
5831 return CMD_SUCCESS;
5832 }
5833
5834 DEFPY_HIDDEN(test_es_add,
5835 test_es_add_cmd,
5836 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5837 NO_STR
5838 "Test\n"
5839 "Ethernet-segment\n"
5840 "Ethernet-Segment Identifier\n"
5841 "ES link state\n"
5842 "up|down\n"
5843 )
5844 {
5845 int ret = 0;
5846 esi_t esi;
5847 struct bgp *bgp;
5848 struct in_addr vtep_ip;
5849 bool oper_up;
5850
5851 bgp = bgp_get_evpn();
5852 if (!bgp) {
5853 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5854 return CMD_WARNING;
5855 }
5856
5857 if (!str_to_esi(esi_str, &esi)) {
5858 vty_out(vty, "%% Malformed ESI\n");
5859 return CMD_WARNING;
5860 }
5861
5862 if (no) {
5863 ret = bgp_evpn_local_es_del(bgp, &esi);
5864 if (ret == -1) {
5865 vty_out(vty, "%% Failed to delete ES\n");
5866 return CMD_WARNING;
5867 }
5868 } else {
5869 if (state_str && !strcmp(state_str, "up"))
5870 oper_up = true;
5871 else
5872 oper_up = false;
5873 vtep_ip = bgp->router_id;
5874
5875 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
5876 EVPN_MH_DF_PREF_MIN, false);
5877 if (ret == -1) {
5878 vty_out(vty, "%% Failed to add ES\n");
5879 return CMD_WARNING;
5880 }
5881 }
5882 return CMD_SUCCESS;
5883 }
5884
5885 DEFPY_HIDDEN(test_es_vni_add,
5886 test_es_vni_add_cmd,
5887 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5888 NO_STR
5889 "Test\n"
5890 "Ethernet-segment\n"
5891 "Ethernet-Segment Identifier\n"
5892 "VNI\n"
5893 "1-16777215\n"
5894 )
5895 {
5896 int ret = 0;
5897 esi_t esi;
5898 struct bgp *bgp;
5899
5900 bgp = bgp_get_evpn();
5901 if (!bgp) {
5902 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5903 return CMD_WARNING;
5904 }
5905
5906 if (!str_to_esi(esi_str, &esi)) {
5907 vty_out(vty, "%% Malformed ESI\n");
5908 return CMD_WARNING;
5909 }
5910
5911 if (no) {
5912 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5913 if (ret == -1) {
5914 vty_out(vty, "%% Failed to deref ES VNI\n");
5915 return CMD_WARNING;
5916 }
5917 } else {
5918 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5919 if (ret == -1) {
5920 vty_out(vty, "%% Failed to ref ES VNI\n");
5921 return CMD_WARNING;
5922 }
5923 }
5924 return CMD_SUCCESS;
5925 }
5926
5927 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
5928 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5929 "Show VNI\n"
5930 "VNI number\n")
5931
5932 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5933 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5934 "Summary of BGP neighbor status\n" JSON_STR)
5935
5936 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
5937 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5938 SHOW_STR BGP_STR EVPN_HELP_STR
5939 EVPN_RT_HELP_STR
5940 "Display Detailed Information\n"
5941 EVPN_TYPE_HELP_STR
5942 EVPN_TYPE_2_HELP_STR
5943 EVPN_TYPE_2_HELP_STR
5944 EVPN_TYPE_3_HELP_STR
5945 EVPN_TYPE_3_HELP_STR)
5946
5947 ALIAS_HIDDEN(
5948 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
5949 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5950 SHOW_STR BGP_STR EVPN_HELP_STR
5951 EVPN_RT_HELP_STR
5952 EVPN_RT_DIST_HELP_STR
5953 EVPN_ASN_IP_HELP_STR
5954 EVPN_TYPE_HELP_STR
5955 EVPN_TYPE_2_HELP_STR
5956 EVPN_TYPE_2_HELP_STR
5957 EVPN_TYPE_3_HELP_STR
5958 EVPN_TYPE_3_HELP_STR)
5959
5960 ALIAS_HIDDEN(
5961 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
5962 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5963 SHOW_STR BGP_STR EVPN_HELP_STR
5964 EVPN_RT_HELP_STR
5965 EVPN_RT_DIST_HELP_STR
5966 EVPN_ASN_IP_HELP_STR
5967 "MAC\n"
5968 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5969 "IP\n"
5970 "IP address (IPv4 or IPv6)\n")
5971
5972 ALIAS_HIDDEN(
5973 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
5974 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5975 SHOW_STR BGP_STR EVPN_HELP_STR
5976 EVPN_RT_HELP_STR
5977 "VXLAN Network Identifier\n"
5978 "VNI number\n"
5979 EVPN_TYPE_HELP_STR
5980 EVPN_TYPE_2_HELP_STR
5981 EVPN_TYPE_2_HELP_STR
5982 EVPN_TYPE_3_HELP_STR
5983 EVPN_TYPE_3_HELP_STR
5984 "Remote VTEP\n"
5985 "Remote VTEP IP address\n")
5986
5987 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
5988 show_bgp_evpn_route_vni_macip_cmd,
5989 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
5990 SHOW_STR BGP_STR EVPN_HELP_STR
5991 EVPN_RT_HELP_STR
5992 "VXLAN Network Identifier\n"
5993 "VNI number\n"
5994 "MAC\n"
5995 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5996 "IP\n"
5997 "IP address (IPv4 or IPv6)\n")
5998
5999 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
6000 show_bgp_evpn_route_vni_multicast_cmd,
6001 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
6002 SHOW_STR BGP_STR EVPN_HELP_STR
6003 EVPN_RT_HELP_STR
6004 "VXLAN Network Identifier\n"
6005 "VNI number\n"
6006 EVPN_TYPE_3_HELP_STR
6007 "Originating Router IP address\n")
6008
6009 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
6010 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6011 SHOW_STR BGP_STR EVPN_HELP_STR
6012 EVPN_RT_HELP_STR
6013 "VXLAN Network Identifier\n"
6014 "All VNIs\n"
6015 "Print Detailed Output\n"
6016 "Remote VTEP\n"
6017 "Remote VTEP IP address\n")
6018
6019 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
6020 "show bgp evpn import-rt",
6021 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
6022
6023 DEFUN_NOSH (bgp_evpn_vni,
6024 bgp_evpn_vni_cmd,
6025 "vni " CMD_VNI_RANGE,
6026 "VXLAN Network Identifier\n"
6027 "VNI number\n")
6028 {
6029 vni_t vni;
6030 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6031 struct bgpevpn *vpn;
6032
6033 if (!bgp)
6034 return CMD_WARNING;
6035
6036 vni = strtoul(argv[1]->arg, NULL, 10);
6037
6038 /* Create VNI, or mark as configured. */
6039 vpn = evpn_create_update_vni(bgp, vni);
6040 if (!vpn) {
6041 vty_out(vty, "%% Failed to create VNI \n");
6042 return CMD_WARNING;
6043 }
6044
6045 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
6046 return CMD_SUCCESS;
6047 }
6048
6049 DEFUN (no_bgp_evpn_vni,
6050 no_bgp_evpn_vni_cmd,
6051 "no vni " CMD_VNI_RANGE,
6052 NO_STR
6053 "VXLAN Network Identifier\n"
6054 "VNI number\n")
6055 {
6056 vni_t vni;
6057 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6058 struct bgpevpn *vpn;
6059
6060 if (!bgp)
6061 return CMD_WARNING;
6062
6063 vni = strtoul(argv[2]->arg, NULL, 10);
6064
6065 /* Check if we should disallow. */
6066 vpn = bgp_evpn_lookup_vni(bgp, vni);
6067 if (!vpn) {
6068 vty_out(vty, "%% Specified VNI does not exist\n");
6069 return CMD_WARNING;
6070 }
6071 if (!is_vni_configured(vpn)) {
6072 vty_out(vty, "%% Specified VNI is not configured\n");
6073 return CMD_WARNING;
6074 }
6075
6076 evpn_delete_vni(bgp, vpn);
6077 return CMD_SUCCESS;
6078 }
6079
6080 DEFUN_NOSH (exit_vni,
6081 exit_vni_cmd,
6082 "exit-vni",
6083 "Exit from VNI mode\n")
6084 {
6085 if (vty->node == BGP_EVPN_VNI_NODE)
6086 vty->node = BGP_EVPN_NODE;
6087 return CMD_SUCCESS;
6088 }
6089
6090 DEFUN (bgp_evpn_vrf_rd,
6091 bgp_evpn_vrf_rd_cmd,
6092 "rd ASN:NN_OR_IP-ADDRESS:NN",
6093 EVPN_RT_DIST_HELP_STR
6094 EVPN_ASN_IP_HELP_STR)
6095 {
6096 int ret;
6097 struct prefix_rd prd;
6098 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6099
6100 if (!bgp_vrf)
6101 return CMD_WARNING;
6102
6103 ret = str2prefix_rd(argv[1]->arg, &prd);
6104 if (!ret) {
6105 vty_out(vty, "%% Malformed Route Distinguisher\n");
6106 return CMD_WARNING;
6107 }
6108
6109 /* If same as existing value, there is nothing more to do. */
6110 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
6111 return CMD_SUCCESS;
6112
6113 /* Configure or update the RD. */
6114 evpn_configure_vrf_rd(bgp_vrf, &prd);
6115 return CMD_SUCCESS;
6116 }
6117
6118 DEFUN (no_bgp_evpn_vrf_rd,
6119 no_bgp_evpn_vrf_rd_cmd,
6120 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6121 NO_STR
6122 EVPN_RT_DIST_HELP_STR
6123 EVPN_ASN_IP_HELP_STR)
6124 {
6125 int ret;
6126 struct prefix_rd prd;
6127 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6128
6129 if (!bgp_vrf)
6130 return CMD_WARNING;
6131
6132 ret = str2prefix_rd(argv[2]->arg, &prd);
6133 if (!ret) {
6134 vty_out(vty, "%% Malformed Route Distinguisher\n");
6135 return CMD_WARNING;
6136 }
6137
6138 /* Check if we should disallow. */
6139 if (!is_vrf_rd_configured(bgp_vrf)) {
6140 vty_out(vty, "%% RD is not configured for this VRF\n");
6141 return CMD_WARNING;
6142 }
6143
6144 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
6145 vty_out(vty,
6146 "%% RD specified does not match configuration for this VRF\n");
6147 return CMD_WARNING;
6148 }
6149
6150 evpn_unconfigure_vrf_rd(bgp_vrf);
6151 return CMD_SUCCESS;
6152 }
6153
6154 DEFUN (no_bgp_evpn_vrf_rd_without_val,
6155 no_bgp_evpn_vrf_rd_without_val_cmd,
6156 "no rd",
6157 NO_STR
6158 EVPN_RT_DIST_HELP_STR)
6159 {
6160 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6161
6162 if (!bgp_vrf)
6163 return CMD_WARNING;
6164
6165 /* Check if we should disallow. */
6166 if (!is_vrf_rd_configured(bgp_vrf)) {
6167 vty_out(vty, "%% RD is not configured for this VRF\n");
6168 return CMD_WARNING;
6169 }
6170
6171 evpn_unconfigure_vrf_rd(bgp_vrf);
6172 return CMD_SUCCESS;
6173 }
6174
6175 DEFUN (bgp_evpn_vni_rd,
6176 bgp_evpn_vni_rd_cmd,
6177 "rd ASN:NN_OR_IP-ADDRESS:NN",
6178 EVPN_RT_DIST_HELP_STR
6179 EVPN_ASN_IP_HELP_STR)
6180 {
6181 struct prefix_rd prd;
6182 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6183 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6184 int ret;
6185
6186 if (!bgp)
6187 return CMD_WARNING;
6188
6189 if (!EVPN_ENABLED(bgp)) {
6190 vty_out(vty,
6191 "This command is only supported under EVPN VRF\n");
6192 return CMD_WARNING;
6193 }
6194
6195 ret = str2prefix_rd(argv[1]->arg, &prd);
6196 if (!ret) {
6197 vty_out(vty, "%% Malformed Route Distinguisher\n");
6198 return CMD_WARNING;
6199 }
6200
6201 /* If same as existing value, there is nothing more to do. */
6202 if (bgp_evpn_rd_matches_existing(vpn, &prd))
6203 return CMD_SUCCESS;
6204
6205 /* Configure or update the RD. */
6206 evpn_configure_rd(bgp, vpn, &prd);
6207 return CMD_SUCCESS;
6208 }
6209
6210 DEFUN (no_bgp_evpn_vni_rd,
6211 no_bgp_evpn_vni_rd_cmd,
6212 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6213 NO_STR
6214 EVPN_RT_DIST_HELP_STR
6215 EVPN_ASN_IP_HELP_STR)
6216 {
6217 struct prefix_rd prd;
6218 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6219 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6220 int ret;
6221
6222 if (!bgp)
6223 return CMD_WARNING;
6224
6225 if (!EVPN_ENABLED(bgp)) {
6226 vty_out(vty,
6227 "This command is only supported under EVPN VRF\n");
6228 return CMD_WARNING;
6229 }
6230
6231 ret = str2prefix_rd(argv[2]->arg, &prd);
6232 if (!ret) {
6233 vty_out(vty, "%% Malformed Route Distinguisher\n");
6234 return CMD_WARNING;
6235 }
6236
6237 /* Check if we should disallow. */
6238 if (!is_rd_configured(vpn)) {
6239 vty_out(vty, "%% RD is not configured for this VNI\n");
6240 return CMD_WARNING;
6241 }
6242
6243 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
6244 vty_out(vty,
6245 "%% RD specified does not match configuration for this VNI\n");
6246 return CMD_WARNING;
6247 }
6248
6249 evpn_unconfigure_rd(bgp, vpn);
6250 return CMD_SUCCESS;
6251 }
6252
6253 DEFUN (no_bgp_evpn_vni_rd_without_val,
6254 no_bgp_evpn_vni_rd_without_val_cmd,
6255 "no rd",
6256 NO_STR
6257 EVPN_RT_DIST_HELP_STR)
6258 {
6259 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6260 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6261
6262 if (!bgp)
6263 return CMD_WARNING;
6264
6265 if (!EVPN_ENABLED(bgp)) {
6266 vty_out(vty,
6267 "This command is only supported under EVPN VRF\n");
6268 return CMD_WARNING;
6269 }
6270
6271 /* Check if we should disallow. */
6272 if (!is_rd_configured(vpn)) {
6273 vty_out(vty, "%% RD is not configured for this VNI\n");
6274 return CMD_WARNING;
6275 }
6276
6277 evpn_unconfigure_rd(bgp, vpn);
6278 return CMD_SUCCESS;
6279 }
6280
6281 /*
6282 * Loop over all extended-communities in the route-target list rtl and
6283 * return 1 if we find ecomtarget
6284 */
6285 static bool bgp_evpn_rt_matches_existing(struct list *rtl,
6286 struct ecommunity *ecomtarget)
6287 {
6288 struct listnode *node;
6289 struct ecommunity *ecom;
6290
6291 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
6292 if (ecommunity_match(ecom, ecomtarget))
6293 return true;
6294 }
6295
6296 return false;
6297 }
6298
6299 /*
6300 * L3 RT version of above.
6301 */
6302 static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
6303 struct ecommunity *ecomtarget)
6304 {
6305 struct listnode *node;
6306 struct vrf_route_target *l3rt;
6307
6308 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
6309 if (ecommunity_match(l3rt->ecom, ecomtarget))
6310 return true;
6311 }
6312
6313 return false;
6314 }
6315
6316 /* display L3VNI related info for a VRF instance */
6317 DEFUN (show_bgp_vrf_l3vni_info,
6318 show_bgp_vrf_l3vni_info_cmd,
6319 "show bgp vrf VRFNAME vni [json]",
6320 SHOW_STR
6321 BGP_STR
6322 "show bgp vrf\n"
6323 "VRF Name\n"
6324 "L3-VNI\n"
6325 JSON_STR)
6326 {
6327 char buf[ETHER_ADDR_STRLEN];
6328 int idx_vrf = 3;
6329 const char *name = NULL;
6330 struct bgp *bgp = NULL;
6331 struct listnode *node = NULL;
6332 struct bgpevpn *vpn = NULL;
6333 struct vrf_route_target *l3rt;
6334 json_object *json = NULL;
6335 json_object *json_vnis = NULL;
6336 json_object *json_export_rts = NULL;
6337 json_object *json_import_rts = NULL;
6338 bool uj = use_json(argc, argv);
6339
6340 if (uj) {
6341 json = json_object_new_object();
6342 json_vnis = json_object_new_array();
6343 json_export_rts = json_object_new_array();
6344 json_import_rts = json_object_new_array();
6345 }
6346
6347 name = argv[idx_vrf]->arg;
6348 bgp = bgp_lookup_by_name(name);
6349 if (strmatch(name, VRF_DEFAULT_NAME))
6350 bgp = bgp_get_default();
6351
6352 if (!bgp) {
6353 if (!uj)
6354 vty_out(vty, "BGP instance for VRF %s not found\n",
6355 name);
6356 else {
6357 json_object_string_add(json, "warning",
6358 "BGP instance not found");
6359 vty_out(vty, "%s\n", json_object_to_json_string(json));
6360 json_object_free(json);
6361 }
6362 return CMD_WARNING;
6363 }
6364
6365 if (!json) {
6366 vty_out(vty, "BGP VRF: %s\n", name);
6367 vty_out(vty, " Local-Ip: %pI4\n", &bgp->originator_ip);
6368 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
6369 vty_out(vty, " Rmac: %s\n",
6370 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6371 vty_out(vty, " VNI Filter: %s\n",
6372 CHECK_FLAG(bgp->vrf_flags,
6373 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6374 ? "prefix-routes-only"
6375 : "none");
6376 vty_out(vty, " L2-VNI List:\n");
6377 vty_out(vty, " ");
6378 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6379 vty_out(vty, "%u ", vpn->vni);
6380 vty_out(vty, "\n");
6381 vty_out(vty, " Export-RTs:\n");
6382 vty_out(vty, " ");
6383 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6384 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
6385 vty_out(vty, "\n");
6386 vty_out(vty, " Import-RTs:\n");
6387 vty_out(vty, " ");
6388 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6389 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
6390 vty_out(vty, "\n");
6391 vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd);
6392 } else {
6393 json_object_string_add(json, "vrf", name);
6394 json_object_string_addf(json, "local-ip", "%pI4",
6395 &bgp->originator_ip);
6396 json_object_int_add(json, "l3vni", bgp->l3vni);
6397 json_object_string_add(
6398 json, "rmac",
6399 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6400 json_object_string_add(
6401 json, "vniFilter",
6402 CHECK_FLAG(bgp->vrf_flags,
6403 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6404 ? "prefix-routes-only"
6405 : "none");
6406 /* list of l2vnis */
6407 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6408 json_object_array_add(json_vnis,
6409 json_object_new_int(vpn->vni));
6410 json_object_object_add(json, "l2vnis", json_vnis);
6411
6412 /* export rts */
6413 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6414 json_object_array_add(
6415 json_export_rts,
6416 json_object_new_string(
6417 ecommunity_str(l3rt->ecom)));
6418 json_object_object_add(json, "export-rts", json_export_rts);
6419
6420 /* import rts */
6421 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6422 json_object_array_add(
6423 json_import_rts,
6424 json_object_new_string(
6425 ecommunity_str(l3rt->ecom)));
6426 json_object_object_add(json, "import-rts", json_import_rts);
6427 json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
6428 }
6429
6430 if (uj)
6431 vty_json(vty, json);
6432 return CMD_SUCCESS;
6433 }
6434
6435 static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
6436 bool is_wildcard)
6437 {
6438 /* Do nothing if we already have this route-target */
6439 if (is_import) {
6440 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6441 ecom))
6442 bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
6443 is_wildcard);
6444 else
6445 return -1;
6446 } else {
6447 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6448 ecom))
6449 bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
6450 else
6451 return -1;
6452 }
6453
6454 return 0;
6455 }
6456
6457 static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
6458 {
6459 /* Verify we already have this route-target */
6460 if (is_import) {
6461 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6462 ecom))
6463 return -1;
6464
6465 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
6466 } else {
6467 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6468 ecom))
6469 return -1;
6470
6471 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
6472 }
6473
6474 return 0;
6475 }
6476
6477 static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
6478 struct cmd_token **argv, int rt_idx, bool is_add,
6479 bool is_import)
6480 {
6481 int ret = CMD_SUCCESS;
6482 bool is_wildcard = false;
6483 struct ecommunity *ecom = NULL;
6484
6485 for (int i = rt_idx; i < argc; i++) {
6486 is_wildcard = false;
6487
6488 /*
6489 * Special handling for wildcard '*' here.
6490 *
6491 * Let's just convert it to 0 here so we dont have to modify
6492 * the ecommunity parser.
6493 */
6494 if ((argv[i]->arg)[0] == '*') {
6495 (argv[i]->arg)[0] = '0';
6496 is_wildcard = true;
6497 }
6498
6499 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
6500 0);
6501
6502 /* Put it back as was */
6503 if (is_wildcard)
6504 (argv[i]->arg)[0] = '*';
6505
6506 if (!ecom) {
6507 vty_out(vty, "%% Malformed Route Target list\n");
6508 ret = CMD_WARNING;
6509 continue;
6510 }
6511
6512 ecommunity_str(ecom);
6513
6514 if (is_add) {
6515 if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
6516 vty_out(vty,
6517 "%% RT specified already configured for this VRF: %s\n",
6518 argv[i]->arg);
6519 ecommunity_free(&ecom);
6520 ret = CMD_WARNING;
6521 }
6522
6523 } else {
6524 if (del_rt(bgp, ecom, is_import) != 0) {
6525 vty_out(vty,
6526 "%% RT specified does not match configuration for this VRF: %s\n",
6527 argv[i]->arg);
6528 ret = CMD_WARNING;
6529 }
6530
6531 ecommunity_free(&ecom);
6532 }
6533 }
6534
6535 return ret;
6536 }
6537
6538 /* import/export rt for l3vni-vrf */
6539 DEFUN (bgp_evpn_vrf_rt,
6540 bgp_evpn_vrf_rt_cmd,
6541 "route-target <both|import|export> RTLIST...",
6542 "Route Target\n"
6543 "import and export\n"
6544 "import\n"
6545 "export\n"
6546 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6547 {
6548 int ret = CMD_SUCCESS;
6549 int tmp_ret = CMD_SUCCESS;
6550 int rt_type;
6551 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6552
6553 if (!bgp)
6554 return CMD_WARNING_CONFIG_FAILED;
6555
6556 if (!strcmp(argv[1]->arg, "import"))
6557 rt_type = RT_TYPE_IMPORT;
6558 else if (!strcmp(argv[1]->arg, "export"))
6559 rt_type = RT_TYPE_EXPORT;
6560 else if (!strcmp(argv[1]->arg, "both"))
6561 rt_type = RT_TYPE_BOTH;
6562 else {
6563 vty_out(vty, "%% Invalid Route Target type\n");
6564 return CMD_WARNING_CONFIG_FAILED;
6565 }
6566
6567 if (strmatch(argv[2]->arg, "auto")) {
6568 vty_out(vty, "%% `auto` cannot be configured via list\n");
6569 return CMD_WARNING_CONFIG_FAILED;
6570 }
6571
6572 if (rt_type != RT_TYPE_IMPORT) {
6573 for (int i = 2; i < argc; i++) {
6574 if ((argv[i]->arg)[0] == '*') {
6575 vty_out(vty,
6576 "%% Wildcard '*' only applicable for import\n");
6577 return CMD_WARNING_CONFIG_FAILED;
6578 }
6579 }
6580 }
6581
6582 /* Add/update the import route-target */
6583 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6584 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
6585
6586 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6587 ret = tmp_ret;
6588
6589 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6590 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
6591
6592 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6593 ret = tmp_ret;
6594
6595 return ret;
6596 }
6597
6598 DEFPY (bgp_evpn_vrf_rt_auto,
6599 bgp_evpn_vrf_rt_auto_cmd,
6600 "route-target <both|import|export>$type auto",
6601 "Route Target\n"
6602 "import and export\n"
6603 "import\n"
6604 "export\n"
6605 "Automatically derive route target\n")
6606 {
6607 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6608 int rt_type;
6609
6610 if (!bgp)
6611 return CMD_WARNING_CONFIG_FAILED;
6612
6613 if (strmatch(type, "import"))
6614 rt_type = RT_TYPE_IMPORT;
6615 else if (strmatch(type, "export"))
6616 rt_type = RT_TYPE_EXPORT;
6617 else if (strmatch(type, "both"))
6618 rt_type = RT_TYPE_BOTH;
6619 else {
6620 vty_out(vty, "%% Invalid Route Target type\n");
6621 return CMD_WARNING_CONFIG_FAILED;
6622 }
6623
6624 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6625 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6626
6627 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6628 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6629
6630 return CMD_SUCCESS;
6631 }
6632
6633 DEFUN (no_bgp_evpn_vrf_rt,
6634 no_bgp_evpn_vrf_rt_cmd,
6635 "no route-target <both|import|export> RTLIST...",
6636 NO_STR
6637 "Route Target\n"
6638 "import and export\n"
6639 "import\n"
6640 "export\n"
6641 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6642 {
6643 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6644 int ret = CMD_SUCCESS;
6645 int tmp_ret = CMD_SUCCESS;
6646 int rt_type;
6647
6648 if (!bgp)
6649 return CMD_WARNING_CONFIG_FAILED;
6650
6651 if (!strcmp(argv[2]->arg, "import"))
6652 rt_type = RT_TYPE_IMPORT;
6653 else if (!strcmp(argv[2]->arg, "export"))
6654 rt_type = RT_TYPE_EXPORT;
6655 else if (!strcmp(argv[2]->arg, "both"))
6656 rt_type = RT_TYPE_BOTH;
6657 else {
6658 vty_out(vty, "%% Invalid Route Target type\n");
6659 return CMD_WARNING_CONFIG_FAILED;
6660 }
6661
6662 if (!strcmp(argv[3]->arg, "auto")) {
6663 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6664 return CMD_WARNING_CONFIG_FAILED;
6665 }
6666
6667 if (rt_type == RT_TYPE_IMPORT) {
6668 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6669 vty_out(vty,
6670 "%% Import RT is not configured for this VRF\n");
6671 return CMD_WARNING_CONFIG_FAILED;
6672 }
6673 } else if (rt_type == RT_TYPE_EXPORT) {
6674 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6675 vty_out(vty,
6676 "%% Export RT is not configured for this VRF\n");
6677 return CMD_WARNING_CONFIG_FAILED;
6678 }
6679 } else if (rt_type == RT_TYPE_BOTH) {
6680 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6681 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6682 vty_out(vty,
6683 "%% Import/Export RT is not configured for this VRF\n");
6684 return CMD_WARNING_CONFIG_FAILED;
6685 }
6686 }
6687
6688 if (rt_type != RT_TYPE_IMPORT) {
6689 for (int i = 3; i < argc; i++) {
6690 if ((argv[i]->arg)[0] == '*') {
6691 vty_out(vty,
6692 "%% Wildcard '*' only applicable for import\n");
6693 return CMD_WARNING_CONFIG_FAILED;
6694 }
6695 }
6696 }
6697
6698 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6699 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
6700
6701 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6702 ret = tmp_ret;
6703
6704 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6705 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
6706
6707 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6708 ret = tmp_ret;
6709
6710 return ret;
6711 }
6712
6713 DEFPY (no_bgp_evpn_vrf_rt_auto,
6714 no_bgp_evpn_vrf_rt_auto_cmd,
6715 "no route-target <both|import|export>$type auto",
6716 NO_STR
6717 "Route Target\n"
6718 "import and export\n"
6719 "import\n"
6720 "export\n"
6721 "Automatically derive route target\n")
6722 {
6723 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6724 int rt_type;
6725
6726 if (!bgp)
6727 return CMD_WARNING_CONFIG_FAILED;
6728
6729 if (strmatch(type, "import"))
6730 rt_type = RT_TYPE_IMPORT;
6731 else if (strmatch(type, "export"))
6732 rt_type = RT_TYPE_EXPORT;
6733 else if (strmatch(type, "both"))
6734 rt_type = RT_TYPE_BOTH;
6735 else {
6736 vty_out(vty, "%% Invalid Route Target type\n");
6737 return CMD_WARNING_CONFIG_FAILED;
6738 }
6739
6740 if (rt_type == RT_TYPE_IMPORT) {
6741 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
6742 vty_out(vty,
6743 "%% Import AUTO RT is not configured for this VRF\n");
6744 return CMD_WARNING_CONFIG_FAILED;
6745 }
6746 } else if (rt_type == RT_TYPE_EXPORT) {
6747 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6748 vty_out(vty,
6749 "%% Export AUTO RT is not configured for this VRF\n");
6750 return CMD_WARNING_CONFIG_FAILED;
6751 }
6752 } else if (rt_type == RT_TYPE_BOTH) {
6753 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6754 !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6755 vty_out(vty,
6756 "%% Import/Export AUTO RT is not configured for this VRF\n");
6757 return CMD_WARNING_CONFIG_FAILED;
6758 }
6759 }
6760
6761 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6762 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6763
6764 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6765 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6766
6767 return CMD_SUCCESS;
6768 }
6769
6770 DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6771 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6772 NO_STR
6773 "EAD ES fragment config\n"
6774 "EVIs per-fragment\n"
6775 "limit\n")
6776 {
6777 bgp_mh_info->evi_per_es_frag =
6778 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6779
6780 return CMD_SUCCESS;
6781 }
6782
6783 DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6784 "ead-es-route-target export RT",
6785 "EAD ES Route Target\n"
6786 "export\n"
6787 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6788 {
6789 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6790 struct ecommunity *ecomadd = NULL;
6791
6792 if (!bgp)
6793 return CMD_WARNING;
6794
6795 if (!EVPN_ENABLED(bgp)) {
6796 vty_out(vty, "This command is only supported under EVPN VRF\n");
6797 return CMD_WARNING;
6798 }
6799
6800 /* Add/update the export route-target */
6801 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6802 if (!ecomadd) {
6803 vty_out(vty, "%% Malformed Route Target list\n");
6804 return CMD_WARNING;
6805 }
6806 ecommunity_str(ecomadd);
6807
6808 /* Do nothing if we already have this export route-target */
6809 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6810 ecomadd))
6811 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6812
6813 return CMD_SUCCESS;
6814 }
6815
6816 DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6817 "no ead-es-route-target export RT",
6818 NO_STR
6819 "EAD ES Route Target\n"
6820 "export\n" EVPN_ASN_IP_HELP_STR)
6821 {
6822 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6823 struct ecommunity *ecomdel = NULL;
6824
6825 if (!bgp)
6826 return CMD_WARNING;
6827
6828 if (!EVPN_ENABLED(bgp)) {
6829 vty_out(vty, "This command is only supported under EVPN VRF\n");
6830 return CMD_WARNING;
6831 }
6832
6833 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6834 if (!ecomdel) {
6835 vty_out(vty, "%% Malformed Route Target list\n");
6836 return CMD_WARNING;
6837 }
6838 ecommunity_str(ecomdel);
6839
6840 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6841 ecomdel)) {
6842 ecommunity_free(&ecomdel);
6843 vty_out(vty,
6844 "%% RT specified does not match EAD-ES RT configuration\n");
6845 return CMD_WARNING;
6846 }
6847 bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6848
6849 return CMD_SUCCESS;
6850 }
6851
6852 DEFUN (bgp_evpn_vni_rt,
6853 bgp_evpn_vni_rt_cmd,
6854 "route-target <both|import|export> RT",
6855 "Route Target\n"
6856 "import and export\n"
6857 "import\n"
6858 "export\n"
6859 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6860 {
6861 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6862 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6863 int rt_type;
6864 struct ecommunity *ecomadd = NULL;
6865
6866 if (!bgp)
6867 return CMD_WARNING;
6868
6869 if (!EVPN_ENABLED(bgp)) {
6870 vty_out(vty,
6871 "This command is only supported under EVPN VRF\n");
6872 return CMD_WARNING;
6873 }
6874
6875 if (!strcmp(argv[1]->text, "import"))
6876 rt_type = RT_TYPE_IMPORT;
6877 else if (!strcmp(argv[1]->text, "export"))
6878 rt_type = RT_TYPE_EXPORT;
6879 else if (!strcmp(argv[1]->text, "both"))
6880 rt_type = RT_TYPE_BOTH;
6881 else {
6882 vty_out(vty, "%% Invalid Route Target type\n");
6883 return CMD_WARNING;
6884 }
6885
6886 /* Add/update the import route-target */
6887 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
6888 /* Note that first of the two RTs is created for "both" type */
6889 ecomadd = ecommunity_str2com(argv[2]->arg,
6890 ECOMMUNITY_ROUTE_TARGET, 0);
6891 if (!ecomadd) {
6892 vty_out(vty, "%% Malformed Route Target list\n");
6893 return CMD_WARNING;
6894 }
6895 ecommunity_str(ecomadd);
6896
6897 /* Do nothing if we already have this import route-target */
6898 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6899 evpn_configure_import_rt(bgp, vpn, ecomadd);
6900 }
6901
6902 /* Add/update the export route-target */
6903 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
6904 /* Note that second of the two RTs is created for "both" type */
6905 ecomadd = ecommunity_str2com(argv[2]->arg,
6906 ECOMMUNITY_ROUTE_TARGET, 0);
6907 if (!ecomadd) {
6908 vty_out(vty, "%% Malformed Route Target list\n");
6909 return CMD_WARNING;
6910 }
6911 ecommunity_str(ecomadd);
6912
6913 /* Do nothing if we already have this export route-target */
6914 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6915 evpn_configure_export_rt(bgp, vpn, ecomadd);
6916 }
6917
6918 return CMD_SUCCESS;
6919 }
6920
6921 DEFUN (no_bgp_evpn_vni_rt,
6922 no_bgp_evpn_vni_rt_cmd,
6923 "no route-target <both|import|export> RT",
6924 NO_STR
6925 "Route Target\n"
6926 "import and export\n"
6927 "import\n"
6928 "export\n"
6929 EVPN_ASN_IP_HELP_STR)
6930 {
6931 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6932 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6933 int rt_type, found_ecomdel;
6934 struct ecommunity *ecomdel = NULL;
6935
6936 if (!bgp)
6937 return CMD_WARNING;
6938
6939 if (!EVPN_ENABLED(bgp)) {
6940 vty_out(vty,
6941 "This command is only supported under EVPN VRF\n");
6942 return CMD_WARNING;
6943 }
6944
6945 if (!strcmp(argv[2]->text, "import"))
6946 rt_type = RT_TYPE_IMPORT;
6947 else if (!strcmp(argv[2]->text, "export"))
6948 rt_type = RT_TYPE_EXPORT;
6949 else if (!strcmp(argv[2]->text, "both"))
6950 rt_type = RT_TYPE_BOTH;
6951 else {
6952 vty_out(vty, "%% Invalid Route Target type\n");
6953 return CMD_WARNING;
6954 }
6955
6956 /* The user did "no route-target import", check to see if there are any
6957 * import route-targets configured. */
6958 if (rt_type == RT_TYPE_IMPORT) {
6959 if (!is_import_rt_configured(vpn)) {
6960 vty_out(vty,
6961 "%% Import RT is not configured for this VNI\n");
6962 return CMD_WARNING;
6963 }
6964 } else if (rt_type == RT_TYPE_EXPORT) {
6965 if (!is_export_rt_configured(vpn)) {
6966 vty_out(vty,
6967 "%% Export RT is not configured for this VNI\n");
6968 return CMD_WARNING;
6969 }
6970 } else if (rt_type == RT_TYPE_BOTH) {
6971 if (!is_import_rt_configured(vpn)
6972 && !is_export_rt_configured(vpn)) {
6973 vty_out(vty,
6974 "%% Import/Export RT is not configured for this VNI\n");
6975 return CMD_WARNING;
6976 }
6977 }
6978
6979 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6980 if (!ecomdel) {
6981 vty_out(vty, "%% Malformed Route Target list\n");
6982 return CMD_WARNING;
6983 }
6984 ecommunity_str(ecomdel);
6985
6986 if (rt_type == RT_TYPE_IMPORT) {
6987 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
6988 ecommunity_free(&ecomdel);
6989 vty_out(vty,
6990 "%% RT specified does not match configuration for this VNI\n");
6991 return CMD_WARNING;
6992 }
6993 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
6994 } else if (rt_type == RT_TYPE_EXPORT) {
6995 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
6996 ecommunity_free(&ecomdel);
6997 vty_out(vty,
6998 "%% RT specified does not match configuration for this VNI\n");
6999 return CMD_WARNING;
7000 }
7001 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7002 } else if (rt_type == RT_TYPE_BOTH) {
7003 found_ecomdel = 0;
7004
7005 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7006 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7007 found_ecomdel = 1;
7008 }
7009
7010 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7011 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7012 found_ecomdel = 1;
7013 }
7014
7015 if (!found_ecomdel) {
7016 ecommunity_free(&ecomdel);
7017 vty_out(vty,
7018 "%% RT specified does not match configuration for this VNI\n");
7019 return CMD_WARNING;
7020 }
7021 }
7022
7023 return CMD_SUCCESS;
7024 }
7025
7026 DEFUN (no_bgp_evpn_vni_rt_without_val,
7027 no_bgp_evpn_vni_rt_without_val_cmd,
7028 "no route-target <import|export>",
7029 NO_STR
7030 "Route Target\n"
7031 "import\n"
7032 "export\n")
7033 {
7034 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7035 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
7036 int rt_type;
7037
7038 if (!bgp)
7039 return CMD_WARNING;
7040
7041 if (!EVPN_ENABLED(bgp)) {
7042 vty_out(vty,
7043 "This command is only supported under EVPN VRF\n");
7044 return CMD_WARNING;
7045 }
7046
7047 if (!strcmp(argv[2]->text, "import")) {
7048 rt_type = RT_TYPE_IMPORT;
7049 } else if (!strcmp(argv[2]->text, "export")) {
7050 rt_type = RT_TYPE_EXPORT;
7051 } else {
7052 vty_out(vty, "%% Invalid Route Target type\n");
7053 return CMD_WARNING;
7054 }
7055
7056 /* Check if we should disallow. */
7057 if (rt_type == RT_TYPE_IMPORT) {
7058 if (!is_import_rt_configured(vpn)) {
7059 vty_out(vty,
7060 "%% Import RT is not configured for this VNI\n");
7061 return CMD_WARNING;
7062 }
7063 } else {
7064 if (!is_export_rt_configured(vpn)) {
7065 vty_out(vty,
7066 "%% Export RT is not configured for this VNI\n");
7067 return CMD_WARNING;
7068 }
7069 }
7070
7071 /* Unconfigure the RT. */
7072 if (rt_type == RT_TYPE_IMPORT)
7073 evpn_unconfigure_import_rt(bgp, vpn, NULL);
7074 else
7075 evpn_unconfigure_export_rt(bgp, vpn, NULL);
7076 return CMD_SUCCESS;
7077 }
7078
7079 static int vni_cmp(const void **a, const void **b)
7080 {
7081 const struct bgpevpn *first = *a;
7082 const struct bgpevpn *secnd = *b;
7083
7084 return secnd->vni - first->vni;
7085 }
7086
7087 /*
7088 * Output EVPN configuration information.
7089 */
7090 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
7091 safi_t safi)
7092 {
7093 if (bgp->advertise_all_vni)
7094 vty_out(vty, " advertise-all-vni\n");
7095
7096 if (hashcount(bgp->vnihash)) {
7097 struct list *vnilist = hash_to_list(bgp->vnihash);
7098 struct listnode *ln;
7099 struct bgpevpn *data;
7100
7101 list_sort(vnilist, vni_cmp);
7102 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
7103 write_vni_config(vty, data);
7104
7105 list_delete(&vnilist);
7106 }
7107
7108 if (bgp->advertise_autort_rfc8365)
7109 vty_out(vty, " autort rfc8365-compatible\n");
7110
7111 if (bgp->advertise_gw_macip)
7112 vty_out(vty, " advertise-default-gw\n");
7113
7114 if (bgp->evpn_info->advertise_svi_macip)
7115 vty_out(vty, " advertise-svi-ip\n");
7116
7117 if (bgp->resolve_overlay_index)
7118 vty_out(vty, " enable-resolve-overlay-index\n");
7119
7120 if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
7121 vty_out(vty, " ead-es-frag evi-limit %u\n",
7122 bgp_mh_info->evi_per_es_frag);
7123
7124 if (bgp_mh_info->host_routes_use_l3nhg !=
7125 BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
7126 if (bgp_mh_info->host_routes_use_l3nhg)
7127 vty_out(vty, " use-es-l3nhg\n");
7128 else
7129 vty_out(vty, " no use-es-l3nhg\n");
7130 }
7131
7132 if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
7133 if (bgp_mh_info->ead_evi_rx)
7134 vty_out(vty, " no disable-ead-evi-rx\n");
7135 else
7136 vty_out(vty, " disable-ead-evi-rx\n");
7137 }
7138
7139 if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
7140 if (bgp_mh_info->ead_evi_tx)
7141 vty_out(vty, " no disable-ead-evi-tx\n");
7142 else
7143 vty_out(vty, " disable-ead-evi-tx\n");
7144 }
7145
7146 if (!bgp->evpn_info->dup_addr_detect)
7147 vty_out(vty, " no dup-addr-detection\n");
7148
7149 if (bgp->evpn_info->dad_max_moves !=
7150 EVPN_DAD_DEFAULT_MAX_MOVES ||
7151 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
7152 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
7153 bgp->evpn_info->dad_max_moves,
7154 bgp->evpn_info->dad_time);
7155
7156 if (bgp->evpn_info->dad_freeze) {
7157 if (bgp->evpn_info->dad_freeze_time)
7158 vty_out(vty,
7159 " dup-addr-detection freeze %u\n",
7160 bgp->evpn_info->dad_freeze_time);
7161 else
7162 vty_out(vty,
7163 " dup-addr-detection freeze permanent\n");
7164 }
7165
7166 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
7167 vty_out(vty, " flooding disable\n");
7168
7169 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7170 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
7171 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7172 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
7173 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7174 else
7175 vty_out(vty,
7176 " advertise ipv4 unicast\n");
7177 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7178 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
7179 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7180 vty_out(vty,
7181 " advertise ipv4 unicast gateway-ip route-map %s\n",
7182 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7183 else
7184 vty_out(vty, " advertise ipv4 unicast gateway-ip\n");
7185 }
7186
7187 /* EAD ES export route-target */
7188 if (listcount(bgp_mh_info->ead_es_export_rtl)) {
7189 struct ecommunity *ecom;
7190 char *ecom_str;
7191 struct listnode *node;
7192
7193 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
7194 ecom)) {
7195
7196 ecom_str = ecommunity_ecom2str(
7197 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7198 vty_out(vty, " ead-es-route-target export %s\n",
7199 ecom_str);
7200 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7201 }
7202 }
7203
7204 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7205 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
7206 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7207 vty_out(vty,
7208 " advertise ipv6 unicast route-map %s\n",
7209 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7210 else
7211 vty_out(vty,
7212 " advertise ipv6 unicast\n");
7213 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7214 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
7215 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7216 vty_out(vty,
7217 " advertise ipv6 unicast gateway-ip route-map %s\n",
7218 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7219 else
7220 vty_out(vty, " advertise ipv6 unicast gateway-ip\n");
7221 }
7222
7223 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7224 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
7225 vty_out(vty, " default-originate ipv4\n");
7226
7227 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7228 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
7229 vty_out(vty, " default-originate ipv6\n");
7230
7231 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
7232 if (!bgp->evpn_info->advertise_pip)
7233 vty_out(vty, " no advertise-pip\n");
7234 if (bgp->evpn_info->advertise_pip) {
7235 if (bgp->evpn_info->pip_ip_static.s_addr
7236 != INADDR_ANY) {
7237 vty_out(vty, " advertise-pip ip %pI4",
7238 &bgp->evpn_info->pip_ip_static);
7239 if (!is_zero_mac(&(
7240 bgp->evpn_info->pip_rmac_static))) {
7241 char buf[ETHER_ADDR_STRLEN];
7242
7243 vty_out(vty, " mac %s",
7244 prefix_mac2str(
7245 &bgp->evpn_info
7246 ->pip_rmac,
7247 buf, sizeof(buf)));
7248 }
7249 vty_out(vty, "\n");
7250 }
7251 }
7252 }
7253 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
7254 vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
7255
7256 /* import route-target */
7257 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
7258 char *ecom_str;
7259 struct listnode *node, *nnode;
7260 struct vrf_route_target *l3rt;
7261
7262 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
7263 l3rt)) {
7264
7265 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7266 continue;
7267
7268 ecom_str = ecommunity_ecom2str(
7269 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7270
7271 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
7272 char *vni_str = NULL;
7273
7274 vni_str = strchr(ecom_str, ':');
7275 if (!vni_str) {
7276 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7277 continue;
7278 }
7279
7280 /* Move pointer to vni */
7281 vni_str += 1;
7282
7283 vty_out(vty, " route-target import *:%s\n",
7284 vni_str);
7285
7286 } else
7287 vty_out(vty, " route-target import %s\n",
7288 ecom_str);
7289
7290 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7291 }
7292 }
7293
7294 /* import route-target auto */
7295 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
7296 vty_out(vty, " route-target import auto\n");
7297
7298 /* export route-target */
7299 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
7300 char *ecom_str;
7301 struct listnode *node, *nnode;
7302 struct vrf_route_target *l3rt;
7303
7304 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
7305 l3rt)) {
7306
7307 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7308 continue;
7309
7310 ecom_str = ecommunity_ecom2str(
7311 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7312 vty_out(vty, " route-target export %s\n", ecom_str);
7313 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7314 }
7315 }
7316
7317 /* export route-target auto */
7318 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
7319 vty_out(vty, " route-target export auto\n");
7320 }
7321
7322 void bgp_ethernetvpn_init(void)
7323 {
7324 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
7325 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
7326 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
7327 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
7328 install_element(VIEW_NODE,
7329 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
7330 install_element(VIEW_NODE,
7331 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
7332 install_element(
7333 VIEW_NODE,
7334 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
7335 install_element(
7336 VIEW_NODE,
7337 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
7338 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
7339 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
7340 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
7341 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
7342 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
7343 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
7344 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
7345 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
7346 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
7347 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
7348 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
7349 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
7350 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
7351 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
7352 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
7353 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
7354 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
7355 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
7356 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
7357 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
7358 install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
7359 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
7360 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
7361 install_element(BGP_EVPN_NODE,
7362 &bgp_evpn_enable_resolve_overlay_index_cmd);
7363
7364 /* test commands */
7365 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
7366 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
7367
7368 /* "show bgp l2vpn evpn" commands. */
7369 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
7370 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
7371 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
7372 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
7373 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
7374 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
7375 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
7376 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
7377 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
7378 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
7379 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
7380 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
7381 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
7382 install_element(VIEW_NODE,
7383 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
7384 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
7385 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
7386 install_element(VIEW_NODE,
7387 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
7388 install_element(VIEW_NODE,
7389 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
7390 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
7391 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
7392
7393 /* "show bgp vni" commands. */
7394 install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
7395 install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
7396 install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
7397 install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
7398 install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
7399 install_element(VIEW_NODE, &show_bgp_vni_cmd);
7400 install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
7401 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
7402 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
7403 install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
7404 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
7405 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
7406
7407 /* "show bgp evpn" commands. */
7408 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
7409 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
7410 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
7411 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
7412 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
7413 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
7414 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
7415 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
7416 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
7417 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
7418 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7419 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
7420
7421 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
7422 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
7423 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
7424 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
7425 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
7426 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
7427 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
7428 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
7429 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
7430 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
7431 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
7432 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
7433 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
7434 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
7435 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
7436 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
7437 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
7438 install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
7439 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
7440 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
7441 install_element(BGP_EVPN_VNI_NODE,
7442 &bgp_evpn_advertise_default_gw_vni_cmd);
7443 install_element(BGP_EVPN_VNI_NODE,
7444 &no_bgp_evpn_advertise_default_gw_vni_cmd);
7445 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
7446 install_element(BGP_EVPN_VNI_NODE,
7447 &no_bgp_evpn_advertise_vni_subnet_cmd);
7448 }