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");
362 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
363 vty_out(vty
, " (known to the kernel)");
366 vty_out(vty
, " Type: %s\n", "L3");
367 vty_out(vty
, " Tenant VRF: %s\n",
368 vrf_id_to_name(bgp_vrf
->vrf_id
));
369 vty_out(vty
, " RD: %s\n",
370 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
371 vty_out(vty
, " Originator IP: %s\n",
372 inet_ntoa(bgp_vrf
->originator_ip
));
373 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
377 vty_out(vty
, " Import Route Target:\n");
379 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
380 ecom_str
= ecommunity_ecom2str(ecom
,
381 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
384 json_object_array_add(json_import_rtl
,
385 json_object_new_string(ecom_str
));
387 vty_out(vty
, " %s\n", ecom_str
);
389 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
393 json_object_object_add(json
, "importRts", json_import_rtl
);
395 vty_out(vty
, " Export Route Target:\n");
397 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
398 ecom_str
= ecommunity_ecom2str(ecom
,
399 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
402 json_object_array_add(json_export_rtl
,
403 json_object_new_string(ecom_str
));
405 vty_out(vty
, " %s\n", ecom_str
);
407 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
411 json_object_object_add(json
, "exportRts", json_export_rtl
);
414 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
416 struct in_addr
*vtep
;
417 char buf
[ESI_STR_LEN
];
418 char buf1
[RD_ADDRSTRLEN
];
419 char buf2
[INET6_ADDRSTRLEN
];
420 struct listnode
*node
= NULL
;
421 json_object
*json_vteps
= NULL
;
424 json_vteps
= json_object_new_array();
425 json_object_string_add(json
, "esi",
426 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
427 json_object_string_add(json
, "rd",
428 prefix_rd2str(&es
->prd
, buf1
,
430 json_object_string_add(
431 json
, "originatorIp",
432 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
434 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
435 json_object_array_add(
436 json_vteps
, json_object_new_string(
439 json_object_object_add(json
, "vteps", json_vteps
);
441 vty_out(vty
, "ESI: %s\n",
442 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
443 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
445 vty_out(vty
, " Originator-IP: %s\n",
446 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
448 vty_out(vty
, " VTEP List:\n");
449 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
450 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
455 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
457 char buf1
[RD_ADDRSTRLEN
];
459 struct listnode
*node
, *nnode
;
460 struct ecommunity
*ecom
;
461 json_object
*json_import_rtl
= NULL
;
462 json_object
*json_export_rtl
= NULL
;
465 json_import_rtl
= json_object_new_array();
466 json_export_rtl
= json_object_new_array();
467 json_object_int_add(json
, "vni", vpn
->vni
);
468 json_object_string_add(json
, "type", "L2");
469 json_object_string_add(json
, "kernelFlag",
470 is_vni_live(vpn
) ? "Yes" : "No");
471 json_object_string_add(
473 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
474 json_object_string_add(json
, "originatorIp",
475 inet_ntoa(vpn
->originator_ip
));
476 json_object_string_add(json
, "mcastGroup",
477 inet_ntoa(vpn
->mcast_grp
));
478 json_object_string_add(json
, "advertiseGatewayMacip",
479 vpn
->advertise_gw_macip
? "Yes" : "No");
481 vty_out(vty
, "VNI: %d", vpn
->vni
);
482 if (is_vni_live(vpn
))
483 vty_out(vty
, " (known to the kernel)");
486 vty_out(vty
, " Type: %s\n", "L2");
487 vty_out(vty
, " Tenant-Vrf: %s\n",
488 vrf_id_to_name(vpn
->tenant_vrf_id
));
489 vty_out(vty
, " RD: %s\n",
490 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
491 vty_out(vty
, " Originator IP: %s\n",
492 inet_ntoa(vpn
->originator_ip
));
493 vty_out(vty
, " Mcast group: %s\n",
494 inet_ntoa(vpn
->mcast_grp
));
495 vty_out(vty
, " Advertise-gw-macip : %s\n",
496 vpn
->advertise_gw_macip
? "Yes" : "No");
497 vty_out(vty
, " Advertise-svi-macip : %s\n",
498 vpn
->advertise_svi_macip
? "Yes" : "No");
502 vty_out(vty
, " Import Route Target:\n");
504 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
505 ecom_str
= ecommunity_ecom2str(ecom
,
506 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
509 json_object_array_add(json_import_rtl
,
510 json_object_new_string(ecom_str
));
512 vty_out(vty
, " %s\n", ecom_str
);
514 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
518 json_object_object_add(json
, "importRts", json_import_rtl
);
520 vty_out(vty
, " Export Route Target:\n");
522 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
523 ecom_str
= ecommunity_ecom2str(ecom
,
524 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
527 json_object_array_add(json_export_rtl
,
528 json_object_new_string(ecom_str
));
530 vty_out(vty
, " %s\n", ecom_str
);
532 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
536 json_object_object_add(json
, "exportRts", json_export_rtl
);
539 static void show_esi_routes(struct bgp
*bgp
,
546 struct bgp_path_info
*pi
;
547 uint32_t prefix_cnt
, path_cnt
;
550 prefix_cnt
= path_cnt
= 0;
552 tbl_ver
= es
->route_table
->version
;
553 for (rn
= bgp_table_top(es
->route_table
); rn
;
554 rn
= bgp_route_next(rn
)) {
555 int add_prefix_to_json
= 0;
556 char prefix_str
[BUFSIZ
];
557 json_object
*json_paths
= NULL
;
558 json_object
*json_prefix
= NULL
;
560 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
564 json_prefix
= json_object_new_object();
566 pi
= bgp_node_get_bgp_path_info(rn
);
568 /* Overall header/legend displayed once. */
570 bgp_evpn_show_route_header(vty
, bgp
,
579 json_paths
= json_object_new_array();
581 /* For EVPN, the prefix is displayed for each path (to fit in
582 * with code that already exists).
584 for (; pi
; pi
= pi
->next
) {
585 json_object
*json_path
= NULL
;
588 json_path
= json_object_new_array();
590 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
593 json_object_array_add(json_paths
, json_path
);
596 add_prefix_to_json
= 1;
599 if (json
&& add_prefix_to_json
) {
600 json_object_string_add(json_prefix
, "prefix",
602 json_object_int_add(json_prefix
, "prefixLen",
604 json_object_object_add(json_prefix
, "paths",
606 json_object_object_add(json
, prefix_str
, json_prefix
);
611 json_object_int_add(json
, "numPrefix", prefix_cnt
);
612 json_object_int_add(json
, "numPaths", path_cnt
);
615 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
617 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
618 prefix_cnt
, path_cnt
);
622 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
623 struct vty
*vty
, struct in_addr vtep_ip
,
624 json_object
*json
, int detail
)
627 struct bgp_path_info
*pi
;
628 struct bgp_table
*table
;
629 int header
= detail
? 0 : 1;
631 uint32_t prefix_cnt
, path_cnt
;
633 prefix_cnt
= path_cnt
= 0;
635 table
= vpn
->route_table
;
636 tbl_ver
= table
->version
;
637 for (rn
= bgp_table_top(table
); rn
;
638 rn
= bgp_route_next(rn
)) {
639 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
640 int add_prefix_to_json
= 0;
641 char prefix_str
[BUFSIZ
];
642 json_object
*json_paths
= NULL
;
643 json_object
*json_prefix
= NULL
;
645 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
648 if (type
&& evp
->prefix
.route_type
!= type
)
652 json_prefix
= json_object_new_object();
654 pi
= bgp_node_get_bgp_path_info(rn
);
656 /* Overall header/legend displayed once. */
658 bgp_evpn_show_route_header(vty
, bgp
,
667 json_paths
= json_object_new_array();
669 /* For EVPN, the prefix is displayed for each path (to fit in
670 * with code that already exists).
672 for (; pi
; pi
= pi
->next
) {
673 json_object
*json_path
= NULL
;
676 && !IPV4_ADDR_SAME(&(vtep_ip
),
677 &(pi
->attr
->nexthop
)))
681 json_path
= json_object_new_array();
684 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
,
685 AFI_L2VPN
, SAFI_EVPN
,
688 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
692 json_object_array_add(json_paths
, json_path
);
695 add_prefix_to_json
= 1;
698 if (json
&& add_prefix_to_json
) {
699 json_object_string_add(json_prefix
, "prefix",
701 json_object_int_add(json_prefix
, "prefixLen",
703 json_object_object_add(json_prefix
, "paths",
705 json_object_object_add(json
, prefix_str
, json_prefix
);
710 json_object_int_add(json
, "numPrefix", prefix_cnt
);
711 json_object_int_add(json
, "numPaths", path_cnt
);
714 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
715 type
? "(of requested type) " : "");
717 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
718 prefix_cnt
, path_cnt
,
719 type
? " (of requested type)" : "");
724 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
726 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
727 struct vni_walk_ctx
*wctx
= arg
;
728 struct vty
*vty
= wctx
->vty
;
729 json_object
*json
= wctx
->json
;
730 json_object
*json_vni
= NULL
;
731 char vni_str
[VNI_STR_LEN
];
733 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
735 json_vni
= json_object_new_object();
736 json_object_int_add(json_vni
, "vni", vpn
->vni
);
738 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
741 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
745 json_object_object_add(json
, vni_str
, json_vni
);
748 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
751 json_object
*json_vni
= NULL
;
752 json_object
*json_import_rtl
= NULL
;
753 json_object
*json_export_rtl
= NULL
;
755 char buf2
[INET6_ADDRSTRLEN
];
758 struct listnode
*node
, *nnode
;
759 struct ecommunity
*ecom
;
765 json_vni
= json_object_new_object();
766 json_import_rtl
= json_object_new_array();
767 json_export_rtl
= json_object_new_array();
770 /* if an l3vni is present in bgp it is live */
775 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
776 json_object_string_add(json_vni
, "type", "L3");
777 json_object_string_add(json_vni
, "inKernel", "True");
778 json_object_string_add(json_vni
, "originatorIp",
779 inet_ntoa(bgp
->originator_ip
));
780 json_object_string_add(
782 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
784 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
785 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
788 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
789 ecom_str
= ecommunity_ecom2str(ecom
,
790 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
793 json_object_array_add(json_import_rtl
,
794 json_object_new_string(ecom_str
));
796 if (listcount(bgp
->vrf_import_rtl
) > 1)
797 sprintf(rt_buf
, "%s, ...", ecom_str
);
799 sprintf(rt_buf
, "%s", ecom_str
);
800 vty_out(vty
, " %-25s", rt_buf
);
803 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
805 /* If there are multiple import RTs we break here and show only
812 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
814 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
815 ecom_str
= ecommunity_ecom2str(ecom
,
816 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
819 json_object_array_add(json_export_rtl
,
820 json_object_new_string(ecom_str
));
822 if (listcount(bgp
->vrf_export_rtl
) > 1)
823 sprintf(rt_buf
, "%s, ...", ecom_str
);
825 sprintf(rt_buf
, "%s", ecom_str
);
826 vty_out(vty
, " %-25s", rt_buf
);
829 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
831 /* If there are multiple export RTs we break here and show only
838 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
841 char vni_str
[VNI_STR_LEN
];
843 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
844 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
845 json_object_object_add(json
, vni_str
, json_vni
);
851 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
853 char buf
[ESI_STR_LEN
];
854 char buf1
[RD_ADDRSTRLEN
];
855 char buf2
[INET6_ADDRSTRLEN
];
856 struct in_addr
*vtep
= NULL
;
857 struct vty
*vty
= args
[0];
858 json_object
*json
= args
[1];
859 json_object
*json_vteps
= NULL
;
860 struct listnode
*node
= NULL
;
861 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
864 json_vteps
= json_object_new_array();
865 json_object_string_add(json
, "esi",
866 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
867 json_object_string_add(json
, "type",
868 is_es_local(es
) ? "Local" : "Remote");
869 json_object_string_add(json
, "rd",
870 prefix_rd2str(&es
->prd
, buf1
,
872 json_object_string_add(
873 json
, "originatorIp",
874 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
876 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
877 json_object_array_add(json_vteps
,
878 json_object_new_string(
881 json_object_object_add(json
, "vteps", json_vteps
);
883 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
884 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
885 is_es_local(es
) ? "Local" : "Remote",
886 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
887 ipaddr2str(&es
->originator_ip
, buf2
,
889 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
893 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
897 json_object
*json_vni
= NULL
;
898 json_object
*json_import_rtl
= NULL
;
899 json_object
*json_export_rtl
= NULL
;
900 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
902 char buf2
[RD_ADDRSTRLEN
];
905 struct listnode
*node
, *nnode
;
906 struct ecommunity
*ecom
;
912 json_vni
= json_object_new_object();
913 json_import_rtl
= json_object_new_array();
914 json_export_rtl
= json_object_new_array();
918 if (is_vni_live(vpn
))
922 json_object_int_add(json_vni
, "vni", vpn
->vni
);
923 json_object_string_add(json_vni
, "type", "L2");
924 json_object_string_add(json_vni
, "inKernel",
925 is_vni_live(vpn
) ? "True" : "False");
926 json_object_string_add(json_vni
, "originatorIp",
927 inet_ntoa(vpn
->originator_ip
));
928 json_object_string_add(json_vni
, "originatorIp",
929 inet_ntoa(vpn
->originator_ip
));
930 json_object_string_add(
932 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
934 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
935 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
938 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
939 ecom_str
= ecommunity_ecom2str(ecom
,
940 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
943 json_object_array_add(json_import_rtl
,
944 json_object_new_string(ecom_str
));
946 if (listcount(vpn
->import_rtl
) > 1)
947 sprintf(rt_buf
, "%s, ...", ecom_str
);
949 sprintf(rt_buf
, "%s", ecom_str
);
950 vty_out(vty
, " %-25s", rt_buf
);
953 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
955 /* If there are multiple import RTs we break here and show only
962 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
964 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
965 ecom_str
= ecommunity_ecom2str(ecom
,
966 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
969 json_object_array_add(json_export_rtl
,
970 json_object_new_string(ecom_str
));
972 if (listcount(vpn
->export_rtl
) > 1)
973 sprintf(rt_buf
, "%s, ...", ecom_str
);
975 sprintf(rt_buf
, "%s", ecom_str
);
976 vty_out(vty
, " %-25s", rt_buf
);
979 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
981 /* If there are multiple export RTs we break here and show only
988 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
991 char vni_str
[VNI_STR_LEN
];
993 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
994 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
995 json_object_object_add(json
, vni_str
, json_vni
);
1001 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1002 enum bgp_show_type type
, void *output_arg
,
1003 int option
, bool use_json
)
1005 afi_t afi
= AFI_L2VPN
;
1007 struct bgp_table
*table
;
1008 struct bgp_node
*rn
;
1009 struct bgp_node
*rm
;
1010 struct bgp_path_info
*pi
;
1013 char rd_str
[BUFSIZ
];
1016 unsigned long output_count
= 0;
1017 unsigned long total_count
= 0;
1018 json_object
*json
= NULL
;
1019 json_object
*json_nroute
= NULL
;
1020 json_object
*json_array
= NULL
;
1021 json_object
*json_prefix_info
= NULL
;
1023 memset(rd_str
, 0, BUFSIZ
);
1025 bgp
= bgp_get_evpn();
1028 vty_out(vty
, "No BGP process is configured\n");
1030 vty_out(vty
, "{}\n");
1035 json
= json_object_new_object();
1037 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1038 rn
= bgp_route_next(rn
)) {
1041 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1044 table
= bgp_node_get_bgp_table_info(rn
);
1049 tbl_ver
= table
->version
;
1051 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1052 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
1055 if (type
== bgp_show_type_neighbor
) {
1056 union sockunion
*su
= output_arg
;
1058 if (pi
->peer
->su_remote
== NULL
1060 pi
->peer
->su_remote
, su
))
1065 json_object_int_add(
1066 json
, "bgpTableVersion",
1068 json_object_string_add(
1073 json_object_int_add(
1076 bgp
->default_local_pref
);
1077 json_object_int_add(
1081 if (option
== SHOW_DISPLAY_TAGS
)
1086 == SHOW_DISPLAY_OVERLAY
)
1091 "BGP table version is %" PRIu64
", local router ID is %s\n",
1096 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1098 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1099 vty_out(vty
, V4_HEADER
);
1112 /* Decode RD type. */
1113 type
= decode_rd_type(pnt
);
1114 /* Decode RD value. */
1115 if (type
== RD_TYPE_AS
)
1116 decode_rd_as(pnt
+ 2, &rd_as
);
1117 else if (type
== RD_TYPE_AS4
)
1118 decode_rd_as4(pnt
+ 2, &rd_as
);
1119 else if (type
== RD_TYPE_IP
)
1120 decode_rd_ip(pnt
+ 2, &rd_ip
);
1123 json_object_new_object();
1125 json_object_new_object();
1127 json_object_new_array();
1128 if (type
== RD_TYPE_AS
1129 || type
== RD_TYPE_AS4
)
1130 sprintf(rd_str
, "%u:%d",
1133 else if (type
== RD_TYPE_IP
)
1134 sprintf(rd_str
, "%s:%d",
1138 json_object_string_add(
1143 json_object_string_add(
1147 (struct prefix_evpn
*)
1148 &rm
->p
, buf
, BUFSIZ
));
1150 json_object_int_add(
1157 "Route Distinguisher: ");
1158 if (type
== RD_TYPE_AS
)
1163 else if (type
== RD_TYPE_AS4
)
1168 else if (type
== RD_TYPE_IP
)
1169 vty_out(vty
, "ip %s:%d",
1173 vty_out(vty
, "\n\n");
1177 if (option
== SHOW_DISPLAY_TAGS
)
1178 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1181 else if (option
== SHOW_DISPLAY_OVERLAY
)
1182 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1185 route_vty_out(vty
, &rm
->p
, pi
, 0,
1186 SAFI_EVPN
, json_array
);
1191 json_object_object_add(json_prefix_info
, "paths",
1193 json_object_object_add(json_nroute
, buf
,
1195 json_object_object_add(json
, rd_str
, json_nroute
);
1200 json_object_int_add(json
, "numPrefix", output_count
);
1201 json_object_int_add(json
, "totalPrefix", total_count
);
1202 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1203 json
, JSON_C_TO_STRING_PRETTY
));
1204 json_object_free(json
);
1206 if (output_count
== 0)
1207 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1211 "\nDisplayed %ld out of %ld total prefixes\n",
1212 output_count
, total_count
);
1217 DEFUN(show_ip_bgp_l2vpn_evpn
,
1218 show_ip_bgp_l2vpn_evpn_cmd
,
1219 "show [ip] bgp l2vpn evpn [json]",
1220 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1222 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1223 use_json(argc
, argv
));
1226 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1227 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1228 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1234 "Display information for a route distinguisher\n"
1235 "VPN Route Distinguisher\n" JSON_STR
)
1237 int idx_ext_community
= 0;
1239 struct prefix_rd prd
;
1241 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1243 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1245 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1248 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1249 use_json(argc
, argv
));
1252 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1253 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1254 "show [ip] bgp l2vpn evpn all tags",
1260 "Display information about all EVPN NLRIs\n"
1261 "Display BGP tags for prefixes\n")
1263 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1267 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1268 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1269 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1275 "Display information for a route distinguisher\n"
1276 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1278 int idx_ext_community
= 0;
1280 struct prefix_rd prd
;
1282 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1284 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1286 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1289 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1293 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1294 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1295 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1301 "Display information about all EVPN NLRIs\n"
1302 "Detailed information on TCP and BGP neighbor connections\n"
1303 "Neighbor to display information about\n"
1304 "Display routes learned from neighbor\n" JSON_STR
)
1310 bool uj
= use_json(argc
, argv
);
1312 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1314 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1317 json_object
*json_no
= NULL
;
1318 json_no
= json_object_new_object();
1319 json_object_string_add(json_no
, "warning",
1320 "Malformed address");
1321 vty_out(vty
, "%s\n",
1322 json_object_to_json_string(json_no
));
1323 json_object_free(json_no
);
1325 vty_out(vty
, "Malformed address: %s\n",
1326 argv
[idx_ipv4
]->arg
);
1330 peer
= peer_lookup(NULL
, &su
);
1331 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1333 json_object
*json_no
= NULL
;
1334 json_no
= json_object_new_object();
1335 json_object_string_add(
1337 "No such neighbor or address family");
1338 vty_out(vty
, "%s\n",
1339 json_object_to_json_string(json_no
));
1340 json_object_free(json_no
);
1342 vty_out(vty
, "%% No such neighbor or address family\n");
1346 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1350 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1351 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1352 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1358 "Display information for a route distinguisher\n"
1359 "VPN Route Distinguisher\n"
1360 "Detailed information on TCP and BGP neighbor connections\n"
1361 "Neighbor to display information about\n"
1362 "Display routes learned from neighbor\n" JSON_STR
)
1364 int idx_ext_community
= 0;
1369 struct prefix_rd prd
;
1370 bool uj
= use_json(argc
, argv
);
1372 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1373 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1375 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1378 json_object
*json_no
= NULL
;
1379 json_no
= json_object_new_object();
1380 json_object_string_add(json_no
, "warning",
1381 "Malformed Route Distinguisher");
1382 vty_out(vty
, "%s\n",
1383 json_object_to_json_string(json_no
));
1384 json_object_free(json_no
);
1386 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1390 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1393 json_object
*json_no
= NULL
;
1394 json_no
= json_object_new_object();
1395 json_object_string_add(json_no
, "warning",
1396 "Malformed address");
1397 vty_out(vty
, "%s\n",
1398 json_object_to_json_string(json_no
));
1399 json_object_free(json_no
);
1401 vty_out(vty
, "Malformed address: %s\n",
1402 argv
[idx_ext_community
]->arg
);
1406 peer
= peer_lookup(NULL
, &su
);
1407 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1409 json_object
*json_no
= NULL
;
1410 json_no
= json_object_new_object();
1411 json_object_string_add(
1413 "No such neighbor or address family");
1414 vty_out(vty
, "%s\n",
1415 json_object_to_json_string(json_no
));
1416 json_object_free(json_no
);
1418 vty_out(vty
, "%% No such neighbor or address family\n");
1422 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1426 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1427 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1428 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1434 "Display information about all EVPN NLRIs\n"
1435 "Detailed information on TCP and BGP neighbor connections\n"
1436 "Neighbor to display information about\n"
1437 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1443 bool uj
= use_json(argc
, argv
);
1445 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1447 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1450 json_object
*json_no
= NULL
;
1451 json_no
= json_object_new_object();
1452 json_object_string_add(json_no
, "warning",
1453 "Malformed address");
1454 vty_out(vty
, "%s\n",
1455 json_object_to_json_string(json_no
));
1456 json_object_free(json_no
);
1458 vty_out(vty
, "Malformed address: %s\n",
1459 argv
[idx_ipv4
]->arg
);
1462 peer
= peer_lookup(NULL
, &su
);
1463 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1465 json_object
*json_no
= NULL
;
1466 json_no
= json_object_new_object();
1467 json_object_string_add(
1469 "No such neighbor or address family");
1470 vty_out(vty
, "%s\n",
1471 json_object_to_json_string(json_no
));
1472 json_object_free(json_no
);
1474 vty_out(vty
, "%% No such neighbor or address family\n");
1478 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1481 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1482 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1483 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1489 "Display information for a route distinguisher\n"
1490 "VPN Route Distinguisher\n"
1491 "Detailed information on TCP and BGP neighbor connections\n"
1492 "Neighbor to display information about\n"
1493 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1495 int idx_ext_community
= 0;
1499 struct prefix_rd prd
;
1501 bool uj
= use_json(argc
, argv
);
1503 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1504 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1506 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1509 json_object
*json_no
= NULL
;
1510 json_no
= json_object_new_object();
1511 json_object_string_add(json_no
, "warning",
1512 "Malformed address");
1513 vty_out(vty
, "%s\n",
1514 json_object_to_json_string(json_no
));
1515 json_object_free(json_no
);
1517 vty_out(vty
, "Malformed address: %s\n",
1518 argv
[idx_ext_community
]->arg
);
1521 peer
= peer_lookup(NULL
, &su
);
1522 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1524 json_object
*json_no
= NULL
;
1525 json_no
= json_object_new_object();
1526 json_object_string_add(
1528 "No such neighbor or address family");
1529 vty_out(vty
, "%s\n",
1530 json_object_to_json_string(json_no
));
1531 json_object_free(json_no
);
1533 vty_out(vty
, "%% No such neighbor or address family\n");
1537 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1540 json_object
*json_no
= NULL
;
1541 json_no
= json_object_new_object();
1542 json_object_string_add(json_no
, "warning",
1543 "Malformed Route Distinguisher");
1544 vty_out(vty
, "%s\n",
1545 json_object_to_json_string(json_no
));
1546 json_object_free(json_no
);
1548 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1552 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1555 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1556 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1557 "show [ip] bgp l2vpn evpn all overlay",
1563 "Display information about all EVPN NLRIs\n"
1564 "Display BGP Overlay Information for prefixes\n")
1566 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1567 SHOW_DISPLAY_OVERLAY
,
1568 use_json(argc
, argv
));
1571 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1572 show_ip_bgp_evpn_rd_overlay_cmd
,
1573 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1579 "Display information for a route distinguisher\n"
1580 "VPN Route Distinguisher\n"
1581 "Display BGP Overlay Information for prefixes\n")
1583 int idx_ext_community
= 0;
1585 struct prefix_rd prd
;
1587 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1589 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1591 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1594 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1595 SHOW_DISPLAY_OVERLAY
,
1596 use_json(argc
, argv
));
1599 /* For testing purpose, static route of MPLS-VPN. */
1600 DEFUN(evpnrt5_network
,
1601 evpnrt5_network_cmd
,
1602 "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]",
1603 "Specify a network to announce via BGP\n"
1606 "Specify Route Distinguisher\n"
1607 "VPN Route Distinguisher\n"
1609 "Ethernet Tag Value\n"
1612 "Ethernet Segment Identifier\n"
1613 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1615 "Gateway IP ( A.B.C.D )\n"
1616 "Gateway IPv6 ( X:X::X:X )\n"
1617 "Router Mac Ext Comm\n"
1618 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1619 "Route-map to modify the attributes\n"
1620 "Name of the route map\n")
1622 int idx_ipv4_prefixlen
= 1;
1623 int idx_route_distinguisher
= 3;
1628 int idx_routermac
= 13;
1630 return bgp_static_set_safi(
1631 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1632 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1633 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1634 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1635 argv
[idx_routermac
]->arg
);
1638 /* For testing purpose, static route of MPLS-VPN. */
1639 DEFUN(no_evpnrt5_network
,
1640 no_evpnrt5_network_cmd
,
1641 "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>",
1643 "Specify a network to announce via BGP\n"
1646 "Specify Route Distinguisher\n"
1647 "VPN Route Distinguisher\n"
1649 "Ethernet Tag Value\n"
1652 "Ethernet Segment Identifier\n"
1653 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1654 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1656 int idx_ipv4_prefixlen
= 2;
1657 int idx_ext_community
= 4;
1662 return bgp_static_unset_safi(
1663 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1664 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1665 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1666 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1669 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1671 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1674 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1676 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1680 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1681 * check that this is a change.
1683 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1684 struct ecommunity
*ecomadd
)
1686 /* If the VNI is "live", we need to uninstall routes using the current
1687 * import RT(s) first before we update the import RT, and subsequently
1690 if (is_vni_live(vpn
))
1691 bgp_evpn_uninstall_routes(bgp
, vpn
);
1693 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1694 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1696 /* If the auto route-target is in use we must remove it */
1697 evpn_import_rt_delete_auto(bgp
, vpn
);
1699 /* Add new RT and rebuild the RT to VNI mapping */
1700 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1702 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1703 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1705 /* Install routes that match new import RT */
1706 if (is_vni_live(vpn
))
1707 bgp_evpn_install_routes(bgp
, vpn
);
1711 * Unconfigure Import RT(s) for a VNI (vty handler).
1713 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1714 struct ecommunity
*ecomdel
)
1716 struct listnode
*node
, *nnode
, *node_to_del
;
1717 struct ecommunity
*ecom
;
1719 /* Along the lines of "configure" except we have to reset to the
1722 if (is_vni_live(vpn
))
1723 bgp_evpn_uninstall_routes(bgp
, vpn
);
1725 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1726 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1728 /* Delete all import RTs */
1729 if (ecomdel
== NULL
) {
1730 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1731 ecommunity_free(&ecom
);
1732 list_delete_node(vpn
->import_rtl
, node
);
1736 /* Delete a specific import RT */
1740 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1741 if (ecommunity_match(ecom
, ecomdel
)) {
1742 ecommunity_free(&ecom
);
1749 list_delete_node(vpn
->import_rtl
, node_to_del
);
1752 assert(vpn
->import_rtl
);
1753 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1754 if (list_isempty(vpn
->import_rtl
)) {
1755 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1756 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1758 /* Rebuild the RT to VNI mapping */
1760 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1762 /* Install routes that match new import RT */
1763 if (is_vni_live(vpn
))
1764 bgp_evpn_install_routes(bgp
, vpn
);
1768 * Configure the Export RT for a VNI (vty handler). Caller expected to
1769 * check that this is a change. Note that only a single export RT is
1770 * allowed for a VNI and any change to configuration is implemented as
1771 * a "replace" (similar to other configuration).
1773 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1774 struct ecommunity
*ecomadd
)
1776 /* If the auto route-target is in use we must remove it */
1777 evpn_export_rt_delete_auto(bgp
, vpn
);
1779 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1780 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1782 if (is_vni_live(vpn
))
1783 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1787 * Unconfigure the Export RT for a VNI (vty handler)
1789 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1790 struct ecommunity
*ecomdel
)
1792 struct listnode
*node
, *nnode
, *node_to_del
;
1793 struct ecommunity
*ecom
;
1795 /* Delete all export RTs */
1796 if (ecomdel
== NULL
) {
1797 /* Reset to default and process all routes. */
1798 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1799 ecommunity_free(&ecom
);
1800 list_delete_node(vpn
->export_rtl
, node
);
1804 /* Delete a specific export RT */
1808 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1809 if (ecommunity_match(ecom
, ecomdel
)) {
1810 ecommunity_free(&ecom
);
1817 list_delete_node(vpn
->export_rtl
, node_to_del
);
1820 assert(vpn
->export_rtl
);
1821 if (list_isempty(vpn
->export_rtl
)) {
1822 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1823 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1826 if (is_vni_live(vpn
))
1827 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1831 * Configure RD for VRF
1833 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1835 /* If we have already advertise type-5 routes with a diffrent RD, we
1836 * have to delete and withdraw them firs
1838 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1841 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1842 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1844 /* We have a new RD for VRF.
1845 * Advertise all type-5 routes again with the new RD
1847 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1851 * Unconfigure RD for VRF
1853 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1855 /* If we have already advertise type-5 routes with a diffrent RD, we
1856 * have to delete and withdraw them firs
1858 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1860 /* fall back to default RD */
1861 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1862 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1864 /* We have a new RD for VRF.
1865 * Advertise all type-5 routes again with the new RD
1867 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1871 * Configure RD for a VNI (vty handler)
1873 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1874 struct prefix_rd
*rd
)
1876 /* If the VNI is "live", we need to delete and withdraw this VNI's
1877 * local routes with the prior RD first. Then, after updating RD,
1878 * need to re-advertise.
1880 if (is_vni_live(vpn
))
1881 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1884 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1885 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1887 if (is_vni_live(vpn
))
1888 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1892 * Unconfigure RD for a VNI (vty handler)
1894 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1896 /* If the VNI is "live", we need to delete and withdraw this VNI's
1897 * local routes with the prior RD first. Then, after resetting RD
1898 * to automatic value, need to re-advertise.
1900 if (is_vni_live(vpn
))
1901 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1903 /* reset RD to default */
1904 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1906 if (is_vni_live(vpn
))
1907 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1911 * Create VNI, if not already present (VTY handler). Mark as configured.
1913 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1915 struct bgpevpn
*vpn
;
1916 struct in_addr mcast_grp
= {INADDR_ANY
};
1921 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1923 /* Check if this L2VNI is already configured as L3VNI */
1924 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
1927 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1932 /* tenant vrf will be updated when we get local_vni_add from
1935 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
1939 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1945 /* Mark as configured. */
1946 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1951 * Delete VNI. If VNI does not exist in the system (i.e., just
1952 * configuration), all that is needed is to free it. Otherwise,
1953 * any parameters configured for the VNI need to be reset (with
1954 * appropriate action) and the VNI marked as unconfigured; the
1955 * VNI will continue to exist, purely as a "learnt" entity.
1957 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1959 assert(bgp
->vnihash
);
1961 if (!is_vni_live(vpn
)) {
1962 bgp_evpn_free(bgp
, vpn
);
1966 /* We need to take the unconfigure action for each parameter of this VNI
1967 * that is configured. Some optimization is possible, but not worth the
1968 * additional code for an operation that should be pretty rare.
1970 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1972 /* First, deal with the export side - RD and export RT changes. */
1973 if (is_rd_configured(vpn
))
1974 evpn_unconfigure_rd(bgp
, vpn
);
1975 if (is_export_rt_configured(vpn
))
1976 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1978 /* Next, deal with the import side. */
1979 if (is_import_rt_configured(vpn
))
1980 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1986 * Display import RT mapping to VRFs (vty handler)
1987 * bgp_evpn: evpn bgp instance
1989 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
1997 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
1998 (void (*)(struct hash_bucket
*,
1999 void *))show_vrf_import_rt_entry
,
2004 * Display import RT mapping to VNIs (vty handler)
2006 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2015 bgp
->import_rt_hash
,
2016 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2021 * Display EVPN routes for all VNIs - vty handler.
2023 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2024 struct in_addr vtep_ip
, json_object
*json
,
2028 struct vni_walk_ctx wctx
;
2030 num_vnis
= hashcount(bgp
->vnihash
);
2033 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2036 wctx
.vtep_ip
= vtep_ip
;
2038 wctx
.detail
= detail
;
2039 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2040 void *))show_vni_routes_hash
,
2045 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2047 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2048 vni_t vni
, struct in_addr orig_ip
,
2051 struct bgpevpn
*vpn
;
2052 struct prefix_evpn p
;
2053 struct bgp_node
*rn
;
2054 struct bgp_path_info
*pi
;
2055 uint32_t path_cnt
= 0;
2058 json_object
*json_paths
= NULL
;
2064 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2066 vty_out(vty
, "VNI not found\n");
2070 /* See if route exists. */
2071 build_evpn_type3_prefix(&p
, orig_ip
);
2072 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2073 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2075 vty_out(vty
, "%% Network not in table\n");
2080 json_paths
= json_object_new_array();
2082 /* Prefix and num paths displayed once per prefix. */
2083 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2085 /* Display each path for this prefix. */
2086 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2087 json_object
*json_path
= NULL
;
2090 json_path
= json_object_new_array();
2092 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2096 json_object_array_add(json_paths
, json_path
);
2103 json_object_object_add(json
, "paths", json_paths
);
2105 json_object_int_add(json
, "numPaths", path_cnt
);
2107 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2113 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2114 * By definition, only matching type-2 route will be displayed.
2116 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2117 vni_t vni
, struct ethaddr
*mac
,
2118 struct ipaddr
*ip
, json_object
*json
)
2120 struct bgpevpn
*vpn
;
2121 struct prefix_evpn p
;
2122 struct bgp_node
*rn
;
2123 struct bgp_path_info
*pi
;
2124 uint32_t path_cnt
= 0;
2127 json_object
*json_paths
= NULL
;
2133 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2136 vty_out(vty
, "VNI not found\n");
2140 /* See if route exists. Look for both non-sticky and sticky. */
2141 build_evpn_type2_prefix(&p
, mac
, ip
);
2142 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2143 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2145 vty_out(vty
, "%% Network not in table\n");
2150 json_paths
= json_object_new_array();
2152 /* Prefix and num paths displayed once per prefix. */
2153 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2155 /* Display each path for this prefix. */
2156 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2157 json_object
*json_path
= NULL
;
2160 json_path
= json_object_new_array();
2162 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2166 json_object_array_add(json_paths
, json_path
);
2173 json_object_object_add(json
, "paths", json_paths
);
2175 json_object_int_add(json
, "numPaths", path_cnt
);
2177 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2182 /* Disaplay EVPN routes for a ESI - VTY handler */
2183 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2184 esi_t
*esi
, json_object
*json
)
2186 struct evpnes
*es
= NULL
;
2189 es
= bgp_evpn_lookup_es(bgp
, esi
);
2192 vty_out(vty
, "ESI not found\n");
2196 show_esi_routes(bgp
, es
, vty
, json
);
2200 * Display EVPN routes for a VNI - vty handler.
2201 * If 'type' is non-zero, only routes matching that type are shown.
2202 * If the vtep_ip is non zero, only routes behind that vtep are shown
2204 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2205 int type
, struct in_addr vtep_ip
,
2208 struct bgpevpn
*vpn
;
2211 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2214 vty_out(vty
, "VNI not found\n");
2218 /* Walk this VNI's route table and display appropriate routes. */
2219 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2223 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2224 * IP (vty handler). By definition, only matching type-2 route will be
2227 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2228 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2229 struct ipaddr
*ip
, json_object
*json
)
2231 struct prefix_evpn p
;
2232 struct bgp_node
*rn
;
2233 struct bgp_path_info
*pi
;
2236 uint32_t path_cnt
= 0;
2237 json_object
*json_paths
= NULL
;
2238 char prefix_str
[BUFSIZ
];
2243 /* See if route exists. Look for both non-sticky and sticky. */
2244 build_evpn_type2_prefix(&p
, mac
, ip
);
2245 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2246 (struct prefix
*)&p
, prd
);
2247 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2249 vty_out(vty
, "%% Network not in table\n");
2253 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2254 sizeof(prefix_str
));
2256 /* Prefix and num paths displayed once per prefix. */
2257 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2260 json_paths
= json_object_new_array();
2262 /* Display each path for this prefix. */
2263 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2264 json_object
*json_path
= NULL
;
2267 json_path
= json_object_new_array();
2269 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2273 json_object_array_add(json_paths
, json_path
);
2278 if (json
&& path_cnt
) {
2280 json_object_object_add(json
, prefix_str
, json_paths
);
2281 json_object_int_add(json
, "numPaths", path_cnt
);
2283 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2289 * Display BGP EVPN routing table -- for specific RD (vty handler)
2290 * If 'type' is non-zero, only routes matching that type are shown.
2292 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2293 struct prefix_rd
*prd
, int type
,
2296 struct bgp_node
*rd_rn
;
2297 struct bgp_table
*table
;
2298 struct bgp_node
*rn
;
2299 struct bgp_path_info
*pi
;
2303 uint32_t prefix_cnt
, path_cnt
;
2304 char rd_str
[RD_ADDRSTRLEN
];
2305 json_object
*json_rd
= NULL
;
2306 int add_rd_to_json
= 0;
2310 prefix_cnt
= path_cnt
= 0;
2312 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2314 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2318 table
= bgp_node_get_bgp_table_info(rd_rn
);
2323 json_rd
= json_object_new_object();
2324 json_object_string_add(json_rd
, "rd", rd_str
);
2327 /* Display all prefixes with this RD. */
2328 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2329 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2330 json_object
*json_prefix
= NULL
;
2331 json_object
*json_paths
= NULL
;
2332 char prefix_str
[BUFSIZ
];
2333 int add_prefix_to_json
= 0;
2335 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2336 sizeof(prefix_str
));
2338 if (type
&& evp
->prefix
.route_type
!= type
)
2342 json_prefix
= json_object_new_object();
2344 pi
= bgp_node_get_bgp_path_info(rn
);
2346 /* RD header and legend - once overall. */
2347 if (rd_header
&& !json
) {
2349 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2351 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2353 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2357 /* Prefix and num paths displayed once per prefix. */
2358 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2365 json_paths
= json_object_new_array();
2367 /* Display each path for this prefix. */
2368 for (; pi
; pi
= pi
->next
) {
2369 json_object
*json_path
= NULL
;
2372 json_path
= json_object_new_array();
2374 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2378 json_object_array_add(json_paths
, json_path
);
2381 add_prefix_to_json
= 1;
2385 if (json
&& add_prefix_to_json
) {
2386 json_object_object_add(json_prefix
, "paths",
2388 json_object_object_add(json_rd
, prefix_str
,
2393 if (json
&& add_rd_to_json
)
2394 json_object_object_add(json
, rd_str
, json_rd
);
2397 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2398 json_object_int_add(json
, "numPaths", path_cnt
);
2400 if (prefix_cnt
== 0)
2401 vty_out(vty
, "No prefixes exist with this RD%s\n",
2402 type
? " (of requested type)" : "");
2405 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2406 prefix_cnt
, path_cnt
,
2407 type
? " (of requested type)" : "");
2412 * Display BGP EVPN routing table - all routes (vty handler).
2413 * If 'type' is non-zero, only routes matching that type are shown.
2415 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2416 json_object
*json
, int detail
)
2418 struct bgp_node
*rd_rn
;
2419 struct bgp_table
*table
;
2420 struct bgp_node
*rn
;
2421 struct bgp_path_info
*pi
;
2422 int header
= detail
? 0 : 1;
2426 uint32_t prefix_cnt
, path_cnt
;
2430 prefix_cnt
= path_cnt
= 0;
2432 /* EVPN routing table is a 2-level table with the first level being
2435 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2436 rd_rn
= bgp_route_next(rd_rn
)) {
2437 char rd_str
[RD_ADDRSTRLEN
];
2438 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2439 int add_rd_to_json
= 0;
2442 table
= bgp_node_get_bgp_table_info(rd_rn
);
2446 tbl_ver
= table
->version
;
2447 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2451 json_rd
= json_object_new_object();
2452 json_object_string_add(json_rd
, "rd", rd_str
);
2457 /* Display all prefixes for an RD */
2458 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2459 json_object
*json_prefix
=
2460 NULL
; /* contains prefix under a RD */
2461 json_object
*json_paths
=
2462 NULL
; /* array of paths under a prefix*/
2463 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2464 char prefix_str
[BUFSIZ
];
2465 int add_prefix_to_json
= 0;
2467 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2468 prefix_str
, sizeof(prefix_str
));
2470 if (type
&& evp
->prefix
.route_type
!= type
)
2473 pi
= bgp_node_get_bgp_path_info(rn
);
2475 /* Overall header/legend displayed once. */
2477 bgp_evpn_show_route_header(vty
, bgp
,
2483 /* RD header - per RD. */
2485 bgp_evpn_show_route_rd_header(
2494 json_prefix
= json_object_new_object();
2495 json_paths
= json_object_new_array();
2496 json_object_string_add(json_prefix
, "prefix",
2498 json_object_int_add(json_prefix
, "prefixLen",
2502 /* Prefix and num paths displayed once per prefix. */
2504 route_vty_out_detail_header(
2506 (struct prefix_rd
*)&rd_rn
->p
,
2507 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2509 /* For EVPN, the prefix is displayed for each path (to
2511 * with code that already exists).
2513 for (; pi
; pi
= pi
->next
) {
2514 json_object
*json_path
= NULL
;
2516 add_prefix_to_json
= 1;
2520 json_path
= json_object_new_array();
2523 route_vty_out_detail(
2524 vty
, bgp
, &rn
->p
, pi
, AFI_L2VPN
,
2525 SAFI_EVPN
, json_path
);
2527 route_vty_out(vty
, &rn
->p
, pi
, 0,
2528 SAFI_EVPN
, json_path
);
2531 json_object_array_add(json_paths
,
2535 if (json
&& add_prefix_to_json
) {
2536 json_object_object_add(json_prefix
, "paths",
2538 json_object_object_add(json_rd
, prefix_str
,
2543 if (json
&& add_rd_to_json
)
2544 json_object_object_add(json
, rd_str
, json_rd
);
2548 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2549 json_object_int_add(json
, "numPaths", path_cnt
);
2551 if (prefix_cnt
== 0) {
2552 vty_out(vty
, "No EVPN prefixes %sexist\n",
2553 type
? "(of requested type) " : "");
2555 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2556 prefix_cnt
, path_cnt
,
2557 type
? " (of requested type)" : "");
2562 /* Display specific ES */
2563 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2566 struct evpnes
*es
= NULL
;
2568 es
= bgp_evpn_lookup_es(bgp
, esi
);
2570 display_es(vty
, es
, json
);
2573 vty_out(vty
, "{}\n");
2575 vty_out(vty
, "ESI not found\n");
2581 /* Display all ESs */
2582 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2588 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2589 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2594 hash_iterate(bgp
->esihash
,
2595 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2600 * Display specified VNI (vty handler)
2602 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2606 struct bgpevpn
*vpn
;
2608 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2611 display_vni(vty
, vpn
, json
);
2613 struct bgp
*bgp_temp
;
2614 struct listnode
*node
= NULL
;
2616 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2617 if (bgp_temp
->l3vni
== vni
) {
2619 display_l3vni(vty
, bgp_temp
, json
);
2626 vty_out(vty
, "{}\n");
2628 vty_out(vty
, "VNI not found\n");
2635 * Display a VNI (upon user query).
2637 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2641 struct bgp
*bgp_temp
= NULL
;
2642 struct listnode
*node
;
2646 vty_out(vty
, "Flags: * - Kernel\n");
2647 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2648 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2651 /* print all L2 VNIS */
2654 hash_iterate(bgp
->vnihash
,
2655 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2658 /* print all L3 VNIs */
2659 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2660 show_l3vni_entry(vty
, bgp_temp
, json
);
2664 * evpn - enable advertisement of svi MAC-IP
2666 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2670 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2672 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2675 bgp
->evpn_info
->advertise_svi_macip
= set
;
2676 bgp_zebra_advertise_svi_macip(bgp
,
2677 bgp
->evpn_info
->advertise_svi_macip
, 0);
2679 if (set
&& vpn
->advertise_svi_macip
)
2681 else if (!set
&& !vpn
->advertise_svi_macip
)
2684 vpn
->advertise_svi_macip
= set
;
2685 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2691 * evpn - enable advertisement of default g/w
2693 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2696 if (bgp
->advertise_gw_macip
)
2699 bgp
->advertise_gw_macip
= 1;
2700 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2702 if (vpn
->advertise_gw_macip
)
2705 vpn
->advertise_gw_macip
= 1;
2706 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2713 * evpn - disable advertisement of default g/w
2715 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2716 struct bgpevpn
*vpn
)
2719 if (!bgp
->advertise_gw_macip
)
2722 bgp
->advertise_gw_macip
= 0;
2723 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2725 if (!vpn
->advertise_gw_macip
)
2728 vpn
->advertise_gw_macip
= 0;
2729 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2736 * evpn - enable advertisement of default g/w
2738 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2739 afi_t afi
, bool add
)
2741 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2744 /* bail if we are already advertising default route */
2745 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2749 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2750 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2751 else if (afi
== AFI_IP6
)
2752 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2753 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2755 /* bail out if we havent advertised the default route */
2756 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2759 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2760 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2761 else if (afi
== AFI_IP6
)
2762 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2763 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2766 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2770 * evpn - enable advertisement of default g/w
2772 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2773 struct bgpevpn
*vpn
)
2775 if (vpn
->advertise_subnet
)
2778 vpn
->advertise_subnet
= 1;
2779 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2783 * evpn - disable advertisement of default g/w
2785 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2787 if (!vpn
->advertise_subnet
)
2790 vpn
->advertise_subnet
= 0;
2791 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2795 * EVPN (VNI advertisement) enabled. Register with zebra.
2797 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2799 bgp
->advertise_all_vni
= 1;
2801 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2805 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2806 * cache, EVPN routes (delete and withdraw from peers).
2808 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2810 bgp
->advertise_all_vni
= 0;
2811 bgp_set_evpn(bgp_get_default());
2812 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2813 bgp_evpn_cleanup_on_disable(bgp
);
2817 * EVPN - use RFC8365 to auto-derive RT
2819 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2821 bgp
->advertise_autort_rfc8365
= 1;
2822 bgp_evpn_handle_autort_change(bgp
);
2826 * EVPN - don't use RFC8365 to auto-derive RT
2828 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2830 bgp
->advertise_autort_rfc8365
= 0;
2831 bgp_evpn_handle_autort_change(bgp
);
2834 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2836 char buf1
[RD_ADDRSTRLEN
];
2838 struct listnode
*node
, *nnode
;
2839 struct ecommunity
*ecom
;
2841 if (is_vni_configured(vpn
)) {
2842 vty_out(vty
, " vni %d\n", vpn
->vni
);
2843 if (is_rd_configured(vpn
))
2844 vty_out(vty
, " rd %s\n",
2845 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2847 if (is_import_rt_configured(vpn
)) {
2848 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2850 ecom_str
= ecommunity_ecom2str(
2851 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2852 vty_out(vty
, " route-target import %s\n",
2854 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2858 if (is_export_rt_configured(vpn
)) {
2859 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2861 ecom_str
= ecommunity_ecom2str(
2862 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2863 vty_out(vty
, " route-target export %s\n",
2865 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2869 if (vpn
->advertise_gw_macip
)
2870 vty_out(vty
, " advertise-default-gw\n");
2872 if (vpn
->advertise_svi_macip
)
2873 vty_out(vty
, " advertise-svi-ip\n");
2875 if (vpn
->advertise_subnet
)
2876 vty_out(vty
, " advertise-subnet\n");
2878 vty_out(vty
, " exit-vni\n");
2882 #ifndef VTYSH_EXTRACT_PL
2883 #include "bgpd/bgp_evpn_vty_clippy.c"
2886 DEFPY(bgp_evpn_flood_control
,
2887 bgp_evpn_flood_control_cmd
,
2888 "[no$no] flooding <disable$disable|head-end-replication$her>",
2890 "Specify handling for BUM packets\n"
2891 "Do not flood any BUM packets\n"
2892 "Flood BUM packets using head-end replication\n")
2894 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2895 enum vxlan_flood_control flood_ctrl
;
2901 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
2903 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
2907 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
2910 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
2911 bgp_evpn_flood_control_change(bgp
);
2916 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2917 bgp_evpn_advertise_default_gw_vni_cmd
,
2918 "advertise-default-gw",
2919 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2921 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2922 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2927 evpn_set_advertise_default_gw(bgp
, vpn
);
2932 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2933 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2934 "no advertise-default-gw",
2936 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2938 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2939 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2944 evpn_unset_advertise_default_gw(bgp
, vpn
);
2950 DEFUN (bgp_evpn_advertise_default_gw
,
2951 bgp_evpn_advertise_default_gw_cmd
,
2952 "advertise-default-gw",
2953 "Advertise All default g/w mac-ip routes in EVPN\n")
2955 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2960 if (!EVPN_ENABLED(bgp
)) {
2962 "This command is only supported under the EVPN VRF\n");
2966 evpn_set_advertise_default_gw(bgp
, NULL
);
2971 DEFUN (no_bgp_evpn_advertise_default_gw
,
2972 no_bgp_evpn_advertise_default_gw_cmd
,
2973 "no advertise-default-gw",
2975 "Withdraw All default g/w mac-ip routes from EVPN\n")
2977 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2982 if (!EVPN_ENABLED(bgp
)) {
2984 "This command is only supported under the EVPN VRF\n");
2988 evpn_unset_advertise_default_gw(bgp
, NULL
);
2993 DEFUN (bgp_evpn_advertise_all_vni
,
2994 bgp_evpn_advertise_all_vni_cmd
,
2995 "advertise-all-vni",
2996 "Advertise All local VNIs\n")
2998 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2999 struct bgp
*bgp_evpn
= NULL
;
3004 bgp_evpn
= bgp_get_evpn();
3005 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3006 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3008 return CMD_WARNING_CONFIG_FAILED
;
3011 evpn_set_advertise_all_vni(bgp
);
3015 DEFUN (no_bgp_evpn_advertise_all_vni
,
3016 no_bgp_evpn_advertise_all_vni_cmd
,
3017 "no advertise-all-vni",
3019 "Advertise All local VNIs\n")
3021 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3025 evpn_unset_advertise_all_vni(bgp
);
3029 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3030 bgp_evpn_advertise_autort_rfc8365_cmd
,
3031 "autort rfc8365-compatible",
3032 "Auto-derivation of RT\n"
3033 "Auto-derivation of RT using RFC8365\n")
3035 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3039 evpn_set_advertise_autort_rfc8365(bgp
);
3043 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3044 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3045 "no autort rfc8365-compatible",
3047 "Auto-derivation of RT\n"
3048 "Auto-derivation of RT using RFC8365\n")
3050 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3054 evpn_unset_advertise_autort_rfc8365(bgp
);
3058 DEFUN (bgp_evpn_default_originate
,
3059 bgp_evpn_default_originate_cmd
,
3060 "default-originate <ipv4 | ipv6>",
3061 "originate a default route\n"
3062 "ipv4 address family\n"
3063 "ipv6 address family\n")
3067 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3071 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3072 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3076 DEFUN (no_bgp_evpn_default_originate
,
3077 no_bgp_evpn_default_originate_cmd
,
3078 "no default-originate <ipv4 | ipv6>",
3080 "withdraw a default route\n"
3081 "ipv4 address family\n"
3082 "ipv6 address family\n")
3086 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3090 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3091 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3095 DEFPY (dup_addr_detection
,
3096 dup_addr_detection_cmd
,
3097 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3098 "Duplicate address detection\n"
3099 "Max allowed moves before address detected as duplicate\n"
3100 "Num of max allowed moves (2-1000) default 5\n"
3101 "Duplicate address detection time\n"
3102 "Time in seconds (2-1800) default 180\n")
3104 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3109 if (!EVPN_ENABLED(bgp_vrf
)) {
3111 "This command is only supported under the EVPN VRF\n");
3115 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3118 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3120 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3122 bgp_zebra_dup_addr_detection(bgp_vrf
);
3127 DEFPY (dup_addr_detection_auto_recovery
,
3128 dup_addr_detection_auto_recovery_cmd
,
3129 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3130 "Duplicate address detection\n"
3131 "Duplicate address detection freeze\n"
3132 "Duplicate address detection permanent freeze\n"
3133 "Duplicate address detection freeze time (30-3600)\n")
3135 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3136 uint32_t freeze_time
= freeze_time_val
;
3141 if (!EVPN_ENABLED(bgp_vrf
)) {
3143 "This command is only supported under the EVPN VRF\n");
3147 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3148 bgp_vrf
->evpn_info
->dad_freeze
= true;
3149 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3151 bgp_zebra_dup_addr_detection(bgp_vrf
);
3156 DEFPY (no_dup_addr_detection
,
3157 no_dup_addr_detection_cmd
,
3158 "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>]",
3160 "Duplicate address detection\n"
3161 "Max allowed moves before address detected as duplicate\n"
3162 "Num of max allowed moves (2-1000) default 5\n"
3163 "Duplicate address detection time\n"
3164 "Time in seconds (2-1800) default 180\n"
3165 "Duplicate address detection freeze\n"
3166 "Duplicate address detection permanent freeze\n"
3167 "Duplicate address detection freeze time (30-3600)\n")
3169 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3170 uint32_t max_moves
= (uint32_t)max_moves_val
;
3171 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3176 if (!EVPN_ENABLED(bgp_vrf
)) {
3178 "This command is only supported under the EVPN VRF\n");
3183 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3185 /* Reset all parameters to default. */
3186 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3187 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3188 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3189 bgp_vrf
->evpn_info
->dad_freeze
= false;
3190 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3193 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3195 "%% Value does not match with config\n");
3198 bgp_vrf
->evpn_info
->dad_max_moves
=
3199 EVPN_DAD_DEFAULT_MAX_MOVES
;
3203 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3205 "%% Value does not match with config\n");
3208 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3212 if (bgp_vrf
->evpn_info
->dad_freeze_time
3215 "%% Value does not match with config\n");
3218 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3219 bgp_vrf
->evpn_info
->dad_freeze
= false;
3222 if (permanent_val
) {
3223 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3225 "%% Value does not match with config\n");
3228 bgp_vrf
->evpn_info
->dad_freeze
= false;
3232 bgp_zebra_dup_addr_detection(bgp_vrf
);
3237 DEFPY(bgp_evpn_advertise_svi_ip
,
3238 bgp_evpn_advertise_svi_ip_cmd
,
3239 "[no$no] advertise-svi-ip",
3241 "Advertise svi mac-ip routes in EVPN\n")
3243 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3248 if (!EVPN_ENABLED(bgp
)) {
3250 "This command is only supported under EVPN VRF\n");
3255 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3257 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3262 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3263 bgp_evpn_advertise_svi_ip_vni_cmd
,
3264 "[no$no] advertise-svi-ip",
3266 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3268 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3269 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3275 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3277 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3282 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3283 bgp_evpn_advertise_vni_subnet_cmd
,
3285 "Advertise the subnet corresponding to VNI\n")
3287 struct bgp
*bgp_vrf
= NULL
;
3288 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3289 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3294 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3298 evpn_set_advertise_subnet(bgp
, vpn
);
3302 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3303 no_bgp_evpn_advertise_vni_subnet_cmd
,
3304 "no advertise-subnet",
3306 "Advertise All local VNIs\n")
3308 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3309 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3314 evpn_unset_advertise_subnet(bgp
, vpn
);
3318 DEFUN (bgp_evpn_advertise_type5
,
3319 bgp_evpn_advertise_type5_cmd
,
3320 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3321 "Advertise prefix routes\n"
3324 "route-map for filtering specific routes\n"
3325 "Name of the route map\n")
3327 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3334 int rmap_changed
= 0;
3336 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3337 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3338 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3340 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3342 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3343 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3346 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3350 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3352 "%%only ipv4 or ipv6 address families are supported");
3356 if (safi
!= SAFI_UNICAST
) {
3358 "%%only ipv4 unicast or ipv6 unicast are supported");
3362 if (afi
== AFI_IP
) {
3364 /* if we are already advertising ipv4 prefix as type-5
3367 if (!rmap_changed
&&
3368 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3369 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3371 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3372 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3375 /* if we are already advertising ipv6 prefix as type-5
3378 if (!rmap_changed
&&
3379 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3380 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3382 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3383 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3387 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3388 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3389 XFREE(MTYPE_ROUTE_MAP_NAME
,
3390 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3391 route_map_counter_decrement(
3392 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3393 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3394 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3398 /* set the route-map for advertise command */
3399 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3400 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3401 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3402 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3403 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3404 route_map_counter_increment(
3405 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3408 /* advertise type-5 routes */
3409 if (advertise_type5_routes(bgp_vrf
, afi
))
3410 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3414 DEFUN (no_bgp_evpn_advertise_type5
,
3415 no_bgp_evpn_advertise_type5_cmd
,
3416 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3418 "Advertise prefix routes\n"
3422 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3428 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3429 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3431 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3433 "%%only ipv4 or ipv6 address families are supported");
3437 if (safi
!= SAFI_UNICAST
) {
3439 "%%only ipv4 unicast or ipv6 unicast are supported");
3443 if (afi
== AFI_IP
) {
3445 /* if we are not advertising ipv4 prefix as type-5
3448 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3449 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3450 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3451 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3452 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3456 /* if we are not advertising ipv6 prefix as type-5
3459 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3460 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3461 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3462 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3463 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3467 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3468 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3469 XFREE(MTYPE_ROUTE_MAP_NAME
,
3470 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3471 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3472 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3479 * Display VNI information - for all or a specific VNI
3481 DEFUN(show_bgp_l2vpn_evpn_vni
,
3482 show_bgp_l2vpn_evpn_vni_cmd
,
3483 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3492 struct bgp
*bgp_evpn
;
3496 json_object
*json
= NULL
;
3497 uint32_t num_l2vnis
= 0;
3498 uint32_t num_l3vnis
= 0;
3499 uint32_t num_vnis
= 0;
3500 struct listnode
*node
= NULL
;
3501 struct bgp
*bgp_temp
= NULL
;
3503 uj
= use_json(argc
, argv
);
3505 bgp_evpn
= bgp_get_evpn();
3509 if (!argv_find(argv
, argc
, "evpn", &idx
))
3513 json
= json_object_new_object();
3515 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3517 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3519 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3520 if (bgp_temp
->l3vni
)
3523 num_vnis
= num_l2vnis
+ num_l3vnis
;
3525 json_object_string_add(json
, "advertiseGatewayMacip",
3526 bgp_evpn
->advertise_gw_macip
3529 json_object_string_add(json
, "advertiseAllVnis",
3530 is_evpn_enabled() ? "Enabled"
3532 json_object_string_add(
3534 bgp_evpn
->vxlan_flood_ctrl
3535 == VXLAN_FLOOD_HEAD_END_REPL
3536 ? "Head-end replication"
3538 json_object_int_add(json
, "numVnis", num_vnis
);
3539 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3540 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3542 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3543 bgp_evpn
->advertise_gw_macip
? "Enabled"
3545 vty_out(vty
, "Advertise SVI Macip: %s\n",
3546 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3548 vty_out(vty
, "Advertise All VNI flag: %s\n",
3549 is_evpn_enabled() ? "Enabled" : "Disabled");
3550 vty_out(vty
, "BUM flooding: %s\n",
3551 bgp_evpn
->vxlan_flood_ctrl
3552 == VXLAN_FLOOD_HEAD_END_REPL
3553 ? "Head-end replication"
3555 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3556 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3558 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3562 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3565 /* Display specific VNI */
3566 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3567 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3571 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3572 json
, JSON_C_TO_STRING_PRETTY
));
3573 json_object_free(json
);
3580 DEFUN(show_bgp_l2vpn_evpn_es
,
3581 show_bgp_l2vpn_evpn_es_cmd
,
3582 "show bgp l2vpn evpn es [ESI] [json]",
3587 "ethernet-Segment\n"
3588 "Ethernet-Segment Identifier\n"
3594 json_object
*json
= NULL
;
3595 struct bgp
*bgp
= NULL
;
3597 memset(&esi
, 0, sizeof(esi
));
3598 uj
= use_json(argc
, argv
);
3600 bgp
= bgp_get_evpn();
3604 if (!argv_find(argv
, argc
, "evpn", &idx
))
3607 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3608 (!uj
&& argc
== (idx
+ 1) + 1)) {
3611 evpn_show_all_es(vty
, bgp
, json
);
3614 /* show a specific ES */
3616 /* get the ESI - ESI-ID is at argv[5] */
3617 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3618 vty_out(vty
, "%% Malformed ESI\n");
3621 evpn_show_es(vty
, bgp
, &esi
, json
);
3625 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3626 json
, JSON_C_TO_STRING_PRETTY
));
3627 json_object_free(json
);
3634 * Display EVPN neighbor summary.
3636 DEFUN(show_bgp_l2vpn_evpn_summary
,
3637 show_bgp_l2vpn_evpn_summary_cmd
,
3638 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3645 "Summary of BGP neighbor status\n"
3649 bool uj
= use_json(argc
, argv
);
3652 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3653 vrf
= argv
[++idx_vrf
]->arg
;
3654 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3658 * Display global EVPN routing table.
3660 DEFUN(show_bgp_l2vpn_evpn_route
,
3661 show_bgp_l2vpn_evpn_route_cmd
,
3662 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3667 "EVPN route information\n"
3668 "Display Detailed Information\n"
3669 "Specify Route type\n"
3670 "MAC-IP (Type-2) route\n"
3671 "Multicast (Type-3) route\n"
3672 "Ethernet Segment (type-4) route \n"
3673 "Prefix (type-5 )route\n"
3681 json_object
*json
= NULL
;
3683 uj
= use_json(argc
, argv
);
3685 bgp
= bgp_get_evpn();
3690 json
= json_object_new_object();
3693 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3694 /* Specific type is requested */
3695 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3696 type
= BGP_EVPN_MAC_IP_ROUTE
;
3697 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3698 type
= BGP_EVPN_IMET_ROUTE
;
3699 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3700 type
= BGP_EVPN_ES_ROUTE
;
3701 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3702 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3707 if (argv_find(argv
, argc
, "detail", &detail
))
3710 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3713 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3714 json
, JSON_C_TO_STRING_PRETTY
));
3715 json_object_free(json
);
3721 * Display global EVPN routing table for specific RD.
3723 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3724 show_bgp_l2vpn_evpn_route_rd_cmd
,
3725 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3730 "EVPN route information\n"
3731 "Route Distinguisher\n"
3732 "ASN:XX or A.B.C.D:XX\n"
3733 "Specify Route type\n"
3734 "MAC-IP (Type-2) route\n"
3735 "Multicast (Type-3) route\n"
3736 "Ethernet Segment route\n"
3742 struct prefix_rd prd
;
3747 json_object
*json
= NULL
;
3749 bgp
= bgp_get_evpn();
3753 /* check if we need json output */
3754 uj
= use_json(argc
, argv
);
3756 json
= json_object_new_object();
3759 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3760 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3763 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3769 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3770 /* Specific type is requested */
3771 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3772 type
= BGP_EVPN_MAC_IP_ROUTE
;
3773 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3774 type
= BGP_EVPN_IMET_ROUTE
;
3775 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3776 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3781 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3784 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3785 json
, JSON_C_TO_STRING_PRETTY
));
3786 json_object_free(json
);
3793 * Display global EVPN routing table for specific RD and MACIP.
3795 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3796 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3797 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3802 "EVPN route information\n"
3803 "Route Distinguisher\n"
3804 "ASN:XX or A.B.C.D:XX\n"
3806 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3808 "IP address (IPv4 or IPv6)\n"
3813 struct prefix_rd prd
;
3820 json_object
*json
= NULL
;
3822 memset(&mac
, 0, sizeof(struct ethaddr
));
3823 memset(&ip
, 0, sizeof(struct ipaddr
));
3825 bgp
= bgp_get_evpn();
3829 /* check if we need json output */
3830 uj
= use_json(argc
, argv
);
3832 json
= json_object_new_object();
3835 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3836 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3838 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3844 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3845 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3846 vty_out(vty
, "%% Malformed MAC address\n");
3851 /* get the ip if specified */
3852 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3853 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3854 vty_out(vty
, "%% Malformed IP address\n");
3859 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3862 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3863 json
, JSON_C_TO_STRING_PRETTY
));
3864 json_object_free(json
);
3870 /* Display per ESI routing table */
3871 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3872 show_bgp_l2vpn_evpn_route_esi_cmd
,
3873 "show bgp l2vpn evpn route esi ESI [json]",
3878 "EVPN route information\n"
3879 "Ethernet Segment Identifier\n"
3885 struct bgp
*bgp
= NULL
;
3886 json_object
*json
= NULL
;
3888 memset(&esi
, 0, sizeof(esi
));
3889 bgp
= bgp_get_evpn();
3893 uj
= use_json(argc
, argv
);
3895 json
= json_object_new_object();
3897 /* get the ESI - ESI-ID is at argv[6] */
3898 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3899 vty_out(vty
, "%% Malformed ESI\n");
3903 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3906 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3907 json
, JSON_C_TO_STRING_PRETTY
));
3908 json_object_free(json
);
3916 * Display per-VNI EVPN routing table.
3918 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3919 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3924 "EVPN route information\n"
3925 "VXLAN Network Identifier\n"
3927 "Specify Route type\n"
3928 "MAC-IP (Type-2) route\n"
3929 "Multicast (Type-3) route\n"
3931 "Remote VTEP IP address\n"
3936 struct in_addr vtep_ip
;
3940 json_object
*json
= NULL
;
3942 bgp
= bgp_get_evpn();
3946 /* check if we need json output */
3947 uj
= use_json(argc
, argv
);
3949 json
= json_object_new_object();
3951 if (!argv_find(argv
, argc
, "evpn", &idx
))
3956 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3958 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3959 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3960 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3961 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3962 type
= BGP_EVPN_MAC_IP_ROUTE
;
3963 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3964 type
= BGP_EVPN_IMET_ROUTE
;
3967 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3968 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3969 vty_out(vty
, "%% Malformed VTEP IP address\n");
3976 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3979 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3980 json
, JSON_C_TO_STRING_PRETTY
));
3981 json_object_free(json
);
3988 * Display per-VNI EVPN routing table for specific MACIP.
3990 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3991 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3992 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
3997 "EVPN route information\n"
3998 "VXLAN Network Identifier\n"
4001 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4003 "IP address (IPv4 or IPv6)\n"
4012 json_object
*json
= NULL
;
4014 bgp
= bgp_get_evpn();
4018 /* check if we need json output */
4019 uj
= use_json(argc
, argv
);
4021 json
= json_object_new_object();
4023 if (!argv_find(argv
, argc
, "evpn", &idx
))
4027 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4030 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4031 vty_out(vty
, "%% Malformed MAC address\n");
4036 memset(&ip
, 0, sizeof(ip
));
4037 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4039 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4040 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4041 vty_out(vty
, "%% Malformed IP address\n");
4046 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4049 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4050 json
, JSON_C_TO_STRING_PRETTY
));
4051 json_object_free(json
);
4058 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4060 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4061 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4062 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4067 "EVPN route information\n"
4068 "VXLAN Network Identifier\n"
4070 "Multicast (Type-3) route\n"
4071 "Originating Router IP address\n"
4077 struct in_addr orig_ip
;
4080 json_object
*json
= NULL
;
4082 bgp
= bgp_get_evpn();
4086 /* check if we need json output */
4087 uj
= use_json(argc
, argv
);
4089 json
= json_object_new_object();
4091 if (!argv_find(argv
, argc
, "evpn", &idx
))
4095 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4098 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4100 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4104 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4107 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4108 json
, JSON_C_TO_STRING_PRETTY
));
4109 json_object_free(json
);
4116 * Display per-VNI EVPN routing table - for all VNIs.
4118 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4119 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4120 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4125 "EVPN route information\n"
4126 "VXLAN Network Identifier\n"
4128 "Print Detailed Output\n"
4130 "Remote VTEP IP address\n"
4134 struct in_addr vtep_ip
;
4137 json_object
*json
= NULL
;
4138 /* Detail Adjust. Adjust indexes according to detail option */
4141 bgp
= bgp_get_evpn();
4145 /* check if we need json output */
4146 uj
= use_json(argc
, argv
);
4148 json
= json_object_new_object();
4150 if (!argv_find(argv
, argc
, "evpn", &idx
))
4153 if (argv_find(argv
, argc
, "detail", &da
))
4156 /* vtep-ip position depends on detail option */
4158 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4160 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4161 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4162 vty_out(vty
, "%% Malformed VTEP IP address\n");
4167 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4170 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4171 json
, JSON_C_TO_STRING_PRETTY
));
4172 json_object_free(json
);
4179 * Display EVPN import route-target hash table
4181 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4182 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4183 "show bgp l2vpn evpn vrf-import-rt [json]",
4188 "Show vrf import route target\n"
4192 struct bgp
*bgp_evpn
= NULL
;
4193 json_object
*json
= NULL
;
4195 bgp_evpn
= bgp_get_evpn();
4199 uj
= use_json(argc
, argv
);
4201 json
= json_object_new_object();
4203 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4206 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4207 json
, JSON_C_TO_STRING_PRETTY
));
4208 json_object_free(json
);
4215 * Display EVPN import route-target hash table
4217 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4218 show_bgp_l2vpn_evpn_import_rt_cmd
,
4219 "show bgp l2vpn evpn import-rt [json]",
4224 "Show import route target\n"
4229 json_object
*json
= NULL
;
4231 bgp
= bgp_get_evpn();
4235 uj
= use_json(argc
, argv
);
4237 json
= json_object_new_object();
4239 evpn_show_import_rts(vty
, bgp
, json
);
4242 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4243 json
, JSON_C_TO_STRING_PRETTY
));
4244 json_object_free(json
);
4250 DEFUN(test_adv_evpn_type4_route
,
4251 test_adv_evpn_type4_route_cmd
,
4253 "Advertise EVPN ES route\n"
4254 "Ethernet-segment\n"
4255 "Ethernet-Segment Identifier\n")
4260 struct ipaddr vtep_ip
;
4262 bgp
= bgp_get_evpn();
4264 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4268 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4269 vty_out(vty
, "%%Malformed ESI\n");
4273 vtep_ip
.ipa_type
= IPADDR_V4
;
4274 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4276 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4278 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4284 DEFUN(test_withdraw_evpn_type4_route
,
4285 test_withdraw_evpn_type4_route_cmd
,
4287 "Advertise EVPN ES route\n"
4288 "Ethernet-segment\n"
4289 "Ethernet-Segment Identifier\n")
4294 struct ipaddr vtep_ip
;
4296 bgp
= bgp_get_evpn();
4298 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4302 if (!bgp
->peer_self
) {
4303 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4307 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4308 vty_out(vty
, "%%Malformed ESI\n");
4312 vtep_ip
.ipa_type
= IPADDR_V4
;
4313 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4314 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4316 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4322 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4323 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4327 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4328 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4329 "Summary of BGP neighbor status\n" JSON_STR
)
4331 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4332 "show bgp evpn route [detail] [type <macip|multicast>]",
4333 SHOW_STR BGP_STR EVPN_HELP_STR
4334 "EVPN route information\n"
4335 "Display Detailed Information\n"
4336 "Specify Route type\n"
4337 "MAC-IP (Type-2) route\n"
4338 "Multicast (Type-3) route\n")
4341 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4342 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4343 SHOW_STR BGP_STR EVPN_HELP_STR
4344 "EVPN route information\n"
4345 "Route Distinguisher\n"
4346 "ASN:XX or A.B.C.D:XX\n"
4347 "Specify Route type\n"
4348 "MAC-IP (Type-2) route\n"
4349 "Multicast (Type-3) route\n")
4352 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4353 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4354 SHOW_STR BGP_STR EVPN_HELP_STR
4355 "EVPN route information\n"
4356 "Route Distinguisher\n"
4357 "ASN:XX or A.B.C.D:XX\n"
4359 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4361 "IP address (IPv4 or IPv6)\n")
4364 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4365 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4366 SHOW_STR BGP_STR EVPN_HELP_STR
4367 "EVPN route information\n"
4368 "VXLAN Network Identifier\n"
4370 "Specify Route type\n"
4371 "MAC-IP (Type-2) route\n"
4372 "Multicast (Type-3) route\n"
4374 "Remote VTEP IP address\n")
4376 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4377 show_bgp_evpn_route_vni_macip_cmd
,
4378 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4379 SHOW_STR BGP_STR EVPN_HELP_STR
4380 "EVPN route information\n"
4381 "VXLAN Network Identifier\n"
4384 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4386 "IP address (IPv4 or IPv6)\n")
4388 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4389 show_bgp_evpn_route_vni_multicast_cmd
,
4390 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4391 SHOW_STR BGP_STR EVPN_HELP_STR
4392 "EVPN route information\n"
4393 "VXLAN Network Identifier\n"
4395 "Multicast (Type-3) route\n"
4396 "Originating Router IP address\n")
4398 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4399 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4400 SHOW_STR BGP_STR EVPN_HELP_STR
4401 "EVPN route information\n"
4402 "VXLAN Network Identifier\n"
4404 "Print Detailed Output\n"
4406 "Remote VTEP IP address\n")
4408 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4409 "show bgp evpn import-rt",
4410 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4412 DEFUN_NOSH (bgp_evpn_vni
,
4414 "vni " CMD_VNI_RANGE
,
4415 "VXLAN Network Identifier\n"
4419 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4420 struct bgpevpn
*vpn
;
4425 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4427 /* Create VNI, or mark as configured. */
4428 vpn
= evpn_create_update_vni(bgp
, vni
);
4430 vty_out(vty
, "%% Failed to create VNI \n");
4434 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4438 DEFUN (no_bgp_evpn_vni
,
4439 no_bgp_evpn_vni_cmd
,
4440 "no vni " CMD_VNI_RANGE
,
4442 "VXLAN Network Identifier\n"
4446 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4447 struct bgpevpn
*vpn
;
4452 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4454 /* Check if we should disallow. */
4455 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4457 vty_out(vty
, "%% Specified VNI does not exist\n");
4460 if (!is_vni_configured(vpn
)) {
4461 vty_out(vty
, "%% Specified VNI is not configured\n");
4465 evpn_delete_vni(bgp
, vpn
);
4469 DEFUN_NOSH (exit_vni
,
4472 "Exit from VNI mode\n")
4474 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4475 vty
->node
= BGP_EVPN_NODE
;
4479 DEFUN (bgp_evpn_vrf_rd
,
4480 bgp_evpn_vrf_rd_cmd
,
4481 "rd ASN:NN_OR_IP-ADDRESS:NN",
4482 "Route Distinguisher\n"
4483 "ASN:XX or A.B.C.D:XX\n")
4486 struct prefix_rd prd
;
4487 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4492 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4494 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4498 /* If same as existing value, there is nothing more to do. */
4499 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4502 /* Configure or update the RD. */
4503 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4507 DEFUN (no_bgp_evpn_vrf_rd
,
4508 no_bgp_evpn_vrf_rd_cmd
,
4509 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4511 "Route Distinguisher\n"
4512 "ASN:XX or A.B.C.D:XX\n")
4515 struct prefix_rd prd
;
4516 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4521 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4523 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4527 /* Check if we should disallow. */
4528 if (!is_vrf_rd_configured(bgp_vrf
)) {
4529 vty_out(vty
, "%% RD is not configured for this VRF\n");
4533 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4535 "%% RD specified does not match configuration for this VRF\n");
4539 evpn_unconfigure_vrf_rd(bgp_vrf
);
4543 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4544 no_bgp_evpn_vrf_rd_without_val_cmd
,
4547 "Route Distinguisher\n")
4549 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4554 /* Check if we should disallow. */
4555 if (!is_vrf_rd_configured(bgp_vrf
)) {
4556 vty_out(vty
, "%% RD is not configured for this VRF\n");
4560 evpn_unconfigure_vrf_rd(bgp_vrf
);
4564 DEFUN (bgp_evpn_vni_rd
,
4565 bgp_evpn_vni_rd_cmd
,
4566 "rd ASN:NN_OR_IP-ADDRESS:NN",
4567 "Route Distinguisher\n"
4568 "ASN:XX or A.B.C.D:XX\n")
4570 struct prefix_rd prd
;
4571 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4572 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4578 if (!EVPN_ENABLED(bgp
)) {
4580 "This command is only supported under EVPN VRF\n");
4584 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4586 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4590 /* If same as existing value, there is nothing more to do. */
4591 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4594 /* Configure or update the RD. */
4595 evpn_configure_rd(bgp
, vpn
, &prd
);
4599 DEFUN (no_bgp_evpn_vni_rd
,
4600 no_bgp_evpn_vni_rd_cmd
,
4601 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4603 "Route Distinguisher\n"
4604 "ASN:XX or A.B.C.D:XX\n")
4606 struct prefix_rd prd
;
4607 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4608 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4614 if (!EVPN_ENABLED(bgp
)) {
4616 "This command is only supported under EVPN VRF\n");
4620 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4622 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4626 /* Check if we should disallow. */
4627 if (!is_rd_configured(vpn
)) {
4628 vty_out(vty
, "%% RD is not configured for this VNI\n");
4632 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4634 "%% RD specified does not match configuration for this VNI\n");
4638 evpn_unconfigure_rd(bgp
, vpn
);
4642 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4643 no_bgp_evpn_vni_rd_without_val_cmd
,
4646 "Route Distinguisher\n")
4648 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4649 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4654 if (!EVPN_ENABLED(bgp
)) {
4656 "This command is only supported under EVPN VRF\n");
4660 /* Check if we should disallow. */
4661 if (!is_rd_configured(vpn
)) {
4662 vty_out(vty
, "%% RD is not configured for this VNI\n");
4666 evpn_unconfigure_rd(bgp
, vpn
);
4671 * Loop over all extended-communities in the route-target list rtl and
4672 * return 1 if we find ecomtarget
4674 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4675 struct ecommunity
*ecomtarget
)
4677 struct listnode
*node
, *nnode
;
4678 struct ecommunity
*ecom
;
4680 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4681 if (ecommunity_match(ecom
, ecomtarget
))
4688 /* display L3VNI related info for a VRF instance */
4689 DEFUN (show_bgp_vrf_l3vni_info
,
4690 show_bgp_vrf_l3vni_info_cmd
,
4691 "show bgp vrf VRFNAME vni [json]",
4699 char buf
[ETHER_ADDR_STRLEN
];
4700 char buf1
[INET6_ADDRSTRLEN
];
4702 const char *name
= NULL
;
4703 struct bgp
*bgp
= NULL
;
4704 struct listnode
*node
= NULL
;
4705 struct bgpevpn
*vpn
= NULL
;
4706 struct ecommunity
*ecom
= NULL
;
4707 json_object
*json
= NULL
;
4708 json_object
*json_vnis
= NULL
;
4709 json_object
*json_export_rts
= NULL
;
4710 json_object
*json_import_rts
= NULL
;
4711 bool uj
= use_json(argc
, argv
);
4714 json
= json_object_new_object();
4715 json_vnis
= json_object_new_array();
4716 json_export_rts
= json_object_new_array();
4717 json_import_rts
= json_object_new_array();
4720 name
= argv
[idx_vrf
]->arg
;
4721 bgp
= bgp_lookup_by_name(name
);
4724 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4726 json_object_string_add(json
, "warning",
4727 "BGP instance not found");
4728 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4729 json_object_free(json
);
4735 vty_out(vty
, "BGP VRF: %s\n", name
);
4736 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4737 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4738 vty_out(vty
, " Rmac: %s\n",
4739 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4740 vty_out(vty
, " VNI Filter: %s\n",
4741 CHECK_FLAG(bgp
->vrf_flags
,
4742 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4743 ? "prefix-routes-only"
4745 vty_out(vty
, " L2-VNI List:\n");
4747 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4748 vty_out(vty
, "%u ", vpn
->vni
);
4750 vty_out(vty
, " Export-RTs:\n");
4752 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4753 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4755 vty_out(vty
, " Import-RTs:\n");
4757 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4758 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4760 vty_out(vty
, " RD: %s\n",
4761 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4763 json_object_string_add(json
, "vrf", name
);
4764 json_object_string_add(json
, "local-ip",
4765 inet_ntoa(bgp
->originator_ip
));
4766 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4767 json_object_string_add(
4769 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4770 json_object_string_add(
4772 CHECK_FLAG(bgp
->vrf_flags
,
4773 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4774 ? "prefix-routes-only"
4776 /* list of l2vnis */
4777 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4778 json_object_array_add(json_vnis
,
4779 json_object_new_int(vpn
->vni
));
4780 json_object_object_add(json
, "l2vnis", json_vnis
);
4783 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4784 json_object_array_add(
4786 json_object_new_string(ecommunity_str(ecom
)));
4787 json_object_object_add(json
, "export-rts", json_export_rts
);
4790 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4791 json_object_array_add(
4793 json_object_new_string(ecommunity_str(ecom
)));
4794 json_object_object_add(json
, "import-rts", json_import_rts
);
4795 json_object_string_add(
4797 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4801 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4802 json
, JSON_C_TO_STRING_PRETTY
));
4803 json_object_free(json
);
4808 /* import/export rt for l3vni-vrf */
4809 DEFUN (bgp_evpn_vrf_rt
,
4810 bgp_evpn_vrf_rt_cmd
,
4811 "route-target <both|import|export> RT",
4813 "import and export\n"
4816 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4819 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4820 struct ecommunity
*ecomadd
= NULL
;
4825 if (!strcmp(argv
[1]->arg
, "import"))
4826 rt_type
= RT_TYPE_IMPORT
;
4827 else if (!strcmp(argv
[1]->arg
, "export"))
4828 rt_type
= RT_TYPE_EXPORT
;
4829 else if (!strcmp(argv
[1]->arg
, "both"))
4830 rt_type
= RT_TYPE_BOTH
;
4832 vty_out(vty
, "%% Invalid Route Target type\n");
4836 /* Add/update the import route-target */
4837 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4838 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4839 ECOMMUNITY_ROUTE_TARGET
, 0);
4841 vty_out(vty
, "%% Malformed Route Target list\n");
4844 ecommunity_str(ecomadd
);
4846 /* Do nothing if we already have this import route-target */
4847 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4848 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4851 /* Add/update the export route-target */
4852 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4853 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4854 ECOMMUNITY_ROUTE_TARGET
, 0);
4856 vty_out(vty
, "%% Malformed Route Target list\n");
4859 ecommunity_str(ecomadd
);
4861 /* Do nothing if we already have this export route-target */
4862 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4863 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4869 DEFUN (no_bgp_evpn_vrf_rt
,
4870 no_bgp_evpn_vrf_rt_cmd
,
4871 "no route-target <both|import|export> RT",
4874 "import and export\n"
4877 "ASN:XX or A.B.C.D:XX\n")
4879 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4880 int rt_type
, found_ecomdel
;
4881 struct ecommunity
*ecomdel
= NULL
;
4886 if (!strcmp(argv
[2]->arg
, "import"))
4887 rt_type
= RT_TYPE_IMPORT
;
4888 else if (!strcmp(argv
[2]->arg
, "export"))
4889 rt_type
= RT_TYPE_EXPORT
;
4890 else if (!strcmp(argv
[2]->arg
, "both"))
4891 rt_type
= RT_TYPE_BOTH
;
4893 vty_out(vty
, "%% Invalid Route Target type\n");
4897 if (rt_type
== RT_TYPE_IMPORT
) {
4898 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4900 "%% Import RT is not configured for this VRF\n");
4903 } else if (rt_type
== RT_TYPE_EXPORT
) {
4904 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4906 "%% Export RT is not configured for this VRF\n");
4909 } else if (rt_type
== RT_TYPE_BOTH
) {
4910 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4911 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4913 "%% Import/Export RT is not configured for this VRF\n");
4918 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4920 vty_out(vty
, "%% Malformed Route Target list\n");
4923 ecommunity_str(ecomdel
);
4925 if (rt_type
== RT_TYPE_IMPORT
) {
4926 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4929 "%% RT specified does not match configuration for this VRF\n");
4932 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4933 } else if (rt_type
== RT_TYPE_EXPORT
) {
4934 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4937 "%% RT specified does not match configuration for this VRF\n");
4940 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4941 } else if (rt_type
== RT_TYPE_BOTH
) {
4944 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4946 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4950 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4952 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4956 if (!found_ecomdel
) {
4958 "%% RT specified does not match configuration for this VRF\n");
4966 DEFUN (bgp_evpn_vni_rt
,
4967 bgp_evpn_vni_rt_cmd
,
4968 "route-target <both|import|export> RT",
4970 "import and export\n"
4973 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4975 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4976 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4978 struct ecommunity
*ecomadd
= NULL
;
4983 if (!EVPN_ENABLED(bgp
)) {
4985 "This command is only supported under EVPN VRF\n");
4989 if (!strcmp(argv
[1]->text
, "import"))
4990 rt_type
= RT_TYPE_IMPORT
;
4991 else if (!strcmp(argv
[1]->text
, "export"))
4992 rt_type
= RT_TYPE_EXPORT
;
4993 else if (!strcmp(argv
[1]->text
, "both"))
4994 rt_type
= RT_TYPE_BOTH
;
4996 vty_out(vty
, "%% Invalid Route Target type\n");
5000 /* Add/update the import route-target */
5001 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5002 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5003 ECOMMUNITY_ROUTE_TARGET
, 0);
5005 vty_out(vty
, "%% Malformed Route Target list\n");
5008 ecommunity_str(ecomadd
);
5010 /* Do nothing if we already have this import route-target */
5011 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5012 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5015 /* Add/update the export route-target */
5016 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5017 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5018 ECOMMUNITY_ROUTE_TARGET
, 0);
5020 vty_out(vty
, "%% Malformed Route Target list\n");
5023 ecommunity_str(ecomadd
);
5025 /* Do nothing if we already have this export route-target */
5026 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5027 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5033 DEFUN (no_bgp_evpn_vni_rt
,
5034 no_bgp_evpn_vni_rt_cmd
,
5035 "no route-target <both|import|export> RT",
5038 "import and export\n"
5041 "ASN:XX or A.B.C.D:XX\n")
5043 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5044 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5045 int rt_type
, found_ecomdel
;
5046 struct ecommunity
*ecomdel
= NULL
;
5051 if (!EVPN_ENABLED(bgp
)) {
5053 "This command is only supported under EVPN VRF\n");
5057 if (!strcmp(argv
[2]->text
, "import"))
5058 rt_type
= RT_TYPE_IMPORT
;
5059 else if (!strcmp(argv
[2]->text
, "export"))
5060 rt_type
= RT_TYPE_EXPORT
;
5061 else if (!strcmp(argv
[2]->text
, "both"))
5062 rt_type
= RT_TYPE_BOTH
;
5064 vty_out(vty
, "%% Invalid Route Target type\n");
5068 /* The user did "no route-target import", check to see if there are any
5069 * import route-targets configured. */
5070 if (rt_type
== RT_TYPE_IMPORT
) {
5071 if (!is_import_rt_configured(vpn
)) {
5073 "%% Import RT is not configured for this VNI\n");
5076 } else if (rt_type
== RT_TYPE_EXPORT
) {
5077 if (!is_export_rt_configured(vpn
)) {
5079 "%% Export RT is not configured for this VNI\n");
5082 } else if (rt_type
== RT_TYPE_BOTH
) {
5083 if (!is_import_rt_configured(vpn
)
5084 && !is_export_rt_configured(vpn
)) {
5086 "%% Import/Export RT is not configured for this VNI\n");
5091 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5093 vty_out(vty
, "%% Malformed Route Target list\n");
5096 ecommunity_str(ecomdel
);
5098 if (rt_type
== RT_TYPE_IMPORT
) {
5099 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5101 "%% RT specified does not match configuration for this VNI\n");
5104 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5105 } else if (rt_type
== RT_TYPE_EXPORT
) {
5106 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5108 "%% RT specified does not match configuration for this VNI\n");
5111 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5112 } else if (rt_type
== RT_TYPE_BOTH
) {
5115 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5116 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5120 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5121 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5125 if (!found_ecomdel
) {
5127 "%% RT specified does not match configuration for this VNI\n");
5135 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5136 no_bgp_evpn_vni_rt_without_val_cmd
,
5137 "no route-target <import|export>",
5143 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5144 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5150 if (!EVPN_ENABLED(bgp
)) {
5152 "This command is only supported under EVPN VRF\n");
5156 if (!strcmp(argv
[2]->text
, "import")) {
5157 rt_type
= RT_TYPE_IMPORT
;
5158 } else if (!strcmp(argv
[2]->text
, "export")) {
5159 rt_type
= RT_TYPE_EXPORT
;
5161 vty_out(vty
, "%% Invalid Route Target type\n");
5165 /* Check if we should disallow. */
5166 if (rt_type
== RT_TYPE_IMPORT
) {
5167 if (!is_import_rt_configured(vpn
)) {
5169 "%% Import RT is not configured for this VNI\n");
5173 if (!is_export_rt_configured(vpn
)) {
5175 "%% Export RT is not configured for this VNI\n");
5180 /* Unconfigure the RT. */
5181 if (rt_type
== RT_TYPE_IMPORT
)
5182 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5184 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5188 static int vni_cmp(const void **a
, const void **b
)
5190 const struct bgpevpn
*first
= *a
;
5191 const struct bgpevpn
*secnd
= *b
;
5193 return secnd
->vni
- first
->vni
;
5197 * Output EVPN configuration information.
5199 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5202 char buf1
[RD_ADDRSTRLEN
];
5205 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5206 struct listnode
*ln
;
5207 struct bgpevpn
*data
;
5209 list_sort(vnilist
, vni_cmp
);
5210 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5211 write_vni_config(vty
, data
);
5213 list_delete(&vnilist
);
5216 if (bgp
->advertise_all_vni
)
5217 vty_out(vty
, " advertise-all-vni\n");
5219 if (bgp
->advertise_autort_rfc8365
)
5220 vty_out(vty
, " autort rfc8365-compatible\n");
5222 if (bgp
->advertise_gw_macip
)
5223 vty_out(vty
, " advertise-default-gw\n");
5225 if (bgp
->evpn_info
->advertise_svi_macip
)
5226 vty_out(vty
, " advertise-svi-ip\n");
5228 if (!bgp
->evpn_info
->dup_addr_detect
)
5229 vty_out(vty
, " no dup-addr-detection\n");
5231 if (bgp
->evpn_info
->dad_max_moves
!=
5232 EVPN_DAD_DEFAULT_MAX_MOVES
||
5233 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5234 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5235 bgp
->evpn_info
->dad_max_moves
,
5236 bgp
->evpn_info
->dad_time
);
5238 if (bgp
->evpn_info
->dad_freeze
) {
5239 if (bgp
->evpn_info
->dad_freeze_time
)
5241 " dup-addr-detection freeze %u\n",
5242 bgp
->evpn_info
->dad_freeze_time
);
5245 " dup-addr-detection freeze permanent\n");
5248 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5249 vty_out(vty
, " flooding disable\n");
5251 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5252 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5253 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5254 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5255 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5257 vty_out(vty
, " advertise ipv4 unicast\n");
5260 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5261 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5262 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5263 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5264 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5266 vty_out(vty
, " advertise ipv6 unicast\n");
5269 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5270 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5271 vty_out(vty
, " default-originate ipv4\n");
5273 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5274 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5275 vty_out(vty
, " default-originate ipv6\n");
5277 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5278 vty_out(vty
, " rd %s\n",
5279 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5281 /* import route-target */
5282 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5284 struct listnode
*node
, *nnode
;
5285 struct ecommunity
*ecom
;
5287 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5289 ecom_str
= ecommunity_ecom2str(
5290 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5291 vty_out(vty
, " route-target import %s\n", ecom_str
);
5292 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5296 /* export route-target */
5297 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5299 struct listnode
*node
, *nnode
;
5300 struct ecommunity
*ecom
;
5302 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5304 ecom_str
= ecommunity_ecom2str(
5305 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5306 vty_out(vty
, " route-target export %s\n", ecom_str
);
5307 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5312 void bgp_ethernetvpn_init(void)
5314 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5315 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5316 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5317 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5318 install_element(VIEW_NODE
,
5319 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
5320 install_element(VIEW_NODE
,
5321 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5324 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
5327 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5328 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5329 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5330 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5331 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5332 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5333 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5334 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5335 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5336 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5337 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5338 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5339 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5340 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5341 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5342 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5343 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5344 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5345 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5346 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5349 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5350 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5352 /* "show bgp l2vpn evpn" commands. */
5353 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5354 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5355 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5356 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5357 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5358 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5359 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5360 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5361 install_element(VIEW_NODE
,
5362 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5363 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5364 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5365 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5366 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5368 /* "show bgp evpn" commands. */
5369 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5370 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5371 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5372 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5373 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5374 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5375 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5376 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5377 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5378 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5379 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5381 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5382 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5383 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5384 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5385 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5386 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5387 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5388 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5389 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5390 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5391 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5392 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5393 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5394 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5395 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5396 install_element(BGP_EVPN_VNI_NODE
,
5397 &bgp_evpn_advertise_default_gw_vni_cmd
);
5398 install_element(BGP_EVPN_VNI_NODE
,
5399 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5400 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5401 install_element(BGP_EVPN_VNI_NODE
,
5402 &no_bgp_evpn_advertise_vni_subnet_cmd
);