]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
Merge pull request #12851 from sri-mohan1/sri-mohan-ldp
[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)
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 /* Overall header/legend displayed once. */
3096 if (header) {
3097 bgp_evpn_show_route_header(vty, bgp,
3098 tbl_ver,
3099 json);
3100 if (!json)
3101 vty_out(vty,
3102 "%19s Extended Community\n"
3103 , " ");
3104 header = 0;
3105 }
3106
3107 /* RD header - per RD. */
3108 if (rd_header) {
3109 bgp_evpn_show_route_rd_header(
3110 vty, rd_dest, json_rd, rd_str,
3111 RD_ADDRSTRLEN);
3112 rd_header = 0;
3113 }
3114
3115 prefix_cnt++;
3116 }
3117
3118 if (json) {
3119 json_prefix = json_object_new_object();
3120 json_paths = json_object_new_array();
3121 json_object_string_addf(json_prefix, "prefix",
3122 "%pFX", p);
3123 json_object_int_add(json_prefix, "prefixLen",
3124 p->prefixlen);
3125 }
3126
3127 /* Prefix and num paths displayed once per prefix. */
3128 if (detail)
3129 route_vty_out_detail_header(
3130 vty, bgp, dest,
3131 bgp_dest_get_prefix(dest),
3132 (struct prefix_rd *)rd_destp, AFI_L2VPN,
3133 SAFI_EVPN, json_prefix, false);
3134
3135 /* For EVPN, the prefix is displayed for each path (to
3136 * fit in
3137 * with code that already exists).
3138 */
3139 for (; pi; pi = pi->next) {
3140 json_object *json_path = NULL;
3141
3142 path_cnt++;
3143 add_prefix_to_json = 1;
3144 add_rd_to_json = 1;
3145
3146 if (json)
3147 json_path = json_object_new_array();
3148
3149 if (detail) {
3150 route_vty_out_detail(
3151 vty, bgp, dest,
3152 bgp_dest_get_prefix(dest), pi,
3153 AFI_L2VPN, SAFI_EVPN,
3154 RPKI_NOT_BEING_USED, json_path);
3155 } else
3156 route_vty_out(vty, p, pi, 0, SAFI_EVPN,
3157 json_path, false);
3158
3159 if (json)
3160 json_object_array_add(json_paths,
3161 json_path);
3162 }
3163
3164 if (json) {
3165 if (add_prefix_to_json) {
3166 json_object_object_add(json_prefix,
3167 "paths",
3168 json_paths);
3169 json_object_object_addf(json_rd,
3170 json_prefix,
3171 "%pFX", p);
3172 } else {
3173 json_object_free(json_prefix);
3174 json_object_free(json_paths);
3175 json_prefix = NULL;
3176 json_paths = NULL;
3177 }
3178 }
3179 }
3180
3181 if (json) {
3182 if (add_rd_to_json)
3183 json_object_object_add(json, rd_str, json_rd);
3184 else {
3185 json_object_free(json_rd);
3186 json_rd = NULL;
3187 }
3188 }
3189 }
3190
3191 if (json) {
3192 json_object_int_add(json, "numPrefix", prefix_cnt);
3193 json_object_int_add(json, "numPaths", path_cnt);
3194 } else {
3195 if (prefix_cnt == 0) {
3196 vty_out(vty, "No EVPN prefixes %sexist\n",
3197 type ? "(of requested type) " : "");
3198 } else {
3199 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
3200 prefix_cnt, path_cnt,
3201 type ? " (of requested type)" : "");
3202 }
3203 }
3204 }
3205
3206 int bgp_evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
3207 bool use_json, int detail)
3208 {
3209 json_object *json = NULL;
3210
3211 if (use_json)
3212 json = json_object_new_object();
3213
3214 evpn_show_all_routes(vty, bgp, type, json, detail);
3215
3216 if (use_json)
3217 vty_json(vty, json);
3218 return CMD_SUCCESS;
3219 }
3220
3221 /*
3222 * Display specified VNI (vty handler)
3223 */
3224 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
3225 json_object *json)
3226 {
3227 uint8_t found = 0;
3228 struct bgpevpn *vpn;
3229
3230 vpn = bgp_evpn_lookup_vni(bgp, vni);
3231 if (vpn) {
3232 found = 1;
3233 display_vni(vty, vpn, json);
3234 } else {
3235 struct bgp *bgp_temp;
3236 struct listnode *node = NULL;
3237
3238 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3239 if (bgp_temp->l3vni == vni) {
3240 found = 1;
3241 display_l3vni(vty, bgp_temp, json);
3242 }
3243 }
3244 }
3245
3246 if (!found) {
3247 if (json) {
3248 vty_out(vty, "{}\n");
3249 } else {
3250 vty_out(vty, "VNI not found\n");
3251 return;
3252 }
3253 }
3254 }
3255
3256 /*
3257 * Display a VNI (upon user query).
3258 */
3259 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
3260 json_object *json)
3261 {
3262 void *args[2];
3263 struct bgp *bgp_temp = NULL;
3264 struct listnode *node;
3265
3266
3267 if (!json) {
3268 vty_out(vty, "Flags: * - Kernel\n");
3269 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3270 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3271 }
3272
3273 /* print all L2 VNIS */
3274 args[0] = vty;
3275 args[1] = json;
3276 hash_iterate(bgp->vnihash,
3277 (void (*)(struct hash_bucket *, void *))show_vni_entry,
3278 args);
3279
3280 /* print all L3 VNIs */
3281 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
3282 show_l3vni_entry(vty, bgp_temp, json);
3283 }
3284
3285 /*
3286 * evpn - enable advertisement of svi MAC-IP
3287 */
3288 static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
3289 uint32_t set)
3290 {
3291 if (!vpn) {
3292 if (set && bgp->evpn_info->advertise_svi_macip)
3293 return;
3294 else if (!set && !bgp->evpn_info->advertise_svi_macip)
3295 return;
3296
3297 bgp->evpn_info->advertise_svi_macip = set;
3298 bgp_zebra_advertise_svi_macip(bgp,
3299 bgp->evpn_info->advertise_svi_macip, 0);
3300 } else {
3301 if (set && vpn->advertise_svi_macip)
3302 return;
3303 else if (!set && !vpn->advertise_svi_macip)
3304 return;
3305
3306 vpn->advertise_svi_macip = set;
3307 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
3308 vpn->vni);
3309 }
3310 }
3311
3312 /*
3313 * evpn - enable advertisement of default g/w
3314 */
3315 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
3316 {
3317 if (!vpn) {
3318 if (bgp->advertise_gw_macip)
3319 return;
3320
3321 bgp->advertise_gw_macip = 1;
3322 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3323 } else {
3324 if (vpn->advertise_gw_macip)
3325 return;
3326
3327 vpn->advertise_gw_macip = 1;
3328 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3329 vpn->vni);
3330 }
3331 return;
3332 }
3333
3334 /*
3335 * evpn - disable advertisement of default g/w
3336 */
3337 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
3338 struct bgpevpn *vpn)
3339 {
3340 if (!vpn) {
3341 if (!bgp->advertise_gw_macip)
3342 return;
3343
3344 bgp->advertise_gw_macip = 0;
3345 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
3346 } else {
3347 if (!vpn->advertise_gw_macip)
3348 return;
3349
3350 vpn->advertise_gw_macip = 0;
3351 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
3352 vpn->vni);
3353 }
3354 return;
3355 }
3356
3357 /*
3358 * evpn - enable advertisement of default g/w
3359 */
3360 static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
3361 afi_t afi, bool add)
3362 {
3363 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
3364
3365 if (add) {
3366 /* bail if we are already advertising default route */
3367 if (evpn_default_originate_set(bgp_vrf, afi, safi))
3368 return;
3369
3370 if (afi == AFI_IP)
3371 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3372 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3373 else if (afi == AFI_IP6)
3374 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3375 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3376 } else {
3377 /* bail out if we havent advertised the default route */
3378 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
3379 return;
3380 if (afi == AFI_IP)
3381 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3382 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
3383 else if (afi == AFI_IP6)
3384 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
3386 }
3387
3388 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
3389 }
3390
3391 /*
3392 * evpn - enable advertisement of default g/w
3393 */
3394 static void evpn_set_advertise_subnet(struct bgp *bgp,
3395 struct bgpevpn *vpn)
3396 {
3397 if (vpn->advertise_subnet)
3398 return;
3399
3400 vpn->advertise_subnet = 1;
3401 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3402 }
3403
3404 /*
3405 * evpn - disable advertisement of default g/w
3406 */
3407 static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
3408 {
3409 if (!vpn->advertise_subnet)
3410 return;
3411
3412 vpn->advertise_subnet = 0;
3413 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
3414 }
3415
3416 /*
3417 * EVPN (VNI advertisement) enabled. Register with zebra.
3418 */
3419 static void evpn_set_advertise_all_vni(struct bgp *bgp)
3420 {
3421 bgp->advertise_all_vni = 1;
3422 bgp_set_evpn(bgp);
3423 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3424 }
3425
3426 /*
3427 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3428 * cache, EVPN routes (delete and withdraw from peers).
3429 */
3430 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
3431 {
3432 bgp->advertise_all_vni = 0;
3433 bgp_set_evpn(bgp_get_default());
3434 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3435 bgp_evpn_cleanup_on_disable(bgp);
3436 }
3437
3438 /* Set resolve overlay index flag */
3439 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp *bgp, bool set)
3440 {
3441 if (set == bgp->resolve_overlay_index)
3442 return;
3443
3444 if (set) {
3445 bgp->resolve_overlay_index = true;
3446 hash_iterate(bgp->vnihash,
3447 (void (*)(struct hash_bucket *, void *))
3448 bgp_evpn_handle_resolve_overlay_index_set,
3449 NULL);
3450 } else {
3451 hash_iterate(
3452 bgp->vnihash,
3453 (void (*)(struct hash_bucket *, void *))
3454 bgp_evpn_handle_resolve_overlay_index_unset,
3455 NULL);
3456 bgp->resolve_overlay_index = false;
3457 }
3458 }
3459
3460 /*
3461 * EVPN - use RFC8365 to auto-derive RT
3462 */
3463 static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3464 {
3465 bgp->advertise_autort_rfc8365 = 1;
3466 bgp_evpn_handle_autort_change(bgp);
3467 }
3468
3469 /*
3470 * EVPN - don't use RFC8365 to auto-derive RT
3471 */
3472 static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3473 {
3474 bgp->advertise_autort_rfc8365 = 0;
3475 bgp_evpn_handle_autort_change(bgp);
3476 }
3477
3478 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
3479 {
3480 char *ecom_str;
3481 struct listnode *node, *nnode;
3482 struct ecommunity *ecom;
3483
3484 if (is_vni_configured(vpn)) {
3485 vty_out(vty, " vni %u\n", vpn->vni);
3486 if (is_rd_configured(vpn))
3487 vty_out(vty, " rd %s\n", vpn->prd_pretty);
3488
3489 if (is_import_rt_configured(vpn)) {
3490 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3491 ecom)) {
3492 ecom_str = ecommunity_ecom2str(
3493 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3494 vty_out(vty, " route-target import %s\n",
3495 ecom_str);
3496 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3497 }
3498 }
3499
3500 if (is_export_rt_configured(vpn)) {
3501 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3502 ecom)) {
3503 ecom_str = ecommunity_ecom2str(
3504 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3505 vty_out(vty, " route-target export %s\n",
3506 ecom_str);
3507 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3508 }
3509 }
3510
3511 if (vpn->advertise_gw_macip)
3512 vty_out(vty, " advertise-default-gw\n");
3513
3514 if (vpn->advertise_svi_macip)
3515 vty_out(vty, " advertise-svi-ip\n");
3516
3517 if (vpn->advertise_subnet)
3518 vty_out(vty, " advertise-subnet\n");
3519
3520 vty_out(vty, " exit-vni\n");
3521 }
3522 }
3523
3524 #include "bgpd/bgp_evpn_vty_clippy.c"
3525
3526 DEFPY(bgp_evpn_flood_control,
3527 bgp_evpn_flood_control_cmd,
3528 "[no$no] flooding <disable$disable|head-end-replication$her>",
3529 NO_STR
3530 "Specify handling for BUM packets\n"
3531 "Do not flood any BUM packets\n"
3532 "Flood BUM packets using head-end replication\n")
3533 {
3534 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3535 enum vxlan_flood_control flood_ctrl;
3536
3537 if (!bgp)
3538 return CMD_WARNING;
3539
3540 if (disable && !no)
3541 flood_ctrl = VXLAN_FLOOD_DISABLED;
3542 else if (her || no)
3543 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3544 else
3545 return CMD_WARNING;
3546
3547 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3548 return CMD_SUCCESS;
3549
3550 bgp->vxlan_flood_ctrl = flood_ctrl;
3551 bgp_evpn_flood_control_change(bgp);
3552
3553 return CMD_SUCCESS;
3554 }
3555
3556 DEFUN (bgp_evpn_advertise_default_gw_vni,
3557 bgp_evpn_advertise_default_gw_vni_cmd,
3558 "advertise-default-gw",
3559 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3560 {
3561 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3562 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3563
3564 if (!bgp)
3565 return CMD_WARNING;
3566
3567 evpn_set_advertise_default_gw(bgp, vpn);
3568
3569 return CMD_SUCCESS;
3570 }
3571
3572 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3573 no_bgp_evpn_advertise_default_gw_vni_cmd,
3574 "no advertise-default-gw",
3575 NO_STR
3576 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3577 {
3578 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3579 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3580
3581 if (!bgp)
3582 return CMD_WARNING;
3583
3584 evpn_unset_advertise_default_gw(bgp, vpn);
3585
3586 return CMD_SUCCESS;
3587 }
3588
3589
3590 DEFUN (bgp_evpn_advertise_default_gw,
3591 bgp_evpn_advertise_default_gw_cmd,
3592 "advertise-default-gw",
3593 "Advertise All default g/w mac-ip routes in EVPN\n")
3594 {
3595 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3596
3597 if (!bgp)
3598 return CMD_WARNING;
3599
3600 if (!EVPN_ENABLED(bgp)) {
3601 vty_out(vty,
3602 "This command is only supported under the EVPN VRF\n");
3603 return CMD_WARNING;
3604 }
3605
3606 evpn_set_advertise_default_gw(bgp, NULL);
3607
3608 return CMD_SUCCESS;
3609 }
3610
3611 DEFUN (no_bgp_evpn_advertise_default_gw,
3612 no_bgp_evpn_advertise_default_gw_cmd,
3613 "no advertise-default-gw",
3614 NO_STR
3615 "Withdraw All default g/w mac-ip routes from EVPN\n")
3616 {
3617 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3618
3619 if (!bgp)
3620 return CMD_WARNING;
3621
3622 evpn_unset_advertise_default_gw(bgp, NULL);
3623
3624 return CMD_SUCCESS;
3625 }
3626
3627 DEFUN (bgp_evpn_advertise_all_vni,
3628 bgp_evpn_advertise_all_vni_cmd,
3629 "advertise-all-vni",
3630 "Advertise All local VNIs\n")
3631 {
3632 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3633 struct bgp *bgp_evpn = NULL;
3634
3635 if (!bgp)
3636 return CMD_WARNING;
3637
3638 bgp_evpn = bgp_get_evpn();
3639 if (bgp_evpn && bgp_evpn != bgp) {
3640 vty_out(vty, "%% Please unconfigure EVPN in %s\n",
3641 bgp_evpn->name_pretty);
3642 return CMD_WARNING_CONFIG_FAILED;
3643 }
3644
3645 evpn_set_advertise_all_vni(bgp);
3646 return CMD_SUCCESS;
3647 }
3648
3649 DEFUN (no_bgp_evpn_advertise_all_vni,
3650 no_bgp_evpn_advertise_all_vni_cmd,
3651 "no advertise-all-vni",
3652 NO_STR
3653 "Advertise All local VNIs\n")
3654 {
3655 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3656
3657 if (!bgp)
3658 return CMD_WARNING;
3659 evpn_unset_advertise_all_vni(bgp);
3660 return CMD_SUCCESS;
3661 }
3662
3663 DEFUN (bgp_evpn_advertise_autort_rfc8365,
3664 bgp_evpn_advertise_autort_rfc8365_cmd,
3665 "autort rfc8365-compatible",
3666 "Auto-derivation of RT\n"
3667 "Auto-derivation of RT using RFC8365\n")
3668 {
3669 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3670
3671 if (!bgp)
3672 return CMD_WARNING;
3673 evpn_set_advertise_autort_rfc8365(bgp);
3674 return CMD_SUCCESS;
3675 }
3676
3677 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3678 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3679 "no autort rfc8365-compatible",
3680 NO_STR
3681 "Auto-derivation of RT\n"
3682 "Auto-derivation of RT using RFC8365\n")
3683 {
3684 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3685
3686 if (!bgp)
3687 return CMD_WARNING;
3688 evpn_unset_advertise_autort_rfc8365(bgp);
3689 return CMD_SUCCESS;
3690 }
3691
3692 DEFUN (bgp_evpn_default_originate,
3693 bgp_evpn_default_originate_cmd,
3694 "default-originate <ipv4 | ipv6>",
3695 "originate a default route\n"
3696 "ipv4 address family\n"
3697 "ipv6 address family\n")
3698 {
3699 afi_t afi = 0;
3700 int idx_afi = 0;
3701 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3702
3703 if (!bgp_vrf)
3704 return CMD_WARNING;
3705 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3706 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3707 return CMD_SUCCESS;
3708 }
3709
3710 DEFUN (no_bgp_evpn_default_originate,
3711 no_bgp_evpn_default_originate_cmd,
3712 "no default-originate <ipv4 | ipv6>",
3713 NO_STR
3714 "withdraw a default route\n"
3715 "ipv4 address family\n"
3716 "ipv6 address family\n")
3717 {
3718 afi_t afi = 0;
3719 int idx_afi = 0;
3720 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3721
3722 if (!bgp_vrf)
3723 return CMD_WARNING;
3724 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3725 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3726 return CMD_SUCCESS;
3727 }
3728
3729 DEFPY (dup_addr_detection,
3730 dup_addr_detection_cmd,
3731 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3732 "Duplicate address detection\n"
3733 "Max allowed moves before address detected as duplicate\n"
3734 "Num of max allowed moves (2-1000) default 5\n"
3735 "Duplicate address detection time\n"
3736 "Time in seconds (2-1800) default 180\n")
3737 {
3738 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3739
3740 if (!bgp_vrf)
3741 return CMD_WARNING;
3742
3743 if (!EVPN_ENABLED(bgp_vrf)) {
3744 vty_out(vty,
3745 "This command is only supported under the EVPN VRF\n");
3746 return CMD_WARNING;
3747 }
3748
3749 bgp_vrf->evpn_info->dup_addr_detect = true;
3750
3751 if (time_val)
3752 bgp_vrf->evpn_info->dad_time = time_val;
3753 if (max_moves_val)
3754 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3755
3756 bgp_zebra_dup_addr_detection(bgp_vrf);
3757
3758 return CMD_SUCCESS;
3759 }
3760
3761 DEFPY (dup_addr_detection_auto_recovery,
3762 dup_addr_detection_auto_recovery_cmd,
3763 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3764 "Duplicate address detection\n"
3765 "Duplicate address detection freeze\n"
3766 "Duplicate address detection permanent freeze\n"
3767 "Duplicate address detection freeze time (30-3600)\n")
3768 {
3769 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3770 uint32_t freeze_time = freeze_time_val;
3771
3772 if (!bgp_vrf)
3773 return CMD_WARNING;
3774
3775 if (!EVPN_ENABLED(bgp_vrf)) {
3776 vty_out(vty,
3777 "This command is only supported under the EVPN VRF\n");
3778 return CMD_WARNING;
3779 }
3780
3781 bgp_vrf->evpn_info->dup_addr_detect = true;
3782 bgp_vrf->evpn_info->dad_freeze = true;
3783 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3784
3785 bgp_zebra_dup_addr_detection(bgp_vrf);
3786
3787 return CMD_SUCCESS;
3788 }
3789
3790 DEFPY (no_dup_addr_detection,
3791 no_dup_addr_detection_cmd,
3792 "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>]",
3793 NO_STR
3794 "Duplicate address detection\n"
3795 "Max allowed moves before address detected as duplicate\n"
3796 "Num of max allowed moves (2-1000) default 5\n"
3797 "Duplicate address detection time\n"
3798 "Time in seconds (2-1800) default 180\n"
3799 "Duplicate address detection freeze\n"
3800 "Duplicate address detection permanent freeze\n"
3801 "Duplicate address detection freeze time (30-3600)\n")
3802 {
3803 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3804 uint32_t max_moves = (uint32_t)max_moves_val;
3805 uint32_t freeze_time = (uint32_t)freeze_time_val;
3806
3807 if (!bgp_vrf)
3808 return CMD_WARNING;
3809
3810 if (!EVPN_ENABLED(bgp_vrf)) {
3811 vty_out(vty,
3812 "This command is only supported under the EVPN VRF\n");
3813 return CMD_WARNING;
3814 }
3815
3816 if (argc == 2) {
3817 if (!bgp_vrf->evpn_info->dup_addr_detect)
3818 return CMD_SUCCESS;
3819 /* Reset all parameters to default. */
3820 bgp_vrf->evpn_info->dup_addr_detect = false;
3821 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3822 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3823 bgp_vrf->evpn_info->dad_freeze = false;
3824 bgp_vrf->evpn_info->dad_freeze_time = 0;
3825 } else {
3826 if (max_moves) {
3827 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3828 vty_out(vty,
3829 "%% Value does not match with config\n");
3830 return CMD_SUCCESS;
3831 }
3832 bgp_vrf->evpn_info->dad_max_moves =
3833 EVPN_DAD_DEFAULT_MAX_MOVES;
3834 }
3835
3836 if (time_val) {
3837 if (bgp_vrf->evpn_info->dad_time != time_val) {
3838 vty_out(vty,
3839 "%% Value does not match with config\n");
3840 return CMD_SUCCESS;
3841 }
3842 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3843 }
3844
3845 if (freeze_time) {
3846 if (bgp_vrf->evpn_info->dad_freeze_time
3847 != freeze_time) {
3848 vty_out(vty,
3849 "%% Value does not match with config\n");
3850 return CMD_SUCCESS;
3851 }
3852 bgp_vrf->evpn_info->dad_freeze_time = 0;
3853 bgp_vrf->evpn_info->dad_freeze = false;
3854 }
3855
3856 if (permanent_val) {
3857 if (bgp_vrf->evpn_info->dad_freeze_time) {
3858 vty_out(vty,
3859 "%% Value does not match with config\n");
3860 return CMD_SUCCESS;
3861 }
3862 bgp_vrf->evpn_info->dad_freeze = false;
3863 }
3864 }
3865
3866 bgp_zebra_dup_addr_detection(bgp_vrf);
3867
3868 return CMD_SUCCESS;
3869 }
3870
3871 DEFPY(bgp_evpn_advertise_svi_ip,
3872 bgp_evpn_advertise_svi_ip_cmd,
3873 "[no$no] advertise-svi-ip",
3874 NO_STR
3875 "Advertise svi mac-ip routes in EVPN\n")
3876 {
3877 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3878
3879 if (!bgp)
3880 return CMD_WARNING;
3881
3882 if (no)
3883 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3884 else {
3885 if (!EVPN_ENABLED(bgp)) {
3886 vty_out(vty,
3887 "This command is only supported under EVPN VRF\n");
3888 return CMD_WARNING;
3889 }
3890 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3891 }
3892
3893 return CMD_SUCCESS;
3894 }
3895
3896 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3897 bgp_evpn_advertise_svi_ip_vni_cmd,
3898 "[no$no] advertise-svi-ip",
3899 NO_STR
3900 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3901 {
3902 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3903 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3904
3905 if (!bgp)
3906 return CMD_WARNING;
3907
3908 if (no)
3909 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3910 else
3911 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3912
3913 return CMD_SUCCESS;
3914 }
3915
3916 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3917 bgp_evpn_advertise_vni_subnet_cmd,
3918 "advertise-subnet",
3919 "Advertise the subnet corresponding to VNI\n")
3920 {
3921 struct bgp *bgp_vrf = NULL;
3922 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3923 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3924
3925 if (!bgp)
3926 return CMD_WARNING;
3927
3928 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3929 if (!bgp_vrf)
3930 return CMD_WARNING;
3931
3932 evpn_set_advertise_subnet(bgp, vpn);
3933 return CMD_SUCCESS;
3934 }
3935
3936 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3937 no_bgp_evpn_advertise_vni_subnet_cmd,
3938 "no advertise-subnet",
3939 NO_STR
3940 "Advertise All local VNIs\n")
3941 {
3942 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3943 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3944
3945 if (!bgp)
3946 return CMD_WARNING;
3947
3948 evpn_unset_advertise_subnet(bgp, vpn);
3949 return CMD_SUCCESS;
3950 }
3951
3952 DEFUN (bgp_evpn_advertise_type5,
3953 bgp_evpn_advertise_type5_cmd,
3954 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [gateway-ip] [route-map RMAP_NAME]",
3955 "Advertise prefix routes\n"
3956 BGP_AFI_HELP_STR
3957 BGP_SAFI_HELP_STR
3958 "advertise gateway IP overlay index\n"
3959 "route-map for filtering specific routes\n"
3960 "Name of the route map\n")
3961 {
3962 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3963 int idx_afi = 0;
3964 int idx_safi = 0;
3965 int idx_rmap = 0;
3966 afi_t afi = 0;
3967 safi_t safi = 0;
3968 int ret = 0;
3969 int rmap_changed = 0;
3970 enum overlay_index_type oly = OVERLAY_INDEX_TYPE_NONE;
3971 int idx_oly = 0;
3972 bool adv_flag_changed = false;
3973
3974 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3975 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3976 argv_find_and_parse_oly_idx(argv, argc, &idx_oly, &oly);
3977
3978 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3979 if (ret) {
3980 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3981 rmap_changed = 1;
3982 else if (strcmp(argv[idx_rmap + 1]->arg,
3983 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3984 != 0)
3985 rmap_changed = 1;
3986 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3987 rmap_changed = 1;
3988 }
3989
3990 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3991 vty_out(vty,
3992 "%% Only ipv4 or ipv6 address families are supported\n");
3993 return CMD_WARNING;
3994 }
3995
3996 if (safi != SAFI_UNICAST) {
3997 vty_out(vty,
3998 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3999 return CMD_WARNING;
4000 }
4001
4002 if ((oly != OVERLAY_INDEX_TYPE_NONE)
4003 && (oly != OVERLAY_INDEX_GATEWAY_IP)) {
4004 vty_out(vty, "%% Unknown overlay-index type specified\n");
4005 return CMD_WARNING;
4006 }
4007
4008 if (afi == AFI_IP) {
4009 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4010 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))
4011 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4012 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4013
4014 /*
4015 * this is the case for first time ever configuration
4016 * adv ipv4 unicast is enabled for the first time.
4017 * So no need to reset any flag
4018 */
4019 if (oly == OVERLAY_INDEX_TYPE_NONE)
4020 SET_FLAG(
4021 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4022 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4023 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4024 SET_FLAG(
4025 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4027 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4028 && (!CHECK_FLAG(
4029 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4030 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST))) {
4031
4032 /*
4033 * This is modify case from gateway-ip
4034 * to no overlay index
4035 */
4036 adv_flag_changed = true;
4037 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4038 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4039 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4040 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4041 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4042 && (!CHECK_FLAG(
4043 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4044 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4045
4046 /*
4047 * This is modify case from no overlay index
4048 * to gateway-ip
4049 */
4050 adv_flag_changed = true;
4051 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4052 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4053 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4054 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4055 } else {
4056
4057 /*
4058 * Command is issued with the same option
4059 * (no overlay index or gateway-ip) which was
4060 * already configured. So nothing to do.
4061 * However, route-map may have been modified.
4062 * check if route-map has been modified.
4063 * If not, return an error
4064 */
4065 if (!rmap_changed)
4066 return CMD_WARNING;
4067 }
4068 } else {
4069 if ((!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4070 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))
4071 && (!CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4072 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4073
4074 /*
4075 * this is the case for first time ever configuration
4076 * adv ipv6 unicast is enabled for the first time.
4077 * So no need to reset any flag
4078 */
4079 if (oly == OVERLAY_INDEX_TYPE_NONE)
4080 SET_FLAG(
4081 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4083 else if (oly == OVERLAY_INDEX_GATEWAY_IP)
4084 SET_FLAG(
4085 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4086 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4087 } else if ((oly == OVERLAY_INDEX_TYPE_NONE)
4088 && (!CHECK_FLAG(
4089 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4090 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST))) {
4091
4092 /*
4093 * This is modify case from gateway-ip
4094 * to no overlay index
4095 */
4096 adv_flag_changed = true;
4097 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4098 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4099 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4100 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4101 } else if ((oly == OVERLAY_INDEX_GATEWAY_IP)
4102 && (!CHECK_FLAG(
4103 bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4104 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))) {
4105
4106 /*
4107 * This is modify case from no overlay index
4108 * to gateway-ip
4109 */
4110 adv_flag_changed = true;
4111 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4112 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4113 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4114 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4115 } else {
4116
4117 /*
4118 * Command is issued with the same option
4119 * (no overlay index or gateway-ip) which was
4120 * already configured. So nothing to do.
4121 * However, route-map may have been modified.
4122 * check if route-map has been modified.
4123 * If not, return an error
4124 */
4125 if (!rmap_changed)
4126 return CMD_WARNING;
4127 }
4128 }
4129
4130 if ((rmap_changed) || (adv_flag_changed)) {
4131
4132 /* If either of these are changed, then FRR needs to
4133 * withdraw already advertised type5 routes.
4134 */
4135 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4136 if (rmap_changed) {
4137 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4138 XFREE(MTYPE_ROUTE_MAP_NAME,
4139 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4140 route_map_counter_decrement(
4141 bgp_vrf->adv_cmd_rmap[afi][safi].map);
4142 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4143 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4144 }
4145 }
4146 }
4147
4148 /* set the route-map for advertise command */
4149 if (ret && argv[idx_rmap + 1]->arg) {
4150 bgp_vrf->adv_cmd_rmap[afi][safi].name =
4151 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
4152 bgp_vrf->adv_cmd_rmap[afi][safi].map =
4153 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
4154 route_map_counter_increment(
4155 bgp_vrf->adv_cmd_rmap[afi][safi].map);
4156 }
4157
4158 /* advertise type-5 routes */
4159 if (advertise_type5_routes(bgp_vrf, afi))
4160 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
4161 return CMD_SUCCESS;
4162 }
4163
4164 DEFUN (no_bgp_evpn_advertise_type5,
4165 no_bgp_evpn_advertise_type5_cmd,
4166 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
4167 NO_STR
4168 "Advertise prefix routes\n"
4169 BGP_AFI_HELP_STR
4170 BGP_SAFI_HELP_STR
4171 "route-map for filtering specific routes\n"
4172 "Name of the route map\n")
4173 {
4174 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4175 int idx_afi = 0;
4176 int idx_safi = 0;
4177 afi_t afi = 0;
4178 safi_t safi = 0;
4179
4180 if (!bgp_vrf)
4181 return CMD_WARNING;
4182
4183 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
4184 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
4185
4186 if (!(afi == AFI_IP || afi == AFI_IP6)) {
4187 vty_out(vty,
4188 "%% Only ipv4 or ipv6 address families are supported\n");
4189 return CMD_WARNING;
4190 }
4191
4192 if (safi != SAFI_UNICAST) {
4193 vty_out(vty,
4194 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4195 return CMD_WARNING;
4196 }
4197
4198 if (afi == AFI_IP) {
4199
4200 /* if we are not advertising ipv4 prefix as type-5
4201 * nothing to do
4202 */
4203 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4204 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) ||
4205 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP))) {
4207 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4208 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4209 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST);
4210 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4211 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP);
4212 }
4213 } else {
4214
4215 /* if we are not advertising ipv6 prefix as type-5
4216 * nothing to do
4217 */
4218 if ((CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4219 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) ||
4220 (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4221 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP))){
4222 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
4223 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4224 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST);
4225 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
4226 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP);
4227 }
4228 }
4229
4230 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4231 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
4232 XFREE(MTYPE_ROUTE_MAP_NAME,
4233 bgp_vrf->adv_cmd_rmap[afi][safi].name);
4234 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
4235 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
4236 }
4237
4238 return CMD_SUCCESS;
4239 }
4240
4241 DEFPY (bgp_evpn_use_es_l3nhg,
4242 bgp_evpn_use_es_l3nhg_cmd,
4243 "[no$no] use-es-l3nhg",
4244 NO_STR
4245 "use L3 nexthop group for host routes with ES destination\n")
4246 {
4247 bgp_mh_info->host_routes_use_l3nhg = no ? false :true;
4248 return CMD_SUCCESS;
4249 }
4250
4251 DEFPY (bgp_evpn_ead_evi_rx_disable,
4252 bgp_evpn_ead_evi_rx_disable_cmd,
4253 "[no$no] disable-ead-evi-rx",
4254 NO_STR
4255 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4256 {
4257 bool ead_evi_rx = no? true :false;
4258
4259 if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
4260 bgp_mh_info->ead_evi_rx = ead_evi_rx;
4261 bgp_evpn_switch_ead_evi_rx();
4262 }
4263 return CMD_SUCCESS;
4264 }
4265
4266 DEFPY (bgp_evpn_ead_evi_tx_disable,
4267 bgp_evpn_ead_evi_tx_disable_cmd,
4268 "[no$no] disable-ead-evi-tx",
4269 NO_STR
4270 "Don't advertise EAD-EVI for local ESs\n")
4271 {
4272 bgp_mh_info->ead_evi_tx = no? true :false;
4273 return CMD_SUCCESS;
4274 }
4275
4276 DEFPY (bgp_evpn_enable_resolve_overlay_index,
4277 bgp_evpn_enable_resolve_overlay_index_cmd,
4278 "[no$no] enable-resolve-overlay-index",
4279 NO_STR
4280 "Enable Recursive Resolution of type-5 route overlay index\n")
4281 {
4282 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4283
4284 if (bgp != bgp_get_evpn()) {
4285 vty_out(vty, "This command is only supported under EVPN VRF\n");
4286 return CMD_WARNING;
4287 }
4288
4289 bgp_evpn_set_unset_resolve_overlay_index(bgp, no ? false : true);
4290 return CMD_SUCCESS;
4291 }
4292
4293 DEFPY (bgp_evpn_advertise_pip_ip_mac,
4294 bgp_evpn_advertise_pip_ip_mac_cmd,
4295 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4296 NO_STR
4297 "evpn system primary IP\n"
4298 IP_STR
4299 "ip address\n"
4300 MAC_STR MAC_STR MAC_STR)
4301 {
4302 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
4303 struct bgp *bgp_evpn = NULL;
4304
4305 if (EVPN_ENABLED(bgp_vrf)) {
4306 vty_out(vty,
4307 "This command is supported under L3VNI BGP EVPN VRF\n");
4308 return CMD_WARNING_CONFIG_FAILED;
4309 }
4310 bgp_evpn = bgp_get_evpn();
4311
4312 if (!no) {
4313 /* pip is already enabled */
4314 if (argc == 1 && bgp_vrf->evpn_info->advertise_pip)
4315 return CMD_SUCCESS;
4316
4317 bgp_vrf->evpn_info->advertise_pip = true;
4318 if (ip.s_addr != INADDR_ANY) {
4319 /* Already configured with same IP */
4320 if (IPV4_ADDR_SAME(&ip,
4321 &bgp_vrf->evpn_info->pip_ip_static))
4322 return CMD_SUCCESS;
4323
4324 bgp_vrf->evpn_info->pip_ip_static = ip;
4325 bgp_vrf->evpn_info->pip_ip = ip;
4326 } else {
4327 bgp_vrf->evpn_info->pip_ip_static.s_addr
4328 = INADDR_ANY;
4329 /* default instance router-id assignemt */
4330 if (bgp_evpn)
4331 bgp_vrf->evpn_info->pip_ip =
4332 bgp_evpn->router_id;
4333 }
4334 /* parse sys mac */
4335 if (!is_zero_mac(&mac->eth_addr)) {
4336 /* Already configured with same MAC */
4337 if (memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4338 &mac->eth_addr, ETH_ALEN) == 0)
4339 return CMD_SUCCESS;
4340
4341 memcpy(&bgp_vrf->evpn_info->pip_rmac_static,
4342 &mac->eth_addr, ETH_ALEN);
4343 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4344 &bgp_vrf->evpn_info->pip_rmac_static,
4345 ETH_ALEN);
4346 } else {
4347 /* Copy zebra sys mac */
4348 if (!is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_zebra))
4349 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4350 &bgp_vrf->evpn_info->pip_rmac_zebra,
4351 ETH_ALEN);
4352 }
4353 } else {
4354 if (argc == 2) {
4355 if (!bgp_vrf->evpn_info->advertise_pip)
4356 return CMD_SUCCESS;
4357 /* Disable PIP feature */
4358 bgp_vrf->evpn_info->advertise_pip = false;
4359 /* copy anycast mac */
4360 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4361 &bgp_vrf->rmac, ETH_ALEN);
4362 } else {
4363 /* remove MAC-IP option retain PIP knob. */
4364 if ((ip.s_addr != INADDR_ANY) &&
4365 !IPV4_ADDR_SAME(&ip,
4366 &bgp_vrf->evpn_info->pip_ip_static)) {
4367 vty_out(vty,
4368 "%% BGP EVPN PIP IP does not match\n");
4369 return CMD_WARNING_CONFIG_FAILED;
4370 }
4371
4372 if (!is_zero_mac(&mac->eth_addr) &&
4373 memcmp(&bgp_vrf->evpn_info->pip_rmac_static,
4374 &mac->eth_addr, ETH_ALEN) != 0) {
4375 vty_out(vty,
4376 "%% BGP EVPN PIP MAC does not match\n");
4377 return CMD_WARNING_CONFIG_FAILED;
4378 }
4379 /* pip_rmac can carry vrr_rmac reset only if it matches
4380 * with static value.
4381 */
4382 if (memcmp(&bgp_vrf->evpn_info->pip_rmac,
4383 &bgp_vrf->evpn_info->pip_rmac_static,
4384 ETH_ALEN) == 0) {
4385 /* Copy zebra sys mac */
4386 if (!is_zero_mac(
4387 &bgp_vrf->evpn_info->pip_rmac_zebra))
4388 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4389 &bgp_vrf->evpn_info->pip_rmac_zebra,
4390 ETH_ALEN);
4391 else {
4392 /* copy anycast mac */
4393 memcpy(&bgp_vrf->evpn_info->pip_rmac,
4394 &bgp_vrf->rmac, ETH_ALEN);
4395 }
4396 }
4397 }
4398 /* reset user configured sys MAC */
4399 memset(&bgp_vrf->evpn_info->pip_rmac_static, 0, ETH_ALEN);
4400 /* reset user configured sys IP */
4401 bgp_vrf->evpn_info->pip_ip_static.s_addr = INADDR_ANY;
4402 /* Assign default PIP IP (bgp instance router-id) */
4403 if (bgp_evpn)
4404 bgp_vrf->evpn_info->pip_ip = bgp_evpn->router_id;
4405 else
4406 bgp_vrf->evpn_info->pip_ip.s_addr = INADDR_ANY;
4407 }
4408
4409 if (is_evpn_enabled()) {
4410 struct listnode *node = NULL;
4411 struct bgpevpn *vpn = NULL;
4412
4413 /*
4414 * At this point if bgp_evpn is NULL and evpn is enabled
4415 * something stupid has gone wrong
4416 */
4417 assert(bgp_evpn);
4418
4419 update_advertise_vrf_routes(bgp_vrf);
4420
4421 /* Update (svi) type-2 routes */
4422 for (ALL_LIST_ELEMENTS_RO(bgp_vrf->l2vnis, node, vpn)) {
4423 if (!bgp_evpn_is_svi_macip_enabled(vpn))
4424 continue;
4425 update_routes_for_vni(bgp_evpn, vpn);
4426 }
4427 }
4428
4429 return CMD_SUCCESS;
4430 }
4431
4432 /*
4433 * Display VNI information - for all or a specific VNI
4434 */
4435 DEFUN(show_bgp_l2vpn_evpn_vni,
4436 show_bgp_l2vpn_evpn_vni_cmd,
4437 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
4438 SHOW_STR
4439 BGP_STR
4440 L2VPN_HELP_STR
4441 EVPN_HELP_STR
4442 "Show VNI\n"
4443 "VNI number\n"
4444 JSON_STR)
4445 {
4446 struct bgp *bgp_evpn;
4447 vni_t vni;
4448 int idx = 0;
4449 bool uj = false;
4450 json_object *json = NULL;
4451 uint32_t num_l2vnis = 0;
4452 uint32_t num_l3vnis = 0;
4453 uint32_t num_vnis = 0;
4454 struct listnode *node = NULL;
4455 struct bgp *bgp_temp = NULL;
4456
4457 uj = use_json(argc, argv);
4458
4459 bgp_evpn = bgp_get_evpn();
4460 if (!bgp_evpn)
4461 return CMD_WARNING;
4462
4463 if (!argv_find(argv, argc, "evpn", &idx))
4464 return CMD_WARNING;
4465
4466 if (uj)
4467 json = json_object_new_object();
4468
4469 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
4470
4471 num_l2vnis = hashcount(bgp_evpn->vnihash);
4472
4473 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
4474 if (bgp_temp->l3vni)
4475 num_l3vnis++;
4476 }
4477 num_vnis = num_l2vnis + num_l3vnis;
4478 if (uj) {
4479 json_object_string_add(json, "advertiseGatewayMacip",
4480 bgp_evpn->advertise_gw_macip
4481 ? "Enabled"
4482 : "Disabled");
4483 json_object_string_add(json, "advertiseSviMacIp",
4484 bgp_evpn->evpn_info->advertise_svi_macip
4485 ? "Enabled" : "Disabled");
4486 json_object_string_add(json, "advertiseAllVnis",
4487 is_evpn_enabled() ? "Enabled"
4488 : "Disabled");
4489 json_object_string_add(
4490 json, "flooding",
4491 bgp_evpn->vxlan_flood_ctrl ==
4492 VXLAN_FLOOD_HEAD_END_REPL
4493 ? "Head-end replication"
4494 : "Disabled");
4495 json_object_string_add(
4496 json, "vxlanFlooding",
4497 bgp_evpn->vxlan_flood_ctrl ==
4498 VXLAN_FLOOD_HEAD_END_REPL
4499 ? "Enabled"
4500 : "Disabled");
4501 json_object_int_add(json, "numVnis", num_vnis);
4502 json_object_int_add(json, "numL2Vnis", num_l2vnis);
4503 json_object_int_add(json, "numL3Vnis", num_l3vnis);
4504 } else {
4505 vty_out(vty, "Advertise Gateway Macip: %s\n",
4506 bgp_evpn->advertise_gw_macip ? "Enabled"
4507 : "Disabled");
4508 vty_out(vty, "Advertise SVI Macip: %s\n",
4509 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
4510 : "Disabled");
4511 vty_out(vty, "Advertise All VNI flag: %s\n",
4512 is_evpn_enabled() ? "Enabled" : "Disabled");
4513 vty_out(vty, "BUM flooding: %s\n",
4514 bgp_evpn->vxlan_flood_ctrl ==
4515 VXLAN_FLOOD_HEAD_END_REPL
4516 ? "Head-end replication"
4517 : "Disabled");
4518 vty_out(vty, "VXLAN flooding: %s\n",
4519 bgp_evpn->vxlan_flood_ctrl ==
4520 VXLAN_FLOOD_HEAD_END_REPL
4521 ? "Enabled"
4522 : "Disabled");
4523 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
4524 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
4525 }
4526 evpn_show_all_vnis(vty, bgp_evpn, json);
4527 } else {
4528 int vni_idx = 0;
4529
4530 if (!argv_find(argv, argc, "vni", &vni_idx))
4531 return CMD_WARNING;
4532
4533 /* Display specific VNI */
4534 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
4535 evpn_show_vni(vty, bgp_evpn, vni, json);
4536 }
4537
4538 if (uj)
4539 vty_json(vty, json);
4540
4541 return CMD_SUCCESS;
4542 }
4543
4544 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash,
4545 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd,
4546 "show bgp l2vpn evpn vni remote-ip-hash",
4547 SHOW_STR
4548 BGP_STR
4549 L2VPN_HELP_STR
4550 EVPN_HELP_STR
4551 "Show VNI\n"
4552 "Remote IP hash\n")
4553 {
4554 struct bgp *bgp_evpn;
4555 int idx = 0;
4556
4557 bgp_evpn = bgp_get_evpn();
4558 if (!bgp_evpn)
4559 return CMD_WARNING;
4560
4561 if (!argv_find(argv, argc, "evpn", &idx))
4562 return CMD_WARNING;
4563
4564 hash_iterate(bgp_evpn->vnihash,
4565 (void (*)(struct hash_bucket *,
4566 void *))bgp_evpn_show_remote_ip_hash,
4567 vty);
4568
4569 return CMD_SUCCESS;
4570 }
4571
4572 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash,
4573 show_bgp_l2vpn_evpn_vni_svi_hash_cmd,
4574 "show bgp l2vpn evpn vni-svi-hash",
4575 SHOW_STR
4576 BGP_STR
4577 L2VPN_HELP_STR
4578 EVPN_HELP_STR
4579 "Show vni-svi-hash\n")
4580 {
4581 struct bgp *bgp_evpn;
4582 int idx = 0;
4583
4584 bgp_evpn = bgp_get_evpn();
4585 if (!bgp_evpn)
4586 return CMD_WARNING;
4587
4588 if (!argv_find(argv, argc, "evpn", &idx))
4589 return CMD_WARNING;
4590
4591 hash_iterate(bgp_evpn->vni_svi_hash,
4592 (void (*)(struct hash_bucket *,
4593 void *))bgp_evpn_show_vni_svi_hash,
4594 vty);
4595
4596 return CMD_SUCCESS;
4597 }
4598
4599 DEFPY(show_bgp_l2vpn_evpn_es_evi,
4600 show_bgp_l2vpn_evpn_es_evi_cmd,
4601 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4602 SHOW_STR
4603 BGP_STR
4604 L2VPN_HELP_STR
4605 EVPN_HELP_STR
4606 "ES per EVI\n"
4607 "VxLAN Network Identifier\n"
4608 "VNI\n"
4609 JSON_STR
4610 "Detailed information\n")
4611 {
4612 if (vni)
4613 bgp_evpn_es_evi_show_vni(vty, vni, !!uj, !!detail);
4614 else
4615 bgp_evpn_es_evi_show(vty, !!uj, !!detail);
4616
4617 return CMD_SUCCESS;
4618 }
4619
4620 DEFPY(show_bgp_l2vpn_evpn_es,
4621 show_bgp_l2vpn_evpn_es_cmd,
4622 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4623 SHOW_STR
4624 BGP_STR
4625 L2VPN_HELP_STR
4626 EVPN_HELP_STR
4627 "Ethernet Segment\n"
4628 "ES ID\n"
4629 "Detailed information\n"
4630 JSON_STR)
4631 {
4632 esi_t esi;
4633
4634 if (esi_str) {
4635 if (!str_to_esi(esi_str, &esi)) {
4636 vty_out(vty, "%% Malformed ESI\n");
4637 return CMD_WARNING;
4638 }
4639 bgp_evpn_es_show_esi(vty, &esi, uj);
4640 } else {
4641
4642 bgp_evpn_es_show(vty, uj, !!detail);
4643 }
4644
4645 return CMD_SUCCESS;
4646 }
4647
4648 DEFPY(show_bgp_l2vpn_evpn_es_vrf, show_bgp_l2vpn_evpn_es_vrf_cmd,
4649 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4650 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4651 "Ethernet Segment\n"
4652 "ES ID\n" JSON_STR)
4653 {
4654 esi_t esi;
4655
4656 if (esi_str) {
4657 if (!str_to_esi(esi_str, &esi)) {
4658 vty_out(vty, "%% Malformed ESI\n");
4659 return CMD_WARNING;
4660 }
4661 bgp_evpn_es_vrf_show_esi(vty, &esi, uj);
4662 } else {
4663
4664 bgp_evpn_es_vrf_show(vty, uj, NULL);
4665 }
4666
4667 return CMD_SUCCESS;
4668 }
4669
4670 DEFPY(show_bgp_l2vpn_evpn_nh,
4671 show_bgp_l2vpn_evpn_nh_cmd,
4672 "show bgp l2vpn evpn next-hops [json$uj]",
4673 SHOW_STR
4674 BGP_STR
4675 L2VPN_HELP_STR
4676 EVPN_HELP_STR
4677 "Nexthops\n"
4678 JSON_STR)
4679 {
4680 bgp_evpn_nh_show(vty, uj);
4681
4682 return CMD_SUCCESS;
4683 }
4684
4685 /*
4686 * Display EVPN neighbor summary.
4687 */
4688 DEFUN(show_bgp_l2vpn_evpn_summary, show_bgp_l2vpn_evpn_summary_cmd,
4689 "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]",
4690 SHOW_STR BGP_STR
4691 "bgp vrf\n"
4692 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4693 "Summary of BGP neighbor status\n"
4694 "Show only sessions in Established state\n"
4695 "Show only sessions not in Established state\n"
4696 "Show only the specified neighbor session\n"
4697 "Neighbor to display information about\n"
4698 "Neighbor to display information about\n"
4699 "Neighbor on BGP configured interface\n"
4700 "Show only the specified remote AS sessions\n"
4701 "AS number\n"
4702 "Internal (iBGP) AS sessions\n"
4703 "External (eBGP) AS sessions\n"
4704 "Shorten the information on BGP instances\n"
4705 "Increase table width for longer output\n" JSON_STR)
4706 {
4707 int idx_vrf = 0;
4708 int idx = 0;
4709 char *vrf = NULL;
4710 char *neighbor = NULL;
4711 as_t as = 0; /* 0 means AS filter not set */
4712 int as_type = AS_UNSPECIFIED;
4713 uint16_t show_flags = 0;
4714
4715 if (argv_find(argv, argc, "vrf", &idx_vrf))
4716 vrf = argv[++idx_vrf]->arg;
4717
4718 if (argv_find(argv, argc, "failed", &idx))
4719 SET_FLAG(show_flags, BGP_SHOW_OPT_FAILED);
4720
4721 if (argv_find(argv, argc, "established", &idx))
4722 SET_FLAG(show_flags, BGP_SHOW_OPT_ESTABLISHED);
4723
4724
4725 if (argv_find(argv, argc, "neighbor", &idx))
4726 neighbor = argv[idx + 1]->arg;
4727
4728 if (argv_find(argv, argc, "remote-as", &idx)) {
4729 if (argv[idx + 1]->arg[0] == 'i')
4730 as_type = AS_INTERNAL;
4731 else if (argv[idx + 1]->arg[0] == 'e')
4732 as_type = AS_EXTERNAL;
4733 else
4734 as = (as_t)atoi(argv[idx + 1]->arg);
4735 }
4736
4737 if (argv_find(argv, argc, "terse", &idx))
4738 SET_FLAG(show_flags, BGP_SHOW_OPT_TERSE);
4739
4740 if (argv_find(argv, argc, "wide", &idx))
4741 SET_FLAG(show_flags, BGP_SHOW_OPT_WIDE);
4742
4743 if (use_json(argc, argv))
4744 SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
4745
4746 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN, neighbor,
4747 as_type, as, show_flags);
4748 }
4749
4750 static int bgp_evpn_cli_parse_type_cmp(int *type, const char *type_str)
4751 {
4752 if ((strncmp(type_str, "ma", 2) == 0) || (strmatch(type_str, "2")))
4753 *type = BGP_EVPN_MAC_IP_ROUTE;
4754 else if ((strncmp(type_str, "mu", 2) == 0) || (strmatch(type_str, "3")))
4755 *type = BGP_EVPN_IMET_ROUTE;
4756 else if ((strncmp(type_str, "es", 2) == 0) || (strmatch(type_str, "4")))
4757 *type = BGP_EVPN_ES_ROUTE;
4758 else if ((strncmp(type_str, "ea", 2) == 0) || (strmatch(type_str, "1")))
4759 *type = BGP_EVPN_AD_ROUTE;
4760 else if ((strncmp(type_str, "p", 1) == 0) || (strmatch(type_str, "5")))
4761 *type = BGP_EVPN_IP_PREFIX_ROUTE;
4762 else
4763 return -1;
4764
4765 return 0;
4766 }
4767
4768 int bgp_evpn_cli_parse_type(int *type, struct cmd_token **argv, int argc)
4769 {
4770 int type_idx = 0;
4771
4772 if (argv_find(argv, argc, "type", &type_idx)) {
4773 /* Specific type is requested */
4774 if (bgp_evpn_cli_parse_type_cmp(type,
4775 argv[type_idx + 1]->arg) != 0)
4776 return -1;
4777 }
4778
4779 return 0;
4780 }
4781
4782 /*
4783 * Display global EVPN routing table.
4784 */
4785 DEFUN(show_bgp_l2vpn_evpn_route,
4786 show_bgp_l2vpn_evpn_route_cmd,
4787 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST"] [json]",
4788 SHOW_STR
4789 BGP_STR
4790 L2VPN_HELP_STR
4791 EVPN_HELP_STR
4792 EVPN_RT_HELP_STR
4793 "Display Detailed Information\n"
4794 EVPN_TYPE_HELP_STR
4795 EVPN_TYPE_ALL_LIST_HELP_STR
4796 JSON_STR)
4797 {
4798 struct bgp *bgp;
4799 int detail = 0;
4800 int type = 0;
4801 bool uj = false;
4802 json_object *json = NULL;
4803
4804 uj = use_json(argc, argv);
4805
4806 bgp = bgp_get_evpn();
4807 if (!bgp)
4808 return CMD_WARNING;
4809
4810 if (uj)
4811 json = json_object_new_object();
4812
4813 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4814 return CMD_WARNING;
4815
4816 if (argv_find(argv, argc, "detail", &detail))
4817 detail = 1;
4818
4819 evpn_show_all_routes(vty, bgp, type, json, detail);
4820
4821 /*
4822 * This is an extremely expensive operation at scale
4823 * and as such we need to save as much time as is
4824 * possible.
4825 */
4826 if (uj)
4827 vty_json_no_pretty(vty, json);
4828
4829 return CMD_SUCCESS;
4830 }
4831
4832 /*
4833 * Display global EVPN routing table for specific RD.
4834 */
4835 DEFUN(show_bgp_l2vpn_evpn_route_rd,
4836 show_bgp_l2vpn_evpn_route_rd_cmd,
4837 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST"] [json]",
4838 SHOW_STR
4839 BGP_STR
4840 L2VPN_HELP_STR
4841 EVPN_HELP_STR
4842 EVPN_RT_HELP_STR
4843 EVPN_RT_DIST_HELP_STR
4844 EVPN_ASN_IP_HELP_STR
4845 "All VPN Route Distinguishers\n"
4846 EVPN_TYPE_HELP_STR
4847 EVPN_TYPE_ALL_LIST_HELP_STR
4848 JSON_STR)
4849 {
4850 struct bgp *bgp;
4851 int ret = 0;
4852 struct prefix_rd prd;
4853 int type = 0;
4854 bool uj = false;
4855 json_object *json = NULL;
4856 int idx_ext_community = 0;
4857 int rd_all = 0;
4858
4859 bgp = bgp_get_evpn();
4860 if (!bgp)
4861 return CMD_WARNING;
4862
4863 /* check if we need json output */
4864 uj = use_json(argc, argv);
4865 if (uj)
4866 json = json_object_new_object();
4867
4868 if (!argv_find(argv, argc, "all", &rd_all)) {
4869 /* get the RD */
4870 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4871 &idx_ext_community)) {
4872 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4873 if (!ret) {
4874 vty_out(vty,
4875 "%% Malformed Route Distinguisher\n");
4876 return CMD_WARNING;
4877 }
4878 }
4879 }
4880
4881 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
4882 return CMD_WARNING;
4883
4884 if (rd_all)
4885 evpn_show_all_routes(vty, bgp, type, json, 1);
4886 else
4887 evpn_show_route_rd(vty, bgp, &prd, type, json);
4888
4889 if (uj)
4890 vty_json(vty, json);
4891
4892 return CMD_SUCCESS;
4893 }
4894
4895 /*
4896 * Display global EVPN routing table for specific RD and MACIP.
4897 */
4898 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4899 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
4900 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4901 SHOW_STR
4902 BGP_STR
4903 L2VPN_HELP_STR
4904 EVPN_HELP_STR
4905 EVPN_RT_HELP_STR
4906 EVPN_RT_DIST_HELP_STR
4907 EVPN_ASN_IP_HELP_STR
4908 "All VPN Route Distinguishers\n"
4909 "MAC\n"
4910 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4911 "IP\n"
4912 "IP address (IPv4 or IPv6)\n"
4913 JSON_STR)
4914 {
4915 struct bgp *bgp;
4916 int ret = 0;
4917 struct prefix_rd prd;
4918 struct ethaddr mac;
4919 struct ipaddr ip;
4920 int idx_ext_community = 0;
4921 int mac_idx = 0;
4922 int ip_idx = 0;
4923 bool uj = false;
4924 json_object *json = NULL;
4925 int rd_all = 0;
4926
4927 memset(&mac, 0, sizeof(struct ethaddr));
4928 memset(&ip, 0, sizeof(struct ipaddr));
4929
4930 bgp = bgp_get_evpn();
4931 if (!bgp)
4932 return CMD_WARNING;
4933
4934 /* check if we need json output */
4935 uj = use_json(argc, argv);
4936 if (uj)
4937 json = json_object_new_object();
4938
4939 /* get the prd */
4940 if (!argv_find(argv, argc, "all", &rd_all)) {
4941 if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
4942 &idx_ext_community)) {
4943 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
4944 if (!ret) {
4945 vty_out(vty,
4946 "%% Malformed Route Distinguisher\n");
4947 return CMD_WARNING;
4948 }
4949 }
4950 }
4951
4952 /* get the mac */
4953 if (argv_find(argv, argc, "mac", &mac_idx)) {
4954 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4955 vty_out(vty, "%% Malformed MAC address\n");
4956 return CMD_WARNING;
4957 }
4958 }
4959
4960 /* get the ip if specified */
4961 if (argv_find(argv, argc, "ip", &ip_idx)) {
4962 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4963 vty_out(vty, "%% Malformed IP address\n");
4964 return CMD_WARNING;
4965 }
4966 }
4967
4968 if (rd_all)
4969 evpn_show_route_rd_all_macip(vty, bgp, &mac, &ip, json);
4970 else
4971 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4972
4973 if (uj)
4974 vty_json(vty, json);
4975
4976 return CMD_SUCCESS;
4977 }
4978
4979 /* Display per ESI routing table */
4980 DEFUN(show_bgp_l2vpn_evpn_route_esi,
4981 show_bgp_l2vpn_evpn_route_esi_cmd,
4982 "show bgp l2vpn evpn route esi ESI [json]",
4983 SHOW_STR
4984 BGP_STR
4985 L2VPN_HELP_STR
4986 EVPN_HELP_STR
4987 EVPN_RT_HELP_STR
4988 "Ethernet Segment Identifier\n"
4989 "ESI ID\n"
4990 JSON_STR)
4991 {
4992 bool uj = false;
4993 esi_t esi;
4994 struct bgp *bgp = NULL;
4995 json_object *json = NULL;
4996
4997 memset(&esi, 0, sizeof(esi));
4998 bgp = bgp_get_evpn();
4999 if (!bgp)
5000 return CMD_WARNING;
5001
5002 uj = use_json(argc, argv);
5003 if (uj)
5004 json = json_object_new_object();
5005
5006 /* get the ESI - ESI-ID is at argv[6] */
5007 if (!str_to_esi(argv[6]->arg, &esi)) {
5008 vty_out(vty, "%% Malformed ESI\n");
5009 return CMD_WARNING;
5010 }
5011
5012 evpn_show_routes_esi(vty, bgp, &esi, json);
5013
5014 if (uj)
5015 vty_json(vty, json);
5016
5017 return CMD_SUCCESS;
5018 }
5019
5020
5021 /*
5022 * Display per-VNI EVPN routing table.
5023 */
5024 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
5025 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5026 SHOW_STR
5027 BGP_STR
5028 L2VPN_HELP_STR
5029 EVPN_HELP_STR
5030 EVPN_RT_HELP_STR
5031 "VXLAN Network Identifier\n"
5032 "VNI number\n"
5033 EVPN_TYPE_HELP_STR
5034 EVPN_TYPE_1_HELP_STR
5035 EVPN_TYPE_1_HELP_STR
5036 EVPN_TYPE_2_HELP_STR
5037 EVPN_TYPE_2_HELP_STR
5038 EVPN_TYPE_3_HELP_STR
5039 EVPN_TYPE_3_HELP_STR
5040 "Remote VTEP\n"
5041 "Remote VTEP IP address\n"
5042 JSON_STR)
5043 {
5044 vni_t vni;
5045 struct bgp *bgp;
5046 struct in_addr vtep_ip;
5047 int type = 0;
5048 int idx = 0;
5049 int vtep_idx = 0;
5050 bool uj = false;
5051 json_object *json = NULL;
5052
5053 bgp = bgp_get_evpn();
5054 if (!bgp)
5055 return CMD_WARNING;
5056
5057 /* check if we need json output */
5058 uj = use_json(argc, argv);
5059 if (uj)
5060 json = json_object_new_object();
5061
5062 if (!argv_find(argv, argc, "evpn", &idx))
5063 return CMD_WARNING;
5064
5065 vtep_ip.s_addr = 0;
5066
5067 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5068
5069 if (bgp_evpn_cli_parse_type(&type, argv, argc) < 0)
5070 return CMD_WARNING;
5071
5072 if (argv_find(argv, argc, "vtep", &vtep_idx)) {
5073 if (!inet_aton(argv[vtep_idx + 1]->arg, &vtep_ip)) {
5074 vty_out(vty, "%% Malformed VTEP IP address\n");
5075 return CMD_WARNING;
5076 }
5077 }
5078
5079 evpn_show_routes_vni(vty, bgp, vni, type, false, vtep_ip, json);
5080
5081 if (uj)
5082 vty_json(vty, json);
5083
5084 return CMD_SUCCESS;
5085 }
5086
5087 /*
5088 * Display per-VNI EVPN routing table for specific MACIP.
5089 */
5090 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
5091 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
5092 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
5093 SHOW_STR
5094 BGP_STR
5095 L2VPN_HELP_STR
5096 EVPN_HELP_STR
5097 EVPN_RT_HELP_STR
5098 "VXLAN Network Identifier\n"
5099 "VNI number\n"
5100 "MAC\n"
5101 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5102 "IP\n"
5103 "IP address (IPv4 or IPv6)\n"
5104 JSON_STR)
5105 {
5106 vni_t vni;
5107 struct bgp *bgp;
5108 struct ethaddr mac;
5109 struct ipaddr ip;
5110 int idx = 0;
5111 bool uj = false;
5112 json_object *json = NULL;
5113
5114 bgp = bgp_get_evpn();
5115 if (!bgp)
5116 return CMD_WARNING;
5117
5118 /* check if we need json output */
5119 uj = use_json(argc, argv);
5120 if (uj)
5121 json = json_object_new_object();
5122
5123 if (!argv_find(argv, argc, "evpn", &idx))
5124 return CMD_WARNING;
5125
5126 /* get the VNI */
5127 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5128
5129 /* get the mac */
5130 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
5131 vty_out(vty, "%% Malformed MAC address\n");
5132 return CMD_WARNING;
5133 }
5134
5135 /* get the ip */
5136 memset(&ip, 0, sizeof(ip));
5137 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
5138 || (uj
5139 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
5140 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
5141 vty_out(vty, "%% Malformed IP address\n");
5142 return CMD_WARNING;
5143 }
5144 }
5145
5146 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
5147
5148 if (uj)
5149 vty_json(vty, json);
5150
5151 return CMD_SUCCESS;
5152 }
5153
5154 /*
5155 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5156 */
5157 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
5158 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
5159 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
5160 SHOW_STR
5161 BGP_STR
5162 L2VPN_HELP_STR
5163 EVPN_HELP_STR
5164 EVPN_RT_HELP_STR
5165 "VXLAN Network Identifier\n"
5166 "VNI number\n"
5167 EVPN_TYPE_3_HELP_STR
5168 "Originating Router IP address\n"
5169 JSON_STR)
5170 {
5171 vni_t vni;
5172 struct bgp *bgp;
5173 int ret;
5174 struct in_addr orig_ip;
5175 int idx = 0;
5176 bool uj = false;
5177 json_object *json = NULL;
5178
5179 bgp = bgp_get_evpn();
5180 if (!bgp)
5181 return CMD_WARNING;
5182
5183 /* check if we need json output */
5184 uj = use_json(argc, argv);
5185 if (uj)
5186 json = json_object_new_object();
5187
5188 if (!argv_find(argv, argc, "evpn", &idx))
5189 return CMD_WARNING;
5190
5191 /* get the VNI */
5192 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
5193
5194 /* get the ip */
5195 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
5196 if (!ret) {
5197 vty_out(vty, "%% Malformed Originating Router IP address\n");
5198 return CMD_WARNING;
5199 }
5200
5201 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
5202
5203 if (uj)
5204 vty_json(vty, json);
5205
5206 return CMD_SUCCESS;
5207 }
5208
5209 /*
5210 * Display per-VNI EVPN routing table - for all VNIs.
5211 */
5212 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
5213 show_bgp_l2vpn_evpn_route_vni_all_cmd,
5214 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5215 SHOW_STR
5216 BGP_STR
5217 L2VPN_HELP_STR
5218 EVPN_HELP_STR
5219 EVPN_RT_HELP_STR
5220 "VXLAN Network Identifier\n"
5221 "All VNIs\n"
5222 "Print Detailed Output\n"
5223 "Remote VTEP\n"
5224 "Remote VTEP IP address\n"
5225 JSON_STR)
5226 {
5227 struct bgp *bgp;
5228 struct in_addr vtep_ip;
5229 int idx = 0;
5230 bool uj = false;
5231 json_object *json = NULL;
5232 /* Detail Adjust. Adjust indexes according to detail option */
5233 int da = 0;
5234
5235 bgp = bgp_get_evpn();
5236 if (!bgp)
5237 return CMD_WARNING;
5238
5239 /* check if we need json output */
5240 uj = use_json(argc, argv);
5241 if (uj)
5242 json = json_object_new_object();
5243
5244 if (!argv_find(argv, argc, "evpn", &idx))
5245 return CMD_WARNING;
5246
5247 if (argv_find(argv, argc, "detail", &da))
5248 da = 1;
5249
5250 /* vtep-ip position depends on detail option */
5251 vtep_ip.s_addr = 0;
5252 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
5253 || (uj
5254 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
5255 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
5256 vty_out(vty, "%% Malformed VTEP IP address\n");
5257 return CMD_WARNING;
5258 }
5259 }
5260
5261 evpn_show_routes_vni_all(vty, bgp, 0, false, vtep_ip, json, da);
5262
5263 if (uj) {
5264 vty_json(vty, json);
5265 json_object_free(json);
5266 }
5267
5268 return CMD_SUCCESS;
5269 }
5270
5271 /*
5272 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5273 */
5274 DEFPY(show_bgp_vni_all,
5275 show_bgp_vni_all_cmd,
5276 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5277 SHOW_STR
5278 BGP_STR
5279 VNI_HELP_STR
5280 VNI_ALL_HELP_STR
5281 VTEP_HELP_STR
5282 VTEP_IP_HELP_STR
5283 DETAIL_HELP_STR
5284 JSON_STR)
5285 {
5286 struct bgp *bgp;
5287 json_object *json = NULL;
5288
5289 bgp = bgp_get_evpn();
5290 if (!bgp)
5291 return CMD_WARNING;
5292
5293 /* check if we need json output */
5294 if (uj)
5295 json = json_object_new_object();
5296
5297 evpn_show_routes_vni_all_type_all(vty, bgp, addr, json, !!detail);
5298
5299 if (uj)
5300 vty_json(vty, json);
5301
5302 return CMD_SUCCESS;
5303 }
5304
5305 /*
5306 * Display per-VNI EVPN EAD routing table - for all VNIs.
5307 */
5308 DEFPY(show_bgp_vni_all_ead,
5309 show_bgp_vni_all_ead_cmd,
5310 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5311 SHOW_STR
5312 BGP_STR
5313 VNI_HELP_STR
5314 VNI_ALL_HELP_STR
5315 EVPN_TYPE_HELP_STR
5316 EVPN_TYPE_1_HELP_STR
5317 EVPN_TYPE_1_HELP_STR
5318 VTEP_HELP_STR
5319 VTEP_IP_HELP_STR
5320 DETAIL_HELP_STR
5321 JSON_STR)
5322 {
5323 struct bgp *bgp;
5324 json_object *json = NULL;
5325
5326 bgp = bgp_get_evpn();
5327 if (!bgp)
5328 return CMD_WARNING;
5329
5330 /* check if we need json output */
5331 if (uj)
5332 json = json_object_new_object();
5333
5334 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_AD_ROUTE, false, addr, json,
5335 !!detail);
5336
5337 if (uj)
5338 vty_json(vty, json);
5339
5340 return CMD_SUCCESS;
5341 }
5342
5343 /*
5344 * Display per-VNI EVPN MAC routing table - for all VNIs.
5345 */
5346 DEFPY(show_bgp_vni_all_macip_mac,
5347 show_bgp_vni_all_macip_mac_cmd,
5348 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5349 SHOW_STR
5350 BGP_STR
5351 VNI_HELP_STR
5352 VNI_ALL_HELP_STR
5353 EVPN_TYPE_HELP_STR
5354 EVPN_TYPE_2_HELP_STR
5355 EVPN_TYPE_2_HELP_STR
5356 "MAC Table\n"
5357 VTEP_HELP_STR
5358 VTEP_IP_HELP_STR
5359 DETAIL_HELP_STR
5360 JSON_STR)
5361 {
5362 struct bgp *bgp;
5363 json_object *json = NULL;
5364
5365 bgp = bgp_get_evpn();
5366 if (!bgp)
5367 return CMD_WARNING;
5368
5369 /* check if we need json output */
5370 if (uj)
5371 json = json_object_new_object();
5372
5373 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5374 json, !!detail);
5375
5376 if (uj)
5377 vty_json(vty, json);
5378
5379 return CMD_SUCCESS;
5380 }
5381
5382 /*
5383 * Display per-VNI EVPN IP routing table - for all VNIs.
5384 */
5385 DEFPY(show_bgp_vni_all_macip_ip,
5386 show_bgp_vni_all_macip_ip_cmd,
5387 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5388 SHOW_STR
5389 BGP_STR
5390 VNI_HELP_STR
5391 VNI_ALL_HELP_STR
5392 EVPN_TYPE_HELP_STR
5393 EVPN_TYPE_2_HELP_STR
5394 EVPN_TYPE_2_HELP_STR
5395 "IP Table\n"
5396 VTEP_HELP_STR
5397 VTEP_IP_HELP_STR
5398 DETAIL_HELP_STR
5399 JSON_STR)
5400 {
5401 struct bgp *bgp;
5402 json_object *json = NULL;
5403
5404 bgp = bgp_get_evpn();
5405 if (!bgp)
5406 return CMD_WARNING;
5407
5408 /* check if we need json output */
5409 if (uj)
5410 json = json_object_new_object();
5411
5412 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5413 json, !!detail);
5414
5415 if (uj)
5416 vty_json(vty, json);
5417
5418 return CMD_SUCCESS;
5419 }
5420
5421 /*
5422 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5423 */
5424 DEFPY(show_bgp_vni_all_imet,
5425 show_bgp_vni_all_imet_cmd,
5426 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5427 SHOW_STR
5428 BGP_STR
5429 VNI_HELP_STR
5430 VNI_ALL_HELP_STR
5431 EVPN_TYPE_HELP_STR
5432 EVPN_TYPE_3_HELP_STR
5433 EVPN_TYPE_3_HELP_STR
5434 VTEP_HELP_STR
5435 VTEP_IP_HELP_STR
5436 DETAIL_HELP_STR
5437 JSON_STR)
5438 {
5439 struct bgp *bgp;
5440 json_object *json = NULL;
5441
5442 bgp = bgp_get_evpn();
5443 if (!bgp)
5444 return CMD_WARNING;
5445
5446 /* check if we need json output */
5447 if (uj)
5448 json = json_object_new_object();
5449
5450 evpn_show_routes_vni_all(vty, bgp, BGP_EVPN_IMET_ROUTE, false, addr,
5451 json, !!detail);
5452
5453 if (uj)
5454 vty_json(vty, json);
5455
5456 return CMD_SUCCESS;
5457 }
5458
5459 /*
5460 * Display per-VNI EVPN ALL routing tables - for select VNI
5461 */
5462 DEFPY(show_bgp_vni,
5463 show_bgp_vni_cmd,
5464 "show bgp vni "CMD_VNI_RANGE"$vni [vtep A.B.C.D$addr] [json$uj]",
5465 SHOW_STR
5466 BGP_STR
5467 VNI_HELP_STR
5468 VNI_NUM_HELP_STR
5469 VTEP_HELP_STR
5470 VTEP_IP_HELP_STR
5471 JSON_STR)
5472 {
5473 struct bgp *bgp;
5474 json_object *json = NULL;
5475 json_object *json_mac = NULL;
5476
5477 bgp = bgp_get_evpn();
5478 if (!bgp)
5479 return CMD_WARNING;
5480
5481 /* check if we need json output */
5482 if (uj) {
5483 json = json_object_new_object();
5484 json_mac = json_object_new_object();
5485 }
5486
5487 evpn_show_routes_vni(vty, bgp, vni, 0, false, addr, json);
5488
5489 if (!uj)
5490 vty_out(vty, "\n\nMAC Table:\n\n");
5491
5492 evpn_show_routes_vni(vty, bgp, vni, 0, true, addr, json_mac);
5493
5494 if (uj) {
5495 json_object_object_add(json, "macTable", json_mac);
5496 vty_json(vty, json);
5497 }
5498
5499 return CMD_SUCCESS;
5500 }
5501
5502 /*
5503 * Display per-VNI EVPN EAD routing table - for select VNI
5504 */
5505 DEFPY(show_bgp_vni_ead,
5506 show_bgp_vni_ead_cmd,
5507 "show bgp vni "CMD_VNI_RANGE"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5508 SHOW_STR
5509 BGP_STR
5510 VNI_HELP_STR
5511 VNI_NUM_HELP_STR
5512 EVPN_TYPE_HELP_STR
5513 EVPN_TYPE_1_HELP_STR
5514 EVPN_TYPE_1_HELP_STR
5515 VTEP_HELP_STR
5516 VTEP_IP_HELP_STR
5517 JSON_STR)
5518 {
5519 struct bgp *bgp;
5520 json_object *json = NULL;
5521
5522 bgp = bgp_get_evpn();
5523 if (!bgp)
5524 return CMD_WARNING;
5525
5526 /* check if we need json output */
5527 if (uj)
5528 json = json_object_new_object();
5529
5530 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_AD_ROUTE, false, addr,
5531 json);
5532
5533 if (uj)
5534 vty_json(vty, json);
5535
5536 return CMD_SUCCESS;
5537 }
5538
5539 /*
5540 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5541 */
5542 DEFPY(show_bgp_vni_macip_mac,
5543 show_bgp_vni_macip_mac_cmd,
5544 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5545 SHOW_STR
5546 BGP_STR
5547 VNI_HELP_STR
5548 VNI_NUM_HELP_STR
5549 EVPN_TYPE_HELP_STR
5550 EVPN_TYPE_2_HELP_STR
5551 EVPN_TYPE_2_HELP_STR
5552 "MAC Table\n"
5553 VTEP_HELP_STR
5554 VTEP_IP_HELP_STR
5555 JSON_STR)
5556 {
5557 struct bgp *bgp;
5558 json_object *json = NULL;
5559
5560 bgp = bgp_get_evpn();
5561 if (!bgp)
5562 return CMD_WARNING;
5563
5564 /* check if we need json output */
5565 if (uj)
5566 json = json_object_new_object();
5567
5568 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, true, addr,
5569 json);
5570
5571 if (uj)
5572 vty_json(vty, json);
5573
5574 return CMD_SUCCESS;
5575 }
5576
5577 /*
5578 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5579 */
5580 DEFPY(show_bgp_vni_macip_ip,
5581 show_bgp_vni_macip_ip_cmd,
5582 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5583 SHOW_STR
5584 BGP_STR
5585 VNI_HELP_STR
5586 VNI_NUM_HELP_STR
5587 EVPN_TYPE_HELP_STR
5588 EVPN_TYPE_2_HELP_STR
5589 EVPN_TYPE_2_HELP_STR
5590 "IP Table\n"
5591 VTEP_HELP_STR
5592 VTEP_IP_HELP_STR
5593 JSON_STR)
5594 {
5595 struct bgp *bgp;
5596 json_object *json = NULL;
5597
5598 bgp = bgp_get_evpn();
5599 if (!bgp)
5600 return CMD_WARNING;
5601
5602 /* check if we need json output */
5603 if (uj)
5604 json = json_object_new_object();
5605
5606 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_MAC_IP_ROUTE, false, addr,
5607 json);
5608
5609 if (uj)
5610 vty_json(vty, json);
5611
5612 return CMD_SUCCESS;
5613 }
5614
5615 /*
5616 * Display per-VNI EVPN Multicast routing table - for select VNI
5617 */
5618 DEFPY(show_bgp_vni_imet,
5619 show_bgp_vni_imet_cmd,
5620 "show bgp vni "CMD_VNI_RANGE"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5621 SHOW_STR
5622 BGP_STR
5623 VNI_HELP_STR
5624 VNI_NUM_HELP_STR
5625 EVPN_TYPE_HELP_STR
5626 EVPN_TYPE_3_HELP_STR
5627 EVPN_TYPE_3_HELP_STR
5628 VTEP_HELP_STR
5629 VTEP_IP_HELP_STR
5630 JSON_STR)
5631 {
5632 struct bgp *bgp;
5633 json_object *json = NULL;
5634
5635 bgp = bgp_get_evpn();
5636 if (!bgp)
5637 return CMD_WARNING;
5638
5639 /* check if we need json output */
5640 if (uj)
5641 json = json_object_new_object();
5642
5643 evpn_show_routes_vni(vty, bgp, vni, BGP_EVPN_IMET_ROUTE, false, addr,
5644 json);
5645
5646 if (uj)
5647 vty_json(vty, json);
5648
5649 return CMD_SUCCESS;
5650 }
5651
5652 /*
5653 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5654 */
5655 DEFPY(show_bgp_vni_macip_mac_addr,
5656 show_bgp_vni_macip_mac_addr_cmd,
5657 "show bgp vni "CMD_VNI_RANGE"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5658 SHOW_STR
5659 BGP_STR
5660 VNI_HELP_STR
5661 VNI_NUM_HELP_STR
5662 EVPN_TYPE_HELP_STR
5663 EVPN_TYPE_2_HELP_STR
5664 EVPN_TYPE_2_HELP_STR
5665 "MAC Table\n"
5666 MAC_STR
5667 JSON_STR)
5668 {
5669 struct bgp *bgp;
5670 json_object *json = NULL;
5671
5672 bgp = bgp_get_evpn();
5673 if (!bgp)
5674 return CMD_WARNING;
5675
5676 /* check if we need json output */
5677 if (uj)
5678 json = json_object_new_object();
5679
5680 evpn_show_route_vni_macip(vty, bgp, vni, &mac->eth_addr, NULL, json);
5681
5682 if (uj)
5683 vty_json(vty, json);
5684
5685 return CMD_SUCCESS;
5686 }
5687
5688 /*
5689 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5690 */
5691 DEFPY(show_bgp_vni_macip_ip_addr, show_bgp_vni_macip_ip_addr_cmd,
5692 "show bgp vni " CMD_VNI_RANGE
5693 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5694 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5695 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5696 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR)
5697 {
5698 struct bgp *bgp;
5699 json_object *json = NULL;
5700 struct ipaddr ip_addr = {.ipa_type = IPADDR_NONE};
5701
5702 bgp = bgp_get_evpn();
5703 if (!bgp)
5704 return CMD_WARNING;
5705
5706 /* check if we need json output */
5707 if (uj)
5708 json = json_object_new_object();
5709
5710 if (sockunion_family(ip) == AF_INET) {
5711 ip_addr.ipa_type = IPADDR_V4;
5712 ip_addr.ipaddr_v4.s_addr = sockunion2ip(ip);
5713 } else {
5714 ip_addr.ipa_type = IPADDR_V6;
5715 memcpy(&ip_addr.ipaddr_v6, &ip->sin6.sin6_addr,
5716 sizeof(struct in6_addr));
5717 }
5718 evpn_show_route_vni_macip(vty, bgp, vni, NULL, &ip_addr, json);
5719
5720 if (uj)
5721 vty_json(vty, json);
5722
5723 return CMD_SUCCESS;
5724 }
5725
5726 DEFPY_HIDDEN(
5727 show_bgp_l2vpn_evpn_route_mac_ip_evi_es,
5728 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd,
5729 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5730 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5731 "EVPN route information\n"
5732 "MAC IP routes in the EVI tables linked to the ES\n"
5733 "ES ID\n"
5734 "Detailed information\n" JSON_STR)
5735 {
5736 esi_t esi;
5737 esi_t *esi_p;
5738 json_object *json = NULL;
5739
5740 if (esi_str) {
5741 if (!str_to_esi(esi_str, &esi)) {
5742 vty_out(vty, "%% Malformed ESI\n");
5743 return CMD_WARNING;
5744 }
5745 esi_p = &esi;
5746 } else {
5747 esi_p = NULL;
5748 }
5749
5750 if (uj)
5751 json = json_object_new_object();
5752 bgp_evpn_show_routes_mac_ip_evi_es(vty, esi_p, json, !!detail);
5753 if (uj)
5754 vty_json(vty, json);
5755
5756 return CMD_SUCCESS;
5757 }
5758
5759 DEFPY_HIDDEN(
5760 show_bgp_l2vpn_evpn_route_mac_ip_global_es,
5761 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd,
5762 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5763 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5764 "EVPN route information\n"
5765 "MAC IP routes in the global table linked to the ES\n"
5766 "ES ID\n"
5767 "Detailed information\n" JSON_STR)
5768 {
5769 esi_t esi;
5770 esi_t *esi_p;
5771 json_object *json = NULL;
5772
5773 if (esi_str) {
5774 if (!str_to_esi(esi_str, &esi)) {
5775 vty_out(vty, "%% Malformed ESI\n");
5776 return CMD_WARNING;
5777 }
5778 esi_p = &esi;
5779 } else {
5780 esi_p = NULL;
5781 }
5782
5783 if (uj)
5784 json = json_object_new_object();
5785 bgp_evpn_show_routes_mac_ip_global_es(vty, esi_p, json, !!detail);
5786 if (uj)
5787 vty_json(vty, json);
5788
5789 return CMD_SUCCESS;
5790 }
5791
5792 /*
5793 * Display EVPN import route-target hash table
5794 */
5795 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
5796 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
5797 "show bgp l2vpn evpn vrf-import-rt [json]",
5798 SHOW_STR
5799 BGP_STR
5800 L2VPN_HELP_STR
5801 EVPN_HELP_STR
5802 "Show vrf import route target\n"
5803 JSON_STR)
5804 {
5805 bool uj = false;
5806 struct bgp *bgp_evpn = NULL;
5807 json_object *json = NULL;
5808
5809 bgp_evpn = bgp_get_evpn();
5810 if (!bgp_evpn)
5811 return CMD_WARNING;
5812
5813 uj = use_json(argc, argv);
5814 if (uj)
5815 json = json_object_new_object();
5816
5817 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
5818
5819 if (uj)
5820 vty_json(vty, json);
5821
5822 return CMD_SUCCESS;
5823 }
5824
5825 /*
5826 * Display EVPN import route-target hash table
5827 */
5828 DEFUN(show_bgp_l2vpn_evpn_import_rt,
5829 show_bgp_l2vpn_evpn_import_rt_cmd,
5830 "show bgp l2vpn evpn import-rt [json]",
5831 SHOW_STR
5832 BGP_STR
5833 L2VPN_HELP_STR
5834 EVPN_HELP_STR
5835 "Show import route target\n"
5836 JSON_STR)
5837 {
5838 struct bgp *bgp;
5839 bool uj = false;
5840 json_object *json = NULL;
5841
5842 bgp = bgp_get_evpn();
5843 if (!bgp)
5844 return CMD_WARNING;
5845
5846 uj = use_json(argc, argv);
5847 if (uj)
5848 json = json_object_new_object();
5849
5850 evpn_show_import_rts(vty, bgp, json);
5851
5852 if (uj)
5853 vty_json(vty, json);
5854
5855 return CMD_SUCCESS;
5856 }
5857
5858 DEFPY_HIDDEN(test_es_add,
5859 test_es_add_cmd,
5860 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5861 NO_STR
5862 "Test\n"
5863 "Ethernet-segment\n"
5864 "Ethernet-Segment Identifier\n"
5865 "ES link state\n"
5866 "up|down\n"
5867 )
5868 {
5869 int ret = 0;
5870 esi_t esi;
5871 struct bgp *bgp;
5872 struct in_addr vtep_ip;
5873 bool oper_up;
5874
5875 bgp = bgp_get_evpn();
5876 if (!bgp) {
5877 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5878 return CMD_WARNING;
5879 }
5880
5881 if (!str_to_esi(esi_str, &esi)) {
5882 vty_out(vty, "%% Malformed ESI\n");
5883 return CMD_WARNING;
5884 }
5885
5886 if (no) {
5887 ret = bgp_evpn_local_es_del(bgp, &esi);
5888 if (ret == -1) {
5889 vty_out(vty, "%% Failed to delete ES\n");
5890 return CMD_WARNING;
5891 }
5892 } else {
5893 if (state_str && !strcmp(state_str, "up"))
5894 oper_up = true;
5895 else
5896 oper_up = false;
5897 vtep_ip = bgp->router_id;
5898
5899 ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
5900 EVPN_MH_DF_PREF_MIN, false);
5901 if (ret == -1) {
5902 vty_out(vty, "%% Failed to add ES\n");
5903 return CMD_WARNING;
5904 }
5905 }
5906 return CMD_SUCCESS;
5907 }
5908
5909 DEFPY_HIDDEN(test_es_vni_add,
5910 test_es_vni_add_cmd,
5911 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5912 NO_STR
5913 "Test\n"
5914 "Ethernet-segment\n"
5915 "Ethernet-Segment Identifier\n"
5916 "VNI\n"
5917 "1-16777215\n"
5918 )
5919 {
5920 int ret = 0;
5921 esi_t esi;
5922 struct bgp *bgp;
5923
5924 bgp = bgp_get_evpn();
5925 if (!bgp) {
5926 vty_out(vty, "%% EVPN BGP instance not yet created\n");
5927 return CMD_WARNING;
5928 }
5929
5930 if (!str_to_esi(esi_str, &esi)) {
5931 vty_out(vty, "%% Malformed ESI\n");
5932 return CMD_WARNING;
5933 }
5934
5935 if (no) {
5936 ret = bgp_evpn_local_es_evi_del(bgp, &esi, vni);
5937 if (ret == -1) {
5938 vty_out(vty, "%% Failed to deref ES VNI\n");
5939 return CMD_WARNING;
5940 }
5941 } else {
5942 ret = bgp_evpn_local_es_evi_add(bgp, &esi, vni);
5943 if (ret == -1) {
5944 vty_out(vty, "%% Failed to ref ES VNI\n");
5945 return CMD_WARNING;
5946 }
5947 }
5948 return CMD_SUCCESS;
5949 }
5950
5951 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
5952 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
5953 "Show VNI\n"
5954 "VNI number\n")
5955
5956 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
5957 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5958 "Summary of BGP neighbor status\n" JSON_STR)
5959
5960 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
5961 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5962 SHOW_STR BGP_STR EVPN_HELP_STR
5963 EVPN_RT_HELP_STR
5964 "Display Detailed Information\n"
5965 EVPN_TYPE_HELP_STR
5966 EVPN_TYPE_2_HELP_STR
5967 EVPN_TYPE_2_HELP_STR
5968 EVPN_TYPE_3_HELP_STR
5969 EVPN_TYPE_3_HELP_STR)
5970
5971 ALIAS_HIDDEN(
5972 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
5973 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5974 SHOW_STR BGP_STR EVPN_HELP_STR
5975 EVPN_RT_HELP_STR
5976 EVPN_RT_DIST_HELP_STR
5977 EVPN_ASN_IP_HELP_STR
5978 EVPN_TYPE_HELP_STR
5979 EVPN_TYPE_2_HELP_STR
5980 EVPN_TYPE_2_HELP_STR
5981 EVPN_TYPE_3_HELP_STR
5982 EVPN_TYPE_3_HELP_STR)
5983
5984 ALIAS_HIDDEN(
5985 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
5986 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5987 SHOW_STR BGP_STR EVPN_HELP_STR
5988 EVPN_RT_HELP_STR
5989 EVPN_RT_DIST_HELP_STR
5990 EVPN_ASN_IP_HELP_STR
5991 "MAC\n"
5992 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5993 "IP\n"
5994 "IP address (IPv4 or IPv6)\n")
5995
5996 ALIAS_HIDDEN(
5997 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
5998 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5999 SHOW_STR BGP_STR EVPN_HELP_STR
6000 EVPN_RT_HELP_STR
6001 "VXLAN Network Identifier\n"
6002 "VNI number\n"
6003 EVPN_TYPE_HELP_STR
6004 EVPN_TYPE_2_HELP_STR
6005 EVPN_TYPE_2_HELP_STR
6006 EVPN_TYPE_3_HELP_STR
6007 EVPN_TYPE_3_HELP_STR
6008 "Remote VTEP\n"
6009 "Remote VTEP IP address\n")
6010
6011 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
6012 show_bgp_evpn_route_vni_macip_cmd,
6013 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
6014 SHOW_STR BGP_STR EVPN_HELP_STR
6015 EVPN_RT_HELP_STR
6016 "VXLAN Network Identifier\n"
6017 "VNI number\n"
6018 "MAC\n"
6019 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6020 "IP\n"
6021 "IP address (IPv4 or IPv6)\n")
6022
6023 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
6024 show_bgp_evpn_route_vni_multicast_cmd,
6025 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
6026 SHOW_STR BGP_STR EVPN_HELP_STR
6027 EVPN_RT_HELP_STR
6028 "VXLAN Network Identifier\n"
6029 "VNI number\n"
6030 EVPN_TYPE_3_HELP_STR
6031 "Originating Router IP address\n")
6032
6033 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
6034 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6035 SHOW_STR BGP_STR EVPN_HELP_STR
6036 EVPN_RT_HELP_STR
6037 "VXLAN Network Identifier\n"
6038 "All VNIs\n"
6039 "Print Detailed Output\n"
6040 "Remote VTEP\n"
6041 "Remote VTEP IP address\n")
6042
6043 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
6044 "show bgp evpn import-rt",
6045 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
6046
6047 DEFUN_NOSH (bgp_evpn_vni,
6048 bgp_evpn_vni_cmd,
6049 "vni " CMD_VNI_RANGE,
6050 "VXLAN Network Identifier\n"
6051 "VNI number\n")
6052 {
6053 vni_t vni;
6054 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6055 struct bgpevpn *vpn;
6056
6057 if (!bgp)
6058 return CMD_WARNING;
6059
6060 vni = strtoul(argv[1]->arg, NULL, 10);
6061
6062 /* Create VNI, or mark as configured. */
6063 vpn = evpn_create_update_vni(bgp, vni);
6064 if (!vpn) {
6065 vty_out(vty, "%% Failed to create VNI \n");
6066 return CMD_WARNING;
6067 }
6068
6069 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
6070 return CMD_SUCCESS;
6071 }
6072
6073 DEFUN (no_bgp_evpn_vni,
6074 no_bgp_evpn_vni_cmd,
6075 "no vni " CMD_VNI_RANGE,
6076 NO_STR
6077 "VXLAN Network Identifier\n"
6078 "VNI number\n")
6079 {
6080 vni_t vni;
6081 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6082 struct bgpevpn *vpn;
6083
6084 if (!bgp)
6085 return CMD_WARNING;
6086
6087 vni = strtoul(argv[2]->arg, NULL, 10);
6088
6089 /* Check if we should disallow. */
6090 vpn = bgp_evpn_lookup_vni(bgp, vni);
6091 if (!vpn) {
6092 vty_out(vty, "%% Specified VNI does not exist\n");
6093 return CMD_WARNING;
6094 }
6095 if (!is_vni_configured(vpn)) {
6096 vty_out(vty, "%% Specified VNI is not configured\n");
6097 return CMD_WARNING;
6098 }
6099
6100 evpn_delete_vni(bgp, vpn);
6101 return CMD_SUCCESS;
6102 }
6103
6104 DEFUN_NOSH (exit_vni,
6105 exit_vni_cmd,
6106 "exit-vni",
6107 "Exit from VNI mode\n")
6108 {
6109 if (vty->node == BGP_EVPN_VNI_NODE)
6110 vty->node = BGP_EVPN_NODE;
6111 return CMD_SUCCESS;
6112 }
6113
6114 DEFUN (bgp_evpn_vrf_rd,
6115 bgp_evpn_vrf_rd_cmd,
6116 "rd ASN:NN_OR_IP-ADDRESS:NN",
6117 EVPN_RT_DIST_HELP_STR
6118 EVPN_ASN_IP_HELP_STR)
6119 {
6120 int ret;
6121 struct prefix_rd prd;
6122 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6123
6124 if (!bgp_vrf)
6125 return CMD_WARNING;
6126
6127 ret = str2prefix_rd(argv[1]->arg, &prd);
6128 if (!ret) {
6129 vty_out(vty, "%% Malformed Route Distinguisher\n");
6130 return CMD_WARNING;
6131 }
6132
6133 /* If same as existing value, there is nothing more to do. */
6134 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
6135 return CMD_SUCCESS;
6136
6137 /* Configure or update the RD. */
6138 evpn_configure_vrf_rd(bgp_vrf, &prd, argv[1]->arg);
6139 return CMD_SUCCESS;
6140 }
6141
6142 DEFUN (no_bgp_evpn_vrf_rd,
6143 no_bgp_evpn_vrf_rd_cmd,
6144 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6145 NO_STR
6146 EVPN_RT_DIST_HELP_STR
6147 EVPN_ASN_IP_HELP_STR)
6148 {
6149 int ret;
6150 struct prefix_rd prd;
6151 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6152
6153 if (!bgp_vrf)
6154 return CMD_WARNING;
6155
6156 ret = str2prefix_rd(argv[2]->arg, &prd);
6157 if (!ret) {
6158 vty_out(vty, "%% Malformed Route Distinguisher\n");
6159 return CMD_WARNING;
6160 }
6161
6162 /* Check if we should disallow. */
6163 if (!is_vrf_rd_configured(bgp_vrf)) {
6164 vty_out(vty, "%% RD is not configured for this VRF\n");
6165 return CMD_WARNING;
6166 }
6167
6168 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
6169 vty_out(vty,
6170 "%% RD specified does not match configuration for this VRF\n");
6171 return CMD_WARNING;
6172 }
6173
6174 evpn_unconfigure_vrf_rd(bgp_vrf);
6175 return CMD_SUCCESS;
6176 }
6177
6178 DEFUN (no_bgp_evpn_vrf_rd_without_val,
6179 no_bgp_evpn_vrf_rd_without_val_cmd,
6180 "no rd",
6181 NO_STR
6182 EVPN_RT_DIST_HELP_STR)
6183 {
6184 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
6185
6186 if (!bgp_vrf)
6187 return CMD_WARNING;
6188
6189 /* Check if we should disallow. */
6190 if (!is_vrf_rd_configured(bgp_vrf)) {
6191 vty_out(vty, "%% RD is not configured for this VRF\n");
6192 return CMD_WARNING;
6193 }
6194
6195 evpn_unconfigure_vrf_rd(bgp_vrf);
6196 return CMD_SUCCESS;
6197 }
6198
6199 DEFUN (bgp_evpn_vni_rd,
6200 bgp_evpn_vni_rd_cmd,
6201 "rd ASN:NN_OR_IP-ADDRESS:NN",
6202 EVPN_RT_DIST_HELP_STR
6203 EVPN_ASN_IP_HELP_STR)
6204 {
6205 struct prefix_rd prd;
6206 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6207 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6208 int ret;
6209
6210 if (!bgp)
6211 return CMD_WARNING;
6212
6213 if (!EVPN_ENABLED(bgp)) {
6214 vty_out(vty,
6215 "This command is only supported under EVPN VRF\n");
6216 return CMD_WARNING;
6217 }
6218
6219 ret = str2prefix_rd(argv[1]->arg, &prd);
6220 if (!ret) {
6221 vty_out(vty, "%% Malformed Route Distinguisher\n");
6222 return CMD_WARNING;
6223 }
6224
6225 /* If same as existing value, there is nothing more to do. */
6226 if (bgp_evpn_rd_matches_existing(vpn, &prd))
6227 return CMD_SUCCESS;
6228
6229 /* Configure or update the RD. */
6230 evpn_configure_rd(bgp, vpn, &prd, argv[1]->arg);
6231 return CMD_SUCCESS;
6232 }
6233
6234 DEFUN (no_bgp_evpn_vni_rd,
6235 no_bgp_evpn_vni_rd_cmd,
6236 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6237 NO_STR
6238 EVPN_RT_DIST_HELP_STR
6239 EVPN_ASN_IP_HELP_STR)
6240 {
6241 struct prefix_rd prd;
6242 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6243 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6244 int ret;
6245
6246 if (!bgp)
6247 return CMD_WARNING;
6248
6249 if (!EVPN_ENABLED(bgp)) {
6250 vty_out(vty,
6251 "This command is only supported under EVPN VRF\n");
6252 return CMD_WARNING;
6253 }
6254
6255 ret = str2prefix_rd(argv[2]->arg, &prd);
6256 if (!ret) {
6257 vty_out(vty, "%% Malformed Route Distinguisher\n");
6258 return CMD_WARNING;
6259 }
6260
6261 /* Check if we should disallow. */
6262 if (!is_rd_configured(vpn)) {
6263 vty_out(vty, "%% RD is not configured for this VNI\n");
6264 return CMD_WARNING;
6265 }
6266
6267 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
6268 vty_out(vty,
6269 "%% RD specified does not match configuration for this VNI\n");
6270 return CMD_WARNING;
6271 }
6272
6273 evpn_unconfigure_rd(bgp, vpn);
6274 return CMD_SUCCESS;
6275 }
6276
6277 DEFUN (no_bgp_evpn_vni_rd_without_val,
6278 no_bgp_evpn_vni_rd_without_val_cmd,
6279 "no rd",
6280 NO_STR
6281 EVPN_RT_DIST_HELP_STR)
6282 {
6283 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6284 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6285
6286 if (!bgp)
6287 return CMD_WARNING;
6288
6289 if (!EVPN_ENABLED(bgp)) {
6290 vty_out(vty,
6291 "This command is only supported under EVPN VRF\n");
6292 return CMD_WARNING;
6293 }
6294
6295 /* Check if we should disallow. */
6296 if (!is_rd_configured(vpn)) {
6297 vty_out(vty, "%% RD is not configured for this VNI\n");
6298 return CMD_WARNING;
6299 }
6300
6301 evpn_unconfigure_rd(bgp, vpn);
6302 return CMD_SUCCESS;
6303 }
6304
6305 /*
6306 * Loop over all extended-communities in the route-target list rtl and
6307 * return 1 if we find ecomtarget
6308 */
6309 static bool bgp_evpn_rt_matches_existing(struct list *rtl,
6310 struct ecommunity *ecomtarget)
6311 {
6312 struct listnode *node;
6313 struct ecommunity *ecom;
6314
6315 for (ALL_LIST_ELEMENTS_RO(rtl, node, ecom)) {
6316 if (ecommunity_match(ecom, ecomtarget))
6317 return true;
6318 }
6319
6320 return false;
6321 }
6322
6323 /*
6324 * L3 RT version of above.
6325 */
6326 static bool bgp_evpn_vrf_rt_matches_existing(struct list *rtl,
6327 struct ecommunity *ecomtarget)
6328 {
6329 struct listnode *node;
6330 struct vrf_route_target *l3rt;
6331
6332 for (ALL_LIST_ELEMENTS_RO(rtl, node, l3rt)) {
6333 if (ecommunity_match(l3rt->ecom, ecomtarget))
6334 return true;
6335 }
6336
6337 return false;
6338 }
6339
6340 /* display L3VNI related info for a VRF instance */
6341 DEFUN (show_bgp_vrf_l3vni_info,
6342 show_bgp_vrf_l3vni_info_cmd,
6343 "show bgp vrf VRFNAME vni [json]",
6344 SHOW_STR
6345 BGP_STR
6346 "show bgp vrf\n"
6347 "VRF Name\n"
6348 "L3-VNI\n"
6349 JSON_STR)
6350 {
6351 char buf[ETHER_ADDR_STRLEN];
6352 int idx_vrf = 3;
6353 const char *name = NULL;
6354 struct bgp *bgp = NULL;
6355 struct listnode *node = NULL;
6356 struct bgpevpn *vpn = NULL;
6357 struct vrf_route_target *l3rt;
6358 json_object *json = NULL;
6359 json_object *json_vnis = NULL;
6360 json_object *json_export_rts = NULL;
6361 json_object *json_import_rts = NULL;
6362 bool uj = use_json(argc, argv);
6363
6364 if (uj) {
6365 json = json_object_new_object();
6366 json_vnis = json_object_new_array();
6367 json_export_rts = json_object_new_array();
6368 json_import_rts = json_object_new_array();
6369 }
6370
6371 name = argv[idx_vrf]->arg;
6372 bgp = bgp_lookup_by_name(name);
6373 if (strmatch(name, VRF_DEFAULT_NAME))
6374 bgp = bgp_get_default();
6375
6376 if (!bgp) {
6377 if (!uj)
6378 vty_out(vty, "BGP instance for VRF %s not found\n",
6379 name);
6380 else {
6381 json_object_string_add(json, "warning",
6382 "BGP instance not found");
6383 vty_out(vty, "%s\n", json_object_to_json_string(json));
6384 json_object_free(json);
6385 }
6386 return CMD_WARNING;
6387 }
6388
6389 if (!json) {
6390 vty_out(vty, "BGP VRF: %s\n", name);
6391 vty_out(vty, " Local-Ip: %pI4\n", &bgp->originator_ip);
6392 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
6393 vty_out(vty, " Rmac: %s\n",
6394 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6395 vty_out(vty, " VNI Filter: %s\n",
6396 CHECK_FLAG(bgp->vrf_flags,
6397 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6398 ? "prefix-routes-only"
6399 : "none");
6400 vty_out(vty, " L2-VNI List:\n");
6401 vty_out(vty, " ");
6402 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6403 vty_out(vty, "%u ", vpn->vni);
6404 vty_out(vty, "\n");
6405 vty_out(vty, " Export-RTs:\n");
6406 vty_out(vty, " ");
6407 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6408 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
6409 vty_out(vty, "\n");
6410 vty_out(vty, " Import-RTs:\n");
6411 vty_out(vty, " ");
6412 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6413 vty_out(vty, "%s ", ecommunity_str(l3rt->ecom));
6414 vty_out(vty, "\n");
6415 vty_out(vty, " RD: ");
6416 vty_out(vty, BGP_RD_AS_FORMAT(bgp->asnotation), &bgp->vrf_prd);
6417 vty_out(vty, "\n");
6418 } else {
6419 json_object_string_add(json, "vrf", name);
6420 json_object_string_addf(json, "local-ip", "%pI4",
6421 &bgp->originator_ip);
6422 json_object_int_add(json, "l3vni", bgp->l3vni);
6423 json_object_string_add(
6424 json, "rmac",
6425 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
6426 json_object_string_add(
6427 json, "vniFilter",
6428 CHECK_FLAG(bgp->vrf_flags,
6429 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
6430 ? "prefix-routes-only"
6431 : "none");
6432 /* list of l2vnis */
6433 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
6434 json_object_array_add(json_vnis,
6435 json_object_new_int(vpn->vni));
6436 json_object_object_add(json, "l2vnis", json_vnis);
6437
6438 /* export rts */
6439 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, l3rt))
6440 json_object_array_add(
6441 json_export_rts,
6442 json_object_new_string(
6443 ecommunity_str(l3rt->ecom)));
6444 json_object_object_add(json, "export-rts", json_export_rts);
6445
6446 /* import rts */
6447 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, l3rt))
6448 json_object_array_add(
6449 json_import_rts,
6450 json_object_new_string(
6451 ecommunity_str(l3rt->ecom)));
6452 json_object_object_add(json, "import-rts", json_import_rts);
6453 json_object_string_addf(json, "rd",
6454 BGP_RD_AS_FORMAT(bgp->asnotation),
6455 &bgp->vrf_prd);
6456 }
6457
6458 if (uj)
6459 vty_json(vty, json);
6460 return CMD_SUCCESS;
6461 }
6462
6463 static int add_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import,
6464 bool is_wildcard)
6465 {
6466 /* Do nothing if we already have this route-target */
6467 if (is_import) {
6468 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6469 ecom))
6470 bgp_evpn_configure_import_rt_for_vrf(bgp, ecom,
6471 is_wildcard);
6472 else
6473 return -1;
6474 } else {
6475 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6476 ecom))
6477 bgp_evpn_configure_export_rt_for_vrf(bgp, ecom);
6478 else
6479 return -1;
6480 }
6481
6482 return 0;
6483 }
6484
6485 static int del_rt(struct bgp *bgp, struct ecommunity *ecom, bool is_import)
6486 {
6487 /* Verify we already have this route-target */
6488 if (is_import) {
6489 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_import_rtl,
6490 ecom))
6491 return -1;
6492
6493 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecom);
6494 } else {
6495 if (!bgp_evpn_vrf_rt_matches_existing(bgp->vrf_export_rtl,
6496 ecom))
6497 return -1;
6498
6499 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecom);
6500 }
6501
6502 return 0;
6503 }
6504
6505 static int parse_rtlist(struct bgp *bgp, struct vty *vty, int argc,
6506 struct cmd_token **argv, int rt_idx, bool is_add,
6507 bool is_import)
6508 {
6509 int ret = CMD_SUCCESS;
6510 bool is_wildcard = false;
6511 struct ecommunity *ecom = NULL;
6512
6513 for (int i = rt_idx; i < argc; i++) {
6514 is_wildcard = false;
6515
6516 /*
6517 * Special handling for wildcard '*' here.
6518 *
6519 * Let's just convert it to 0 here so we dont have to modify
6520 * the ecommunity parser.
6521 */
6522 if ((argv[i]->arg)[0] == '*') {
6523 (argv[i]->arg)[0] = '0';
6524 is_wildcard = true;
6525 }
6526
6527 ecom = ecommunity_str2com(argv[i]->arg, ECOMMUNITY_ROUTE_TARGET,
6528 0);
6529
6530 /* Put it back as was */
6531 if (is_wildcard)
6532 (argv[i]->arg)[0] = '*';
6533
6534 if (!ecom) {
6535 vty_out(vty, "%% Malformed Route Target list\n");
6536 ret = CMD_WARNING;
6537 continue;
6538 }
6539
6540 ecommunity_str(ecom);
6541
6542 if (is_add) {
6543 if (add_rt(bgp, ecom, is_import, is_wildcard) != 0) {
6544 vty_out(vty,
6545 "%% RT specified already configured for this VRF: %s\n",
6546 argv[i]->arg);
6547 ecommunity_free(&ecom);
6548 ret = CMD_WARNING;
6549 }
6550
6551 } else {
6552 if (del_rt(bgp, ecom, is_import) != 0) {
6553 vty_out(vty,
6554 "%% RT specified does not match configuration for this VRF: %s\n",
6555 argv[i]->arg);
6556 ret = CMD_WARNING;
6557 }
6558
6559 ecommunity_free(&ecom);
6560 }
6561 }
6562
6563 return ret;
6564 }
6565
6566 /* import/export rt for l3vni-vrf */
6567 DEFUN (bgp_evpn_vrf_rt,
6568 bgp_evpn_vrf_rt_cmd,
6569 "route-target <both|import|export> RTLIST...",
6570 "Route Target\n"
6571 "import and export\n"
6572 "import\n"
6573 "export\n"
6574 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6575 {
6576 int ret = CMD_SUCCESS;
6577 int tmp_ret = CMD_SUCCESS;
6578 int rt_type;
6579 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6580
6581 if (!bgp)
6582 return CMD_WARNING_CONFIG_FAILED;
6583
6584 if (!strcmp(argv[1]->arg, "import"))
6585 rt_type = RT_TYPE_IMPORT;
6586 else if (!strcmp(argv[1]->arg, "export"))
6587 rt_type = RT_TYPE_EXPORT;
6588 else if (!strcmp(argv[1]->arg, "both"))
6589 rt_type = RT_TYPE_BOTH;
6590 else {
6591 vty_out(vty, "%% Invalid Route Target type\n");
6592 return CMD_WARNING_CONFIG_FAILED;
6593 }
6594
6595 if (strmatch(argv[2]->arg, "auto")) {
6596 vty_out(vty, "%% `auto` cannot be configured via list\n");
6597 return CMD_WARNING_CONFIG_FAILED;
6598 }
6599
6600 if (rt_type != RT_TYPE_IMPORT) {
6601 for (int i = 2; i < argc; i++) {
6602 if ((argv[i]->arg)[0] == '*') {
6603 vty_out(vty,
6604 "%% Wildcard '*' only applicable for import\n");
6605 return CMD_WARNING_CONFIG_FAILED;
6606 }
6607 }
6608 }
6609
6610 /* Add/update the import route-target */
6611 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6612 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, true);
6613
6614 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6615 ret = tmp_ret;
6616
6617 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6618 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 2, true, false);
6619
6620 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6621 ret = tmp_ret;
6622
6623 return ret;
6624 }
6625
6626 DEFPY (bgp_evpn_vrf_rt_auto,
6627 bgp_evpn_vrf_rt_auto_cmd,
6628 "route-target <both|import|export>$type auto",
6629 "Route Target\n"
6630 "import and export\n"
6631 "import\n"
6632 "export\n"
6633 "Automatically derive route target\n")
6634 {
6635 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6636 int rt_type;
6637
6638 if (!bgp)
6639 return CMD_WARNING_CONFIG_FAILED;
6640
6641 if (strmatch(type, "import"))
6642 rt_type = RT_TYPE_IMPORT;
6643 else if (strmatch(type, "export"))
6644 rt_type = RT_TYPE_EXPORT;
6645 else if (strmatch(type, "both"))
6646 rt_type = RT_TYPE_BOTH;
6647 else {
6648 vty_out(vty, "%% Invalid Route Target type\n");
6649 return CMD_WARNING_CONFIG_FAILED;
6650 }
6651
6652 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6653 bgp_evpn_configure_import_auto_rt_for_vrf(bgp);
6654
6655 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6656 bgp_evpn_configure_export_auto_rt_for_vrf(bgp);
6657
6658 return CMD_SUCCESS;
6659 }
6660
6661 DEFUN (no_bgp_evpn_vrf_rt,
6662 no_bgp_evpn_vrf_rt_cmd,
6663 "no route-target <both|import|export> RTLIST...",
6664 NO_STR
6665 "Route Target\n"
6666 "import and export\n"
6667 "import\n"
6668 "export\n"
6669 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6670 {
6671 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6672 int ret = CMD_SUCCESS;
6673 int tmp_ret = CMD_SUCCESS;
6674 int rt_type;
6675
6676 if (!bgp)
6677 return CMD_WARNING_CONFIG_FAILED;
6678
6679 if (!strcmp(argv[2]->arg, "import"))
6680 rt_type = RT_TYPE_IMPORT;
6681 else if (!strcmp(argv[2]->arg, "export"))
6682 rt_type = RT_TYPE_EXPORT;
6683 else if (!strcmp(argv[2]->arg, "both"))
6684 rt_type = RT_TYPE_BOTH;
6685 else {
6686 vty_out(vty, "%% Invalid Route Target type\n");
6687 return CMD_WARNING_CONFIG_FAILED;
6688 }
6689
6690 if (!strcmp(argv[3]->arg, "auto")) {
6691 vty_out(vty, "%% `auto` cannot be unconfigured via list\n");
6692 return CMD_WARNING_CONFIG_FAILED;
6693 }
6694
6695 if (rt_type == RT_TYPE_IMPORT) {
6696 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
6697 vty_out(vty,
6698 "%% Import RT is not configured for this VRF\n");
6699 return CMD_WARNING_CONFIG_FAILED;
6700 }
6701 } else if (rt_type == RT_TYPE_EXPORT) {
6702 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6703 vty_out(vty,
6704 "%% Export RT is not configured for this VRF\n");
6705 return CMD_WARNING_CONFIG_FAILED;
6706 }
6707 } else if (rt_type == RT_TYPE_BOTH) {
6708 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
6709 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
6710 vty_out(vty,
6711 "%% Import/Export RT is not configured for this VRF\n");
6712 return CMD_WARNING_CONFIG_FAILED;
6713 }
6714 }
6715
6716 if (rt_type != RT_TYPE_IMPORT) {
6717 for (int i = 3; i < argc; i++) {
6718 if ((argv[i]->arg)[0] == '*') {
6719 vty_out(vty,
6720 "%% Wildcard '*' only applicable for import\n");
6721 return CMD_WARNING_CONFIG_FAILED;
6722 }
6723 }
6724 }
6725
6726 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6727 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, true);
6728
6729 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6730 ret = tmp_ret;
6731
6732 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6733 tmp_ret = parse_rtlist(bgp, vty, argc, argv, 3, false, false);
6734
6735 if (ret == CMD_SUCCESS && tmp_ret != CMD_SUCCESS)
6736 ret = tmp_ret;
6737
6738 return ret;
6739 }
6740
6741 DEFPY (no_bgp_evpn_vrf_rt_auto,
6742 no_bgp_evpn_vrf_rt_auto_cmd,
6743 "no route-target <both|import|export>$type auto",
6744 NO_STR
6745 "Route Target\n"
6746 "import and export\n"
6747 "import\n"
6748 "export\n"
6749 "Automatically derive route target\n")
6750 {
6751 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6752 int rt_type;
6753
6754 if (!bgp)
6755 return CMD_WARNING_CONFIG_FAILED;
6756
6757 if (strmatch(type, "import"))
6758 rt_type = RT_TYPE_IMPORT;
6759 else if (strmatch(type, "export"))
6760 rt_type = RT_TYPE_EXPORT;
6761 else if (strmatch(type, "both"))
6762 rt_type = RT_TYPE_BOTH;
6763 else {
6764 vty_out(vty, "%% Invalid Route Target type\n");
6765 return CMD_WARNING_CONFIG_FAILED;
6766 }
6767
6768 if (rt_type == RT_TYPE_IMPORT) {
6769 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD)) {
6770 vty_out(vty,
6771 "%% Import AUTO RT is not configured for this VRF\n");
6772 return CMD_WARNING_CONFIG_FAILED;
6773 }
6774 } else if (rt_type == RT_TYPE_EXPORT) {
6775 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6776 vty_out(vty,
6777 "%% Export AUTO RT is not configured for this VRF\n");
6778 return CMD_WARNING_CONFIG_FAILED;
6779 }
6780 } else if (rt_type == RT_TYPE_BOTH) {
6781 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD) &&
6782 !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD)) {
6783 vty_out(vty,
6784 "%% Import/Export AUTO RT is not configured for this VRF\n");
6785 return CMD_WARNING_CONFIG_FAILED;
6786 }
6787 }
6788
6789 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT)
6790 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp);
6791
6792 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT)
6793 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp);
6794
6795 return CMD_SUCCESS;
6796 }
6797
6798 DEFPY(bgp_evpn_ead_ess_frag_evi_limit, bgp_evpn_ead_es_frag_evi_limit_cmd,
6799 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6800 NO_STR
6801 "EAD ES fragment config\n"
6802 "EVIs per-fragment\n"
6803 "limit\n")
6804 {
6805 bgp_mh_info->evi_per_es_frag =
6806 no ? BGP_EVPN_MAX_EVI_PER_ES_FRAG : limit;
6807
6808 return CMD_SUCCESS;
6809 }
6810
6811 DEFUN(bgp_evpn_ead_es_rt, bgp_evpn_ead_es_rt_cmd,
6812 "ead-es-route-target export RT",
6813 "EAD ES Route Target\n"
6814 "export\n"
6815 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6816 {
6817 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6818 struct ecommunity *ecomadd = NULL;
6819
6820 if (!bgp)
6821 return CMD_WARNING;
6822
6823 if (!EVPN_ENABLED(bgp)) {
6824 vty_out(vty, "This command is only supported under EVPN VRF\n");
6825 return CMD_WARNING;
6826 }
6827
6828 /* Add/update the export route-target */
6829 ecomadd = ecommunity_str2com(argv[2]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6830 if (!ecomadd) {
6831 vty_out(vty, "%% Malformed Route Target list\n");
6832 return CMD_WARNING;
6833 }
6834 ecommunity_str(ecomadd);
6835
6836 /* Do nothing if we already have this export route-target */
6837 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6838 ecomadd))
6839 bgp_evpn_mh_config_ead_export_rt(bgp, ecomadd, false);
6840
6841 return CMD_SUCCESS;
6842 }
6843
6844 DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
6845 "no ead-es-route-target export RT",
6846 NO_STR
6847 "EAD ES Route Target\n"
6848 "export\n" EVPN_ASN_IP_HELP_STR)
6849 {
6850 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6851 struct ecommunity *ecomdel = NULL;
6852
6853 if (!bgp)
6854 return CMD_WARNING;
6855
6856 if (!EVPN_ENABLED(bgp)) {
6857 vty_out(vty, "This command is only supported under EVPN VRF\n");
6858 return CMD_WARNING;
6859 }
6860
6861 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
6862 if (!ecomdel) {
6863 vty_out(vty, "%% Malformed Route Target list\n");
6864 return CMD_WARNING;
6865 }
6866 ecommunity_str(ecomdel);
6867
6868 if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
6869 ecomdel)) {
6870 ecommunity_free(&ecomdel);
6871 vty_out(vty,
6872 "%% RT specified does not match EAD-ES RT configuration\n");
6873 return CMD_WARNING;
6874 }
6875 bgp_evpn_mh_config_ead_export_rt(bgp, ecomdel, true);
6876
6877 return CMD_SUCCESS;
6878 }
6879
6880 DEFUN (bgp_evpn_vni_rt,
6881 bgp_evpn_vni_rt_cmd,
6882 "route-target <both|import|export> RT",
6883 "Route Target\n"
6884 "import and export\n"
6885 "import\n"
6886 "export\n"
6887 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6888 {
6889 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6890 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6891 int rt_type;
6892 struct ecommunity *ecomadd = NULL;
6893
6894 if (!bgp)
6895 return CMD_WARNING;
6896
6897 if (!EVPN_ENABLED(bgp)) {
6898 vty_out(vty,
6899 "This command is only supported under EVPN VRF\n");
6900 return CMD_WARNING;
6901 }
6902
6903 if (!strcmp(argv[1]->text, "import"))
6904 rt_type = RT_TYPE_IMPORT;
6905 else if (!strcmp(argv[1]->text, "export"))
6906 rt_type = RT_TYPE_EXPORT;
6907 else if (!strcmp(argv[1]->text, "both"))
6908 rt_type = RT_TYPE_BOTH;
6909 else {
6910 vty_out(vty, "%% Invalid Route Target type\n");
6911 return CMD_WARNING;
6912 }
6913
6914 /* Add/update the import route-target */
6915 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
6916 /* Note that first of the two RTs is created for "both" type */
6917 ecomadd = ecommunity_str2com(argv[2]->arg,
6918 ECOMMUNITY_ROUTE_TARGET, 0);
6919 if (!ecomadd) {
6920 vty_out(vty, "%% Malformed Route Target list\n");
6921 return CMD_WARNING;
6922 }
6923 ecommunity_str(ecomadd);
6924
6925 /* Do nothing if we already have this import route-target */
6926 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
6927 evpn_configure_import_rt(bgp, vpn, ecomadd);
6928 }
6929
6930 /* Add/update the export route-target */
6931 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
6932 /* Note that second of the two RTs is created for "both" type */
6933 ecomadd = ecommunity_str2com(argv[2]->arg,
6934 ECOMMUNITY_ROUTE_TARGET, 0);
6935 if (!ecomadd) {
6936 vty_out(vty, "%% Malformed Route Target list\n");
6937 return CMD_WARNING;
6938 }
6939 ecommunity_str(ecomadd);
6940
6941 /* Do nothing if we already have this export route-target */
6942 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
6943 evpn_configure_export_rt(bgp, vpn, ecomadd);
6944 }
6945
6946 return CMD_SUCCESS;
6947 }
6948
6949 DEFUN (no_bgp_evpn_vni_rt,
6950 no_bgp_evpn_vni_rt_cmd,
6951 "no route-target <both|import|export> RT",
6952 NO_STR
6953 "Route Target\n"
6954 "import and export\n"
6955 "import\n"
6956 "export\n"
6957 EVPN_ASN_IP_HELP_STR)
6958 {
6959 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
6960 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
6961 int rt_type, found_ecomdel;
6962 struct ecommunity *ecomdel = NULL;
6963
6964 if (!bgp)
6965 return CMD_WARNING;
6966
6967 if (!EVPN_ENABLED(bgp)) {
6968 vty_out(vty,
6969 "This command is only supported under EVPN VRF\n");
6970 return CMD_WARNING;
6971 }
6972
6973 if (!strcmp(argv[2]->text, "import"))
6974 rt_type = RT_TYPE_IMPORT;
6975 else if (!strcmp(argv[2]->text, "export"))
6976 rt_type = RT_TYPE_EXPORT;
6977 else if (!strcmp(argv[2]->text, "both"))
6978 rt_type = RT_TYPE_BOTH;
6979 else {
6980 vty_out(vty, "%% Invalid Route Target type\n");
6981 return CMD_WARNING;
6982 }
6983
6984 /* The user did "no route-target import", check to see if there are any
6985 * import route-targets configured. */
6986 if (rt_type == RT_TYPE_IMPORT) {
6987 if (!is_import_rt_configured(vpn)) {
6988 vty_out(vty,
6989 "%% Import RT is not configured for this VNI\n");
6990 return CMD_WARNING;
6991 }
6992 } else if (rt_type == RT_TYPE_EXPORT) {
6993 if (!is_export_rt_configured(vpn)) {
6994 vty_out(vty,
6995 "%% Export RT is not configured for this VNI\n");
6996 return CMD_WARNING;
6997 }
6998 } else if (rt_type == RT_TYPE_BOTH) {
6999 if (!is_import_rt_configured(vpn)
7000 && !is_export_rt_configured(vpn)) {
7001 vty_out(vty,
7002 "%% Import/Export RT is not configured for this VNI\n");
7003 return CMD_WARNING;
7004 }
7005 }
7006
7007 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
7008 if (!ecomdel) {
7009 vty_out(vty, "%% Malformed Route Target list\n");
7010 return CMD_WARNING;
7011 }
7012 ecommunity_str(ecomdel);
7013
7014 if (rt_type == RT_TYPE_IMPORT) {
7015 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7016 ecommunity_free(&ecomdel);
7017 vty_out(vty,
7018 "%% RT specified does not match configuration for this VNI\n");
7019 return CMD_WARNING;
7020 }
7021 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7022 } else if (rt_type == RT_TYPE_EXPORT) {
7023 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7024 ecommunity_free(&ecomdel);
7025 vty_out(vty,
7026 "%% RT specified does not match configuration for this VNI\n");
7027 return CMD_WARNING;
7028 }
7029 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7030 } else if (rt_type == RT_TYPE_BOTH) {
7031 found_ecomdel = 0;
7032
7033 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
7034 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
7035 found_ecomdel = 1;
7036 }
7037
7038 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
7039 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
7040 found_ecomdel = 1;
7041 }
7042
7043 if (!found_ecomdel) {
7044 ecommunity_free(&ecomdel);
7045 vty_out(vty,
7046 "%% RT specified does not match configuration for this VNI\n");
7047 return CMD_WARNING;
7048 }
7049 }
7050
7051 return CMD_SUCCESS;
7052 }
7053
7054 DEFUN (no_bgp_evpn_vni_rt_without_val,
7055 no_bgp_evpn_vni_rt_without_val_cmd,
7056 "no route-target <import|export>",
7057 NO_STR
7058 "Route Target\n"
7059 "import\n"
7060 "export\n")
7061 {
7062 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
7063 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
7064 int rt_type;
7065
7066 if (!bgp)
7067 return CMD_WARNING;
7068
7069 if (!EVPN_ENABLED(bgp)) {
7070 vty_out(vty,
7071 "This command is only supported under EVPN VRF\n");
7072 return CMD_WARNING;
7073 }
7074
7075 if (!strcmp(argv[2]->text, "import")) {
7076 rt_type = RT_TYPE_IMPORT;
7077 } else if (!strcmp(argv[2]->text, "export")) {
7078 rt_type = RT_TYPE_EXPORT;
7079 } else {
7080 vty_out(vty, "%% Invalid Route Target type\n");
7081 return CMD_WARNING;
7082 }
7083
7084 /* Check if we should disallow. */
7085 if (rt_type == RT_TYPE_IMPORT) {
7086 if (!is_import_rt_configured(vpn)) {
7087 vty_out(vty,
7088 "%% Import RT is not configured for this VNI\n");
7089 return CMD_WARNING;
7090 }
7091 } else {
7092 if (!is_export_rt_configured(vpn)) {
7093 vty_out(vty,
7094 "%% Export RT is not configured for this VNI\n");
7095 return CMD_WARNING;
7096 }
7097 }
7098
7099 /* Unconfigure the RT. */
7100 if (rt_type == RT_TYPE_IMPORT)
7101 evpn_unconfigure_import_rt(bgp, vpn, NULL);
7102 else
7103 evpn_unconfigure_export_rt(bgp, vpn, NULL);
7104 return CMD_SUCCESS;
7105 }
7106
7107 static int vni_cmp(const void **a, const void **b)
7108 {
7109 const struct bgpevpn *first = *a;
7110 const struct bgpevpn *secnd = *b;
7111
7112 return secnd->vni - first->vni;
7113 }
7114
7115 /*
7116 * Output EVPN configuration information.
7117 */
7118 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
7119 safi_t safi)
7120 {
7121 if (bgp->advertise_all_vni)
7122 vty_out(vty, " advertise-all-vni\n");
7123
7124 if (hashcount(bgp->vnihash)) {
7125 struct list *vnilist = hash_to_list(bgp->vnihash);
7126 struct listnode *ln;
7127 struct bgpevpn *data;
7128
7129 list_sort(vnilist, vni_cmp);
7130 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
7131 write_vni_config(vty, data);
7132
7133 list_delete(&vnilist);
7134 }
7135
7136 if (bgp->advertise_autort_rfc8365)
7137 vty_out(vty, " autort rfc8365-compatible\n");
7138
7139 if (bgp->advertise_gw_macip)
7140 vty_out(vty, " advertise-default-gw\n");
7141
7142 if (bgp->evpn_info->advertise_svi_macip)
7143 vty_out(vty, " advertise-svi-ip\n");
7144
7145 if (bgp->resolve_overlay_index)
7146 vty_out(vty, " enable-resolve-overlay-index\n");
7147
7148 if (bgp_mh_info->evi_per_es_frag != BGP_EVPN_MAX_EVI_PER_ES_FRAG)
7149 vty_out(vty, " ead-es-frag evi-limit %u\n",
7150 bgp_mh_info->evi_per_es_frag);
7151
7152 if (bgp_mh_info->host_routes_use_l3nhg !=
7153 BGP_EVPN_MH_USE_ES_L3NHG_DEF) {
7154 if (bgp_mh_info->host_routes_use_l3nhg)
7155 vty_out(vty, " use-es-l3nhg\n");
7156 else
7157 vty_out(vty, " no use-es-l3nhg\n");
7158 }
7159
7160 if (bgp_mh_info->ead_evi_rx != BGP_EVPN_MH_EAD_EVI_RX_DEF) {
7161 if (bgp_mh_info->ead_evi_rx)
7162 vty_out(vty, " no disable-ead-evi-rx\n");
7163 else
7164 vty_out(vty, " disable-ead-evi-rx\n");
7165 }
7166
7167 if (bgp_mh_info->ead_evi_tx != BGP_EVPN_MH_EAD_EVI_TX_DEF) {
7168 if (bgp_mh_info->ead_evi_tx)
7169 vty_out(vty, " no disable-ead-evi-tx\n");
7170 else
7171 vty_out(vty, " disable-ead-evi-tx\n");
7172 }
7173
7174 if (!bgp->evpn_info->dup_addr_detect)
7175 vty_out(vty, " no dup-addr-detection\n");
7176
7177 if (bgp->evpn_info->dad_max_moves !=
7178 EVPN_DAD_DEFAULT_MAX_MOVES ||
7179 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
7180 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
7181 bgp->evpn_info->dad_max_moves,
7182 bgp->evpn_info->dad_time);
7183
7184 if (bgp->evpn_info->dad_freeze) {
7185 if (bgp->evpn_info->dad_freeze_time)
7186 vty_out(vty,
7187 " dup-addr-detection freeze %u\n",
7188 bgp->evpn_info->dad_freeze_time);
7189 else
7190 vty_out(vty,
7191 " dup-addr-detection freeze permanent\n");
7192 }
7193
7194 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
7195 vty_out(vty, " flooding disable\n");
7196
7197 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7198 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST)) {
7199 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7200 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
7201 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7202 else
7203 vty_out(vty,
7204 " advertise ipv4 unicast\n");
7205 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP)) {
7207 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
7208 vty_out(vty,
7209 " advertise ipv4 unicast gateway-ip route-map %s\n",
7210 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
7211 else
7212 vty_out(vty, " advertise ipv4 unicast gateway-ip\n");
7213 }
7214
7215 /* EAD ES export route-target */
7216 if (listcount(bgp_mh_info->ead_es_export_rtl)) {
7217 struct ecommunity *ecom;
7218 char *ecom_str;
7219 struct listnode *node;
7220
7221 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info->ead_es_export_rtl, node,
7222 ecom)) {
7223
7224 ecom_str = ecommunity_ecom2str(
7225 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7226 vty_out(vty, " ead-es-route-target export %s\n",
7227 ecom_str);
7228 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7229 }
7230 }
7231
7232 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7233 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST)) {
7234 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7235 vty_out(vty,
7236 " advertise ipv6 unicast route-map %s\n",
7237 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7238 else
7239 vty_out(vty,
7240 " advertise ipv6 unicast\n");
7241 } else if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7242 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP)) {
7243 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
7244 vty_out(vty,
7245 " advertise ipv6 unicast gateway-ip route-map %s\n",
7246 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
7247 else
7248 vty_out(vty, " advertise ipv6 unicast gateway-ip\n");
7249 }
7250
7251 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7252 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
7253 vty_out(vty, " default-originate ipv4\n");
7254
7255 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
7256 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
7257 vty_out(vty, " default-originate ipv6\n");
7258
7259 if (bgp->inst_type == BGP_INSTANCE_TYPE_VRF) {
7260 if (!bgp->evpn_info->advertise_pip)
7261 vty_out(vty, " no advertise-pip\n");
7262 if (bgp->evpn_info->advertise_pip) {
7263 if (bgp->evpn_info->pip_ip_static.s_addr
7264 != INADDR_ANY) {
7265 vty_out(vty, " advertise-pip ip %pI4",
7266 &bgp->evpn_info->pip_ip_static);
7267 if (!is_zero_mac(&(
7268 bgp->evpn_info->pip_rmac_static))) {
7269 char buf[ETHER_ADDR_STRLEN];
7270
7271 vty_out(vty, " mac %s",
7272 prefix_mac2str(
7273 &bgp->evpn_info
7274 ->pip_rmac,
7275 buf, sizeof(buf)));
7276 }
7277 vty_out(vty, "\n");
7278 }
7279 }
7280 }
7281 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
7282 vty_out(vty, " rd %s\n", bgp->vrf_prd_pretty);
7283
7284 /* import route-target */
7285 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
7286 char *ecom_str;
7287 struct listnode *node, *nnode;
7288 struct vrf_route_target *l3rt;
7289
7290 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
7291 l3rt)) {
7292
7293 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7294 continue;
7295
7296 ecom_str = ecommunity_ecom2str(
7297 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7298
7299 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_WILD)) {
7300 char *vni_str = NULL;
7301
7302 vni_str = strchr(ecom_str, ':');
7303 if (!vni_str) {
7304 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7305 continue;
7306 }
7307
7308 /* Move pointer to vni */
7309 vni_str += 1;
7310
7311 vty_out(vty, " route-target import *:%s\n",
7312 vni_str);
7313
7314 } else
7315 vty_out(vty, " route-target import %s\n",
7316 ecom_str);
7317
7318 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7319 }
7320 }
7321
7322 /* import route-target auto */
7323 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_AUTO_RT_CFGD))
7324 vty_out(vty, " route-target import auto\n");
7325
7326 /* export route-target */
7327 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
7328 char *ecom_str;
7329 struct listnode *node, *nnode;
7330 struct vrf_route_target *l3rt;
7331
7332 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
7333 l3rt)) {
7334
7335 if (CHECK_FLAG(l3rt->flags, BGP_VRF_RT_AUTO))
7336 continue;
7337
7338 ecom_str = ecommunity_ecom2str(
7339 l3rt->ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
7340 vty_out(vty, " route-target export %s\n", ecom_str);
7341 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
7342 }
7343 }
7344
7345 /* export route-target auto */
7346 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_AUTO_RT_CFGD))
7347 vty_out(vty, " route-target export auto\n");
7348 }
7349
7350 void bgp_ethernetvpn_init(void)
7351 {
7352 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
7353 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
7354 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
7355 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
7356 install_element(VIEW_NODE,
7357 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
7358 install_element(VIEW_NODE,
7359 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
7360 install_element(
7361 VIEW_NODE,
7362 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
7363 install_element(
7364 VIEW_NODE,
7365 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
7366 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
7367 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
7368 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
7369 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
7370 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
7371 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
7372 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
7373 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
7374 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
7375 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
7376 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
7377 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
7378 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
7379 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
7380 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
7381 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
7382 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
7383 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
7384 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
7385 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_pip_ip_mac_cmd);
7386 install_element(BGP_EVPN_NODE, &bgp_evpn_use_es_l3nhg_cmd);
7387 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_rx_disable_cmd);
7388 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_evi_tx_disable_cmd);
7389 install_element(BGP_EVPN_NODE,
7390 &bgp_evpn_enable_resolve_overlay_index_cmd);
7391
7392 /* test commands */
7393 install_element(BGP_EVPN_NODE, &test_es_add_cmd);
7394 install_element(BGP_EVPN_NODE, &test_es_vni_add_cmd);
7395
7396 /* "show bgp l2vpn evpn" commands. */
7397 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
7398 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_evi_cmd);
7399 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_vrf_cmd);
7400 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_nh_cmd);
7401 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
7402 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd);
7403 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd);
7404 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
7405 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
7406 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
7407 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
7408 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
7409 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
7410 install_element(VIEW_NODE,
7411 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
7412 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
7413 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
7414 install_element(VIEW_NODE,
7415 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd);
7416 install_element(VIEW_NODE,
7417 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd);
7418 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
7419 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
7420
7421 /* "show bgp vni" commands. */
7422 install_element(VIEW_NODE, &show_bgp_vni_all_cmd);
7423 install_element(VIEW_NODE, &show_bgp_vni_all_ead_cmd);
7424 install_element(VIEW_NODE, &show_bgp_vni_all_macip_mac_cmd);
7425 install_element(VIEW_NODE, &show_bgp_vni_all_macip_ip_cmd);
7426 install_element(VIEW_NODE, &show_bgp_vni_all_imet_cmd);
7427 install_element(VIEW_NODE, &show_bgp_vni_cmd);
7428 install_element(VIEW_NODE, &show_bgp_vni_ead_cmd);
7429 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_cmd);
7430 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_cmd);
7431 install_element(VIEW_NODE, &show_bgp_vni_imet_cmd);
7432 install_element(VIEW_NODE, &show_bgp_vni_macip_mac_addr_cmd);
7433 install_element(VIEW_NODE, &show_bgp_vni_macip_ip_addr_cmd);
7434
7435 /* "show bgp evpn" commands. */
7436 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
7437 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
7438 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
7439 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
7440 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
7441 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
7442 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
7443 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
7444 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
7445 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
7446 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
7447 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
7448
7449 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
7450 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
7451 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
7452 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
7453 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
7454 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
7455 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
7456 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
7457 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
7458 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
7459 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
7460 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
7461 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
7462 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
7463 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_auto_cmd);
7464 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_auto_cmd);
7465 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_rt_cmd);
7466 install_element(BGP_EVPN_NODE, &no_bgp_evpn_ead_es_rt_cmd);
7467 install_element(BGP_EVPN_NODE, &bgp_evpn_ead_es_frag_evi_limit_cmd);
7468 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
7469 install_element(BGP_EVPN_VNI_NODE,
7470 &bgp_evpn_advertise_default_gw_vni_cmd);
7471 install_element(BGP_EVPN_VNI_NODE,
7472 &no_bgp_evpn_advertise_default_gw_vni_cmd);
7473 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
7474 install_element(BGP_EVPN_VNI_NODE,
7475 &no_bgp_evpn_advertise_vni_subnet_cmd);
7476 }