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