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