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
, 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
)) {
1053 json_array
= json_object_new_array();
1054 json_prefix_info
= json_object_new_object();
1056 json_object_string_add(json_prefix_info
,
1057 "prefix", bgp_evpn_route2str(
1058 (struct prefix_evpn
*)&rm
->p
, buf
,
1061 json_object_int_add(json_prefix_info
,
1062 "prefixLen", rm
->p
.prefixlen
);
1065 json_nroute
= json_object_new_object();
1068 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
1071 if (type
== bgp_show_type_neighbor
) {
1072 struct peer
*peer
= output_arg
;
1074 if (peer_cmp(peer
, pi
->peer
) != 0)
1079 json_object_int_add(
1080 json
, "bgpTableVersion",
1082 json_object_string_add(
1087 json_object_int_add(
1090 bgp
->default_local_pref
);
1091 json_object_int_add(
1095 if (option
== SHOW_DISPLAY_TAGS
)
1100 == SHOW_DISPLAY_OVERLAY
)
1105 "BGP table version is %" PRIu64
", local router ID is %s\n",
1110 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1112 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1113 vty_out(vty
, V4_HEADER
);
1126 /* Decode RD type. */
1127 type
= decode_rd_type(pnt
);
1128 /* Decode RD value. */
1129 if (type
== RD_TYPE_AS
)
1130 decode_rd_as(pnt
+ 2, &rd_as
);
1131 else if (type
== RD_TYPE_AS4
)
1132 decode_rd_as4(pnt
+ 2, &rd_as
);
1133 else if (type
== RD_TYPE_IP
)
1134 decode_rd_ip(pnt
+ 2, &rd_ip
);
1136 if (type
== RD_TYPE_AS
1137 || type
== RD_TYPE_AS4
)
1138 sprintf(rd_str
, "%u:%d",
1141 else if (type
== RD_TYPE_IP
)
1142 sprintf(rd_str
, "%s:%d",
1146 json_object_string_add(
1153 "Route Distinguisher: ");
1154 if (type
== RD_TYPE_AS
)
1159 else if (type
== RD_TYPE_AS4
)
1164 else if (type
== RD_TYPE_IP
)
1165 vty_out(vty
, "ip %s:%d",
1169 vty_out(vty
, "\n\n");
1174 if (option
== SHOW_DISPLAY_TAGS
)
1175 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1178 else if (option
== SHOW_DISPLAY_OVERLAY
)
1179 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1182 route_vty_out(vty
, &rm
->p
, pi
, 0,
1183 SAFI_EVPN
, json_array
);
1188 json_object_object_add(json_prefix_info
,
1189 "paths", json_array
);
1190 json_object_object_add(json_nroute
, buf
,
1196 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_neighbor_routes
,
1294 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1295 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1301 "Detailed information on TCP and BGP neighbor connections\n"
1302 "IPv4 Neighbor to display information about\n"
1303 "IPv6 Neighbor to display information about\n"
1304 "Neighbor on BGP configured interface\n"
1305 "Display routes learned from neighbor\n" JSON_STR
)
1309 char *peerstr
= NULL
;
1310 bool uj
= use_json(argc
, argv
);
1311 afi_t afi
= AFI_L2VPN
;
1312 safi_t safi
= SAFI_EVPN
;
1313 struct bgp
*bgp
= NULL
;
1315 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1318 vty_out(vty
, "No index\n");
1322 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1323 argv_find(argv
, argc
, "neighbors", &idx
);
1324 peerstr
= argv
[++idx
]->arg
;
1326 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1329 json_object
*json_no
= NULL
;
1330 json_no
= json_object_new_object();
1331 json_object_string_add(json_no
, "warning",
1332 "Malformed address");
1333 vty_out(vty
, "%s\n",
1334 json_object_to_json_string(json_no
));
1335 json_object_free(json_no
);
1337 vty_out(vty
, "Malformed address: %s\n",
1341 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1343 json_object
*json_no
= NULL
;
1344 json_no
= json_object_new_object();
1345 json_object_string_add(
1347 "No such neighbor or address family");
1348 vty_out(vty
, "%s\n",
1349 json_object_to_json_string(json_no
));
1350 json_object_free(json_no
);
1352 vty_out(vty
, "%% No such neighbor or address family\n");
1356 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1360 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1361 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1362 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1368 "Display information for a route distinguisher\n"
1369 "VPN Route Distinguisher\n"
1370 "Detailed information on TCP and BGP neighbor connections\n"
1371 "IPv4 Neighbor to display information about\n"
1372 "IPv6 Neighbor to display information about\n"
1373 "Neighbor on BGP configured interface\n"
1374 "Display routes learned from neighbor\n" JSON_STR
)
1376 int idx_ext_community
= 0;
1380 char *peerstr
= NULL
;
1381 struct prefix_rd prd
;
1382 bool uj
= use_json(argc
, argv
);
1383 afi_t afi
= AFI_L2VPN
;
1384 safi_t safi
= SAFI_EVPN
;
1385 struct bgp
*bgp
= NULL
;
1387 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1390 vty_out(vty
, "No index\n");
1394 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1395 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1398 json_object
*json_no
= NULL
;
1399 json_no
= json_object_new_object();
1400 json_object_string_add(json_no
, "warning",
1401 "Malformed Route Distinguisher");
1402 vty_out(vty
, "%s\n",
1403 json_object_to_json_string(json_no
));
1404 json_object_free(json_no
);
1406 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1410 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1411 argv_find(argv
, argc
, "neighbors", &idx
);
1412 peerstr
= argv
[++idx
]->arg
;
1414 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1417 json_object
*json_no
= NULL
;
1418 json_no
= json_object_new_object();
1419 json_object_string_add(json_no
, "warning",
1420 "Malformed address");
1421 vty_out(vty
, "%s\n",
1422 json_object_to_json_string(json_no
));
1423 json_object_free(json_no
);
1425 vty_out(vty
, "Malformed address: %s\n",
1429 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1431 json_object
*json_no
= NULL
;
1432 json_no
= json_object_new_object();
1433 json_object_string_add(
1435 "No such neighbor or address family");
1436 vty_out(vty
, "%s\n",
1437 json_object_to_json_string(json_no
));
1438 json_object_free(json_no
);
1440 vty_out(vty
, "%% No such neighbor or address family\n");
1444 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1448 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1449 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1450 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1456 "Detailed information on TCP and BGP neighbor connections\n"
1457 "IPv4 Neighbor to display information about\n"
1458 "IPv6 Neighbor to display information about\n"
1459 "Neighbor on BGP configured interface\n"
1460 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1464 bool uj
= use_json(argc
, argv
);
1465 struct bgp
*bgp
= NULL
;
1466 afi_t afi
= AFI_L2VPN
;
1467 safi_t safi
= SAFI_EVPN
;
1468 char *peerstr
= NULL
;
1473 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1476 vty_out(vty
, "No index\n");
1480 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1481 argv_find(argv
, argc
, "neighbors", &idx
);
1482 peerstr
= argv
[++idx
]->arg
;
1484 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1487 json_object
*json_no
= NULL
;
1488 json_no
= json_object_new_object();
1489 json_object_string_add(json_no
, "warning",
1490 "Malformed address");
1491 vty_out(vty
, "%s\n",
1492 json_object_to_json_string(json_no
));
1493 json_object_free(json_no
);
1495 vty_out(vty
, "Malformed address: %s\n",
1499 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1501 json_object
*json_no
= NULL
;
1502 json_no
= json_object_new_object();
1503 json_object_string_add(
1505 "No such neighbor or address family");
1506 vty_out(vty
, "%s\n",
1507 json_object_to_json_string(json_no
));
1508 json_object_free(json_no
);
1510 vty_out(vty
, "%% No such neighbor or address family\n");
1514 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1517 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1518 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1519 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1525 "Display information for a route distinguisher\n"
1526 "VPN Route Distinguisher\n"
1527 "Detailed information on TCP and BGP neighbor connections\n"
1528 "IPv4 Neighbor to display information about\n"
1529 "IPv6 Neighbor to display information about\n"
1530 "Neighbor on BGP configured interface\n"
1531 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1533 int idx_ext_community
= 0;
1537 struct prefix_rd prd
;
1538 struct bgp
*bgp
= NULL
;
1539 bool uj
= use_json(argc
, argv
);
1540 char *peerstr
= NULL
;
1541 afi_t afi
= AFI_L2VPN
;
1542 safi_t safi
= SAFI_EVPN
;
1550 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1553 vty_out(vty
, "No index\n");
1557 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1559 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1560 argv_find(argv
, argc
, "neighbors", &idx
);
1561 peerstr
= argv
[++idx
]->arg
;
1563 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1566 json_object
*json_no
= NULL
;
1567 json_no
= json_object_new_object();
1568 json_object_string_add(json_no
, "warning",
1569 "Malformed address");
1570 vty_out(vty
, "%s\n",
1571 json_object_to_json_string(json_no
));
1572 json_object_free(json_no
);
1574 vty_out(vty
, "Malformed address: %s\n",
1578 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1580 json_object
*json_no
= NULL
;
1581 json_no
= json_object_new_object();
1582 json_object_string_add(
1584 "No such neighbor or address family");
1585 vty_out(vty
, "%s\n",
1586 json_object_to_json_string(json_no
));
1587 json_object_free(json_no
);
1589 vty_out(vty
, "%% No such neighbor or address family\n");
1593 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1596 json_object
*json_no
= NULL
;
1597 json_no
= json_object_new_object();
1598 json_object_string_add(json_no
, "warning",
1599 "Malformed Route Distinguisher");
1600 vty_out(vty
, "%s\n",
1601 json_object_to_json_string(json_no
));
1602 json_object_free(json_no
);
1604 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1608 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1611 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1612 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1613 "show [ip] bgp l2vpn evpn all overlay [json]",
1619 "Display information about all EVPN NLRIs\n"
1620 "Display BGP Overlay Information for prefixes\n"
1623 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1624 SHOW_DISPLAY_OVERLAY
,
1625 use_json(argc
, argv
));
1628 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1629 show_ip_bgp_evpn_rd_overlay_cmd
,
1630 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1636 "Display information for a route distinguisher\n"
1637 "VPN Route Distinguisher\n"
1638 "Display BGP Overlay Information for prefixes\n")
1640 int idx_ext_community
= 0;
1642 struct prefix_rd prd
;
1644 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1646 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1648 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1651 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1652 SHOW_DISPLAY_OVERLAY
,
1653 use_json(argc
, argv
));
1656 /* For testing purpose, static route of EVPN RT-5. */
1657 DEFUN(evpnrt5_network
,
1658 evpnrt5_network_cmd
,
1659 "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]",
1660 "Specify a network to announce via BGP\n"
1663 "Specify Route Distinguisher\n"
1664 "VPN Route Distinguisher\n"
1666 "Ethernet Tag Value\n"
1669 "Ethernet Segment Identifier\n"
1670 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1672 "Gateway IP ( A.B.C.D )\n"
1673 "Gateway IPv6 ( X:X::X:X )\n"
1674 "Router Mac Ext Comm\n"
1675 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1676 "Route-map to modify the attributes\n"
1677 "Name of the route map\n")
1679 int idx_ipv4_prefixlen
= 1;
1680 int idx_route_distinguisher
= 3;
1685 int idx_routermac
= 13;
1687 return bgp_static_set_safi(
1688 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1689 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1690 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1691 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1692 argv
[idx_routermac
]->arg
);
1695 /* For testing purpose, static route of EVPN RT-5. */
1696 DEFUN(no_evpnrt5_network
,
1697 no_evpnrt5_network_cmd
,
1698 "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>",
1700 "Specify a network to announce via BGP\n"
1703 "Specify Route Distinguisher\n"
1704 "VPN Route Distinguisher\n"
1706 "Ethernet Tag Value\n"
1709 "Ethernet Segment Identifier\n"
1710 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1711 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1713 int idx_ipv4_prefixlen
= 2;
1714 int idx_ext_community
= 4;
1719 return bgp_static_unset_safi(
1720 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1721 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1722 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1723 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1726 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1728 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1731 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1733 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1737 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1738 * check that this is a change.
1740 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1741 struct ecommunity
*ecomadd
)
1743 /* If the VNI is "live", we need to uninstall routes using the current
1744 * import RT(s) first before we update the import RT, and subsequently
1747 if (is_vni_live(vpn
))
1748 bgp_evpn_uninstall_routes(bgp
, vpn
);
1750 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1751 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1753 /* If the auto route-target is in use we must remove it */
1754 evpn_import_rt_delete_auto(bgp
, vpn
);
1756 /* Add new RT and rebuild the RT to VNI mapping */
1757 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1759 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
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 * Unconfigure Import RT(s) for a VNI (vty handler).
1770 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1771 struct ecommunity
*ecomdel
)
1773 struct listnode
*node
, *nnode
, *node_to_del
;
1774 struct ecommunity
*ecom
;
1776 /* Along the lines of "configure" except we have to reset to the
1779 if (is_vni_live(vpn
))
1780 bgp_evpn_uninstall_routes(bgp
, vpn
);
1782 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1783 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1785 /* Delete all import RTs */
1786 if (ecomdel
== NULL
) {
1787 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1788 ecommunity_free(&ecom
);
1789 list_delete_node(vpn
->import_rtl
, node
);
1793 /* Delete a specific import RT */
1797 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1798 if (ecommunity_match(ecom
, ecomdel
)) {
1799 ecommunity_free(&ecom
);
1806 list_delete_node(vpn
->import_rtl
, node_to_del
);
1809 assert(vpn
->import_rtl
);
1810 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1811 if (list_isempty(vpn
->import_rtl
)) {
1812 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1813 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1815 /* Rebuild the RT to VNI mapping */
1817 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1819 /* Install routes that match new import RT */
1820 if (is_vni_live(vpn
))
1821 bgp_evpn_install_routes(bgp
, vpn
);
1825 * Configure the Export RT for a VNI (vty handler). Caller expected to
1826 * check that this is a change. Note that only a single export RT is
1827 * allowed for a VNI and any change to configuration is implemented as
1828 * a "replace" (similar to other configuration).
1830 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1831 struct ecommunity
*ecomadd
)
1833 /* If the auto route-target is in use we must remove it */
1834 evpn_export_rt_delete_auto(bgp
, vpn
);
1836 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1837 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1839 if (is_vni_live(vpn
))
1840 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1844 * Unconfigure the Export RT for a VNI (vty handler)
1846 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1847 struct ecommunity
*ecomdel
)
1849 struct listnode
*node
, *nnode
, *node_to_del
;
1850 struct ecommunity
*ecom
;
1852 /* Delete all export RTs */
1853 if (ecomdel
== NULL
) {
1854 /* Reset to default and process all routes. */
1855 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1856 ecommunity_free(&ecom
);
1857 list_delete_node(vpn
->export_rtl
, node
);
1861 /* Delete a specific export RT */
1865 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1866 if (ecommunity_match(ecom
, ecomdel
)) {
1867 ecommunity_free(&ecom
);
1874 list_delete_node(vpn
->export_rtl
, node_to_del
);
1877 assert(vpn
->export_rtl
);
1878 if (list_isempty(vpn
->export_rtl
)) {
1879 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1880 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1883 if (is_vni_live(vpn
))
1884 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1888 * Configure RD for VRF
1890 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1892 /* If we have already advertise type-5 routes with a diffrent RD, we
1893 * have to delete and withdraw them firs
1895 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1898 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1899 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1901 /* We have a new RD for VRF.
1902 * Advertise all type-5 routes again with the new RD
1904 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1908 * Unconfigure RD for VRF
1910 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1912 /* If we have already advertise type-5 routes with a diffrent RD, we
1913 * have to delete and withdraw them firs
1915 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1917 /* fall back to default RD */
1918 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1919 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1921 /* We have a new RD for VRF.
1922 * Advertise all type-5 routes again with the new RD
1924 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1928 * Configure RD for a VNI (vty handler)
1930 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1931 struct prefix_rd
*rd
)
1933 /* If the VNI is "live", we need to delete and withdraw this VNI's
1934 * local routes with the prior RD first. Then, after updating RD,
1935 * need to re-advertise.
1937 if (is_vni_live(vpn
))
1938 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1941 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1942 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1944 if (is_vni_live(vpn
))
1945 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1949 * Unconfigure RD for a VNI (vty handler)
1951 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1953 /* If the VNI is "live", we need to delete and withdraw this VNI's
1954 * local routes with the prior RD first. Then, after resetting RD
1955 * to automatic value, need to re-advertise.
1957 if (is_vni_live(vpn
))
1958 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1960 /* reset RD to default */
1961 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1963 if (is_vni_live(vpn
))
1964 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1968 * Create VNI, if not already present (VTY handler). Mark as configured.
1970 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1972 struct bgpevpn
*vpn
;
1973 struct in_addr mcast_grp
= {INADDR_ANY
};
1978 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1980 /* Check if this L2VNI is already configured as L3VNI */
1981 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
1984 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1989 /* tenant vrf will be updated when we get local_vni_add from
1992 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
1996 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2002 /* Mark as configured. */
2003 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2008 * Delete VNI. If VNI does not exist in the system (i.e., just
2009 * configuration), all that is needed is to free it. Otherwise,
2010 * any parameters configured for the VNI need to be reset (with
2011 * appropriate action) and the VNI marked as unconfigured; the
2012 * VNI will continue to exist, purely as a "learnt" entity.
2014 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2016 assert(bgp
->vnihash
);
2018 if (!is_vni_live(vpn
)) {
2019 bgp_evpn_free(bgp
, vpn
);
2023 /* We need to take the unconfigure action for each parameter of this VNI
2024 * that is configured. Some optimization is possible, but not worth the
2025 * additional code for an operation that should be pretty rare.
2027 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2029 /* First, deal with the export side - RD and export RT changes. */
2030 if (is_rd_configured(vpn
))
2031 evpn_unconfigure_rd(bgp
, vpn
);
2032 if (is_export_rt_configured(vpn
))
2033 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2035 /* Next, deal with the import side. */
2036 if (is_import_rt_configured(vpn
))
2037 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2043 * Display import RT mapping to VRFs (vty handler)
2044 * bgp_evpn: evpn bgp instance
2046 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2054 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2055 (void (*)(struct hash_bucket
*,
2056 void *))show_vrf_import_rt_entry
,
2061 * Display import RT mapping to VNIs (vty handler)
2063 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2072 bgp
->import_rt_hash
,
2073 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2078 * Display EVPN routes for all VNIs - vty handler.
2080 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2081 struct in_addr vtep_ip
, json_object
*json
,
2085 struct vni_walk_ctx wctx
;
2087 num_vnis
= hashcount(bgp
->vnihash
);
2090 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2093 wctx
.vtep_ip
= vtep_ip
;
2095 wctx
.detail
= detail
;
2096 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2097 void *))show_vni_routes_hash
,
2102 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2104 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2105 vni_t vni
, struct in_addr orig_ip
,
2108 struct bgpevpn
*vpn
;
2109 struct prefix_evpn p
;
2110 struct bgp_node
*rn
;
2111 struct bgp_path_info
*pi
;
2112 uint32_t path_cnt
= 0;
2115 json_object
*json_paths
= NULL
;
2121 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2123 vty_out(vty
, "VNI not found\n");
2127 /* See if route exists. */
2128 build_evpn_type3_prefix(&p
, orig_ip
);
2129 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2130 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2132 vty_out(vty
, "%% Network not in table\n");
2137 json_paths
= json_object_new_array();
2139 /* Prefix and num paths displayed once per prefix. */
2140 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2142 /* Display each path for this prefix. */
2143 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2144 json_object
*json_path
= NULL
;
2147 json_path
= json_object_new_array();
2149 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2153 json_object_array_add(json_paths
, json_path
);
2160 json_object_object_add(json
, "paths", json_paths
);
2162 json_object_int_add(json
, "numPaths", path_cnt
);
2164 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2170 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2171 * By definition, only matching type-2 route will be displayed.
2173 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2174 vni_t vni
, struct ethaddr
*mac
,
2175 struct ipaddr
*ip
, json_object
*json
)
2177 struct bgpevpn
*vpn
;
2178 struct prefix_evpn p
;
2179 struct bgp_node
*rn
;
2180 struct bgp_path_info
*pi
;
2181 uint32_t path_cnt
= 0;
2184 json_object
*json_paths
= NULL
;
2190 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2193 vty_out(vty
, "VNI not found\n");
2197 /* See if route exists. Look for both non-sticky and sticky. */
2198 build_evpn_type2_prefix(&p
, mac
, ip
);
2199 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2200 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2202 vty_out(vty
, "%% Network not in table\n");
2207 json_paths
= json_object_new_array();
2209 /* Prefix and num paths displayed once per prefix. */
2210 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2212 /* Display each path for this prefix. */
2213 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2214 json_object
*json_path
= NULL
;
2217 json_path
= json_object_new_array();
2219 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2223 json_object_array_add(json_paths
, json_path
);
2230 json_object_object_add(json
, "paths", json_paths
);
2232 json_object_int_add(json
, "numPaths", path_cnt
);
2234 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2239 /* Disaplay EVPN routes for a ESI - VTY handler */
2240 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2241 esi_t
*esi
, json_object
*json
)
2243 struct evpnes
*es
= NULL
;
2246 es
= bgp_evpn_lookup_es(bgp
, esi
);
2249 vty_out(vty
, "ESI not found\n");
2253 show_esi_routes(bgp
, es
, vty
, json
);
2257 * Display EVPN routes for a VNI - vty handler.
2258 * If 'type' is non-zero, only routes matching that type are shown.
2259 * If the vtep_ip is non zero, only routes behind that vtep are shown
2261 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2262 int type
, struct in_addr vtep_ip
,
2265 struct bgpevpn
*vpn
;
2268 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2271 vty_out(vty
, "VNI not found\n");
2275 /* Walk this VNI's route table and display appropriate routes. */
2276 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2280 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2281 * IP (vty handler). By definition, only matching type-2 route will be
2284 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2285 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2286 struct ipaddr
*ip
, json_object
*json
)
2288 struct prefix_evpn p
;
2289 struct bgp_node
*rn
;
2290 struct bgp_path_info
*pi
;
2293 uint32_t path_cnt
= 0;
2294 json_object
*json_paths
= NULL
;
2295 char prefix_str
[BUFSIZ
];
2300 /* See if route exists. Look for both non-sticky and sticky. */
2301 build_evpn_type2_prefix(&p
, mac
, ip
);
2302 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2303 (struct prefix
*)&p
, prd
);
2304 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2306 vty_out(vty
, "%% Network not in table\n");
2310 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2311 sizeof(prefix_str
));
2313 /* Prefix and num paths displayed once per prefix. */
2314 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2317 json_paths
= json_object_new_array();
2319 /* Display each path for this prefix. */
2320 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2321 json_object
*json_path
= NULL
;
2324 json_path
= json_object_new_array();
2326 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2330 json_object_array_add(json_paths
, json_path
);
2335 if (json
&& path_cnt
) {
2337 json_object_object_add(json
, prefix_str
, json_paths
);
2338 json_object_int_add(json
, "numPaths", path_cnt
);
2340 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2346 * Display BGP EVPN routing table -- for specific RD (vty handler)
2347 * If 'type' is non-zero, only routes matching that type are shown.
2349 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2350 struct prefix_rd
*prd
, int type
,
2353 struct bgp_node
*rd_rn
;
2354 struct bgp_table
*table
;
2355 struct bgp_node
*rn
;
2356 struct bgp_path_info
*pi
;
2360 uint32_t prefix_cnt
, path_cnt
;
2361 char rd_str
[RD_ADDRSTRLEN
];
2362 json_object
*json_rd
= NULL
;
2363 int add_rd_to_json
= 0;
2367 prefix_cnt
= path_cnt
= 0;
2369 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2371 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2375 table
= bgp_node_get_bgp_table_info(rd_rn
);
2380 json_rd
= json_object_new_object();
2381 json_object_string_add(json_rd
, "rd", rd_str
);
2384 /* Display all prefixes with this RD. */
2385 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2386 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2387 json_object
*json_prefix
= NULL
;
2388 json_object
*json_paths
= NULL
;
2389 char prefix_str
[BUFSIZ
];
2390 int add_prefix_to_json
= 0;
2392 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2393 sizeof(prefix_str
));
2395 if (type
&& evp
->prefix
.route_type
!= type
)
2399 json_prefix
= json_object_new_object();
2401 pi
= bgp_node_get_bgp_path_info(rn
);
2403 /* RD header and legend - once overall. */
2404 if (rd_header
&& !json
) {
2406 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2408 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2410 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2414 /* Prefix and num paths displayed once per prefix. */
2415 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2422 json_paths
= json_object_new_array();
2424 /* Display each path for this prefix. */
2425 for (; pi
; pi
= pi
->next
) {
2426 json_object
*json_path
= NULL
;
2429 json_path
= json_object_new_array();
2431 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2435 json_object_array_add(json_paths
, json_path
);
2438 add_prefix_to_json
= 1;
2442 if (json
&& add_prefix_to_json
) {
2443 json_object_object_add(json_prefix
, "paths",
2445 json_object_object_add(json_rd
, prefix_str
,
2450 if (json
&& add_rd_to_json
)
2451 json_object_object_add(json
, rd_str
, json_rd
);
2454 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2455 json_object_int_add(json
, "numPaths", path_cnt
);
2457 if (prefix_cnt
== 0)
2458 vty_out(vty
, "No prefixes exist with this RD%s\n",
2459 type
? " (of requested type)" : "");
2462 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2463 prefix_cnt
, path_cnt
,
2464 type
? " (of requested type)" : "");
2469 * Display BGP EVPN routing table - all routes (vty handler).
2470 * If 'type' is non-zero, only routes matching that type are shown.
2472 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2473 json_object
*json
, int detail
)
2475 struct bgp_node
*rd_rn
;
2476 struct bgp_table
*table
;
2477 struct bgp_node
*rn
;
2478 struct bgp_path_info
*pi
;
2479 int header
= detail
? 0 : 1;
2483 uint32_t prefix_cnt
, path_cnt
;
2487 prefix_cnt
= path_cnt
= 0;
2489 /* EVPN routing table is a 2-level table with the first level being
2492 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2493 rd_rn
= bgp_route_next(rd_rn
)) {
2494 char rd_str
[RD_ADDRSTRLEN
];
2495 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2496 int add_rd_to_json
= 0;
2499 table
= bgp_node_get_bgp_table_info(rd_rn
);
2503 tbl_ver
= table
->version
;
2504 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2508 json_rd
= json_object_new_object();
2509 json_object_string_add(json_rd
, "rd", rd_str
);
2514 /* Display all prefixes for an RD */
2515 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2516 json_object
*json_prefix
=
2517 NULL
; /* contains prefix under a RD */
2518 json_object
*json_paths
=
2519 NULL
; /* array of paths under a prefix*/
2520 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2521 char prefix_str
[BUFSIZ
];
2522 int add_prefix_to_json
= 0;
2524 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2525 prefix_str
, sizeof(prefix_str
));
2527 if (type
&& evp
->prefix
.route_type
!= type
)
2530 pi
= bgp_node_get_bgp_path_info(rn
);
2532 /* Overall header/legend displayed once. */
2534 bgp_evpn_show_route_header(vty
, bgp
,
2539 "%19s Extended Community\n"
2544 /* RD header - per RD. */
2546 bgp_evpn_show_route_rd_header(
2555 json_prefix
= json_object_new_object();
2556 json_paths
= json_object_new_array();
2557 json_object_string_add(json_prefix
, "prefix",
2559 json_object_int_add(json_prefix
, "prefixLen",
2563 /* Prefix and num paths displayed once per prefix. */
2565 route_vty_out_detail_header(
2567 (struct prefix_rd
*)&rd_rn
->p
,
2568 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2570 /* For EVPN, the prefix is displayed for each path (to
2572 * with code that already exists).
2574 for (; pi
; pi
= pi
->next
) {
2575 json_object
*json_path
= NULL
;
2577 add_prefix_to_json
= 1;
2581 json_path
= json_object_new_array();
2584 route_vty_out_detail(
2585 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2586 SAFI_EVPN
, json_path
);
2588 route_vty_out(vty
, &rn
->p
, pi
, 0,
2589 SAFI_EVPN
, json_path
);
2592 json_object_array_add(json_paths
,
2596 if (json
&& add_prefix_to_json
) {
2597 json_object_object_add(json_prefix
, "paths",
2599 json_object_object_add(json_rd
, prefix_str
,
2604 if (json
&& add_rd_to_json
)
2605 json_object_object_add(json
, rd_str
, json_rd
);
2609 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2610 json_object_int_add(json
, "numPaths", path_cnt
);
2612 if (prefix_cnt
== 0) {
2613 vty_out(vty
, "No EVPN prefixes %sexist\n",
2614 type
? "(of requested type) " : "");
2616 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2617 prefix_cnt
, path_cnt
,
2618 type
? " (of requested type)" : "");
2623 /* Display specific ES */
2624 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2627 struct evpnes
*es
= NULL
;
2629 es
= bgp_evpn_lookup_es(bgp
, esi
);
2631 display_es(vty
, es
, json
);
2634 vty_out(vty
, "{}\n");
2636 vty_out(vty
, "ESI not found\n");
2642 /* Display all ESs */
2643 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2649 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2650 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2655 hash_iterate(bgp
->esihash
,
2656 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2661 * Display specified VNI (vty handler)
2663 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2667 struct bgpevpn
*vpn
;
2669 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2672 display_vni(vty
, vpn
, json
);
2674 struct bgp
*bgp_temp
;
2675 struct listnode
*node
= NULL
;
2677 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2678 if (bgp_temp
->l3vni
== vni
) {
2680 display_l3vni(vty
, bgp_temp
, json
);
2687 vty_out(vty
, "{}\n");
2689 vty_out(vty
, "VNI not found\n");
2696 * Display a VNI (upon user query).
2698 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2702 struct bgp
*bgp_temp
= NULL
;
2703 struct listnode
*node
;
2707 vty_out(vty
, "Flags: * - Kernel\n");
2708 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2709 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2712 /* print all L2 VNIS */
2715 hash_iterate(bgp
->vnihash
,
2716 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2719 /* print all L3 VNIs */
2720 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2721 show_l3vni_entry(vty
, bgp_temp
, json
);
2725 * evpn - enable advertisement of svi MAC-IP
2727 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2731 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2733 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2736 bgp
->evpn_info
->advertise_svi_macip
= set
;
2737 bgp_zebra_advertise_svi_macip(bgp
,
2738 bgp
->evpn_info
->advertise_svi_macip
, 0);
2740 if (set
&& vpn
->advertise_svi_macip
)
2742 else if (!set
&& !vpn
->advertise_svi_macip
)
2745 vpn
->advertise_svi_macip
= set
;
2746 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2752 * evpn - enable advertisement of default g/w
2754 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2757 if (bgp
->advertise_gw_macip
)
2760 bgp
->advertise_gw_macip
= 1;
2761 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2763 if (vpn
->advertise_gw_macip
)
2766 vpn
->advertise_gw_macip
= 1;
2767 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2774 * evpn - disable advertisement of default g/w
2776 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2777 struct bgpevpn
*vpn
)
2780 if (!bgp
->advertise_gw_macip
)
2783 bgp
->advertise_gw_macip
= 0;
2784 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2786 if (!vpn
->advertise_gw_macip
)
2789 vpn
->advertise_gw_macip
= 0;
2790 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2797 * evpn - enable advertisement of default g/w
2799 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2800 afi_t afi
, bool add
)
2802 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2805 /* bail if we are already advertising default route */
2806 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2810 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2811 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2812 else if (afi
== AFI_IP6
)
2813 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2814 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2816 /* bail out if we havent advertised the default route */
2817 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2820 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2821 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2822 else if (afi
== AFI_IP6
)
2823 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2824 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2827 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2831 * evpn - enable advertisement of default g/w
2833 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2834 struct bgpevpn
*vpn
)
2836 if (vpn
->advertise_subnet
)
2839 vpn
->advertise_subnet
= 1;
2840 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2844 * evpn - disable advertisement of default g/w
2846 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2848 if (!vpn
->advertise_subnet
)
2851 vpn
->advertise_subnet
= 0;
2852 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2856 * EVPN (VNI advertisement) enabled. Register with zebra.
2858 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2860 bgp
->advertise_all_vni
= 1;
2862 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2866 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2867 * cache, EVPN routes (delete and withdraw from peers).
2869 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2871 bgp
->advertise_all_vni
= 0;
2872 bgp_set_evpn(bgp_get_default());
2873 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2874 bgp_evpn_cleanup_on_disable(bgp
);
2878 * EVPN - use RFC8365 to auto-derive RT
2880 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2882 bgp
->advertise_autort_rfc8365
= 1;
2883 bgp_evpn_handle_autort_change(bgp
);
2887 * EVPN - don't use RFC8365 to auto-derive RT
2889 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2891 bgp
->advertise_autort_rfc8365
= 0;
2892 bgp_evpn_handle_autort_change(bgp
);
2895 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2897 char buf1
[RD_ADDRSTRLEN
];
2899 struct listnode
*node
, *nnode
;
2900 struct ecommunity
*ecom
;
2902 if (is_vni_configured(vpn
)) {
2903 vty_out(vty
, " vni %d\n", vpn
->vni
);
2904 if (is_rd_configured(vpn
))
2905 vty_out(vty
, " rd %s\n",
2906 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2908 if (is_import_rt_configured(vpn
)) {
2909 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2911 ecom_str
= ecommunity_ecom2str(
2912 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2913 vty_out(vty
, " route-target import %s\n",
2915 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2919 if (is_export_rt_configured(vpn
)) {
2920 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2922 ecom_str
= ecommunity_ecom2str(
2923 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2924 vty_out(vty
, " route-target export %s\n",
2926 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2930 if (vpn
->advertise_gw_macip
)
2931 vty_out(vty
, " advertise-default-gw\n");
2933 if (vpn
->advertise_svi_macip
)
2934 vty_out(vty
, " advertise-svi-ip\n");
2936 if (vpn
->advertise_subnet
)
2937 vty_out(vty
, " advertise-subnet\n");
2939 vty_out(vty
, " exit-vni\n");
2943 #ifndef VTYSH_EXTRACT_PL
2944 #include "bgpd/bgp_evpn_vty_clippy.c"
2947 DEFPY(bgp_evpn_flood_control
,
2948 bgp_evpn_flood_control_cmd
,
2949 "[no$no] flooding <disable$disable|head-end-replication$her>",
2951 "Specify handling for BUM packets\n"
2952 "Do not flood any BUM packets\n"
2953 "Flood BUM packets using head-end replication\n")
2955 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2956 enum vxlan_flood_control flood_ctrl
;
2962 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
2964 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
2968 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
2971 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
2972 bgp_evpn_flood_control_change(bgp
);
2977 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2978 bgp_evpn_advertise_default_gw_vni_cmd
,
2979 "advertise-default-gw",
2980 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2982 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2983 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2988 evpn_set_advertise_default_gw(bgp
, vpn
);
2993 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2994 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2995 "no advertise-default-gw",
2997 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2999 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3000 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3005 evpn_unset_advertise_default_gw(bgp
, vpn
);
3011 DEFUN (bgp_evpn_advertise_default_gw
,
3012 bgp_evpn_advertise_default_gw_cmd
,
3013 "advertise-default-gw",
3014 "Advertise All default g/w mac-ip routes in EVPN\n")
3016 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3021 if (!EVPN_ENABLED(bgp
)) {
3023 "This command is only supported under the EVPN VRF\n");
3027 evpn_set_advertise_default_gw(bgp
, NULL
);
3032 DEFUN (no_bgp_evpn_advertise_default_gw
,
3033 no_bgp_evpn_advertise_default_gw_cmd
,
3034 "no advertise-default-gw",
3036 "Withdraw All default g/w mac-ip routes from EVPN\n")
3038 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3043 if (!EVPN_ENABLED(bgp
)) {
3045 "This command is only supported under the EVPN VRF\n");
3049 evpn_unset_advertise_default_gw(bgp
, NULL
);
3054 DEFUN (bgp_evpn_advertise_all_vni
,
3055 bgp_evpn_advertise_all_vni_cmd
,
3056 "advertise-all-vni",
3057 "Advertise All local VNIs\n")
3059 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3060 struct bgp
*bgp_evpn
= NULL
;
3065 bgp_evpn
= bgp_get_evpn();
3066 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3067 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3069 return CMD_WARNING_CONFIG_FAILED
;
3072 evpn_set_advertise_all_vni(bgp
);
3076 DEFUN (no_bgp_evpn_advertise_all_vni
,
3077 no_bgp_evpn_advertise_all_vni_cmd
,
3078 "no advertise-all-vni",
3080 "Advertise All local VNIs\n")
3082 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3086 evpn_unset_advertise_all_vni(bgp
);
3090 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3091 bgp_evpn_advertise_autort_rfc8365_cmd
,
3092 "autort rfc8365-compatible",
3093 "Auto-derivation of RT\n"
3094 "Auto-derivation of RT using RFC8365\n")
3096 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3100 evpn_set_advertise_autort_rfc8365(bgp
);
3104 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3105 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3106 "no autort rfc8365-compatible",
3108 "Auto-derivation of RT\n"
3109 "Auto-derivation of RT using RFC8365\n")
3111 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3115 evpn_unset_advertise_autort_rfc8365(bgp
);
3119 DEFUN (bgp_evpn_default_originate
,
3120 bgp_evpn_default_originate_cmd
,
3121 "default-originate <ipv4 | ipv6>",
3122 "originate a default route\n"
3123 "ipv4 address family\n"
3124 "ipv6 address family\n")
3128 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3132 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3133 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3137 DEFUN (no_bgp_evpn_default_originate
,
3138 no_bgp_evpn_default_originate_cmd
,
3139 "no default-originate <ipv4 | ipv6>",
3141 "withdraw a default route\n"
3142 "ipv4 address family\n"
3143 "ipv6 address family\n")
3147 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3151 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3152 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3156 DEFPY (dup_addr_detection
,
3157 dup_addr_detection_cmd
,
3158 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3159 "Duplicate address detection\n"
3160 "Max allowed moves before address detected as duplicate\n"
3161 "Num of max allowed moves (2-1000) default 5\n"
3162 "Duplicate address detection time\n"
3163 "Time in seconds (2-1800) default 180\n")
3165 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3170 if (!EVPN_ENABLED(bgp_vrf
)) {
3172 "This command is only supported under the EVPN VRF\n");
3176 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3179 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3181 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3183 bgp_zebra_dup_addr_detection(bgp_vrf
);
3188 DEFPY (dup_addr_detection_auto_recovery
,
3189 dup_addr_detection_auto_recovery_cmd
,
3190 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3191 "Duplicate address detection\n"
3192 "Duplicate address detection freeze\n"
3193 "Duplicate address detection permanent freeze\n"
3194 "Duplicate address detection freeze time (30-3600)\n")
3196 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3197 uint32_t freeze_time
= freeze_time_val
;
3202 if (!EVPN_ENABLED(bgp_vrf
)) {
3204 "This command is only supported under the EVPN VRF\n");
3208 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3209 bgp_vrf
->evpn_info
->dad_freeze
= true;
3210 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3212 bgp_zebra_dup_addr_detection(bgp_vrf
);
3217 DEFPY (no_dup_addr_detection
,
3218 no_dup_addr_detection_cmd
,
3219 "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>]",
3221 "Duplicate address detection\n"
3222 "Max allowed moves before address detected as duplicate\n"
3223 "Num of max allowed moves (2-1000) default 5\n"
3224 "Duplicate address detection time\n"
3225 "Time in seconds (2-1800) default 180\n"
3226 "Duplicate address detection freeze\n"
3227 "Duplicate address detection permanent freeze\n"
3228 "Duplicate address detection freeze time (30-3600)\n")
3230 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3231 uint32_t max_moves
= (uint32_t)max_moves_val
;
3232 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3237 if (!EVPN_ENABLED(bgp_vrf
)) {
3239 "This command is only supported under the EVPN VRF\n");
3244 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3246 /* Reset all parameters to default. */
3247 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3248 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3249 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3250 bgp_vrf
->evpn_info
->dad_freeze
= false;
3251 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3254 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3256 "%% Value does not match with config\n");
3259 bgp_vrf
->evpn_info
->dad_max_moves
=
3260 EVPN_DAD_DEFAULT_MAX_MOVES
;
3264 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3266 "%% Value does not match with config\n");
3269 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3273 if (bgp_vrf
->evpn_info
->dad_freeze_time
3276 "%% Value does not match with config\n");
3279 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3280 bgp_vrf
->evpn_info
->dad_freeze
= false;
3283 if (permanent_val
) {
3284 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3286 "%% Value does not match with config\n");
3289 bgp_vrf
->evpn_info
->dad_freeze
= false;
3293 bgp_zebra_dup_addr_detection(bgp_vrf
);
3298 DEFPY(bgp_evpn_advertise_svi_ip
,
3299 bgp_evpn_advertise_svi_ip_cmd
,
3300 "[no$no] advertise-svi-ip",
3302 "Advertise svi mac-ip routes in EVPN\n")
3304 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3309 if (!EVPN_ENABLED(bgp
)) {
3311 "This command is only supported under EVPN VRF\n");
3316 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3318 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3323 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3324 bgp_evpn_advertise_svi_ip_vni_cmd
,
3325 "[no$no] advertise-svi-ip",
3327 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3329 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3330 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3336 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3338 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3343 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3344 bgp_evpn_advertise_vni_subnet_cmd
,
3346 "Advertise the subnet corresponding to VNI\n")
3348 struct bgp
*bgp_vrf
= NULL
;
3349 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3350 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3355 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3359 evpn_set_advertise_subnet(bgp
, vpn
);
3363 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3364 no_bgp_evpn_advertise_vni_subnet_cmd
,
3365 "no advertise-subnet",
3367 "Advertise All local VNIs\n")
3369 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3370 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3375 evpn_unset_advertise_subnet(bgp
, vpn
);
3379 DEFUN (bgp_evpn_advertise_type5
,
3380 bgp_evpn_advertise_type5_cmd
,
3381 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3382 "Advertise prefix routes\n"
3385 "route-map for filtering specific routes\n"
3386 "Name of the route map\n")
3388 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3395 int rmap_changed
= 0;
3397 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3398 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3399 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3401 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3403 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3404 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3407 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3411 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3413 "%%only ipv4 or ipv6 address families are supported");
3417 if (safi
!= SAFI_UNICAST
) {
3419 "%%only ipv4 unicast or ipv6 unicast are supported");
3423 if (afi
== AFI_IP
) {
3425 /* if we are already advertising ipv4 prefix as type-5
3428 if (!rmap_changed
&&
3429 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3430 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3432 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3433 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3436 /* if we are already advertising ipv6 prefix as type-5
3439 if (!rmap_changed
&&
3440 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3441 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3443 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3444 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3448 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3449 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3450 XFREE(MTYPE_ROUTE_MAP_NAME
,
3451 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3452 route_map_counter_decrement(
3453 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3454 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3455 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3459 /* set the route-map for advertise command */
3460 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3461 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3462 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3463 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3464 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3465 route_map_counter_increment(
3466 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3469 /* advertise type-5 routes */
3470 if (advertise_type5_routes(bgp_vrf
, afi
))
3471 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3475 DEFUN (no_bgp_evpn_advertise_type5
,
3476 no_bgp_evpn_advertise_type5_cmd
,
3477 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3479 "Advertise prefix routes\n"
3483 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3489 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3490 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3492 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3494 "%%only ipv4 or ipv6 address families are supported");
3498 if (safi
!= SAFI_UNICAST
) {
3500 "%%only ipv4 unicast or ipv6 unicast are supported");
3504 if (afi
== AFI_IP
) {
3506 /* if we are not advertising ipv4 prefix as type-5
3509 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3510 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3511 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3512 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3513 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3517 /* if we are not advertising ipv6 prefix as type-5
3520 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3521 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3522 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3523 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3524 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3528 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3529 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3530 XFREE(MTYPE_ROUTE_MAP_NAME
,
3531 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3532 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3533 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3540 * Display VNI information - for all or a specific VNI
3542 DEFUN(show_bgp_l2vpn_evpn_vni
,
3543 show_bgp_l2vpn_evpn_vni_cmd
,
3544 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3553 struct bgp
*bgp_evpn
;
3557 json_object
*json
= NULL
;
3558 uint32_t num_l2vnis
= 0;
3559 uint32_t num_l3vnis
= 0;
3560 uint32_t num_vnis
= 0;
3561 struct listnode
*node
= NULL
;
3562 struct bgp
*bgp_temp
= NULL
;
3564 uj
= use_json(argc
, argv
);
3566 bgp_evpn
= bgp_get_evpn();
3570 if (!argv_find(argv
, argc
, "evpn", &idx
))
3574 json
= json_object_new_object();
3576 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3578 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3580 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3581 if (bgp_temp
->l3vni
)
3584 num_vnis
= num_l2vnis
+ num_l3vnis
;
3586 json_object_string_add(json
, "advertiseGatewayMacip",
3587 bgp_evpn
->advertise_gw_macip
3590 json_object_string_add(json
, "advertiseAllVnis",
3591 is_evpn_enabled() ? "Enabled"
3593 json_object_string_add(
3595 bgp_evpn
->vxlan_flood_ctrl
3596 == VXLAN_FLOOD_HEAD_END_REPL
3597 ? "Head-end replication"
3599 json_object_int_add(json
, "numVnis", num_vnis
);
3600 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3601 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3603 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3604 bgp_evpn
->advertise_gw_macip
? "Enabled"
3606 vty_out(vty
, "Advertise SVI Macip: %s\n",
3607 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3609 vty_out(vty
, "Advertise All VNI flag: %s\n",
3610 is_evpn_enabled() ? "Enabled" : "Disabled");
3611 vty_out(vty
, "BUM flooding: %s\n",
3612 bgp_evpn
->vxlan_flood_ctrl
3613 == VXLAN_FLOOD_HEAD_END_REPL
3614 ? "Head-end replication"
3616 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3617 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3619 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3623 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3626 /* Display specific VNI */
3627 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3628 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3632 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3633 json
, JSON_C_TO_STRING_PRETTY
));
3634 json_object_free(json
);
3641 DEFUN(show_bgp_l2vpn_evpn_es
,
3642 show_bgp_l2vpn_evpn_es_cmd
,
3643 "show bgp l2vpn evpn es [ESI] [json]",
3648 "ethernet-Segment\n"
3649 "Ethernet-Segment Identifier\n"
3655 json_object
*json
= NULL
;
3656 struct bgp
*bgp
= NULL
;
3658 memset(&esi
, 0, sizeof(esi
));
3659 uj
= use_json(argc
, argv
);
3661 bgp
= bgp_get_evpn();
3665 if (!argv_find(argv
, argc
, "evpn", &idx
))
3668 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3669 (!uj
&& argc
== (idx
+ 1) + 1)) {
3672 evpn_show_all_es(vty
, bgp
, json
);
3675 /* show a specific ES */
3677 /* get the ESI - ESI-ID is at argv[5] */
3678 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3679 vty_out(vty
, "%% Malformed ESI\n");
3682 evpn_show_es(vty
, bgp
, &esi
, json
);
3686 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3687 json
, JSON_C_TO_STRING_PRETTY
));
3688 json_object_free(json
);
3695 * Display EVPN neighbor summary.
3697 DEFUN(show_bgp_l2vpn_evpn_summary
,
3698 show_bgp_l2vpn_evpn_summary_cmd
,
3699 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3706 "Summary of BGP neighbor status\n"
3707 "Show only sessions not in Established state\n"
3711 bool uj
= use_json(argc
, argv
);
3713 bool show_failed
= false;
3715 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3716 vrf
= argv
[++idx_vrf
]->arg
;
3717 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3719 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3724 * Display global EVPN routing table.
3726 DEFUN(show_bgp_l2vpn_evpn_route
,
3727 show_bgp_l2vpn_evpn_route_cmd
,
3728 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3733 "EVPN route information\n"
3734 "Display Detailed Information\n"
3735 "Specify Route type\n"
3736 "MAC-IP (Type-2) route\n"
3737 "Multicast (Type-3) route\n"
3738 "Ethernet Segment (type-4) route \n"
3739 "Prefix (type-5 )route\n"
3747 json_object
*json
= NULL
;
3749 uj
= use_json(argc
, argv
);
3751 bgp
= bgp_get_evpn();
3756 json
= json_object_new_object();
3759 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3760 /* Specific type is requested */
3761 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3762 type
= BGP_EVPN_MAC_IP_ROUTE
;
3763 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3764 type
= BGP_EVPN_IMET_ROUTE
;
3765 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
3766 type
= BGP_EVPN_ES_ROUTE
;
3767 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
3768 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3773 if (argv_find(argv
, argc
, "detail", &detail
))
3776 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3779 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3780 json
, JSON_C_TO_STRING_PRETTY
));
3781 json_object_free(json
);
3787 * Display global EVPN routing table for specific RD.
3789 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3790 show_bgp_l2vpn_evpn_route_rd_cmd
,
3791 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3796 "EVPN route information\n"
3797 "Route Distinguisher\n"
3798 "ASN:XX or A.B.C.D:XX\n"
3799 "Specify Route type\n"
3800 "MAC-IP (Type-2) route\n"
3801 "Multicast (Type-3) route\n"
3802 "Ethernet Segment route\n"
3808 struct prefix_rd prd
;
3813 json_object
*json
= NULL
;
3815 bgp
= bgp_get_evpn();
3819 /* check if we need json output */
3820 uj
= use_json(argc
, argv
);
3822 json
= json_object_new_object();
3825 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3826 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3829 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3835 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3836 /* Specific type is requested */
3837 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3838 type
= BGP_EVPN_MAC_IP_ROUTE
;
3839 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3840 type
= BGP_EVPN_IMET_ROUTE
;
3841 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3842 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3847 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3850 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3851 json
, JSON_C_TO_STRING_PRETTY
));
3852 json_object_free(json
);
3859 * Display global EVPN routing table for specific RD and MACIP.
3861 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3862 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3863 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3868 "EVPN route information\n"
3869 "Route Distinguisher\n"
3870 "ASN:XX or A.B.C.D:XX\n"
3872 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3874 "IP address (IPv4 or IPv6)\n"
3879 struct prefix_rd prd
;
3886 json_object
*json
= NULL
;
3888 memset(&mac
, 0, sizeof(struct ethaddr
));
3889 memset(&ip
, 0, sizeof(struct ipaddr
));
3891 bgp
= bgp_get_evpn();
3895 /* check if we need json output */
3896 uj
= use_json(argc
, argv
);
3898 json
= json_object_new_object();
3901 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3902 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3904 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3910 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3911 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3912 vty_out(vty
, "%% Malformed MAC address\n");
3917 /* get the ip if specified */
3918 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3919 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3920 vty_out(vty
, "%% Malformed IP address\n");
3925 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3928 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3929 json
, JSON_C_TO_STRING_PRETTY
));
3930 json_object_free(json
);
3936 /* Display per ESI routing table */
3937 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3938 show_bgp_l2vpn_evpn_route_esi_cmd
,
3939 "show bgp l2vpn evpn route esi ESI [json]",
3944 "EVPN route information\n"
3945 "Ethernet Segment Identifier\n"
3951 struct bgp
*bgp
= NULL
;
3952 json_object
*json
= NULL
;
3954 memset(&esi
, 0, sizeof(esi
));
3955 bgp
= bgp_get_evpn();
3959 uj
= use_json(argc
, argv
);
3961 json
= json_object_new_object();
3963 /* get the ESI - ESI-ID is at argv[6] */
3964 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3965 vty_out(vty
, "%% Malformed ESI\n");
3969 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3972 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3973 json
, JSON_C_TO_STRING_PRETTY
));
3974 json_object_free(json
);
3982 * Display per-VNI EVPN routing table.
3984 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3985 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3990 "EVPN route information\n"
3991 "VXLAN Network Identifier\n"
3993 "Specify Route type\n"
3994 "MAC-IP (Type-2) route\n"
3995 "Multicast (Type-3) route\n"
3997 "Remote VTEP IP address\n"
4002 struct in_addr vtep_ip
;
4006 json_object
*json
= NULL
;
4008 bgp
= bgp_get_evpn();
4012 /* check if we need json output */
4013 uj
= use_json(argc
, argv
);
4015 json
= json_object_new_object();
4017 if (!argv_find(argv
, argc
, "evpn", &idx
))
4022 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4024 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4025 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4026 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4027 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4028 type
= BGP_EVPN_MAC_IP_ROUTE
;
4029 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4030 type
= BGP_EVPN_IMET_ROUTE
;
4033 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4034 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4035 vty_out(vty
, "%% Malformed VTEP IP address\n");
4042 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4045 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4046 json
, JSON_C_TO_STRING_PRETTY
));
4047 json_object_free(json
);
4054 * Display per-VNI EVPN routing table for specific MACIP.
4056 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4057 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4058 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4063 "EVPN route information\n"
4064 "VXLAN Network Identifier\n"
4067 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4069 "IP address (IPv4 or IPv6)\n"
4078 json_object
*json
= NULL
;
4080 bgp
= bgp_get_evpn();
4084 /* check if we need json output */
4085 uj
= use_json(argc
, argv
);
4087 json
= json_object_new_object();
4089 if (!argv_find(argv
, argc
, "evpn", &idx
))
4093 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4096 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4097 vty_out(vty
, "%% Malformed MAC address\n");
4102 memset(&ip
, 0, sizeof(ip
));
4103 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4105 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4106 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4107 vty_out(vty
, "%% Malformed IP address\n");
4112 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4115 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4116 json
, JSON_C_TO_STRING_PRETTY
));
4117 json_object_free(json
);
4124 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4126 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4127 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4128 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4133 "EVPN route information\n"
4134 "VXLAN Network Identifier\n"
4136 "Multicast (Type-3) route\n"
4137 "Originating Router IP address\n"
4143 struct in_addr orig_ip
;
4146 json_object
*json
= NULL
;
4148 bgp
= bgp_get_evpn();
4152 /* check if we need json output */
4153 uj
= use_json(argc
, argv
);
4155 json
= json_object_new_object();
4157 if (!argv_find(argv
, argc
, "evpn", &idx
))
4161 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4164 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4166 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4170 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4173 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4174 json
, JSON_C_TO_STRING_PRETTY
));
4175 json_object_free(json
);
4182 * Display per-VNI EVPN routing table - for all VNIs.
4184 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4185 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4186 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4191 "EVPN route information\n"
4192 "VXLAN Network Identifier\n"
4194 "Print Detailed Output\n"
4196 "Remote VTEP IP address\n"
4200 struct in_addr vtep_ip
;
4203 json_object
*json
= NULL
;
4204 /* Detail Adjust. Adjust indexes according to detail option */
4207 bgp
= bgp_get_evpn();
4211 /* check if we need json output */
4212 uj
= use_json(argc
, argv
);
4214 json
= json_object_new_object();
4216 if (!argv_find(argv
, argc
, "evpn", &idx
))
4219 if (argv_find(argv
, argc
, "detail", &da
))
4222 /* vtep-ip position depends on detail option */
4224 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4226 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4227 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4228 vty_out(vty
, "%% Malformed VTEP IP address\n");
4233 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4236 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4237 json
, JSON_C_TO_STRING_PRETTY
));
4238 json_object_free(json
);
4245 * Display EVPN import route-target hash table
4247 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4248 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4249 "show bgp l2vpn evpn vrf-import-rt [json]",
4254 "Show vrf import route target\n"
4258 struct bgp
*bgp_evpn
= NULL
;
4259 json_object
*json
= NULL
;
4261 bgp_evpn
= bgp_get_evpn();
4265 uj
= use_json(argc
, argv
);
4267 json
= json_object_new_object();
4269 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4272 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4273 json
, JSON_C_TO_STRING_PRETTY
));
4274 json_object_free(json
);
4281 * Display EVPN import route-target hash table
4283 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4284 show_bgp_l2vpn_evpn_import_rt_cmd
,
4285 "show bgp l2vpn evpn import-rt [json]",
4290 "Show import route target\n"
4295 json_object
*json
= NULL
;
4297 bgp
= bgp_get_evpn();
4301 uj
= use_json(argc
, argv
);
4303 json
= json_object_new_object();
4305 evpn_show_import_rts(vty
, bgp
, json
);
4308 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4309 json
, JSON_C_TO_STRING_PRETTY
));
4310 json_object_free(json
);
4316 DEFUN(test_adv_evpn_type4_route
,
4317 test_adv_evpn_type4_route_cmd
,
4319 "Advertise EVPN ES route\n"
4320 "Ethernet-segment\n"
4321 "Ethernet-Segment Identifier\n")
4326 struct ipaddr vtep_ip
;
4328 bgp
= bgp_get_evpn();
4330 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4334 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4335 vty_out(vty
, "%%Malformed ESI\n");
4339 vtep_ip
.ipa_type
= IPADDR_V4
;
4340 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4342 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4344 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4350 DEFUN(test_withdraw_evpn_type4_route
,
4351 test_withdraw_evpn_type4_route_cmd
,
4353 "Advertise EVPN ES route\n"
4354 "Ethernet-segment\n"
4355 "Ethernet-Segment Identifier\n")
4360 struct ipaddr vtep_ip
;
4362 bgp
= bgp_get_evpn();
4364 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4368 if (!bgp
->peer_self
) {
4369 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4373 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4374 vty_out(vty
, "%%Malformed ESI\n");
4378 vtep_ip
.ipa_type
= IPADDR_V4
;
4379 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4380 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4382 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4388 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4389 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4393 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4394 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4395 "Summary of BGP neighbor status\n" JSON_STR
)
4397 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4398 "show bgp evpn route [detail] [type <macip|multicast>]",
4399 SHOW_STR BGP_STR EVPN_HELP_STR
4400 "EVPN route information\n"
4401 "Display Detailed Information\n"
4402 "Specify Route type\n"
4403 "MAC-IP (Type-2) route\n"
4404 "Multicast (Type-3) route\n")
4407 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4408 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4409 SHOW_STR BGP_STR EVPN_HELP_STR
4410 "EVPN route information\n"
4411 "Route Distinguisher\n"
4412 "ASN:XX or A.B.C.D:XX\n"
4413 "Specify Route type\n"
4414 "MAC-IP (Type-2) route\n"
4415 "Multicast (Type-3) route\n")
4418 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4419 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4420 SHOW_STR BGP_STR EVPN_HELP_STR
4421 "EVPN route information\n"
4422 "Route Distinguisher\n"
4423 "ASN:XX or A.B.C.D:XX\n"
4425 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4427 "IP address (IPv4 or IPv6)\n")
4430 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4431 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4432 SHOW_STR BGP_STR EVPN_HELP_STR
4433 "EVPN route information\n"
4434 "VXLAN Network Identifier\n"
4436 "Specify Route type\n"
4437 "MAC-IP (Type-2) route\n"
4438 "Multicast (Type-3) route\n"
4440 "Remote VTEP IP address\n")
4442 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4443 show_bgp_evpn_route_vni_macip_cmd
,
4444 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4445 SHOW_STR BGP_STR EVPN_HELP_STR
4446 "EVPN route information\n"
4447 "VXLAN Network Identifier\n"
4450 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4452 "IP address (IPv4 or IPv6)\n")
4454 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4455 show_bgp_evpn_route_vni_multicast_cmd
,
4456 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4457 SHOW_STR BGP_STR EVPN_HELP_STR
4458 "EVPN route information\n"
4459 "VXLAN Network Identifier\n"
4461 "Multicast (Type-3) route\n"
4462 "Originating Router IP address\n")
4464 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4465 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4466 SHOW_STR BGP_STR EVPN_HELP_STR
4467 "EVPN route information\n"
4468 "VXLAN Network Identifier\n"
4470 "Print Detailed Output\n"
4472 "Remote VTEP IP address\n")
4474 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4475 "show bgp evpn import-rt",
4476 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4478 DEFUN_NOSH (bgp_evpn_vni
,
4480 "vni " CMD_VNI_RANGE
,
4481 "VXLAN Network Identifier\n"
4485 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4486 struct bgpevpn
*vpn
;
4491 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4493 /* Create VNI, or mark as configured. */
4494 vpn
= evpn_create_update_vni(bgp
, vni
);
4496 vty_out(vty
, "%% Failed to create VNI \n");
4500 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4504 DEFUN (no_bgp_evpn_vni
,
4505 no_bgp_evpn_vni_cmd
,
4506 "no vni " CMD_VNI_RANGE
,
4508 "VXLAN Network Identifier\n"
4512 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4513 struct bgpevpn
*vpn
;
4518 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4520 /* Check if we should disallow. */
4521 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4523 vty_out(vty
, "%% Specified VNI does not exist\n");
4526 if (!is_vni_configured(vpn
)) {
4527 vty_out(vty
, "%% Specified VNI is not configured\n");
4531 evpn_delete_vni(bgp
, vpn
);
4535 DEFUN_NOSH (exit_vni
,
4538 "Exit from VNI mode\n")
4540 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4541 vty
->node
= BGP_EVPN_NODE
;
4545 DEFUN (bgp_evpn_vrf_rd
,
4546 bgp_evpn_vrf_rd_cmd
,
4547 "rd ASN:NN_OR_IP-ADDRESS:NN",
4548 "Route Distinguisher\n"
4549 "ASN:XX or A.B.C.D:XX\n")
4552 struct prefix_rd prd
;
4553 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4558 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4560 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4564 /* If same as existing value, there is nothing more to do. */
4565 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4568 /* Configure or update the RD. */
4569 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4573 DEFUN (no_bgp_evpn_vrf_rd
,
4574 no_bgp_evpn_vrf_rd_cmd
,
4575 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4577 "Route Distinguisher\n"
4578 "ASN:XX or A.B.C.D:XX\n")
4581 struct prefix_rd prd
;
4582 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4587 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4589 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4593 /* Check if we should disallow. */
4594 if (!is_vrf_rd_configured(bgp_vrf
)) {
4595 vty_out(vty
, "%% RD is not configured for this VRF\n");
4599 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4601 "%% RD specified does not match configuration for this VRF\n");
4605 evpn_unconfigure_vrf_rd(bgp_vrf
);
4609 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4610 no_bgp_evpn_vrf_rd_without_val_cmd
,
4613 "Route Distinguisher\n")
4615 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4620 /* Check if we should disallow. */
4621 if (!is_vrf_rd_configured(bgp_vrf
)) {
4622 vty_out(vty
, "%% RD is not configured for this VRF\n");
4626 evpn_unconfigure_vrf_rd(bgp_vrf
);
4630 DEFUN (bgp_evpn_vni_rd
,
4631 bgp_evpn_vni_rd_cmd
,
4632 "rd ASN:NN_OR_IP-ADDRESS:NN",
4633 "Route Distinguisher\n"
4634 "ASN:XX or A.B.C.D:XX\n")
4636 struct prefix_rd prd
;
4637 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4638 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4644 if (!EVPN_ENABLED(bgp
)) {
4646 "This command is only supported under EVPN VRF\n");
4650 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4652 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4656 /* If same as existing value, there is nothing more to do. */
4657 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4660 /* Configure or update the RD. */
4661 evpn_configure_rd(bgp
, vpn
, &prd
);
4665 DEFUN (no_bgp_evpn_vni_rd
,
4666 no_bgp_evpn_vni_rd_cmd
,
4667 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4669 "Route Distinguisher\n"
4670 "ASN:XX or A.B.C.D:XX\n")
4672 struct prefix_rd prd
;
4673 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4674 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4680 if (!EVPN_ENABLED(bgp
)) {
4682 "This command is only supported under EVPN VRF\n");
4686 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4688 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4692 /* Check if we should disallow. */
4693 if (!is_rd_configured(vpn
)) {
4694 vty_out(vty
, "%% RD is not configured for this VNI\n");
4698 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4700 "%% RD specified does not match configuration for this VNI\n");
4704 evpn_unconfigure_rd(bgp
, vpn
);
4708 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4709 no_bgp_evpn_vni_rd_without_val_cmd
,
4712 "Route Distinguisher\n")
4714 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4715 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4720 if (!EVPN_ENABLED(bgp
)) {
4722 "This command is only supported under EVPN VRF\n");
4726 /* Check if we should disallow. */
4727 if (!is_rd_configured(vpn
)) {
4728 vty_out(vty
, "%% RD is not configured for this VNI\n");
4732 evpn_unconfigure_rd(bgp
, vpn
);
4737 * Loop over all extended-communities in the route-target list rtl and
4738 * return 1 if we find ecomtarget
4740 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4741 struct ecommunity
*ecomtarget
)
4743 struct listnode
*node
, *nnode
;
4744 struct ecommunity
*ecom
;
4746 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4747 if (ecommunity_match(ecom
, ecomtarget
))
4754 /* display L3VNI related info for a VRF instance */
4755 DEFUN (show_bgp_vrf_l3vni_info
,
4756 show_bgp_vrf_l3vni_info_cmd
,
4757 "show bgp vrf VRFNAME vni [json]",
4765 char buf
[ETHER_ADDR_STRLEN
];
4766 char buf1
[INET6_ADDRSTRLEN
];
4768 const char *name
= NULL
;
4769 struct bgp
*bgp
= NULL
;
4770 struct listnode
*node
= NULL
;
4771 struct bgpevpn
*vpn
= NULL
;
4772 struct ecommunity
*ecom
= NULL
;
4773 json_object
*json
= NULL
;
4774 json_object
*json_vnis
= NULL
;
4775 json_object
*json_export_rts
= NULL
;
4776 json_object
*json_import_rts
= NULL
;
4777 bool uj
= use_json(argc
, argv
);
4780 json
= json_object_new_object();
4781 json_vnis
= json_object_new_array();
4782 json_export_rts
= json_object_new_array();
4783 json_import_rts
= json_object_new_array();
4786 name
= argv
[idx_vrf
]->arg
;
4787 bgp
= bgp_lookup_by_name(name
);
4790 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4792 json_object_string_add(json
, "warning",
4793 "BGP instance not found");
4794 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4795 json_object_free(json
);
4801 vty_out(vty
, "BGP VRF: %s\n", name
);
4802 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4803 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4804 vty_out(vty
, " Rmac: %s\n",
4805 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4806 vty_out(vty
, " VNI Filter: %s\n",
4807 CHECK_FLAG(bgp
->vrf_flags
,
4808 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4809 ? "prefix-routes-only"
4811 vty_out(vty
, " L2-VNI List:\n");
4813 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4814 vty_out(vty
, "%u ", vpn
->vni
);
4816 vty_out(vty
, " Export-RTs:\n");
4818 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4819 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4821 vty_out(vty
, " Import-RTs:\n");
4823 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4824 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4826 vty_out(vty
, " RD: %s\n",
4827 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4829 json_object_string_add(json
, "vrf", name
);
4830 json_object_string_add(json
, "local-ip",
4831 inet_ntoa(bgp
->originator_ip
));
4832 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4833 json_object_string_add(
4835 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4836 json_object_string_add(
4838 CHECK_FLAG(bgp
->vrf_flags
,
4839 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4840 ? "prefix-routes-only"
4842 /* list of l2vnis */
4843 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4844 json_object_array_add(json_vnis
,
4845 json_object_new_int(vpn
->vni
));
4846 json_object_object_add(json
, "l2vnis", json_vnis
);
4849 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4850 json_object_array_add(
4852 json_object_new_string(ecommunity_str(ecom
)));
4853 json_object_object_add(json
, "export-rts", json_export_rts
);
4856 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4857 json_object_array_add(
4859 json_object_new_string(ecommunity_str(ecom
)));
4860 json_object_object_add(json
, "import-rts", json_import_rts
);
4861 json_object_string_add(
4863 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4867 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4868 json
, JSON_C_TO_STRING_PRETTY
));
4869 json_object_free(json
);
4874 /* import/export rt for l3vni-vrf */
4875 DEFUN (bgp_evpn_vrf_rt
,
4876 bgp_evpn_vrf_rt_cmd
,
4877 "route-target <both|import|export> RT",
4879 "import and export\n"
4882 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4885 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4886 struct ecommunity
*ecomadd
= NULL
;
4891 if (!strcmp(argv
[1]->arg
, "import"))
4892 rt_type
= RT_TYPE_IMPORT
;
4893 else if (!strcmp(argv
[1]->arg
, "export"))
4894 rt_type
= RT_TYPE_EXPORT
;
4895 else if (!strcmp(argv
[1]->arg
, "both"))
4896 rt_type
= RT_TYPE_BOTH
;
4898 vty_out(vty
, "%% Invalid Route Target type\n");
4902 /* Add/update the import route-target */
4903 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4904 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4905 ECOMMUNITY_ROUTE_TARGET
, 0);
4907 vty_out(vty
, "%% Malformed Route Target list\n");
4910 ecommunity_str(ecomadd
);
4912 /* Do nothing if we already have this import route-target */
4913 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4914 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4917 /* Add/update the export route-target */
4918 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4919 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4920 ECOMMUNITY_ROUTE_TARGET
, 0);
4922 vty_out(vty
, "%% Malformed Route Target list\n");
4925 ecommunity_str(ecomadd
);
4927 /* Do nothing if we already have this export route-target */
4928 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4929 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4935 DEFUN (no_bgp_evpn_vrf_rt
,
4936 no_bgp_evpn_vrf_rt_cmd
,
4937 "no route-target <both|import|export> RT",
4940 "import and export\n"
4943 "ASN:XX or A.B.C.D:XX\n")
4945 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4946 int rt_type
, found_ecomdel
;
4947 struct ecommunity
*ecomdel
= NULL
;
4952 if (!strcmp(argv
[2]->arg
, "import"))
4953 rt_type
= RT_TYPE_IMPORT
;
4954 else if (!strcmp(argv
[2]->arg
, "export"))
4955 rt_type
= RT_TYPE_EXPORT
;
4956 else if (!strcmp(argv
[2]->arg
, "both"))
4957 rt_type
= RT_TYPE_BOTH
;
4959 vty_out(vty
, "%% Invalid Route Target type\n");
4963 if (rt_type
== RT_TYPE_IMPORT
) {
4964 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4966 "%% Import RT is not configured for this VRF\n");
4969 } else if (rt_type
== RT_TYPE_EXPORT
) {
4970 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4972 "%% Export RT is not configured for this VRF\n");
4975 } else if (rt_type
== RT_TYPE_BOTH
) {
4976 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4977 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4979 "%% Import/Export RT is not configured for this VRF\n");
4984 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4986 vty_out(vty
, "%% Malformed Route Target list\n");
4989 ecommunity_str(ecomdel
);
4991 if (rt_type
== RT_TYPE_IMPORT
) {
4992 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4995 "%% RT specified does not match configuration for this VRF\n");
4998 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4999 } else if (rt_type
== RT_TYPE_EXPORT
) {
5000 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5003 "%% RT specified does not match configuration for this VRF\n");
5006 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5007 } else if (rt_type
== RT_TYPE_BOTH
) {
5010 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5012 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5016 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5018 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5022 if (!found_ecomdel
) {
5024 "%% RT specified does not match configuration for this VRF\n");
5032 DEFUN (bgp_evpn_vni_rt
,
5033 bgp_evpn_vni_rt_cmd
,
5034 "route-target <both|import|export> RT",
5036 "import and export\n"
5039 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5041 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5042 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5044 struct ecommunity
*ecomadd
= NULL
;
5049 if (!EVPN_ENABLED(bgp
)) {
5051 "This command is only supported under EVPN VRF\n");
5055 if (!strcmp(argv
[1]->text
, "import"))
5056 rt_type
= RT_TYPE_IMPORT
;
5057 else if (!strcmp(argv
[1]->text
, "export"))
5058 rt_type
= RT_TYPE_EXPORT
;
5059 else if (!strcmp(argv
[1]->text
, "both"))
5060 rt_type
= RT_TYPE_BOTH
;
5062 vty_out(vty
, "%% Invalid Route Target type\n");
5066 /* Add/update the import route-target */
5067 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5068 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5069 ECOMMUNITY_ROUTE_TARGET
, 0);
5071 vty_out(vty
, "%% Malformed Route Target list\n");
5074 ecommunity_str(ecomadd
);
5076 /* Do nothing if we already have this import route-target */
5077 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5078 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5081 /* Add/update the export route-target */
5082 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5083 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5084 ECOMMUNITY_ROUTE_TARGET
, 0);
5086 vty_out(vty
, "%% Malformed Route Target list\n");
5089 ecommunity_str(ecomadd
);
5091 /* Do nothing if we already have this export route-target */
5092 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5093 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5099 DEFUN (no_bgp_evpn_vni_rt
,
5100 no_bgp_evpn_vni_rt_cmd
,
5101 "no route-target <both|import|export> RT",
5104 "import and export\n"
5107 "ASN:XX or A.B.C.D:XX\n")
5109 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5110 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5111 int rt_type
, found_ecomdel
;
5112 struct ecommunity
*ecomdel
= NULL
;
5117 if (!EVPN_ENABLED(bgp
)) {
5119 "This command is only supported under EVPN VRF\n");
5123 if (!strcmp(argv
[2]->text
, "import"))
5124 rt_type
= RT_TYPE_IMPORT
;
5125 else if (!strcmp(argv
[2]->text
, "export"))
5126 rt_type
= RT_TYPE_EXPORT
;
5127 else if (!strcmp(argv
[2]->text
, "both"))
5128 rt_type
= RT_TYPE_BOTH
;
5130 vty_out(vty
, "%% Invalid Route Target type\n");
5134 /* The user did "no route-target import", check to see if there are any
5135 * import route-targets configured. */
5136 if (rt_type
== RT_TYPE_IMPORT
) {
5137 if (!is_import_rt_configured(vpn
)) {
5139 "%% Import RT is not configured for this VNI\n");
5142 } else if (rt_type
== RT_TYPE_EXPORT
) {
5143 if (!is_export_rt_configured(vpn
)) {
5145 "%% Export RT is not configured for this VNI\n");
5148 } else if (rt_type
== RT_TYPE_BOTH
) {
5149 if (!is_import_rt_configured(vpn
)
5150 && !is_export_rt_configured(vpn
)) {
5152 "%% Import/Export RT is not configured for this VNI\n");
5157 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5159 vty_out(vty
, "%% Malformed Route Target list\n");
5162 ecommunity_str(ecomdel
);
5164 if (rt_type
== RT_TYPE_IMPORT
) {
5165 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5167 "%% RT specified does not match configuration for this VNI\n");
5170 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5171 } else if (rt_type
== RT_TYPE_EXPORT
) {
5172 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5174 "%% RT specified does not match configuration for this VNI\n");
5177 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5178 } else if (rt_type
== RT_TYPE_BOTH
) {
5181 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5182 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5186 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5187 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5191 if (!found_ecomdel
) {
5193 "%% RT specified does not match configuration for this VNI\n");
5201 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5202 no_bgp_evpn_vni_rt_without_val_cmd
,
5203 "no route-target <import|export>",
5209 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5210 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5216 if (!EVPN_ENABLED(bgp
)) {
5218 "This command is only supported under EVPN VRF\n");
5222 if (!strcmp(argv
[2]->text
, "import")) {
5223 rt_type
= RT_TYPE_IMPORT
;
5224 } else if (!strcmp(argv
[2]->text
, "export")) {
5225 rt_type
= RT_TYPE_EXPORT
;
5227 vty_out(vty
, "%% Invalid Route Target type\n");
5231 /* Check if we should disallow. */
5232 if (rt_type
== RT_TYPE_IMPORT
) {
5233 if (!is_import_rt_configured(vpn
)) {
5235 "%% Import RT is not configured for this VNI\n");
5239 if (!is_export_rt_configured(vpn
)) {
5241 "%% Export RT is not configured for this VNI\n");
5246 /* Unconfigure the RT. */
5247 if (rt_type
== RT_TYPE_IMPORT
)
5248 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5250 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5254 static int vni_cmp(const void **a
, const void **b
)
5256 const struct bgpevpn
*first
= *a
;
5257 const struct bgpevpn
*secnd
= *b
;
5259 return secnd
->vni
- first
->vni
;
5263 * Output EVPN configuration information.
5265 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5268 char buf1
[RD_ADDRSTRLEN
];
5271 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5272 struct listnode
*ln
;
5273 struct bgpevpn
*data
;
5275 list_sort(vnilist
, vni_cmp
);
5276 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5277 write_vni_config(vty
, data
);
5279 list_delete(&vnilist
);
5282 if (bgp
->advertise_all_vni
)
5283 vty_out(vty
, " advertise-all-vni\n");
5285 if (bgp
->advertise_autort_rfc8365
)
5286 vty_out(vty
, " autort rfc8365-compatible\n");
5288 if (bgp
->advertise_gw_macip
)
5289 vty_out(vty
, " advertise-default-gw\n");
5291 if (bgp
->evpn_info
->advertise_svi_macip
)
5292 vty_out(vty
, " advertise-svi-ip\n");
5294 if (!bgp
->evpn_info
->dup_addr_detect
)
5295 vty_out(vty
, " no dup-addr-detection\n");
5297 if (bgp
->evpn_info
->dad_max_moves
!=
5298 EVPN_DAD_DEFAULT_MAX_MOVES
||
5299 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5300 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5301 bgp
->evpn_info
->dad_max_moves
,
5302 bgp
->evpn_info
->dad_time
);
5304 if (bgp
->evpn_info
->dad_freeze
) {
5305 if (bgp
->evpn_info
->dad_freeze_time
)
5307 " dup-addr-detection freeze %u\n",
5308 bgp
->evpn_info
->dad_freeze_time
);
5311 " dup-addr-detection freeze permanent\n");
5314 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5315 vty_out(vty
, " flooding disable\n");
5317 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5318 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5319 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5320 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5321 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5323 vty_out(vty
, " advertise ipv4 unicast\n");
5326 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5327 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5328 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5329 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5330 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5332 vty_out(vty
, " advertise ipv6 unicast\n");
5335 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5336 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5337 vty_out(vty
, " default-originate ipv4\n");
5339 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5340 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5341 vty_out(vty
, " default-originate ipv6\n");
5343 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5344 vty_out(vty
, " rd %s\n",
5345 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5347 /* import route-target */
5348 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5350 struct listnode
*node
, *nnode
;
5351 struct ecommunity
*ecom
;
5353 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5355 ecom_str
= ecommunity_ecom2str(
5356 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5357 vty_out(vty
, " route-target import %s\n", ecom_str
);
5358 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5362 /* export route-target */
5363 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5365 struct listnode
*node
, *nnode
;
5366 struct ecommunity
*ecom
;
5368 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5370 ecom_str
= ecommunity_ecom2str(
5371 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5372 vty_out(vty
, " route-target export %s\n", ecom_str
);
5373 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5378 void bgp_ethernetvpn_init(void)
5380 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5381 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5382 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5383 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5384 install_element(VIEW_NODE
,
5385 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5386 install_element(VIEW_NODE
,
5387 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5390 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5393 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5394 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5395 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5396 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5397 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5398 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5399 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5400 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5401 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5402 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5403 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5404 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5405 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5406 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5407 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5408 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5409 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5410 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5411 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5412 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5415 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5416 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5418 /* "show bgp l2vpn evpn" commands. */
5419 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5420 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5421 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5422 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5423 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5424 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5425 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5426 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5427 install_element(VIEW_NODE
,
5428 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5429 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5430 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5431 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5432 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5434 /* "show bgp evpn" commands. */
5435 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5436 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5437 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5438 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5439 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5440 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5441 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5442 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5443 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5444 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5445 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5447 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5448 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5449 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5450 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5451 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5452 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5453 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5454 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5455 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5456 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5457 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5458 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5459 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5460 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5461 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5462 install_element(BGP_EVPN_VNI_NODE
,
5463 &bgp_evpn_advertise_default_gw_vni_cmd
);
5464 install_element(BGP_EVPN_VNI_NODE
,
5465 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5466 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5467 install_element(BGP_EVPN_VNI_NODE
,
5468 &no_bgp_evpn_advertise_vni_subnet_cmd
);