]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_evpn_vty.c
Merge pull request #5088 from pogojotz/revert-asm-equiv-in-MTYPE
[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 "stream.h"
26
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
42
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
47
48 /*
49 * Context for VNI hash walk - used by callbacks.
50 */
51 struct vni_walk_ctx {
52 struct bgp *bgp;
53 struct vty *vty;
54 struct in_addr vtep_ip;
55 json_object *json;
56 int detail;
57 };
58
59 static void display_vrf_import_rt(struct vty *vty, struct vrf_irt_node *irt,
60 json_object *json)
61 {
62 uint8_t *pnt;
63 uint8_t type, sub_type;
64 struct ecommunity_as eas;
65 struct ecommunity_ip eip;
66 struct listnode *node, *nnode;
67 struct bgp *tmp_bgp_vrf = NULL;
68 json_object *json_rt = NULL;
69 json_object *json_vrfs = NULL;
70 char rt_buf[RT_ADDRSTRLEN];
71
72 if (json) {
73 json_rt = json_object_new_object();
74 json_vrfs = json_object_new_array();
75 }
76
77 pnt = (uint8_t *)&irt->rt.val;
78 type = *pnt++;
79 sub_type = *pnt++;
80 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
81 return;
82
83 memset(&eas, 0, sizeof(eas));
84 switch (type) {
85 case ECOMMUNITY_ENCODE_AS:
86 eas.as = (*pnt++ << 8);
87 eas.as |= (*pnt++);
88 ptr_get_be32(pnt, &eas.val);
89
90 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
91
92 if (json)
93 json_object_string_add(json_rt, "rt", rt_buf);
94 else
95 vty_out(vty, "Route-target: %s", rt_buf);
96
97 break;
98
99 case ECOMMUNITY_ENCODE_IP:
100 memcpy(&eip.ip, pnt, 4);
101 pnt += 4;
102 eip.val = (*pnt++ << 8);
103 eip.val |= (*pnt++);
104
105 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
106 eip.val);
107
108 if (json)
109 json_object_string_add(json_rt, "rt", rt_buf);
110 else
111 vty_out(vty, "Route-target: %s", rt_buf);
112
113 break;
114
115 case ECOMMUNITY_ENCODE_AS4:
116 pnt = ptr_get_be32(pnt, &eas.val);
117 eas.val = (*pnt++ << 8);
118 eas.val |= (*pnt++);
119
120 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
121
122 if (json)
123 json_object_string_add(json_rt, "rt", rt_buf);
124 else
125 vty_out(vty, "Route-target: %s", rt_buf);
126
127 break;
128
129 default:
130 return;
131 }
132
133 if (!json) {
134 vty_out(vty,
135 "\nList of VRFs importing routes with this route-target:\n");
136 }
137
138 for (ALL_LIST_ELEMENTS(irt->vrfs, node, nnode, tmp_bgp_vrf)) {
139 if (json)
140 json_object_array_add(
141 json_vrfs,
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf->vrf_id)));
144 else
145 vty_out(vty, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf->vrf_id));
147 }
148
149 if (json) {
150 json_object_object_add(json_rt, "vrfs", json_vrfs);
151 json_object_object_add(json, rt_buf, json_rt);
152 }
153 }
154
155 static void show_vrf_import_rt_entry(struct hash_bucket *bucket, void *args[])
156 {
157 json_object *json = NULL;
158 struct vty *vty = NULL;
159 struct vrf_irt_node *irt = (struct vrf_irt_node *)bucket->data;
160
161 vty = (struct vty *)args[0];
162 json = (struct json_object *)args[1];
163
164 display_vrf_import_rt(vty, irt, json);
165 }
166
167 static void display_import_rt(struct vty *vty, struct irt_node *irt,
168 json_object *json)
169 {
170 uint8_t *pnt;
171 uint8_t type, sub_type;
172 struct ecommunity_as eas;
173 struct ecommunity_ip eip;
174 struct listnode *node, *nnode;
175 struct bgpevpn *tmp_vpn;
176 json_object *json_rt = NULL;
177 json_object *json_vnis = NULL;
178 char rt_buf[RT_ADDRSTRLEN];
179
180 if (json) {
181 json_rt = json_object_new_object();
182 json_vnis = json_object_new_array();
183 }
184
185 /* TODO: This needs to go into a function */
186
187 pnt = (uint8_t *)&irt->rt.val;
188 type = *pnt++;
189 sub_type = *pnt++;
190 if (sub_type != ECOMMUNITY_ROUTE_TARGET)
191 return;
192
193 memset(&eas, 0, sizeof(eas));
194 switch (type) {
195 case ECOMMUNITY_ENCODE_AS:
196 eas.as = (*pnt++ << 8);
197 eas.as |= (*pnt++);
198 ptr_get_be32(pnt, &eas.val);
199
200 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
201
202 if (json)
203 json_object_string_add(json_rt, "rt", rt_buf);
204 else
205 vty_out(vty, "Route-target: %s", rt_buf);
206
207 break;
208
209 case ECOMMUNITY_ENCODE_IP:
210 memcpy(&eip.ip, pnt, 4);
211 pnt += 4;
212 eip.val = (*pnt++ << 8);
213 eip.val |= (*pnt++);
214
215 snprintf(rt_buf, RT_ADDRSTRLEN, "%s:%u", inet_ntoa(eip.ip),
216 eip.val);
217
218 if (json)
219 json_object_string_add(json_rt, "rt", rt_buf);
220 else
221 vty_out(vty, "Route-target: %s", rt_buf);
222
223 break;
224
225 case ECOMMUNITY_ENCODE_AS4:
226 pnt = ptr_get_be32(pnt, &eas.val);
227 eas.val = (*pnt++ << 8);
228 eas.val |= (*pnt++);
229
230 snprintf(rt_buf, RT_ADDRSTRLEN, "%u:%u", eas.as, eas.val);
231
232 if (json)
233 json_object_string_add(json_rt, "rt", rt_buf);
234 else
235 vty_out(vty, "Route-target: %s", rt_buf);
236
237 break;
238
239 default:
240 return;
241 }
242
243 if (!json) {
244 vty_out(vty,
245 "\nList of VNIs importing routes with this route-target:\n");
246 }
247
248 for (ALL_LIST_ELEMENTS(irt->vnis, node, nnode, tmp_vpn)) {
249 if (json)
250 json_object_array_add(
251 json_vnis, json_object_new_int(tmp_vpn->vni));
252 else
253 vty_out(vty, " %u\n", tmp_vpn->vni);
254 }
255
256 if (json) {
257 json_object_object_add(json_rt, "vnis", json_vnis);
258 json_object_object_add(json, rt_buf, json_rt);
259 }
260 }
261
262 static void show_import_rt_entry(struct hash_bucket *bucket, void *args[])
263 {
264 json_object *json = NULL;
265 struct vty *vty = NULL;
266 struct irt_node *irt = (struct irt_node *)bucket->data;
267
268 vty = args[0];
269 json = args[1];
270
271 display_import_rt(vty, irt, json);
272
273 return;
274 }
275
276 static void bgp_evpn_show_route_rd_header(struct vty *vty,
277 struct bgp_node *rd_rn,
278 json_object *json)
279 {
280 uint16_t type;
281 struct rd_as rd_as;
282 struct rd_ip rd_ip;
283 uint8_t *pnt;
284 char rd_str[RD_ADDRSTRLEN];
285
286 pnt = rd_rn->p.u.val;
287
288 /* Decode RD type. */
289 type = decode_rd_type(pnt);
290
291 if (json)
292 return;
293
294 vty_out(vty, "Route Distinguisher: ");
295
296 switch (type) {
297 case RD_TYPE_AS:
298 decode_rd_as(pnt + 2, &rd_as);
299 snprintf(rd_str, RD_ADDRSTRLEN, "%u:%d", rd_as.as, rd_as.val);
300 break;
301
302 case RD_TYPE_IP:
303 decode_rd_ip(pnt + 2, &rd_ip);
304 snprintf(rd_str, RD_ADDRSTRLEN, "%s:%d", inet_ntoa(rd_ip.ip),
305 rd_ip.val);
306 break;
307
308 default:
309 snprintf(rd_str, RD_ADDRSTRLEN, "Unknown RD type");
310 break;
311 }
312
313 vty_out(vty, "%s\n", rd_str);
314 }
315
316 static void bgp_evpn_show_route_header(struct vty *vty, struct bgp *bgp,
317 uint64_t tbl_ver, json_object *json)
318 {
319 char ri_header[] =
320 " Network Next Hop Metric LocPrf Weight Path\n";
321
322 if (json)
323 return;
324
325 vty_out(vty, "BGP table version is %" PRIu64 ", local router ID is %s\n",
326 tbl_ver, inet_ntoa(bgp->router_id));
327 vty_out(vty,
328 "Status codes: s suppressed, d damped, h history, "
329 "* valid, > best, i - internal\n");
330 vty_out(vty, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
331 vty_out(vty,
332 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
333 vty_out(vty, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
334 vty_out(vty, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
335 vty_out(vty, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
336 vty_out(vty, "%s", ri_header);
337 }
338
339 static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
340 json_object *json)
341 {
342 char buf1[INET6_ADDRSTRLEN];
343 char *ecom_str;
344 struct listnode *node, *nnode;
345 struct ecommunity *ecom;
346 json_object *json_import_rtl = NULL;
347 json_object *json_export_rtl = NULL;
348
349 json_import_rtl = json_export_rtl = 0;
350
351 if (json) {
352 json_import_rtl = json_object_new_array();
353 json_export_rtl = json_object_new_array();
354 json_object_int_add(json, "vni", bgp_vrf->l3vni);
355 json_object_string_add(json, "type", "L3");
356 json_object_string_add(json, "kernelFlag", "Yes");
357 json_object_string_add(
358 json, "rd",
359 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
360 json_object_string_add(json, "originatorIp",
361 inet_ntoa(bgp_vrf->originator_ip));
362 json_object_string_add(json, "advertiseGatewayMacip", "n/a");
363 json_object_string_add(json, "advertiseSviMacip", "n/a");
364 json_object_to_json_string_ext(json,
365 JSON_C_TO_STRING_NOSLASHESCAPE);
366 } else {
367 vty_out(vty, "VNI: %d", bgp_vrf->l3vni);
368 vty_out(vty, " (known to the kernel)");
369 vty_out(vty, "\n");
370
371 vty_out(vty, " Type: %s\n", "L3");
372 vty_out(vty, " Tenant VRF: %s\n",
373 vrf_id_to_name(bgp_vrf->vrf_id));
374 vty_out(vty, " RD: %s\n",
375 prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
376 vty_out(vty, " Originator IP: %s\n",
377 inet_ntoa(bgp_vrf->originator_ip));
378 vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
379 vty_out(vty, " Advertise-svi-macip : %s\n", "n/a");
380 }
381
382 if (!json)
383 vty_out(vty, " Import Route Target:\n");
384
385 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_import_rtl, node, nnode, ecom)) {
386 ecom_str = ecommunity_ecom2str(ecom,
387 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
388
389 if (json)
390 json_object_array_add(json_import_rtl,
391 json_object_new_string(ecom_str));
392 else
393 vty_out(vty, " %s\n", ecom_str);
394
395 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
396 }
397
398 if (json)
399 json_object_object_add(json, "importRts", json_import_rtl);
400 else
401 vty_out(vty, " Export Route Target:\n");
402
403 for (ALL_LIST_ELEMENTS(bgp_vrf->vrf_export_rtl, node, nnode, ecom)) {
404 ecom_str = ecommunity_ecom2str(ecom,
405 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
406
407 if (json)
408 json_object_array_add(json_export_rtl,
409 json_object_new_string(ecom_str));
410 else
411 vty_out(vty, " %s\n", ecom_str);
412
413 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
414 }
415
416 if (json)
417 json_object_object_add(json, "exportRts", json_export_rtl);
418 }
419
420 static void display_es(struct vty *vty, struct evpnes *es, json_object *json)
421 {
422 struct in_addr *vtep;
423 char buf[ESI_STR_LEN];
424 char buf1[RD_ADDRSTRLEN];
425 char buf2[INET6_ADDRSTRLEN];
426 struct listnode *node = NULL;
427 json_object *json_vteps = NULL;
428
429 if (json) {
430 json_vteps = json_object_new_array();
431 json_object_string_add(json, "esi",
432 esi_to_str(&es->esi, buf, sizeof(buf)));
433 json_object_string_add(json, "rd",
434 prefix_rd2str(&es->prd, buf1,
435 sizeof(buf1)));
436 json_object_string_add(
437 json, "originatorIp",
438 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
439 if (es->vtep_list) {
440 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
441 json_object_array_add(
442 json_vteps, json_object_new_string(
443 inet_ntoa(*vtep)));
444 }
445 json_object_object_add(json, "vteps", json_vteps);
446 } else {
447 vty_out(vty, "ESI: %s\n",
448 esi_to_str(&es->esi, buf, sizeof(buf)));
449 vty_out(vty, " RD: %s\n", prefix_rd2str(&es->prd, buf1,
450 sizeof(buf1)));
451 vty_out(vty, " Originator-IP: %s\n",
452 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
453 if (es->vtep_list) {
454 vty_out(vty, " VTEP List:\n");
455 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
456 vty_out(vty, " %s\n", inet_ntoa(*vtep));
457 }
458 }
459 }
460
461 static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
462 {
463 char buf1[RD_ADDRSTRLEN];
464 char *ecom_str;
465 struct listnode *node, *nnode;
466 struct ecommunity *ecom;
467 json_object *json_import_rtl = NULL;
468 json_object *json_export_rtl = NULL;
469 struct bgp *bgp_evpn;
470
471 bgp_evpn = bgp_get_evpn();
472
473 if (json) {
474 json_import_rtl = json_object_new_array();
475 json_export_rtl = json_object_new_array();
476 json_object_int_add(json, "vni", vpn->vni);
477 json_object_string_add(json, "type", "L2");
478 json_object_string_add(json, "kernelFlag",
479 is_vni_live(vpn) ? "Yes" : "No");
480 json_object_string_add(
481 json, "rd",
482 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
483 json_object_string_add(json, "originatorIp",
484 inet_ntoa(vpn->originator_ip));
485 json_object_string_add(json, "mcastGroup",
486 inet_ntoa(vpn->mcast_grp));
487 /* per vni knob is enabled -- Enabled
488 * Global knob is enabled -- Active
489 * default -- Disabled
490 */
491 if (!vpn->advertise_gw_macip &&
492 bgp_evpn && bgp_evpn->advertise_gw_macip)
493 json_object_string_add(json, "advertiseGatewayMacip",
494 "Active");
495 else if (vpn->advertise_gw_macip)
496 json_object_string_add(json, "advertiseGatewayMacip",
497 "Enabled");
498 else
499 json_object_string_add(json, "advertiseGatewayMacip",
500 "Disabled");
501 if (!vpn->advertise_svi_macip && bgp_evpn &&
502 bgp_evpn->evpn_info->advertise_svi_macip)
503 json_object_string_add(json, "advertiseSviMacip",
504 "Active");
505 else if (vpn->advertise_svi_macip)
506 json_object_string_add(json, "advertiseSviMacip",
507 "Enabled");
508 else
509 json_object_string_add(json, "advertiseSviMacip",
510 "Disabled");
511 } else {
512 vty_out(vty, "VNI: %d", vpn->vni);
513 if (is_vni_live(vpn))
514 vty_out(vty, " (known to the kernel)");
515 vty_out(vty, "\n");
516
517 vty_out(vty, " Type: %s\n", "L2");
518 vty_out(vty, " Tenant-Vrf: %s\n",
519 vrf_id_to_name(vpn->tenant_vrf_id));
520 vty_out(vty, " RD: %s\n",
521 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
522 vty_out(vty, " Originator IP: %s\n",
523 inet_ntoa(vpn->originator_ip));
524 vty_out(vty, " Mcast group: %s\n",
525 inet_ntoa(vpn->mcast_grp));
526 if (!vpn->advertise_gw_macip &&
527 bgp_evpn && bgp_evpn->advertise_gw_macip)
528 vty_out(vty, " Advertise-gw-macip : %s\n",
529 "Active");
530 else if (vpn->advertise_gw_macip)
531 vty_out(vty, " Advertise-gw-macip : %s\n",
532 "Enabled");
533 else
534 vty_out(vty, " Advertise-gw-macip : %s\n",
535 "Disabled");
536 if (!vpn->advertise_svi_macip && bgp_evpn &&
537 bgp_evpn->evpn_info->advertise_svi_macip)
538 vty_out(vty, " Advertise-svi-macip : %s\n",
539 "Active");
540 else if (vpn->advertise_svi_macip)
541 vty_out(vty, " Advertise-svi-macip : %s\n",
542 "Enabled");
543 else
544 vty_out(vty, " Advertise-svi-macip : %s\n",
545 "Disabled");
546 }
547
548 if (!json)
549 vty_out(vty, " Import Route Target:\n");
550
551 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
552 ecom_str = ecommunity_ecom2str(ecom,
553 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
554
555 if (json)
556 json_object_array_add(json_import_rtl,
557 json_object_new_string(ecom_str));
558 else
559 vty_out(vty, " %s\n", ecom_str);
560
561 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
562 }
563
564 if (json)
565 json_object_object_add(json, "importRts", json_import_rtl);
566 else
567 vty_out(vty, " Export Route Target:\n");
568
569 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
570 ecom_str = ecommunity_ecom2str(ecom,
571 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
572
573 if (json)
574 json_object_array_add(json_export_rtl,
575 json_object_new_string(ecom_str));
576 else
577 vty_out(vty, " %s\n", ecom_str);
578
579 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
580 }
581
582 if (json)
583 json_object_object_add(json, "exportRts", json_export_rtl);
584 }
585
586 static void show_esi_routes(struct bgp *bgp,
587 struct evpnes *es,
588 struct vty *vty,
589 json_object *json)
590 {
591 int header = 1;
592 struct bgp_node *rn;
593 struct bgp_path_info *pi;
594 uint32_t prefix_cnt, path_cnt;
595 uint64_t tbl_ver;
596
597 prefix_cnt = path_cnt = 0;
598
599 tbl_ver = es->route_table->version;
600 for (rn = bgp_table_top(es->route_table); rn;
601 rn = bgp_route_next(rn)) {
602 int add_prefix_to_json = 0;
603 char prefix_str[BUFSIZ];
604 json_object *json_paths = NULL;
605 json_object *json_prefix = NULL;
606
607 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
608 sizeof(prefix_str));
609
610 if (json)
611 json_prefix = json_object_new_object();
612
613 pi = bgp_node_get_bgp_path_info(rn);
614 if (pi) {
615 /* Overall header/legend displayed once. */
616 if (header) {
617 bgp_evpn_show_route_header(vty, bgp,
618 tbl_ver, json);
619 header = 0;
620 }
621
622 prefix_cnt++;
623 }
624
625 if (json)
626 json_paths = json_object_new_array();
627
628 /* For EVPN, the prefix is displayed for each path (to fit in
629 * with code that already exists).
630 */
631 for (; pi; pi = pi->next) {
632 json_object *json_path = NULL;
633
634 if (json)
635 json_path = json_object_new_array();
636
637 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN, json_path);
638
639 if (json)
640 json_object_array_add(json_paths, json_path);
641
642 path_cnt++;
643 add_prefix_to_json = 1;
644 }
645
646 if (json && add_prefix_to_json) {
647 json_object_string_add(json_prefix, "prefix",
648 prefix_str);
649 json_object_int_add(json_prefix, "prefixLen",
650 rn->p.prefixlen);
651 json_object_object_add(json_prefix, "paths",
652 json_paths);
653 json_object_object_add(json, prefix_str, json_prefix);
654 }
655 }
656
657 if (json) {
658 json_object_int_add(json, "numPrefix", prefix_cnt);
659 json_object_int_add(json, "numPaths", path_cnt);
660 } else {
661 if (prefix_cnt == 0)
662 vty_out(vty, "No EVPN prefixes exist for this ESI\n");
663 else
664 vty_out(vty, "\nDisplayed %u prefixes (%u paths)\n",
665 prefix_cnt, path_cnt);
666 }
667 }
668
669 static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
670 struct vty *vty, struct in_addr vtep_ip,
671 json_object *json, int detail)
672 {
673 struct bgp_node *rn;
674 struct bgp_path_info *pi;
675 struct bgp_table *table;
676 int header = detail ? 0 : 1;
677 uint64_t tbl_ver;
678 uint32_t prefix_cnt, path_cnt;
679
680 prefix_cnt = path_cnt = 0;
681
682 table = vpn->route_table;
683 tbl_ver = table->version;
684 for (rn = bgp_table_top(table); rn;
685 rn = bgp_route_next(rn)) {
686 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
687 int add_prefix_to_json = 0;
688 char prefix_str[BUFSIZ];
689 json_object *json_paths = NULL;
690 json_object *json_prefix = NULL;
691
692 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
693 sizeof(prefix_str));
694
695 if (type && evp->prefix.route_type != type)
696 continue;
697
698 if (json)
699 json_prefix = json_object_new_object();
700
701 pi = bgp_node_get_bgp_path_info(rn);
702 if (pi) {
703 /* Overall header/legend displayed once. */
704 if (header) {
705 bgp_evpn_show_route_header(vty, bgp,
706 tbl_ver, json);
707 header = 0;
708 }
709
710 prefix_cnt++;
711 }
712
713 if (json)
714 json_paths = json_object_new_array();
715
716 /* For EVPN, the prefix is displayed for each path (to fit in
717 * with code that already exists).
718 */
719 for (; pi; pi = pi->next) {
720 json_object *json_path = NULL;
721
722 if (vtep_ip.s_addr
723 && !IPV4_ADDR_SAME(&(vtep_ip),
724 &(pi->attr->nexthop)))
725 continue;
726
727 if (json)
728 json_path = json_object_new_array();
729
730 if (detail)
731 route_vty_out_detail(vty, bgp, rn, pi,
732 AFI_L2VPN, SAFI_EVPN,
733 json_path);
734 else
735 route_vty_out(vty, &rn->p, pi, 0, SAFI_EVPN,
736 json_path);
737
738 if (json)
739 json_object_array_add(json_paths, json_path);
740
741 path_cnt++;
742 add_prefix_to_json = 1;
743 }
744
745 if (json && add_prefix_to_json) {
746 json_object_string_add(json_prefix, "prefix",
747 prefix_str);
748 json_object_int_add(json_prefix, "prefixLen",
749 rn->p.prefixlen);
750 json_object_object_add(json_prefix, "paths",
751 json_paths);
752 json_object_object_add(json, prefix_str, json_prefix);
753 }
754 }
755
756 if (json) {
757 json_object_int_add(json, "numPrefix", prefix_cnt);
758 json_object_int_add(json, "numPaths", path_cnt);
759 } else {
760 if (prefix_cnt == 0)
761 vty_out(vty, "No EVPN prefixes %sexist for this VNI",
762 type ? "(of requested type) " : "");
763 else
764 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
765 prefix_cnt, path_cnt,
766 type ? " (of requested type)" : "");
767 vty_out(vty, "\n");
768 }
769 }
770
771 static void show_vni_routes_hash(struct hash_bucket *bucket, void *arg)
772 {
773 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
774 struct vni_walk_ctx *wctx = arg;
775 struct vty *vty = wctx->vty;
776 json_object *json = wctx->json;
777 json_object *json_vni = NULL;
778 char vni_str[VNI_STR_LEN];
779
780 snprintf(vni_str, VNI_STR_LEN, "%d", vpn->vni);
781 if (json) {
782 json_vni = json_object_new_object();
783 json_object_int_add(json_vni, "vni", vpn->vni);
784 } else {
785 vty_out(vty, "\nVNI: %d\n\n", vpn->vni);
786 }
787
788 show_vni_routes(wctx->bgp, vpn, 0, wctx->vty, wctx->vtep_ip, json_vni,
789 wctx->detail);
790
791 if (json)
792 json_object_object_add(json, vni_str, json_vni);
793 }
794
795 static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
796 json_object *json)
797 {
798 json_object *json_vni = NULL;
799 json_object *json_import_rtl = NULL;
800 json_object *json_export_rtl = NULL;
801 char buf1[10];
802 char buf2[INET6_ADDRSTRLEN];
803 char rt_buf[25];
804 char *ecom_str;
805 struct listnode *node, *nnode;
806 struct ecommunity *ecom;
807
808 if (!bgp->l3vni)
809 return;
810
811 if (json) {
812 json_vni = json_object_new_object();
813 json_import_rtl = json_object_new_array();
814 json_export_rtl = json_object_new_array();
815 }
816
817 /* if an l3vni is present in bgp it is live */
818 buf1[0] = '\0';
819 sprintf(buf1, "*");
820
821 if (json) {
822 json_object_int_add(json_vni, "vni", bgp->l3vni);
823 json_object_string_add(json_vni, "type", "L3");
824 json_object_string_add(json_vni, "inKernel", "True");
825 json_object_string_add(json_vni, "originatorIp",
826 inet_ntoa(bgp->originator_ip));
827 json_object_string_add(
828 json_vni, "rd",
829 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
830 } else {
831 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
832 prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
833 }
834
835 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
836 ecom_str = ecommunity_ecom2str(ecom,
837 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
838
839 if (json) {
840 json_object_array_add(json_import_rtl,
841 json_object_new_string(ecom_str));
842 } else {
843 if (listcount(bgp->vrf_import_rtl) > 1)
844 sprintf(rt_buf, "%s, ...", ecom_str);
845 else
846 sprintf(rt_buf, "%s", ecom_str);
847 vty_out(vty, " %-25s", rt_buf);
848 }
849
850 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
851
852 /* If there are multiple import RTs we break here and show only
853 * one */
854 if (!json)
855 break;
856 }
857
858 if (json)
859 json_object_object_add(json_vni, "importRTs", json_import_rtl);
860
861 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode, ecom)) {
862 ecom_str = ecommunity_ecom2str(ecom,
863 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
864
865 if (json) {
866 json_object_array_add(json_export_rtl,
867 json_object_new_string(ecom_str));
868 } else {
869 if (listcount(bgp->vrf_export_rtl) > 1)
870 sprintf(rt_buf, "%s, ...", ecom_str);
871 else
872 sprintf(rt_buf, "%s", ecom_str);
873 vty_out(vty, " %-25s", rt_buf);
874 }
875
876 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
877
878 /* If there are multiple export RTs we break here and show only
879 * one */
880 if (!json)
881 break;
882 }
883
884 if (!json)
885 vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
886
887 if (json) {
888 char vni_str[VNI_STR_LEN];
889
890 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
891 snprintf(vni_str, VNI_STR_LEN, "%u", bgp->l3vni);
892 json_object_object_add(json, vni_str, json_vni);
893 } else {
894 vty_out(vty, "\n");
895 }
896 }
897
898 static void show_es_entry(struct hash_bucket *bucket, void *args[])
899 {
900 char buf[ESI_STR_LEN];
901 char buf1[RD_ADDRSTRLEN];
902 char buf2[INET6_ADDRSTRLEN];
903 struct in_addr *vtep = NULL;
904 struct vty *vty = args[0];
905 json_object *json = args[1];
906 json_object *json_vteps = NULL;
907 struct listnode *node = NULL;
908 struct evpnes *es = (struct evpnes *)bucket->data;
909
910 if (json) {
911 json_vteps = json_object_new_array();
912 json_object_string_add(json, "esi",
913 esi_to_str(&es->esi, buf, sizeof(buf)));
914 json_object_string_add(json, "type",
915 is_es_local(es) ? "Local" : "Remote");
916 json_object_string_add(json, "rd",
917 prefix_rd2str(&es->prd, buf1,
918 sizeof(buf1)));
919 json_object_string_add(
920 json, "originatorIp",
921 ipaddr2str(&es->originator_ip, buf2, sizeof(buf2)));
922 if (es->vtep_list) {
923 for (ALL_LIST_ELEMENTS_RO(es->vtep_list, node, vtep))
924 json_object_array_add(json_vteps,
925 json_object_new_string(
926 inet_ntoa(*vtep)));
927 }
928 json_object_object_add(json, "vteps", json_vteps);
929 } else {
930 vty_out(vty, "%-30s %-6s %-21s %-15s %-6d\n",
931 esi_to_str(&es->esi, buf, sizeof(buf)),
932 is_es_local(es) ? "Local" : "Remote",
933 prefix_rd2str(&es->prd, buf1, sizeof(buf1)),
934 ipaddr2str(&es->originator_ip, buf2,
935 sizeof(buf2)),
936 es->vtep_list ? listcount(es->vtep_list) : 0);
937 }
938 }
939
940 static void show_vni_entry(struct hash_bucket *bucket, void *args[])
941 {
942 struct vty *vty;
943 json_object *json;
944 json_object *json_vni = NULL;
945 json_object *json_import_rtl = NULL;
946 json_object *json_export_rtl = NULL;
947 struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
948 char buf1[10];
949 char buf2[RD_ADDRSTRLEN];
950 char rt_buf[25];
951 char *ecom_str;
952 struct listnode *node, *nnode;
953 struct ecommunity *ecom;
954
955 vty = args[0];
956 json = args[1];
957
958 if (json) {
959 json_vni = json_object_new_object();
960 json_import_rtl = json_object_new_array();
961 json_export_rtl = json_object_new_array();
962 }
963
964 buf1[0] = '\0';
965 if (is_vni_live(vpn))
966 sprintf(buf1, "*");
967
968 if (json) {
969 json_object_int_add(json_vni, "vni", vpn->vni);
970 json_object_string_add(json_vni, "type", "L2");
971 json_object_string_add(json_vni, "inKernel",
972 is_vni_live(vpn) ? "True" : "False");
973 json_object_string_add(json_vni, "originatorIp",
974 inet_ntoa(vpn->originator_ip));
975 json_object_string_add(json_vni, "originatorIp",
976 inet_ntoa(vpn->originator_ip));
977 json_object_string_add(
978 json_vni, "rd",
979 prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
980 } else {
981 vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
982 prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
983 }
984
985 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
986 ecom_str = ecommunity_ecom2str(ecom,
987 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
988
989 if (json) {
990 json_object_array_add(json_import_rtl,
991 json_object_new_string(ecom_str));
992 } else {
993 if (listcount(vpn->import_rtl) > 1)
994 sprintf(rt_buf, "%s, ...", ecom_str);
995 else
996 sprintf(rt_buf, "%s", ecom_str);
997 vty_out(vty, " %-25s", rt_buf);
998 }
999
1000 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1001
1002 /* If there are multiple import RTs we break here and show only
1003 * one */
1004 if (!json)
1005 break;
1006 }
1007
1008 if (json)
1009 json_object_object_add(json_vni, "importRTs", json_import_rtl);
1010
1011 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
1012 ecom_str = ecommunity_ecom2str(ecom,
1013 ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
1014
1015 if (json) {
1016 json_object_array_add(json_export_rtl,
1017 json_object_new_string(ecom_str));
1018 } else {
1019 if (listcount(vpn->export_rtl) > 1)
1020 sprintf(rt_buf, "%s, ...", ecom_str);
1021 else
1022 sprintf(rt_buf, "%s", ecom_str);
1023 vty_out(vty, " %-25s", rt_buf);
1024 }
1025
1026 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
1027
1028 /* If there are multiple export RTs we break here and show only
1029 * one */
1030 if (!json)
1031 break;
1032 }
1033
1034 if (!json)
1035 vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
1036
1037 if (json) {
1038 char vni_str[VNI_STR_LEN];
1039
1040 json_object_object_add(json_vni, "exportRTs", json_export_rtl);
1041 snprintf(vni_str, VNI_STR_LEN, "%u", vpn->vni);
1042 json_object_object_add(json, vni_str, json_vni);
1043 } else {
1044 vty_out(vty, "\n");
1045 }
1046 }
1047
1048 static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
1049 enum bgp_show_type type, void *output_arg,
1050 int option, bool use_json)
1051 {
1052 afi_t afi = AFI_L2VPN;
1053 struct bgp *bgp;
1054 struct bgp_table *table;
1055 struct bgp_node *rn;
1056 struct bgp_node *rm;
1057 struct bgp_path_info *pi;
1058 int rd_header;
1059 int header = 1;
1060 char rd_str[BUFSIZ];
1061 char buf[BUFSIZ];
1062 int no_display;
1063
1064 unsigned long output_count = 0;
1065 unsigned long total_count = 0;
1066 json_object *json = NULL;
1067 json_object *json_nroute = NULL;
1068 json_object *json_array = NULL;
1069 json_object *json_prefix_info = NULL;
1070
1071 memset(rd_str, 0, BUFSIZ);
1072
1073 bgp = bgp_get_evpn();
1074 if (bgp == NULL) {
1075 if (!use_json)
1076 vty_out(vty, "No BGP process is configured\n");
1077 else
1078 vty_out(vty, "{}\n");
1079 return CMD_WARNING;
1080 }
1081
1082 if (use_json)
1083 json = json_object_new_object();
1084
1085 for (rn = bgp_table_top(bgp->rib[afi][SAFI_EVPN]); rn;
1086 rn = bgp_route_next(rn)) {
1087 uint64_t tbl_ver;
1088
1089 if (prd && memcmp(rn->p.u.val, prd->val, 8) != 0)
1090 continue;
1091
1092 table = bgp_node_get_bgp_table_info(rn);
1093 if (!table)
1094 continue;
1095
1096 rd_header = 1;
1097 tbl_ver = table->version;
1098
1099 for (rm = bgp_table_top(table); rm; rm = bgp_route_next(rm)) {
1100 pi = bgp_node_get_bgp_path_info(rm);
1101 if (pi == NULL)
1102 continue;
1103
1104 no_display = 0;
1105 if (use_json) {
1106 json_array = json_object_new_array();
1107 json_prefix_info = json_object_new_object();
1108
1109 json_object_string_add(json_prefix_info,
1110 "prefix", bgp_evpn_route2str(
1111 (struct prefix_evpn *)&rm->p, buf,
1112 BUFSIZ));
1113
1114 json_object_int_add(json_prefix_info,
1115 "prefixLen", rm->p.prefixlen);
1116
1117 if (rd_header)
1118 json_nroute = json_object_new_object();
1119 }
1120
1121 for (; pi; pi = pi->next) {
1122 total_count++;
1123 if (type == bgp_show_type_neighbor) {
1124 struct peer *peer = output_arg;
1125
1126 if (peer_cmp(peer, pi->peer) != 0)
1127 continue;
1128 }
1129 if (type == bgp_show_type_lcommunity_exact) {
1130 struct lcommunity *lcom = output_arg;
1131
1132 if (!pi->attr->lcommunity ||
1133 !lcommunity_cmp(
1134 pi->attr->lcommunity, lcom))
1135 continue;
1136 }
1137 if (type == bgp_show_type_lcommunity) {
1138 struct lcommunity *lcom = output_arg;
1139
1140 if (!pi->attr->lcommunity ||
1141 !lcommunity_match(
1142 pi->attr->lcommunity, lcom))
1143 continue;
1144 }
1145 if (type == bgp_show_type_community) {
1146 struct community *com = output_arg;
1147
1148 if (!pi->attr->community ||
1149 !community_match(
1150 pi->attr->community, com))
1151 continue;
1152 }
1153 if (type == bgp_show_type_community_exact) {
1154 struct community *com = output_arg;
1155
1156 if (!pi->attr->community ||
1157 !community_cmp(
1158 pi->attr->community, com))
1159 continue;
1160 }
1161 if (header) {
1162 if (use_json) {
1163 json_object_int_add(
1164 json, "bgpTableVersion",
1165 tbl_ver);
1166 json_object_string_add(
1167 json,
1168 "bgpLocalRouterId",
1169 inet_ntoa(
1170 bgp->router_id));
1171 json_object_int_add(
1172 json,
1173 "defaultLocPrf",
1174 bgp->default_local_pref);
1175 json_object_int_add(
1176 json, "localAS",
1177 bgp->as);
1178 } else {
1179 if (option == SHOW_DISPLAY_TAGS)
1180 vty_out(vty,
1181 V4_HEADER_TAG);
1182 else if (
1183 option
1184 == SHOW_DISPLAY_OVERLAY)
1185 vty_out(vty,
1186 V4_HEADER_OVERLAY);
1187 else {
1188 bgp_evpn_show_route_header(vty, bgp, tbl_ver, NULL);
1189 }
1190 }
1191 header = 0;
1192 }
1193 if (rd_header) {
1194 uint16_t type;
1195 struct rd_as rd_as;
1196 struct rd_ip rd_ip;
1197 uint8_t *pnt;
1198
1199 pnt = rn->p.u.val;
1200
1201 /* Decode RD type. */
1202 type = decode_rd_type(pnt);
1203 /* Decode RD value. */
1204 if (type == RD_TYPE_AS)
1205 decode_rd_as(pnt + 2, &rd_as);
1206 else if (type == RD_TYPE_AS4)
1207 decode_rd_as4(pnt + 2, &rd_as);
1208 else if (type == RD_TYPE_IP)
1209 decode_rd_ip(pnt + 2, &rd_ip);
1210 if (use_json) {
1211 if (type == RD_TYPE_AS
1212 || type == RD_TYPE_AS4)
1213 sprintf(rd_str, "%u:%d",
1214 rd_as.as,
1215 rd_as.val);
1216 else if (type == RD_TYPE_IP)
1217 sprintf(rd_str, "%s:%d",
1218 inet_ntoa(
1219 rd_ip.ip),
1220 rd_ip.val);
1221 json_object_string_add(
1222 json_nroute,
1223 "rd",
1224 rd_str);
1225
1226 } else {
1227 vty_out(vty,
1228 "Route Distinguisher: ");
1229 if (type == RD_TYPE_AS)
1230 vty_out(vty,
1231 "as2 %u:%d",
1232 rd_as.as,
1233 rd_as.val);
1234 else if (type == RD_TYPE_AS4)
1235 vty_out(vty,
1236 "as4 %u:%d",
1237 rd_as.as,
1238 rd_as.val);
1239 else if (type == RD_TYPE_IP)
1240 vty_out(vty, "ip %s:%d",
1241 inet_ntoa(
1242 rd_ip.ip),
1243 rd_ip.val);
1244 vty_out(vty, "\n\n");
1245 }
1246 rd_header = 0;
1247 }
1248
1249 if (option == SHOW_DISPLAY_TAGS)
1250 route_vty_out_tag(vty, &rm->p, pi,
1251 no_display, SAFI_EVPN,
1252 json_array);
1253 else if (option == SHOW_DISPLAY_OVERLAY)
1254 route_vty_out_overlay(vty, &rm->p, pi,
1255 no_display,
1256 json_array);
1257 else
1258 route_vty_out(vty, &rm->p, pi,
1259 no_display, SAFI_EVPN,
1260 json_array);
1261 no_display = 1;
1262 }
1263
1264 if (no_display)
1265 output_count++;
1266
1267 if (use_json) {
1268 json_object_object_add(json_prefix_info,
1269 "paths", json_array);
1270 json_object_object_add(json_nroute, buf,
1271 json_prefix_info);
1272 }
1273 }
1274
1275 if (use_json)
1276 json_object_object_add(json, rd_str, json_nroute);
1277 }
1278
1279 if (use_json) {
1280 json_object_int_add(json, "numPrefix", output_count);
1281 json_object_int_add(json, "totalPrefix", total_count);
1282 vty_out(vty, "%s\n", json_object_to_json_string_ext(
1283 json, JSON_C_TO_STRING_PRETTY));
1284 json_object_free(json);
1285 } else {
1286 if (output_count == 0)
1287 vty_out(vty, "No prefixes displayed, %ld exist\n",
1288 total_count);
1289 else
1290 vty_out(vty,
1291 "\nDisplayed %ld out of %ld total prefixes\n",
1292 output_count, total_count);
1293 }
1294 return CMD_SUCCESS;
1295 }
1296
1297 DEFUN(show_ip_bgp_l2vpn_evpn,
1298 show_ip_bgp_l2vpn_evpn_cmd,
1299 "show [ip] bgp l2vpn evpn [json]",
1300 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR)
1301 {
1302 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 0,
1303 use_json(argc, argv));
1304 }
1305
1306 DEFUN(show_ip_bgp_l2vpn_evpn_rd,
1307 show_ip_bgp_l2vpn_evpn_rd_cmd,
1308 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1309 SHOW_STR
1310 IP_STR
1311 BGP_STR
1312 L2VPN_HELP_STR
1313 EVPN_HELP_STR
1314 "Display information for a route distinguisher\n"
1315 "VPN Route Distinguisher\n" JSON_STR)
1316 {
1317 int idx_ext_community = 0;
1318 int ret;
1319 struct prefix_rd prd;
1320
1321 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1322
1323 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1324 if (!ret) {
1325 vty_out(vty, "%% Malformed Route Distinguisher\n");
1326 return CMD_WARNING;
1327 }
1328 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 0,
1329 use_json(argc, argv));
1330 }
1331
1332 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags,
1333 show_ip_bgp_l2vpn_evpn_all_tags_cmd,
1334 "show [ip] bgp l2vpn evpn all tags",
1335 SHOW_STR
1336 IP_STR
1337 BGP_STR
1338 L2VPN_HELP_STR
1339 EVPN_HELP_STR
1340 "Display information about all EVPN NLRIs\n"
1341 "Display BGP tags for prefixes\n")
1342 {
1343 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL, 1,
1344 0);
1345 }
1346
1347 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags,
1348 show_ip_bgp_l2vpn_evpn_rd_tags_cmd,
1349 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1350 SHOW_STR
1351 IP_STR
1352 BGP_STR
1353 L2VPN_HELP_STR
1354 EVPN_HELP_STR
1355 "Display information for a route distinguisher\n"
1356 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1357 {
1358 int idx_ext_community = 0;
1359 int ret;
1360 struct prefix_rd prd;
1361
1362 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1363
1364 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1365 if (!ret) {
1366 vty_out(vty, "%% Malformed Route Distinguisher\n");
1367 return CMD_WARNING;
1368 }
1369 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL, 1,
1370 0);
1371 }
1372
1373 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes,
1374 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd,
1375 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1376 SHOW_STR
1377 IP_STR
1378 BGP_STR
1379 L2VPN_HELP_STR
1380 EVPN_HELP_STR
1381 "Detailed information on TCP and BGP neighbor connections\n"
1382 "IPv4 Neighbor to display information about\n"
1383 "IPv6 Neighbor to display information about\n"
1384 "Neighbor on BGP configured interface\n"
1385 "Display routes learned from neighbor\n" JSON_STR)
1386 {
1387 int idx = 0;
1388 struct peer *peer;
1389 char *peerstr = NULL;
1390 bool uj = use_json(argc, argv);
1391 afi_t afi = AFI_L2VPN;
1392 safi_t safi = SAFI_EVPN;
1393 struct bgp *bgp = NULL;
1394
1395 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1396 &bgp, uj);
1397 if (!idx) {
1398 vty_out(vty, "No index\n");
1399 return CMD_WARNING;
1400 }
1401
1402 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1403 argv_find(argv, argc, "neighbors", &idx);
1404 peerstr = argv[++idx]->arg;
1405
1406 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1407 if (!peer) {
1408 if (uj) {
1409 json_object *json_no = NULL;
1410 json_no = json_object_new_object();
1411 json_object_string_add(json_no, "warning",
1412 "Malformed address");
1413 vty_out(vty, "%s\n",
1414 json_object_to_json_string(json_no));
1415 json_object_free(json_no);
1416 } else
1417 vty_out(vty, "Malformed address: %s\n",
1418 argv[idx]->arg);
1419 return CMD_WARNING;
1420 }
1421 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1422 if (uj) {
1423 json_object *json_no = NULL;
1424 json_no = json_object_new_object();
1425 json_object_string_add(
1426 json_no, "warning",
1427 "No such neighbor or address family");
1428 vty_out(vty, "%s\n",
1429 json_object_to_json_string(json_no));
1430 json_object_free(json_no);
1431 } else
1432 vty_out(vty, "%% No such neighbor or address family\n");
1433 return CMD_WARNING;
1434 }
1435
1436 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_neighbor, peer, 0,
1437 uj);
1438 }
1439
1440 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes,
1441 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd,
1442 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1443 SHOW_STR
1444 IP_STR
1445 BGP_STR
1446 L2VPN_HELP_STR
1447 EVPN_HELP_STR
1448 "Display information for a route distinguisher\n"
1449 "VPN Route Distinguisher\n"
1450 "Detailed information on TCP and BGP neighbor connections\n"
1451 "IPv4 Neighbor to display information about\n"
1452 "IPv6 Neighbor to display information about\n"
1453 "Neighbor on BGP configured interface\n"
1454 "Display routes learned from neighbor\n" JSON_STR)
1455 {
1456 int idx_ext_community = 0;
1457 int idx = 0;
1458 int ret;
1459 struct peer *peer;
1460 char *peerstr = NULL;
1461 struct prefix_rd prd;
1462 bool uj = use_json(argc, argv);
1463 afi_t afi = AFI_L2VPN;
1464 safi_t safi = SAFI_EVPN;
1465 struct bgp *bgp = NULL;
1466
1467 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1468 &bgp, uj);
1469 if (!idx) {
1470 vty_out(vty, "No index\n");
1471 return CMD_WARNING;
1472 }
1473
1474 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1475 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1476 if (!ret) {
1477 if (uj) {
1478 json_object *json_no = NULL;
1479 json_no = json_object_new_object();
1480 json_object_string_add(json_no, "warning",
1481 "Malformed Route Distinguisher");
1482 vty_out(vty, "%s\n",
1483 json_object_to_json_string(json_no));
1484 json_object_free(json_no);
1485 } else
1486 vty_out(vty, "%% Malformed Route Distinguisher\n");
1487 return CMD_WARNING;
1488 }
1489
1490 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1491 argv_find(argv, argc, "neighbors", &idx);
1492 peerstr = argv[++idx]->arg;
1493
1494 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1495 if (!peer) {
1496 if (uj) {
1497 json_object *json_no = NULL;
1498 json_no = json_object_new_object();
1499 json_object_string_add(json_no, "warning",
1500 "Malformed address");
1501 vty_out(vty, "%s\n",
1502 json_object_to_json_string(json_no));
1503 json_object_free(json_no);
1504 } else
1505 vty_out(vty, "Malformed address: %s\n",
1506 argv[idx]->arg);
1507 return CMD_WARNING;
1508 }
1509 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1510 if (uj) {
1511 json_object *json_no = NULL;
1512 json_no = json_object_new_object();
1513 json_object_string_add(
1514 json_no, "warning",
1515 "No such neighbor or address family");
1516 vty_out(vty, "%s\n",
1517 json_object_to_json_string(json_no));
1518 json_object_free(json_no);
1519 } else
1520 vty_out(vty, "%% No such neighbor or address family\n");
1521 return CMD_WARNING;
1522 }
1523
1524 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_neighbor, peer, 0,
1525 uj);
1526 }
1527
1528 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes,
1529 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd,
1530 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1531 SHOW_STR
1532 IP_STR
1533 BGP_STR
1534 L2VPN_HELP_STR
1535 EVPN_HELP_STR
1536 "Detailed information on TCP and BGP neighbor connections\n"
1537 "IPv4 Neighbor to display information about\n"
1538 "IPv6 Neighbor to display information about\n"
1539 "Neighbor on BGP configured interface\n"
1540 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1541 {
1542 int idx = 0;
1543 struct peer *peer;
1544 bool uj = use_json(argc, argv);
1545 struct bgp *bgp = NULL;
1546 afi_t afi = AFI_L2VPN;
1547 safi_t safi = SAFI_EVPN;
1548 char *peerstr = NULL;
1549
1550 if (uj)
1551 argc--;
1552
1553 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1554 &bgp, uj);
1555 if (!idx) {
1556 vty_out(vty, "No index\n");
1557 return CMD_WARNING;
1558 }
1559
1560 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1561 argv_find(argv, argc, "neighbors", &idx);
1562 peerstr = argv[++idx]->arg;
1563
1564 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1565 if (!peer) {
1566 if (uj) {
1567 json_object *json_no = NULL;
1568 json_no = json_object_new_object();
1569 json_object_string_add(json_no, "warning",
1570 "Malformed address");
1571 vty_out(vty, "%s\n",
1572 json_object_to_json_string(json_no));
1573 json_object_free(json_no);
1574 } else
1575 vty_out(vty, "Malformed address: %s\n",
1576 argv[idx]->arg);
1577 return CMD_WARNING;
1578 }
1579 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1580 if (uj) {
1581 json_object *json_no = NULL;
1582 json_no = json_object_new_object();
1583 json_object_string_add(
1584 json_no, "warning",
1585 "No such neighbor or address family");
1586 vty_out(vty, "%s\n",
1587 json_object_to_json_string(json_no));
1588 json_object_free(json_no);
1589 } else
1590 vty_out(vty, "%% No such neighbor or address family\n");
1591 return CMD_WARNING;
1592 }
1593
1594 return show_adj_route_vpn(vty, peer, NULL, AFI_L2VPN, SAFI_EVPN, uj);
1595 }
1596
1597 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes,
1598 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd,
1599 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-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 "Detailed information on TCP and BGP neighbor connections\n"
1608 "IPv4 Neighbor to display information about\n"
1609 "IPv6 Neighbor to display information about\n"
1610 "Neighbor on BGP configured interface\n"
1611 "Display the routes advertised to a BGP neighbor\n" JSON_STR)
1612 {
1613 int idx_ext_community = 0;
1614 int idx = 0;
1615 int ret;
1616 struct peer *peer;
1617 struct prefix_rd prd;
1618 struct bgp *bgp = NULL;
1619 bool uj = use_json(argc, argv);
1620 char *peerstr = NULL;
1621 afi_t afi = AFI_L2VPN;
1622 safi_t safi = SAFI_EVPN;
1623
1624 if (uj)
1625 argc--;
1626
1627 if (uj)
1628 argc--;
1629
1630 bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
1631 &bgp, uj);
1632 if (!idx) {
1633 vty_out(vty, "No index\n");
1634 return CMD_WARNING;
1635 }
1636
1637 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1638
1639 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1640 argv_find(argv, argc, "neighbors", &idx);
1641 peerstr = argv[++idx]->arg;
1642
1643 peer = peer_lookup_in_view(vty, bgp, peerstr, uj);
1644 if (!peer) {
1645 if (uj) {
1646 json_object *json_no = NULL;
1647 json_no = json_object_new_object();
1648 json_object_string_add(json_no, "warning",
1649 "Malformed address");
1650 vty_out(vty, "%s\n",
1651 json_object_to_json_string(json_no));
1652 json_object_free(json_no);
1653 } else
1654 vty_out(vty, "Malformed address: %s\n",
1655 argv[idx]->arg);
1656 return CMD_WARNING;
1657 }
1658 if (!peer || !peer->afc[AFI_L2VPN][SAFI_EVPN]) {
1659 if (uj) {
1660 json_object *json_no = NULL;
1661 json_no = json_object_new_object();
1662 json_object_string_add(
1663 json_no, "warning",
1664 "No such neighbor or address family");
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, "%% No such neighbor or address family\n");
1670 return CMD_WARNING;
1671 }
1672
1673 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1674 if (!ret) {
1675 if (uj) {
1676 json_object *json_no = NULL;
1677 json_no = json_object_new_object();
1678 json_object_string_add(json_no, "warning",
1679 "Malformed Route Distinguisher");
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, "%% Malformed Route Distinguisher\n");
1685 return CMD_WARNING;
1686 }
1687
1688 return show_adj_route_vpn(vty, peer, &prd, AFI_L2VPN, SAFI_EVPN, uj);
1689 }
1690
1691 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay,
1692 show_ip_bgp_l2vpn_evpn_all_overlay_cmd,
1693 "show [ip] bgp l2vpn evpn all overlay [json]",
1694 SHOW_STR
1695 IP_STR
1696 BGP_STR
1697 L2VPN_HELP_STR
1698 EVPN_HELP_STR
1699 "Display information about all EVPN NLRIs\n"
1700 "Display BGP Overlay Information for prefixes\n"
1701 JSON_STR)
1702 {
1703 return bgp_show_ethernet_vpn(vty, NULL, bgp_show_type_normal, NULL,
1704 SHOW_DISPLAY_OVERLAY,
1705 use_json(argc, argv));
1706 }
1707
1708 DEFUN(show_ip_bgp_evpn_rd_overlay,
1709 show_ip_bgp_evpn_rd_overlay_cmd,
1710 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1711 SHOW_STR
1712 IP_STR
1713 BGP_STR
1714 L2VPN_HELP_STR
1715 EVPN_HELP_STR
1716 "Display information for a route distinguisher\n"
1717 "VPN Route Distinguisher\n"
1718 "Display BGP Overlay Information for prefixes\n")
1719 {
1720 int idx_ext_community = 0;
1721 int ret;
1722 struct prefix_rd prd;
1723
1724 argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community);
1725
1726 ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
1727 if (!ret) {
1728 vty_out(vty, "%% Malformed Route Distinguisher\n");
1729 return CMD_WARNING;
1730 }
1731 return bgp_show_ethernet_vpn(vty, &prd, bgp_show_type_normal, NULL,
1732 SHOW_DISPLAY_OVERLAY,
1733 use_json(argc, argv));
1734 }
1735
1736 DEFUN(show_bgp_l2vpn_evpn_com,
1737 show_bgp_l2vpn_evpn_com_cmd,
1738 "show bgp l2vpn evpn \
1739 <community AA:NN|large-community AA:BB:CC> \
1740 [exact-match] [json]",
1741 SHOW_STR
1742 BGP_STR
1743 L2VPN_HELP_STR
1744 EVPN_HELP_STR
1745 "Display routes matching the community\n"
1746 "Community number where AA and NN are (0-65535)\n"
1747 "Display routes matching the large-community\n"
1748 "List of large-community numbers\n"
1749 "Exact match of the communities\n"
1750 JSON_STR)
1751 {
1752 int idx = 0;
1753 int ret = 0;
1754 const char *clist_number_or_name;
1755 int show_type = bgp_show_type_normal;
1756 struct community *com;
1757 struct lcommunity *lcom;
1758
1759 if (argv_find(argv, argc, "large-community", &idx)) {
1760 clist_number_or_name = argv[++idx]->arg;
1761 show_type = bgp_show_type_lcommunity;
1762
1763 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1764 show_type = bgp_show_type_lcommunity_exact;
1765
1766 lcom = lcommunity_str2com(clist_number_or_name);
1767 if (!lcom) {
1768 vty_out(vty, "%% Large-community malformed\n");
1769 return CMD_WARNING;
1770 }
1771
1772 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, lcom,
1773 SHOW_DISPLAY_STANDARD,
1774 use_json(argc, argv));
1775
1776 lcommunity_free(&lcom);
1777 } else if (argv_find(argv, argc, "community", &idx)) {
1778 clist_number_or_name = argv[++idx]->arg;
1779 show_type = bgp_show_type_community;
1780
1781 if (++idx < argc && strmatch(argv[idx]->text, "exact-match"))
1782 show_type = bgp_show_type_community_exact;
1783
1784 com = community_str2com(clist_number_or_name);
1785
1786 if (!com) {
1787 vty_out(vty, "%% Community malformed: %s\n",
1788 clist_number_or_name);
1789 return CMD_WARNING;
1790 }
1791
1792 ret = bgp_show_ethernet_vpn(vty, NULL, show_type, com,
1793 SHOW_DISPLAY_STANDARD,
1794 use_json(argc, argv));
1795 community_free(&com);
1796 }
1797
1798 return ret;
1799 }
1800
1801 /* For testing purpose, static route of EVPN RT-5. */
1802 DEFUN(evpnrt5_network,
1803 evpnrt5_network_cmd,
1804 "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 WORD]",
1805 "Specify a network to announce via BGP\n"
1806 "IP prefix\n"
1807 "IPv6 prefix\n"
1808 "Specify Route Distinguisher\n"
1809 "VPN Route Distinguisher\n"
1810 "Ethernet Tag\n"
1811 "Ethernet Tag Value\n"
1812 "BGP label\n"
1813 "label value\n"
1814 "Ethernet Segment Identifier\n"
1815 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1816 "Gateway IP\n"
1817 "Gateway IP ( A.B.C.D )\n"
1818 "Gateway IPv6 ( X:X::X:X )\n"
1819 "Router Mac Ext Comm\n"
1820 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1821 "Route-map to modify the attributes\n"
1822 "Name of the route map\n")
1823 {
1824 int idx_ipv4_prefixlen = 1;
1825 int idx_route_distinguisher = 3;
1826 int idx_label = 7;
1827 int idx_esi = 9;
1828 int idx_gwip = 11;
1829 int idx_ethtag = 5;
1830 int idx_routermac = 13;
1831
1832 return bgp_static_set_safi(
1833 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1834 argv[idx_route_distinguisher]->arg, argv[idx_label]->arg, NULL,
1835 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1836 argv[idx_gwip]->arg, argv[idx_ethtag]->arg,
1837 argv[idx_routermac]->arg);
1838 }
1839
1840 /* For testing purpose, static route of EVPN RT-5. */
1841 DEFUN(no_evpnrt5_network,
1842 no_evpnrt5_network_cmd,
1843 "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>",
1844 NO_STR
1845 "Specify a network to announce via BGP\n"
1846 "IP prefix\n"
1847 "IPv6 prefix\n"
1848 "Specify Route Distinguisher\n"
1849 "VPN Route Distinguisher\n"
1850 "Ethernet Tag\n"
1851 "Ethernet Tag Value\n"
1852 "BGP label\n"
1853 "label value\n"
1854 "Ethernet Segment Identifier\n"
1855 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1856 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1857 {
1858 int idx_ipv4_prefixlen = 2;
1859 int idx_ext_community = 4;
1860 int idx_label = 8;
1861 int idx_ethtag = 6;
1862 int idx_esi = 10;
1863 int idx_gwip = 12;
1864 return bgp_static_unset_safi(
1865 AFI_L2VPN, SAFI_EVPN, vty, argv[idx_ipv4_prefixlen]->arg,
1866 argv[idx_ext_community]->arg, argv[idx_label]->arg,
1867 BGP_EVPN_IP_PREFIX_ROUTE, argv[idx_esi]->arg,
1868 argv[idx_gwip]->arg, argv[idx_ethtag]->arg);
1869 }
1870
1871 static void evpn_import_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1872 {
1873 evpn_rt_delete_auto(bgp, vpn->vni, vpn->import_rtl);
1874 }
1875
1876 static void evpn_export_rt_delete_auto(struct bgp *bgp, struct bgpevpn *vpn)
1877 {
1878 evpn_rt_delete_auto(bgp, vpn->vni, vpn->export_rtl);
1879 }
1880
1881 /*
1882 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1883 * check that this is a change.
1884 */
1885 static void evpn_configure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1886 struct ecommunity *ecomadd)
1887 {
1888 /* If the VNI is "live", we need to uninstall routes using the current
1889 * import RT(s) first before we update the import RT, and subsequently
1890 * install routes.
1891 */
1892 if (is_vni_live(vpn))
1893 bgp_evpn_uninstall_routes(bgp, vpn);
1894
1895 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1896 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1897
1898 /* If the auto route-target is in use we must remove it */
1899 evpn_import_rt_delete_auto(bgp, vpn);
1900
1901 /* Add new RT and rebuild the RT to VNI mapping */
1902 listnode_add_sort(vpn->import_rtl, ecomadd);
1903
1904 SET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1905 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1906
1907 /* Install routes that match new import RT */
1908 if (is_vni_live(vpn))
1909 bgp_evpn_install_routes(bgp, vpn);
1910 }
1911
1912 /*
1913 * Unconfigure Import RT(s) for a VNI (vty handler).
1914 */
1915 static void evpn_unconfigure_import_rt(struct bgp *bgp, struct bgpevpn *vpn,
1916 struct ecommunity *ecomdel)
1917 {
1918 struct listnode *node, *nnode, *node_to_del;
1919 struct ecommunity *ecom;
1920
1921 /* Along the lines of "configure" except we have to reset to the
1922 * automatic value.
1923 */
1924 if (is_vni_live(vpn))
1925 bgp_evpn_uninstall_routes(bgp, vpn);
1926
1927 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1928 bgp_evpn_unmap_vni_from_its_rts(bgp, vpn);
1929
1930 /* Delete all import RTs */
1931 if (ecomdel == NULL) {
1932 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1933 ecommunity_free(&ecom);
1934 list_delete_node(vpn->import_rtl, node);
1935 }
1936 }
1937
1938 /* Delete a specific import RT */
1939 else {
1940 node_to_del = NULL;
1941
1942 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
1943 if (ecommunity_match(ecom, ecomdel)) {
1944 ecommunity_free(&ecom);
1945 node_to_del = node;
1946 break;
1947 }
1948 }
1949
1950 if (node_to_del)
1951 list_delete_node(vpn->import_rtl, node_to_del);
1952 }
1953
1954 assert(vpn->import_rtl);
1955 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1956 if (list_isempty(vpn->import_rtl)) {
1957 UNSET_FLAG(vpn->flags, VNI_FLAG_IMPRT_CFGD);
1958 bgp_evpn_derive_auto_rt_import(bgp, vpn);
1959 }
1960 /* Rebuild the RT to VNI mapping */
1961 else
1962 bgp_evpn_map_vni_to_its_rts(bgp, vpn);
1963
1964 /* Install routes that match new import RT */
1965 if (is_vni_live(vpn))
1966 bgp_evpn_install_routes(bgp, vpn);
1967 }
1968
1969 /*
1970 * Configure the Export RT for a VNI (vty handler). Caller expected to
1971 * check that this is a change. Note that only a single export RT is
1972 * allowed for a VNI and any change to configuration is implemented as
1973 * a "replace" (similar to other configuration).
1974 */
1975 static void evpn_configure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1976 struct ecommunity *ecomadd)
1977 {
1978 /* If the auto route-target is in use we must remove it */
1979 evpn_export_rt_delete_auto(bgp, vpn);
1980
1981 listnode_add_sort(vpn->export_rtl, ecomadd);
1982 SET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
1983
1984 if (is_vni_live(vpn))
1985 bgp_evpn_handle_export_rt_change(bgp, vpn);
1986 }
1987
1988 /*
1989 * Unconfigure the Export RT for a VNI (vty handler)
1990 */
1991 static void evpn_unconfigure_export_rt(struct bgp *bgp, struct bgpevpn *vpn,
1992 struct ecommunity *ecomdel)
1993 {
1994 struct listnode *node, *nnode, *node_to_del;
1995 struct ecommunity *ecom;
1996
1997 /* Delete all export RTs */
1998 if (ecomdel == NULL) {
1999 /* Reset to default and process all routes. */
2000 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2001 ecommunity_free(&ecom);
2002 list_delete_node(vpn->export_rtl, node);
2003 }
2004 }
2005
2006 /* Delete a specific export RT */
2007 else {
2008 node_to_del = NULL;
2009
2010 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode, ecom)) {
2011 if (ecommunity_match(ecom, ecomdel)) {
2012 ecommunity_free(&ecom);
2013 node_to_del = node;
2014 break;
2015 }
2016 }
2017
2018 if (node_to_del)
2019 list_delete_node(vpn->export_rtl, node_to_del);
2020 }
2021
2022 assert(vpn->export_rtl);
2023 if (list_isempty(vpn->export_rtl)) {
2024 UNSET_FLAG(vpn->flags, VNI_FLAG_EXPRT_CFGD);
2025 bgp_evpn_derive_auto_rt_export(bgp, vpn);
2026 }
2027
2028 if (is_vni_live(vpn))
2029 bgp_evpn_handle_export_rt_change(bgp, vpn);
2030 }
2031
2032 /*
2033 * Configure RD for VRF
2034 */
2035 static void evpn_configure_vrf_rd(struct bgp *bgp_vrf, struct prefix_rd *rd)
2036 {
2037 /* If we have already advertise type-5 routes with a diffrent RD, we
2038 * have to delete and withdraw them firs
2039 */
2040 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2041
2042 /* update RD */
2043 memcpy(&bgp_vrf->vrf_prd, rd, sizeof(struct prefix_rd));
2044 SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2045
2046 /* We have a new RD for VRF.
2047 * Advertise all type-5 routes again with the new RD
2048 */
2049 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2050 }
2051
2052 /*
2053 * Unconfigure RD for VRF
2054 */
2055 static void evpn_unconfigure_vrf_rd(struct bgp *bgp_vrf)
2056 {
2057 /* If we have already advertise type-5 routes with a diffrent RD, we
2058 * have to delete and withdraw them firs
2059 */
2060 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 1);
2061
2062 /* fall back to default RD */
2063 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf);
2064 UNSET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_RD_CFGD);
2065
2066 /* We have a new RD for VRF.
2067 * Advertise all type-5 routes again with the new RD
2068 */
2069 bgp_evpn_handle_vrf_rd_change(bgp_vrf, 0);
2070 }
2071
2072 /*
2073 * Configure RD for a VNI (vty handler)
2074 */
2075 static void evpn_configure_rd(struct bgp *bgp, struct bgpevpn *vpn,
2076 struct prefix_rd *rd)
2077 {
2078 /* If the VNI is "live", we need to delete and withdraw this VNI's
2079 * local routes with the prior RD first. Then, after updating RD,
2080 * need to re-advertise.
2081 */
2082 if (is_vni_live(vpn))
2083 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2084
2085 /* update RD */
2086 memcpy(&vpn->prd, rd, sizeof(struct prefix_rd));
2087 SET_FLAG(vpn->flags, VNI_FLAG_RD_CFGD);
2088
2089 if (is_vni_live(vpn))
2090 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2091 }
2092
2093 /*
2094 * Unconfigure RD for a VNI (vty handler)
2095 */
2096 static void evpn_unconfigure_rd(struct bgp *bgp, struct bgpevpn *vpn)
2097 {
2098 /* If the VNI is "live", we need to delete and withdraw this VNI's
2099 * local routes with the prior RD first. Then, after resetting RD
2100 * to automatic value, need to re-advertise.
2101 */
2102 if (is_vni_live(vpn))
2103 bgp_evpn_handle_rd_change(bgp, vpn, 1);
2104
2105 /* reset RD to default */
2106 bgp_evpn_derive_auto_rd(bgp, vpn);
2107
2108 if (is_vni_live(vpn))
2109 bgp_evpn_handle_rd_change(bgp, vpn, 0);
2110 }
2111
2112 /*
2113 * Create VNI, if not already present (VTY handler). Mark as configured.
2114 */
2115 static struct bgpevpn *evpn_create_update_vni(struct bgp *bgp, vni_t vni)
2116 {
2117 struct bgpevpn *vpn;
2118 struct in_addr mcast_grp = {INADDR_ANY};
2119
2120 if (!bgp->vnihash)
2121 return NULL;
2122
2123 vpn = bgp_evpn_lookup_vni(bgp, vni);
2124 if (!vpn) {
2125 /* Check if this L2VNI is already configured as L3VNI */
2126 if (bgp_evpn_lookup_l3vni_l2vni_table(vni)) {
2127 flog_err(
2128 EC_BGP_VNI,
2129 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2130 bgp->vrf_id, vni);
2131 return NULL;
2132 }
2133
2134 /* tenant vrf will be updated when we get local_vni_add from
2135 * zebra
2136 */
2137 vpn = bgp_evpn_new(bgp, vni, bgp->router_id, 0, mcast_grp);
2138 if (!vpn) {
2139 flog_err(
2140 EC_BGP_VNI,
2141 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2142 bgp->vrf_id, vni);
2143 return NULL;
2144 }
2145 }
2146
2147 /* Mark as configured. */
2148 SET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2149 return vpn;
2150 }
2151
2152 /*
2153 * Delete VNI. If VNI does not exist in the system (i.e., just
2154 * configuration), all that is needed is to free it. Otherwise,
2155 * any parameters configured for the VNI need to be reset (with
2156 * appropriate action) and the VNI marked as unconfigured; the
2157 * VNI will continue to exist, purely as a "learnt" entity.
2158 */
2159 static int evpn_delete_vni(struct bgp *bgp, struct bgpevpn *vpn)
2160 {
2161 assert(bgp->vnihash);
2162
2163 if (!is_vni_live(vpn)) {
2164 bgp_evpn_free(bgp, vpn);
2165 return 0;
2166 }
2167
2168 /* We need to take the unconfigure action for each parameter of this VNI
2169 * that is configured. Some optimization is possible, but not worth the
2170 * additional code for an operation that should be pretty rare.
2171 */
2172 UNSET_FLAG(vpn->flags, VNI_FLAG_CFGD);
2173
2174 /* First, deal with the export side - RD and export RT changes. */
2175 if (is_rd_configured(vpn))
2176 evpn_unconfigure_rd(bgp, vpn);
2177 if (is_export_rt_configured(vpn))
2178 evpn_unconfigure_export_rt(bgp, vpn, NULL);
2179
2180 /* Next, deal with the import side. */
2181 if (is_import_rt_configured(vpn))
2182 evpn_unconfigure_import_rt(bgp, vpn, NULL);
2183
2184 return 0;
2185 }
2186
2187 /*
2188 * Display import RT mapping to VRFs (vty handler)
2189 * bgp_evpn: evpn bgp instance
2190 */
2191 static void evpn_show_vrf_import_rts(struct vty *vty, struct bgp *bgp_evpn,
2192 json_object *json)
2193 {
2194 void *args[2];
2195
2196 args[0] = vty;
2197 args[1] = json;
2198
2199 hash_iterate(bgp_evpn->vrf_import_rt_hash,
2200 (void (*)(struct hash_bucket *,
2201 void *))show_vrf_import_rt_entry,
2202 args);
2203 }
2204
2205 /*
2206 * Display import RT mapping to VNIs (vty handler)
2207 */
2208 static void evpn_show_import_rts(struct vty *vty, struct bgp *bgp,
2209 json_object *json)
2210 {
2211 void *args[2];
2212
2213 args[0] = vty;
2214 args[1] = json;
2215
2216 hash_iterate(
2217 bgp->import_rt_hash,
2218 (void (*)(struct hash_bucket *, void *))show_import_rt_entry,
2219 args);
2220 }
2221
2222 /*
2223 * Display EVPN routes for all VNIs - vty handler.
2224 */
2225 static void evpn_show_routes_vni_all(struct vty *vty, struct bgp *bgp,
2226 struct in_addr vtep_ip, json_object *json,
2227 int detail)
2228 {
2229 uint32_t num_vnis;
2230 struct vni_walk_ctx wctx;
2231
2232 num_vnis = hashcount(bgp->vnihash);
2233 if (!num_vnis)
2234 return;
2235 memset(&wctx, 0, sizeof(struct vni_walk_ctx));
2236 wctx.bgp = bgp;
2237 wctx.vty = vty;
2238 wctx.vtep_ip = vtep_ip;
2239 wctx.json = json;
2240 wctx.detail = detail;
2241 hash_iterate(bgp->vnihash, (void (*)(struct hash_bucket *,
2242 void *))show_vni_routes_hash,
2243 &wctx);
2244 }
2245
2246 /*
2247 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2248 */
2249 static void evpn_show_route_vni_multicast(struct vty *vty, struct bgp *bgp,
2250 vni_t vni, struct in_addr orig_ip,
2251 json_object *json)
2252 {
2253 struct bgpevpn *vpn;
2254 struct prefix_evpn p;
2255 struct bgp_node *rn;
2256 struct bgp_path_info *pi;
2257 uint32_t path_cnt = 0;
2258 afi_t afi;
2259 safi_t safi;
2260 json_object *json_paths = NULL;
2261
2262 afi = AFI_L2VPN;
2263 safi = SAFI_EVPN;
2264
2265 /* Locate VNI. */
2266 vpn = bgp_evpn_lookup_vni(bgp, vni);
2267 if (!vpn) {
2268 vty_out(vty, "VNI not found\n");
2269 return;
2270 }
2271
2272 /* See if route exists. */
2273 build_evpn_type3_prefix(&p, orig_ip);
2274 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2275 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2276 if (!json)
2277 vty_out(vty, "%% Network not in table\n");
2278 return;
2279 }
2280
2281 if (json)
2282 json_paths = json_object_new_array();
2283
2284 /* Prefix and num paths displayed once per prefix. */
2285 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2286
2287 /* Display each path for this prefix. */
2288 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2289 json_object *json_path = NULL;
2290
2291 if (json)
2292 json_path = json_object_new_array();
2293
2294 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2295 json_path);
2296
2297 if (json)
2298 json_object_array_add(json_paths, json_path);
2299
2300 path_cnt++;
2301 }
2302
2303 if (json) {
2304 if (path_cnt)
2305 json_object_object_add(json, "paths", json_paths);
2306
2307 json_object_int_add(json, "numPaths", path_cnt);
2308 } else {
2309 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2310 path_cnt);
2311 }
2312 }
2313
2314 /*
2315 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2316 * By definition, only matching type-2 route will be displayed.
2317 */
2318 static void evpn_show_route_vni_macip(struct vty *vty, struct bgp *bgp,
2319 vni_t vni, struct ethaddr *mac,
2320 struct ipaddr *ip, json_object *json)
2321 {
2322 struct bgpevpn *vpn;
2323 struct prefix_evpn p;
2324 struct bgp_node *rn;
2325 struct bgp_path_info *pi;
2326 uint32_t path_cnt = 0;
2327 afi_t afi;
2328 safi_t safi;
2329 json_object *json_paths = NULL;
2330
2331 afi = AFI_L2VPN;
2332 safi = SAFI_EVPN;
2333
2334 /* Locate VNI. */
2335 vpn = bgp_evpn_lookup_vni(bgp, vni);
2336 if (!vpn) {
2337 if (!json)
2338 vty_out(vty, "VNI not found\n");
2339 return;
2340 }
2341
2342 /* See if route exists. Look for both non-sticky and sticky. */
2343 build_evpn_type2_prefix(&p, mac, ip);
2344 rn = bgp_node_lookup(vpn->route_table, (struct prefix *)&p);
2345 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2346 if (!json)
2347 vty_out(vty, "%% Network not in table\n");
2348 return;
2349 }
2350
2351 if (json)
2352 json_paths = json_object_new_array();
2353
2354 /* Prefix and num paths displayed once per prefix. */
2355 route_vty_out_detail_header(vty, bgp, rn, NULL, afi, safi, json);
2356
2357 /* Display each path for this prefix. */
2358 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2359 json_object *json_path = NULL;
2360
2361 if (json)
2362 json_path = json_object_new_array();
2363
2364 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2365 json_path);
2366
2367 if (json)
2368 json_object_array_add(json_paths, json_path);
2369
2370 path_cnt++;
2371 }
2372
2373 if (json) {
2374 if (path_cnt)
2375 json_object_object_add(json, "paths", json_paths);
2376
2377 json_object_int_add(json, "numPaths", path_cnt);
2378 } else {
2379 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2380 path_cnt);
2381 }
2382 }
2383
2384 /* Disaplay EVPN routes for a ESI - VTY handler */
2385 static void evpn_show_routes_esi(struct vty *vty, struct bgp *bgp,
2386 esi_t *esi, json_object *json)
2387 {
2388 struct evpnes *es = NULL;
2389
2390 /* locate the ES */
2391 es = bgp_evpn_lookup_es(bgp, esi);
2392 if (!es) {
2393 if (!json)
2394 vty_out(vty, "ESI not found\n");
2395 return;
2396 }
2397
2398 show_esi_routes(bgp, es, vty, json);
2399 }
2400
2401 /*
2402 * Display EVPN routes for a VNI - vty handler.
2403 * If 'type' is non-zero, only routes matching that type are shown.
2404 * If the vtep_ip is non zero, only routes behind that vtep are shown
2405 */
2406 static void evpn_show_routes_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2407 int type, struct in_addr vtep_ip,
2408 json_object *json)
2409 {
2410 struct bgpevpn *vpn;
2411
2412 /* Locate VNI. */
2413 vpn = bgp_evpn_lookup_vni(bgp, vni);
2414 if (!vpn) {
2415 if (!json)
2416 vty_out(vty, "VNI not found\n");
2417 return;
2418 }
2419
2420 /* Walk this VNI's route table and display appropriate routes. */
2421 show_vni_routes(bgp, vpn, type, vty, vtep_ip, json, 0);
2422 }
2423
2424 /*
2425 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2426 * IP (vty handler). By definition, only matching type-2 route will be
2427 * displayed.
2428 */
2429 static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
2430 struct prefix_rd *prd, struct ethaddr *mac,
2431 struct ipaddr *ip, json_object *json)
2432 {
2433 struct prefix_evpn p;
2434 struct bgp_node *rn;
2435 struct bgp_path_info *pi;
2436 afi_t afi;
2437 safi_t safi;
2438 uint32_t path_cnt = 0;
2439 json_object *json_paths = NULL;
2440 char prefix_str[BUFSIZ];
2441
2442 afi = AFI_L2VPN;
2443 safi = SAFI_EVPN;
2444
2445 /* See if route exists. Look for both non-sticky and sticky. */
2446 build_evpn_type2_prefix(&p, mac, ip);
2447 rn = bgp_afi_node_lookup(bgp->rib[afi][safi], afi, safi,
2448 (struct prefix *)&p, prd);
2449 if (!rn || !bgp_node_has_bgp_path_info_data(rn)) {
2450 if (!json)
2451 vty_out(vty, "%% Network not in table\n");
2452 return;
2453 }
2454
2455 bgp_evpn_route2str((struct prefix_evpn *)&p, prefix_str,
2456 sizeof(prefix_str));
2457
2458 /* Prefix and num paths displayed once per prefix. */
2459 route_vty_out_detail_header(vty, bgp, rn, prd, afi, safi, json);
2460
2461 if (json)
2462 json_paths = json_object_new_array();
2463
2464 /* Display each path for this prefix. */
2465 for (pi = bgp_node_get_bgp_path_info(rn); pi; pi = pi->next) {
2466 json_object *json_path = NULL;
2467
2468 if (json)
2469 json_path = json_object_new_array();
2470
2471 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2472 json_path);
2473
2474 if (json)
2475 json_object_array_add(json_paths, json_path);
2476
2477 path_cnt++;
2478 }
2479
2480 if (json && path_cnt) {
2481 if (path_cnt)
2482 json_object_object_add(json, prefix_str, json_paths);
2483 json_object_int_add(json, "numPaths", path_cnt);
2484 } else {
2485 vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
2486 path_cnt);
2487 }
2488 }
2489
2490 /*
2491 * Display BGP EVPN routing table -- for specific RD (vty handler)
2492 * If 'type' is non-zero, only routes matching that type are shown.
2493 */
2494 static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
2495 struct prefix_rd *prd, int type,
2496 json_object *json)
2497 {
2498 struct bgp_node *rd_rn;
2499 struct bgp_table *table;
2500 struct bgp_node *rn;
2501 struct bgp_path_info *pi;
2502 int rd_header = 1;
2503 afi_t afi;
2504 safi_t safi;
2505 uint32_t prefix_cnt, path_cnt;
2506 char rd_str[RD_ADDRSTRLEN];
2507 json_object *json_rd = NULL;
2508 int add_rd_to_json = 0;
2509
2510 afi = AFI_L2VPN;
2511 safi = SAFI_EVPN;
2512 prefix_cnt = path_cnt = 0;
2513
2514 prefix_rd2str((struct prefix_rd *)prd, rd_str, sizeof(rd_str));
2515
2516 rd_rn = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
2517 if (!rd_rn)
2518 return;
2519
2520 table = bgp_node_get_bgp_table_info(rd_rn);
2521 if (table == NULL)
2522 return;
2523
2524 if (json) {
2525 json_rd = json_object_new_object();
2526 json_object_string_add(json_rd, "rd", rd_str);
2527 }
2528
2529 /* Display all prefixes with this RD. */
2530 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2531 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2532 json_object *json_prefix = NULL;
2533 json_object *json_paths = NULL;
2534 char prefix_str[BUFSIZ];
2535 int add_prefix_to_json = 0;
2536
2537 bgp_evpn_route2str((struct prefix_evpn *)&rn->p, prefix_str,
2538 sizeof(prefix_str));
2539
2540 if (type && evp->prefix.route_type != type)
2541 continue;
2542
2543 if (json)
2544 json_prefix = json_object_new_object();
2545
2546 pi = bgp_node_get_bgp_path_info(rn);
2547 if (pi) {
2548 /* RD header and legend - once overall. */
2549 if (rd_header && !json) {
2550 vty_out(vty,
2551 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2552 vty_out(vty,
2553 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2554 vty_out(vty,
2555 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2556 rd_header = 0;
2557 }
2558
2559 /* Prefix and num paths displayed once per prefix. */
2560 route_vty_out_detail_header(vty, bgp, rn, prd, afi,
2561 safi, json_prefix);
2562
2563 prefix_cnt++;
2564 }
2565
2566 if (json)
2567 json_paths = json_object_new_array();
2568
2569 /* Display each path for this prefix. */
2570 for (; pi; pi = pi->next) {
2571 json_object *json_path = NULL;
2572
2573 if (json)
2574 json_path = json_object_new_array();
2575
2576 route_vty_out_detail(vty, bgp, rn, pi, afi, safi,
2577 json_path);
2578
2579 if (json)
2580 json_object_array_add(json_paths, json_path);
2581
2582 path_cnt++;
2583 add_prefix_to_json = 1;
2584 add_rd_to_json = 1;
2585 }
2586
2587 if (json && add_prefix_to_json) {
2588 json_object_object_add(json_prefix, "paths",
2589 json_paths);
2590 json_object_object_add(json_rd, prefix_str,
2591 json_prefix);
2592 }
2593 }
2594
2595 if (json && add_rd_to_json)
2596 json_object_object_add(json, rd_str, json_rd);
2597
2598 if (json) {
2599 json_object_int_add(json, "numPrefix", prefix_cnt);
2600 json_object_int_add(json, "numPaths", path_cnt);
2601 } else {
2602 if (prefix_cnt == 0)
2603 vty_out(vty, "No prefixes exist with this RD%s\n",
2604 type ? " (of requested type)" : "");
2605 else
2606 vty_out(vty,
2607 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2608 prefix_cnt, path_cnt,
2609 type ? " (of requested type)" : "");
2610 }
2611 }
2612
2613 /*
2614 * Display BGP EVPN routing table - all routes (vty handler).
2615 * If 'type' is non-zero, only routes matching that type are shown.
2616 */
2617 static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
2618 json_object *json, int detail)
2619 {
2620 struct bgp_node *rd_rn;
2621 struct bgp_table *table;
2622 struct bgp_node *rn;
2623 struct bgp_path_info *pi;
2624 int header = detail ? 0 : 1;
2625 int rd_header;
2626 afi_t afi;
2627 safi_t safi;
2628 uint32_t prefix_cnt, path_cnt;
2629
2630 afi = AFI_L2VPN;
2631 safi = SAFI_EVPN;
2632 prefix_cnt = path_cnt = 0;
2633
2634 /* EVPN routing table is a 2-level table with the first level being
2635 * the RD.
2636 */
2637 for (rd_rn = bgp_table_top(bgp->rib[afi][safi]); rd_rn;
2638 rd_rn = bgp_route_next(rd_rn)) {
2639 char rd_str[RD_ADDRSTRLEN];
2640 json_object *json_rd = NULL; /* contains routes for an RD */
2641 int add_rd_to_json = 0;
2642 uint64_t tbl_ver;
2643
2644 table = bgp_node_get_bgp_table_info(rd_rn);
2645 if (table == NULL)
2646 continue;
2647
2648 tbl_ver = table->version;
2649 prefix_rd2str((struct prefix_rd *)&rd_rn->p, rd_str,
2650 sizeof(rd_str));
2651
2652 if (json) {
2653 json_rd = json_object_new_object();
2654 json_object_string_add(json_rd, "rd", rd_str);
2655 }
2656
2657 rd_header = 1;
2658
2659 /* Display all prefixes for an RD */
2660 for (rn = bgp_table_top(table); rn; rn = bgp_route_next(rn)) {
2661 json_object *json_prefix =
2662 NULL; /* contains prefix under a RD */
2663 json_object *json_paths =
2664 NULL; /* array of paths under a prefix*/
2665 struct prefix_evpn *evp = (struct prefix_evpn *)&rn->p;
2666 char prefix_str[BUFSIZ];
2667 int add_prefix_to_json = 0;
2668
2669 bgp_evpn_route2str((struct prefix_evpn *)&rn->p,
2670 prefix_str, sizeof(prefix_str));
2671
2672 if (type && evp->prefix.route_type != type)
2673 continue;
2674
2675 pi = bgp_node_get_bgp_path_info(rn);
2676 if (pi) {
2677 /* Overall header/legend displayed once. */
2678 if (header) {
2679 bgp_evpn_show_route_header(vty, bgp,
2680 tbl_ver,
2681 json);
2682 if (!json)
2683 vty_out(vty,
2684 "%19s Extended Community\n"
2685 , " ");
2686 header = 0;
2687 }
2688
2689 /* RD header - per RD. */
2690 if (rd_header) {
2691 bgp_evpn_show_route_rd_header(
2692 vty, rd_rn, json);
2693 rd_header = 0;
2694 }
2695
2696 prefix_cnt++;
2697 }
2698
2699 if (json) {
2700 json_prefix = json_object_new_object();
2701 json_paths = json_object_new_array();
2702 json_object_string_add(json_prefix, "prefix",
2703 prefix_str);
2704 json_object_int_add(json_prefix, "prefixLen",
2705 rn->p.prefixlen);
2706 }
2707
2708 /* Prefix and num paths displayed once per prefix. */
2709 if (detail)
2710 route_vty_out_detail_header(
2711 vty, bgp, rn,
2712 (struct prefix_rd *)&rd_rn->p,
2713 AFI_L2VPN, SAFI_EVPN, json_prefix);
2714
2715 /* For EVPN, the prefix is displayed for each path (to
2716 * fit in
2717 * with code that already exists).
2718 */
2719 for (; pi; pi = pi->next) {
2720 json_object *json_path = NULL;
2721 path_cnt++;
2722 add_prefix_to_json = 1;
2723 add_rd_to_json = 1;
2724
2725 if (json)
2726 json_path = json_object_new_array();
2727
2728 if (detail) {
2729 route_vty_out_detail(
2730 vty, bgp, rn, pi, AFI_L2VPN,
2731 SAFI_EVPN, json_path);
2732 } else
2733 route_vty_out(vty, &rn->p, pi, 0,
2734 SAFI_EVPN, json_path);
2735
2736 if (json)
2737 json_object_array_add(json_paths,
2738 json_path);
2739 }
2740
2741 if (json && add_prefix_to_json) {
2742 json_object_object_add(json_prefix, "paths",
2743 json_paths);
2744 json_object_object_add(json_rd, prefix_str,
2745 json_prefix);
2746 }
2747 }
2748
2749 if (json && add_rd_to_json)
2750 json_object_object_add(json, rd_str, json_rd);
2751 }
2752
2753 if (json) {
2754 json_object_int_add(json, "numPrefix", prefix_cnt);
2755 json_object_int_add(json, "numPaths", path_cnt);
2756 } else {
2757 if (prefix_cnt == 0) {
2758 vty_out(vty, "No EVPN prefixes %sexist\n",
2759 type ? "(of requested type) " : "");
2760 } else {
2761 vty_out(vty, "\nDisplayed %u prefixes (%u paths)%s\n",
2762 prefix_cnt, path_cnt,
2763 type ? " (of requested type)" : "");
2764 }
2765 }
2766 }
2767
2768 /* Display specific ES */
2769 static void evpn_show_es(struct vty *vty, struct bgp *bgp, esi_t *esi,
2770 json_object *json)
2771 {
2772 struct evpnes *es = NULL;
2773
2774 es = bgp_evpn_lookup_es(bgp, esi);
2775 if (es) {
2776 display_es(vty, es, json);
2777 } else {
2778 if (json) {
2779 vty_out(vty, "{}\n");
2780 } else {
2781 vty_out(vty, "ESI not found\n");
2782 return;
2783 }
2784 }
2785 }
2786
2787 /* Display all ESs */
2788 static void evpn_show_all_es(struct vty *vty, struct bgp *bgp,
2789 json_object *json)
2790 {
2791 void *args[2];
2792
2793 if (!json)
2794 vty_out(vty, "%-30s %-6s %-21s %-15s %-6s\n",
2795 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2796
2797 /* print all ESs */
2798 args[0] = vty;
2799 args[1] = json;
2800 hash_iterate(bgp->esihash,
2801 (void (*)(struct hash_bucket *, void *))show_es_entry,
2802 args);
2803 }
2804
2805 /*
2806 * Display specified VNI (vty handler)
2807 */
2808 static void evpn_show_vni(struct vty *vty, struct bgp *bgp, vni_t vni,
2809 json_object *json)
2810 {
2811 uint8_t found = 0;
2812 struct bgpevpn *vpn;
2813
2814 vpn = bgp_evpn_lookup_vni(bgp, vni);
2815 if (vpn) {
2816 found = 1;
2817 display_vni(vty, vpn, json);
2818 } else {
2819 struct bgp *bgp_temp;
2820 struct listnode *node = NULL;
2821
2822 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
2823 if (bgp_temp->l3vni == vni) {
2824 found = 1;
2825 display_l3vni(vty, bgp_temp, json);
2826 }
2827 }
2828 }
2829
2830 if (!found) {
2831 if (json) {
2832 vty_out(vty, "{}\n");
2833 } else {
2834 vty_out(vty, "VNI not found\n");
2835 return;
2836 }
2837 }
2838 }
2839
2840 /*
2841 * Display a VNI (upon user query).
2842 */
2843 static void evpn_show_all_vnis(struct vty *vty, struct bgp *bgp,
2844 json_object *json)
2845 {
2846 void *args[2];
2847 struct bgp *bgp_temp = NULL;
2848 struct listnode *node;
2849
2850
2851 if (!json) {
2852 vty_out(vty, "Flags: * - Kernel\n");
2853 vty_out(vty, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2854 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2855 }
2856
2857 /* print all L2 VNIS */
2858 args[0] = vty;
2859 args[1] = json;
2860 hash_iterate(bgp->vnihash,
2861 (void (*)(struct hash_bucket *, void *))show_vni_entry,
2862 args);
2863
2864 /* print all L3 VNIs */
2865 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp))
2866 show_l3vni_entry(vty, bgp_temp, json);
2867 }
2868
2869 /*
2870 * evpn - enable advertisement of svi MAC-IP
2871 */
2872 static void evpn_set_advertise_svi_macip(struct bgp *bgp, struct bgpevpn *vpn,
2873 uint32_t set)
2874 {
2875 if (!vpn) {
2876 if (set && bgp->evpn_info->advertise_svi_macip)
2877 return;
2878 else if (!set && !bgp->evpn_info->advertise_svi_macip)
2879 return;
2880
2881 bgp->evpn_info->advertise_svi_macip = set;
2882 bgp_zebra_advertise_svi_macip(bgp,
2883 bgp->evpn_info->advertise_svi_macip, 0);
2884 } else {
2885 if (set && vpn->advertise_svi_macip)
2886 return;
2887 else if (!set && !vpn->advertise_svi_macip)
2888 return;
2889
2890 vpn->advertise_svi_macip = set;
2891 bgp_zebra_advertise_svi_macip(bgp, vpn->advertise_svi_macip,
2892 vpn->vni);
2893 }
2894 }
2895
2896 /*
2897 * evpn - enable advertisement of default g/w
2898 */
2899 static void evpn_set_advertise_default_gw(struct bgp *bgp, struct bgpevpn *vpn)
2900 {
2901 if (!vpn) {
2902 if (bgp->advertise_gw_macip)
2903 return;
2904
2905 bgp->advertise_gw_macip = 1;
2906 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2907 } else {
2908 if (vpn->advertise_gw_macip)
2909 return;
2910
2911 vpn->advertise_gw_macip = 1;
2912 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2913 vpn->vni);
2914 }
2915 return;
2916 }
2917
2918 /*
2919 * evpn - disable advertisement of default g/w
2920 */
2921 static void evpn_unset_advertise_default_gw(struct bgp *bgp,
2922 struct bgpevpn *vpn)
2923 {
2924 if (!vpn) {
2925 if (!bgp->advertise_gw_macip)
2926 return;
2927
2928 bgp->advertise_gw_macip = 0;
2929 bgp_zebra_advertise_gw_macip(bgp, bgp->advertise_gw_macip, 0);
2930 } else {
2931 if (!vpn->advertise_gw_macip)
2932 return;
2933
2934 vpn->advertise_gw_macip = 0;
2935 bgp_zebra_advertise_gw_macip(bgp, vpn->advertise_gw_macip,
2936 vpn->vni);
2937 }
2938 return;
2939 }
2940
2941 /*
2942 * evpn - enable advertisement of default g/w
2943 */
2944 static void evpn_process_default_originate_cmd(struct bgp *bgp_vrf,
2945 afi_t afi, bool add)
2946 {
2947 safi_t safi = SAFI_UNICAST; /* ipv4/ipv6 unicast */
2948
2949 if (add) {
2950 /* bail if we are already advertising default route */
2951 if (evpn_default_originate_set(bgp_vrf, afi, safi))
2952 return;
2953
2954 if (afi == AFI_IP)
2955 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2956 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2957 else if (afi == AFI_IP6)
2958 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2959 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2960 } else {
2961 /* bail out if we havent advertised the default route */
2962 if (!evpn_default_originate_set(bgp_vrf, afi, safi))
2963 return;
2964 if (afi == AFI_IP)
2965 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2966 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4);
2967 else if (afi == AFI_IP6)
2968 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
2969 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6);
2970 }
2971
2972 bgp_evpn_install_uninstall_default_route(bgp_vrf, afi, safi, add);
2973 }
2974
2975 /*
2976 * evpn - enable advertisement of default g/w
2977 */
2978 static void evpn_set_advertise_subnet(struct bgp *bgp,
2979 struct bgpevpn *vpn)
2980 {
2981 if (vpn->advertise_subnet)
2982 return;
2983
2984 vpn->advertise_subnet = 1;
2985 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2986 }
2987
2988 /*
2989 * evpn - disable advertisement of default g/w
2990 */
2991 static void evpn_unset_advertise_subnet(struct bgp *bgp, struct bgpevpn *vpn)
2992 {
2993 if (!vpn->advertise_subnet)
2994 return;
2995
2996 vpn->advertise_subnet = 0;
2997 bgp_zebra_advertise_subnet(bgp, vpn->advertise_subnet, vpn->vni);
2998 }
2999
3000 /*
3001 * EVPN (VNI advertisement) enabled. Register with zebra.
3002 */
3003 static void evpn_set_advertise_all_vni(struct bgp *bgp)
3004 {
3005 bgp->advertise_all_vni = 1;
3006 bgp_set_evpn(bgp);
3007 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3008 }
3009
3010 /*
3011 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3012 * cache, EVPN routes (delete and withdraw from peers).
3013 */
3014 static void evpn_unset_advertise_all_vni(struct bgp *bgp)
3015 {
3016 bgp->advertise_all_vni = 0;
3017 bgp_set_evpn(bgp_get_default());
3018 bgp_zebra_advertise_all_vni(bgp, bgp->advertise_all_vni);
3019 bgp_evpn_cleanup_on_disable(bgp);
3020 }
3021
3022 /*
3023 * EVPN - use RFC8365 to auto-derive RT
3024 */
3025 static void evpn_set_advertise_autort_rfc8365(struct bgp *bgp)
3026 {
3027 bgp->advertise_autort_rfc8365 = 1;
3028 bgp_evpn_handle_autort_change(bgp);
3029 }
3030
3031 /*
3032 * EVPN - don't use RFC8365 to auto-derive RT
3033 */
3034 static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
3035 {
3036 bgp->advertise_autort_rfc8365 = 0;
3037 bgp_evpn_handle_autort_change(bgp);
3038 }
3039
3040 static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
3041 {
3042 char buf1[RD_ADDRSTRLEN];
3043 char *ecom_str;
3044 struct listnode *node, *nnode;
3045 struct ecommunity *ecom;
3046
3047 if (is_vni_configured(vpn)) {
3048 vty_out(vty, " vni %d\n", vpn->vni);
3049 if (is_rd_configured(vpn))
3050 vty_out(vty, " rd %s\n",
3051 prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
3052
3053 if (is_import_rt_configured(vpn)) {
3054 for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
3055 ecom)) {
3056 ecom_str = ecommunity_ecom2str(
3057 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3058 vty_out(vty, " route-target import %s\n",
3059 ecom_str);
3060 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3061 }
3062 }
3063
3064 if (is_export_rt_configured(vpn)) {
3065 for (ALL_LIST_ELEMENTS(vpn->export_rtl, node, nnode,
3066 ecom)) {
3067 ecom_str = ecommunity_ecom2str(
3068 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
3069 vty_out(vty, " route-target export %s\n",
3070 ecom_str);
3071 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
3072 }
3073 }
3074
3075 if (vpn->advertise_gw_macip)
3076 vty_out(vty, " advertise-default-gw\n");
3077
3078 if (vpn->advertise_svi_macip)
3079 vty_out(vty, " advertise-svi-ip\n");
3080
3081 if (vpn->advertise_subnet)
3082 vty_out(vty, " advertise-subnet\n");
3083
3084 vty_out(vty, " exit-vni\n");
3085 }
3086 }
3087
3088 #ifndef VTYSH_EXTRACT_PL
3089 #include "bgpd/bgp_evpn_vty_clippy.c"
3090 #endif
3091
3092 DEFPY(bgp_evpn_flood_control,
3093 bgp_evpn_flood_control_cmd,
3094 "[no$no] flooding <disable$disable|head-end-replication$her>",
3095 NO_STR
3096 "Specify handling for BUM packets\n"
3097 "Do not flood any BUM packets\n"
3098 "Flood BUM packets using head-end replication\n")
3099 {
3100 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3101 enum vxlan_flood_control flood_ctrl;
3102
3103 if (!bgp)
3104 return CMD_WARNING;
3105
3106 if (disable && !no)
3107 flood_ctrl = VXLAN_FLOOD_DISABLED;
3108 else if (her || no)
3109 flood_ctrl = VXLAN_FLOOD_HEAD_END_REPL;
3110 else
3111 return CMD_WARNING;
3112
3113 if (bgp->vxlan_flood_ctrl == flood_ctrl)
3114 return CMD_SUCCESS;
3115
3116 bgp->vxlan_flood_ctrl = flood_ctrl;
3117 bgp_evpn_flood_control_change(bgp);
3118
3119 return CMD_SUCCESS;
3120 }
3121
3122 DEFUN (bgp_evpn_advertise_default_gw_vni,
3123 bgp_evpn_advertise_default_gw_vni_cmd,
3124 "advertise-default-gw",
3125 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3126 {
3127 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3128 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3129
3130 if (!bgp)
3131 return CMD_WARNING;
3132
3133 evpn_set_advertise_default_gw(bgp, vpn);
3134
3135 return CMD_SUCCESS;
3136 }
3137
3138 DEFUN (no_bgp_evpn_advertise_default_vni_gw,
3139 no_bgp_evpn_advertise_default_gw_vni_cmd,
3140 "no advertise-default-gw",
3141 NO_STR
3142 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3143 {
3144 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3145 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3146
3147 if (!bgp)
3148 return CMD_WARNING;
3149
3150 evpn_unset_advertise_default_gw(bgp, vpn);
3151
3152 return CMD_SUCCESS;
3153 }
3154
3155
3156 DEFUN (bgp_evpn_advertise_default_gw,
3157 bgp_evpn_advertise_default_gw_cmd,
3158 "advertise-default-gw",
3159 "Advertise All default g/w mac-ip routes in EVPN\n")
3160 {
3161 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3162
3163 if (!bgp)
3164 return CMD_WARNING;
3165
3166 if (!EVPN_ENABLED(bgp)) {
3167 vty_out(vty,
3168 "This command is only supported under the EVPN VRF\n");
3169 return CMD_WARNING;
3170 }
3171
3172 evpn_set_advertise_default_gw(bgp, NULL);
3173
3174 return CMD_SUCCESS;
3175 }
3176
3177 DEFUN (no_bgp_evpn_advertise_default_gw,
3178 no_bgp_evpn_advertise_default_gw_cmd,
3179 "no advertise-default-gw",
3180 NO_STR
3181 "Withdraw All default g/w mac-ip routes from EVPN\n")
3182 {
3183 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3184
3185 if (!bgp)
3186 return CMD_WARNING;
3187
3188 if (!EVPN_ENABLED(bgp)) {
3189 vty_out(vty,
3190 "This command is only supported under the EVPN VRF\n");
3191 return CMD_WARNING;
3192 }
3193
3194 evpn_unset_advertise_default_gw(bgp, NULL);
3195
3196 return CMD_SUCCESS;
3197 }
3198
3199 DEFUN (bgp_evpn_advertise_all_vni,
3200 bgp_evpn_advertise_all_vni_cmd,
3201 "advertise-all-vni",
3202 "Advertise All local VNIs\n")
3203 {
3204 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3205 struct bgp *bgp_evpn = NULL;
3206
3207 if (!bgp)
3208 return CMD_WARNING;
3209
3210 bgp_evpn = bgp_get_evpn();
3211 if (bgp_evpn && bgp_evpn != bgp) {
3212 vty_out(vty, "%% Please unconfigure EVPN in VRF %s\n",
3213 bgp_evpn->name);
3214 return CMD_WARNING_CONFIG_FAILED;
3215 }
3216
3217 evpn_set_advertise_all_vni(bgp);
3218 return CMD_SUCCESS;
3219 }
3220
3221 DEFUN (no_bgp_evpn_advertise_all_vni,
3222 no_bgp_evpn_advertise_all_vni_cmd,
3223 "no advertise-all-vni",
3224 NO_STR
3225 "Advertise All local VNIs\n")
3226 {
3227 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3228
3229 if (!bgp)
3230 return CMD_WARNING;
3231 evpn_unset_advertise_all_vni(bgp);
3232 return CMD_SUCCESS;
3233 }
3234
3235 DEFUN (bgp_evpn_advertise_autort_rfc8365,
3236 bgp_evpn_advertise_autort_rfc8365_cmd,
3237 "autort rfc8365-compatible",
3238 "Auto-derivation of RT\n"
3239 "Auto-derivation of RT using RFC8365\n")
3240 {
3241 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3242
3243 if (!bgp)
3244 return CMD_WARNING;
3245 evpn_set_advertise_autort_rfc8365(bgp);
3246 return CMD_SUCCESS;
3247 }
3248
3249 DEFUN (no_bgp_evpn_advertise_autort_rfc8365,
3250 no_bgp_evpn_advertise_autort_rfc8365_cmd,
3251 "no autort rfc8365-compatible",
3252 NO_STR
3253 "Auto-derivation of RT\n"
3254 "Auto-derivation of RT using RFC8365\n")
3255 {
3256 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3257
3258 if (!bgp)
3259 return CMD_WARNING;
3260 evpn_unset_advertise_autort_rfc8365(bgp);
3261 return CMD_SUCCESS;
3262 }
3263
3264 DEFUN (bgp_evpn_default_originate,
3265 bgp_evpn_default_originate_cmd,
3266 "default-originate <ipv4 | ipv6>",
3267 "originate a default route\n"
3268 "ipv4 address family\n"
3269 "ipv6 address family\n")
3270 {
3271 afi_t afi = 0;
3272 int idx_afi = 0;
3273 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3274
3275 if (!bgp_vrf)
3276 return CMD_WARNING;
3277 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3278 evpn_process_default_originate_cmd(bgp_vrf, afi, true);
3279 return CMD_SUCCESS;
3280 }
3281
3282 DEFUN (no_bgp_evpn_default_originate,
3283 no_bgp_evpn_default_originate_cmd,
3284 "no default-originate <ipv4 | ipv6>",
3285 NO_STR
3286 "withdraw a default route\n"
3287 "ipv4 address family\n"
3288 "ipv6 address family\n")
3289 {
3290 afi_t afi = 0;
3291 int idx_afi = 0;
3292 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3293
3294 if (!bgp_vrf)
3295 return CMD_WARNING;
3296 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3297 evpn_process_default_originate_cmd(bgp_vrf, afi, false);
3298 return CMD_SUCCESS;
3299 }
3300
3301 DEFPY (dup_addr_detection,
3302 dup_addr_detection_cmd,
3303 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3304 "Duplicate address detection\n"
3305 "Max allowed moves before address detected as duplicate\n"
3306 "Num of max allowed moves (2-1000) default 5\n"
3307 "Duplicate address detection time\n"
3308 "Time in seconds (2-1800) default 180\n")
3309 {
3310 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3311
3312 if (!bgp_vrf)
3313 return CMD_WARNING;
3314
3315 if (!EVPN_ENABLED(bgp_vrf)) {
3316 vty_out(vty,
3317 "This command is only supported under the EVPN VRF\n");
3318 return CMD_WARNING;
3319 }
3320
3321 bgp_vrf->evpn_info->dup_addr_detect = true;
3322
3323 if (time_val)
3324 bgp_vrf->evpn_info->dad_time = time_val;
3325 if (max_moves_val)
3326 bgp_vrf->evpn_info->dad_max_moves = max_moves_val;
3327
3328 bgp_zebra_dup_addr_detection(bgp_vrf);
3329
3330 return CMD_SUCCESS;
3331 }
3332
3333 DEFPY (dup_addr_detection_auto_recovery,
3334 dup_addr_detection_auto_recovery_cmd,
3335 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3336 "Duplicate address detection\n"
3337 "Duplicate address detection freeze\n"
3338 "Duplicate address detection permanent freeze\n"
3339 "Duplicate address detection freeze time (30-3600)\n")
3340 {
3341 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3342 uint32_t freeze_time = freeze_time_val;
3343
3344 if (!bgp_vrf)
3345 return CMD_WARNING;
3346
3347 if (!EVPN_ENABLED(bgp_vrf)) {
3348 vty_out(vty,
3349 "This command is only supported under the EVPN VRF\n");
3350 return CMD_WARNING;
3351 }
3352
3353 bgp_vrf->evpn_info->dup_addr_detect = true;
3354 bgp_vrf->evpn_info->dad_freeze = true;
3355 bgp_vrf->evpn_info->dad_freeze_time = freeze_time;
3356
3357 bgp_zebra_dup_addr_detection(bgp_vrf);
3358
3359 return CMD_SUCCESS;
3360 }
3361
3362 DEFPY (no_dup_addr_detection,
3363 no_dup_addr_detection_cmd,
3364 "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>]",
3365 NO_STR
3366 "Duplicate address detection\n"
3367 "Max allowed moves before address detected as duplicate\n"
3368 "Num of max allowed moves (2-1000) default 5\n"
3369 "Duplicate address detection time\n"
3370 "Time in seconds (2-1800) default 180\n"
3371 "Duplicate address detection freeze\n"
3372 "Duplicate address detection permanent freeze\n"
3373 "Duplicate address detection freeze time (30-3600)\n")
3374 {
3375 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
3376 uint32_t max_moves = (uint32_t)max_moves_val;
3377 uint32_t freeze_time = (uint32_t)freeze_time_val;
3378
3379 if (!bgp_vrf)
3380 return CMD_WARNING;
3381
3382 if (!EVPN_ENABLED(bgp_vrf)) {
3383 vty_out(vty,
3384 "This command is only supported under the EVPN VRF\n");
3385 return CMD_WARNING;
3386 }
3387
3388 if (argc == 2) {
3389 if (!bgp_vrf->evpn_info->dup_addr_detect)
3390 return CMD_SUCCESS;
3391 /* Reset all parameters to default. */
3392 bgp_vrf->evpn_info->dup_addr_detect = false;
3393 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3394 bgp_vrf->evpn_info->dad_max_moves = EVPN_DAD_DEFAULT_MAX_MOVES;
3395 bgp_vrf->evpn_info->dad_freeze = false;
3396 bgp_vrf->evpn_info->dad_freeze_time = 0;
3397 } else {
3398 if (max_moves) {
3399 if (bgp_vrf->evpn_info->dad_max_moves != max_moves) {
3400 vty_out(vty,
3401 "%% Value does not match with config\n");
3402 return CMD_SUCCESS;
3403 }
3404 bgp_vrf->evpn_info->dad_max_moves =
3405 EVPN_DAD_DEFAULT_MAX_MOVES;
3406 }
3407
3408 if (time_val) {
3409 if (bgp_vrf->evpn_info->dad_time != time_val) {
3410 vty_out(vty,
3411 "%% Value does not match with config\n");
3412 return CMD_SUCCESS;
3413 }
3414 bgp_vrf->evpn_info->dad_time = EVPN_DAD_DEFAULT_TIME;
3415 }
3416
3417 if (freeze_time) {
3418 if (bgp_vrf->evpn_info->dad_freeze_time
3419 != freeze_time) {
3420 vty_out(vty,
3421 "%% Value does not match with config\n");
3422 return CMD_SUCCESS;
3423 }
3424 bgp_vrf->evpn_info->dad_freeze_time = 0;
3425 bgp_vrf->evpn_info->dad_freeze = false;
3426 }
3427
3428 if (permanent_val) {
3429 if (bgp_vrf->evpn_info->dad_freeze_time) {
3430 vty_out(vty,
3431 "%% Value does not match with config\n");
3432 return CMD_SUCCESS;
3433 }
3434 bgp_vrf->evpn_info->dad_freeze = false;
3435 }
3436 }
3437
3438 bgp_zebra_dup_addr_detection(bgp_vrf);
3439
3440 return CMD_SUCCESS;
3441 }
3442
3443 DEFPY(bgp_evpn_advertise_svi_ip,
3444 bgp_evpn_advertise_svi_ip_cmd,
3445 "[no$no] advertise-svi-ip",
3446 NO_STR
3447 "Advertise svi mac-ip routes in EVPN\n")
3448 {
3449 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3450
3451 if (!bgp)
3452 return CMD_WARNING;
3453
3454 if (!EVPN_ENABLED(bgp)) {
3455 vty_out(vty,
3456 "This command is only supported under EVPN VRF\n");
3457 return CMD_WARNING;
3458 }
3459
3460 if (no)
3461 evpn_set_advertise_svi_macip(bgp, NULL, 0);
3462 else
3463 evpn_set_advertise_svi_macip(bgp, NULL, 1);
3464
3465 return CMD_SUCCESS;
3466 }
3467
3468 DEFPY(bgp_evpn_advertise_svi_ip_vni,
3469 bgp_evpn_advertise_svi_ip_vni_cmd,
3470 "[no$no] advertise-svi-ip",
3471 NO_STR
3472 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3473 {
3474 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3475 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3476
3477 if (!bgp)
3478 return CMD_WARNING;
3479
3480 if (no)
3481 evpn_set_advertise_svi_macip(bgp, vpn, 0);
3482 else
3483 evpn_set_advertise_svi_macip(bgp, vpn, 1);
3484
3485 return CMD_SUCCESS;
3486 }
3487
3488 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet,
3489 bgp_evpn_advertise_vni_subnet_cmd,
3490 "advertise-subnet",
3491 "Advertise the subnet corresponding to VNI\n")
3492 {
3493 struct bgp *bgp_vrf = NULL;
3494 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3495 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3496
3497 if (!bgp)
3498 return CMD_WARNING;
3499
3500 bgp_vrf = bgp_lookup_by_vrf_id(vpn->tenant_vrf_id);
3501 if (!bgp_vrf)
3502 return CMD_WARNING;
3503
3504 evpn_set_advertise_subnet(bgp, vpn);
3505 return CMD_SUCCESS;
3506 }
3507
3508 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet,
3509 no_bgp_evpn_advertise_vni_subnet_cmd,
3510 "no advertise-subnet",
3511 NO_STR
3512 "Advertise All local VNIs\n")
3513 {
3514 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
3515 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
3516
3517 if (!bgp)
3518 return CMD_WARNING;
3519
3520 evpn_unset_advertise_subnet(bgp, vpn);
3521 return CMD_SUCCESS;
3522 }
3523
3524 DEFUN (bgp_evpn_advertise_type5,
3525 bgp_evpn_advertise_type5_cmd,
3526 "advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR " [route-map WORD]",
3527 "Advertise prefix routes\n"
3528 BGP_AFI_HELP_STR
3529 BGP_SAFI_HELP_STR
3530 "route-map for filtering specific routes\n"
3531 "Name of the route map\n")
3532 {
3533 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3534 int idx_afi = 0;
3535 int idx_safi = 0;
3536 int idx_rmap = 0;
3537 afi_t afi = 0;
3538 safi_t safi = 0;
3539 int ret = 0;
3540 int rmap_changed = 0;
3541
3542 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3543 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3544 ret = argv_find(argv, argc, "route-map", &idx_rmap);
3545 if (ret) {
3546 if (!bgp_vrf->adv_cmd_rmap[afi][safi].name)
3547 rmap_changed = 1;
3548 else if (strcmp(argv[idx_rmap + 1]->arg,
3549 bgp_vrf->adv_cmd_rmap[afi][safi].name)
3550 != 0)
3551 rmap_changed = 1;
3552 } else if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3553 rmap_changed = 1;
3554 }
3555
3556 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3557 vty_out(vty,
3558 "%%only ipv4 or ipv6 address families are supported");
3559 return CMD_WARNING;
3560 }
3561
3562 if (safi != SAFI_UNICAST) {
3563 vty_out(vty,
3564 "%%only ipv4 unicast or ipv6 unicast are supported");
3565 return CMD_WARNING;
3566 }
3567
3568 if (afi == AFI_IP) {
3569
3570 /* if we are already advertising ipv4 prefix as type-5
3571 * nothing to do
3572 */
3573 if (!rmap_changed &&
3574 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3575 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST))
3576 return CMD_WARNING;
3577 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3578 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3579 } else {
3580
3581 /* if we are already advertising ipv6 prefix as type-5
3582 * nothing to do
3583 */
3584 if (!rmap_changed &&
3585 CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3586 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))
3587 return CMD_WARNING;
3588 SET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3589 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3590 }
3591
3592 if (rmap_changed) {
3593 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3594 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3595 XFREE(MTYPE_ROUTE_MAP_NAME,
3596 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3597 route_map_counter_decrement(
3598 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3599 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3600 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3601 }
3602 }
3603
3604 /* set the route-map for advertise command */
3605 if (ret && argv[idx_rmap + 1]->arg) {
3606 bgp_vrf->adv_cmd_rmap[afi][safi].name =
3607 XSTRDUP(MTYPE_ROUTE_MAP_NAME, argv[idx_rmap + 1]->arg);
3608 bgp_vrf->adv_cmd_rmap[afi][safi].map =
3609 route_map_lookup_by_name(argv[idx_rmap + 1]->arg);
3610 route_map_counter_increment(
3611 bgp_vrf->adv_cmd_rmap[afi][safi].map);
3612 }
3613
3614 /* advertise type-5 routes */
3615 if (advertise_type5_routes(bgp_vrf, afi))
3616 bgp_evpn_advertise_type5_routes(bgp_vrf, afi, safi);
3617 return CMD_SUCCESS;
3618 }
3619
3620 DEFUN (no_bgp_evpn_advertise_type5,
3621 no_bgp_evpn_advertise_type5_cmd,
3622 "no advertise " BGP_AFI_CMD_STR "" BGP_SAFI_CMD_STR,
3623 NO_STR
3624 "Advertise prefix routes\n"
3625 BGP_AFI_HELP_STR
3626 BGP_SAFI_HELP_STR)
3627 {
3628 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp); /* bgp vrf instance */
3629 int idx_afi = 0;
3630 int idx_safi = 0;
3631 afi_t afi = 0;
3632 safi_t safi = 0;
3633
3634 argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
3635 argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
3636
3637 if (!(afi == AFI_IP || afi == AFI_IP6)) {
3638 vty_out(vty,
3639 "%%only ipv4 or ipv6 address families are supported");
3640 return CMD_WARNING;
3641 }
3642
3643 if (safi != SAFI_UNICAST) {
3644 vty_out(vty,
3645 "%%only ipv4 unicast or ipv6 unicast are supported");
3646 return CMD_WARNING;
3647 }
3648
3649 if (afi == AFI_IP) {
3650
3651 /* if we are not advertising ipv4 prefix as type-5
3652 * nothing to do
3653 */
3654 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3655 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
3656 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3657 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3658 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST);
3659 }
3660 } else {
3661
3662 /* if we are not advertising ipv6 prefix as type-5
3663 * nothing to do
3664 */
3665 if (CHECK_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3666 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
3667 bgp_evpn_withdraw_type5_routes(bgp_vrf, afi, safi);
3668 UNSET_FLAG(bgp_vrf->af_flags[AFI_L2VPN][SAFI_EVPN],
3669 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST);
3670 }
3671 }
3672
3673 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3674 if (bgp_vrf->adv_cmd_rmap[afi][safi].name) {
3675 XFREE(MTYPE_ROUTE_MAP_NAME,
3676 bgp_vrf->adv_cmd_rmap[afi][safi].name);
3677 bgp_vrf->adv_cmd_rmap[afi][safi].name = NULL;
3678 bgp_vrf->adv_cmd_rmap[afi][safi].map = NULL;
3679 }
3680
3681 return CMD_SUCCESS;
3682 }
3683
3684 /*
3685 * Display VNI information - for all or a specific VNI
3686 */
3687 DEFUN(show_bgp_l2vpn_evpn_vni,
3688 show_bgp_l2vpn_evpn_vni_cmd,
3689 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE "] [json]",
3690 SHOW_STR
3691 BGP_STR
3692 L2VPN_HELP_STR
3693 EVPN_HELP_STR
3694 "Show VNI\n"
3695 "VNI number\n"
3696 JSON_STR)
3697 {
3698 struct bgp *bgp_evpn;
3699 vni_t vni;
3700 int idx = 0;
3701 bool uj = false;
3702 json_object *json = NULL;
3703 uint32_t num_l2vnis = 0;
3704 uint32_t num_l3vnis = 0;
3705 uint32_t num_vnis = 0;
3706 struct listnode *node = NULL;
3707 struct bgp *bgp_temp = NULL;
3708
3709 uj = use_json(argc, argv);
3710
3711 bgp_evpn = bgp_get_evpn();
3712 if (!bgp_evpn)
3713 return CMD_WARNING;
3714
3715 if (!argv_find(argv, argc, "evpn", &idx))
3716 return CMD_WARNING;
3717
3718 if (uj)
3719 json = json_object_new_object();
3720
3721 if ((uj && argc == ((idx + 1) + 2)) || (!uj && argc == (idx + 1) + 1)) {
3722
3723 num_l2vnis = hashcount(bgp_evpn->vnihash);
3724
3725 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_temp)) {
3726 if (bgp_temp->l3vni)
3727 num_l3vnis++;
3728 }
3729 num_vnis = num_l2vnis + num_l3vnis;
3730 if (uj) {
3731 json_object_string_add(json, "advertiseGatewayMacip",
3732 bgp_evpn->advertise_gw_macip
3733 ? "Enabled"
3734 : "Disabled");
3735 json_object_string_add(json, "advertiseSviMacip",
3736 bgp_evpn->evpn_info->advertise_svi_macip
3737 ? "Enabled" : "Disabled");
3738 json_object_string_add(json, "advertiseAllVnis",
3739 is_evpn_enabled() ? "Enabled"
3740 : "Disabled");
3741 json_object_string_add(
3742 json, "flooding",
3743 bgp_evpn->vxlan_flood_ctrl
3744 == VXLAN_FLOOD_HEAD_END_REPL
3745 ? "Head-end replication"
3746 : "Disabled");
3747 json_object_int_add(json, "numVnis", num_vnis);
3748 json_object_int_add(json, "numL2Vnis", num_l2vnis);
3749 json_object_int_add(json, "numL3Vnis", num_l3vnis);
3750 } else {
3751 vty_out(vty, "Advertise Gateway Macip: %s\n",
3752 bgp_evpn->advertise_gw_macip ? "Enabled"
3753 : "Disabled");
3754 vty_out(vty, "Advertise SVI Macip: %s\n",
3755 bgp_evpn->evpn_info->advertise_svi_macip ? "Enabled"
3756 : "Disabled");
3757 vty_out(vty, "Advertise All VNI flag: %s\n",
3758 is_evpn_enabled() ? "Enabled" : "Disabled");
3759 vty_out(vty, "BUM flooding: %s\n",
3760 bgp_evpn->vxlan_flood_ctrl
3761 == VXLAN_FLOOD_HEAD_END_REPL
3762 ? "Head-end replication"
3763 : "Disabled");
3764 vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
3765 vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
3766 }
3767 evpn_show_all_vnis(vty, bgp_evpn, json);
3768 } else {
3769 int vni_idx = 0;
3770
3771 if (!argv_find(argv, argc, "vni", &vni_idx))
3772 return CMD_WARNING;
3773
3774 /* Display specific VNI */
3775 vni = strtoul(argv[vni_idx + 1]->arg, NULL, 10);
3776 evpn_show_vni(vty, bgp_evpn, vni, json);
3777 }
3778
3779 if (uj) {
3780 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3781 json, JSON_C_TO_STRING_PRETTY));
3782 json_object_free(json);
3783 }
3784
3785 return CMD_SUCCESS;
3786 }
3787
3788 /* Disaply ES */
3789 DEFUN(show_bgp_l2vpn_evpn_es,
3790 show_bgp_l2vpn_evpn_es_cmd,
3791 "show bgp l2vpn evpn es [ESI] [json]",
3792 SHOW_STR
3793 BGP_STR
3794 L2VPN_HELP_STR
3795 EVPN_HELP_STR
3796 "ethernet-Segment\n"
3797 "Ethernet-Segment Identifier\n"
3798 JSON_STR)
3799 {
3800 int idx = 0;
3801 bool uj = false;
3802 esi_t esi;
3803 json_object *json = NULL;
3804 struct bgp *bgp = NULL;
3805
3806 memset(&esi, 0, sizeof(esi));
3807 uj = use_json(argc, argv);
3808
3809 bgp = bgp_get_evpn();
3810 if (!bgp)
3811 return CMD_WARNING;
3812
3813 if (!argv_find(argv, argc, "evpn", &idx))
3814 return CMD_WARNING;
3815
3816 if ((uj && argc == ((idx + 1) + 2)) ||
3817 (!uj && argc == (idx + 1) + 1)) {
3818
3819 /* show all ESs */
3820 evpn_show_all_es(vty, bgp, json);
3821 } else {
3822
3823 /* show a specific ES */
3824
3825 /* get the ESI - ESI-ID is at argv[5] */
3826 if (!str_to_esi(argv[idx + 2]->arg, &esi)) {
3827 vty_out(vty, "%% Malformed ESI\n");
3828 return CMD_WARNING;
3829 }
3830 evpn_show_es(vty, bgp, &esi, json);
3831 }
3832
3833 if (uj) {
3834 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3835 json, JSON_C_TO_STRING_PRETTY));
3836 json_object_free(json);
3837 }
3838
3839 return CMD_SUCCESS;
3840 }
3841
3842 /*
3843 * Display EVPN neighbor summary.
3844 */
3845 DEFUN(show_bgp_l2vpn_evpn_summary,
3846 show_bgp_l2vpn_evpn_summary_cmd,
3847 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3848 SHOW_STR
3849 BGP_STR
3850 "bgp vrf\n"
3851 "vrf name\n"
3852 L2VPN_HELP_STR
3853 EVPN_HELP_STR
3854 "Summary of BGP neighbor status\n"
3855 "Show only sessions not in Established state\n"
3856 JSON_STR)
3857 {
3858 int idx_vrf = 0;
3859 bool uj = use_json(argc, argv);
3860 char *vrf = NULL;
3861 bool show_failed = false;
3862
3863 if (argv_find(argv, argc, "vrf", &idx_vrf))
3864 vrf = argv[++idx_vrf]->arg;
3865 if (argv_find(argv, argc, "failed", &idx_vrf))
3866 show_failed = true;
3867 return bgp_show_summary_vty(vty, vrf, AFI_L2VPN, SAFI_EVPN,
3868 show_failed, uj);
3869 }
3870
3871 /*
3872 * Display global EVPN routing table.
3873 */
3874 DEFUN(show_bgp_l2vpn_evpn_route,
3875 show_bgp_l2vpn_evpn_route_cmd,
3876 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3877 SHOW_STR
3878 BGP_STR
3879 L2VPN_HELP_STR
3880 EVPN_HELP_STR
3881 "EVPN route information\n"
3882 "Display Detailed Information\n"
3883 "Specify Route type\n"
3884 "MAC-IP (Type-2) route\n"
3885 "Multicast (Type-3) route\n"
3886 "Ethernet Segment (type-4) route \n"
3887 "Prefix (type-5 )route\n"
3888 JSON_STR)
3889 {
3890 struct bgp *bgp;
3891 int type_idx = 0;
3892 int detail = 0;
3893 int type = 0;
3894 bool uj = false;
3895 json_object *json = NULL;
3896
3897 uj = use_json(argc, argv);
3898
3899 bgp = bgp_get_evpn();
3900 if (!bgp)
3901 return CMD_WARNING;
3902
3903 if (uj)
3904 json = json_object_new_object();
3905
3906 /* get the type */
3907 if (argv_find(argv, argc, "type", &type_idx)) {
3908 /* Specific type is requested */
3909 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3910 type = BGP_EVPN_MAC_IP_ROUTE;
3911 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3912 type = BGP_EVPN_IMET_ROUTE;
3913 else if (strncmp(argv[type_idx + 1]->arg, "e", 1) == 0)
3914 type = BGP_EVPN_ES_ROUTE;
3915 else if (strncmp(argv[type_idx + 1]->arg, "p", 1) == 0)
3916 type = BGP_EVPN_IP_PREFIX_ROUTE;
3917 else
3918 return CMD_WARNING;
3919 }
3920
3921 if (argv_find(argv, argc, "detail", &detail))
3922 detail = 1;
3923
3924 evpn_show_all_routes(vty, bgp, type, json, detail);
3925
3926 if (uj) {
3927 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3928 json, JSON_C_TO_STRING_PRETTY));
3929 json_object_free(json);
3930 }
3931 return CMD_SUCCESS;
3932 }
3933
3934 /*
3935 * Display global EVPN routing table for specific RD.
3936 */
3937 DEFUN(show_bgp_l2vpn_evpn_route_rd,
3938 show_bgp_l2vpn_evpn_route_rd_cmd,
3939 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3940 SHOW_STR
3941 BGP_STR
3942 L2VPN_HELP_STR
3943 EVPN_HELP_STR
3944 "EVPN route information\n"
3945 "Route Distinguisher\n"
3946 "ASN:XX or A.B.C.D:XX\n"
3947 "Specify Route type\n"
3948 "MAC-IP (Type-2) route\n"
3949 "Multicast (Type-3) route\n"
3950 "Ethernet Segment route\n"
3951 "Prefix route\n"
3952 JSON_STR)
3953 {
3954 struct bgp *bgp;
3955 int ret;
3956 struct prefix_rd prd;
3957 int type = 0;
3958 int rd_idx = 0;
3959 int type_idx = 0;
3960 bool uj = false;
3961 json_object *json = NULL;
3962
3963 bgp = bgp_get_evpn();
3964 if (!bgp)
3965 return CMD_WARNING;
3966
3967 /* check if we need json output */
3968 uj = use_json(argc, argv);
3969 if (uj)
3970 json = json_object_new_object();
3971
3972 /* get the RD */
3973 if (argv_find(argv, argc, "rd", &rd_idx)) {
3974 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
3975
3976 if (!ret) {
3977 vty_out(vty, "%% Malformed Route Distinguisher\n");
3978 return CMD_WARNING;
3979 }
3980 }
3981
3982 /* get the type */
3983 if (argv_find(argv, argc, "type", &type_idx)) {
3984 /* Specific type is requested */
3985 if (strncmp(argv[type_idx + 1]->arg, "ma", 2) == 0)
3986 type = BGP_EVPN_MAC_IP_ROUTE;
3987 else if (strncmp(argv[type_idx + 1]->arg, "mu", 2) == 0)
3988 type = BGP_EVPN_IMET_ROUTE;
3989 else if (strncmp(argv[type_idx + 1]->arg, "pr", 2) == 0)
3990 type = BGP_EVPN_IP_PREFIX_ROUTE;
3991 else
3992 return CMD_WARNING;
3993 }
3994
3995 evpn_show_route_rd(vty, bgp, &prd, type, json);
3996
3997 if (uj) {
3998 vty_out(vty, "%s\n", json_object_to_json_string_ext(
3999 json, JSON_C_TO_STRING_PRETTY));
4000 json_object_free(json);
4001 }
4002
4003 return CMD_SUCCESS;
4004 }
4005
4006 /*
4007 * Display global EVPN routing table for specific RD and MACIP.
4008 */
4009 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
4010 show_bgp_l2vpn_evpn_route_rd_macip_cmd,
4011 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4012 SHOW_STR
4013 BGP_STR
4014 L2VPN_HELP_STR
4015 EVPN_HELP_STR
4016 "EVPN route information\n"
4017 "Route Distinguisher\n"
4018 "ASN:XX or A.B.C.D:XX\n"
4019 "MAC\n"
4020 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4021 "IP\n"
4022 "IP address (IPv4 or IPv6)\n"
4023 JSON_STR)
4024 {
4025 struct bgp *bgp;
4026 int ret;
4027 struct prefix_rd prd;
4028 struct ethaddr mac;
4029 struct ipaddr ip;
4030 int rd_idx = 0;
4031 int mac_idx = 0;
4032 int ip_idx = 0;
4033 bool uj = false;
4034 json_object *json = NULL;
4035
4036 memset(&mac, 0, sizeof(struct ethaddr));
4037 memset(&ip, 0, sizeof(struct ipaddr));
4038
4039 bgp = bgp_get_evpn();
4040 if (!bgp)
4041 return CMD_WARNING;
4042
4043 /* check if we need json output */
4044 uj = use_json(argc, argv);
4045 if (uj)
4046 json = json_object_new_object();
4047
4048 /* get the prd */
4049 if (argv_find(argv, argc, "rd", &rd_idx)) {
4050 ret = str2prefix_rd(argv[rd_idx + 1]->arg, &prd);
4051 if (!ret) {
4052 vty_out(vty, "%% Malformed Route Distinguisher\n");
4053 return CMD_WARNING;
4054 }
4055 }
4056
4057 /* get the mac */
4058 if (argv_find(argv, argc, "mac", &mac_idx)) {
4059 if (!prefix_str2mac(argv[mac_idx + 1]->arg, &mac)) {
4060 vty_out(vty, "%% Malformed MAC address\n");
4061 return CMD_WARNING;
4062 }
4063 }
4064
4065 /* get the ip if specified */
4066 if (argv_find(argv, argc, "ip", &ip_idx)) {
4067 if (str2ipaddr(argv[ip_idx + 1]->arg, &ip) != 0) {
4068 vty_out(vty, "%% Malformed IP address\n");
4069 return CMD_WARNING;
4070 }
4071 }
4072
4073 evpn_show_route_rd_macip(vty, bgp, &prd, &mac, &ip, json);
4074
4075 if (uj) {
4076 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4077 json, JSON_C_TO_STRING_PRETTY));
4078 json_object_free(json);
4079 }
4080
4081 return CMD_SUCCESS;
4082 }
4083
4084 /* Display per ESI routing table */
4085 DEFUN(show_bgp_l2vpn_evpn_route_esi,
4086 show_bgp_l2vpn_evpn_route_esi_cmd,
4087 "show bgp l2vpn evpn route esi ESI [json]",
4088 SHOW_STR
4089 BGP_STR
4090 L2VPN_HELP_STR
4091 EVPN_HELP_STR
4092 "EVPN route information\n"
4093 "Ethernet Segment Identifier\n"
4094 "ESI ID\n"
4095 JSON_STR)
4096 {
4097 bool uj = false;
4098 esi_t esi;
4099 struct bgp *bgp = NULL;
4100 json_object *json = NULL;
4101
4102 memset(&esi, 0, sizeof(esi));
4103 bgp = bgp_get_evpn();
4104 if (!bgp)
4105 return CMD_WARNING;
4106
4107 uj = use_json(argc, argv);
4108 if (uj)
4109 json = json_object_new_object();
4110
4111 /* get the ESI - ESI-ID is at argv[6] */
4112 if (!str_to_esi(argv[6]->arg, &esi)) {
4113 vty_out(vty, "%% Malformed ESI\n");
4114 return CMD_WARNING;
4115 }
4116
4117 evpn_show_routes_esi(vty, bgp, &esi, json);
4118
4119 if (uj) {
4120 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4121 json, JSON_C_TO_STRING_PRETTY));
4122 json_object_free(json);
4123 }
4124
4125 return CMD_SUCCESS;
4126 }
4127
4128
4129 /*
4130 * Display per-VNI EVPN routing table.
4131 */
4132 DEFUN(show_bgp_l2vpn_evpn_route_vni, show_bgp_l2vpn_evpn_route_vni_cmd,
4133 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4134 SHOW_STR
4135 BGP_STR
4136 L2VPN_HELP_STR
4137 EVPN_HELP_STR
4138 "EVPN route information\n"
4139 "VXLAN Network Identifier\n"
4140 "VNI number\n"
4141 "Specify Route type\n"
4142 "MAC-IP (Type-2) route\n"
4143 "Multicast (Type-3) route\n"
4144 "Remote VTEP\n"
4145 "Remote VTEP IP address\n"
4146 JSON_STR)
4147 {
4148 vni_t vni;
4149 struct bgp *bgp;
4150 struct in_addr vtep_ip;
4151 int type = 0;
4152 int idx = 0;
4153 bool uj = false;
4154 json_object *json = NULL;
4155
4156 bgp = bgp_get_evpn();
4157 if (!bgp)
4158 return CMD_WARNING;
4159
4160 /* check if we need json output */
4161 uj = use_json(argc, argv);
4162 if (uj)
4163 json = json_object_new_object();
4164
4165 if (!argv_find(argv, argc, "evpn", &idx))
4166 return CMD_WARNING;
4167
4168 vtep_ip.s_addr = 0;
4169
4170 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4171
4172 if ((!uj && ((argc == (idx + 1 + 5)) && argv[idx + 4]->arg))
4173 || (uj && ((argc == (idx + 1 + 6)) && argv[idx + 4]->arg))) {
4174 if (strncmp(argv[idx + 4]->arg, "type", 4) == 0) {
4175 if (strncmp(argv[idx + 5]->arg, "ma", 2) == 0)
4176 type = BGP_EVPN_MAC_IP_ROUTE;
4177 else if (strncmp(argv[idx + 5]->arg, "mu", 2) == 0)
4178 type = BGP_EVPN_IMET_ROUTE;
4179 else
4180 return CMD_WARNING;
4181 } else if (strncmp(argv[idx + 4]->arg, "vtep", 4) == 0) {
4182 if (!inet_aton(argv[idx + 5]->arg, &vtep_ip)) {
4183 vty_out(vty, "%% Malformed VTEP IP address\n");
4184 return CMD_WARNING;
4185 }
4186 } else
4187 return CMD_WARNING;
4188 }
4189
4190 evpn_show_routes_vni(vty, bgp, vni, type, vtep_ip, json);
4191
4192 if (uj) {
4193 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4194 json, JSON_C_TO_STRING_PRETTY));
4195 json_object_free(json);
4196 }
4197
4198 return CMD_SUCCESS;
4199 }
4200
4201 /*
4202 * Display per-VNI EVPN routing table for specific MACIP.
4203 */
4204 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip,
4205 show_bgp_l2vpn_evpn_route_vni_macip_cmd,
4206 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD] [json]",
4207 SHOW_STR
4208 BGP_STR
4209 L2VPN_HELP_STR
4210 EVPN_HELP_STR
4211 "EVPN route information\n"
4212 "VXLAN Network Identifier\n"
4213 "VNI number\n"
4214 "MAC\n"
4215 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4216 "IP\n"
4217 "IP address (IPv4 or IPv6)\n"
4218 JSON_STR)
4219 {
4220 vni_t vni;
4221 struct bgp *bgp;
4222 struct ethaddr mac;
4223 struct ipaddr ip;
4224 int idx = 0;
4225 bool uj = false;
4226 json_object *json = NULL;
4227
4228 bgp = bgp_get_evpn();
4229 if (!bgp)
4230 return CMD_WARNING;
4231
4232 /* check if we need json output */
4233 uj = use_json(argc, argv);
4234 if (uj)
4235 json = json_object_new_object();
4236
4237 if (!argv_find(argv, argc, "evpn", &idx))
4238 return CMD_WARNING;
4239
4240 /* get the VNI */
4241 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4242
4243 /* get the mac */
4244 if (!prefix_str2mac(argv[idx + 5]->arg, &mac)) {
4245 vty_out(vty, "%% Malformed MAC address\n");
4246 return CMD_WARNING;
4247 }
4248
4249 /* get the ip */
4250 memset(&ip, 0, sizeof(ip));
4251 if ((!uj && ((argc == (idx + 1 + 7)) && argv[idx + 7]->arg != NULL))
4252 || (uj
4253 && ((argc == (idx + 1 + 8)) && argv[idx + 7]->arg != NULL))) {
4254 if (str2ipaddr(argv[idx + 7]->arg, &ip) != 0) {
4255 vty_out(vty, "%% Malformed IP address\n");
4256 return CMD_WARNING;
4257 }
4258 }
4259
4260 evpn_show_route_vni_macip(vty, bgp, vni, &mac, &ip, json);
4261
4262 if (uj) {
4263 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4264 json, JSON_C_TO_STRING_PRETTY));
4265 json_object_free(json);
4266 }
4267
4268 return CMD_SUCCESS;
4269 }
4270
4271 /*
4272 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4273 */
4274 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast,
4275 show_bgp_l2vpn_evpn_route_vni_multicast_cmd,
4276 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D [json]",
4277 SHOW_STR
4278 BGP_STR
4279 L2VPN_HELP_STR
4280 EVPN_HELP_STR
4281 "EVPN route information\n"
4282 "VXLAN Network Identifier\n"
4283 "VNI number\n"
4284 "Multicast (Type-3) route\n"
4285 "Originating Router IP address\n"
4286 JSON_STR)
4287 {
4288 vni_t vni;
4289 struct bgp *bgp;
4290 int ret;
4291 struct in_addr orig_ip;
4292 int idx = 0;
4293 bool uj = false;
4294 json_object *json = NULL;
4295
4296 bgp = bgp_get_evpn();
4297 if (!bgp)
4298 return CMD_WARNING;
4299
4300 /* check if we need json output */
4301 uj = use_json(argc, argv);
4302 if (uj)
4303 json = json_object_new_object();
4304
4305 if (!argv_find(argv, argc, "evpn", &idx))
4306 return CMD_WARNING;
4307
4308 /* get the VNI */
4309 vni = strtoul(argv[idx + 3]->arg, NULL, 10);
4310
4311 /* get the ip */
4312 ret = inet_aton(argv[idx + 5]->arg, &orig_ip);
4313 if (!ret) {
4314 vty_out(vty, "%% Malformed Originating Router IP address\n");
4315 return CMD_WARNING;
4316 }
4317
4318 evpn_show_route_vni_multicast(vty, bgp, vni, orig_ip, json);
4319
4320 if (uj) {
4321 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4322 json, JSON_C_TO_STRING_PRETTY));
4323 json_object_free(json);
4324 }
4325
4326 return CMD_SUCCESS;
4327 }
4328
4329 /*
4330 * Display per-VNI EVPN routing table - for all VNIs.
4331 */
4332 DEFUN(show_bgp_l2vpn_evpn_route_vni_all,
4333 show_bgp_l2vpn_evpn_route_vni_all_cmd,
4334 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4335 SHOW_STR
4336 BGP_STR
4337 L2VPN_HELP_STR
4338 EVPN_HELP_STR
4339 "EVPN route information\n"
4340 "VXLAN Network Identifier\n"
4341 "All VNIs\n"
4342 "Print Detailed Output\n"
4343 "Remote VTEP\n"
4344 "Remote VTEP IP address\n"
4345 JSON_STR)
4346 {
4347 struct bgp *bgp;
4348 struct in_addr vtep_ip;
4349 int idx = 0;
4350 bool uj = false;
4351 json_object *json = NULL;
4352 /* Detail Adjust. Adjust indexes according to detail option */
4353 int da = 0;
4354
4355 bgp = bgp_get_evpn();
4356 if (!bgp)
4357 return CMD_WARNING;
4358
4359 /* check if we need json output */
4360 uj = use_json(argc, argv);
4361 if (uj)
4362 json = json_object_new_object();
4363
4364 if (!argv_find(argv, argc, "evpn", &idx))
4365 return CMD_WARNING;
4366
4367 if (argv_find(argv, argc, "detail", &da))
4368 da = 1;
4369
4370 /* vtep-ip position depends on detail option */
4371 vtep_ip.s_addr = 0;
4372 if ((!uj && (argc == (idx + 1 + 5 + da) && argv[idx + 5 + da]->arg))
4373 || (uj
4374 && (argc == (idx + 1 + 6 + da) && argv[idx + 5 + da]->arg))) {
4375 if (!inet_aton(argv[idx + 5 + da]->arg, &vtep_ip)) {
4376 vty_out(vty, "%% Malformed VTEP IP address\n");
4377 return CMD_WARNING;
4378 }
4379 }
4380
4381 evpn_show_routes_vni_all(vty, bgp, vtep_ip, json, da);
4382
4383 if (uj) {
4384 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4385 json, JSON_C_TO_STRING_PRETTY));
4386 json_object_free(json);
4387 }
4388
4389 return CMD_SUCCESS;
4390 }
4391
4392 /*
4393 * Display EVPN import route-target hash table
4394 */
4395 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt,
4396 show_bgp_l2vpn_evpn_vrf_import_rt_cmd,
4397 "show bgp l2vpn evpn vrf-import-rt [json]",
4398 SHOW_STR
4399 BGP_STR
4400 L2VPN_HELP_STR
4401 EVPN_HELP_STR
4402 "Show vrf import route target\n"
4403 JSON_STR)
4404 {
4405 bool uj = false;
4406 struct bgp *bgp_evpn = NULL;
4407 json_object *json = NULL;
4408
4409 bgp_evpn = bgp_get_evpn();
4410 if (!bgp_evpn)
4411 return CMD_WARNING;
4412
4413 uj = use_json(argc, argv);
4414 if (uj)
4415 json = json_object_new_object();
4416
4417 evpn_show_vrf_import_rts(vty, bgp_evpn, json);
4418
4419 if (uj) {
4420 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4421 json, JSON_C_TO_STRING_PRETTY));
4422 json_object_free(json);
4423 }
4424
4425 return CMD_SUCCESS;
4426 }
4427
4428 /*
4429 * Display EVPN import route-target hash table
4430 */
4431 DEFUN(show_bgp_l2vpn_evpn_import_rt,
4432 show_bgp_l2vpn_evpn_import_rt_cmd,
4433 "show bgp l2vpn evpn import-rt [json]",
4434 SHOW_STR
4435 BGP_STR
4436 L2VPN_HELP_STR
4437 EVPN_HELP_STR
4438 "Show import route target\n"
4439 JSON_STR)
4440 {
4441 struct bgp *bgp;
4442 bool uj = false;
4443 json_object *json = NULL;
4444
4445 bgp = bgp_get_evpn();
4446 if (!bgp)
4447 return CMD_WARNING;
4448
4449 uj = use_json(argc, argv);
4450 if (uj)
4451 json = json_object_new_object();
4452
4453 evpn_show_import_rts(vty, bgp, json);
4454
4455 if (uj) {
4456 vty_out(vty, "%s\n", json_object_to_json_string_ext(
4457 json, JSON_C_TO_STRING_PRETTY));
4458 json_object_free(json);
4459 }
4460
4461 return CMD_SUCCESS;
4462 }
4463
4464 DEFUN(test_adv_evpn_type4_route,
4465 test_adv_evpn_type4_route_cmd,
4466 "advertise es ESI",
4467 "Advertise EVPN ES route\n"
4468 "Ethernet-segment\n"
4469 "Ethernet-Segment Identifier\n")
4470 {
4471 int ret = 0;
4472 esi_t esi;
4473 struct bgp *bgp;
4474 struct ipaddr vtep_ip;
4475
4476 bgp = bgp_get_evpn();
4477 if (!bgp) {
4478 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4479 return CMD_WARNING;
4480 }
4481
4482 if (!str_to_esi(argv[2]->arg, &esi)) {
4483 vty_out(vty, "%%Malformed ESI\n");
4484 return CMD_WARNING;
4485 }
4486
4487 vtep_ip.ipa_type = IPADDR_V4;
4488 vtep_ip.ipaddr_v4 = bgp->router_id;
4489
4490 ret = bgp_evpn_local_es_add(bgp, &esi, &vtep_ip);
4491 if (ret == -1) {
4492 vty_out(vty, "%%Failed to EVPN advertise type-4 route\n");
4493 return CMD_WARNING;
4494 }
4495 return CMD_SUCCESS;
4496 }
4497
4498 DEFUN(test_withdraw_evpn_type4_route,
4499 test_withdraw_evpn_type4_route_cmd,
4500 "withdraw es ESI",
4501 "Advertise EVPN ES route\n"
4502 "Ethernet-segment\n"
4503 "Ethernet-Segment Identifier\n")
4504 {
4505 int ret = 0;
4506 esi_t esi;
4507 struct bgp *bgp;
4508 struct ipaddr vtep_ip;
4509
4510 bgp = bgp_get_evpn();
4511 if (!bgp) {
4512 vty_out(vty, "%%EVPN BGP instance not yet created\n");
4513 return CMD_WARNING;
4514 }
4515
4516 if (!bgp->peer_self) {
4517 vty_out(vty, "%%BGP instance doesn't have self peer\n");
4518 return CMD_WARNING;
4519 }
4520
4521 if (!str_to_esi(argv[2]->arg, &esi)) {
4522 vty_out(vty, "%%Malformed ESI\n");
4523 return CMD_WARNING;
4524 }
4525
4526 vtep_ip.ipa_type = IPADDR_V4;
4527 vtep_ip.ipaddr_v4 = bgp->router_id;
4528 ret = bgp_evpn_local_es_del(bgp, &esi, &vtep_ip);
4529 if (ret == -1) {
4530 vty_out(vty, "%%Failed to withdraw EVPN type-4 route\n");
4531 return CMD_WARNING;
4532 }
4533 return CMD_SUCCESS;
4534 }
4535
4536 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni, show_bgp_evpn_vni_cmd,
4537 "show bgp evpn vni [" CMD_VNI_RANGE "]", SHOW_STR BGP_STR EVPN_HELP_STR
4538 "Show VNI\n"
4539 "VNI number\n")
4540
4541 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary, show_bgp_evpn_summary_cmd,
4542 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4543 "Summary of BGP neighbor status\n" JSON_STR)
4544
4545 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route, show_bgp_evpn_route_cmd,
4546 "show bgp evpn route [detail] [type <macip|multicast>]",
4547 SHOW_STR BGP_STR EVPN_HELP_STR
4548 "EVPN route information\n"
4549 "Display Detailed Information\n"
4550 "Specify Route type\n"
4551 "MAC-IP (Type-2) route\n"
4552 "Multicast (Type-3) route\n")
4553
4554 ALIAS_HIDDEN(
4555 show_bgp_l2vpn_evpn_route_rd, show_bgp_evpn_route_rd_cmd,
4556 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4557 SHOW_STR BGP_STR EVPN_HELP_STR
4558 "EVPN route information\n"
4559 "Route Distinguisher\n"
4560 "ASN:XX or A.B.C.D:XX\n"
4561 "Specify Route type\n"
4562 "MAC-IP (Type-2) route\n"
4563 "Multicast (Type-3) route\n")
4564
4565 ALIAS_HIDDEN(
4566 show_bgp_l2vpn_evpn_route_rd_macip, show_bgp_evpn_route_rd_macip_cmd,
4567 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4568 SHOW_STR BGP_STR EVPN_HELP_STR
4569 "EVPN route information\n"
4570 "Route Distinguisher\n"
4571 "ASN:XX or A.B.C.D:XX\n"
4572 "MAC\n"
4573 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4574 "IP\n"
4575 "IP address (IPv4 or IPv6)\n")
4576
4577 ALIAS_HIDDEN(
4578 show_bgp_l2vpn_evpn_route_vni, show_bgp_evpn_route_vni_cmd,
4579 "show bgp evpn route vni " CMD_VNI_RANGE " [<type <macip|multicast> | vtep A.B.C.D>]",
4580 SHOW_STR BGP_STR EVPN_HELP_STR
4581 "EVPN route information\n"
4582 "VXLAN Network Identifier\n"
4583 "VNI number\n"
4584 "Specify Route type\n"
4585 "MAC-IP (Type-2) route\n"
4586 "Multicast (Type-3) route\n"
4587 "Remote VTEP\n"
4588 "Remote VTEP IP address\n")
4589
4590 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip,
4591 show_bgp_evpn_route_vni_macip_cmd,
4592 "show bgp evpn route vni " CMD_VNI_RANGE " mac WORD [ip WORD]",
4593 SHOW_STR BGP_STR EVPN_HELP_STR
4594 "EVPN route information\n"
4595 "VXLAN Network Identifier\n"
4596 "VNI number\n"
4597 "MAC\n"
4598 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4599 "IP\n"
4600 "IP address (IPv4 or IPv6)\n")
4601
4602 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast,
4603 show_bgp_evpn_route_vni_multicast_cmd,
4604 "show bgp evpn route vni " CMD_VNI_RANGE " multicast A.B.C.D",
4605 SHOW_STR BGP_STR EVPN_HELP_STR
4606 "EVPN route information\n"
4607 "VXLAN Network Identifier\n"
4608 "VNI number\n"
4609 "Multicast (Type-3) route\n"
4610 "Originating Router IP address\n")
4611
4612 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all, show_bgp_evpn_route_vni_all_cmd,
4613 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4614 SHOW_STR BGP_STR EVPN_HELP_STR
4615 "EVPN route information\n"
4616 "VXLAN Network Identifier\n"
4617 "All VNIs\n"
4618 "Print Detailed Output\n"
4619 "Remote VTEP\n"
4620 "Remote VTEP IP address\n")
4621
4622 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt, show_bgp_evpn_import_rt_cmd,
4623 "show bgp evpn import-rt",
4624 SHOW_STR BGP_STR EVPN_HELP_STR "Show import route target\n")
4625
4626 DEFUN_NOSH (bgp_evpn_vni,
4627 bgp_evpn_vni_cmd,
4628 "vni " CMD_VNI_RANGE,
4629 "VXLAN Network Identifier\n"
4630 "VNI number\n")
4631 {
4632 vni_t vni;
4633 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4634 struct bgpevpn *vpn;
4635
4636 if (!bgp)
4637 return CMD_WARNING;
4638
4639 vni = strtoul(argv[1]->arg, NULL, 10);
4640
4641 /* Create VNI, or mark as configured. */
4642 vpn = evpn_create_update_vni(bgp, vni);
4643 if (!vpn) {
4644 vty_out(vty, "%% Failed to create VNI \n");
4645 return CMD_WARNING;
4646 }
4647
4648 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE, vpn);
4649 return CMD_SUCCESS;
4650 }
4651
4652 DEFUN (no_bgp_evpn_vni,
4653 no_bgp_evpn_vni_cmd,
4654 "no vni " CMD_VNI_RANGE,
4655 NO_STR
4656 "VXLAN Network Identifier\n"
4657 "VNI number\n")
4658 {
4659 vni_t vni;
4660 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4661 struct bgpevpn *vpn;
4662
4663 if (!bgp)
4664 return CMD_WARNING;
4665
4666 vni = strtoul(argv[2]->arg, NULL, 10);
4667
4668 /* Check if we should disallow. */
4669 vpn = bgp_evpn_lookup_vni(bgp, vni);
4670 if (!vpn) {
4671 vty_out(vty, "%% Specified VNI does not exist\n");
4672 return CMD_WARNING;
4673 }
4674 if (!is_vni_configured(vpn)) {
4675 vty_out(vty, "%% Specified VNI is not configured\n");
4676 return CMD_WARNING;
4677 }
4678
4679 evpn_delete_vni(bgp, vpn);
4680 return CMD_SUCCESS;
4681 }
4682
4683 DEFUN_NOSH (exit_vni,
4684 exit_vni_cmd,
4685 "exit-vni",
4686 "Exit from VNI mode\n")
4687 {
4688 if (vty->node == BGP_EVPN_VNI_NODE)
4689 vty->node = BGP_EVPN_NODE;
4690 return CMD_SUCCESS;
4691 }
4692
4693 DEFUN (bgp_evpn_vrf_rd,
4694 bgp_evpn_vrf_rd_cmd,
4695 "rd ASN:NN_OR_IP-ADDRESS:NN",
4696 "Route Distinguisher\n"
4697 "ASN:XX or A.B.C.D:XX\n")
4698 {
4699 int ret;
4700 struct prefix_rd prd;
4701 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4702
4703 if (!bgp_vrf)
4704 return CMD_WARNING;
4705
4706 ret = str2prefix_rd(argv[1]->arg, &prd);
4707 if (!ret) {
4708 vty_out(vty, "%% Malformed Route Distinguisher\n");
4709 return CMD_WARNING;
4710 }
4711
4712 /* If same as existing value, there is nothing more to do. */
4713 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd))
4714 return CMD_SUCCESS;
4715
4716 /* Configure or update the RD. */
4717 evpn_configure_vrf_rd(bgp_vrf, &prd);
4718 return CMD_SUCCESS;
4719 }
4720
4721 DEFUN (no_bgp_evpn_vrf_rd,
4722 no_bgp_evpn_vrf_rd_cmd,
4723 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4724 NO_STR
4725 "Route Distinguisher\n"
4726 "ASN:XX or A.B.C.D:XX\n")
4727 {
4728 int ret;
4729 struct prefix_rd prd;
4730 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4731
4732 if (!bgp_vrf)
4733 return CMD_WARNING;
4734
4735 ret = str2prefix_rd(argv[2]->arg, &prd);
4736 if (!ret) {
4737 vty_out(vty, "%% Malformed Route Distinguisher\n");
4738 return CMD_WARNING;
4739 }
4740
4741 /* Check if we should disallow. */
4742 if (!is_vrf_rd_configured(bgp_vrf)) {
4743 vty_out(vty, "%% RD is not configured for this VRF\n");
4744 return CMD_WARNING;
4745 }
4746
4747 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf, &prd)) {
4748 vty_out(vty,
4749 "%% RD specified does not match configuration for this VRF\n");
4750 return CMD_WARNING;
4751 }
4752
4753 evpn_unconfigure_vrf_rd(bgp_vrf);
4754 return CMD_SUCCESS;
4755 }
4756
4757 DEFUN (no_bgp_evpn_vrf_rd_without_val,
4758 no_bgp_evpn_vrf_rd_without_val_cmd,
4759 "no rd",
4760 NO_STR
4761 "Route Distinguisher\n")
4762 {
4763 struct bgp *bgp_vrf = VTY_GET_CONTEXT(bgp);
4764
4765 if (!bgp_vrf)
4766 return CMD_WARNING;
4767
4768 /* Check if we should disallow. */
4769 if (!is_vrf_rd_configured(bgp_vrf)) {
4770 vty_out(vty, "%% RD is not configured for this VRF\n");
4771 return CMD_WARNING;
4772 }
4773
4774 evpn_unconfigure_vrf_rd(bgp_vrf);
4775 return CMD_SUCCESS;
4776 }
4777
4778 DEFUN (bgp_evpn_vni_rd,
4779 bgp_evpn_vni_rd_cmd,
4780 "rd ASN:NN_OR_IP-ADDRESS:NN",
4781 "Route Distinguisher\n"
4782 "ASN:XX or A.B.C.D:XX\n")
4783 {
4784 struct prefix_rd prd;
4785 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4786 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4787 int ret;
4788
4789 if (!bgp)
4790 return CMD_WARNING;
4791
4792 if (!EVPN_ENABLED(bgp)) {
4793 vty_out(vty,
4794 "This command is only supported under EVPN VRF\n");
4795 return CMD_WARNING;
4796 }
4797
4798 ret = str2prefix_rd(argv[1]->arg, &prd);
4799 if (!ret) {
4800 vty_out(vty, "%% Malformed Route Distinguisher\n");
4801 return CMD_WARNING;
4802 }
4803
4804 /* If same as existing value, there is nothing more to do. */
4805 if (bgp_evpn_rd_matches_existing(vpn, &prd))
4806 return CMD_SUCCESS;
4807
4808 /* Configure or update the RD. */
4809 evpn_configure_rd(bgp, vpn, &prd);
4810 return CMD_SUCCESS;
4811 }
4812
4813 DEFUN (no_bgp_evpn_vni_rd,
4814 no_bgp_evpn_vni_rd_cmd,
4815 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4816 NO_STR
4817 "Route Distinguisher\n"
4818 "ASN:XX or A.B.C.D:XX\n")
4819 {
4820 struct prefix_rd prd;
4821 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4822 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4823 int ret;
4824
4825 if (!bgp)
4826 return CMD_WARNING;
4827
4828 if (!EVPN_ENABLED(bgp)) {
4829 vty_out(vty,
4830 "This command is only supported under EVPN VRF\n");
4831 return CMD_WARNING;
4832 }
4833
4834 ret = str2prefix_rd(argv[2]->arg, &prd);
4835 if (!ret) {
4836 vty_out(vty, "%% Malformed Route Distinguisher\n");
4837 return CMD_WARNING;
4838 }
4839
4840 /* Check if we should disallow. */
4841 if (!is_rd_configured(vpn)) {
4842 vty_out(vty, "%% RD is not configured for this VNI\n");
4843 return CMD_WARNING;
4844 }
4845
4846 if (!bgp_evpn_rd_matches_existing(vpn, &prd)) {
4847 vty_out(vty,
4848 "%% RD specified does not match configuration for this VNI\n");
4849 return CMD_WARNING;
4850 }
4851
4852 evpn_unconfigure_rd(bgp, vpn);
4853 return CMD_SUCCESS;
4854 }
4855
4856 DEFUN (no_bgp_evpn_vni_rd_without_val,
4857 no_bgp_evpn_vni_rd_without_val_cmd,
4858 "no rd",
4859 NO_STR
4860 "Route Distinguisher\n")
4861 {
4862 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
4863 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
4864
4865 if (!bgp)
4866 return CMD_WARNING;
4867
4868 if (!EVPN_ENABLED(bgp)) {
4869 vty_out(vty,
4870 "This command is only supported under EVPN VRF\n");
4871 return CMD_WARNING;
4872 }
4873
4874 /* Check if we should disallow. */
4875 if (!is_rd_configured(vpn)) {
4876 vty_out(vty, "%% RD is not configured for this VNI\n");
4877 return CMD_WARNING;
4878 }
4879
4880 evpn_unconfigure_rd(bgp, vpn);
4881 return CMD_SUCCESS;
4882 }
4883
4884 /*
4885 * Loop over all extended-communities in the route-target list rtl and
4886 * return 1 if we find ecomtarget
4887 */
4888 static int bgp_evpn_rt_matches_existing(struct list *rtl,
4889 struct ecommunity *ecomtarget)
4890 {
4891 struct listnode *node, *nnode;
4892 struct ecommunity *ecom;
4893
4894 for (ALL_LIST_ELEMENTS(rtl, node, nnode, ecom)) {
4895 if (ecommunity_match(ecom, ecomtarget))
4896 return 1;
4897 }
4898
4899 return 0;
4900 }
4901
4902 /* display L3VNI related info for a VRF instance */
4903 DEFUN (show_bgp_vrf_l3vni_info,
4904 show_bgp_vrf_l3vni_info_cmd,
4905 "show bgp vrf VRFNAME vni [json]",
4906 SHOW_STR
4907 BGP_STR
4908 "show bgp vrf\n"
4909 "VRF Name\n"
4910 "L3-VNI\n"
4911 JSON_STR)
4912 {
4913 char buf[ETHER_ADDR_STRLEN];
4914 char buf1[INET6_ADDRSTRLEN];
4915 int idx_vrf = 3;
4916 const char *name = NULL;
4917 struct bgp *bgp = NULL;
4918 struct listnode *node = NULL;
4919 struct bgpevpn *vpn = NULL;
4920 struct ecommunity *ecom = NULL;
4921 json_object *json = NULL;
4922 json_object *json_vnis = NULL;
4923 json_object *json_export_rts = NULL;
4924 json_object *json_import_rts = NULL;
4925 bool uj = use_json(argc, argv);
4926
4927 if (uj) {
4928 json = json_object_new_object();
4929 json_vnis = json_object_new_array();
4930 json_export_rts = json_object_new_array();
4931 json_import_rts = json_object_new_array();
4932 }
4933
4934 name = argv[idx_vrf]->arg;
4935 bgp = bgp_lookup_by_name(name);
4936 if (!bgp) {
4937 if (!uj)
4938 vty_out(vty, "BGP instance for VRF %s not found", name);
4939 else {
4940 json_object_string_add(json, "warning",
4941 "BGP instance not found");
4942 vty_out(vty, "%s\n", json_object_to_json_string(json));
4943 json_object_free(json);
4944 }
4945 return CMD_WARNING;
4946 }
4947
4948 if (!json) {
4949 vty_out(vty, "BGP VRF: %s\n", name);
4950 vty_out(vty, " Local-Ip: %s\n", inet_ntoa(bgp->originator_ip));
4951 vty_out(vty, " L3-VNI: %u\n", bgp->l3vni);
4952 vty_out(vty, " Rmac: %s\n",
4953 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4954 vty_out(vty, " VNI Filter: %s\n",
4955 CHECK_FLAG(bgp->vrf_flags,
4956 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4957 ? "prefix-routes-only"
4958 : "none");
4959 vty_out(vty, " L2-VNI List:\n");
4960 vty_out(vty, " ");
4961 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4962 vty_out(vty, "%u ", vpn->vni);
4963 vty_out(vty, "\n");
4964 vty_out(vty, " Export-RTs:\n");
4965 vty_out(vty, " ");
4966 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4967 vty_out(vty, "%s ", ecommunity_str(ecom));
4968 vty_out(vty, "\n");
4969 vty_out(vty, " Import-RTs:\n");
4970 vty_out(vty, " ");
4971 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
4972 vty_out(vty, "%s ", ecommunity_str(ecom));
4973 vty_out(vty, "\n");
4974 vty_out(vty, " RD: %s\n",
4975 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
4976 } else {
4977 json_object_string_add(json, "vrf", name);
4978 json_object_string_add(json, "local-ip",
4979 inet_ntoa(bgp->originator_ip));
4980 json_object_int_add(json, "l3vni", bgp->l3vni);
4981 json_object_string_add(
4982 json, "rmac",
4983 prefix_mac2str(&bgp->rmac, buf, sizeof(buf)));
4984 json_object_string_add(
4985 json, "vniFilter",
4986 CHECK_FLAG(bgp->vrf_flags,
4987 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY)
4988 ? "prefix-routes-only"
4989 : "none");
4990 /* list of l2vnis */
4991 for (ALL_LIST_ELEMENTS_RO(bgp->l2vnis, node, vpn))
4992 json_object_array_add(json_vnis,
4993 json_object_new_int(vpn->vni));
4994 json_object_object_add(json, "l2vnis", json_vnis);
4995
4996 /* export rts */
4997 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_export_rtl, node, ecom))
4998 json_object_array_add(
4999 json_export_rts,
5000 json_object_new_string(ecommunity_str(ecom)));
5001 json_object_object_add(json, "export-rts", json_export_rts);
5002
5003 /* import rts */
5004 for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
5005 json_object_array_add(
5006 json_import_rts,
5007 json_object_new_string(ecommunity_str(ecom)));
5008 json_object_object_add(json, "import-rts", json_import_rts);
5009 json_object_string_add(
5010 json, "rd",
5011 prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
5012 }
5013
5014 if (uj) {
5015 vty_out(vty, "%s\n", json_object_to_json_string_ext(
5016 json, JSON_C_TO_STRING_PRETTY));
5017 json_object_free(json);
5018 }
5019 return CMD_SUCCESS;
5020 }
5021
5022 /* import/export rt for l3vni-vrf */
5023 DEFUN (bgp_evpn_vrf_rt,
5024 bgp_evpn_vrf_rt_cmd,
5025 "route-target <both|import|export> RT",
5026 "Route Target\n"
5027 "import and export\n"
5028 "import\n"
5029 "export\n"
5030 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5031 {
5032 int rt_type;
5033 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5034 struct ecommunity *ecomadd = NULL;
5035
5036 if (!bgp)
5037 return CMD_WARNING;
5038
5039 if (!strcmp(argv[1]->arg, "import"))
5040 rt_type = RT_TYPE_IMPORT;
5041 else if (!strcmp(argv[1]->arg, "export"))
5042 rt_type = RT_TYPE_EXPORT;
5043 else if (!strcmp(argv[1]->arg, "both"))
5044 rt_type = RT_TYPE_BOTH;
5045 else {
5046 vty_out(vty, "%% Invalid Route Target type\n");
5047 return CMD_WARNING;
5048 }
5049
5050 /* Add/update the import route-target */
5051 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5052 ecomadd = ecommunity_str2com(argv[2]->arg,
5053 ECOMMUNITY_ROUTE_TARGET, 0);
5054 if (!ecomadd) {
5055 vty_out(vty, "%% Malformed Route Target list\n");
5056 return CMD_WARNING;
5057 }
5058 ecommunity_str(ecomadd);
5059
5060 /* Do nothing if we already have this import route-target */
5061 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl, ecomadd))
5062 bgp_evpn_configure_import_rt_for_vrf(bgp, ecomadd);
5063 }
5064
5065 /* Add/update the export route-target */
5066 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5067 ecomadd = ecommunity_str2com(argv[2]->arg,
5068 ECOMMUNITY_ROUTE_TARGET, 0);
5069 if (!ecomadd) {
5070 vty_out(vty, "%% Malformed Route Target list\n");
5071 return CMD_WARNING;
5072 }
5073 ecommunity_str(ecomadd);
5074
5075 /* Do nothing if we already have this export route-target */
5076 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl, ecomadd))
5077 bgp_evpn_configure_export_rt_for_vrf(bgp, ecomadd);
5078 }
5079
5080 return CMD_SUCCESS;
5081 }
5082
5083 DEFUN (no_bgp_evpn_vrf_rt,
5084 no_bgp_evpn_vrf_rt_cmd,
5085 "no route-target <both|import|export> RT",
5086 NO_STR
5087 "Route Target\n"
5088 "import and export\n"
5089 "import\n"
5090 "export\n"
5091 "ASN:XX or A.B.C.D:XX\n")
5092 {
5093 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5094 int rt_type, found_ecomdel;
5095 struct ecommunity *ecomdel = NULL;
5096
5097 if (!bgp)
5098 return CMD_WARNING;
5099
5100 if (!strcmp(argv[2]->arg, "import"))
5101 rt_type = RT_TYPE_IMPORT;
5102 else if (!strcmp(argv[2]->arg, "export"))
5103 rt_type = RT_TYPE_EXPORT;
5104 else if (!strcmp(argv[2]->arg, "both"))
5105 rt_type = RT_TYPE_BOTH;
5106 else {
5107 vty_out(vty, "%% Invalid Route Target type\n");
5108 return CMD_WARNING;
5109 }
5110
5111 if (rt_type == RT_TYPE_IMPORT) {
5112 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5113 vty_out(vty,
5114 "%% Import RT is not configured for this VRF\n");
5115 return CMD_WARNING;
5116 }
5117 } else if (rt_type == RT_TYPE_EXPORT) {
5118 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5119 vty_out(vty,
5120 "%% Export RT is not configured for this VRF\n");
5121 return CMD_WARNING;
5122 }
5123 } else if (rt_type == RT_TYPE_BOTH) {
5124 if (!CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)
5125 && !CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5126 vty_out(vty,
5127 "%% Import/Export RT is not configured for this VRF\n");
5128 return CMD_WARNING;
5129 }
5130 }
5131
5132 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5133 if (!ecomdel) {
5134 vty_out(vty, "%% Malformed Route Target list\n");
5135 return CMD_WARNING;
5136 }
5137 ecommunity_str(ecomdel);
5138
5139 if (rt_type == RT_TYPE_IMPORT) {
5140 if (!bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5141 ecomdel)) {
5142 vty_out(vty,
5143 "%% RT specified does not match configuration for this VRF\n");
5144 return CMD_WARNING;
5145 }
5146 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5147 } else if (rt_type == RT_TYPE_EXPORT) {
5148 if (!bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5149 ecomdel)) {
5150 vty_out(vty,
5151 "%% RT specified does not match configuration for this VRF\n");
5152 return CMD_WARNING;
5153 }
5154 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5155 } else if (rt_type == RT_TYPE_BOTH) {
5156 found_ecomdel = 0;
5157
5158 if (bgp_evpn_rt_matches_existing(bgp->vrf_import_rtl,
5159 ecomdel)) {
5160 bgp_evpn_unconfigure_import_rt_for_vrf(bgp, ecomdel);
5161 found_ecomdel = 1;
5162 }
5163
5164 if (bgp_evpn_rt_matches_existing(bgp->vrf_export_rtl,
5165 ecomdel)) {
5166 bgp_evpn_unconfigure_export_rt_for_vrf(bgp, ecomdel);
5167 found_ecomdel = 1;
5168 }
5169
5170 if (!found_ecomdel) {
5171 vty_out(vty,
5172 "%% RT specified does not match configuration for this VRF\n");
5173 return CMD_WARNING;
5174 }
5175 }
5176
5177 return CMD_SUCCESS;
5178 }
5179
5180 DEFUN (bgp_evpn_vni_rt,
5181 bgp_evpn_vni_rt_cmd,
5182 "route-target <both|import|export> RT",
5183 "Route Target\n"
5184 "import and export\n"
5185 "import\n"
5186 "export\n"
5187 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5188 {
5189 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5190 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5191 int rt_type;
5192 struct ecommunity *ecomadd = NULL;
5193
5194 if (!bgp)
5195 return CMD_WARNING;
5196
5197 if (!EVPN_ENABLED(bgp)) {
5198 vty_out(vty,
5199 "This command is only supported under EVPN VRF\n");
5200 return CMD_WARNING;
5201 }
5202
5203 if (!strcmp(argv[1]->text, "import"))
5204 rt_type = RT_TYPE_IMPORT;
5205 else if (!strcmp(argv[1]->text, "export"))
5206 rt_type = RT_TYPE_EXPORT;
5207 else if (!strcmp(argv[1]->text, "both"))
5208 rt_type = RT_TYPE_BOTH;
5209 else {
5210 vty_out(vty, "%% Invalid Route Target type\n");
5211 return CMD_WARNING;
5212 }
5213
5214 /* Add/update the import route-target */
5215 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_IMPORT) {
5216 ecomadd = ecommunity_str2com(argv[2]->arg,
5217 ECOMMUNITY_ROUTE_TARGET, 0);
5218 if (!ecomadd) {
5219 vty_out(vty, "%% Malformed Route Target list\n");
5220 return CMD_WARNING;
5221 }
5222 ecommunity_str(ecomadd);
5223
5224 /* Do nothing if we already have this import route-target */
5225 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomadd))
5226 evpn_configure_import_rt(bgp, vpn, ecomadd);
5227 }
5228
5229 /* Add/update the export route-target */
5230 if (rt_type == RT_TYPE_BOTH || rt_type == RT_TYPE_EXPORT) {
5231 ecomadd = ecommunity_str2com(argv[2]->arg,
5232 ECOMMUNITY_ROUTE_TARGET, 0);
5233 if (!ecomadd) {
5234 vty_out(vty, "%% Malformed Route Target list\n");
5235 return CMD_WARNING;
5236 }
5237 ecommunity_str(ecomadd);
5238
5239 /* Do nothing if we already have this export route-target */
5240 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomadd))
5241 evpn_configure_export_rt(bgp, vpn, ecomadd);
5242 }
5243
5244 return CMD_SUCCESS;
5245 }
5246
5247 DEFUN (no_bgp_evpn_vni_rt,
5248 no_bgp_evpn_vni_rt_cmd,
5249 "no route-target <both|import|export> RT",
5250 NO_STR
5251 "Route Target\n"
5252 "import and export\n"
5253 "import\n"
5254 "export\n"
5255 "ASN:XX or A.B.C.D:XX\n")
5256 {
5257 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5258 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5259 int rt_type, found_ecomdel;
5260 struct ecommunity *ecomdel = NULL;
5261
5262 if (!bgp)
5263 return CMD_WARNING;
5264
5265 if (!EVPN_ENABLED(bgp)) {
5266 vty_out(vty,
5267 "This command is only supported under EVPN VRF\n");
5268 return CMD_WARNING;
5269 }
5270
5271 if (!strcmp(argv[2]->text, "import"))
5272 rt_type = RT_TYPE_IMPORT;
5273 else if (!strcmp(argv[2]->text, "export"))
5274 rt_type = RT_TYPE_EXPORT;
5275 else if (!strcmp(argv[2]->text, "both"))
5276 rt_type = RT_TYPE_BOTH;
5277 else {
5278 vty_out(vty, "%% Invalid Route Target type\n");
5279 return CMD_WARNING;
5280 }
5281
5282 /* The user did "no route-target import", check to see if there are any
5283 * import route-targets configured. */
5284 if (rt_type == RT_TYPE_IMPORT) {
5285 if (!is_import_rt_configured(vpn)) {
5286 vty_out(vty,
5287 "%% Import RT is not configured for this VNI\n");
5288 return CMD_WARNING;
5289 }
5290 } else if (rt_type == RT_TYPE_EXPORT) {
5291 if (!is_export_rt_configured(vpn)) {
5292 vty_out(vty,
5293 "%% Export RT is not configured for this VNI\n");
5294 return CMD_WARNING;
5295 }
5296 } else if (rt_type == RT_TYPE_BOTH) {
5297 if (!is_import_rt_configured(vpn)
5298 && !is_export_rt_configured(vpn)) {
5299 vty_out(vty,
5300 "%% Import/Export RT is not configured for this VNI\n");
5301 return CMD_WARNING;
5302 }
5303 }
5304
5305 ecomdel = ecommunity_str2com(argv[3]->arg, ECOMMUNITY_ROUTE_TARGET, 0);
5306 if (!ecomdel) {
5307 vty_out(vty, "%% Malformed Route Target list\n");
5308 return CMD_WARNING;
5309 }
5310 ecommunity_str(ecomdel);
5311
5312 if (rt_type == RT_TYPE_IMPORT) {
5313 if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5314 vty_out(vty,
5315 "%% RT specified does not match configuration for this VNI\n");
5316 return CMD_WARNING;
5317 }
5318 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5319 } else if (rt_type == RT_TYPE_EXPORT) {
5320 if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5321 vty_out(vty,
5322 "%% RT specified does not match configuration for this VNI\n");
5323 return CMD_WARNING;
5324 }
5325 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5326 } else if (rt_type == RT_TYPE_BOTH) {
5327 found_ecomdel = 0;
5328
5329 if (bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
5330 evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
5331 found_ecomdel = 1;
5332 }
5333
5334 if (bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
5335 evpn_unconfigure_export_rt(bgp, vpn, ecomdel);
5336 found_ecomdel = 1;
5337 }
5338
5339 if (!found_ecomdel) {
5340 vty_out(vty,
5341 "%% RT specified does not match configuration for this VNI\n");
5342 return CMD_WARNING;
5343 }
5344 }
5345
5346 return CMD_SUCCESS;
5347 }
5348
5349 DEFUN (no_bgp_evpn_vni_rt_without_val,
5350 no_bgp_evpn_vni_rt_without_val_cmd,
5351 "no route-target <import|export>",
5352 NO_STR
5353 "Route Target\n"
5354 "import\n"
5355 "export\n")
5356 {
5357 struct bgp *bgp = VTY_GET_CONTEXT(bgp);
5358 VTY_DECLVAR_CONTEXT_SUB(bgpevpn, vpn);
5359 int rt_type;
5360
5361 if (!bgp)
5362 return CMD_WARNING;
5363
5364 if (!EVPN_ENABLED(bgp)) {
5365 vty_out(vty,
5366 "This command is only supported under EVPN VRF\n");
5367 return CMD_WARNING;
5368 }
5369
5370 if (!strcmp(argv[2]->text, "import")) {
5371 rt_type = RT_TYPE_IMPORT;
5372 } else if (!strcmp(argv[2]->text, "export")) {
5373 rt_type = RT_TYPE_EXPORT;
5374 } else {
5375 vty_out(vty, "%% Invalid Route Target type\n");
5376 return CMD_WARNING;
5377 }
5378
5379 /* Check if we should disallow. */
5380 if (rt_type == RT_TYPE_IMPORT) {
5381 if (!is_import_rt_configured(vpn)) {
5382 vty_out(vty,
5383 "%% Import RT is not configured for this VNI\n");
5384 return CMD_WARNING;
5385 }
5386 } else {
5387 if (!is_export_rt_configured(vpn)) {
5388 vty_out(vty,
5389 "%% Export RT is not configured for this VNI\n");
5390 return CMD_WARNING;
5391 }
5392 }
5393
5394 /* Unconfigure the RT. */
5395 if (rt_type == RT_TYPE_IMPORT)
5396 evpn_unconfigure_import_rt(bgp, vpn, NULL);
5397 else
5398 evpn_unconfigure_export_rt(bgp, vpn, NULL);
5399 return CMD_SUCCESS;
5400 }
5401
5402 static int vni_cmp(const void **a, const void **b)
5403 {
5404 const struct bgpevpn *first = *a;
5405 const struct bgpevpn *secnd = *b;
5406
5407 return secnd->vni - first->vni;
5408 }
5409
5410 /*
5411 * Output EVPN configuration information.
5412 */
5413 void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
5414 safi_t safi)
5415 {
5416 char buf1[RD_ADDRSTRLEN];
5417
5418 if (bgp->vnihash) {
5419 struct list *vnilist = hash_to_list(bgp->vnihash);
5420 struct listnode *ln;
5421 struct bgpevpn *data;
5422
5423 list_sort(vnilist, vni_cmp);
5424 for (ALL_LIST_ELEMENTS_RO(vnilist, ln, data))
5425 write_vni_config(vty, data);
5426
5427 list_delete(&vnilist);
5428 }
5429
5430 if (bgp->advertise_all_vni)
5431 vty_out(vty, " advertise-all-vni\n");
5432
5433 if (bgp->advertise_autort_rfc8365)
5434 vty_out(vty, " autort rfc8365-compatible\n");
5435
5436 if (bgp->advertise_gw_macip)
5437 vty_out(vty, " advertise-default-gw\n");
5438
5439 if (bgp->evpn_info->advertise_svi_macip)
5440 vty_out(vty, " advertise-svi-ip\n");
5441
5442 if (!bgp->evpn_info->dup_addr_detect)
5443 vty_out(vty, " no dup-addr-detection\n");
5444
5445 if (bgp->evpn_info->dad_max_moves !=
5446 EVPN_DAD_DEFAULT_MAX_MOVES ||
5447 bgp->evpn_info->dad_time != EVPN_DAD_DEFAULT_TIME)
5448 vty_out(vty, " dup-addr-detection max-moves %u time %u\n",
5449 bgp->evpn_info->dad_max_moves,
5450 bgp->evpn_info->dad_time);
5451
5452 if (bgp->evpn_info->dad_freeze) {
5453 if (bgp->evpn_info->dad_freeze_time)
5454 vty_out(vty,
5455 " dup-addr-detection freeze %u\n",
5456 bgp->evpn_info->dad_freeze_time);
5457 else
5458 vty_out(vty,
5459 " dup-addr-detection freeze permanent\n");
5460 }
5461
5462 if (bgp->vxlan_flood_ctrl == VXLAN_FLOOD_DISABLED)
5463 vty_out(vty, " flooding disable\n");
5464
5465 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5466 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST)) {
5467 if (bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name)
5468 vty_out(vty, " advertise ipv4 unicast route-map %s\n",
5469 bgp->adv_cmd_rmap[AFI_IP][SAFI_UNICAST].name);
5470 else
5471 vty_out(vty, " advertise ipv4 unicast\n");
5472 }
5473
5474 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5475 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST)) {
5476 if (bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name)
5477 vty_out(vty, " advertise ipv6 unicast route-map %s\n",
5478 bgp->adv_cmd_rmap[AFI_IP6][SAFI_UNICAST].name);
5479 else
5480 vty_out(vty, " advertise ipv6 unicast\n");
5481 }
5482
5483 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5484 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4))
5485 vty_out(vty, " default-originate ipv4\n");
5486
5487 if (CHECK_FLAG(bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
5488 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6))
5489 vty_out(vty, " default-originate ipv6\n");
5490
5491 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
5492 vty_out(vty, " rd %s\n",
5493 prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
5494
5495 /* import route-target */
5496 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
5497 char *ecom_str;
5498 struct listnode *node, *nnode;
5499 struct ecommunity *ecom;
5500
5501 for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode,
5502 ecom)) {
5503 ecom_str = ecommunity_ecom2str(
5504 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5505 vty_out(vty, " route-target import %s\n", ecom_str);
5506 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5507 }
5508 }
5509
5510 /* export route-target */
5511 if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_EXPORT_RT_CFGD)) {
5512 char *ecom_str;
5513 struct listnode *node, *nnode;
5514 struct ecommunity *ecom;
5515
5516 for (ALL_LIST_ELEMENTS(bgp->vrf_export_rtl, node, nnode,
5517 ecom)) {
5518 ecom_str = ecommunity_ecom2str(
5519 ecom, ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
5520 vty_out(vty, " route-target export %s\n", ecom_str);
5521 XFREE(MTYPE_ECOMMUNITY_STR, ecom_str);
5522 }
5523 }
5524 }
5525
5526 void bgp_ethernetvpn_init(void)
5527 {
5528 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_cmd);
5529 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_cmd);
5530 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_tags_cmd);
5531 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd);
5532 install_element(VIEW_NODE,
5533 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd);
5534 install_element(VIEW_NODE,
5535 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd);
5536 install_element(
5537 VIEW_NODE,
5538 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd);
5539 install_element(
5540 VIEW_NODE,
5541 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd);
5542 install_element(VIEW_NODE, &show_ip_bgp_evpn_rd_overlay_cmd);
5543 install_element(VIEW_NODE, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd);
5544 install_element(BGP_EVPN_NODE, &no_evpnrt5_network_cmd);
5545 install_element(BGP_EVPN_NODE, &evpnrt5_network_cmd);
5546 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_all_vni_cmd);
5547 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_all_vni_cmd);
5548 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_autort_rfc8365_cmd);
5549 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_autort_rfc8365_cmd);
5550 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_default_gw_cmd);
5551 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_default_gw_cmd);
5552 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_svi_ip_cmd);
5553 install_element(BGP_EVPN_NODE, &bgp_evpn_advertise_type5_cmd);
5554 install_element(BGP_EVPN_NODE, &no_bgp_evpn_advertise_type5_cmd);
5555 install_element(BGP_EVPN_NODE, &bgp_evpn_default_originate_cmd);
5556 install_element(BGP_EVPN_NODE, &no_bgp_evpn_default_originate_cmd);
5557 install_element(BGP_EVPN_NODE, &dup_addr_detection_cmd);
5558 install_element(BGP_EVPN_NODE, &dup_addr_detection_auto_recovery_cmd);
5559 install_element(BGP_EVPN_NODE, &no_dup_addr_detection_cmd);
5560 install_element(BGP_EVPN_NODE, &bgp_evpn_flood_control_cmd);
5561
5562 /* test commands */
5563 install_element(BGP_EVPN_NODE, &test_adv_evpn_type4_route_cmd);
5564 install_element(BGP_EVPN_NODE, &test_withdraw_evpn_type4_route_cmd);
5565
5566 /* "show bgp l2vpn evpn" commands. */
5567 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_es_cmd);
5568 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vni_cmd);
5569 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_summary_cmd);
5570 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_cmd);
5571 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_cmd);
5572 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_rd_macip_cmd);
5573 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_esi_cmd);
5574 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_cmd);
5575 install_element(VIEW_NODE,
5576 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd);
5577 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_macip_cmd);
5578 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_route_vni_all_cmd);
5579 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_import_rt_cmd);
5580 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd);
5581
5582 /* "show bgp evpn" commands. */
5583 install_element(VIEW_NODE, &show_bgp_evpn_vni_cmd);
5584 install_element(VIEW_NODE, &show_bgp_evpn_summary_cmd);
5585 install_element(VIEW_NODE, &show_bgp_evpn_route_cmd);
5586 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_cmd);
5587 install_element(VIEW_NODE, &show_bgp_evpn_route_rd_macip_cmd);
5588 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_cmd);
5589 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_multicast_cmd);
5590 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_macip_cmd);
5591 install_element(VIEW_NODE, &show_bgp_evpn_route_vni_all_cmd);
5592 install_element(VIEW_NODE, &show_bgp_evpn_import_rt_cmd);
5593 install_element(VIEW_NODE, &show_bgp_vrf_l3vni_info_cmd);
5594 install_element(VIEW_NODE, &show_bgp_l2vpn_evpn_com_cmd);
5595
5596 install_element(BGP_EVPN_NODE, &bgp_evpn_vni_cmd);
5597 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vni_cmd);
5598 install_element(BGP_EVPN_VNI_NODE, &exit_vni_cmd);
5599 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rd_cmd);
5600 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_cmd);
5601 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rd_without_val_cmd);
5602 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_vni_rt_cmd);
5603 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_cmd);
5604 install_element(BGP_EVPN_VNI_NODE, &no_bgp_evpn_vni_rt_without_val_cmd);
5605 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rd_cmd);
5606 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rd_cmd);
5607 install_element(BGP_NODE, &no_bgp_evpn_vrf_rd_without_val_cmd);
5608 install_element(BGP_EVPN_NODE, &bgp_evpn_vrf_rt_cmd);
5609 install_element(BGP_EVPN_NODE, &no_bgp_evpn_vrf_rt_cmd);
5610 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_svi_ip_vni_cmd);
5611 install_element(BGP_EVPN_VNI_NODE,
5612 &bgp_evpn_advertise_default_gw_vni_cmd);
5613 install_element(BGP_EVPN_VNI_NODE,
5614 &no_bgp_evpn_advertise_default_gw_vni_cmd);
5615 install_element(BGP_EVPN_VNI_NODE, &bgp_evpn_advertise_vni_subnet_cmd);
5616 install_element(BGP_EVPN_VNI_NODE,
5617 &no_bgp_evpn_advertise_vni_subnet_cmd);
5618 }