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