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