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"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
49 * Context for VNI hash walk - used by callbacks.
54 struct in_addr vtep_ip
;
59 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
63 uint8_t type
, sub_type
;
64 struct ecommunity_as eas
;
65 struct ecommunity_ip eip
;
66 struct listnode
*node
, *nnode
;
67 struct bgp
*tmp_bgp_vrf
= NULL
;
68 json_object
*json_rt
= NULL
;
69 json_object
*json_vrfs
= NULL
;
70 char rt_buf
[RT_ADDRSTRLEN
];
73 json_rt
= json_object_new_object();
74 json_vrfs
= json_object_new_array();
77 pnt
= (uint8_t *)&irt
->rt
.val
;
80 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
83 memset(&eas
, 0, sizeof(eas
));
85 case ECOMMUNITY_ENCODE_AS
:
86 eas
.as
= (*pnt
++ << 8);
88 ptr_get_be32(pnt
, &eas
.val
);
90 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
93 json_object_string_add(json_rt
, "rt", rt_buf
);
95 vty_out(vty
, "Route-target: %s", rt_buf
);
99 case ECOMMUNITY_ENCODE_IP
:
100 memcpy(&eip
.ip
, pnt
, 4);
102 eip
.val
= (*pnt
++ << 8);
105 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
109 json_object_string_add(json_rt
, "rt", rt_buf
);
111 vty_out(vty
, "Route-target: %s", rt_buf
);
115 case ECOMMUNITY_ENCODE_AS4
:
116 pnt
= ptr_get_be32(pnt
, &eas
.val
);
117 eas
.val
= (*pnt
++ << 8);
120 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
123 json_object_string_add(json_rt
, "rt", rt_buf
);
125 vty_out(vty
, "Route-target: %s", rt_buf
);
135 "\nList of VRFs importing routes with this route-target:\n");
138 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
140 json_object_array_add(
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
145 vty_out(vty
, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
150 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
151 json_object_object_add(json
, rt_buf
, json_rt
);
155 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 uint8_t type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (uint8_t *)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
219 json_object_string_add(json_rt
, "rt", rt_buf
);
221 vty_out(vty
, "Route-target: %s", rt_buf
);
225 case ECOMMUNITY_ENCODE_AS4
:
226 pnt
= ptr_get_be32(pnt
, &eas
.val
);
227 eas
.val
= (*pnt
++ << 8);
230 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
233 json_object_string_add(json_rt
, "rt", rt_buf
);
235 vty_out(vty
, "Route-target: %s", rt_buf
);
245 "\nList of VNIs importing routes with this route-target:\n");
248 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
250 json_object_array_add(
251 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
253 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
257 json_object_object_add(json_rt
, "vnis", json_vnis
);
258 json_object_object_add(json
, rt_buf
, json_rt
);
262 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
264 json_object
*json
= NULL
;
265 struct vty
*vty
= NULL
;
266 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
271 display_import_rt(vty
, irt
, json
);
276 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
277 struct bgp_node
*rd_rn
,
284 char rd_str
[RD_ADDRSTRLEN
];
286 pnt
= rd_rn
->p
.u
.val
;
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
294 vty_out(vty
, "Route Distinguisher: ");
298 decode_rd_as(pnt
+ 2, &rd_as
);
299 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
303 decode_rd_ip(pnt
+ 2, &rd_ip
);
304 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
309 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
313 vty_out(vty
, "%s\n", rd_str
);
316 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
317 uint64_t tbl_ver
, json_object
*json
)
320 " Network Next Hop Metric LocPrf Weight Path\n";
325 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
326 tbl_ver
, inet_ntoa(bgp
->router_id
));
328 "Status codes: s suppressed, d damped, h history, "
329 "* valid, > best, i - internal\n");
330 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
332 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
333 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
334 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
335 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
336 vty_out(vty
, "%s", ri_header
);
339 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
342 char buf1
[INET6_ADDRSTRLEN
];
344 struct listnode
*node
, *nnode
;
345 struct ecommunity
*ecom
;
346 json_object
*json_import_rtl
= NULL
;
347 json_object
*json_export_rtl
= NULL
;
349 json_import_rtl
= json_export_rtl
= 0;
352 json_import_rtl
= json_object_new_array();
353 json_export_rtl
= json_object_new_array();
354 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
355 json_object_string_add(json
, "type", "L3");
356 json_object_string_add(json
, "kernelFlag", "Yes");
357 json_object_string_add(
359 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
360 json_object_string_add(json
, "originatorIp",
361 inet_ntoa(bgp_vrf
->originator_ip
));
362 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
364 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
365 vty_out(vty
, " (known to the kernel)");
368 vty_out(vty
, " Type: %s\n", "L3");
369 vty_out(vty
, " Tenant VRF: %s\n",
370 vrf_id_to_name(bgp_vrf
->vrf_id
));
371 vty_out(vty
, " RD: %s\n",
372 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
373 vty_out(vty
, " Originator IP: %s\n",
374 inet_ntoa(bgp_vrf
->originator_ip
));
375 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
379 vty_out(vty
, " Import Route Target:\n");
381 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
382 ecom_str
= ecommunity_ecom2str(ecom
,
383 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
386 json_object_array_add(json_import_rtl
,
387 json_object_new_string(ecom_str
));
389 vty_out(vty
, " %s\n", ecom_str
);
391 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
395 json_object_object_add(json
, "importRts", json_import_rtl
);
397 vty_out(vty
, " Export Route Target:\n");
399 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
400 ecom_str
= ecommunity_ecom2str(ecom
,
401 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
404 json_object_array_add(json_export_rtl
,
405 json_object_new_string(ecom_str
));
407 vty_out(vty
, " %s\n", ecom_str
);
409 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
413 json_object_object_add(json
, "exportRts", json_export_rtl
);
416 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
418 struct in_addr
*vtep
;
419 char buf
[ESI_STR_LEN
];
420 char buf1
[RD_ADDRSTRLEN
];
421 char buf2
[INET6_ADDRSTRLEN
];
422 struct listnode
*node
= NULL
;
423 json_object
*json_vteps
= NULL
;
426 json_vteps
= json_object_new_array();
427 json_object_string_add(json
, "esi",
428 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
429 json_object_string_add(json
, "rd",
430 prefix_rd2str(&es
->prd
, buf1
,
432 json_object_string_add(
433 json
, "originatorIp",
434 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
436 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
437 json_object_array_add(
438 json_vteps
, json_object_new_string(
441 json_object_object_add(json
, "vteps", json_vteps
);
443 vty_out(vty
, "ESI: %s\n",
444 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
445 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
447 vty_out(vty
, " Originator-IP: %s\n",
448 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
450 vty_out(vty
, " VTEP List:\n");
451 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
452 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
457 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
459 char buf1
[RD_ADDRSTRLEN
];
461 struct listnode
*node
, *nnode
;
462 struct ecommunity
*ecom
;
463 json_object
*json_import_rtl
= NULL
;
464 json_object
*json_export_rtl
= NULL
;
467 json_import_rtl
= json_object_new_array();
468 json_export_rtl
= json_object_new_array();
469 json_object_int_add(json
, "vni", vpn
->vni
);
470 json_object_string_add(json
, "type", "L2");
471 json_object_string_add(json
, "kernelFlag",
472 is_vni_live(vpn
) ? "Yes" : "No");
473 json_object_string_add(
475 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
476 json_object_string_add(json
, "originatorIp",
477 inet_ntoa(vpn
->originator_ip
));
478 json_object_string_add(json
, "mcastGroup",
479 inet_ntoa(vpn
->mcast_grp
));
480 json_object_string_add(json
, "advertiseGatewayMacip",
481 vpn
->advertise_gw_macip
? "Yes" : "No");
483 vty_out(vty
, "VNI: %d", vpn
->vni
);
484 if (is_vni_live(vpn
))
485 vty_out(vty
, " (known to the kernel)");
488 vty_out(vty
, " Type: %s\n", "L2");
489 vty_out(vty
, " Tenant-Vrf: %s\n",
490 vrf_id_to_name(vpn
->tenant_vrf_id
));
491 vty_out(vty
, " RD: %s\n",
492 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
493 vty_out(vty
, " Originator IP: %s\n",
494 inet_ntoa(vpn
->originator_ip
));
495 vty_out(vty
, " Mcast group: %s\n",
496 inet_ntoa(vpn
->mcast_grp
));
497 vty_out(vty
, " Advertise-gw-macip : %s\n",
498 vpn
->advertise_gw_macip
? "Yes" : "No");
499 vty_out(vty
, " Advertise-svi-macip : %s\n",
500 vpn
->advertise_svi_macip
? "Yes" : "No");
504 vty_out(vty
, " Import Route Target:\n");
506 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
507 ecom_str
= ecommunity_ecom2str(ecom
,
508 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
511 json_object_array_add(json_import_rtl
,
512 json_object_new_string(ecom_str
));
514 vty_out(vty
, " %s\n", ecom_str
);
516 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
520 json_object_object_add(json
, "importRts", json_import_rtl
);
522 vty_out(vty
, " Export Route Target:\n");
524 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
525 ecom_str
= ecommunity_ecom2str(ecom
,
526 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
529 json_object_array_add(json_export_rtl
,
530 json_object_new_string(ecom_str
));
532 vty_out(vty
, " %s\n", ecom_str
);
534 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
538 json_object_object_add(json
, "exportRts", json_export_rtl
);
541 static void show_esi_routes(struct bgp
*bgp
,
548 struct bgp_path_info
*pi
;
549 uint32_t prefix_cnt
, path_cnt
;
552 prefix_cnt
= path_cnt
= 0;
554 tbl_ver
= es
->route_table
->version
;
555 for (rn
= bgp_table_top(es
->route_table
); rn
;
556 rn
= bgp_route_next(rn
)) {
557 int add_prefix_to_json
= 0;
558 char prefix_str
[BUFSIZ
];
559 json_object
*json_paths
= NULL
;
560 json_object
*json_prefix
= NULL
;
562 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
566 json_prefix
= json_object_new_object();
568 pi
= bgp_node_get_bgp_path_info(rn
);
570 /* Overall header/legend displayed once. */
572 bgp_evpn_show_route_header(vty
, bgp
,
581 json_paths
= json_object_new_array();
583 /* For EVPN, the prefix is displayed for each path (to fit in
584 * with code that already exists).
586 for (; pi
; pi
= pi
->next
) {
587 json_object
*json_path
= NULL
;
590 json_path
= json_object_new_array();
592 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
595 json_object_array_add(json_paths
, json_path
);
598 add_prefix_to_json
= 1;
601 if (json
&& add_prefix_to_json
) {
602 json_object_string_add(json_prefix
, "prefix",
604 json_object_int_add(json_prefix
, "prefixLen",
606 json_object_object_add(json_prefix
, "paths",
608 json_object_object_add(json
, prefix_str
, json_prefix
);
613 json_object_int_add(json
, "numPrefix", prefix_cnt
);
614 json_object_int_add(json
, "numPaths", path_cnt
);
617 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
619 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
620 prefix_cnt
, path_cnt
);
624 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
625 struct vty
*vty
, struct in_addr vtep_ip
,
626 json_object
*json
, int detail
)
629 struct bgp_path_info
*pi
;
630 struct bgp_table
*table
;
631 int header
= detail
? 0 : 1;
633 uint32_t prefix_cnt
, path_cnt
;
635 prefix_cnt
= path_cnt
= 0;
637 table
= vpn
->route_table
;
638 tbl_ver
= table
->version
;
639 for (rn
= bgp_table_top(table
); rn
;
640 rn
= bgp_route_next(rn
)) {
641 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
642 int add_prefix_to_json
= 0;
643 char prefix_str
[BUFSIZ
];
644 json_object
*json_paths
= NULL
;
645 json_object
*json_prefix
= NULL
;
647 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
650 if (type
&& evp
->prefix
.route_type
!= type
)
654 json_prefix
= json_object_new_object();
656 pi
= bgp_node_get_bgp_path_info(rn
);
658 /* Overall header/legend displayed once. */
660 bgp_evpn_show_route_header(vty
, bgp
,
669 json_paths
= json_object_new_array();
671 /* For EVPN, the prefix is displayed for each path (to fit in
672 * with code that already exists).
674 for (; pi
; pi
= pi
->next
) {
675 json_object
*json_path
= NULL
;
678 && !IPV4_ADDR_SAME(&(vtep_ip
),
679 &(pi
->attr
->nexthop
)))
683 json_path
= json_object_new_array();
686 route_vty_out_detail(vty
, bgp
, rn
, pi
,
687 AFI_L2VPN
, SAFI_EVPN
,
690 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
694 json_object_array_add(json_paths
, json_path
);
697 add_prefix_to_json
= 1;
700 if (json
&& add_prefix_to_json
) {
701 json_object_string_add(json_prefix
, "prefix",
703 json_object_int_add(json_prefix
, "prefixLen",
705 json_object_object_add(json_prefix
, "paths",
707 json_object_object_add(json
, prefix_str
, json_prefix
);
712 json_object_int_add(json
, "numPrefix", prefix_cnt
);
713 json_object_int_add(json
, "numPaths", path_cnt
);
716 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
717 type
? "(of requested type) " : "");
719 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
720 prefix_cnt
, path_cnt
,
721 type
? " (of requested type)" : "");
726 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
728 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
729 struct vni_walk_ctx
*wctx
= arg
;
730 struct vty
*vty
= wctx
->vty
;
731 json_object
*json
= wctx
->json
;
732 json_object
*json_vni
= NULL
;
733 char vni_str
[VNI_STR_LEN
];
735 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
737 json_vni
= json_object_new_object();
738 json_object_int_add(json_vni
, "vni", vpn
->vni
);
740 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
743 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
747 json_object_object_add(json
, vni_str
, json_vni
);
750 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
753 json_object
*json_vni
= NULL
;
754 json_object
*json_import_rtl
= NULL
;
755 json_object
*json_export_rtl
= NULL
;
757 char buf2
[INET6_ADDRSTRLEN
];
760 struct listnode
*node
, *nnode
;
761 struct ecommunity
*ecom
;
767 json_vni
= json_object_new_object();
768 json_import_rtl
= json_object_new_array();
769 json_export_rtl
= json_object_new_array();
772 /* if an l3vni is present in bgp it is live */
777 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
778 json_object_string_add(json_vni
, "type", "L3");
779 json_object_string_add(json_vni
, "inKernel", "True");
780 json_object_string_add(json_vni
, "originatorIp",
781 inet_ntoa(bgp
->originator_ip
));
782 json_object_string_add(
784 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
786 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
787 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
790 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
791 ecom_str
= ecommunity_ecom2str(ecom
,
792 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
795 json_object_array_add(json_import_rtl
,
796 json_object_new_string(ecom_str
));
798 if (listcount(bgp
->vrf_import_rtl
) > 1)
799 sprintf(rt_buf
, "%s, ...", ecom_str
);
801 sprintf(rt_buf
, "%s", ecom_str
);
802 vty_out(vty
, " %-25s", rt_buf
);
805 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
807 /* If there are multiple import RTs we break here and show only
814 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
816 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
817 ecom_str
= ecommunity_ecom2str(ecom
,
818 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
821 json_object_array_add(json_export_rtl
,
822 json_object_new_string(ecom_str
));
824 if (listcount(bgp
->vrf_export_rtl
) > 1)
825 sprintf(rt_buf
, "%s, ...", ecom_str
);
827 sprintf(rt_buf
, "%s", ecom_str
);
828 vty_out(vty
, " %-25s", rt_buf
);
831 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
833 /* If there are multiple export RTs we break here and show only
840 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
843 char vni_str
[VNI_STR_LEN
];
845 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
846 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
847 json_object_object_add(json
, vni_str
, json_vni
);
853 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
855 char buf
[ESI_STR_LEN
];
856 char buf1
[RD_ADDRSTRLEN
];
857 char buf2
[INET6_ADDRSTRLEN
];
858 struct in_addr
*vtep
= NULL
;
859 struct vty
*vty
= args
[0];
860 json_object
*json
= args
[1];
861 json_object
*json_vteps
= NULL
;
862 struct listnode
*node
= NULL
;
863 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
866 json_vteps
= json_object_new_array();
867 json_object_string_add(json
, "esi",
868 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
869 json_object_string_add(json
, "type",
870 is_es_local(es
) ? "Local" : "Remote");
871 json_object_string_add(json
, "rd",
872 prefix_rd2str(&es
->prd
, buf1
,
874 json_object_string_add(
875 json
, "originatorIp",
876 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
878 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
879 json_object_array_add(json_vteps
,
880 json_object_new_string(
883 json_object_object_add(json
, "vteps", json_vteps
);
885 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
886 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
887 is_es_local(es
) ? "Local" : "Remote",
888 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
889 ipaddr2str(&es
->originator_ip
, buf2
,
891 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
895 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
899 json_object
*json_vni
= NULL
;
900 json_object
*json_import_rtl
= NULL
;
901 json_object
*json_export_rtl
= NULL
;
902 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
904 char buf2
[RD_ADDRSTRLEN
];
907 struct listnode
*node
, *nnode
;
908 struct ecommunity
*ecom
;
914 json_vni
= json_object_new_object();
915 json_import_rtl
= json_object_new_array();
916 json_export_rtl
= json_object_new_array();
920 if (is_vni_live(vpn
))
924 json_object_int_add(json_vni
, "vni", vpn
->vni
);
925 json_object_string_add(json_vni
, "type", "L2");
926 json_object_string_add(json_vni
, "inKernel",
927 is_vni_live(vpn
) ? "True" : "False");
928 json_object_string_add(json_vni
, "originatorIp",
929 inet_ntoa(vpn
->originator_ip
));
930 json_object_string_add(json_vni
, "originatorIp",
931 inet_ntoa(vpn
->originator_ip
));
932 json_object_string_add(
934 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
936 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
937 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
940 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
941 ecom_str
= ecommunity_ecom2str(ecom
,
942 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
945 json_object_array_add(json_import_rtl
,
946 json_object_new_string(ecom_str
));
948 if (listcount(vpn
->import_rtl
) > 1)
949 sprintf(rt_buf
, "%s, ...", ecom_str
);
951 sprintf(rt_buf
, "%s", ecom_str
);
952 vty_out(vty
, " %-25s", rt_buf
);
955 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
957 /* If there are multiple import RTs we break here and show only
964 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
966 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
967 ecom_str
= ecommunity_ecom2str(ecom
,
968 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
971 json_object_array_add(json_export_rtl
,
972 json_object_new_string(ecom_str
));
974 if (listcount(vpn
->export_rtl
) > 1)
975 sprintf(rt_buf
, "%s, ...", ecom_str
);
977 sprintf(rt_buf
, "%s", ecom_str
);
978 vty_out(vty
, " %-25s", rt_buf
);
981 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
983 /* If there are multiple export RTs we break here and show only
990 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
993 char vni_str
[VNI_STR_LEN
];
995 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
996 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
997 json_object_object_add(json
, vni_str
, json_vni
);
1003 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1004 enum bgp_show_type type
, void *output_arg
,
1005 int option
, bool use_json
)
1007 afi_t afi
= AFI_L2VPN
;
1009 struct bgp_table
*table
;
1010 struct bgp_node
*rn
;
1011 struct bgp_node
*rm
;
1012 struct bgp_path_info
*pi
;
1015 char rd_str
[BUFSIZ
];
1019 unsigned long output_count
= 0;
1020 unsigned long total_count
= 0;
1021 json_object
*json
= NULL
;
1022 json_object
*json_nroute
= NULL
;
1023 json_object
*json_array
= NULL
;
1024 json_object
*json_prefix_info
= NULL
;
1026 memset(rd_str
, 0, BUFSIZ
);
1028 bgp
= bgp_get_evpn();
1031 vty_out(vty
, "No BGP process is configured\n");
1033 vty_out(vty
, "{}\n");
1038 json
= json_object_new_object();
1040 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1041 rn
= bgp_route_next(rn
)) {
1044 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1047 table
= bgp_node_get_bgp_table_info(rn
);
1052 tbl_ver
= table
->version
;
1054 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1055 pi
= bgp_node_get_bgp_path_info(rm
);
1061 json_array
= json_object_new_array();
1062 json_prefix_info
= json_object_new_object();
1064 json_object_string_add(json_prefix_info
,
1065 "prefix", bgp_evpn_route2str(
1066 (struct prefix_evpn
*)&rm
->p
, buf
,
1069 json_object_int_add(json_prefix_info
,
1070 "prefixLen", rm
->p
.prefixlen
);
1073 json_nroute
= json_object_new_object();
1076 for (; pi
; pi
= pi
->next
) {
1078 if (type
== bgp_show_type_neighbor
) {
1079 struct peer
*peer
= output_arg
;
1081 if (peer_cmp(peer
, pi
->peer
) != 0)
1084 if (type
== bgp_show_type_lcommunity_exact
) {
1085 struct lcommunity
*lcom
= output_arg
;
1087 if (!pi
->attr
->lcommunity
||
1089 pi
->attr
->lcommunity
, lcom
))
1092 if (type
== bgp_show_type_lcommunity
) {
1093 struct lcommunity
*lcom
= output_arg
;
1095 if (!pi
->attr
->lcommunity
||
1097 pi
->attr
->lcommunity
, lcom
))
1100 if (type
== bgp_show_type_community
) {
1101 struct community
*com
= output_arg
;
1103 if (!pi
->attr
->community
||
1105 pi
->attr
->community
, com
))
1108 if (type
== bgp_show_type_community_exact
) {
1109 struct community
*com
= output_arg
;
1111 if (!pi
->attr
->community
||
1113 pi
->attr
->community
, com
))
1118 json_object_int_add(
1119 json
, "bgpTableVersion",
1121 json_object_string_add(
1126 json_object_int_add(
1129 bgp
->default_local_pref
);
1130 json_object_int_add(
1134 if (option
== SHOW_DISPLAY_TAGS
)
1139 == SHOW_DISPLAY_OVERLAY
)
1143 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1156 /* Decode RD type. */
1157 type
= decode_rd_type(pnt
);
1158 /* Decode RD value. */
1159 if (type
== RD_TYPE_AS
)
1160 decode_rd_as(pnt
+ 2, &rd_as
);
1161 else if (type
== RD_TYPE_AS4
)
1162 decode_rd_as4(pnt
+ 2, &rd_as
);
1163 else if (type
== RD_TYPE_IP
)
1164 decode_rd_ip(pnt
+ 2, &rd_ip
);
1166 if (type
== RD_TYPE_AS
1167 || type
== RD_TYPE_AS4
)
1168 sprintf(rd_str
, "%u:%d",
1171 else if (type
== RD_TYPE_IP
)
1172 sprintf(rd_str
, "%s:%d",
1176 json_object_string_add(
1183 "Route Distinguisher: ");
1184 if (type
== RD_TYPE_AS
)
1189 else if (type
== RD_TYPE_AS4
)
1194 else if (type
== RD_TYPE_IP
)
1195 vty_out(vty
, "ip %s:%d",
1199 vty_out(vty
, "\n\n");
1204 if (option
== SHOW_DISPLAY_TAGS
)
1205 route_vty_out_tag(vty
, &rm
->p
, pi
,
1206 no_display
, SAFI_EVPN
,
1208 else if (option
== SHOW_DISPLAY_OVERLAY
)
1209 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1213 route_vty_out(vty
, &rm
->p
, pi
,
1214 no_display
, SAFI_EVPN
,
1223 json_object_object_add(json_prefix_info
,
1224 "paths", json_array
);
1225 json_object_object_add(json_nroute
, buf
,
1231 json_object_object_add(json
, rd_str
, json_nroute
);
1235 json_object_int_add(json
, "numPrefix", output_count
);
1236 json_object_int_add(json
, "totalPrefix", total_count
);
1237 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1238 json
, JSON_C_TO_STRING_PRETTY
));
1239 json_object_free(json
);
1241 if (output_count
== 0)
1242 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1246 "\nDisplayed %ld out of %ld total prefixes\n",
1247 output_count
, total_count
);
1252 DEFUN(show_ip_bgp_l2vpn_evpn
,
1253 show_ip_bgp_l2vpn_evpn_cmd
,
1254 "show [ip] bgp l2vpn evpn [json]",
1255 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1257 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1258 use_json(argc
, argv
));
1261 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1262 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1263 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1269 "Display information for a route distinguisher\n"
1270 "VPN Route Distinguisher\n" JSON_STR
)
1272 int idx_ext_community
= 0;
1274 struct prefix_rd prd
;
1276 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1278 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1280 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1283 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1284 use_json(argc
, argv
));
1287 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1288 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1289 "show [ip] bgp l2vpn evpn all tags",
1295 "Display information about all EVPN NLRIs\n"
1296 "Display BGP tags for prefixes\n")
1298 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1302 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1303 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1304 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1310 "Display information for a route distinguisher\n"
1311 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1313 int idx_ext_community
= 0;
1315 struct prefix_rd prd
;
1317 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1319 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1321 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1324 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1328 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1329 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1330 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1336 "Detailed information on TCP and BGP neighbor connections\n"
1337 "IPv4 Neighbor to display information about\n"
1338 "IPv6 Neighbor to display information about\n"
1339 "Neighbor on BGP configured interface\n"
1340 "Display routes learned from neighbor\n" JSON_STR
)
1344 char *peerstr
= NULL
;
1345 bool uj
= use_json(argc
, argv
);
1346 afi_t afi
= AFI_L2VPN
;
1347 safi_t safi
= SAFI_EVPN
;
1348 struct bgp
*bgp
= NULL
;
1350 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1353 vty_out(vty
, "No index\n");
1357 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1358 argv_find(argv
, argc
, "neighbors", &idx
);
1359 peerstr
= argv
[++idx
]->arg
;
1361 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1364 json_object
*json_no
= NULL
;
1365 json_no
= json_object_new_object();
1366 json_object_string_add(json_no
, "warning",
1367 "Malformed address");
1368 vty_out(vty
, "%s\n",
1369 json_object_to_json_string(json_no
));
1370 json_object_free(json_no
);
1372 vty_out(vty
, "Malformed address: %s\n",
1376 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1378 json_object
*json_no
= NULL
;
1379 json_no
= json_object_new_object();
1380 json_object_string_add(
1382 "No such neighbor or address family");
1383 vty_out(vty
, "%s\n",
1384 json_object_to_json_string(json_no
));
1385 json_object_free(json_no
);
1387 vty_out(vty
, "%% No such neighbor or address family\n");
1391 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1395 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1396 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1397 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1403 "Display information for a route distinguisher\n"
1404 "VPN Route Distinguisher\n"
1405 "Detailed information on TCP and BGP neighbor connections\n"
1406 "IPv4 Neighbor to display information about\n"
1407 "IPv6 Neighbor to display information about\n"
1408 "Neighbor on BGP configured interface\n"
1409 "Display routes learned from neighbor\n" JSON_STR
)
1411 int idx_ext_community
= 0;
1415 char *peerstr
= NULL
;
1416 struct prefix_rd prd
;
1417 bool uj
= use_json(argc
, argv
);
1418 afi_t afi
= AFI_L2VPN
;
1419 safi_t safi
= SAFI_EVPN
;
1420 struct bgp
*bgp
= NULL
;
1422 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1425 vty_out(vty
, "No index\n");
1429 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1430 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1433 json_object
*json_no
= NULL
;
1434 json_no
= json_object_new_object();
1435 json_object_string_add(json_no
, "warning",
1436 "Malformed Route Distinguisher");
1437 vty_out(vty
, "%s\n",
1438 json_object_to_json_string(json_no
));
1439 json_object_free(json_no
);
1441 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1445 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1446 argv_find(argv
, argc
, "neighbors", &idx
);
1447 peerstr
= argv
[++idx
]->arg
;
1449 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1452 json_object
*json_no
= NULL
;
1453 json_no
= json_object_new_object();
1454 json_object_string_add(json_no
, "warning",
1455 "Malformed address");
1456 vty_out(vty
, "%s\n",
1457 json_object_to_json_string(json_no
));
1458 json_object_free(json_no
);
1460 vty_out(vty
, "Malformed address: %s\n",
1464 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1466 json_object
*json_no
= NULL
;
1467 json_no
= json_object_new_object();
1468 json_object_string_add(
1470 "No such neighbor or address family");
1471 vty_out(vty
, "%s\n",
1472 json_object_to_json_string(json_no
));
1473 json_object_free(json_no
);
1475 vty_out(vty
, "%% No such neighbor or address family\n");
1479 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1483 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1484 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1485 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1491 "Detailed information on TCP and BGP neighbor connections\n"
1492 "IPv4 Neighbor to display information about\n"
1493 "IPv6 Neighbor to display information about\n"
1494 "Neighbor on BGP configured interface\n"
1495 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1499 bool uj
= use_json(argc
, argv
);
1500 struct bgp
*bgp
= NULL
;
1501 afi_t afi
= AFI_L2VPN
;
1502 safi_t safi
= SAFI_EVPN
;
1503 char *peerstr
= NULL
;
1508 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1511 vty_out(vty
, "No index\n");
1515 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1516 argv_find(argv
, argc
, "neighbors", &idx
);
1517 peerstr
= argv
[++idx
]->arg
;
1519 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1522 json_object
*json_no
= NULL
;
1523 json_no
= json_object_new_object();
1524 json_object_string_add(json_no
, "warning",
1525 "Malformed address");
1526 vty_out(vty
, "%s\n",
1527 json_object_to_json_string(json_no
));
1528 json_object_free(json_no
);
1530 vty_out(vty
, "Malformed address: %s\n",
1534 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1536 json_object
*json_no
= NULL
;
1537 json_no
= json_object_new_object();
1538 json_object_string_add(
1540 "No such neighbor or address family");
1541 vty_out(vty
, "%s\n",
1542 json_object_to_json_string(json_no
));
1543 json_object_free(json_no
);
1545 vty_out(vty
, "%% No such neighbor or address family\n");
1549 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1552 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1553 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1554 "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]",
1560 "Display information for a route distinguisher\n"
1561 "VPN Route Distinguisher\n"
1562 "Detailed information on TCP and BGP neighbor connections\n"
1563 "IPv4 Neighbor to display information about\n"
1564 "IPv6 Neighbor to display information about\n"
1565 "Neighbor on BGP configured interface\n"
1566 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1568 int idx_ext_community
= 0;
1572 struct prefix_rd prd
;
1573 struct bgp
*bgp
= NULL
;
1574 bool uj
= use_json(argc
, argv
);
1575 char *peerstr
= NULL
;
1576 afi_t afi
= AFI_L2VPN
;
1577 safi_t safi
= SAFI_EVPN
;
1585 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1588 vty_out(vty
, "No index\n");
1592 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1594 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1595 argv_find(argv
, argc
, "neighbors", &idx
);
1596 peerstr
= argv
[++idx
]->arg
;
1598 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1601 json_object
*json_no
= NULL
;
1602 json_no
= json_object_new_object();
1603 json_object_string_add(json_no
, "warning",
1604 "Malformed address");
1605 vty_out(vty
, "%s\n",
1606 json_object_to_json_string(json_no
));
1607 json_object_free(json_no
);
1609 vty_out(vty
, "Malformed address: %s\n",
1613 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1615 json_object
*json_no
= NULL
;
1616 json_no
= json_object_new_object();
1617 json_object_string_add(
1619 "No such neighbor or address family");
1620 vty_out(vty
, "%s\n",
1621 json_object_to_json_string(json_no
));
1622 json_object_free(json_no
);
1624 vty_out(vty
, "%% No such neighbor or address family\n");
1628 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1631 json_object
*json_no
= NULL
;
1632 json_no
= json_object_new_object();
1633 json_object_string_add(json_no
, "warning",
1634 "Malformed Route Distinguisher");
1635 vty_out(vty
, "%s\n",
1636 json_object_to_json_string(json_no
));
1637 json_object_free(json_no
);
1639 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1643 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1646 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1647 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1648 "show [ip] bgp l2vpn evpn all overlay [json]",
1654 "Display information about all EVPN NLRIs\n"
1655 "Display BGP Overlay Information for prefixes\n"
1658 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1659 SHOW_DISPLAY_OVERLAY
,
1660 use_json(argc
, argv
));
1663 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1664 show_ip_bgp_evpn_rd_overlay_cmd
,
1665 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1671 "Display information for a route distinguisher\n"
1672 "VPN Route Distinguisher\n"
1673 "Display BGP Overlay Information for prefixes\n")
1675 int idx_ext_community
= 0;
1677 struct prefix_rd prd
;
1679 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1681 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1683 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1686 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1687 SHOW_DISPLAY_OVERLAY
,
1688 use_json(argc
, argv
));
1691 DEFUN(show_bgp_l2vpn_evpn_com
,
1692 show_bgp_l2vpn_evpn_com_cmd
,
1693 "show bgp l2vpn evpn \
1694 <community AA:NN|large-community AA:BB:CC> \
1695 [exact-match] [json]",
1700 "Display routes matching the community\n"
1701 "Community number where AA and NN are (0-65535)\n"
1702 "Display routes matching the large-community\n"
1703 "List of large-community numbers\n"
1704 "Exact match of the communities\n"
1709 const char *clist_number_or_name
;
1710 int show_type
= bgp_show_type_normal
;
1711 struct community
*com
;
1712 struct lcommunity
*lcom
;
1714 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1715 clist_number_or_name
= argv
[++idx
]->arg
;
1716 show_type
= bgp_show_type_lcommunity
;
1718 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1719 show_type
= bgp_show_type_lcommunity_exact
;
1721 lcom
= lcommunity_str2com(clist_number_or_name
);
1723 vty_out(vty
, "%% Large-community malformed\n");
1727 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1728 SHOW_DISPLAY_STANDARD
,
1729 use_json(argc
, argv
));
1731 lcommunity_free(&lcom
);
1732 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1733 clist_number_or_name
= argv
[++idx
]->arg
;
1734 show_type
= bgp_show_type_community
;
1736 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1737 show_type
= bgp_show_type_community_exact
;
1739 com
= community_str2com(clist_number_or_name
);
1742 vty_out(vty
, "%% Community malformed: %s\n",
1743 clist_number_or_name
);
1747 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1748 SHOW_DISPLAY_STANDARD
,
1749 use_json(argc
, argv
));
1750 community_free(&com
);
1756 /* For testing purpose, static route of EVPN RT-5. */
1757 DEFUN(evpnrt5_network
,
1758 evpnrt5_network_cmd
,
1759 "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]",
1760 "Specify a network to announce via BGP\n"
1763 "Specify Route Distinguisher\n"
1764 "VPN Route Distinguisher\n"
1766 "Ethernet Tag Value\n"
1769 "Ethernet Segment Identifier\n"
1770 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1772 "Gateway IP ( A.B.C.D )\n"
1773 "Gateway IPv6 ( X:X::X:X )\n"
1774 "Router Mac Ext Comm\n"
1775 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1776 "Route-map to modify the attributes\n"
1777 "Name of the route map\n")
1779 int idx_ipv4_prefixlen
= 1;
1780 int idx_route_distinguisher
= 3;
1785 int idx_routermac
= 13;
1787 return bgp_static_set_safi(
1788 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1789 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1790 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1791 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1792 argv
[idx_routermac
]->arg
);
1795 /* For testing purpose, static route of EVPN RT-5. */
1796 DEFUN(no_evpnrt5_network
,
1797 no_evpnrt5_network_cmd
,
1798 "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>",
1800 "Specify a network to announce via BGP\n"
1803 "Specify Route Distinguisher\n"
1804 "VPN Route Distinguisher\n"
1806 "Ethernet Tag Value\n"
1809 "Ethernet Segment Identifier\n"
1810 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1811 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1813 int idx_ipv4_prefixlen
= 2;
1814 int idx_ext_community
= 4;
1819 return bgp_static_unset_safi(
1820 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1821 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1822 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1823 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1826 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1828 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1831 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1833 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1837 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1838 * check that this is a change.
1840 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1841 struct ecommunity
*ecomadd
)
1843 /* If the VNI is "live", we need to uninstall routes using the current
1844 * import RT(s) first before we update the import RT, and subsequently
1847 if (is_vni_live(vpn
))
1848 bgp_evpn_uninstall_routes(bgp
, vpn
);
1850 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1851 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1853 /* If the auto route-target is in use we must remove it */
1854 evpn_import_rt_delete_auto(bgp
, vpn
);
1856 /* Add new RT and rebuild the RT to VNI mapping */
1857 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1859 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1860 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1862 /* Install routes that match new import RT */
1863 if (is_vni_live(vpn
))
1864 bgp_evpn_install_routes(bgp
, vpn
);
1868 * Unconfigure Import RT(s) for a VNI (vty handler).
1870 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1871 struct ecommunity
*ecomdel
)
1873 struct listnode
*node
, *nnode
, *node_to_del
;
1874 struct ecommunity
*ecom
;
1876 /* Along the lines of "configure" except we have to reset to the
1879 if (is_vni_live(vpn
))
1880 bgp_evpn_uninstall_routes(bgp
, vpn
);
1882 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1883 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1885 /* Delete all import RTs */
1886 if (ecomdel
== NULL
) {
1887 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1888 ecommunity_free(&ecom
);
1889 list_delete_node(vpn
->import_rtl
, node
);
1893 /* Delete a specific import RT */
1897 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1898 if (ecommunity_match(ecom
, ecomdel
)) {
1899 ecommunity_free(&ecom
);
1906 list_delete_node(vpn
->import_rtl
, node_to_del
);
1909 assert(vpn
->import_rtl
);
1910 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1911 if (list_isempty(vpn
->import_rtl
)) {
1912 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1913 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1915 /* Rebuild the RT to VNI mapping */
1917 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1919 /* Install routes that match new import RT */
1920 if (is_vni_live(vpn
))
1921 bgp_evpn_install_routes(bgp
, vpn
);
1925 * Configure the Export RT for a VNI (vty handler). Caller expected to
1926 * check that this is a change. Note that only a single export RT is
1927 * allowed for a VNI and any change to configuration is implemented as
1928 * a "replace" (similar to other configuration).
1930 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1931 struct ecommunity
*ecomadd
)
1933 /* If the auto route-target is in use we must remove it */
1934 evpn_export_rt_delete_auto(bgp
, vpn
);
1936 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1937 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1939 if (is_vni_live(vpn
))
1940 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1944 * Unconfigure the Export RT for a VNI (vty handler)
1946 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1947 struct ecommunity
*ecomdel
)
1949 struct listnode
*node
, *nnode
, *node_to_del
;
1950 struct ecommunity
*ecom
;
1952 /* Delete all export RTs */
1953 if (ecomdel
== NULL
) {
1954 /* Reset to default and process all routes. */
1955 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1956 ecommunity_free(&ecom
);
1957 list_delete_node(vpn
->export_rtl
, node
);
1961 /* Delete a specific export RT */
1965 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1966 if (ecommunity_match(ecom
, ecomdel
)) {
1967 ecommunity_free(&ecom
);
1974 list_delete_node(vpn
->export_rtl
, node_to_del
);
1977 assert(vpn
->export_rtl
);
1978 if (list_isempty(vpn
->export_rtl
)) {
1979 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1980 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1983 if (is_vni_live(vpn
))
1984 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1988 * Configure RD for VRF
1990 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1992 /* If we have already advertise type-5 routes with a diffrent RD, we
1993 * have to delete and withdraw them firs
1995 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1998 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1999 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2001 /* We have a new RD for VRF.
2002 * Advertise all type-5 routes again with the new RD
2004 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2008 * Unconfigure RD for VRF
2010 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2012 /* If we have already advertise type-5 routes with a diffrent RD, we
2013 * have to delete and withdraw them firs
2015 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2017 /* fall back to default RD */
2018 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2019 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2021 /* We have a new RD for VRF.
2022 * Advertise all type-5 routes again with the new RD
2024 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2028 * Configure RD for a VNI (vty handler)
2030 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2031 struct prefix_rd
*rd
)
2033 /* If the VNI is "live", we need to delete and withdraw this VNI's
2034 * local routes with the prior RD first. Then, after updating RD,
2035 * need to re-advertise.
2037 if (is_vni_live(vpn
))
2038 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2041 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2042 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2044 if (is_vni_live(vpn
))
2045 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2049 * Unconfigure RD for a VNI (vty handler)
2051 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2053 /* If the VNI is "live", we need to delete and withdraw this VNI's
2054 * local routes with the prior RD first. Then, after resetting RD
2055 * to automatic value, need to re-advertise.
2057 if (is_vni_live(vpn
))
2058 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2060 /* reset RD to default */
2061 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2063 if (is_vni_live(vpn
))
2064 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2068 * Create VNI, if not already present (VTY handler). Mark as configured.
2070 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2072 struct bgpevpn
*vpn
;
2073 struct in_addr mcast_grp
= {INADDR_ANY
};
2078 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2080 /* Check if this L2VNI is already configured as L3VNI */
2081 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2084 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2089 /* tenant vrf will be updated when we get local_vni_add from
2092 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2096 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2102 /* Mark as configured. */
2103 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2108 * Delete VNI. If VNI does not exist in the system (i.e., just
2109 * configuration), all that is needed is to free it. Otherwise,
2110 * any parameters configured for the VNI need to be reset (with
2111 * appropriate action) and the VNI marked as unconfigured; the
2112 * VNI will continue to exist, purely as a "learnt" entity.
2114 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2116 assert(bgp
->vnihash
);
2118 if (!is_vni_live(vpn
)) {
2119 bgp_evpn_free(bgp
, vpn
);
2123 /* We need to take the unconfigure action for each parameter of this VNI
2124 * that is configured. Some optimization is possible, but not worth the
2125 * additional code for an operation that should be pretty rare.
2127 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2129 /* First, deal with the export side - RD and export RT changes. */
2130 if (is_rd_configured(vpn
))
2131 evpn_unconfigure_rd(bgp
, vpn
);
2132 if (is_export_rt_configured(vpn
))
2133 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2135 /* Next, deal with the import side. */
2136 if (is_import_rt_configured(vpn
))
2137 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2143 * Display import RT mapping to VRFs (vty handler)
2144 * bgp_evpn: evpn bgp instance
2146 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2154 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2155 (void (*)(struct hash_bucket
*,
2156 void *))show_vrf_import_rt_entry
,
2161 * Display import RT mapping to VNIs (vty handler)
2163 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2172 bgp
->import_rt_hash
,
2173 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2178 * Display EVPN routes for all VNIs - vty handler.
2180 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2181 struct in_addr vtep_ip
, json_object
*json
,
2185 struct vni_walk_ctx wctx
;
2187 num_vnis
= hashcount(bgp
->vnihash
);
2190 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2193 wctx
.vtep_ip
= vtep_ip
;
2195 wctx
.detail
= detail
;
2196 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2197 void *))show_vni_routes_hash
,
2202 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2204 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2205 vni_t vni
, struct in_addr orig_ip
,
2208 struct bgpevpn
*vpn
;
2209 struct prefix_evpn p
;
2210 struct bgp_node
*rn
;
2211 struct bgp_path_info
*pi
;
2212 uint32_t path_cnt
= 0;
2215 json_object
*json_paths
= NULL
;
2221 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2223 vty_out(vty
, "VNI not found\n");
2227 /* See if route exists. */
2228 build_evpn_type3_prefix(&p
, orig_ip
);
2229 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2230 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2232 vty_out(vty
, "%% Network not in table\n");
2237 json_paths
= json_object_new_array();
2239 /* Prefix and num paths displayed once per prefix. */
2240 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2242 /* Display each path for this prefix. */
2243 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2244 json_object
*json_path
= NULL
;
2247 json_path
= json_object_new_array();
2249 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2253 json_object_array_add(json_paths
, json_path
);
2260 json_object_object_add(json
, "paths", json_paths
);
2262 json_object_int_add(json
, "numPaths", path_cnt
);
2264 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2270 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2271 * By definition, only matching type-2 route will be displayed.
2273 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2274 vni_t vni
, struct ethaddr
*mac
,
2275 struct ipaddr
*ip
, json_object
*json
)
2277 struct bgpevpn
*vpn
;
2278 struct prefix_evpn p
;
2279 struct bgp_node
*rn
;
2280 struct bgp_path_info
*pi
;
2281 uint32_t path_cnt
= 0;
2284 json_object
*json_paths
= NULL
;
2290 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2293 vty_out(vty
, "VNI not found\n");
2297 /* See if route exists. Look for both non-sticky and sticky. */
2298 build_evpn_type2_prefix(&p
, mac
, ip
);
2299 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2300 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2302 vty_out(vty
, "%% Network not in table\n");
2307 json_paths
= json_object_new_array();
2309 /* Prefix and num paths displayed once per prefix. */
2310 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2312 /* Display each path for this prefix. */
2313 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2314 json_object
*json_path
= NULL
;
2317 json_path
= json_object_new_array();
2319 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2323 json_object_array_add(json_paths
, json_path
);
2330 json_object_object_add(json
, "paths", json_paths
);
2332 json_object_int_add(json
, "numPaths", path_cnt
);
2334 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2339 /* Disaplay EVPN routes for a ESI - VTY handler */
2340 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2341 esi_t
*esi
, json_object
*json
)
2343 struct evpnes
*es
= NULL
;
2346 es
= bgp_evpn_lookup_es(bgp
, esi
);
2349 vty_out(vty
, "ESI not found\n");
2353 show_esi_routes(bgp
, es
, vty
, json
);
2357 * Display EVPN routes for a VNI - vty handler.
2358 * If 'type' is non-zero, only routes matching that type are shown.
2359 * If the vtep_ip is non zero, only routes behind that vtep are shown
2361 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2362 int type
, struct in_addr vtep_ip
,
2365 struct bgpevpn
*vpn
;
2368 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2371 vty_out(vty
, "VNI not found\n");
2375 /* Walk this VNI's route table and display appropriate routes. */
2376 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2380 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2381 * IP (vty handler). By definition, only matching type-2 route will be
2384 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2385 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2386 struct ipaddr
*ip
, json_object
*json
)
2388 struct prefix_evpn p
;
2389 struct bgp_node
*rn
;
2390 struct bgp_path_info
*pi
;
2393 uint32_t path_cnt
= 0;
2394 json_object
*json_paths
= NULL
;
2395 char prefix_str
[BUFSIZ
];
2400 /* See if route exists. Look for both non-sticky and sticky. */
2401 build_evpn_type2_prefix(&p
, mac
, ip
);
2402 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2403 (struct prefix
*)&p
, prd
);
2404 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2406 vty_out(vty
, "%% Network not in table\n");
2410 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2411 sizeof(prefix_str
));
2413 /* Prefix and num paths displayed once per prefix. */
2414 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2417 json_paths
= json_object_new_array();
2419 /* Display each path for this prefix. */
2420 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2421 json_object
*json_path
= NULL
;
2424 json_path
= json_object_new_array();
2426 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2430 json_object_array_add(json_paths
, json_path
);
2435 if (json
&& path_cnt
) {
2437 json_object_object_add(json
, prefix_str
, json_paths
);
2438 json_object_int_add(json
, "numPaths", path_cnt
);
2440 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2446 * Display BGP EVPN routing table -- for specific RD (vty handler)
2447 * If 'type' is non-zero, only routes matching that type are shown.
2449 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2450 struct prefix_rd
*prd
, int type
,
2453 struct bgp_node
*rd_rn
;
2454 struct bgp_table
*table
;
2455 struct bgp_node
*rn
;
2456 struct bgp_path_info
*pi
;
2460 uint32_t prefix_cnt
, path_cnt
;
2461 char rd_str
[RD_ADDRSTRLEN
];
2462 json_object
*json_rd
= NULL
;
2463 int add_rd_to_json
= 0;
2467 prefix_cnt
= path_cnt
= 0;
2469 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2471 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2475 table
= bgp_node_get_bgp_table_info(rd_rn
);
2480 json_rd
= json_object_new_object();
2481 json_object_string_add(json_rd
, "rd", rd_str
);
2484 /* Display all prefixes with this RD. */
2485 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2486 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2487 json_object
*json_prefix
= NULL
;
2488 json_object
*json_paths
= NULL
;
2489 char prefix_str
[BUFSIZ
];
2490 int add_prefix_to_json
= 0;
2492 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2493 sizeof(prefix_str
));
2495 if (type
&& evp
->prefix
.route_type
!= type
)
2499 json_prefix
= json_object_new_object();
2501 pi
= bgp_node_get_bgp_path_info(rn
);
2503 /* RD header and legend - once overall. */
2504 if (rd_header
&& !json
) {
2506 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2508 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2510 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2514 /* Prefix and num paths displayed once per prefix. */
2515 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2522 json_paths
= json_object_new_array();
2524 /* Display each path for this prefix. */
2525 for (; pi
; pi
= pi
->next
) {
2526 json_object
*json_path
= NULL
;
2529 json_path
= json_object_new_array();
2531 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2535 json_object_array_add(json_paths
, json_path
);
2538 add_prefix_to_json
= 1;
2542 if (json
&& add_prefix_to_json
) {
2543 json_object_object_add(json_prefix
, "paths",
2545 json_object_object_add(json_rd
, prefix_str
,
2550 if (json
&& add_rd_to_json
)
2551 json_object_object_add(json
, rd_str
, json_rd
);
2554 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2555 json_object_int_add(json
, "numPaths", path_cnt
);
2557 if (prefix_cnt
== 0)
2558 vty_out(vty
, "No prefixes exist with this RD%s\n",
2559 type
? " (of requested type)" : "");
2562 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2563 prefix_cnt
, path_cnt
,
2564 type
? " (of requested type)" : "");
2569 * Display BGP EVPN routing table - all routes (vty handler).
2570 * If 'type' is non-zero, only routes matching that type are shown.
2572 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2573 json_object
*json
, int detail
)
2575 struct bgp_node
*rd_rn
;
2576 struct bgp_table
*table
;
2577 struct bgp_node
*rn
;
2578 struct bgp_path_info
*pi
;
2579 int header
= detail
? 0 : 1;
2583 uint32_t prefix_cnt
, path_cnt
;
2587 prefix_cnt
= path_cnt
= 0;
2589 /* EVPN routing table is a 2-level table with the first level being
2592 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2593 rd_rn
= bgp_route_next(rd_rn
)) {
2594 char rd_str
[RD_ADDRSTRLEN
];
2595 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2596 int add_rd_to_json
= 0;
2599 table
= bgp_node_get_bgp_table_info(rd_rn
);
2603 tbl_ver
= table
->version
;
2604 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2608 json_rd
= json_object_new_object();
2609 json_object_string_add(json_rd
, "rd", rd_str
);
2614 /* Display all prefixes for an RD */
2615 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2616 json_object
*json_prefix
=
2617 NULL
; /* contains prefix under a RD */
2618 json_object
*json_paths
=
2619 NULL
; /* array of paths under a prefix*/
2620 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2621 char prefix_str
[BUFSIZ
];
2622 int add_prefix_to_json
= 0;
2624 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2625 prefix_str
, sizeof(prefix_str
));
2627 if (type
&& evp
->prefix
.route_type
!= type
)
2630 pi
= bgp_node_get_bgp_path_info(rn
);
2632 /* Overall header/legend displayed once. */
2634 bgp_evpn_show_route_header(vty
, bgp
,
2639 "%19s Extended Community\n"
2644 /* RD header - per RD. */
2646 bgp_evpn_show_route_rd_header(
2655 json_prefix
= json_object_new_object();
2656 json_paths
= json_object_new_array();
2657 json_object_string_add(json_prefix
, "prefix",
2659 json_object_int_add(json_prefix
, "prefixLen",
2663 /* Prefix and num paths displayed once per prefix. */
2665 route_vty_out_detail_header(
2667 (struct prefix_rd
*)&rd_rn
->p
,
2668 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2670 /* For EVPN, the prefix is displayed for each path (to
2672 * with code that already exists).
2674 for (; pi
; pi
= pi
->next
) {
2675 json_object
*json_path
= NULL
;
2677 add_prefix_to_json
= 1;
2681 json_path
= json_object_new_array();
2684 route_vty_out_detail(
2685 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2686 SAFI_EVPN
, json_path
);
2688 route_vty_out(vty
, &rn
->p
, pi
, 0,
2689 SAFI_EVPN
, json_path
);
2692 json_object_array_add(json_paths
,
2696 if (json
&& add_prefix_to_json
) {
2697 json_object_object_add(json_prefix
, "paths",
2699 json_object_object_add(json_rd
, prefix_str
,
2704 if (json
&& add_rd_to_json
)
2705 json_object_object_add(json
, rd_str
, json_rd
);
2709 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2710 json_object_int_add(json
, "numPaths", path_cnt
);
2712 if (prefix_cnt
== 0) {
2713 vty_out(vty
, "No EVPN prefixes %sexist\n",
2714 type
? "(of requested type) " : "");
2716 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2717 prefix_cnt
, path_cnt
,
2718 type
? " (of requested type)" : "");
2723 /* Display specific ES */
2724 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2727 struct evpnes
*es
= NULL
;
2729 es
= bgp_evpn_lookup_es(bgp
, esi
);
2731 display_es(vty
, es
, json
);
2734 vty_out(vty
, "{}\n");
2736 vty_out(vty
, "ESI not found\n");
2742 /* Display all ESs */
2743 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2749 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2750 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2755 hash_iterate(bgp
->esihash
,
2756 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2761 * Display specified VNI (vty handler)
2763 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2767 struct bgpevpn
*vpn
;
2769 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2772 display_vni(vty
, vpn
, json
);
2774 struct bgp
*bgp_temp
;
2775 struct listnode
*node
= NULL
;
2777 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2778 if (bgp_temp
->l3vni
== vni
) {
2780 display_l3vni(vty
, bgp_temp
, json
);
2787 vty_out(vty
, "{}\n");
2789 vty_out(vty
, "VNI not found\n");
2796 * Display a VNI (upon user query).
2798 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2802 struct bgp
*bgp_temp
= NULL
;
2803 struct listnode
*node
;
2807 vty_out(vty
, "Flags: * - Kernel\n");
2808 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2809 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2812 /* print all L2 VNIS */
2815 hash_iterate(bgp
->vnihash
,
2816 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2819 /* print all L3 VNIs */
2820 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2821 show_l3vni_entry(vty
, bgp_temp
, json
);
2825 * evpn - enable advertisement of svi MAC-IP
2827 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2831 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2833 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2836 bgp
->evpn_info
->advertise_svi_macip
= set
;
2837 bgp_zebra_advertise_svi_macip(bgp
,
2838 bgp
->evpn_info
->advertise_svi_macip
, 0);
2840 if (set
&& vpn
->advertise_svi_macip
)
2842 else if (!set
&& !vpn
->advertise_svi_macip
)
2845 vpn
->advertise_svi_macip
= set
;
2846 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2852 * evpn - enable advertisement of default g/w
2854 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2857 if (bgp
->advertise_gw_macip
)
2860 bgp
->advertise_gw_macip
= 1;
2861 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2863 if (vpn
->advertise_gw_macip
)
2866 vpn
->advertise_gw_macip
= 1;
2867 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2874 * evpn - disable advertisement of default g/w
2876 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2877 struct bgpevpn
*vpn
)
2880 if (!bgp
->advertise_gw_macip
)
2883 bgp
->advertise_gw_macip
= 0;
2884 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2886 if (!vpn
->advertise_gw_macip
)
2889 vpn
->advertise_gw_macip
= 0;
2890 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2897 * evpn - enable advertisement of default g/w
2899 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2900 afi_t afi
, bool add
)
2902 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2905 /* bail if we are already advertising default route */
2906 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2910 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2911 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2912 else if (afi
== AFI_IP6
)
2913 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2914 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2916 /* bail out if we havent advertised the default route */
2917 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2920 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2921 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2922 else if (afi
== AFI_IP6
)
2923 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2924 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2927 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2931 * evpn - enable advertisement of default g/w
2933 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2934 struct bgpevpn
*vpn
)
2936 if (vpn
->advertise_subnet
)
2939 vpn
->advertise_subnet
= 1;
2940 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2944 * evpn - disable advertisement of default g/w
2946 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2948 if (!vpn
->advertise_subnet
)
2951 vpn
->advertise_subnet
= 0;
2952 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2956 * EVPN (VNI advertisement) enabled. Register with zebra.
2958 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2960 bgp
->advertise_all_vni
= 1;
2962 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2966 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2967 * cache, EVPN routes (delete and withdraw from peers).
2969 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2971 bgp
->advertise_all_vni
= 0;
2972 bgp_set_evpn(bgp_get_default());
2973 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2974 bgp_evpn_cleanup_on_disable(bgp
);
2978 * EVPN - use RFC8365 to auto-derive RT
2980 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2982 bgp
->advertise_autort_rfc8365
= 1;
2983 bgp_evpn_handle_autort_change(bgp
);
2987 * EVPN - don't use RFC8365 to auto-derive RT
2989 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2991 bgp
->advertise_autort_rfc8365
= 0;
2992 bgp_evpn_handle_autort_change(bgp
);
2995 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2997 char buf1
[RD_ADDRSTRLEN
];
2999 struct listnode
*node
, *nnode
;
3000 struct ecommunity
*ecom
;
3002 if (is_vni_configured(vpn
)) {
3003 vty_out(vty
, " vni %d\n", vpn
->vni
);
3004 if (is_rd_configured(vpn
))
3005 vty_out(vty
, " rd %s\n",
3006 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3008 if (is_import_rt_configured(vpn
)) {
3009 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3011 ecom_str
= ecommunity_ecom2str(
3012 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3013 vty_out(vty
, " route-target import %s\n",
3015 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3019 if (is_export_rt_configured(vpn
)) {
3020 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3022 ecom_str
= ecommunity_ecom2str(
3023 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3024 vty_out(vty
, " route-target export %s\n",
3026 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3030 if (vpn
->advertise_gw_macip
)
3031 vty_out(vty
, " advertise-default-gw\n");
3033 if (vpn
->advertise_svi_macip
)
3034 vty_out(vty
, " advertise-svi-ip\n");
3036 if (vpn
->advertise_subnet
)
3037 vty_out(vty
, " advertise-subnet\n");
3039 vty_out(vty
, " exit-vni\n");
3043 #ifndef VTYSH_EXTRACT_PL
3044 #include "bgpd/bgp_evpn_vty_clippy.c"
3047 DEFPY(bgp_evpn_flood_control
,
3048 bgp_evpn_flood_control_cmd
,
3049 "[no$no] flooding <disable$disable|head-end-replication$her>",
3051 "Specify handling for BUM packets\n"
3052 "Do not flood any BUM packets\n"
3053 "Flood BUM packets using head-end replication\n")
3055 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3056 enum vxlan_flood_control flood_ctrl
;
3062 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3064 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3068 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3071 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3072 bgp_evpn_flood_control_change(bgp
);
3077 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3078 bgp_evpn_advertise_default_gw_vni_cmd
,
3079 "advertise-default-gw",
3080 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3082 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3083 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3088 evpn_set_advertise_default_gw(bgp
, vpn
);
3093 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3094 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3095 "no advertise-default-gw",
3097 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3099 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3100 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3105 evpn_unset_advertise_default_gw(bgp
, vpn
);
3111 DEFUN (bgp_evpn_advertise_default_gw
,
3112 bgp_evpn_advertise_default_gw_cmd
,
3113 "advertise-default-gw",
3114 "Advertise All default g/w mac-ip routes in EVPN\n")
3116 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3121 if (!EVPN_ENABLED(bgp
)) {
3123 "This command is only supported under the EVPN VRF\n");
3127 evpn_set_advertise_default_gw(bgp
, NULL
);
3132 DEFUN (no_bgp_evpn_advertise_default_gw
,
3133 no_bgp_evpn_advertise_default_gw_cmd
,
3134 "no advertise-default-gw",
3136 "Withdraw All default g/w mac-ip routes from EVPN\n")
3138 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3143 if (!EVPN_ENABLED(bgp
)) {
3145 "This command is only supported under the EVPN VRF\n");
3149 evpn_unset_advertise_default_gw(bgp
, NULL
);
3154 DEFUN (bgp_evpn_advertise_all_vni
,
3155 bgp_evpn_advertise_all_vni_cmd
,
3156 "advertise-all-vni",
3157 "Advertise All local VNIs\n")
3159 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3160 struct bgp
*bgp_evpn
= NULL
;
3165 bgp_evpn
= bgp_get_evpn();
3166 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3167 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3169 return CMD_WARNING_CONFIG_FAILED
;
3172 evpn_set_advertise_all_vni(bgp
);
3176 DEFUN (no_bgp_evpn_advertise_all_vni
,
3177 no_bgp_evpn_advertise_all_vni_cmd
,
3178 "no advertise-all-vni",
3180 "Advertise All local VNIs\n")
3182 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3186 evpn_unset_advertise_all_vni(bgp
);
3190 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3191 bgp_evpn_advertise_autort_rfc8365_cmd
,
3192 "autort rfc8365-compatible",
3193 "Auto-derivation of RT\n"
3194 "Auto-derivation of RT using RFC8365\n")
3196 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3200 evpn_set_advertise_autort_rfc8365(bgp
);
3204 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3205 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3206 "no autort rfc8365-compatible",
3208 "Auto-derivation of RT\n"
3209 "Auto-derivation of RT using RFC8365\n")
3211 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3215 evpn_unset_advertise_autort_rfc8365(bgp
);
3219 DEFUN (bgp_evpn_default_originate
,
3220 bgp_evpn_default_originate_cmd
,
3221 "default-originate <ipv4 | ipv6>",
3222 "originate a default route\n"
3223 "ipv4 address family\n"
3224 "ipv6 address family\n")
3228 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3232 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3233 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3237 DEFUN (no_bgp_evpn_default_originate
,
3238 no_bgp_evpn_default_originate_cmd
,
3239 "no default-originate <ipv4 | ipv6>",
3241 "withdraw a default route\n"
3242 "ipv4 address family\n"
3243 "ipv6 address family\n")
3247 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3251 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3252 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3256 DEFPY (dup_addr_detection
,
3257 dup_addr_detection_cmd
,
3258 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3259 "Duplicate address detection\n"
3260 "Max allowed moves before address detected as duplicate\n"
3261 "Num of max allowed moves (2-1000) default 5\n"
3262 "Duplicate address detection time\n"
3263 "Time in seconds (2-1800) default 180\n")
3265 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3270 if (!EVPN_ENABLED(bgp_vrf
)) {
3272 "This command is only supported under the EVPN VRF\n");
3276 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3279 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3281 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3283 bgp_zebra_dup_addr_detection(bgp_vrf
);
3288 DEFPY (dup_addr_detection_auto_recovery
,
3289 dup_addr_detection_auto_recovery_cmd
,
3290 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3291 "Duplicate address detection\n"
3292 "Duplicate address detection freeze\n"
3293 "Duplicate address detection permanent freeze\n"
3294 "Duplicate address detection freeze time (30-3600)\n")
3296 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3297 uint32_t freeze_time
= freeze_time_val
;
3302 if (!EVPN_ENABLED(bgp_vrf
)) {
3304 "This command is only supported under the EVPN VRF\n");
3308 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3309 bgp_vrf
->evpn_info
->dad_freeze
= true;
3310 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3312 bgp_zebra_dup_addr_detection(bgp_vrf
);
3317 DEFPY (no_dup_addr_detection
,
3318 no_dup_addr_detection_cmd
,
3319 "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>]",
3321 "Duplicate address detection\n"
3322 "Max allowed moves before address detected as duplicate\n"
3323 "Num of max allowed moves (2-1000) default 5\n"
3324 "Duplicate address detection time\n"
3325 "Time in seconds (2-1800) default 180\n"
3326 "Duplicate address detection freeze\n"
3327 "Duplicate address detection permanent freeze\n"
3328 "Duplicate address detection freeze time (30-3600)\n")
3330 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3331 uint32_t max_moves
= (uint32_t)max_moves_val
;
3332 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3337 if (!EVPN_ENABLED(bgp_vrf
)) {
3339 "This command is only supported under the EVPN VRF\n");
3344 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3346 /* Reset all parameters to default. */
3347 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3348 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3349 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3350 bgp_vrf
->evpn_info
->dad_freeze
= false;
3351 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3354 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3356 "%% Value does not match with config\n");
3359 bgp_vrf
->evpn_info
->dad_max_moves
=
3360 EVPN_DAD_DEFAULT_MAX_MOVES
;
3364 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3366 "%% Value does not match with config\n");
3369 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3373 if (bgp_vrf
->evpn_info
->dad_freeze_time
3376 "%% Value does not match with config\n");
3379 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3380 bgp_vrf
->evpn_info
->dad_freeze
= false;
3383 if (permanent_val
) {
3384 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3386 "%% Value does not match with config\n");
3389 bgp_vrf
->evpn_info
->dad_freeze
= false;
3393 bgp_zebra_dup_addr_detection(bgp_vrf
);
3398 DEFPY(bgp_evpn_advertise_svi_ip
,
3399 bgp_evpn_advertise_svi_ip_cmd
,
3400 "[no$no] advertise-svi-ip",
3402 "Advertise svi mac-ip routes in EVPN\n")
3404 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3409 if (!EVPN_ENABLED(bgp
)) {
3411 "This command is only supported under EVPN VRF\n");
3416 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3418 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3423 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3424 bgp_evpn_advertise_svi_ip_vni_cmd
,
3425 "[no$no] advertise-svi-ip",
3427 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3429 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3430 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3436 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3438 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3443 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3444 bgp_evpn_advertise_vni_subnet_cmd
,
3446 "Advertise the subnet corresponding to VNI\n")
3448 struct bgp
*bgp_vrf
= NULL
;
3449 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3450 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3455 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3459 evpn_set_advertise_subnet(bgp
, vpn
);
3463 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3464 no_bgp_evpn_advertise_vni_subnet_cmd
,
3465 "no advertise-subnet",
3467 "Advertise All local VNIs\n")
3469 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3470 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3475 evpn_unset_advertise_subnet(bgp
, vpn
);
3479 DEFUN (bgp_evpn_advertise_type5
,
3480 bgp_evpn_advertise_type5_cmd
,
3481 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3482 "Advertise prefix routes\n"
3485 "route-map for filtering specific routes\n"
3486 "Name of the route map\n")
3488 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3495 int rmap_changed
= 0;
3497 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3498 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3499 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3501 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3503 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3504 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3507 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3511 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3513 "%%only ipv4 or ipv6 address families are supported");
3517 if (safi
!= SAFI_UNICAST
) {
3519 "%%only ipv4 unicast or ipv6 unicast are supported");
3523 if (afi
== AFI_IP
) {
3525 /* if we are already advertising ipv4 prefix as type-5
3528 if (!rmap_changed
&&
3529 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3530 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3532 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3533 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3536 /* if we are already advertising ipv6 prefix as type-5
3539 if (!rmap_changed
&&
3540 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3541 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3543 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3544 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3548 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3549 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3550 XFREE(MTYPE_ROUTE_MAP_NAME
,
3551 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3552 route_map_counter_decrement(
3553 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3554 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3555 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3559 /* set the route-map for advertise command */
3560 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3561 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3562 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3563 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3564 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3565 route_map_counter_increment(
3566 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3569 /* advertise type-5 routes */
3570 if (advertise_type5_routes(bgp_vrf
, afi
))
3571 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3575 DEFUN (no_bgp_evpn_advertise_type5
,
3576 no_bgp_evpn_advertise_type5_cmd
,
3577 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3579 "Advertise prefix routes\n"
3583 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3589 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3590 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3592 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3594 "%%only ipv4 or ipv6 address families are supported");
3598 if (safi
!= SAFI_UNICAST
) {
3600 "%%only ipv4 unicast or ipv6 unicast are supported");
3604 if (afi
== AFI_IP
) {
3606 /* if we are not advertising ipv4 prefix as type-5
3609 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3610 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3611 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3612 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3613 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3617 /* if we are not advertising ipv6 prefix as type-5
3620 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3621 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3622 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3623 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3624 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3628 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3629 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3630 XFREE(MTYPE_ROUTE_MAP_NAME
,
3631 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3632 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3633 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3640 * Display VNI information - for all or a specific VNI
3642 DEFUN(show_bgp_l2vpn_evpn_vni
,
3643 show_bgp_l2vpn_evpn_vni_cmd
,
3644 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3653 struct bgp
*bgp_evpn
;
3657 json_object
*json
= NULL
;
3658 uint32_t num_l2vnis
= 0;
3659 uint32_t num_l3vnis
= 0;
3660 uint32_t num_vnis
= 0;
3661 struct listnode
*node
= NULL
;
3662 struct bgp
*bgp_temp
= NULL
;
3664 uj
= use_json(argc
, argv
);
3666 bgp_evpn
= bgp_get_evpn();
3670 if (!argv_find(argv
, argc
, "evpn", &idx
))
3674 json
= json_object_new_object();
3676 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3678 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3680 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3681 if (bgp_temp
->l3vni
)
3684 num_vnis
= num_l2vnis
+ num_l3vnis
;
3686 json_object_string_add(json
, "advertiseGatewayMacip",
3687 bgp_evpn
->advertise_gw_macip
3690 json_object_string_add(json
, "advertiseAllVnis",
3691 is_evpn_enabled() ? "Enabled"
3693 json_object_string_add(
3695 bgp_evpn
->vxlan_flood_ctrl
3696 == VXLAN_FLOOD_HEAD_END_REPL
3697 ? "Head-end replication"
3699 json_object_int_add(json
, "numVnis", num_vnis
);
3700 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3701 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3703 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3704 bgp_evpn
->advertise_gw_macip
? "Enabled"
3706 vty_out(vty
, "Advertise SVI Macip: %s\n",
3707 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3709 vty_out(vty
, "Advertise All VNI flag: %s\n",
3710 is_evpn_enabled() ? "Enabled" : "Disabled");
3711 vty_out(vty
, "BUM flooding: %s\n",
3712 bgp_evpn
->vxlan_flood_ctrl
3713 == VXLAN_FLOOD_HEAD_END_REPL
3714 ? "Head-end replication"
3716 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3717 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3719 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3723 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3726 /* Display specific VNI */
3727 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3728 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3732 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3733 json
, JSON_C_TO_STRING_PRETTY
));
3734 json_object_free(json
);
3741 DEFUN(show_bgp_l2vpn_evpn_es
,
3742 show_bgp_l2vpn_evpn_es_cmd
,
3743 "show bgp l2vpn evpn es [ESI] [json]",
3748 "ethernet-Segment\n"
3749 "Ethernet-Segment Identifier\n"
3755 json_object
*json
= NULL
;
3756 struct bgp
*bgp
= NULL
;
3758 memset(&esi
, 0, sizeof(esi
));
3759 uj
= use_json(argc
, argv
);
3761 bgp
= bgp_get_evpn();
3765 if (!argv_find(argv
, argc
, "evpn", &idx
))
3768 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3769 (!uj
&& argc
== (idx
+ 1) + 1)) {
3772 evpn_show_all_es(vty
, bgp
, json
);
3775 /* show a specific ES */
3777 /* get the ESI - ESI-ID is at argv[5] */
3778 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3779 vty_out(vty
, "%% Malformed ESI\n");
3782 evpn_show_es(vty
, bgp
, &esi
, json
);
3786 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3787 json
, JSON_C_TO_STRING_PRETTY
));
3788 json_object_free(json
);
3795 * Display EVPN neighbor summary.
3797 DEFUN(show_bgp_l2vpn_evpn_summary
,
3798 show_bgp_l2vpn_evpn_summary_cmd
,
3799 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3806 "Summary of BGP neighbor status\n"
3807 "Show only sessions not in Established state\n"
3811 bool uj
= use_json(argc
, argv
);
3813 bool show_failed
= false;
3815 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3816 vrf
= argv
[++idx_vrf
]->arg
;
3817 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3819 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3824 * Display global EVPN routing table.
3826 DEFUN(show_bgp_l2vpn_evpn_route
,
3827 show_bgp_l2vpn_evpn_route_cmd
,
3828 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3833 "EVPN route information\n"
3834 "Display Detailed Information\n"
3835 "Specify Route type\n"
3836 "MAC-IP (Type-2) route\n"
3837 "Multicast (Type-3) route\n"
3838 "Ethernet Segment (type-4) route \n"
3839 "Prefix (type-5 )route\n"
3847 json_object
*json
= NULL
;
3849 uj
= use_json(argc
, argv
);
3851 bgp
= bgp_get_evpn();
3856 json
= json_object_new_object();
3859 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3860 /* Specific type is requested */
3861 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3862 type
= BGP_EVPN_MAC_IP_ROUTE
;
3863 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3864 type
= BGP_EVPN_IMET_ROUTE
;
3865 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
3866 type
= BGP_EVPN_ES_ROUTE
;
3867 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
3868 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3873 if (argv_find(argv
, argc
, "detail", &detail
))
3876 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3879 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3880 json
, JSON_C_TO_STRING_PRETTY
));
3881 json_object_free(json
);
3887 * Display global EVPN routing table for specific RD.
3889 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3890 show_bgp_l2vpn_evpn_route_rd_cmd
,
3891 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3896 "EVPN route information\n"
3897 "Route Distinguisher\n"
3898 "ASN:XX or A.B.C.D:XX\n"
3899 "Specify Route type\n"
3900 "MAC-IP (Type-2) route\n"
3901 "Multicast (Type-3) route\n"
3902 "Ethernet Segment route\n"
3908 struct prefix_rd prd
;
3913 json_object
*json
= NULL
;
3915 bgp
= bgp_get_evpn();
3919 /* check if we need json output */
3920 uj
= use_json(argc
, argv
);
3922 json
= json_object_new_object();
3925 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3926 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3929 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3935 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3936 /* Specific type is requested */
3937 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3938 type
= BGP_EVPN_MAC_IP_ROUTE
;
3939 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3940 type
= BGP_EVPN_IMET_ROUTE
;
3941 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3942 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3947 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3950 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3951 json
, JSON_C_TO_STRING_PRETTY
));
3952 json_object_free(json
);
3959 * Display global EVPN routing table for specific RD and MACIP.
3961 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3962 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3963 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3968 "EVPN route information\n"
3969 "Route Distinguisher\n"
3970 "ASN:XX or A.B.C.D:XX\n"
3972 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3974 "IP address (IPv4 or IPv6)\n"
3979 struct prefix_rd prd
;
3986 json_object
*json
= NULL
;
3988 memset(&mac
, 0, sizeof(struct ethaddr
));
3989 memset(&ip
, 0, sizeof(struct ipaddr
));
3991 bgp
= bgp_get_evpn();
3995 /* check if we need json output */
3996 uj
= use_json(argc
, argv
);
3998 json
= json_object_new_object();
4001 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4002 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4004 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4010 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4011 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4012 vty_out(vty
, "%% Malformed MAC address\n");
4017 /* get the ip if specified */
4018 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4019 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4020 vty_out(vty
, "%% Malformed IP address\n");
4025 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4028 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4029 json
, JSON_C_TO_STRING_PRETTY
));
4030 json_object_free(json
);
4036 /* Display per ESI routing table */
4037 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4038 show_bgp_l2vpn_evpn_route_esi_cmd
,
4039 "show bgp l2vpn evpn route esi ESI [json]",
4044 "EVPN route information\n"
4045 "Ethernet Segment Identifier\n"
4051 struct bgp
*bgp
= NULL
;
4052 json_object
*json
= NULL
;
4054 memset(&esi
, 0, sizeof(esi
));
4055 bgp
= bgp_get_evpn();
4059 uj
= use_json(argc
, argv
);
4061 json
= json_object_new_object();
4063 /* get the ESI - ESI-ID is at argv[6] */
4064 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4065 vty_out(vty
, "%% Malformed ESI\n");
4069 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4072 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4073 json
, JSON_C_TO_STRING_PRETTY
));
4074 json_object_free(json
);
4082 * Display per-VNI EVPN routing table.
4084 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4085 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4090 "EVPN route information\n"
4091 "VXLAN Network Identifier\n"
4093 "Specify Route type\n"
4094 "MAC-IP (Type-2) route\n"
4095 "Multicast (Type-3) route\n"
4097 "Remote VTEP IP address\n"
4102 struct in_addr vtep_ip
;
4106 json_object
*json
= NULL
;
4108 bgp
= bgp_get_evpn();
4112 /* check if we need json output */
4113 uj
= use_json(argc
, argv
);
4115 json
= json_object_new_object();
4117 if (!argv_find(argv
, argc
, "evpn", &idx
))
4122 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4124 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4125 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4126 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4127 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4128 type
= BGP_EVPN_MAC_IP_ROUTE
;
4129 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4130 type
= BGP_EVPN_IMET_ROUTE
;
4133 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4134 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4135 vty_out(vty
, "%% Malformed VTEP IP address\n");
4142 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4145 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4146 json
, JSON_C_TO_STRING_PRETTY
));
4147 json_object_free(json
);
4154 * Display per-VNI EVPN routing table for specific MACIP.
4156 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4157 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4158 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4163 "EVPN route information\n"
4164 "VXLAN Network Identifier\n"
4167 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4169 "IP address (IPv4 or IPv6)\n"
4178 json_object
*json
= NULL
;
4180 bgp
= bgp_get_evpn();
4184 /* check if we need json output */
4185 uj
= use_json(argc
, argv
);
4187 json
= json_object_new_object();
4189 if (!argv_find(argv
, argc
, "evpn", &idx
))
4193 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4196 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4197 vty_out(vty
, "%% Malformed MAC address\n");
4202 memset(&ip
, 0, sizeof(ip
));
4203 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4205 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4206 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4207 vty_out(vty
, "%% Malformed IP address\n");
4212 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4215 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4216 json
, JSON_C_TO_STRING_PRETTY
));
4217 json_object_free(json
);
4224 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4226 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4227 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4228 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4233 "EVPN route information\n"
4234 "VXLAN Network Identifier\n"
4236 "Multicast (Type-3) route\n"
4237 "Originating Router IP address\n"
4243 struct in_addr orig_ip
;
4246 json_object
*json
= NULL
;
4248 bgp
= bgp_get_evpn();
4252 /* check if we need json output */
4253 uj
= use_json(argc
, argv
);
4255 json
= json_object_new_object();
4257 if (!argv_find(argv
, argc
, "evpn", &idx
))
4261 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4264 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4266 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4270 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4273 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4274 json
, JSON_C_TO_STRING_PRETTY
));
4275 json_object_free(json
);
4282 * Display per-VNI EVPN routing table - for all VNIs.
4284 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4285 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4286 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4291 "EVPN route information\n"
4292 "VXLAN Network Identifier\n"
4294 "Print Detailed Output\n"
4296 "Remote VTEP IP address\n"
4300 struct in_addr vtep_ip
;
4303 json_object
*json
= NULL
;
4304 /* Detail Adjust. Adjust indexes according to detail option */
4307 bgp
= bgp_get_evpn();
4311 /* check if we need json output */
4312 uj
= use_json(argc
, argv
);
4314 json
= json_object_new_object();
4316 if (!argv_find(argv
, argc
, "evpn", &idx
))
4319 if (argv_find(argv
, argc
, "detail", &da
))
4322 /* vtep-ip position depends on detail option */
4324 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4326 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4327 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4328 vty_out(vty
, "%% Malformed VTEP IP address\n");
4333 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4336 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4337 json
, JSON_C_TO_STRING_PRETTY
));
4338 json_object_free(json
);
4345 * Display EVPN import route-target hash table
4347 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4348 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4349 "show bgp l2vpn evpn vrf-import-rt [json]",
4354 "Show vrf import route target\n"
4358 struct bgp
*bgp_evpn
= NULL
;
4359 json_object
*json
= NULL
;
4361 bgp_evpn
= bgp_get_evpn();
4365 uj
= use_json(argc
, argv
);
4367 json
= json_object_new_object();
4369 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4372 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4373 json
, JSON_C_TO_STRING_PRETTY
));
4374 json_object_free(json
);
4381 * Display EVPN import route-target hash table
4383 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4384 show_bgp_l2vpn_evpn_import_rt_cmd
,
4385 "show bgp l2vpn evpn import-rt [json]",
4390 "Show import route target\n"
4395 json_object
*json
= NULL
;
4397 bgp
= bgp_get_evpn();
4401 uj
= use_json(argc
, argv
);
4403 json
= json_object_new_object();
4405 evpn_show_import_rts(vty
, bgp
, json
);
4408 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4409 json
, JSON_C_TO_STRING_PRETTY
));
4410 json_object_free(json
);
4416 DEFUN(test_adv_evpn_type4_route
,
4417 test_adv_evpn_type4_route_cmd
,
4419 "Advertise EVPN ES route\n"
4420 "Ethernet-segment\n"
4421 "Ethernet-Segment Identifier\n")
4426 struct ipaddr vtep_ip
;
4428 bgp
= bgp_get_evpn();
4430 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4434 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4435 vty_out(vty
, "%%Malformed ESI\n");
4439 vtep_ip
.ipa_type
= IPADDR_V4
;
4440 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4442 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4444 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4450 DEFUN(test_withdraw_evpn_type4_route
,
4451 test_withdraw_evpn_type4_route_cmd
,
4453 "Advertise EVPN ES route\n"
4454 "Ethernet-segment\n"
4455 "Ethernet-Segment Identifier\n")
4460 struct ipaddr vtep_ip
;
4462 bgp
= bgp_get_evpn();
4464 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4468 if (!bgp
->peer_self
) {
4469 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4473 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4474 vty_out(vty
, "%%Malformed ESI\n");
4478 vtep_ip
.ipa_type
= IPADDR_V4
;
4479 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4480 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4482 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4488 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4489 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4493 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4494 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4495 "Summary of BGP neighbor status\n" JSON_STR
)
4497 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4498 "show bgp evpn route [detail] [type <macip|multicast>]",
4499 SHOW_STR BGP_STR EVPN_HELP_STR
4500 "EVPN route information\n"
4501 "Display Detailed Information\n"
4502 "Specify Route type\n"
4503 "MAC-IP (Type-2) route\n"
4504 "Multicast (Type-3) route\n")
4507 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4508 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4509 SHOW_STR BGP_STR EVPN_HELP_STR
4510 "EVPN route information\n"
4511 "Route Distinguisher\n"
4512 "ASN:XX or A.B.C.D:XX\n"
4513 "Specify Route type\n"
4514 "MAC-IP (Type-2) route\n"
4515 "Multicast (Type-3) route\n")
4518 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4519 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4520 SHOW_STR BGP_STR EVPN_HELP_STR
4521 "EVPN route information\n"
4522 "Route Distinguisher\n"
4523 "ASN:XX or A.B.C.D:XX\n"
4525 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4527 "IP address (IPv4 or IPv6)\n")
4530 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4531 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4532 SHOW_STR BGP_STR EVPN_HELP_STR
4533 "EVPN route information\n"
4534 "VXLAN Network Identifier\n"
4536 "Specify Route type\n"
4537 "MAC-IP (Type-2) route\n"
4538 "Multicast (Type-3) route\n"
4540 "Remote VTEP IP address\n")
4542 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4543 show_bgp_evpn_route_vni_macip_cmd
,
4544 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4545 SHOW_STR BGP_STR EVPN_HELP_STR
4546 "EVPN route information\n"
4547 "VXLAN Network Identifier\n"
4550 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4552 "IP address (IPv4 or IPv6)\n")
4554 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4555 show_bgp_evpn_route_vni_multicast_cmd
,
4556 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4557 SHOW_STR BGP_STR EVPN_HELP_STR
4558 "EVPN route information\n"
4559 "VXLAN Network Identifier\n"
4561 "Multicast (Type-3) route\n"
4562 "Originating Router IP address\n")
4564 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4565 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4566 SHOW_STR BGP_STR EVPN_HELP_STR
4567 "EVPN route information\n"
4568 "VXLAN Network Identifier\n"
4570 "Print Detailed Output\n"
4572 "Remote VTEP IP address\n")
4574 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4575 "show bgp evpn import-rt",
4576 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4578 DEFUN_NOSH (bgp_evpn_vni
,
4580 "vni " CMD_VNI_RANGE
,
4581 "VXLAN Network Identifier\n"
4585 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4586 struct bgpevpn
*vpn
;
4591 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4593 /* Create VNI, or mark as configured. */
4594 vpn
= evpn_create_update_vni(bgp
, vni
);
4596 vty_out(vty
, "%% Failed to create VNI \n");
4600 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4604 DEFUN (no_bgp_evpn_vni
,
4605 no_bgp_evpn_vni_cmd
,
4606 "no vni " CMD_VNI_RANGE
,
4608 "VXLAN Network Identifier\n"
4612 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4613 struct bgpevpn
*vpn
;
4618 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4620 /* Check if we should disallow. */
4621 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4623 vty_out(vty
, "%% Specified VNI does not exist\n");
4626 if (!is_vni_configured(vpn
)) {
4627 vty_out(vty
, "%% Specified VNI is not configured\n");
4631 evpn_delete_vni(bgp
, vpn
);
4635 DEFUN_NOSH (exit_vni
,
4638 "Exit from VNI mode\n")
4640 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4641 vty
->node
= BGP_EVPN_NODE
;
4645 DEFUN (bgp_evpn_vrf_rd
,
4646 bgp_evpn_vrf_rd_cmd
,
4647 "rd ASN:NN_OR_IP-ADDRESS:NN",
4648 "Route Distinguisher\n"
4649 "ASN:XX or A.B.C.D:XX\n")
4652 struct prefix_rd prd
;
4653 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4658 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4660 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4664 /* If same as existing value, there is nothing more to do. */
4665 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4668 /* Configure or update the RD. */
4669 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4673 DEFUN (no_bgp_evpn_vrf_rd
,
4674 no_bgp_evpn_vrf_rd_cmd
,
4675 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4677 "Route Distinguisher\n"
4678 "ASN:XX or A.B.C.D:XX\n")
4681 struct prefix_rd prd
;
4682 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4687 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4689 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4693 /* Check if we should disallow. */
4694 if (!is_vrf_rd_configured(bgp_vrf
)) {
4695 vty_out(vty
, "%% RD is not configured for this VRF\n");
4699 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4701 "%% RD specified does not match configuration for this VRF\n");
4705 evpn_unconfigure_vrf_rd(bgp_vrf
);
4709 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4710 no_bgp_evpn_vrf_rd_without_val_cmd
,
4713 "Route Distinguisher\n")
4715 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4720 /* Check if we should disallow. */
4721 if (!is_vrf_rd_configured(bgp_vrf
)) {
4722 vty_out(vty
, "%% RD is not configured for this VRF\n");
4726 evpn_unconfigure_vrf_rd(bgp_vrf
);
4730 DEFUN (bgp_evpn_vni_rd
,
4731 bgp_evpn_vni_rd_cmd
,
4732 "rd ASN:NN_OR_IP-ADDRESS:NN",
4733 "Route Distinguisher\n"
4734 "ASN:XX or A.B.C.D:XX\n")
4736 struct prefix_rd prd
;
4737 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4738 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4744 if (!EVPN_ENABLED(bgp
)) {
4746 "This command is only supported under EVPN VRF\n");
4750 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4752 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4756 /* If same as existing value, there is nothing more to do. */
4757 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4760 /* Configure or update the RD. */
4761 evpn_configure_rd(bgp
, vpn
, &prd
);
4765 DEFUN (no_bgp_evpn_vni_rd
,
4766 no_bgp_evpn_vni_rd_cmd
,
4767 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4769 "Route Distinguisher\n"
4770 "ASN:XX or A.B.C.D:XX\n")
4772 struct prefix_rd prd
;
4773 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4774 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4780 if (!EVPN_ENABLED(bgp
)) {
4782 "This command is only supported under EVPN VRF\n");
4786 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4788 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4792 /* Check if we should disallow. */
4793 if (!is_rd_configured(vpn
)) {
4794 vty_out(vty
, "%% RD is not configured for this VNI\n");
4798 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4800 "%% RD specified does not match configuration for this VNI\n");
4804 evpn_unconfigure_rd(bgp
, vpn
);
4808 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4809 no_bgp_evpn_vni_rd_without_val_cmd
,
4812 "Route Distinguisher\n")
4814 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4815 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4820 if (!EVPN_ENABLED(bgp
)) {
4822 "This command is only supported under EVPN VRF\n");
4826 /* Check if we should disallow. */
4827 if (!is_rd_configured(vpn
)) {
4828 vty_out(vty
, "%% RD is not configured for this VNI\n");
4832 evpn_unconfigure_rd(bgp
, vpn
);
4837 * Loop over all extended-communities in the route-target list rtl and
4838 * return 1 if we find ecomtarget
4840 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4841 struct ecommunity
*ecomtarget
)
4843 struct listnode
*node
, *nnode
;
4844 struct ecommunity
*ecom
;
4846 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4847 if (ecommunity_match(ecom
, ecomtarget
))
4854 /* display L3VNI related info for a VRF instance */
4855 DEFUN (show_bgp_vrf_l3vni_info
,
4856 show_bgp_vrf_l3vni_info_cmd
,
4857 "show bgp vrf VRFNAME vni [json]",
4865 char buf
[ETHER_ADDR_STRLEN
];
4866 char buf1
[INET6_ADDRSTRLEN
];
4868 const char *name
= NULL
;
4869 struct bgp
*bgp
= NULL
;
4870 struct listnode
*node
= NULL
;
4871 struct bgpevpn
*vpn
= NULL
;
4872 struct ecommunity
*ecom
= NULL
;
4873 json_object
*json
= NULL
;
4874 json_object
*json_vnis
= NULL
;
4875 json_object
*json_export_rts
= NULL
;
4876 json_object
*json_import_rts
= NULL
;
4877 bool uj
= use_json(argc
, argv
);
4880 json
= json_object_new_object();
4881 json_vnis
= json_object_new_array();
4882 json_export_rts
= json_object_new_array();
4883 json_import_rts
= json_object_new_array();
4886 name
= argv
[idx_vrf
]->arg
;
4887 bgp
= bgp_lookup_by_name(name
);
4890 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4892 json_object_string_add(json
, "warning",
4893 "BGP instance not found");
4894 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4895 json_object_free(json
);
4901 vty_out(vty
, "BGP VRF: %s\n", name
);
4902 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4903 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4904 vty_out(vty
, " Rmac: %s\n",
4905 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4906 vty_out(vty
, " VNI Filter: %s\n",
4907 CHECK_FLAG(bgp
->vrf_flags
,
4908 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4909 ? "prefix-routes-only"
4911 vty_out(vty
, " L2-VNI List:\n");
4913 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4914 vty_out(vty
, "%u ", vpn
->vni
);
4916 vty_out(vty
, " Export-RTs:\n");
4918 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4919 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4921 vty_out(vty
, " Import-RTs:\n");
4923 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4924 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4926 vty_out(vty
, " RD: %s\n",
4927 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4929 json_object_string_add(json
, "vrf", name
);
4930 json_object_string_add(json
, "local-ip",
4931 inet_ntoa(bgp
->originator_ip
));
4932 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4933 json_object_string_add(
4935 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4936 json_object_string_add(
4938 CHECK_FLAG(bgp
->vrf_flags
,
4939 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4940 ? "prefix-routes-only"
4942 /* list of l2vnis */
4943 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4944 json_object_array_add(json_vnis
,
4945 json_object_new_int(vpn
->vni
));
4946 json_object_object_add(json
, "l2vnis", json_vnis
);
4949 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4950 json_object_array_add(
4952 json_object_new_string(ecommunity_str(ecom
)));
4953 json_object_object_add(json
, "export-rts", json_export_rts
);
4956 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4957 json_object_array_add(
4959 json_object_new_string(ecommunity_str(ecom
)));
4960 json_object_object_add(json
, "import-rts", json_import_rts
);
4961 json_object_string_add(
4963 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4967 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4968 json
, JSON_C_TO_STRING_PRETTY
));
4969 json_object_free(json
);
4974 /* import/export rt for l3vni-vrf */
4975 DEFUN (bgp_evpn_vrf_rt
,
4976 bgp_evpn_vrf_rt_cmd
,
4977 "route-target <both|import|export> RT",
4979 "import and export\n"
4982 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4985 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4986 struct ecommunity
*ecomadd
= NULL
;
4991 if (!strcmp(argv
[1]->arg
, "import"))
4992 rt_type
= RT_TYPE_IMPORT
;
4993 else if (!strcmp(argv
[1]->arg
, "export"))
4994 rt_type
= RT_TYPE_EXPORT
;
4995 else if (!strcmp(argv
[1]->arg
, "both"))
4996 rt_type
= RT_TYPE_BOTH
;
4998 vty_out(vty
, "%% Invalid Route Target type\n");
5002 /* Add/update the import route-target */
5003 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5004 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5005 ECOMMUNITY_ROUTE_TARGET
, 0);
5007 vty_out(vty
, "%% Malformed Route Target list\n");
5010 ecommunity_str(ecomadd
);
5012 /* Do nothing if we already have this import route-target */
5013 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5014 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5017 /* Add/update the export route-target */
5018 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5019 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5020 ECOMMUNITY_ROUTE_TARGET
, 0);
5022 vty_out(vty
, "%% Malformed Route Target list\n");
5025 ecommunity_str(ecomadd
);
5027 /* Do nothing if we already have this export route-target */
5028 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5029 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5035 DEFUN (no_bgp_evpn_vrf_rt
,
5036 no_bgp_evpn_vrf_rt_cmd
,
5037 "no route-target <both|import|export> RT",
5040 "import and export\n"
5043 "ASN:XX or A.B.C.D:XX\n")
5045 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5046 int rt_type
, found_ecomdel
;
5047 struct ecommunity
*ecomdel
= NULL
;
5052 if (!strcmp(argv
[2]->arg
, "import"))
5053 rt_type
= RT_TYPE_IMPORT
;
5054 else if (!strcmp(argv
[2]->arg
, "export"))
5055 rt_type
= RT_TYPE_EXPORT
;
5056 else if (!strcmp(argv
[2]->arg
, "both"))
5057 rt_type
= RT_TYPE_BOTH
;
5059 vty_out(vty
, "%% Invalid Route Target type\n");
5063 if (rt_type
== RT_TYPE_IMPORT
) {
5064 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5066 "%% Import RT is not configured for this VRF\n");
5069 } else if (rt_type
== RT_TYPE_EXPORT
) {
5070 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5072 "%% Export RT is not configured for this VRF\n");
5075 } else if (rt_type
== RT_TYPE_BOTH
) {
5076 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5077 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5079 "%% Import/Export RT is not configured for this VRF\n");
5084 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5086 vty_out(vty
, "%% Malformed Route Target list\n");
5089 ecommunity_str(ecomdel
);
5091 if (rt_type
== RT_TYPE_IMPORT
) {
5092 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5095 "%% RT specified does not match configuration for this VRF\n");
5098 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5099 } else if (rt_type
== RT_TYPE_EXPORT
) {
5100 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5103 "%% RT specified does not match configuration for this VRF\n");
5106 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5107 } else if (rt_type
== RT_TYPE_BOTH
) {
5110 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5112 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5116 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5118 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5122 if (!found_ecomdel
) {
5124 "%% RT specified does not match configuration for this VRF\n");
5132 DEFUN (bgp_evpn_vni_rt
,
5133 bgp_evpn_vni_rt_cmd
,
5134 "route-target <both|import|export> RT",
5136 "import and export\n"
5139 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5141 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5142 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5144 struct ecommunity
*ecomadd
= NULL
;
5149 if (!EVPN_ENABLED(bgp
)) {
5151 "This command is only supported under EVPN VRF\n");
5155 if (!strcmp(argv
[1]->text
, "import"))
5156 rt_type
= RT_TYPE_IMPORT
;
5157 else if (!strcmp(argv
[1]->text
, "export"))
5158 rt_type
= RT_TYPE_EXPORT
;
5159 else if (!strcmp(argv
[1]->text
, "both"))
5160 rt_type
= RT_TYPE_BOTH
;
5162 vty_out(vty
, "%% Invalid Route Target type\n");
5166 /* Add/update the import route-target */
5167 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5168 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5169 ECOMMUNITY_ROUTE_TARGET
, 0);
5171 vty_out(vty
, "%% Malformed Route Target list\n");
5174 ecommunity_str(ecomadd
);
5176 /* Do nothing if we already have this import route-target */
5177 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5178 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5181 /* Add/update the export route-target */
5182 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5183 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5184 ECOMMUNITY_ROUTE_TARGET
, 0);
5186 vty_out(vty
, "%% Malformed Route Target list\n");
5189 ecommunity_str(ecomadd
);
5191 /* Do nothing if we already have this export route-target */
5192 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5193 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5199 DEFUN (no_bgp_evpn_vni_rt
,
5200 no_bgp_evpn_vni_rt_cmd
,
5201 "no route-target <both|import|export> RT",
5204 "import and export\n"
5207 "ASN:XX or A.B.C.D:XX\n")
5209 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5210 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5211 int rt_type
, found_ecomdel
;
5212 struct ecommunity
*ecomdel
= NULL
;
5217 if (!EVPN_ENABLED(bgp
)) {
5219 "This command is only supported under EVPN VRF\n");
5223 if (!strcmp(argv
[2]->text
, "import"))
5224 rt_type
= RT_TYPE_IMPORT
;
5225 else if (!strcmp(argv
[2]->text
, "export"))
5226 rt_type
= RT_TYPE_EXPORT
;
5227 else if (!strcmp(argv
[2]->text
, "both"))
5228 rt_type
= RT_TYPE_BOTH
;
5230 vty_out(vty
, "%% Invalid Route Target type\n");
5234 /* The user did "no route-target import", check to see if there are any
5235 * import route-targets configured. */
5236 if (rt_type
== RT_TYPE_IMPORT
) {
5237 if (!is_import_rt_configured(vpn
)) {
5239 "%% Import RT is not configured for this VNI\n");
5242 } else if (rt_type
== RT_TYPE_EXPORT
) {
5243 if (!is_export_rt_configured(vpn
)) {
5245 "%% Export RT is not configured for this VNI\n");
5248 } else if (rt_type
== RT_TYPE_BOTH
) {
5249 if (!is_import_rt_configured(vpn
)
5250 && !is_export_rt_configured(vpn
)) {
5252 "%% Import/Export RT is not configured for this VNI\n");
5257 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5259 vty_out(vty
, "%% Malformed Route Target list\n");
5262 ecommunity_str(ecomdel
);
5264 if (rt_type
== RT_TYPE_IMPORT
) {
5265 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5267 "%% RT specified does not match configuration for this VNI\n");
5270 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5271 } else if (rt_type
== RT_TYPE_EXPORT
) {
5272 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5274 "%% RT specified does not match configuration for this VNI\n");
5277 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5278 } else if (rt_type
== RT_TYPE_BOTH
) {
5281 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5282 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5286 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5287 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5291 if (!found_ecomdel
) {
5293 "%% RT specified does not match configuration for this VNI\n");
5301 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5302 no_bgp_evpn_vni_rt_without_val_cmd
,
5303 "no route-target <import|export>",
5309 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5310 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5316 if (!EVPN_ENABLED(bgp
)) {
5318 "This command is only supported under EVPN VRF\n");
5322 if (!strcmp(argv
[2]->text
, "import")) {
5323 rt_type
= RT_TYPE_IMPORT
;
5324 } else if (!strcmp(argv
[2]->text
, "export")) {
5325 rt_type
= RT_TYPE_EXPORT
;
5327 vty_out(vty
, "%% Invalid Route Target type\n");
5331 /* Check if we should disallow. */
5332 if (rt_type
== RT_TYPE_IMPORT
) {
5333 if (!is_import_rt_configured(vpn
)) {
5335 "%% Import RT is not configured for this VNI\n");
5339 if (!is_export_rt_configured(vpn
)) {
5341 "%% Export RT is not configured for this VNI\n");
5346 /* Unconfigure the RT. */
5347 if (rt_type
== RT_TYPE_IMPORT
)
5348 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5350 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5354 static int vni_cmp(const void **a
, const void **b
)
5356 const struct bgpevpn
*first
= *a
;
5357 const struct bgpevpn
*secnd
= *b
;
5359 return secnd
->vni
- first
->vni
;
5363 * Output EVPN configuration information.
5365 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5368 char buf1
[RD_ADDRSTRLEN
];
5371 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5372 struct listnode
*ln
;
5373 struct bgpevpn
*data
;
5375 list_sort(vnilist
, vni_cmp
);
5376 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5377 write_vni_config(vty
, data
);
5379 list_delete(&vnilist
);
5382 if (bgp
->advertise_all_vni
)
5383 vty_out(vty
, " advertise-all-vni\n");
5385 if (bgp
->advertise_autort_rfc8365
)
5386 vty_out(vty
, " autort rfc8365-compatible\n");
5388 if (bgp
->advertise_gw_macip
)
5389 vty_out(vty
, " advertise-default-gw\n");
5391 if (bgp
->evpn_info
->advertise_svi_macip
)
5392 vty_out(vty
, " advertise-svi-ip\n");
5394 if (!bgp
->evpn_info
->dup_addr_detect
)
5395 vty_out(vty
, " no dup-addr-detection\n");
5397 if (bgp
->evpn_info
->dad_max_moves
!=
5398 EVPN_DAD_DEFAULT_MAX_MOVES
||
5399 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5400 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5401 bgp
->evpn_info
->dad_max_moves
,
5402 bgp
->evpn_info
->dad_time
);
5404 if (bgp
->evpn_info
->dad_freeze
) {
5405 if (bgp
->evpn_info
->dad_freeze_time
)
5407 " dup-addr-detection freeze %u\n",
5408 bgp
->evpn_info
->dad_freeze_time
);
5411 " dup-addr-detection freeze permanent\n");
5414 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5415 vty_out(vty
, " flooding disable\n");
5417 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5418 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5419 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5420 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5421 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5423 vty_out(vty
, " advertise ipv4 unicast\n");
5426 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5427 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5428 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5429 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5430 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5432 vty_out(vty
, " advertise ipv6 unicast\n");
5435 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5436 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5437 vty_out(vty
, " default-originate ipv4\n");
5439 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5440 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5441 vty_out(vty
, " default-originate ipv6\n");
5443 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5444 vty_out(vty
, " rd %s\n",
5445 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5447 /* import route-target */
5448 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5450 struct listnode
*node
, *nnode
;
5451 struct ecommunity
*ecom
;
5453 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5455 ecom_str
= ecommunity_ecom2str(
5456 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5457 vty_out(vty
, " route-target import %s\n", ecom_str
);
5458 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5462 /* export route-target */
5463 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5465 struct listnode
*node
, *nnode
;
5466 struct ecommunity
*ecom
;
5468 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5470 ecom_str
= ecommunity_ecom2str(
5471 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5472 vty_out(vty
, " route-target export %s\n", ecom_str
);
5473 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5478 void bgp_ethernetvpn_init(void)
5480 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5481 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5482 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5483 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5484 install_element(VIEW_NODE
,
5485 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5486 install_element(VIEW_NODE
,
5487 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5490 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5493 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5494 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5495 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5496 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5497 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5498 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5499 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5500 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5501 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5502 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5503 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5504 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5505 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5506 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5507 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5508 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5509 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5510 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5511 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5512 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5515 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5516 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5518 /* "show bgp l2vpn evpn" commands. */
5519 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5520 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5521 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5522 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5523 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5524 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5525 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5526 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5527 install_element(VIEW_NODE
,
5528 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5529 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5530 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5531 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5532 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5534 /* "show bgp evpn" commands. */
5535 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5536 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5537 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5538 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5539 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5540 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5541 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5542 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5543 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5544 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5545 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5546 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5548 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5549 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5550 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5551 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5552 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5553 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5554 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5555 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5556 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5557 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5558 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5559 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5560 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5561 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5562 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5563 install_element(BGP_EVPN_VNI_NODE
,
5564 &bgp_evpn_advertise_default_gw_vni_cmd
);
5565 install_element(BGP_EVPN_VNI_NODE
,
5566 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5567 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5568 install_element(BGP_EVPN_VNI_NODE
,
5569 &no_bgp_evpn_advertise_vni_subnet_cmd
);