1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
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
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.
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
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"
41 #define SHOW_DISPLAY_STANDARD 0
42 #define SHOW_DISPLAY_TAGS 1
43 #define SHOW_DISPLAY_OVERLAY 2
44 #define VNI_STR_LEN 32
47 * Context for VNI hash walk - used by callbacks.
52 struct in_addr vtep_ip
;
57 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
61 uint8_t type
, sub_type
;
62 struct ecommunity_as eas
;
63 struct ecommunity_ip eip
;
64 struct listnode
*node
, *nnode
;
65 struct bgp
*tmp_bgp_vrf
= NULL
;
66 json_object
*json_rt
= NULL
;
67 json_object
*json_vrfs
= NULL
;
68 char rt_buf
[RT_ADDRSTRLEN
];
71 json_rt
= json_object_new_object();
72 json_vrfs
= json_object_new_array();
75 pnt
= (uint8_t *)&irt
->rt
.val
;
78 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
81 memset(&eas
, 0, sizeof(eas
));
83 case ECOMMUNITY_ENCODE_AS
:
84 eas
.as
= (*pnt
++ << 8);
86 ptr_get_be32(pnt
, &eas
.val
);
88 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
91 json_object_string_add(json_rt
, "rt", rt_buf
);
93 vty_out(vty
, "Route-target: %s", rt_buf
);
97 case ECOMMUNITY_ENCODE_IP
:
98 memcpy(&eip
.ip
, pnt
, 4);
100 eip
.val
= (*pnt
++ << 8);
103 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
107 json_object_string_add(json_rt
, "rt", rt_buf
);
109 vty_out(vty
, "Route-target: %s", rt_buf
);
113 case ECOMMUNITY_ENCODE_AS4
:
114 pnt
= ptr_get_be32(pnt
, &eas
.val
);
115 eas
.val
= (*pnt
++ << 8);
118 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
121 json_object_string_add(json_rt
, "rt", rt_buf
);
123 vty_out(vty
, "Route-target: %s", rt_buf
);
133 "\nList of VRFs importing routes with this route-target:\n");
136 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
138 json_object_array_add(
140 json_object_new_string(
141 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
143 vty_out(vty
, " %s\n",
144 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
148 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
149 json_object_object_add(json
, rt_buf
, json_rt
);
153 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
155 json_object
*json
= NULL
;
156 struct vty
*vty
= NULL
;
157 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
159 vty
= (struct vty
*)args
[0];
160 json
= (struct json_object
*)args
[1];
162 display_vrf_import_rt(vty
, irt
, json
);
165 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
169 uint8_t type
, sub_type
;
170 struct ecommunity_as eas
;
171 struct ecommunity_ip eip
;
172 struct listnode
*node
, *nnode
;
173 struct bgpevpn
*tmp_vpn
;
174 json_object
*json_rt
= NULL
;
175 json_object
*json_vnis
= NULL
;
176 char rt_buf
[RT_ADDRSTRLEN
];
179 json_rt
= json_object_new_object();
180 json_vnis
= json_object_new_array();
183 /* TODO: This needs to go into a function */
185 pnt
= (uint8_t *)&irt
->rt
.val
;
188 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
191 memset(&eas
, 0, sizeof(eas
));
193 case ECOMMUNITY_ENCODE_AS
:
194 eas
.as
= (*pnt
++ << 8);
196 ptr_get_be32(pnt
, &eas
.val
);
198 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
201 json_object_string_add(json_rt
, "rt", rt_buf
);
203 vty_out(vty
, "Route-target: %s", rt_buf
);
207 case ECOMMUNITY_ENCODE_IP
:
208 memcpy(&eip
.ip
, pnt
, 4);
210 eip
.val
= (*pnt
++ << 8);
213 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
217 json_object_string_add(json_rt
, "rt", rt_buf
);
219 vty_out(vty
, "Route-target: %s", rt_buf
);
223 case ECOMMUNITY_ENCODE_AS4
:
224 pnt
= ptr_get_be32(pnt
, &eas
.val
);
225 eas
.val
= (*pnt
++ << 8);
228 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
231 json_object_string_add(json_rt
, "rt", rt_buf
);
233 vty_out(vty
, "Route-target: %s", rt_buf
);
243 "\nList of VNIs importing routes with this route-target:\n");
246 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
248 json_object_array_add(
249 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
251 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
255 json_object_object_add(json_rt
, "vnis", json_vnis
);
256 json_object_object_add(json
, rt_buf
, json_rt
);
260 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
262 json_object
*json
= NULL
;
263 struct vty
*vty
= NULL
;
264 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
269 display_import_rt(vty
, irt
, json
);
274 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
275 struct bgp_node
*rd_rn
,
282 char rd_str
[RD_ADDRSTRLEN
];
284 pnt
= rd_rn
->p
.u
.val
;
286 /* Decode RD type. */
287 type
= decode_rd_type(pnt
);
292 vty_out(vty
, "Route Distinguisher: ");
296 decode_rd_as(pnt
+ 2, &rd_as
);
297 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
301 decode_rd_ip(pnt
+ 2, &rd_ip
);
302 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
307 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
311 vty_out(vty
, "%s\n", rd_str
);
314 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
315 uint64_t tbl_ver
, json_object
*json
)
318 " Network Next Hop Metric LocPrf Weight Path\n";
323 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
324 tbl_ver
, inet_ntoa(bgp
->router_id
));
326 "Status codes: s suppressed, d damped, h history, "
327 "* valid, > best, i - internal\n");
328 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
330 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
331 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
332 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
333 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
334 vty_out(vty
, "%s", ri_header
);
337 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
340 char buf1
[INET6_ADDRSTRLEN
];
342 struct listnode
*node
, *nnode
;
343 struct ecommunity
*ecom
;
344 json_object
*json_import_rtl
= NULL
;
345 json_object
*json_export_rtl
= NULL
;
347 json_import_rtl
= json_export_rtl
= 0;
350 json_import_rtl
= json_object_new_array();
351 json_export_rtl
= json_object_new_array();
352 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
353 json_object_string_add(json
, "type", "L3");
354 json_object_string_add(json
, "kernelFlag", "Yes");
355 json_object_string_add(
357 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
358 json_object_string_add(json
, "originatorIp",
359 inet_ntoa(bgp_vrf
->originator_ip
));
360 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
361 json_object_string_add(json
, "advertiseSviMacip", "n/a");
362 json_object_to_json_string_ext(json
,
363 JSON_C_TO_STRING_NOSLASHESCAPE
);
365 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
366 vty_out(vty
, " (known to the kernel)");
369 vty_out(vty
, " Type: %s\n", "L3");
370 vty_out(vty
, " Tenant VRF: %s\n",
371 vrf_id_to_name(bgp_vrf
->vrf_id
));
372 vty_out(vty
, " RD: %s\n",
373 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
374 vty_out(vty
, " Originator IP: %s\n",
375 inet_ntoa(bgp_vrf
->originator_ip
));
376 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
377 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
381 vty_out(vty
, " Import Route Target:\n");
383 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
384 ecom_str
= ecommunity_ecom2str(ecom
,
385 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
388 json_object_array_add(json_import_rtl
,
389 json_object_new_string(ecom_str
));
391 vty_out(vty
, " %s\n", ecom_str
);
393 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
397 json_object_object_add(json
, "importRts", json_import_rtl
);
399 vty_out(vty
, " Export Route Target:\n");
401 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
402 ecom_str
= ecommunity_ecom2str(ecom
,
403 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
406 json_object_array_add(json_export_rtl
,
407 json_object_new_string(ecom_str
));
409 vty_out(vty
, " %s\n", ecom_str
);
411 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
415 json_object_object_add(json
, "exportRts", json_export_rtl
);
418 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
420 struct in_addr
*vtep
;
421 char buf
[ESI_STR_LEN
];
422 char buf1
[RD_ADDRSTRLEN
];
423 char buf2
[INET6_ADDRSTRLEN
];
424 struct listnode
*node
= NULL
;
425 json_object
*json_vteps
= NULL
;
428 json_vteps
= json_object_new_array();
429 json_object_string_add(json
, "esi",
430 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
431 json_object_string_add(json
, "rd",
432 prefix_rd2str(&es
->prd
, buf1
,
434 json_object_string_add(
435 json
, "originatorIp",
436 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
438 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
439 json_object_array_add(
440 json_vteps
, json_object_new_string(
443 json_object_object_add(json
, "vteps", json_vteps
);
445 vty_out(vty
, "ESI: %s\n",
446 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
447 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
449 vty_out(vty
, " Originator-IP: %s\n",
450 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
452 vty_out(vty
, " VTEP List:\n");
453 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
454 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
459 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
461 char buf1
[RD_ADDRSTRLEN
];
463 struct listnode
*node
, *nnode
;
464 struct ecommunity
*ecom
;
465 json_object
*json_import_rtl
= NULL
;
466 json_object
*json_export_rtl
= NULL
;
467 struct bgp
*bgp_evpn
;
469 bgp_evpn
= bgp_get_evpn();
472 json_import_rtl
= json_object_new_array();
473 json_export_rtl
= json_object_new_array();
474 json_object_int_add(json
, "vni", vpn
->vni
);
475 json_object_string_add(json
, "type", "L2");
476 json_object_string_add(json
, "kernelFlag",
477 is_vni_live(vpn
) ? "Yes" : "No");
478 json_object_string_add(
480 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
481 json_object_string_add(json
, "originatorIp",
482 inet_ntoa(vpn
->originator_ip
));
483 json_object_string_add(json
, "mcastGroup",
484 inet_ntoa(vpn
->mcast_grp
));
485 /* per vni knob is enabled -- Enabled
486 * Global knob is enabled -- Active
487 * default -- Disabled
489 if (!vpn
->advertise_gw_macip
&&
490 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
491 json_object_string_add(json
, "advertiseGatewayMacip",
493 else if (vpn
->advertise_gw_macip
)
494 json_object_string_add(json
, "advertiseGatewayMacip",
497 json_object_string_add(json
, "advertiseGatewayMacip",
499 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
500 bgp_evpn
->evpn_info
->advertise_svi_macip
)
501 json_object_string_add(json
, "advertiseSviMacip",
503 else if (vpn
->advertise_svi_macip
)
504 json_object_string_add(json
, "advertiseSviMacip",
507 json_object_string_add(json
, "advertiseSviMacip",
510 vty_out(vty
, "VNI: %d", vpn
->vni
);
511 if (is_vni_live(vpn
))
512 vty_out(vty
, " (known to the kernel)");
515 vty_out(vty
, " Type: %s\n", "L2");
516 vty_out(vty
, " Tenant-Vrf: %s\n",
517 vrf_id_to_name(vpn
->tenant_vrf_id
));
518 vty_out(vty
, " RD: %s\n",
519 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
520 vty_out(vty
, " Originator IP: %s\n",
521 inet_ntoa(vpn
->originator_ip
));
522 vty_out(vty
, " Mcast group: %s\n",
523 inet_ntoa(vpn
->mcast_grp
));
524 if (!vpn
->advertise_gw_macip
&&
525 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
526 vty_out(vty
, " Advertise-gw-macip : %s\n",
528 else if (vpn
->advertise_gw_macip
)
529 vty_out(vty
, " Advertise-gw-macip : %s\n",
532 vty_out(vty
, " Advertise-gw-macip : %s\n",
534 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
535 bgp_evpn
->evpn_info
->advertise_svi_macip
)
536 vty_out(vty
, " Advertise-svi-macip : %s\n",
538 else if (vpn
->advertise_svi_macip
)
539 vty_out(vty
, " Advertise-svi-macip : %s\n",
542 vty_out(vty
, " Advertise-svi-macip : %s\n",
547 vty_out(vty
, " Import Route Target:\n");
549 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
550 ecom_str
= ecommunity_ecom2str(ecom
,
551 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
554 json_object_array_add(json_import_rtl
,
555 json_object_new_string(ecom_str
));
557 vty_out(vty
, " %s\n", ecom_str
);
559 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
563 json_object_object_add(json
, "importRts", json_import_rtl
);
565 vty_out(vty
, " Export Route Target:\n");
567 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
568 ecom_str
= ecommunity_ecom2str(ecom
,
569 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
572 json_object_array_add(json_export_rtl
,
573 json_object_new_string(ecom_str
));
575 vty_out(vty
, " %s\n", ecom_str
);
577 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
581 json_object_object_add(json
, "exportRts", json_export_rtl
);
584 static void show_esi_routes(struct bgp
*bgp
,
591 struct bgp_path_info
*pi
;
592 uint32_t prefix_cnt
, path_cnt
;
595 prefix_cnt
= path_cnt
= 0;
597 tbl_ver
= es
->route_table
->version
;
598 for (rn
= bgp_table_top(es
->route_table
); rn
;
599 rn
= bgp_route_next(rn
)) {
600 int add_prefix_to_json
= 0;
601 char prefix_str
[BUFSIZ
];
602 json_object
*json_paths
= NULL
;
603 json_object
*json_prefix
= NULL
;
605 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
609 json_prefix
= json_object_new_object();
611 pi
= bgp_node_get_bgp_path_info(rn
);
613 /* Overall header/legend displayed once. */
615 bgp_evpn_show_route_header(vty
, bgp
,
624 json_paths
= json_object_new_array();
626 /* For EVPN, the prefix is displayed for each path (to fit in
627 * with code that already exists).
629 for (; pi
; pi
= pi
->next
) {
630 json_object
*json_path
= NULL
;
633 json_path
= json_object_new_array();
635 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
638 json_object_array_add(json_paths
, json_path
);
641 add_prefix_to_json
= 1;
644 if (json
&& add_prefix_to_json
) {
645 json_object_string_add(json_prefix
, "prefix",
647 json_object_int_add(json_prefix
, "prefixLen",
649 json_object_object_add(json_prefix
, "paths",
651 json_object_object_add(json
, prefix_str
, json_prefix
);
656 json_object_int_add(json
, "numPrefix", prefix_cnt
);
657 json_object_int_add(json
, "numPaths", path_cnt
);
660 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
662 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
663 prefix_cnt
, path_cnt
);
667 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
668 struct vty
*vty
, struct in_addr vtep_ip
,
669 json_object
*json
, int detail
)
672 struct bgp_path_info
*pi
;
673 struct bgp_table
*table
;
674 int header
= detail
? 0 : 1;
676 uint32_t prefix_cnt
, path_cnt
;
678 prefix_cnt
= path_cnt
= 0;
680 table
= vpn
->route_table
;
681 tbl_ver
= table
->version
;
682 for (rn
= bgp_table_top(table
); rn
;
683 rn
= bgp_route_next(rn
)) {
684 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
685 int add_prefix_to_json
= 0;
686 char prefix_str
[BUFSIZ
];
687 json_object
*json_paths
= NULL
;
688 json_object
*json_prefix
= NULL
;
690 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
693 if (type
&& evp
->prefix
.route_type
!= type
)
697 json_prefix
= json_object_new_object();
699 pi
= bgp_node_get_bgp_path_info(rn
);
701 /* Overall header/legend displayed once. */
703 bgp_evpn_show_route_header(vty
, bgp
,
712 json_paths
= json_object_new_array();
714 /* For EVPN, the prefix is displayed for each path (to fit in
715 * with code that already exists).
717 for (; pi
; pi
= pi
->next
) {
718 json_object
*json_path
= NULL
;
721 && !IPV4_ADDR_SAME(&(vtep_ip
),
722 &(pi
->attr
->nexthop
)))
726 json_path
= json_object_new_array();
729 route_vty_out_detail(vty
, bgp
, rn
, pi
,
730 AFI_L2VPN
, SAFI_EVPN
,
733 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
737 json_object_array_add(json_paths
, json_path
);
740 add_prefix_to_json
= 1;
743 if (json
&& add_prefix_to_json
) {
744 json_object_string_add(json_prefix
, "prefix",
746 json_object_int_add(json_prefix
, "prefixLen",
748 json_object_object_add(json_prefix
, "paths",
750 json_object_object_add(json
, prefix_str
, json_prefix
);
755 json_object_int_add(json
, "numPrefix", prefix_cnt
);
756 json_object_int_add(json
, "numPaths", path_cnt
);
759 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
760 type
? "(of requested type) " : "");
762 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
763 prefix_cnt
, path_cnt
,
764 type
? " (of requested type)" : "");
769 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
771 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
772 struct vni_walk_ctx
*wctx
= arg
;
773 struct vty
*vty
= wctx
->vty
;
774 json_object
*json
= wctx
->json
;
775 json_object
*json_vni
= NULL
;
776 char vni_str
[VNI_STR_LEN
];
778 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
780 json_vni
= json_object_new_object();
781 json_object_int_add(json_vni
, "vni", vpn
->vni
);
783 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
786 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
790 json_object_object_add(json
, vni_str
, json_vni
);
793 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
796 json_object
*json_vni
= NULL
;
797 json_object
*json_import_rtl
= NULL
;
798 json_object
*json_export_rtl
= NULL
;
800 char buf2
[INET6_ADDRSTRLEN
];
803 struct listnode
*node
, *nnode
;
804 struct ecommunity
*ecom
;
810 json_vni
= json_object_new_object();
811 json_import_rtl
= json_object_new_array();
812 json_export_rtl
= json_object_new_array();
815 /* if an l3vni is present in bgp it is live */
820 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
821 json_object_string_add(json_vni
, "type", "L3");
822 json_object_string_add(json_vni
, "inKernel", "True");
823 json_object_string_add(json_vni
, "originatorIp",
824 inet_ntoa(bgp
->originator_ip
));
825 json_object_string_add(
827 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
829 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
830 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
833 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
834 ecom_str
= ecommunity_ecom2str(ecom
,
835 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
838 json_object_array_add(json_import_rtl
,
839 json_object_new_string(ecom_str
));
841 if (listcount(bgp
->vrf_import_rtl
) > 1)
842 sprintf(rt_buf
, "%s, ...", ecom_str
);
844 sprintf(rt_buf
, "%s", ecom_str
);
845 vty_out(vty
, " %-25s", rt_buf
);
848 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
850 /* If there are multiple import RTs we break here and show only
857 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
859 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
860 ecom_str
= ecommunity_ecom2str(ecom
,
861 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
864 json_object_array_add(json_export_rtl
,
865 json_object_new_string(ecom_str
));
867 if (listcount(bgp
->vrf_export_rtl
) > 1)
868 sprintf(rt_buf
, "%s, ...", ecom_str
);
870 sprintf(rt_buf
, "%s", ecom_str
);
871 vty_out(vty
, " %-25s", rt_buf
);
874 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
876 /* If there are multiple export RTs we break here and show only
883 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
886 char vni_str
[VNI_STR_LEN
];
888 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
889 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
890 json_object_object_add(json
, vni_str
, json_vni
);
896 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
898 char buf
[ESI_STR_LEN
];
899 char buf1
[RD_ADDRSTRLEN
];
900 char buf2
[INET6_ADDRSTRLEN
];
901 struct in_addr
*vtep
= NULL
;
902 struct vty
*vty
= args
[0];
903 json_object
*json
= args
[1];
904 json_object
*json_vteps
= NULL
;
905 struct listnode
*node
= NULL
;
906 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
909 json_vteps
= json_object_new_array();
910 json_object_string_add(json
, "esi",
911 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
912 json_object_string_add(json
, "type",
913 is_es_local(es
) ? "Local" : "Remote");
914 json_object_string_add(json
, "rd",
915 prefix_rd2str(&es
->prd
, buf1
,
917 json_object_string_add(
918 json
, "originatorIp",
919 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
921 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
922 json_object_array_add(json_vteps
,
923 json_object_new_string(
926 json_object_object_add(json
, "vteps", json_vteps
);
928 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
929 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
930 is_es_local(es
) ? "Local" : "Remote",
931 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
932 ipaddr2str(&es
->originator_ip
, buf2
,
934 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
938 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
942 json_object
*json_vni
= NULL
;
943 json_object
*json_import_rtl
= NULL
;
944 json_object
*json_export_rtl
= NULL
;
945 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
947 char buf2
[RD_ADDRSTRLEN
];
950 struct listnode
*node
, *nnode
;
951 struct ecommunity
*ecom
;
957 json_vni
= json_object_new_object();
958 json_import_rtl
= json_object_new_array();
959 json_export_rtl
= json_object_new_array();
963 if (is_vni_live(vpn
))
967 json_object_int_add(json_vni
, "vni", vpn
->vni
);
968 json_object_string_add(json_vni
, "type", "L2");
969 json_object_string_add(json_vni
, "inKernel",
970 is_vni_live(vpn
) ? "True" : "False");
971 json_object_string_add(json_vni
, "originatorIp",
972 inet_ntoa(vpn
->originator_ip
));
973 json_object_string_add(json_vni
, "originatorIp",
974 inet_ntoa(vpn
->originator_ip
));
975 json_object_string_add(
977 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
979 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
980 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
983 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
984 ecom_str
= ecommunity_ecom2str(ecom
,
985 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
988 json_object_array_add(json_import_rtl
,
989 json_object_new_string(ecom_str
));
991 if (listcount(vpn
->import_rtl
) > 1)
992 sprintf(rt_buf
, "%s, ...", ecom_str
);
994 sprintf(rt_buf
, "%s", ecom_str
);
995 vty_out(vty
, " %-25s", rt_buf
);
998 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1000 /* If there are multiple import RTs we break here and show only
1007 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1009 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1010 ecom_str
= ecommunity_ecom2str(ecom
,
1011 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1014 json_object_array_add(json_export_rtl
,
1015 json_object_new_string(ecom_str
));
1017 if (listcount(vpn
->export_rtl
) > 1)
1018 sprintf(rt_buf
, "%s, ...", ecom_str
);
1020 sprintf(rt_buf
, "%s", ecom_str
);
1021 vty_out(vty
, " %-25s", rt_buf
);
1024 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1026 /* If there are multiple export RTs we break here and show only
1033 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1036 char vni_str
[VNI_STR_LEN
];
1038 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1039 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1040 json_object_object_add(json
, vni_str
, json_vni
);
1046 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1047 enum bgp_show_type type
, void *output_arg
,
1048 int option
, bool use_json
)
1050 afi_t afi
= AFI_L2VPN
;
1052 struct bgp_table
*table
;
1053 struct bgp_node
*rn
;
1054 struct bgp_node
*rm
;
1055 struct bgp_path_info
*pi
;
1058 char rd_str
[BUFSIZ
];
1061 unsigned long output_count
= 0;
1062 unsigned long total_count
= 0;
1063 json_object
*json
= NULL
;
1064 json_object
*json_nroute
= NULL
;
1065 json_object
*json_array
= NULL
;
1066 json_object
*json_prefix_info
= NULL
;
1068 memset(rd_str
, 0, BUFSIZ
);
1070 bgp
= bgp_get_evpn();
1073 vty_out(vty
, "No BGP process is configured\n");
1075 vty_out(vty
, "{}\n");
1080 json
= json_object_new_object();
1082 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1083 rn
= bgp_route_next(rn
)) {
1086 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1089 table
= bgp_node_get_bgp_table_info(rn
);
1094 tbl_ver
= table
->version
;
1096 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1098 json_array
= json_object_new_array();
1099 json_prefix_info
= json_object_new_object();
1101 json_object_string_add(json_prefix_info
,
1102 "prefix", bgp_evpn_route2str(
1103 (struct prefix_evpn
*)&rm
->p
, buf
,
1106 json_object_int_add(json_prefix_info
,
1107 "prefixLen", rm
->p
.prefixlen
);
1110 json_nroute
= json_object_new_object();
1113 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
1116 if (type
== bgp_show_type_neighbor
) {
1117 struct peer
*peer
= output_arg
;
1119 if (peer_cmp(peer
, pi
->peer
) != 0)
1124 json_object_int_add(
1125 json
, "bgpTableVersion",
1127 json_object_string_add(
1132 json_object_int_add(
1135 bgp
->default_local_pref
);
1136 json_object_int_add(
1140 if (option
== SHOW_DISPLAY_TAGS
)
1145 == SHOW_DISPLAY_OVERLAY
)
1150 "BGP table version is %" PRIu64
", local router ID is %s\n",
1155 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1157 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1158 vty_out(vty
, V4_HEADER
);
1171 /* Decode RD type. */
1172 type
= decode_rd_type(pnt
);
1173 /* Decode RD value. */
1174 if (type
== RD_TYPE_AS
)
1175 decode_rd_as(pnt
+ 2, &rd_as
);
1176 else if (type
== RD_TYPE_AS4
)
1177 decode_rd_as4(pnt
+ 2, &rd_as
);
1178 else if (type
== RD_TYPE_IP
)
1179 decode_rd_ip(pnt
+ 2, &rd_ip
);
1181 if (type
== RD_TYPE_AS
1182 || type
== RD_TYPE_AS4
)
1183 sprintf(rd_str
, "%u:%d",
1186 else if (type
== RD_TYPE_IP
)
1187 sprintf(rd_str
, "%s:%d",
1191 json_object_string_add(
1198 "Route Distinguisher: ");
1199 if (type
== RD_TYPE_AS
)
1204 else if (type
== RD_TYPE_AS4
)
1209 else if (type
== RD_TYPE_IP
)
1210 vty_out(vty
, "ip %s:%d",
1214 vty_out(vty
, "\n\n");
1219 if (option
== SHOW_DISPLAY_TAGS
)
1220 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1223 else if (option
== SHOW_DISPLAY_OVERLAY
)
1224 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1227 route_vty_out(vty
, &rm
->p
, pi
, 0,
1228 SAFI_EVPN
, json_array
);
1233 json_object_object_add(json_prefix_info
,
1234 "paths", json_array
);
1235 json_object_object_add(json_nroute
, buf
,
1241 json_object_object_add(json
, rd_str
, json_nroute
);
1245 json_object_int_add(json
, "numPrefix", output_count
);
1246 json_object_int_add(json
, "totalPrefix", total_count
);
1247 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1248 json
, JSON_C_TO_STRING_PRETTY
));
1249 json_object_free(json
);
1251 if (output_count
== 0)
1252 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1256 "\nDisplayed %ld out of %ld total prefixes\n",
1257 output_count
, total_count
);
1262 DEFUN(show_ip_bgp_l2vpn_evpn
,
1263 show_ip_bgp_l2vpn_evpn_cmd
,
1264 "show [ip] bgp l2vpn evpn [json]",
1265 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1267 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1268 use_json(argc
, argv
));
1271 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1272 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1273 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1279 "Display information for a route distinguisher\n"
1280 "VPN Route Distinguisher\n" JSON_STR
)
1282 int idx_ext_community
= 0;
1284 struct prefix_rd prd
;
1286 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1288 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1290 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1293 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1294 use_json(argc
, argv
));
1297 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1298 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1299 "show [ip] bgp l2vpn evpn all tags",
1305 "Display information about all EVPN NLRIs\n"
1306 "Display BGP tags for prefixes\n")
1308 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1312 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1313 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1314 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1320 "Display information for a route distinguisher\n"
1321 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1323 int idx_ext_community
= 0;
1325 struct prefix_rd prd
;
1327 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1329 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1331 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1334 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1338 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1339 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1340 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1346 "Detailed information on TCP and BGP neighbor connections\n"
1347 "IPv4 Neighbor to display information about\n"
1348 "IPv6 Neighbor to display information about\n"
1349 "Neighbor on BGP configured interface\n"
1350 "Display routes learned from neighbor\n" JSON_STR
)
1354 char *peerstr
= NULL
;
1355 bool uj
= use_json(argc
, argv
);
1356 afi_t afi
= AFI_L2VPN
;
1357 safi_t safi
= SAFI_EVPN
;
1358 struct bgp
*bgp
= NULL
;
1360 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1363 vty_out(vty
, "No index\n");
1367 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1368 argv_find(argv
, argc
, "neighbors", &idx
);
1369 peerstr
= argv
[++idx
]->arg
;
1371 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1374 json_object
*json_no
= NULL
;
1375 json_no
= json_object_new_object();
1376 json_object_string_add(json_no
, "warning",
1377 "Malformed address");
1378 vty_out(vty
, "%s\n",
1379 json_object_to_json_string(json_no
));
1380 json_object_free(json_no
);
1382 vty_out(vty
, "Malformed address: %s\n",
1386 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1388 json_object
*json_no
= NULL
;
1389 json_no
= json_object_new_object();
1390 json_object_string_add(
1392 "No such neighbor or address family");
1393 vty_out(vty
, "%s\n",
1394 json_object_to_json_string(json_no
));
1395 json_object_free(json_no
);
1397 vty_out(vty
, "%% No such neighbor or address family\n");
1401 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1405 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1406 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1407 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1413 "Display information for a route distinguisher\n"
1414 "VPN Route Distinguisher\n"
1415 "Detailed information on TCP and BGP neighbor connections\n"
1416 "IPv4 Neighbor to display information about\n"
1417 "IPv6 Neighbor to display information about\n"
1418 "Neighbor on BGP configured interface\n"
1419 "Display routes learned from neighbor\n" JSON_STR
)
1421 int idx_ext_community
= 0;
1425 char *peerstr
= NULL
;
1426 struct prefix_rd prd
;
1427 bool uj
= use_json(argc
, argv
);
1428 afi_t afi
= AFI_L2VPN
;
1429 safi_t safi
= SAFI_EVPN
;
1430 struct bgp
*bgp
= NULL
;
1432 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1435 vty_out(vty
, "No index\n");
1439 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1440 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1443 json_object
*json_no
= NULL
;
1444 json_no
= json_object_new_object();
1445 json_object_string_add(json_no
, "warning",
1446 "Malformed Route Distinguisher");
1447 vty_out(vty
, "%s\n",
1448 json_object_to_json_string(json_no
));
1449 json_object_free(json_no
);
1451 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1455 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1456 argv_find(argv
, argc
, "neighbors", &idx
);
1457 peerstr
= argv
[++idx
]->arg
;
1459 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1462 json_object
*json_no
= NULL
;
1463 json_no
= json_object_new_object();
1464 json_object_string_add(json_no
, "warning",
1465 "Malformed address");
1466 vty_out(vty
, "%s\n",
1467 json_object_to_json_string(json_no
));
1468 json_object_free(json_no
);
1470 vty_out(vty
, "Malformed address: %s\n",
1474 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1476 json_object
*json_no
= NULL
;
1477 json_no
= json_object_new_object();
1478 json_object_string_add(
1480 "No such neighbor or address family");
1481 vty_out(vty
, "%s\n",
1482 json_object_to_json_string(json_no
));
1483 json_object_free(json_no
);
1485 vty_out(vty
, "%% No such neighbor or address family\n");
1489 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1493 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1494 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1495 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1501 "Detailed information on TCP and BGP neighbor connections\n"
1502 "IPv4 Neighbor to display information about\n"
1503 "IPv6 Neighbor to display information about\n"
1504 "Neighbor on BGP configured interface\n"
1505 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1509 bool uj
= use_json(argc
, argv
);
1510 struct bgp
*bgp
= NULL
;
1511 afi_t afi
= AFI_L2VPN
;
1512 safi_t safi
= SAFI_EVPN
;
1513 char *peerstr
= NULL
;
1518 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1521 vty_out(vty
, "No index\n");
1525 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1526 argv_find(argv
, argc
, "neighbors", &idx
);
1527 peerstr
= argv
[++idx
]->arg
;
1529 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1532 json_object
*json_no
= NULL
;
1533 json_no
= json_object_new_object();
1534 json_object_string_add(json_no
, "warning",
1535 "Malformed address");
1536 vty_out(vty
, "%s\n",
1537 json_object_to_json_string(json_no
));
1538 json_object_free(json_no
);
1540 vty_out(vty
, "Malformed address: %s\n",
1544 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1546 json_object
*json_no
= NULL
;
1547 json_no
= json_object_new_object();
1548 json_object_string_add(
1550 "No such neighbor or address family");
1551 vty_out(vty
, "%s\n",
1552 json_object_to_json_string(json_no
));
1553 json_object_free(json_no
);
1555 vty_out(vty
, "%% No such neighbor or address family\n");
1559 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1562 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1563 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1564 "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]",
1570 "Display information for a route distinguisher\n"
1571 "VPN Route Distinguisher\n"
1572 "Detailed information on TCP and BGP neighbor connections\n"
1573 "IPv4 Neighbor to display information about\n"
1574 "IPv6 Neighbor to display information about\n"
1575 "Neighbor on BGP configured interface\n"
1576 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1578 int idx_ext_community
= 0;
1582 struct prefix_rd prd
;
1583 struct bgp
*bgp
= NULL
;
1584 bool uj
= use_json(argc
, argv
);
1585 char *peerstr
= NULL
;
1586 afi_t afi
= AFI_L2VPN
;
1587 safi_t safi
= SAFI_EVPN
;
1595 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1598 vty_out(vty
, "No index\n");
1602 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1604 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1605 argv_find(argv
, argc
, "neighbors", &idx
);
1606 peerstr
= argv
[++idx
]->arg
;
1608 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1611 json_object
*json_no
= NULL
;
1612 json_no
= json_object_new_object();
1613 json_object_string_add(json_no
, "warning",
1614 "Malformed address");
1615 vty_out(vty
, "%s\n",
1616 json_object_to_json_string(json_no
));
1617 json_object_free(json_no
);
1619 vty_out(vty
, "Malformed address: %s\n",
1623 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1625 json_object
*json_no
= NULL
;
1626 json_no
= json_object_new_object();
1627 json_object_string_add(
1629 "No such neighbor or address family");
1630 vty_out(vty
, "%s\n",
1631 json_object_to_json_string(json_no
));
1632 json_object_free(json_no
);
1634 vty_out(vty
, "%% No such neighbor or address family\n");
1638 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1641 json_object
*json_no
= NULL
;
1642 json_no
= json_object_new_object();
1643 json_object_string_add(json_no
, "warning",
1644 "Malformed Route Distinguisher");
1645 vty_out(vty
, "%s\n",
1646 json_object_to_json_string(json_no
));
1647 json_object_free(json_no
);
1649 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1653 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1656 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1657 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1658 "show [ip] bgp l2vpn evpn all overlay [json]",
1664 "Display information about all EVPN NLRIs\n"
1665 "Display BGP Overlay Information for prefixes\n"
1668 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1669 SHOW_DISPLAY_OVERLAY
,
1670 use_json(argc
, argv
));
1673 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1674 show_ip_bgp_evpn_rd_overlay_cmd
,
1675 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1681 "Display information for a route distinguisher\n"
1682 "VPN Route Distinguisher\n"
1683 "Display BGP Overlay Information for prefixes\n")
1685 int idx_ext_community
= 0;
1687 struct prefix_rd prd
;
1689 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1691 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1693 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1696 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1697 SHOW_DISPLAY_OVERLAY
,
1698 use_json(argc
, argv
));
1701 /* For testing purpose, static route of EVPN RT-5. */
1702 DEFUN(evpnrt5_network
,
1703 evpnrt5_network_cmd
,
1704 "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]",
1705 "Specify a network to announce via BGP\n"
1708 "Specify Route Distinguisher\n"
1709 "VPN Route Distinguisher\n"
1711 "Ethernet Tag Value\n"
1714 "Ethernet Segment Identifier\n"
1715 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1717 "Gateway IP ( A.B.C.D )\n"
1718 "Gateway IPv6 ( X:X::X:X )\n"
1719 "Router Mac Ext Comm\n"
1720 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1721 "Route-map to modify the attributes\n"
1722 "Name of the route map\n")
1724 int idx_ipv4_prefixlen
= 1;
1725 int idx_route_distinguisher
= 3;
1730 int idx_routermac
= 13;
1732 return bgp_static_set_safi(
1733 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1734 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1735 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1736 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1737 argv
[idx_routermac
]->arg
);
1740 /* For testing purpose, static route of EVPN RT-5. */
1741 DEFUN(no_evpnrt5_network
,
1742 no_evpnrt5_network_cmd
,
1743 "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>",
1745 "Specify a network to announce via BGP\n"
1748 "Specify Route Distinguisher\n"
1749 "VPN Route Distinguisher\n"
1751 "Ethernet Tag Value\n"
1754 "Ethernet Segment Identifier\n"
1755 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1756 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1758 int idx_ipv4_prefixlen
= 2;
1759 int idx_ext_community
= 4;
1764 return bgp_static_unset_safi(
1765 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1766 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1767 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1768 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1771 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1773 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1776 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1778 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1782 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1783 * check that this is a change.
1785 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1786 struct ecommunity
*ecomadd
)
1788 /* If the VNI is "live", we need to uninstall routes using the current
1789 * import RT(s) first before we update the import RT, and subsequently
1792 if (is_vni_live(vpn
))
1793 bgp_evpn_uninstall_routes(bgp
, vpn
);
1795 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1796 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1798 /* If the auto route-target is in use we must remove it */
1799 evpn_import_rt_delete_auto(bgp
, vpn
);
1801 /* Add new RT and rebuild the RT to VNI mapping */
1802 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1804 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1805 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1807 /* Install routes that match new import RT */
1808 if (is_vni_live(vpn
))
1809 bgp_evpn_install_routes(bgp
, vpn
);
1813 * Unconfigure Import RT(s) for a VNI (vty handler).
1815 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1816 struct ecommunity
*ecomdel
)
1818 struct listnode
*node
, *nnode
, *node_to_del
;
1819 struct ecommunity
*ecom
;
1821 /* Along the lines of "configure" except we have to reset to the
1824 if (is_vni_live(vpn
))
1825 bgp_evpn_uninstall_routes(bgp
, vpn
);
1827 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1828 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1830 /* Delete all import RTs */
1831 if (ecomdel
== NULL
) {
1832 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1833 ecommunity_free(&ecom
);
1834 list_delete_node(vpn
->import_rtl
, node
);
1838 /* Delete a specific import RT */
1842 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1843 if (ecommunity_match(ecom
, ecomdel
)) {
1844 ecommunity_free(&ecom
);
1851 list_delete_node(vpn
->import_rtl
, node_to_del
);
1854 assert(vpn
->import_rtl
);
1855 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1856 if (list_isempty(vpn
->import_rtl
)) {
1857 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1858 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1860 /* Rebuild the RT to VNI mapping */
1862 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1864 /* Install routes that match new import RT */
1865 if (is_vni_live(vpn
))
1866 bgp_evpn_install_routes(bgp
, vpn
);
1870 * Configure the Export RT for a VNI (vty handler). Caller expected to
1871 * check that this is a change. Note that only a single export RT is
1872 * allowed for a VNI and any change to configuration is implemented as
1873 * a "replace" (similar to other configuration).
1875 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1876 struct ecommunity
*ecomadd
)
1878 /* If the auto route-target is in use we must remove it */
1879 evpn_export_rt_delete_auto(bgp
, vpn
);
1881 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1882 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1884 if (is_vni_live(vpn
))
1885 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1889 * Unconfigure the Export RT for a VNI (vty handler)
1891 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1892 struct ecommunity
*ecomdel
)
1894 struct listnode
*node
, *nnode
, *node_to_del
;
1895 struct ecommunity
*ecom
;
1897 /* Delete all export RTs */
1898 if (ecomdel
== NULL
) {
1899 /* Reset to default and process all routes. */
1900 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1901 ecommunity_free(&ecom
);
1902 list_delete_node(vpn
->export_rtl
, node
);
1906 /* Delete a specific export RT */
1910 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1911 if (ecommunity_match(ecom
, ecomdel
)) {
1912 ecommunity_free(&ecom
);
1919 list_delete_node(vpn
->export_rtl
, node_to_del
);
1922 assert(vpn
->export_rtl
);
1923 if (list_isempty(vpn
->export_rtl
)) {
1924 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1925 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1928 if (is_vni_live(vpn
))
1929 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1933 * Configure RD for VRF
1935 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1937 /* If we have already advertise type-5 routes with a diffrent RD, we
1938 * have to delete and withdraw them firs
1940 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1943 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1944 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1946 /* We have a new RD for VRF.
1947 * Advertise all type-5 routes again with the new RD
1949 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1953 * Unconfigure RD for VRF
1955 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1957 /* If we have already advertise type-5 routes with a diffrent RD, we
1958 * have to delete and withdraw them firs
1960 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1962 /* fall back to default RD */
1963 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1964 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1966 /* We have a new RD for VRF.
1967 * Advertise all type-5 routes again with the new RD
1969 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1973 * Configure RD for a VNI (vty handler)
1975 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1976 struct prefix_rd
*rd
)
1978 /* If the VNI is "live", we need to delete and withdraw this VNI's
1979 * local routes with the prior RD first. Then, after updating RD,
1980 * need to re-advertise.
1982 if (is_vni_live(vpn
))
1983 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1986 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1987 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1989 if (is_vni_live(vpn
))
1990 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1994 * Unconfigure RD for a VNI (vty handler)
1996 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1998 /* If the VNI is "live", we need to delete and withdraw this VNI's
1999 * local routes with the prior RD first. Then, after resetting RD
2000 * to automatic value, need to re-advertise.
2002 if (is_vni_live(vpn
))
2003 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2005 /* reset RD to default */
2006 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2008 if (is_vni_live(vpn
))
2009 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2013 * Create VNI, if not already present (VTY handler). Mark as configured.
2015 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2017 struct bgpevpn
*vpn
;
2018 struct in_addr mcast_grp
= {INADDR_ANY
};
2023 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2025 /* Check if this L2VNI is already configured as L3VNI */
2026 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2029 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2034 /* tenant vrf will be updated when we get local_vni_add from
2037 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2041 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2047 /* Mark as configured. */
2048 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2053 * Delete VNI. If VNI does not exist in the system (i.e., just
2054 * configuration), all that is needed is to free it. Otherwise,
2055 * any parameters configured for the VNI need to be reset (with
2056 * appropriate action) and the VNI marked as unconfigured; the
2057 * VNI will continue to exist, purely as a "learnt" entity.
2059 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2061 assert(bgp
->vnihash
);
2063 if (!is_vni_live(vpn
)) {
2064 bgp_evpn_free(bgp
, vpn
);
2068 /* We need to take the unconfigure action for each parameter of this VNI
2069 * that is configured. Some optimization is possible, but not worth the
2070 * additional code for an operation that should be pretty rare.
2072 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2074 /* First, deal with the export side - RD and export RT changes. */
2075 if (is_rd_configured(vpn
))
2076 evpn_unconfigure_rd(bgp
, vpn
);
2077 if (is_export_rt_configured(vpn
))
2078 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2080 /* Next, deal with the import side. */
2081 if (is_import_rt_configured(vpn
))
2082 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2088 * Display import RT mapping to VRFs (vty handler)
2089 * bgp_evpn: evpn bgp instance
2091 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2099 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2100 (void (*)(struct hash_bucket
*,
2101 void *))show_vrf_import_rt_entry
,
2106 * Display import RT mapping to VNIs (vty handler)
2108 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2117 bgp
->import_rt_hash
,
2118 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2123 * Display EVPN routes for all VNIs - vty handler.
2125 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2126 struct in_addr vtep_ip
, json_object
*json
,
2130 struct vni_walk_ctx wctx
;
2132 num_vnis
= hashcount(bgp
->vnihash
);
2135 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2138 wctx
.vtep_ip
= vtep_ip
;
2140 wctx
.detail
= detail
;
2141 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2142 void *))show_vni_routes_hash
,
2147 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2149 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2150 vni_t vni
, struct in_addr orig_ip
,
2153 struct bgpevpn
*vpn
;
2154 struct prefix_evpn p
;
2155 struct bgp_node
*rn
;
2156 struct bgp_path_info
*pi
;
2157 uint32_t path_cnt
= 0;
2160 json_object
*json_paths
= NULL
;
2166 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2168 vty_out(vty
, "VNI not found\n");
2172 /* See if route exists. */
2173 build_evpn_type3_prefix(&p
, orig_ip
);
2174 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2175 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2177 vty_out(vty
, "%% Network not in table\n");
2182 json_paths
= json_object_new_array();
2184 /* Prefix and num paths displayed once per prefix. */
2185 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2187 /* Display each path for this prefix. */
2188 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2189 json_object
*json_path
= NULL
;
2192 json_path
= json_object_new_array();
2194 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2198 json_object_array_add(json_paths
, json_path
);
2205 json_object_object_add(json
, "paths", json_paths
);
2207 json_object_int_add(json
, "numPaths", path_cnt
);
2209 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2215 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2216 * By definition, only matching type-2 route will be displayed.
2218 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2219 vni_t vni
, struct ethaddr
*mac
,
2220 struct ipaddr
*ip
, json_object
*json
)
2222 struct bgpevpn
*vpn
;
2223 struct prefix_evpn p
;
2224 struct bgp_node
*rn
;
2225 struct bgp_path_info
*pi
;
2226 uint32_t path_cnt
= 0;
2229 json_object
*json_paths
= NULL
;
2235 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2238 vty_out(vty
, "VNI not found\n");
2242 /* See if route exists. Look for both non-sticky and sticky. */
2243 build_evpn_type2_prefix(&p
, mac
, ip
);
2244 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2245 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2247 vty_out(vty
, "%% Network not in table\n");
2252 json_paths
= json_object_new_array();
2254 /* Prefix and num paths displayed once per prefix. */
2255 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2257 /* Display each path for this prefix. */
2258 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2259 json_object
*json_path
= NULL
;
2262 json_path
= json_object_new_array();
2264 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2268 json_object_array_add(json_paths
, json_path
);
2275 json_object_object_add(json
, "paths", json_paths
);
2277 json_object_int_add(json
, "numPaths", path_cnt
);
2279 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2284 /* Disaplay EVPN routes for a ESI - VTY handler */
2285 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2286 esi_t
*esi
, json_object
*json
)
2288 struct evpnes
*es
= NULL
;
2291 es
= bgp_evpn_lookup_es(bgp
, esi
);
2294 vty_out(vty
, "ESI not found\n");
2298 show_esi_routes(bgp
, es
, vty
, json
);
2302 * Display EVPN routes for a VNI - vty handler.
2303 * If 'type' is non-zero, only routes matching that type are shown.
2304 * If the vtep_ip is non zero, only routes behind that vtep are shown
2306 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2307 int type
, struct in_addr vtep_ip
,
2310 struct bgpevpn
*vpn
;
2313 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2316 vty_out(vty
, "VNI not found\n");
2320 /* Walk this VNI's route table and display appropriate routes. */
2321 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2325 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2326 * IP (vty handler). By definition, only matching type-2 route will be
2329 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2330 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2331 struct ipaddr
*ip
, json_object
*json
)
2333 struct prefix_evpn p
;
2334 struct bgp_node
*rn
;
2335 struct bgp_path_info
*pi
;
2338 uint32_t path_cnt
= 0;
2339 json_object
*json_paths
= NULL
;
2340 char prefix_str
[BUFSIZ
];
2345 /* See if route exists. Look for both non-sticky and sticky. */
2346 build_evpn_type2_prefix(&p
, mac
, ip
);
2347 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2348 (struct prefix
*)&p
, prd
);
2349 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2351 vty_out(vty
, "%% Network not in table\n");
2355 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2356 sizeof(prefix_str
));
2358 /* Prefix and num paths displayed once per prefix. */
2359 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2362 json_paths
= json_object_new_array();
2364 /* Display each path for this prefix. */
2365 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2366 json_object
*json_path
= NULL
;
2369 json_path
= json_object_new_array();
2371 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2375 json_object_array_add(json_paths
, json_path
);
2380 if (json
&& path_cnt
) {
2382 json_object_object_add(json
, prefix_str
, json_paths
);
2383 json_object_int_add(json
, "numPaths", path_cnt
);
2385 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2391 * Display BGP EVPN routing table -- for specific RD (vty handler)
2392 * If 'type' is non-zero, only routes matching that type are shown.
2394 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2395 struct prefix_rd
*prd
, int type
,
2398 struct bgp_node
*rd_rn
;
2399 struct bgp_table
*table
;
2400 struct bgp_node
*rn
;
2401 struct bgp_path_info
*pi
;
2405 uint32_t prefix_cnt
, path_cnt
;
2406 char rd_str
[RD_ADDRSTRLEN
];
2407 json_object
*json_rd
= NULL
;
2408 int add_rd_to_json
= 0;
2412 prefix_cnt
= path_cnt
= 0;
2414 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2416 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2420 table
= bgp_node_get_bgp_table_info(rd_rn
);
2425 json_rd
= json_object_new_object();
2426 json_object_string_add(json_rd
, "rd", rd_str
);
2429 /* Display all prefixes with this RD. */
2430 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2431 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2432 json_object
*json_prefix
= NULL
;
2433 json_object
*json_paths
= NULL
;
2434 char prefix_str
[BUFSIZ
];
2435 int add_prefix_to_json
= 0;
2437 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2438 sizeof(prefix_str
));
2440 if (type
&& evp
->prefix
.route_type
!= type
)
2444 json_prefix
= json_object_new_object();
2446 pi
= bgp_node_get_bgp_path_info(rn
);
2448 /* RD header and legend - once overall. */
2449 if (rd_header
&& !json
) {
2451 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2453 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2455 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2459 /* Prefix and num paths displayed once per prefix. */
2460 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2467 json_paths
= json_object_new_array();
2469 /* Display each path for this prefix. */
2470 for (; pi
; pi
= pi
->next
) {
2471 json_object
*json_path
= NULL
;
2474 json_path
= json_object_new_array();
2476 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2480 json_object_array_add(json_paths
, json_path
);
2483 add_prefix_to_json
= 1;
2487 if (json
&& add_prefix_to_json
) {
2488 json_object_object_add(json_prefix
, "paths",
2490 json_object_object_add(json_rd
, prefix_str
,
2495 if (json
&& add_rd_to_json
)
2496 json_object_object_add(json
, rd_str
, json_rd
);
2499 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2500 json_object_int_add(json
, "numPaths", path_cnt
);
2502 if (prefix_cnt
== 0)
2503 vty_out(vty
, "No prefixes exist with this RD%s\n",
2504 type
? " (of requested type)" : "");
2507 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2508 prefix_cnt
, path_cnt
,
2509 type
? " (of requested type)" : "");
2514 * Display BGP EVPN routing table - all routes (vty handler).
2515 * If 'type' is non-zero, only routes matching that type are shown.
2517 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2518 json_object
*json
, int detail
)
2520 struct bgp_node
*rd_rn
;
2521 struct bgp_table
*table
;
2522 struct bgp_node
*rn
;
2523 struct bgp_path_info
*pi
;
2524 int header
= detail
? 0 : 1;
2528 uint32_t prefix_cnt
, path_cnt
;
2532 prefix_cnt
= path_cnt
= 0;
2534 /* EVPN routing table is a 2-level table with the first level being
2537 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2538 rd_rn
= bgp_route_next(rd_rn
)) {
2539 char rd_str
[RD_ADDRSTRLEN
];
2540 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2541 int add_rd_to_json
= 0;
2544 table
= bgp_node_get_bgp_table_info(rd_rn
);
2548 tbl_ver
= table
->version
;
2549 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2553 json_rd
= json_object_new_object();
2554 json_object_string_add(json_rd
, "rd", rd_str
);
2559 /* Display all prefixes for an RD */
2560 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2561 json_object
*json_prefix
=
2562 NULL
; /* contains prefix under a RD */
2563 json_object
*json_paths
=
2564 NULL
; /* array of paths under a prefix*/
2565 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2566 char prefix_str
[BUFSIZ
];
2567 int add_prefix_to_json
= 0;
2569 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2570 prefix_str
, sizeof(prefix_str
));
2572 if (type
&& evp
->prefix
.route_type
!= type
)
2575 pi
= bgp_node_get_bgp_path_info(rn
);
2577 /* Overall header/legend displayed once. */
2579 bgp_evpn_show_route_header(vty
, bgp
,
2584 "%19s Extended Community\n"
2589 /* RD header - per RD. */
2591 bgp_evpn_show_route_rd_header(
2600 json_prefix
= json_object_new_object();
2601 json_paths
= json_object_new_array();
2602 json_object_string_add(json_prefix
, "prefix",
2604 json_object_int_add(json_prefix
, "prefixLen",
2608 /* Prefix and num paths displayed once per prefix. */
2610 route_vty_out_detail_header(
2612 (struct prefix_rd
*)&rd_rn
->p
,
2613 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2615 /* For EVPN, the prefix is displayed for each path (to
2617 * with code that already exists).
2619 for (; pi
; pi
= pi
->next
) {
2620 json_object
*json_path
= NULL
;
2622 add_prefix_to_json
= 1;
2626 json_path
= json_object_new_array();
2629 route_vty_out_detail(
2630 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2631 SAFI_EVPN
, json_path
);
2633 route_vty_out(vty
, &rn
->p
, pi
, 0,
2634 SAFI_EVPN
, json_path
);
2637 json_object_array_add(json_paths
,
2641 if (json
&& add_prefix_to_json
) {
2642 json_object_object_add(json_prefix
, "paths",
2644 json_object_object_add(json_rd
, prefix_str
,
2649 if (json
&& add_rd_to_json
)
2650 json_object_object_add(json
, rd_str
, json_rd
);
2654 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2655 json_object_int_add(json
, "numPaths", path_cnt
);
2657 if (prefix_cnt
== 0) {
2658 vty_out(vty
, "No EVPN prefixes %sexist\n",
2659 type
? "(of requested type) " : "");
2661 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2662 prefix_cnt
, path_cnt
,
2663 type
? " (of requested type)" : "");
2668 /* Display specific ES */
2669 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2672 struct evpnes
*es
= NULL
;
2674 es
= bgp_evpn_lookup_es(bgp
, esi
);
2676 display_es(vty
, es
, json
);
2679 vty_out(vty
, "{}\n");
2681 vty_out(vty
, "ESI not found\n");
2687 /* Display all ESs */
2688 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2694 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2695 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2700 hash_iterate(bgp
->esihash
,
2701 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2706 * Display specified VNI (vty handler)
2708 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2712 struct bgpevpn
*vpn
;
2714 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2717 display_vni(vty
, vpn
, json
);
2719 struct bgp
*bgp_temp
;
2720 struct listnode
*node
= NULL
;
2722 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2723 if (bgp_temp
->l3vni
== vni
) {
2725 display_l3vni(vty
, bgp_temp
, json
);
2732 vty_out(vty
, "{}\n");
2734 vty_out(vty
, "VNI not found\n");
2741 * Display a VNI (upon user query).
2743 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2747 struct bgp
*bgp_temp
= NULL
;
2748 struct listnode
*node
;
2752 vty_out(vty
, "Flags: * - Kernel\n");
2753 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2754 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2757 /* print all L2 VNIS */
2760 hash_iterate(bgp
->vnihash
,
2761 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2764 /* print all L3 VNIs */
2765 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2766 show_l3vni_entry(vty
, bgp_temp
, json
);
2770 * evpn - enable advertisement of svi MAC-IP
2772 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2776 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2778 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2781 bgp
->evpn_info
->advertise_svi_macip
= set
;
2782 bgp_zebra_advertise_svi_macip(bgp
,
2783 bgp
->evpn_info
->advertise_svi_macip
, 0);
2785 if (set
&& vpn
->advertise_svi_macip
)
2787 else if (!set
&& !vpn
->advertise_svi_macip
)
2790 vpn
->advertise_svi_macip
= set
;
2791 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2797 * evpn - enable advertisement of default g/w
2799 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2802 if (bgp
->advertise_gw_macip
)
2805 bgp
->advertise_gw_macip
= 1;
2806 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2808 if (vpn
->advertise_gw_macip
)
2811 vpn
->advertise_gw_macip
= 1;
2812 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2819 * evpn - disable advertisement of default g/w
2821 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2822 struct bgpevpn
*vpn
)
2825 if (!bgp
->advertise_gw_macip
)
2828 bgp
->advertise_gw_macip
= 0;
2829 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2831 if (!vpn
->advertise_gw_macip
)
2834 vpn
->advertise_gw_macip
= 0;
2835 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2842 * evpn - enable advertisement of default g/w
2844 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2845 afi_t afi
, bool add
)
2847 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2850 /* bail if we are already advertising default route */
2851 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2855 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2856 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2857 else if (afi
== AFI_IP6
)
2858 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2859 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2861 /* bail out if we havent advertised the default route */
2862 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2865 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2866 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2867 else if (afi
== AFI_IP6
)
2868 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2869 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2872 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2876 * evpn - enable advertisement of default g/w
2878 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2879 struct bgpevpn
*vpn
)
2881 if (vpn
->advertise_subnet
)
2884 vpn
->advertise_subnet
= 1;
2885 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2889 * evpn - disable advertisement of default g/w
2891 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2893 if (!vpn
->advertise_subnet
)
2896 vpn
->advertise_subnet
= 0;
2897 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2901 * EVPN (VNI advertisement) enabled. Register with zebra.
2903 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2905 bgp
->advertise_all_vni
= 1;
2907 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2911 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2912 * cache, EVPN routes (delete and withdraw from peers).
2914 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2916 bgp
->advertise_all_vni
= 0;
2917 bgp_set_evpn(bgp_get_default());
2918 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2919 bgp_evpn_cleanup_on_disable(bgp
);
2923 * EVPN - use RFC8365 to auto-derive RT
2925 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2927 bgp
->advertise_autort_rfc8365
= 1;
2928 bgp_evpn_handle_autort_change(bgp
);
2932 * EVPN - don't use RFC8365 to auto-derive RT
2934 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2936 bgp
->advertise_autort_rfc8365
= 0;
2937 bgp_evpn_handle_autort_change(bgp
);
2940 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2942 char buf1
[RD_ADDRSTRLEN
];
2944 struct listnode
*node
, *nnode
;
2945 struct ecommunity
*ecom
;
2947 if (is_vni_configured(vpn
)) {
2948 vty_out(vty
, " vni %d\n", vpn
->vni
);
2949 if (is_rd_configured(vpn
))
2950 vty_out(vty
, " rd %s\n",
2951 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2953 if (is_import_rt_configured(vpn
)) {
2954 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2956 ecom_str
= ecommunity_ecom2str(
2957 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2958 vty_out(vty
, " route-target import %s\n",
2960 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2964 if (is_export_rt_configured(vpn
)) {
2965 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2967 ecom_str
= ecommunity_ecom2str(
2968 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2969 vty_out(vty
, " route-target export %s\n",
2971 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2975 if (vpn
->advertise_gw_macip
)
2976 vty_out(vty
, " advertise-default-gw\n");
2978 if (vpn
->advertise_svi_macip
)
2979 vty_out(vty
, " advertise-svi-ip\n");
2981 if (vpn
->advertise_subnet
)
2982 vty_out(vty
, " advertise-subnet\n");
2984 vty_out(vty
, " exit-vni\n");
2988 #ifndef VTYSH_EXTRACT_PL
2989 #include "bgpd/bgp_evpn_vty_clippy.c"
2992 DEFPY(bgp_evpn_flood_control
,
2993 bgp_evpn_flood_control_cmd
,
2994 "[no$no] flooding <disable$disable|head-end-replication$her>",
2996 "Specify handling for BUM packets\n"
2997 "Do not flood any BUM packets\n"
2998 "Flood BUM packets using head-end replication\n")
3000 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3001 enum vxlan_flood_control flood_ctrl
;
3007 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3009 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3013 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3016 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3017 bgp_evpn_flood_control_change(bgp
);
3022 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3023 bgp_evpn_advertise_default_gw_vni_cmd
,
3024 "advertise-default-gw",
3025 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3027 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3028 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3033 evpn_set_advertise_default_gw(bgp
, vpn
);
3038 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3039 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3040 "no advertise-default-gw",
3042 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3044 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3045 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3050 evpn_unset_advertise_default_gw(bgp
, vpn
);
3056 DEFUN (bgp_evpn_advertise_default_gw
,
3057 bgp_evpn_advertise_default_gw_cmd
,
3058 "advertise-default-gw",
3059 "Advertise All default g/w mac-ip routes in EVPN\n")
3061 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3066 if (!EVPN_ENABLED(bgp
)) {
3068 "This command is only supported under the EVPN VRF\n");
3072 evpn_set_advertise_default_gw(bgp
, NULL
);
3077 DEFUN (no_bgp_evpn_advertise_default_gw
,
3078 no_bgp_evpn_advertise_default_gw_cmd
,
3079 "no advertise-default-gw",
3081 "Withdraw All default g/w mac-ip routes from EVPN\n")
3083 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3088 if (!EVPN_ENABLED(bgp
)) {
3090 "This command is only supported under the EVPN VRF\n");
3094 evpn_unset_advertise_default_gw(bgp
, NULL
);
3099 DEFUN (bgp_evpn_advertise_all_vni
,
3100 bgp_evpn_advertise_all_vni_cmd
,
3101 "advertise-all-vni",
3102 "Advertise All local VNIs\n")
3104 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3105 struct bgp
*bgp_evpn
= NULL
;
3110 bgp_evpn
= bgp_get_evpn();
3111 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3112 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3114 return CMD_WARNING_CONFIG_FAILED
;
3117 evpn_set_advertise_all_vni(bgp
);
3121 DEFUN (no_bgp_evpn_advertise_all_vni
,
3122 no_bgp_evpn_advertise_all_vni_cmd
,
3123 "no advertise-all-vni",
3125 "Advertise All local VNIs\n")
3127 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3131 evpn_unset_advertise_all_vni(bgp
);
3135 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3136 bgp_evpn_advertise_autort_rfc8365_cmd
,
3137 "autort rfc8365-compatible",
3138 "Auto-derivation of RT\n"
3139 "Auto-derivation of RT using RFC8365\n")
3141 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3145 evpn_set_advertise_autort_rfc8365(bgp
);
3149 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3150 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3151 "no autort rfc8365-compatible",
3153 "Auto-derivation of RT\n"
3154 "Auto-derivation of RT using RFC8365\n")
3156 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3160 evpn_unset_advertise_autort_rfc8365(bgp
);
3164 DEFUN (bgp_evpn_default_originate
,
3165 bgp_evpn_default_originate_cmd
,
3166 "default-originate <ipv4 | ipv6>",
3167 "originate a default route\n"
3168 "ipv4 address family\n"
3169 "ipv6 address family\n")
3173 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3177 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3178 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3182 DEFUN (no_bgp_evpn_default_originate
,
3183 no_bgp_evpn_default_originate_cmd
,
3184 "no default-originate <ipv4 | ipv6>",
3186 "withdraw a default route\n"
3187 "ipv4 address family\n"
3188 "ipv6 address family\n")
3192 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3196 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3197 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3201 DEFPY (dup_addr_detection
,
3202 dup_addr_detection_cmd
,
3203 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3204 "Duplicate address detection\n"
3205 "Max allowed moves before address detected as duplicate\n"
3206 "Num of max allowed moves (2-1000) default 5\n"
3207 "Duplicate address detection time\n"
3208 "Time in seconds (2-1800) default 180\n")
3210 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3215 if (!EVPN_ENABLED(bgp_vrf
)) {
3217 "This command is only supported under the EVPN VRF\n");
3221 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3224 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3226 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3228 bgp_zebra_dup_addr_detection(bgp_vrf
);
3233 DEFPY (dup_addr_detection_auto_recovery
,
3234 dup_addr_detection_auto_recovery_cmd
,
3235 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3236 "Duplicate address detection\n"
3237 "Duplicate address detection freeze\n"
3238 "Duplicate address detection permanent freeze\n"
3239 "Duplicate address detection freeze time (30-3600)\n")
3241 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3242 uint32_t freeze_time
= freeze_time_val
;
3247 if (!EVPN_ENABLED(bgp_vrf
)) {
3249 "This command is only supported under the EVPN VRF\n");
3253 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3254 bgp_vrf
->evpn_info
->dad_freeze
= true;
3255 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3257 bgp_zebra_dup_addr_detection(bgp_vrf
);
3262 DEFPY (no_dup_addr_detection
,
3263 no_dup_addr_detection_cmd
,
3264 "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>]",
3266 "Duplicate address detection\n"
3267 "Max allowed moves before address detected as duplicate\n"
3268 "Num of max allowed moves (2-1000) default 5\n"
3269 "Duplicate address detection time\n"
3270 "Time in seconds (2-1800) default 180\n"
3271 "Duplicate address detection freeze\n"
3272 "Duplicate address detection permanent freeze\n"
3273 "Duplicate address detection freeze time (30-3600)\n")
3275 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3276 uint32_t max_moves
= (uint32_t)max_moves_val
;
3277 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3282 if (!EVPN_ENABLED(bgp_vrf
)) {
3284 "This command is only supported under the EVPN VRF\n");
3289 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3291 /* Reset all parameters to default. */
3292 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3293 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3294 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3295 bgp_vrf
->evpn_info
->dad_freeze
= false;
3296 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3299 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3301 "%% Value does not match with config\n");
3304 bgp_vrf
->evpn_info
->dad_max_moves
=
3305 EVPN_DAD_DEFAULT_MAX_MOVES
;
3309 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3311 "%% Value does not match with config\n");
3314 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3318 if (bgp_vrf
->evpn_info
->dad_freeze_time
3321 "%% Value does not match with config\n");
3324 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3325 bgp_vrf
->evpn_info
->dad_freeze
= false;
3328 if (permanent_val
) {
3329 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3331 "%% Value does not match with config\n");
3334 bgp_vrf
->evpn_info
->dad_freeze
= false;
3338 bgp_zebra_dup_addr_detection(bgp_vrf
);
3343 DEFPY(bgp_evpn_advertise_svi_ip
,
3344 bgp_evpn_advertise_svi_ip_cmd
,
3345 "[no$no] advertise-svi-ip",
3347 "Advertise svi mac-ip routes in EVPN\n")
3349 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3354 if (!EVPN_ENABLED(bgp
)) {
3356 "This command is only supported under EVPN VRF\n");
3361 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3363 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3368 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3369 bgp_evpn_advertise_svi_ip_vni_cmd
,
3370 "[no$no] advertise-svi-ip",
3372 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3374 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3375 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3381 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3383 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3388 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3389 bgp_evpn_advertise_vni_subnet_cmd
,
3391 "Advertise the subnet corresponding to VNI\n")
3393 struct bgp
*bgp_vrf
= NULL
;
3394 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3395 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3400 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3404 evpn_set_advertise_subnet(bgp
, vpn
);
3408 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3409 no_bgp_evpn_advertise_vni_subnet_cmd
,
3410 "no advertise-subnet",
3412 "Advertise All local VNIs\n")
3414 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3415 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3420 evpn_unset_advertise_subnet(bgp
, vpn
);
3424 DEFUN (bgp_evpn_advertise_type5
,
3425 bgp_evpn_advertise_type5_cmd
,
3426 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3427 "Advertise prefix routes\n"
3430 "route-map for filtering specific routes\n"
3431 "Name of the route map\n")
3433 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3440 int rmap_changed
= 0;
3442 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3443 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3444 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3446 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3448 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3449 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3452 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3456 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3458 "%%only ipv4 or ipv6 address families are supported");
3462 if (safi
!= SAFI_UNICAST
) {
3464 "%%only ipv4 unicast or ipv6 unicast are supported");
3468 if (afi
== AFI_IP
) {
3470 /* if we are already advertising ipv4 prefix as type-5
3473 if (!rmap_changed
&&
3474 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3475 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3477 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3478 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3481 /* if we are already advertising ipv6 prefix as type-5
3484 if (!rmap_changed
&&
3485 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3486 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3488 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3489 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3493 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3494 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3495 XFREE(MTYPE_ROUTE_MAP_NAME
,
3496 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3497 route_map_counter_decrement(
3498 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3499 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3500 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3504 /* set the route-map for advertise command */
3505 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3506 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3507 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3508 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3509 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3510 route_map_counter_increment(
3511 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3514 /* advertise type-5 routes */
3515 if (advertise_type5_routes(bgp_vrf
, afi
))
3516 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3520 DEFUN (no_bgp_evpn_advertise_type5
,
3521 no_bgp_evpn_advertise_type5_cmd
,
3522 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3524 "Advertise prefix routes\n"
3528 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3534 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3535 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3537 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3539 "%%only ipv4 or ipv6 address families are supported");
3543 if (safi
!= SAFI_UNICAST
) {
3545 "%%only ipv4 unicast or ipv6 unicast are supported");
3549 if (afi
== AFI_IP
) {
3551 /* if we are not advertising ipv4 prefix as type-5
3554 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3555 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3556 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3557 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3558 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3562 /* if we are not advertising ipv6 prefix as type-5
3565 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3566 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3567 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3568 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3569 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3573 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3574 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3575 XFREE(MTYPE_ROUTE_MAP_NAME
,
3576 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3577 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3578 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3585 * Display VNI information - for all or a specific VNI
3587 DEFUN(show_bgp_l2vpn_evpn_vni
,
3588 show_bgp_l2vpn_evpn_vni_cmd
,
3589 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3598 struct bgp
*bgp_evpn
;
3602 json_object
*json
= NULL
;
3603 uint32_t num_l2vnis
= 0;
3604 uint32_t num_l3vnis
= 0;
3605 uint32_t num_vnis
= 0;
3606 struct listnode
*node
= NULL
;
3607 struct bgp
*bgp_temp
= NULL
;
3609 uj
= use_json(argc
, argv
);
3611 bgp_evpn
= bgp_get_evpn();
3615 if (!argv_find(argv
, argc
, "evpn", &idx
))
3619 json
= json_object_new_object();
3621 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3623 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3625 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3626 if (bgp_temp
->l3vni
)
3629 num_vnis
= num_l2vnis
+ num_l3vnis
;
3631 json_object_string_add(json
, "advertiseGatewayMacip",
3632 bgp_evpn
->advertise_gw_macip
3635 json_object_string_add(json
, "advertiseSviMacip",
3636 bgp_evpn
->evpn_info
->advertise_svi_macip
3637 ? "Enabled" : "Disabled");
3638 json_object_string_add(json
, "advertiseAllVnis",
3639 is_evpn_enabled() ? "Enabled"
3641 json_object_string_add(
3643 bgp_evpn
->vxlan_flood_ctrl
3644 == VXLAN_FLOOD_HEAD_END_REPL
3645 ? "Head-end replication"
3647 json_object_int_add(json
, "numVnis", num_vnis
);
3648 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3649 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3651 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3652 bgp_evpn
->advertise_gw_macip
? "Enabled"
3654 vty_out(vty
, "Advertise SVI Macip: %s\n",
3655 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3657 vty_out(vty
, "Advertise All VNI flag: %s\n",
3658 is_evpn_enabled() ? "Enabled" : "Disabled");
3659 vty_out(vty
, "BUM flooding: %s\n",
3660 bgp_evpn
->vxlan_flood_ctrl
3661 == VXLAN_FLOOD_HEAD_END_REPL
3662 ? "Head-end replication"
3664 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3665 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3667 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3671 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3674 /* Display specific VNI */
3675 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3676 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3680 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3681 json
, JSON_C_TO_STRING_PRETTY
));
3682 json_object_free(json
);
3689 DEFUN(show_bgp_l2vpn_evpn_es
,
3690 show_bgp_l2vpn_evpn_es_cmd
,
3691 "show bgp l2vpn evpn es [ESI] [json]",
3696 "ethernet-Segment\n"
3697 "Ethernet-Segment Identifier\n"
3703 json_object
*json
= NULL
;
3704 struct bgp
*bgp
= NULL
;
3706 memset(&esi
, 0, sizeof(esi
));
3707 uj
= use_json(argc
, argv
);
3709 bgp
= bgp_get_evpn();
3713 if (!argv_find(argv
, argc
, "evpn", &idx
))
3716 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3717 (!uj
&& argc
== (idx
+ 1) + 1)) {
3720 evpn_show_all_es(vty
, bgp
, json
);
3723 /* show a specific ES */
3725 /* get the ESI - ESI-ID is at argv[5] */
3726 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3727 vty_out(vty
, "%% Malformed ESI\n");
3730 evpn_show_es(vty
, bgp
, &esi
, json
);
3734 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3735 json
, JSON_C_TO_STRING_PRETTY
));
3736 json_object_free(json
);
3743 * Display EVPN neighbor summary.
3745 DEFUN(show_bgp_l2vpn_evpn_summary
,
3746 show_bgp_l2vpn_evpn_summary_cmd
,
3747 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3754 "Summary of BGP neighbor status\n"
3755 "Show only sessions not in Established state\n"
3759 bool uj
= use_json(argc
, argv
);
3761 bool show_failed
= false;
3763 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3764 vrf
= argv
[++idx_vrf
]->arg
;
3765 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3767 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3772 * Display global EVPN routing table.
3774 DEFUN(show_bgp_l2vpn_evpn_route
,
3775 show_bgp_l2vpn_evpn_route_cmd
,
3776 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3781 "EVPN route information\n"
3782 "Display Detailed Information\n"
3783 "Specify Route type\n"
3784 "MAC-IP (Type-2) route\n"
3785 "Multicast (Type-3) route\n"
3786 "Ethernet Segment (type-4) route \n"
3787 "Prefix (type-5 )route\n"
3795 json_object
*json
= NULL
;
3797 uj
= use_json(argc
, argv
);
3799 bgp
= bgp_get_evpn();
3804 json
= json_object_new_object();
3807 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3808 /* Specific type is requested */
3809 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3810 type
= BGP_EVPN_MAC_IP_ROUTE
;
3811 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3812 type
= BGP_EVPN_IMET_ROUTE
;
3813 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
3814 type
= BGP_EVPN_ES_ROUTE
;
3815 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
3816 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3821 if (argv_find(argv
, argc
, "detail", &detail
))
3824 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3827 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3828 json
, JSON_C_TO_STRING_PRETTY
));
3829 json_object_free(json
);
3835 * Display global EVPN routing table for specific RD.
3837 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3838 show_bgp_l2vpn_evpn_route_rd_cmd
,
3839 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3844 "EVPN route information\n"
3845 "Route Distinguisher\n"
3846 "ASN:XX or A.B.C.D:XX\n"
3847 "Specify Route type\n"
3848 "MAC-IP (Type-2) route\n"
3849 "Multicast (Type-3) route\n"
3850 "Ethernet Segment route\n"
3856 struct prefix_rd prd
;
3861 json_object
*json
= NULL
;
3863 bgp
= bgp_get_evpn();
3867 /* check if we need json output */
3868 uj
= use_json(argc
, argv
);
3870 json
= json_object_new_object();
3873 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3874 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3877 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3883 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3884 /* Specific type is requested */
3885 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3886 type
= BGP_EVPN_MAC_IP_ROUTE
;
3887 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3888 type
= BGP_EVPN_IMET_ROUTE
;
3889 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3890 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3895 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3899 json
, JSON_C_TO_STRING_PRETTY
));
3900 json_object_free(json
);
3907 * Display global EVPN routing table for specific RD and MACIP.
3909 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3910 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3911 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3916 "EVPN route information\n"
3917 "Route Distinguisher\n"
3918 "ASN:XX or A.B.C.D:XX\n"
3920 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3922 "IP address (IPv4 or IPv6)\n"
3927 struct prefix_rd prd
;
3934 json_object
*json
= NULL
;
3936 memset(&mac
, 0, sizeof(struct ethaddr
));
3937 memset(&ip
, 0, sizeof(struct ipaddr
));
3939 bgp
= bgp_get_evpn();
3943 /* check if we need json output */
3944 uj
= use_json(argc
, argv
);
3946 json
= json_object_new_object();
3949 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3950 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3952 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3958 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3959 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3960 vty_out(vty
, "%% Malformed MAC address\n");
3965 /* get the ip if specified */
3966 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3967 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3968 vty_out(vty
, "%% Malformed IP address\n");
3973 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3976 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3977 json
, JSON_C_TO_STRING_PRETTY
));
3978 json_object_free(json
);
3984 /* Display per ESI routing table */
3985 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3986 show_bgp_l2vpn_evpn_route_esi_cmd
,
3987 "show bgp l2vpn evpn route esi ESI [json]",
3992 "EVPN route information\n"
3993 "Ethernet Segment Identifier\n"
3999 struct bgp
*bgp
= NULL
;
4000 json_object
*json
= NULL
;
4002 memset(&esi
, 0, sizeof(esi
));
4003 bgp
= bgp_get_evpn();
4007 uj
= use_json(argc
, argv
);
4009 json
= json_object_new_object();
4011 /* get the ESI - ESI-ID is at argv[6] */
4012 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4013 vty_out(vty
, "%% Malformed ESI\n");
4017 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4020 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4021 json
, JSON_C_TO_STRING_PRETTY
));
4022 json_object_free(json
);
4030 * Display per-VNI EVPN routing table.
4032 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4033 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4038 "EVPN route information\n"
4039 "VXLAN Network Identifier\n"
4041 "Specify Route type\n"
4042 "MAC-IP (Type-2) route\n"
4043 "Multicast (Type-3) route\n"
4045 "Remote VTEP IP address\n"
4050 struct in_addr vtep_ip
;
4054 json_object
*json
= NULL
;
4056 bgp
= bgp_get_evpn();
4060 /* check if we need json output */
4061 uj
= use_json(argc
, argv
);
4063 json
= json_object_new_object();
4065 if (!argv_find(argv
, argc
, "evpn", &idx
))
4070 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4072 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4073 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4074 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4075 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4076 type
= BGP_EVPN_MAC_IP_ROUTE
;
4077 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4078 type
= BGP_EVPN_IMET_ROUTE
;
4081 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4082 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4083 vty_out(vty
, "%% Malformed VTEP IP address\n");
4090 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4093 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4094 json
, JSON_C_TO_STRING_PRETTY
));
4095 json_object_free(json
);
4102 * Display per-VNI EVPN routing table for specific MACIP.
4104 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4105 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4106 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4111 "EVPN route information\n"
4112 "VXLAN Network Identifier\n"
4115 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4117 "IP address (IPv4 or IPv6)\n"
4126 json_object
*json
= NULL
;
4128 bgp
= bgp_get_evpn();
4132 /* check if we need json output */
4133 uj
= use_json(argc
, argv
);
4135 json
= json_object_new_object();
4137 if (!argv_find(argv
, argc
, "evpn", &idx
))
4141 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4144 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4145 vty_out(vty
, "%% Malformed MAC address\n");
4150 memset(&ip
, 0, sizeof(ip
));
4151 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4153 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4154 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4155 vty_out(vty
, "%% Malformed IP address\n");
4160 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4163 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4164 json
, JSON_C_TO_STRING_PRETTY
));
4165 json_object_free(json
);
4172 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4174 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4175 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4176 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4181 "EVPN route information\n"
4182 "VXLAN Network Identifier\n"
4184 "Multicast (Type-3) route\n"
4185 "Originating Router IP address\n"
4191 struct in_addr orig_ip
;
4194 json_object
*json
= NULL
;
4196 bgp
= bgp_get_evpn();
4200 /* check if we need json output */
4201 uj
= use_json(argc
, argv
);
4203 json
= json_object_new_object();
4205 if (!argv_find(argv
, argc
, "evpn", &idx
))
4209 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4212 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4214 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4218 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4221 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4222 json
, JSON_C_TO_STRING_PRETTY
));
4223 json_object_free(json
);
4230 * Display per-VNI EVPN routing table - for all VNIs.
4232 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4233 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4234 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4239 "EVPN route information\n"
4240 "VXLAN Network Identifier\n"
4242 "Print Detailed Output\n"
4244 "Remote VTEP IP address\n"
4248 struct in_addr vtep_ip
;
4251 json_object
*json
= NULL
;
4252 /* Detail Adjust. Adjust indexes according to detail option */
4255 bgp
= bgp_get_evpn();
4259 /* check if we need json output */
4260 uj
= use_json(argc
, argv
);
4262 json
= json_object_new_object();
4264 if (!argv_find(argv
, argc
, "evpn", &idx
))
4267 if (argv_find(argv
, argc
, "detail", &da
))
4270 /* vtep-ip position depends on detail option */
4272 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4274 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4275 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4276 vty_out(vty
, "%% Malformed VTEP IP address\n");
4281 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4284 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4285 json
, JSON_C_TO_STRING_PRETTY
));
4286 json_object_free(json
);
4293 * Display EVPN import route-target hash table
4295 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4296 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4297 "show bgp l2vpn evpn vrf-import-rt [json]",
4302 "Show vrf import route target\n"
4306 struct bgp
*bgp_evpn
= NULL
;
4307 json_object
*json
= NULL
;
4309 bgp_evpn
= bgp_get_evpn();
4313 uj
= use_json(argc
, argv
);
4315 json
= json_object_new_object();
4317 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4320 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4321 json
, JSON_C_TO_STRING_PRETTY
));
4322 json_object_free(json
);
4329 * Display EVPN import route-target hash table
4331 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4332 show_bgp_l2vpn_evpn_import_rt_cmd
,
4333 "show bgp l2vpn evpn import-rt [json]",
4338 "Show import route target\n"
4343 json_object
*json
= NULL
;
4345 bgp
= bgp_get_evpn();
4349 uj
= use_json(argc
, argv
);
4351 json
= json_object_new_object();
4353 evpn_show_import_rts(vty
, bgp
, json
);
4356 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4357 json
, JSON_C_TO_STRING_PRETTY
));
4358 json_object_free(json
);
4364 DEFUN(test_adv_evpn_type4_route
,
4365 test_adv_evpn_type4_route_cmd
,
4367 "Advertise EVPN ES route\n"
4368 "Ethernet-segment\n"
4369 "Ethernet-Segment Identifier\n")
4374 struct ipaddr vtep_ip
;
4376 bgp
= bgp_get_evpn();
4378 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4382 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4383 vty_out(vty
, "%%Malformed ESI\n");
4387 vtep_ip
.ipa_type
= IPADDR_V4
;
4388 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4390 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4392 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4398 DEFUN(test_withdraw_evpn_type4_route
,
4399 test_withdraw_evpn_type4_route_cmd
,
4401 "Advertise EVPN ES route\n"
4402 "Ethernet-segment\n"
4403 "Ethernet-Segment Identifier\n")
4408 struct ipaddr vtep_ip
;
4410 bgp
= bgp_get_evpn();
4412 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4416 if (!bgp
->peer_self
) {
4417 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4421 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4422 vty_out(vty
, "%%Malformed ESI\n");
4426 vtep_ip
.ipa_type
= IPADDR_V4
;
4427 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4428 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4430 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4436 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4437 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4441 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4442 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4443 "Summary of BGP neighbor status\n" JSON_STR
)
4445 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4446 "show bgp evpn route [detail] [type <macip|multicast>]",
4447 SHOW_STR BGP_STR EVPN_HELP_STR
4448 "EVPN route information\n"
4449 "Display Detailed Information\n"
4450 "Specify Route type\n"
4451 "MAC-IP (Type-2) route\n"
4452 "Multicast (Type-3) route\n")
4455 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4456 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4457 SHOW_STR BGP_STR EVPN_HELP_STR
4458 "EVPN route information\n"
4459 "Route Distinguisher\n"
4460 "ASN:XX or A.B.C.D:XX\n"
4461 "Specify Route type\n"
4462 "MAC-IP (Type-2) route\n"
4463 "Multicast (Type-3) route\n")
4466 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4467 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4468 SHOW_STR BGP_STR EVPN_HELP_STR
4469 "EVPN route information\n"
4470 "Route Distinguisher\n"
4471 "ASN:XX or A.B.C.D:XX\n"
4473 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4475 "IP address (IPv4 or IPv6)\n")
4478 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4479 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4480 SHOW_STR BGP_STR EVPN_HELP_STR
4481 "EVPN route information\n"
4482 "VXLAN Network Identifier\n"
4484 "Specify Route type\n"
4485 "MAC-IP (Type-2) route\n"
4486 "Multicast (Type-3) route\n"
4488 "Remote VTEP IP address\n")
4490 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4491 show_bgp_evpn_route_vni_macip_cmd
,
4492 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4493 SHOW_STR BGP_STR EVPN_HELP_STR
4494 "EVPN route information\n"
4495 "VXLAN Network Identifier\n"
4498 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4500 "IP address (IPv4 or IPv6)\n")
4502 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4503 show_bgp_evpn_route_vni_multicast_cmd
,
4504 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4505 SHOW_STR BGP_STR EVPN_HELP_STR
4506 "EVPN route information\n"
4507 "VXLAN Network Identifier\n"
4509 "Multicast (Type-3) route\n"
4510 "Originating Router IP address\n")
4512 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4513 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4514 SHOW_STR BGP_STR EVPN_HELP_STR
4515 "EVPN route information\n"
4516 "VXLAN Network Identifier\n"
4518 "Print Detailed Output\n"
4520 "Remote VTEP IP address\n")
4522 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4523 "show bgp evpn import-rt",
4524 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4526 DEFUN_NOSH (bgp_evpn_vni
,
4528 "vni " CMD_VNI_RANGE
,
4529 "VXLAN Network Identifier\n"
4533 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4534 struct bgpevpn
*vpn
;
4539 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4541 /* Create VNI, or mark as configured. */
4542 vpn
= evpn_create_update_vni(bgp
, vni
);
4544 vty_out(vty
, "%% Failed to create VNI \n");
4548 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4552 DEFUN (no_bgp_evpn_vni
,
4553 no_bgp_evpn_vni_cmd
,
4554 "no vni " CMD_VNI_RANGE
,
4556 "VXLAN Network Identifier\n"
4560 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4561 struct bgpevpn
*vpn
;
4566 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4568 /* Check if we should disallow. */
4569 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4571 vty_out(vty
, "%% Specified VNI does not exist\n");
4574 if (!is_vni_configured(vpn
)) {
4575 vty_out(vty
, "%% Specified VNI is not configured\n");
4579 evpn_delete_vni(bgp
, vpn
);
4583 DEFUN_NOSH (exit_vni
,
4586 "Exit from VNI mode\n")
4588 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4589 vty
->node
= BGP_EVPN_NODE
;
4593 DEFUN (bgp_evpn_vrf_rd
,
4594 bgp_evpn_vrf_rd_cmd
,
4595 "rd ASN:NN_OR_IP-ADDRESS:NN",
4596 "Route Distinguisher\n"
4597 "ASN:XX or A.B.C.D:XX\n")
4600 struct prefix_rd prd
;
4601 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4606 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4608 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4612 /* If same as existing value, there is nothing more to do. */
4613 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4616 /* Configure or update the RD. */
4617 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4621 DEFUN (no_bgp_evpn_vrf_rd
,
4622 no_bgp_evpn_vrf_rd_cmd
,
4623 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4625 "Route Distinguisher\n"
4626 "ASN:XX or A.B.C.D:XX\n")
4629 struct prefix_rd prd
;
4630 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4635 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4637 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4641 /* Check if we should disallow. */
4642 if (!is_vrf_rd_configured(bgp_vrf
)) {
4643 vty_out(vty
, "%% RD is not configured for this VRF\n");
4647 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4649 "%% RD specified does not match configuration for this VRF\n");
4653 evpn_unconfigure_vrf_rd(bgp_vrf
);
4657 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4658 no_bgp_evpn_vrf_rd_without_val_cmd
,
4661 "Route Distinguisher\n")
4663 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4668 /* Check if we should disallow. */
4669 if (!is_vrf_rd_configured(bgp_vrf
)) {
4670 vty_out(vty
, "%% RD is not configured for this VRF\n");
4674 evpn_unconfigure_vrf_rd(bgp_vrf
);
4678 DEFUN (bgp_evpn_vni_rd
,
4679 bgp_evpn_vni_rd_cmd
,
4680 "rd ASN:NN_OR_IP-ADDRESS:NN",
4681 "Route Distinguisher\n"
4682 "ASN:XX or A.B.C.D:XX\n")
4684 struct prefix_rd prd
;
4685 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4686 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4692 if (!EVPN_ENABLED(bgp
)) {
4694 "This command is only supported under EVPN VRF\n");
4698 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4700 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4704 /* If same as existing value, there is nothing more to do. */
4705 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4708 /* Configure or update the RD. */
4709 evpn_configure_rd(bgp
, vpn
, &prd
);
4713 DEFUN (no_bgp_evpn_vni_rd
,
4714 no_bgp_evpn_vni_rd_cmd
,
4715 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4717 "Route Distinguisher\n"
4718 "ASN:XX or A.B.C.D:XX\n")
4720 struct prefix_rd prd
;
4721 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4722 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4728 if (!EVPN_ENABLED(bgp
)) {
4730 "This command is only supported under EVPN VRF\n");
4734 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4736 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4740 /* Check if we should disallow. */
4741 if (!is_rd_configured(vpn
)) {
4742 vty_out(vty
, "%% RD is not configured for this VNI\n");
4746 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4748 "%% RD specified does not match configuration for this VNI\n");
4752 evpn_unconfigure_rd(bgp
, vpn
);
4756 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4757 no_bgp_evpn_vni_rd_without_val_cmd
,
4760 "Route Distinguisher\n")
4762 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4763 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4768 if (!EVPN_ENABLED(bgp
)) {
4770 "This command is only supported under EVPN VRF\n");
4774 /* Check if we should disallow. */
4775 if (!is_rd_configured(vpn
)) {
4776 vty_out(vty
, "%% RD is not configured for this VNI\n");
4780 evpn_unconfigure_rd(bgp
, vpn
);
4785 * Loop over all extended-communities in the route-target list rtl and
4786 * return 1 if we find ecomtarget
4788 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4789 struct ecommunity
*ecomtarget
)
4791 struct listnode
*node
, *nnode
;
4792 struct ecommunity
*ecom
;
4794 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4795 if (ecommunity_match(ecom
, ecomtarget
))
4802 /* display L3VNI related info for a VRF instance */
4803 DEFUN (show_bgp_vrf_l3vni_info
,
4804 show_bgp_vrf_l3vni_info_cmd
,
4805 "show bgp vrf VRFNAME vni [json]",
4813 char buf
[ETHER_ADDR_STRLEN
];
4814 char buf1
[INET6_ADDRSTRLEN
];
4816 const char *name
= NULL
;
4817 struct bgp
*bgp
= NULL
;
4818 struct listnode
*node
= NULL
;
4819 struct bgpevpn
*vpn
= NULL
;
4820 struct ecommunity
*ecom
= NULL
;
4821 json_object
*json
= NULL
;
4822 json_object
*json_vnis
= NULL
;
4823 json_object
*json_export_rts
= NULL
;
4824 json_object
*json_import_rts
= NULL
;
4825 bool uj
= use_json(argc
, argv
);
4828 json
= json_object_new_object();
4829 json_vnis
= json_object_new_array();
4830 json_export_rts
= json_object_new_array();
4831 json_import_rts
= json_object_new_array();
4834 name
= argv
[idx_vrf
]->arg
;
4835 bgp
= bgp_lookup_by_name(name
);
4838 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4840 json_object_string_add(json
, "warning",
4841 "BGP instance not found");
4842 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4843 json_object_free(json
);
4849 vty_out(vty
, "BGP VRF: %s\n", name
);
4850 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4851 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4852 vty_out(vty
, " Rmac: %s\n",
4853 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4854 vty_out(vty
, " VNI Filter: %s\n",
4855 CHECK_FLAG(bgp
->vrf_flags
,
4856 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4857 ? "prefix-routes-only"
4859 vty_out(vty
, " L2-VNI List:\n");
4861 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4862 vty_out(vty
, "%u ", vpn
->vni
);
4864 vty_out(vty
, " Export-RTs:\n");
4866 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4867 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4869 vty_out(vty
, " Import-RTs:\n");
4871 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4872 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4874 vty_out(vty
, " RD: %s\n",
4875 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4877 json_object_string_add(json
, "vrf", name
);
4878 json_object_string_add(json
, "local-ip",
4879 inet_ntoa(bgp
->originator_ip
));
4880 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4881 json_object_string_add(
4883 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4884 json_object_string_add(
4886 CHECK_FLAG(bgp
->vrf_flags
,
4887 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4888 ? "prefix-routes-only"
4890 /* list of l2vnis */
4891 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4892 json_object_array_add(json_vnis
,
4893 json_object_new_int(vpn
->vni
));
4894 json_object_object_add(json
, "l2vnis", json_vnis
);
4897 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4898 json_object_array_add(
4900 json_object_new_string(ecommunity_str(ecom
)));
4901 json_object_object_add(json
, "export-rts", json_export_rts
);
4904 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4905 json_object_array_add(
4907 json_object_new_string(ecommunity_str(ecom
)));
4908 json_object_object_add(json
, "import-rts", json_import_rts
);
4909 json_object_string_add(
4911 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4915 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4916 json
, JSON_C_TO_STRING_PRETTY
));
4917 json_object_free(json
);
4922 /* import/export rt for l3vni-vrf */
4923 DEFUN (bgp_evpn_vrf_rt
,
4924 bgp_evpn_vrf_rt_cmd
,
4925 "route-target <both|import|export> RT",
4927 "import and export\n"
4930 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4933 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4934 struct ecommunity
*ecomadd
= NULL
;
4939 if (!strcmp(argv
[1]->arg
, "import"))
4940 rt_type
= RT_TYPE_IMPORT
;
4941 else if (!strcmp(argv
[1]->arg
, "export"))
4942 rt_type
= RT_TYPE_EXPORT
;
4943 else if (!strcmp(argv
[1]->arg
, "both"))
4944 rt_type
= RT_TYPE_BOTH
;
4946 vty_out(vty
, "%% Invalid Route Target type\n");
4950 /* Add/update the import route-target */
4951 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4952 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4953 ECOMMUNITY_ROUTE_TARGET
, 0);
4955 vty_out(vty
, "%% Malformed Route Target list\n");
4958 ecommunity_str(ecomadd
);
4960 /* Do nothing if we already have this import route-target */
4961 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4962 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4965 /* Add/update the export route-target */
4966 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4967 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4968 ECOMMUNITY_ROUTE_TARGET
, 0);
4970 vty_out(vty
, "%% Malformed Route Target list\n");
4973 ecommunity_str(ecomadd
);
4975 /* Do nothing if we already have this export route-target */
4976 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4977 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4983 DEFUN (no_bgp_evpn_vrf_rt
,
4984 no_bgp_evpn_vrf_rt_cmd
,
4985 "no route-target <both|import|export> RT",
4988 "import and export\n"
4991 "ASN:XX or A.B.C.D:XX\n")
4993 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4994 int rt_type
, found_ecomdel
;
4995 struct ecommunity
*ecomdel
= NULL
;
5000 if (!strcmp(argv
[2]->arg
, "import"))
5001 rt_type
= RT_TYPE_IMPORT
;
5002 else if (!strcmp(argv
[2]->arg
, "export"))
5003 rt_type
= RT_TYPE_EXPORT
;
5004 else if (!strcmp(argv
[2]->arg
, "both"))
5005 rt_type
= RT_TYPE_BOTH
;
5007 vty_out(vty
, "%% Invalid Route Target type\n");
5011 if (rt_type
== RT_TYPE_IMPORT
) {
5012 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5014 "%% Import RT is not configured for this VRF\n");
5017 } else if (rt_type
== RT_TYPE_EXPORT
) {
5018 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5020 "%% Export RT is not configured for this VRF\n");
5023 } else if (rt_type
== RT_TYPE_BOTH
) {
5024 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5025 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5027 "%% Import/Export RT is not configured for this VRF\n");
5032 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5034 vty_out(vty
, "%% Malformed Route Target list\n");
5037 ecommunity_str(ecomdel
);
5039 if (rt_type
== RT_TYPE_IMPORT
) {
5040 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5043 "%% RT specified does not match configuration for this VRF\n");
5046 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5047 } else if (rt_type
== RT_TYPE_EXPORT
) {
5048 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5051 "%% RT specified does not match configuration for this VRF\n");
5054 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5055 } else if (rt_type
== RT_TYPE_BOTH
) {
5058 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5060 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5064 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5066 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5070 if (!found_ecomdel
) {
5072 "%% RT specified does not match configuration for this VRF\n");
5080 DEFUN (bgp_evpn_vni_rt
,
5081 bgp_evpn_vni_rt_cmd
,
5082 "route-target <both|import|export> RT",
5084 "import and export\n"
5087 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5089 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5090 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5092 struct ecommunity
*ecomadd
= NULL
;
5097 if (!EVPN_ENABLED(bgp
)) {
5099 "This command is only supported under EVPN VRF\n");
5103 if (!strcmp(argv
[1]->text
, "import"))
5104 rt_type
= RT_TYPE_IMPORT
;
5105 else if (!strcmp(argv
[1]->text
, "export"))
5106 rt_type
= RT_TYPE_EXPORT
;
5107 else if (!strcmp(argv
[1]->text
, "both"))
5108 rt_type
= RT_TYPE_BOTH
;
5110 vty_out(vty
, "%% Invalid Route Target type\n");
5114 /* Add/update the import route-target */
5115 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5116 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5117 ECOMMUNITY_ROUTE_TARGET
, 0);
5119 vty_out(vty
, "%% Malformed Route Target list\n");
5122 ecommunity_str(ecomadd
);
5124 /* Do nothing if we already have this import route-target */
5125 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5126 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5129 /* Add/update the export route-target */
5130 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5131 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5132 ECOMMUNITY_ROUTE_TARGET
, 0);
5134 vty_out(vty
, "%% Malformed Route Target list\n");
5137 ecommunity_str(ecomadd
);
5139 /* Do nothing if we already have this export route-target */
5140 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5141 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5147 DEFUN (no_bgp_evpn_vni_rt
,
5148 no_bgp_evpn_vni_rt_cmd
,
5149 "no route-target <both|import|export> RT",
5152 "import and export\n"
5155 "ASN:XX or A.B.C.D:XX\n")
5157 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5158 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5159 int rt_type
, found_ecomdel
;
5160 struct ecommunity
*ecomdel
= NULL
;
5165 if (!EVPN_ENABLED(bgp
)) {
5167 "This command is only supported under EVPN VRF\n");
5171 if (!strcmp(argv
[2]->text
, "import"))
5172 rt_type
= RT_TYPE_IMPORT
;
5173 else if (!strcmp(argv
[2]->text
, "export"))
5174 rt_type
= RT_TYPE_EXPORT
;
5175 else if (!strcmp(argv
[2]->text
, "both"))
5176 rt_type
= RT_TYPE_BOTH
;
5178 vty_out(vty
, "%% Invalid Route Target type\n");
5182 /* The user did "no route-target import", check to see if there are any
5183 * import route-targets configured. */
5184 if (rt_type
== RT_TYPE_IMPORT
) {
5185 if (!is_import_rt_configured(vpn
)) {
5187 "%% Import RT is not configured for this VNI\n");
5190 } else if (rt_type
== RT_TYPE_EXPORT
) {
5191 if (!is_export_rt_configured(vpn
)) {
5193 "%% Export RT is not configured for this VNI\n");
5196 } else if (rt_type
== RT_TYPE_BOTH
) {
5197 if (!is_import_rt_configured(vpn
)
5198 && !is_export_rt_configured(vpn
)) {
5200 "%% Import/Export RT is not configured for this VNI\n");
5205 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5207 vty_out(vty
, "%% Malformed Route Target list\n");
5210 ecommunity_str(ecomdel
);
5212 if (rt_type
== RT_TYPE_IMPORT
) {
5213 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5215 "%% RT specified does not match configuration for this VNI\n");
5218 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5219 } else if (rt_type
== RT_TYPE_EXPORT
) {
5220 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5222 "%% RT specified does not match configuration for this VNI\n");
5225 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5226 } else if (rt_type
== RT_TYPE_BOTH
) {
5229 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5230 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5234 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5235 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5239 if (!found_ecomdel
) {
5241 "%% RT specified does not match configuration for this VNI\n");
5249 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5250 no_bgp_evpn_vni_rt_without_val_cmd
,
5251 "no route-target <import|export>",
5257 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5258 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5264 if (!EVPN_ENABLED(bgp
)) {
5266 "This command is only supported under EVPN VRF\n");
5270 if (!strcmp(argv
[2]->text
, "import")) {
5271 rt_type
= RT_TYPE_IMPORT
;
5272 } else if (!strcmp(argv
[2]->text
, "export")) {
5273 rt_type
= RT_TYPE_EXPORT
;
5275 vty_out(vty
, "%% Invalid Route Target type\n");
5279 /* Check if we should disallow. */
5280 if (rt_type
== RT_TYPE_IMPORT
) {
5281 if (!is_import_rt_configured(vpn
)) {
5283 "%% Import RT is not configured for this VNI\n");
5287 if (!is_export_rt_configured(vpn
)) {
5289 "%% Export RT is not configured for this VNI\n");
5294 /* Unconfigure the RT. */
5295 if (rt_type
== RT_TYPE_IMPORT
)
5296 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5298 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5302 static int vni_cmp(const void **a
, const void **b
)
5304 const struct bgpevpn
*first
= *a
;
5305 const struct bgpevpn
*secnd
= *b
;
5307 return secnd
->vni
- first
->vni
;
5311 * Output EVPN configuration information.
5313 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5316 char buf1
[RD_ADDRSTRLEN
];
5319 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5320 struct listnode
*ln
;
5321 struct bgpevpn
*data
;
5323 list_sort(vnilist
, vni_cmp
);
5324 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5325 write_vni_config(vty
, data
);
5327 list_delete(&vnilist
);
5330 if (bgp
->advertise_all_vni
)
5331 vty_out(vty
, " advertise-all-vni\n");
5333 if (bgp
->advertise_autort_rfc8365
)
5334 vty_out(vty
, " autort rfc8365-compatible\n");
5336 if (bgp
->advertise_gw_macip
)
5337 vty_out(vty
, " advertise-default-gw\n");
5339 if (bgp
->evpn_info
->advertise_svi_macip
)
5340 vty_out(vty
, " advertise-svi-ip\n");
5342 if (!bgp
->evpn_info
->dup_addr_detect
)
5343 vty_out(vty
, " no dup-addr-detection\n");
5345 if (bgp
->evpn_info
->dad_max_moves
!=
5346 EVPN_DAD_DEFAULT_MAX_MOVES
||
5347 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5348 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5349 bgp
->evpn_info
->dad_max_moves
,
5350 bgp
->evpn_info
->dad_time
);
5352 if (bgp
->evpn_info
->dad_freeze
) {
5353 if (bgp
->evpn_info
->dad_freeze_time
)
5355 " dup-addr-detection freeze %u\n",
5356 bgp
->evpn_info
->dad_freeze_time
);
5359 " dup-addr-detection freeze permanent\n");
5362 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5363 vty_out(vty
, " flooding disable\n");
5365 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5366 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5367 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5368 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5369 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5371 vty_out(vty
, " advertise ipv4 unicast\n");
5374 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5375 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5376 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5377 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5378 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5380 vty_out(vty
, " advertise ipv6 unicast\n");
5383 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5384 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5385 vty_out(vty
, " default-originate ipv4\n");
5387 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5388 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5389 vty_out(vty
, " default-originate ipv6\n");
5391 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5392 vty_out(vty
, " rd %s\n",
5393 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5395 /* import route-target */
5396 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5398 struct listnode
*node
, *nnode
;
5399 struct ecommunity
*ecom
;
5401 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5403 ecom_str
= ecommunity_ecom2str(
5404 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5405 vty_out(vty
, " route-target import %s\n", ecom_str
);
5406 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5410 /* export route-target */
5411 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5413 struct listnode
*node
, *nnode
;
5414 struct ecommunity
*ecom
;
5416 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5418 ecom_str
= ecommunity_ecom2str(
5419 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5420 vty_out(vty
, " route-target export %s\n", ecom_str
);
5421 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5426 void bgp_ethernetvpn_init(void)
5428 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5429 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5430 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5431 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5432 install_element(VIEW_NODE
,
5433 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5434 install_element(VIEW_NODE
,
5435 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5438 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5441 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5442 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5443 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5444 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5445 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5446 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5447 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5448 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5449 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5450 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5451 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5452 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5453 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5454 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5455 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5456 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5457 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5458 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5459 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5460 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5463 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5464 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5466 /* "show bgp l2vpn evpn" commands. */
5467 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5468 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5469 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5470 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5471 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5472 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5473 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5474 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5475 install_element(VIEW_NODE
,
5476 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5477 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5478 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5479 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5480 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5482 /* "show bgp evpn" commands. */
5483 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5484 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5485 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5486 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5487 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5488 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5489 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5490 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5491 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5492 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5493 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5495 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5496 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5497 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5498 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5499 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5500 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5501 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5502 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5503 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5504 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5505 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5506 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5507 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5508 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5509 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5510 install_element(BGP_EVPN_VNI_NODE
,
5511 &bgp_evpn_advertise_default_gw_vni_cmd
);
5512 install_element(BGP_EVPN_VNI_NODE
,
5513 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5514 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5515 install_element(BGP_EVPN_VNI_NODE
,
5516 &no_bgp_evpn_advertise_vni_subnet_cmd
);