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