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
,
279 char *rd_str
, int len
)
286 pnt
= rd_rn
->p
.u
.val
;
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
292 vty_out(vty
, "Route Distinguisher: ");
296 decode_rd_as(pnt
+ 2, &rd_as
);
297 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
299 json_object_string_add(json
, "rd", rd_str
);
301 vty_out(vty
, "%s\n", rd_str
);
305 decode_rd_as4(pnt
+ 2, &rd_as
);
306 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
308 json_object_string_add(json
, "rd", rd_str
);
310 vty_out(vty
, "%s\n", rd_str
);
314 decode_rd_ip(pnt
+ 2, &rd_ip
);
315 snprintf(rd_str
, len
, "%s:%d", inet_ntoa(rd_ip
.ip
),
318 json_object_string_add(json
, "rd", rd_str
);
320 vty_out(vty
, "%s\n", rd_str
);
325 snprintf(rd_str
, len
, "Unknown");
326 json_object_string_add(json
, "rd", rd_str
);
328 snprintf(rd_str
, len
, "Unknown RD type");
329 vty_out(vty
, "%s\n", rd_str
);
335 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
336 uint64_t tbl_ver
, json_object
*json
)
339 " Network Next Hop Metric LocPrf Weight Path\n";
344 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
345 tbl_ver
, inet_ntoa(bgp
->router_id
));
347 "Status codes: s suppressed, d damped, h history, "
348 "* valid, > best, i - internal\n");
349 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
351 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
352 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
353 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
354 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
355 vty_out(vty
, "%s", ri_header
);
358 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
361 char buf1
[INET6_ADDRSTRLEN
];
363 struct listnode
*node
, *nnode
;
364 struct ecommunity
*ecom
;
365 json_object
*json_import_rtl
= NULL
;
366 json_object
*json_export_rtl
= NULL
;
368 json_import_rtl
= json_export_rtl
= 0;
371 json_import_rtl
= json_object_new_array();
372 json_export_rtl
= json_object_new_array();
373 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
374 json_object_string_add(json
, "type", "L3");
375 json_object_string_add(json
, "kernelFlag", "Yes");
376 json_object_string_add(
378 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
379 json_object_string_add(json
, "originatorIp",
380 inet_ntoa(bgp_vrf
->originator_ip
));
381 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
382 json_object_string_add(json
, "advertiseSviMacip", "n/a");
383 json_object_to_json_string_ext(json
,
384 JSON_C_TO_STRING_NOSLASHESCAPE
);
386 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
387 vty_out(vty
, " (known to the kernel)");
390 vty_out(vty
, " Type: %s\n", "L3");
391 vty_out(vty
, " Tenant VRF: %s\n",
392 vrf_id_to_name(bgp_vrf
->vrf_id
));
393 vty_out(vty
, " RD: %s\n",
394 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
395 vty_out(vty
, " Originator IP: %s\n",
396 inet_ntoa(bgp_vrf
->originator_ip
));
397 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
398 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
402 vty_out(vty
, " Import Route Target:\n");
404 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
405 ecom_str
= ecommunity_ecom2str(ecom
,
406 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
409 json_object_array_add(json_import_rtl
,
410 json_object_new_string(ecom_str
));
412 vty_out(vty
, " %s\n", ecom_str
);
414 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
418 json_object_object_add(json
, "importRts", json_import_rtl
);
420 vty_out(vty
, " Export Route Target:\n");
422 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
423 ecom_str
= ecommunity_ecom2str(ecom
,
424 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
427 json_object_array_add(json_export_rtl
,
428 json_object_new_string(ecom_str
));
430 vty_out(vty
, " %s\n", ecom_str
);
432 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
436 json_object_object_add(json
, "exportRts", json_export_rtl
);
439 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
441 struct in_addr
*vtep
;
442 char buf
[ESI_STR_LEN
];
443 char buf1
[RD_ADDRSTRLEN
];
444 char buf2
[INET6_ADDRSTRLEN
];
445 struct listnode
*node
= NULL
;
446 json_object
*json_vteps
= NULL
;
449 json_vteps
= json_object_new_array();
450 json_object_string_add(json
, "esi",
451 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
452 json_object_string_add(json
, "rd",
453 prefix_rd2str(&es
->prd
, buf1
,
455 json_object_string_add(
456 json
, "originatorIp",
457 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
459 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
460 json_object_array_add(
461 json_vteps
, json_object_new_string(
464 json_object_object_add(json
, "vteps", json_vteps
);
466 vty_out(vty
, "ESI: %s\n",
467 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
468 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
470 vty_out(vty
, " Originator-IP: %s\n",
471 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
473 vty_out(vty
, " VTEP List:\n");
474 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
475 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
480 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
482 char buf1
[RD_ADDRSTRLEN
];
484 struct listnode
*node
, *nnode
;
485 struct ecommunity
*ecom
;
486 json_object
*json_import_rtl
= NULL
;
487 json_object
*json_export_rtl
= NULL
;
488 struct bgp
*bgp_evpn
;
490 bgp_evpn
= bgp_get_evpn();
493 json_import_rtl
= json_object_new_array();
494 json_export_rtl
= json_object_new_array();
495 json_object_int_add(json
, "vni", vpn
->vni
);
496 json_object_string_add(json
, "type", "L2");
497 json_object_string_add(json
, "kernelFlag",
498 is_vni_live(vpn
) ? "Yes" : "No");
499 json_object_string_add(
501 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
502 json_object_string_add(json
, "originatorIp",
503 inet_ntoa(vpn
->originator_ip
));
504 json_object_string_add(json
, "mcastGroup",
505 inet_ntoa(vpn
->mcast_grp
));
506 /* per vni knob is enabled -- Enabled
507 * Global knob is enabled -- Active
508 * default -- Disabled
510 if (!vpn
->advertise_gw_macip
&&
511 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
512 json_object_string_add(json
, "advertiseGatewayMacip",
514 else if (vpn
->advertise_gw_macip
)
515 json_object_string_add(json
, "advertiseGatewayMacip",
518 json_object_string_add(json
, "advertiseGatewayMacip",
520 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
521 bgp_evpn
->evpn_info
->advertise_svi_macip
)
522 json_object_string_add(json
, "advertiseSviMacip",
524 else if (vpn
->advertise_svi_macip
)
525 json_object_string_add(json
, "advertiseSviMacip",
528 json_object_string_add(json
, "advertiseSviMacip",
531 vty_out(vty
, "VNI: %d", vpn
->vni
);
532 if (is_vni_live(vpn
))
533 vty_out(vty
, " (known to the kernel)");
536 vty_out(vty
, " Type: %s\n", "L2");
537 vty_out(vty
, " Tenant-Vrf: %s\n",
538 vrf_id_to_name(vpn
->tenant_vrf_id
));
539 vty_out(vty
, " RD: %s\n",
540 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
541 vty_out(vty
, " Originator IP: %s\n",
542 inet_ntoa(vpn
->originator_ip
));
543 vty_out(vty
, " Mcast group: %s\n",
544 inet_ntoa(vpn
->mcast_grp
));
545 if (!vpn
->advertise_gw_macip
&&
546 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
547 vty_out(vty
, " Advertise-gw-macip : %s\n",
549 else if (vpn
->advertise_gw_macip
)
550 vty_out(vty
, " Advertise-gw-macip : %s\n",
553 vty_out(vty
, " Advertise-gw-macip : %s\n",
555 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
556 bgp_evpn
->evpn_info
->advertise_svi_macip
)
557 vty_out(vty
, " Advertise-svi-macip : %s\n",
559 else if (vpn
->advertise_svi_macip
)
560 vty_out(vty
, " Advertise-svi-macip : %s\n",
563 vty_out(vty
, " Advertise-svi-macip : %s\n",
568 vty_out(vty
, " Import Route Target:\n");
570 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
571 ecom_str
= ecommunity_ecom2str(ecom
,
572 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
575 json_object_array_add(json_import_rtl
,
576 json_object_new_string(ecom_str
));
578 vty_out(vty
, " %s\n", ecom_str
);
580 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
584 json_object_object_add(json
, "importRts", json_import_rtl
);
586 vty_out(vty
, " Export Route Target:\n");
588 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
589 ecom_str
= ecommunity_ecom2str(ecom
,
590 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
593 json_object_array_add(json_export_rtl
,
594 json_object_new_string(ecom_str
));
596 vty_out(vty
, " %s\n", ecom_str
);
598 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
602 json_object_object_add(json
, "exportRts", json_export_rtl
);
605 static void show_esi_routes(struct bgp
*bgp
,
612 struct bgp_path_info
*pi
;
613 uint32_t prefix_cnt
, path_cnt
;
616 prefix_cnt
= path_cnt
= 0;
618 tbl_ver
= es
->route_table
->version
;
619 for (rn
= bgp_table_top(es
->route_table
); rn
;
620 rn
= bgp_route_next(rn
)) {
621 int add_prefix_to_json
= 0;
622 char prefix_str
[BUFSIZ
];
623 json_object
*json_paths
= NULL
;
624 json_object
*json_prefix
= NULL
;
626 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
630 json_prefix
= json_object_new_object();
632 pi
= bgp_node_get_bgp_path_info(rn
);
634 /* Overall header/legend displayed once. */
636 bgp_evpn_show_route_header(vty
, bgp
,
645 json_paths
= json_object_new_array();
647 /* For EVPN, the prefix is displayed for each path (to fit in
648 * with code that already exists).
650 for (; pi
; pi
= pi
->next
) {
651 json_object
*json_path
= NULL
;
654 json_path
= json_object_new_array();
656 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
659 json_object_array_add(json_paths
, json_path
);
662 add_prefix_to_json
= 1;
665 if (json
&& add_prefix_to_json
) {
666 json_object_string_add(json_prefix
, "prefix",
668 json_object_int_add(json_prefix
, "prefixLen",
670 json_object_object_add(json_prefix
, "paths",
672 json_object_object_add(json
, prefix_str
, json_prefix
);
677 json_object_int_add(json
, "numPrefix", prefix_cnt
);
678 json_object_int_add(json
, "numPaths", path_cnt
);
681 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
683 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
684 prefix_cnt
, path_cnt
);
688 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
689 struct vty
*vty
, struct in_addr vtep_ip
,
690 json_object
*json
, int detail
)
693 struct bgp_path_info
*pi
;
694 struct bgp_table
*table
;
695 int header
= detail
? 0 : 1;
697 uint32_t prefix_cnt
, path_cnt
;
699 prefix_cnt
= path_cnt
= 0;
701 table
= vpn
->route_table
;
702 tbl_ver
= table
->version
;
703 for (rn
= bgp_table_top(table
); rn
;
704 rn
= bgp_route_next(rn
)) {
705 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
706 int add_prefix_to_json
= 0;
707 char prefix_str
[BUFSIZ
];
708 json_object
*json_paths
= NULL
;
709 json_object
*json_prefix
= NULL
;
711 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
714 if (type
&& evp
->prefix
.route_type
!= type
)
718 json_prefix
= json_object_new_object();
720 pi
= bgp_node_get_bgp_path_info(rn
);
722 /* Overall header/legend displayed once. */
724 bgp_evpn_show_route_header(vty
, bgp
,
733 json_paths
= json_object_new_array();
735 /* For EVPN, the prefix is displayed for each path (to fit in
736 * with code that already exists).
738 for (; pi
; pi
= pi
->next
) {
739 json_object
*json_path
= NULL
;
742 && !IPV4_ADDR_SAME(&(vtep_ip
),
743 &(pi
->attr
->nexthop
)))
747 json_path
= json_object_new_array();
750 route_vty_out_detail(vty
, bgp
, rn
, pi
,
751 AFI_L2VPN
, SAFI_EVPN
,
754 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
758 json_object_array_add(json_paths
, json_path
);
761 add_prefix_to_json
= 1;
764 if (json
&& add_prefix_to_json
) {
765 json_object_string_add(json_prefix
, "prefix",
767 json_object_int_add(json_prefix
, "prefixLen",
769 json_object_object_add(json_prefix
, "paths",
771 json_object_object_add(json
, prefix_str
, json_prefix
);
776 json_object_int_add(json
, "numPrefix", prefix_cnt
);
777 json_object_int_add(json
, "numPaths", path_cnt
);
780 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
781 type
? "(of requested type) " : "");
783 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
784 prefix_cnt
, path_cnt
,
785 type
? " (of requested type)" : "");
790 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
792 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
793 struct vni_walk_ctx
*wctx
= arg
;
794 struct vty
*vty
= wctx
->vty
;
795 json_object
*json
= wctx
->json
;
796 json_object
*json_vni
= NULL
;
797 char vni_str
[VNI_STR_LEN
];
799 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
801 json_vni
= json_object_new_object();
802 json_object_int_add(json_vni
, "vni", vpn
->vni
);
804 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
807 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
811 json_object_object_add(json
, vni_str
, json_vni
);
814 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
817 json_object
*json_vni
= NULL
;
818 json_object
*json_import_rtl
= NULL
;
819 json_object
*json_export_rtl
= NULL
;
821 char buf2
[INET6_ADDRSTRLEN
];
824 struct listnode
*node
, *nnode
;
825 struct ecommunity
*ecom
;
831 json_vni
= json_object_new_object();
832 json_import_rtl
= json_object_new_array();
833 json_export_rtl
= json_object_new_array();
836 /* if an l3vni is present in bgp it is live */
841 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
842 json_object_string_add(json_vni
, "type", "L3");
843 json_object_string_add(json_vni
, "inKernel", "True");
844 json_object_string_add(json_vni
, "originatorIp",
845 inet_ntoa(bgp
->originator_ip
));
846 json_object_string_add(
848 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
850 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
851 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
854 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
855 ecom_str
= ecommunity_ecom2str(ecom
,
856 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
859 json_object_array_add(json_import_rtl
,
860 json_object_new_string(ecom_str
));
862 if (listcount(bgp
->vrf_import_rtl
) > 1)
863 sprintf(rt_buf
, "%s, ...", ecom_str
);
865 sprintf(rt_buf
, "%s", ecom_str
);
866 vty_out(vty
, " %-25s", rt_buf
);
869 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
871 /* If there are multiple import RTs we break here and show only
878 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
880 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
881 ecom_str
= ecommunity_ecom2str(ecom
,
882 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
885 json_object_array_add(json_export_rtl
,
886 json_object_new_string(ecom_str
));
888 if (listcount(bgp
->vrf_export_rtl
) > 1)
889 sprintf(rt_buf
, "%s, ...", ecom_str
);
891 sprintf(rt_buf
, "%s", ecom_str
);
892 vty_out(vty
, " %-25s", rt_buf
);
895 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
897 /* If there are multiple export RTs we break here and show only
904 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
907 char vni_str
[VNI_STR_LEN
];
909 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
910 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
911 json_object_object_add(json
, vni_str
, json_vni
);
917 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
919 char buf
[ESI_STR_LEN
];
920 char buf1
[RD_ADDRSTRLEN
];
921 char buf2
[INET6_ADDRSTRLEN
];
922 struct in_addr
*vtep
= NULL
;
923 struct vty
*vty
= args
[0];
924 json_object
*json
= args
[1];
925 json_object
*json_vteps
= NULL
;
926 struct listnode
*node
= NULL
;
927 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
930 json_vteps
= json_object_new_array();
931 json_object_string_add(json
, "esi",
932 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
933 json_object_string_add(json
, "type",
934 is_es_local(es
) ? "Local" : "Remote");
935 json_object_string_add(json
, "rd",
936 prefix_rd2str(&es
->prd
, buf1
,
938 json_object_string_add(
939 json
, "originatorIp",
940 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
942 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
943 json_object_array_add(json_vteps
,
944 json_object_new_string(
947 json_object_object_add(json
, "vteps", json_vteps
);
949 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
950 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
951 is_es_local(es
) ? "Local" : "Remote",
952 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
953 ipaddr2str(&es
->originator_ip
, buf2
,
955 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
959 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
963 json_object
*json_vni
= NULL
;
964 json_object
*json_import_rtl
= NULL
;
965 json_object
*json_export_rtl
= NULL
;
966 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
968 char buf2
[RD_ADDRSTRLEN
];
971 struct listnode
*node
, *nnode
;
972 struct ecommunity
*ecom
;
978 json_vni
= json_object_new_object();
979 json_import_rtl
= json_object_new_array();
980 json_export_rtl
= json_object_new_array();
984 if (is_vni_live(vpn
))
988 json_object_int_add(json_vni
, "vni", vpn
->vni
);
989 json_object_string_add(json_vni
, "type", "L2");
990 json_object_string_add(json_vni
, "inKernel",
991 is_vni_live(vpn
) ? "True" : "False");
992 json_object_string_add(json_vni
, "originatorIp",
993 inet_ntoa(vpn
->originator_ip
));
994 json_object_string_add(json_vni
, "originatorIp",
995 inet_ntoa(vpn
->originator_ip
));
996 json_object_string_add(
998 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1000 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1001 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1004 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1005 ecom_str
= ecommunity_ecom2str(ecom
,
1006 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1009 json_object_array_add(json_import_rtl
,
1010 json_object_new_string(ecom_str
));
1012 if (listcount(vpn
->import_rtl
) > 1)
1013 sprintf(rt_buf
, "%s, ...", ecom_str
);
1015 sprintf(rt_buf
, "%s", ecom_str
);
1016 vty_out(vty
, " %-25s", rt_buf
);
1019 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1021 /* If there are multiple import RTs we break here and show only
1028 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1030 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1031 ecom_str
= ecommunity_ecom2str(ecom
,
1032 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1035 json_object_array_add(json_export_rtl
,
1036 json_object_new_string(ecom_str
));
1038 if (listcount(vpn
->export_rtl
) > 1)
1039 sprintf(rt_buf
, "%s, ...", ecom_str
);
1041 sprintf(rt_buf
, "%s", ecom_str
);
1042 vty_out(vty
, " %-25s", rt_buf
);
1045 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1047 /* If there are multiple export RTs we break here and show only
1054 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1057 char vni_str
[VNI_STR_LEN
];
1059 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1060 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1061 json_object_object_add(json
, vni_str
, json_vni
);
1067 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1068 enum bgp_show_type type
, void *output_arg
,
1069 int option
, bool use_json
)
1071 afi_t afi
= AFI_L2VPN
;
1073 struct bgp_table
*table
;
1074 struct bgp_node
*rn
;
1075 struct bgp_node
*rm
;
1076 struct bgp_path_info
*pi
;
1079 char rd_str
[RD_ADDRSTRLEN
];
1083 unsigned long output_count
= 0;
1084 unsigned long total_count
= 0;
1085 json_object
*json
= NULL
;
1086 json_object
*json_array
= NULL
;
1087 json_object
*json_prefix_info
= NULL
;
1089 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1091 bgp
= bgp_get_evpn();
1094 vty_out(vty
, "No BGP process is configured\n");
1096 vty_out(vty
, "{}\n");
1101 json
= json_object_new_object();
1103 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1104 rn
= bgp_route_next(rn
)) {
1106 json_object
*json_nroute
= NULL
;
1108 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1111 table
= bgp_node_get_bgp_table_info(rn
);
1116 tbl_ver
= table
->version
;
1118 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1119 pi
= bgp_node_get_bgp_path_info(rm
);
1124 for (; pi
; pi
= pi
->next
) {
1126 if (type
== bgp_show_type_neighbor
) {
1127 struct peer
*peer
= output_arg
;
1129 if (peer_cmp(peer
, pi
->peer
) != 0)
1132 if (type
== bgp_show_type_lcommunity_exact
) {
1133 struct lcommunity
*lcom
= output_arg
;
1135 if (!pi
->attr
->lcommunity
||
1137 pi
->attr
->lcommunity
, lcom
))
1140 if (type
== bgp_show_type_lcommunity
) {
1141 struct lcommunity
*lcom
= output_arg
;
1143 if (!pi
->attr
->lcommunity
||
1145 pi
->attr
->lcommunity
, lcom
))
1148 if (type
== bgp_show_type_community
) {
1149 struct community
*com
= output_arg
;
1151 if (!pi
->attr
->community
||
1153 pi
->attr
->community
, com
))
1156 if (type
== bgp_show_type_community_exact
) {
1157 struct community
*com
= output_arg
;
1159 if (!pi
->attr
->community
||
1161 pi
->attr
->community
, com
))
1166 json_object_int_add(
1167 json
, "bgpTableVersion",
1169 json_object_string_add(
1174 json_object_int_add(
1177 bgp
->default_local_pref
);
1178 json_object_int_add(
1182 if (option
== SHOW_DISPLAY_TAGS
)
1187 == SHOW_DISPLAY_OVERLAY
)
1191 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1199 json_object_new_object();
1200 bgp_evpn_show_route_rd_header(vty
, rn
,
1201 json_nroute
, rd_str
,
1205 if (use_json
&& !json_array
)
1206 json_array
= json_object_new_array();
1208 if (option
== SHOW_DISPLAY_TAGS
)
1209 route_vty_out_tag(vty
, &rm
->p
, pi
,
1210 no_display
, SAFI_EVPN
,
1212 else if (option
== SHOW_DISPLAY_OVERLAY
)
1213 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1217 route_vty_out(vty
, &rm
->p
, pi
,
1218 no_display
, SAFI_EVPN
,
1226 if (use_json
&& json_array
) {
1227 json_prefix_info
= json_object_new_object();
1229 json_object_string_add(json_prefix_info
,
1230 "prefix", bgp_evpn_route2str(
1231 (struct prefix_evpn
*)&rm
->p
, buf
,
1234 json_object_int_add(json_prefix_info
,
1235 "prefixLen", rm
->p
.prefixlen
);
1237 json_object_object_add(json_prefix_info
,
1238 "paths", json_array
);
1239 json_object_object_add(json_nroute
, buf
,
1245 if (use_json
&& json_nroute
)
1246 json_object_object_add(json
, rd_str
, json_nroute
);
1250 json_object_int_add(json
, "numPrefix", output_count
);
1251 json_object_int_add(json
, "totalPrefix", total_count
);
1252 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1253 json
, JSON_C_TO_STRING_PRETTY
));
1254 json_object_free(json
);
1256 if (output_count
== 0)
1257 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1261 "\nDisplayed %ld out of %ld total prefixes\n",
1262 output_count
, total_count
);
1267 DEFUN(show_ip_bgp_l2vpn_evpn
,
1268 show_ip_bgp_l2vpn_evpn_cmd
,
1269 "show [ip] bgp l2vpn evpn [json]",
1270 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1272 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1273 use_json(argc
, argv
));
1276 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1277 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1278 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1284 "Display information for a route distinguisher\n"
1285 "VPN Route Distinguisher\n" JSON_STR
)
1287 int idx_ext_community
= 0;
1289 struct prefix_rd prd
;
1291 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1293 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1295 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1298 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1299 use_json(argc
, argv
));
1302 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1303 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1304 "show [ip] bgp l2vpn evpn all tags",
1310 "Display information about all EVPN NLRIs\n"
1311 "Display BGP tags for prefixes\n")
1313 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1317 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1318 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1319 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1325 "Display information for a route distinguisher\n"
1326 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1328 int idx_ext_community
= 0;
1330 struct prefix_rd prd
;
1332 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1334 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1336 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1339 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1343 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1344 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1345 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1351 "Detailed information on TCP and BGP neighbor connections\n"
1352 "IPv4 Neighbor to display information about\n"
1353 "IPv6 Neighbor to display information about\n"
1354 "Neighbor on BGP configured interface\n"
1355 "Display routes learned from neighbor\n" JSON_STR
)
1359 char *peerstr
= NULL
;
1360 bool uj
= use_json(argc
, argv
);
1361 afi_t afi
= AFI_L2VPN
;
1362 safi_t safi
= SAFI_EVPN
;
1363 struct bgp
*bgp
= NULL
;
1365 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1368 vty_out(vty
, "No index\n");
1372 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1373 argv_find(argv
, argc
, "neighbors", &idx
);
1374 peerstr
= argv
[++idx
]->arg
;
1376 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1379 json_object
*json_no
= NULL
;
1380 json_no
= json_object_new_object();
1381 json_object_string_add(json_no
, "warning",
1382 "Malformed address");
1383 vty_out(vty
, "%s\n",
1384 json_object_to_json_string(json_no
));
1385 json_object_free(json_no
);
1387 vty_out(vty
, "Malformed address: %s\n",
1391 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1393 json_object
*json_no
= NULL
;
1394 json_no
= json_object_new_object();
1395 json_object_string_add(
1397 "No such neighbor or address family");
1398 vty_out(vty
, "%s\n",
1399 json_object_to_json_string(json_no
));
1400 json_object_free(json_no
);
1402 vty_out(vty
, "%% No such neighbor or address family\n");
1406 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1410 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1411 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1412 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1418 "Display information for a route distinguisher\n"
1419 "VPN Route Distinguisher\n"
1420 "Detailed information on TCP and BGP neighbor connections\n"
1421 "IPv4 Neighbor to display information about\n"
1422 "IPv6 Neighbor to display information about\n"
1423 "Neighbor on BGP configured interface\n"
1424 "Display routes learned from neighbor\n" JSON_STR
)
1426 int idx_ext_community
= 0;
1430 char *peerstr
= NULL
;
1431 struct prefix_rd prd
;
1432 bool uj
= use_json(argc
, argv
);
1433 afi_t afi
= AFI_L2VPN
;
1434 safi_t safi
= SAFI_EVPN
;
1435 struct bgp
*bgp
= NULL
;
1437 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1440 vty_out(vty
, "No index\n");
1444 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1445 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1448 json_object
*json_no
= NULL
;
1449 json_no
= json_object_new_object();
1450 json_object_string_add(json_no
, "warning",
1451 "Malformed Route Distinguisher");
1452 vty_out(vty
, "%s\n",
1453 json_object_to_json_string(json_no
));
1454 json_object_free(json_no
);
1456 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1460 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1461 argv_find(argv
, argc
, "neighbors", &idx
);
1462 peerstr
= argv
[++idx
]->arg
;
1464 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1467 json_object
*json_no
= NULL
;
1468 json_no
= json_object_new_object();
1469 json_object_string_add(json_no
, "warning",
1470 "Malformed address");
1471 vty_out(vty
, "%s\n",
1472 json_object_to_json_string(json_no
));
1473 json_object_free(json_no
);
1475 vty_out(vty
, "Malformed address: %s\n",
1479 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1481 json_object
*json_no
= NULL
;
1482 json_no
= json_object_new_object();
1483 json_object_string_add(
1485 "No such neighbor or address family");
1486 vty_out(vty
, "%s\n",
1487 json_object_to_json_string(json_no
));
1488 json_object_free(json_no
);
1490 vty_out(vty
, "%% No such neighbor or address family\n");
1494 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1498 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1499 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1500 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1506 "Detailed information on TCP and BGP neighbor connections\n"
1507 "IPv4 Neighbor to display information about\n"
1508 "IPv6 Neighbor to display information about\n"
1509 "Neighbor on BGP configured interface\n"
1510 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1514 bool uj
= use_json(argc
, argv
);
1515 struct bgp
*bgp
= NULL
;
1516 afi_t afi
= AFI_L2VPN
;
1517 safi_t safi
= SAFI_EVPN
;
1518 char *peerstr
= NULL
;
1523 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1526 vty_out(vty
, "No index\n");
1530 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1531 argv_find(argv
, argc
, "neighbors", &idx
);
1532 peerstr
= argv
[++idx
]->arg
;
1534 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1537 json_object
*json_no
= NULL
;
1538 json_no
= json_object_new_object();
1539 json_object_string_add(json_no
, "warning",
1540 "Malformed address");
1541 vty_out(vty
, "%s\n",
1542 json_object_to_json_string(json_no
));
1543 json_object_free(json_no
);
1545 vty_out(vty
, "Malformed address: %s\n",
1549 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1551 json_object
*json_no
= NULL
;
1552 json_no
= json_object_new_object();
1553 json_object_string_add(
1555 "No such neighbor or address family");
1556 vty_out(vty
, "%s\n",
1557 json_object_to_json_string(json_no
));
1558 json_object_free(json_no
);
1560 vty_out(vty
, "%% No such neighbor or address family\n");
1564 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1567 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1568 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1569 "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]",
1575 "Display information for a route distinguisher\n"
1576 "VPN Route Distinguisher\n"
1577 "Detailed information on TCP and BGP neighbor connections\n"
1578 "IPv4 Neighbor to display information about\n"
1579 "IPv6 Neighbor to display information about\n"
1580 "Neighbor on BGP configured interface\n"
1581 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1583 int idx_ext_community
= 0;
1587 struct prefix_rd prd
;
1588 struct bgp
*bgp
= NULL
;
1589 bool uj
= use_json(argc
, argv
);
1590 char *peerstr
= NULL
;
1591 afi_t afi
= AFI_L2VPN
;
1592 safi_t safi
= SAFI_EVPN
;
1600 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1603 vty_out(vty
, "No index\n");
1607 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1609 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1610 argv_find(argv
, argc
, "neighbors", &idx
);
1611 peerstr
= argv
[++idx
]->arg
;
1613 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1616 json_object
*json_no
= NULL
;
1617 json_no
= json_object_new_object();
1618 json_object_string_add(json_no
, "warning",
1619 "Malformed address");
1620 vty_out(vty
, "%s\n",
1621 json_object_to_json_string(json_no
));
1622 json_object_free(json_no
);
1624 vty_out(vty
, "Malformed address: %s\n",
1628 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1630 json_object
*json_no
= NULL
;
1631 json_no
= json_object_new_object();
1632 json_object_string_add(
1634 "No such neighbor or address family");
1635 vty_out(vty
, "%s\n",
1636 json_object_to_json_string(json_no
));
1637 json_object_free(json_no
);
1639 vty_out(vty
, "%% No such neighbor or address family\n");
1643 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1646 json_object
*json_no
= NULL
;
1647 json_no
= json_object_new_object();
1648 json_object_string_add(json_no
, "warning",
1649 "Malformed Route Distinguisher");
1650 vty_out(vty
, "%s\n",
1651 json_object_to_json_string(json_no
));
1652 json_object_free(json_no
);
1654 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1658 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1661 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1662 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1663 "show [ip] bgp l2vpn evpn all overlay [json]",
1669 "Display information about all EVPN NLRIs\n"
1670 "Display BGP Overlay Information for prefixes\n"
1673 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1674 SHOW_DISPLAY_OVERLAY
,
1675 use_json(argc
, argv
));
1678 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1679 show_ip_bgp_evpn_rd_overlay_cmd
,
1680 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1686 "Display information for a route distinguisher\n"
1687 "VPN Route Distinguisher\n"
1688 "Display BGP Overlay Information for prefixes\n")
1690 int idx_ext_community
= 0;
1692 struct prefix_rd prd
;
1694 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1696 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1698 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1701 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1702 SHOW_DISPLAY_OVERLAY
,
1703 use_json(argc
, argv
));
1706 DEFUN(show_bgp_l2vpn_evpn_com
,
1707 show_bgp_l2vpn_evpn_com_cmd
,
1708 "show bgp l2vpn evpn \
1709 <community AA:NN|large-community AA:BB:CC> \
1710 [exact-match] [json]",
1715 "Display routes matching the community\n"
1716 "Community number where AA and NN are (0-65535)\n"
1717 "Display routes matching the large-community\n"
1718 "List of large-community numbers\n"
1719 "Exact match of the communities\n"
1724 const char *clist_number_or_name
;
1725 int show_type
= bgp_show_type_normal
;
1726 struct community
*com
;
1727 struct lcommunity
*lcom
;
1729 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1730 clist_number_or_name
= argv
[++idx
]->arg
;
1731 show_type
= bgp_show_type_lcommunity
;
1733 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1734 show_type
= bgp_show_type_lcommunity_exact
;
1736 lcom
= lcommunity_str2com(clist_number_or_name
);
1738 vty_out(vty
, "%% Large-community malformed\n");
1742 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1743 SHOW_DISPLAY_STANDARD
,
1744 use_json(argc
, argv
));
1746 lcommunity_free(&lcom
);
1747 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1748 clist_number_or_name
= argv
[++idx
]->arg
;
1749 show_type
= bgp_show_type_community
;
1751 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1752 show_type
= bgp_show_type_community_exact
;
1754 com
= community_str2com(clist_number_or_name
);
1757 vty_out(vty
, "%% Community malformed: %s\n",
1758 clist_number_or_name
);
1762 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1763 SHOW_DISPLAY_STANDARD
,
1764 use_json(argc
, argv
));
1765 community_free(&com
);
1771 /* For testing purpose, static route of EVPN RT-5. */
1772 DEFUN(evpnrt5_network
,
1773 evpnrt5_network_cmd
,
1774 "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]",
1775 "Specify a network to announce via BGP\n"
1778 "Specify Route Distinguisher\n"
1779 "VPN Route Distinguisher\n"
1781 "Ethernet Tag Value\n"
1784 "Ethernet Segment Identifier\n"
1785 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1787 "Gateway IP ( A.B.C.D )\n"
1788 "Gateway IPv6 ( X:X::X:X )\n"
1789 "Router Mac Ext Comm\n"
1790 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1791 "Route-map to modify the attributes\n"
1792 "Name of the route map\n")
1794 int idx_ipv4_prefixlen
= 1;
1795 int idx_route_distinguisher
= 3;
1800 int idx_routermac
= 13;
1802 return bgp_static_set_safi(
1803 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1804 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1805 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1806 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1807 argv
[idx_routermac
]->arg
);
1810 /* For testing purpose, static route of EVPN RT-5. */
1811 DEFUN(no_evpnrt5_network
,
1812 no_evpnrt5_network_cmd
,
1813 "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>",
1815 "Specify a network to announce via BGP\n"
1818 "Specify Route Distinguisher\n"
1819 "VPN Route Distinguisher\n"
1821 "Ethernet Tag Value\n"
1824 "Ethernet Segment Identifier\n"
1825 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1826 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1828 int idx_ipv4_prefixlen
= 2;
1829 int idx_ext_community
= 4;
1834 return bgp_static_unset_safi(
1835 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1836 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1837 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1838 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1841 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1843 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1846 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1848 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1852 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1853 * check that this is a change.
1855 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1856 struct ecommunity
*ecomadd
)
1858 /* If the VNI is "live", we need to uninstall routes using the current
1859 * import RT(s) first before we update the import RT, and subsequently
1862 if (is_vni_live(vpn
))
1863 bgp_evpn_uninstall_routes(bgp
, vpn
);
1865 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1866 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1868 /* If the auto route-target is in use we must remove it */
1869 evpn_import_rt_delete_auto(bgp
, vpn
);
1871 /* Add new RT and rebuild the RT to VNI mapping */
1872 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1874 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1875 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1877 /* Install routes that match new import RT */
1878 if (is_vni_live(vpn
))
1879 bgp_evpn_install_routes(bgp
, vpn
);
1883 * Unconfigure Import RT(s) for a VNI (vty handler).
1885 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1886 struct ecommunity
*ecomdel
)
1888 struct listnode
*node
, *nnode
, *node_to_del
;
1889 struct ecommunity
*ecom
;
1891 /* Along the lines of "configure" except we have to reset to the
1894 if (is_vni_live(vpn
))
1895 bgp_evpn_uninstall_routes(bgp
, vpn
);
1897 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1898 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1900 /* Delete all import RTs */
1901 if (ecomdel
== NULL
) {
1902 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1903 ecommunity_free(&ecom
);
1904 list_delete_node(vpn
->import_rtl
, node
);
1908 /* Delete a specific import RT */
1912 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1913 if (ecommunity_match(ecom
, ecomdel
)) {
1914 ecommunity_free(&ecom
);
1921 list_delete_node(vpn
->import_rtl
, node_to_del
);
1924 assert(vpn
->import_rtl
);
1925 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1926 if (list_isempty(vpn
->import_rtl
)) {
1927 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1928 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1930 /* Rebuild the RT to VNI mapping */
1932 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1934 /* Install routes that match new import RT */
1935 if (is_vni_live(vpn
))
1936 bgp_evpn_install_routes(bgp
, vpn
);
1940 * Configure the Export RT for a VNI (vty handler). Caller expected to
1941 * check that this is a change. Note that only a single export RT is
1942 * allowed for a VNI and any change to configuration is implemented as
1943 * a "replace" (similar to other configuration).
1945 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1946 struct ecommunity
*ecomadd
)
1948 /* If the auto route-target is in use we must remove it */
1949 evpn_export_rt_delete_auto(bgp
, vpn
);
1951 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1952 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1954 if (is_vni_live(vpn
))
1955 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1959 * Unconfigure the Export RT for a VNI (vty handler)
1961 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1962 struct ecommunity
*ecomdel
)
1964 struct listnode
*node
, *nnode
, *node_to_del
;
1965 struct ecommunity
*ecom
;
1967 /* Delete all export RTs */
1968 if (ecomdel
== NULL
) {
1969 /* Reset to default and process all routes. */
1970 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1971 ecommunity_free(&ecom
);
1972 list_delete_node(vpn
->export_rtl
, node
);
1976 /* Delete a specific export RT */
1980 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1981 if (ecommunity_match(ecom
, ecomdel
)) {
1982 ecommunity_free(&ecom
);
1989 list_delete_node(vpn
->export_rtl
, node_to_del
);
1992 assert(vpn
->export_rtl
);
1993 if (list_isempty(vpn
->export_rtl
)) {
1994 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1995 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1998 if (is_vni_live(vpn
))
1999 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2003 * Configure RD for VRF
2005 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2007 /* If we have already advertise type-5 routes with a diffrent RD, we
2008 * have to delete and withdraw them firs
2010 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2013 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2014 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2016 /* We have a new RD for VRF.
2017 * Advertise all type-5 routes again with the new RD
2019 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2023 * Unconfigure RD for VRF
2025 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2027 /* If we have already advertise type-5 routes with a diffrent RD, we
2028 * have to delete and withdraw them firs
2030 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2032 /* fall back to default RD */
2033 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2034 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2036 /* We have a new RD for VRF.
2037 * Advertise all type-5 routes again with the new RD
2039 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2043 * Configure RD for a VNI (vty handler)
2045 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2046 struct prefix_rd
*rd
)
2048 /* If the VNI is "live", we need to delete and withdraw this VNI's
2049 * local routes with the prior RD first. Then, after updating RD,
2050 * need to re-advertise.
2052 if (is_vni_live(vpn
))
2053 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2056 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2057 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2059 if (is_vni_live(vpn
))
2060 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2064 * Unconfigure RD for a VNI (vty handler)
2066 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2068 /* If the VNI is "live", we need to delete and withdraw this VNI's
2069 * local routes with the prior RD first. Then, after resetting RD
2070 * to automatic value, need to re-advertise.
2072 if (is_vni_live(vpn
))
2073 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2075 /* reset RD to default */
2076 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2078 if (is_vni_live(vpn
))
2079 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2083 * Create VNI, if not already present (VTY handler). Mark as configured.
2085 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2087 struct bgpevpn
*vpn
;
2088 struct in_addr mcast_grp
= {INADDR_ANY
};
2093 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2095 /* Check if this L2VNI is already configured as L3VNI */
2096 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2099 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2104 /* tenant vrf will be updated when we get local_vni_add from
2107 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2111 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2117 /* Mark as configured. */
2118 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2123 * Delete VNI. If VNI does not exist in the system (i.e., just
2124 * configuration), all that is needed is to free it. Otherwise,
2125 * any parameters configured for the VNI need to be reset (with
2126 * appropriate action) and the VNI marked as unconfigured; the
2127 * VNI will continue to exist, purely as a "learnt" entity.
2129 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2131 assert(bgp
->vnihash
);
2133 if (!is_vni_live(vpn
)) {
2134 bgp_evpn_free(bgp
, vpn
);
2138 /* We need to take the unconfigure action for each parameter of this VNI
2139 * that is configured. Some optimization is possible, but not worth the
2140 * additional code for an operation that should be pretty rare.
2142 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2144 /* First, deal with the export side - RD and export RT changes. */
2145 if (is_rd_configured(vpn
))
2146 evpn_unconfigure_rd(bgp
, vpn
);
2147 if (is_export_rt_configured(vpn
))
2148 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2150 /* Next, deal with the import side. */
2151 if (is_import_rt_configured(vpn
))
2152 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2158 * Display import RT mapping to VRFs (vty handler)
2159 * bgp_evpn: evpn bgp instance
2161 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2169 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2170 (void (*)(struct hash_bucket
*,
2171 void *))show_vrf_import_rt_entry
,
2176 * Display import RT mapping to VNIs (vty handler)
2178 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2187 bgp
->import_rt_hash
,
2188 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2193 * Display EVPN routes for all VNIs - vty handler.
2195 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2196 struct in_addr vtep_ip
, json_object
*json
,
2200 struct vni_walk_ctx wctx
;
2202 num_vnis
= hashcount(bgp
->vnihash
);
2205 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2208 wctx
.vtep_ip
= vtep_ip
;
2210 wctx
.detail
= detail
;
2211 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2212 void *))show_vni_routes_hash
,
2217 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2219 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2220 vni_t vni
, struct in_addr orig_ip
,
2223 struct bgpevpn
*vpn
;
2224 struct prefix_evpn p
;
2225 struct bgp_node
*rn
;
2226 struct bgp_path_info
*pi
;
2227 uint32_t path_cnt
= 0;
2230 json_object
*json_paths
= NULL
;
2236 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2238 vty_out(vty
, "VNI not found\n");
2242 /* See if route exists. */
2243 build_evpn_type3_prefix(&p
, orig_ip
);
2244 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2245 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2247 vty_out(vty
, "%% Network not in table\n");
2252 json_paths
= json_object_new_array();
2254 /* Prefix and num paths displayed once per prefix. */
2255 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2257 /* Display each path for this prefix. */
2258 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2259 json_object
*json_path
= NULL
;
2262 json_path
= json_object_new_array();
2264 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2268 json_object_array_add(json_paths
, json_path
);
2275 json_object_object_add(json
, "paths", json_paths
);
2277 json_object_int_add(json
, "numPaths", path_cnt
);
2279 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2285 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2286 * By definition, only matching type-2 route will be displayed.
2288 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2289 vni_t vni
, struct ethaddr
*mac
,
2290 struct ipaddr
*ip
, json_object
*json
)
2292 struct bgpevpn
*vpn
;
2293 struct prefix_evpn p
;
2294 struct bgp_node
*rn
;
2295 struct bgp_path_info
*pi
;
2296 uint32_t path_cnt
= 0;
2299 json_object
*json_paths
= NULL
;
2305 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2308 vty_out(vty
, "VNI not found\n");
2312 /* See if route exists. Look for both non-sticky and sticky. */
2313 build_evpn_type2_prefix(&p
, mac
, ip
);
2314 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2315 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2317 vty_out(vty
, "%% Network not in table\n");
2322 json_paths
= json_object_new_array();
2324 /* Prefix and num paths displayed once per prefix. */
2325 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2327 /* Display each path for this prefix. */
2328 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2329 json_object
*json_path
= NULL
;
2332 json_path
= json_object_new_array();
2334 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2338 json_object_array_add(json_paths
, json_path
);
2345 json_object_object_add(json
, "paths", json_paths
);
2347 json_object_int_add(json
, "numPaths", path_cnt
);
2349 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2354 /* Disaplay EVPN routes for a ESI - VTY handler */
2355 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2356 esi_t
*esi
, json_object
*json
)
2358 struct evpnes
*es
= NULL
;
2361 es
= bgp_evpn_lookup_es(bgp
, esi
);
2364 vty_out(vty
, "ESI not found\n");
2368 show_esi_routes(bgp
, es
, vty
, json
);
2372 * Display EVPN routes for a VNI - vty handler.
2373 * If 'type' is non-zero, only routes matching that type are shown.
2374 * If the vtep_ip is non zero, only routes behind that vtep are shown
2376 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2377 int type
, struct in_addr vtep_ip
,
2380 struct bgpevpn
*vpn
;
2383 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2386 vty_out(vty
, "VNI not found\n");
2390 /* Walk this VNI's route table and display appropriate routes. */
2391 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2395 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2396 * IP (vty handler). By definition, only matching type-2 route will be
2399 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2400 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2401 struct ipaddr
*ip
, json_object
*json
)
2403 struct prefix_evpn p
;
2404 struct bgp_node
*rn
;
2405 struct bgp_path_info
*pi
;
2408 uint32_t path_cnt
= 0;
2409 json_object
*json_paths
= NULL
;
2410 char prefix_str
[BUFSIZ
];
2415 /* See if route exists. Look for both non-sticky and sticky. */
2416 build_evpn_type2_prefix(&p
, mac
, ip
);
2417 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2418 (struct prefix
*)&p
, prd
);
2419 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2421 vty_out(vty
, "%% Network not in table\n");
2425 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2426 sizeof(prefix_str
));
2428 /* Prefix and num paths displayed once per prefix. */
2429 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2432 json_paths
= json_object_new_array();
2434 /* Display each path for this prefix. */
2435 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2436 json_object
*json_path
= NULL
;
2439 json_path
= json_object_new_array();
2441 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2445 json_object_array_add(json_paths
, json_path
);
2450 if (json
&& path_cnt
) {
2452 json_object_object_add(json
, prefix_str
, json_paths
);
2453 json_object_int_add(json
, "numPaths", path_cnt
);
2455 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2461 * Display BGP EVPN routing table -- for specific RD (vty handler)
2462 * If 'type' is non-zero, only routes matching that type are shown.
2464 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2465 struct prefix_rd
*prd
, int type
,
2468 struct bgp_node
*rd_rn
;
2469 struct bgp_table
*table
;
2470 struct bgp_node
*rn
;
2471 struct bgp_path_info
*pi
;
2475 uint32_t prefix_cnt
, path_cnt
;
2476 char rd_str
[RD_ADDRSTRLEN
];
2477 json_object
*json_rd
= NULL
;
2478 int add_rd_to_json
= 0;
2482 prefix_cnt
= path_cnt
= 0;
2484 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2486 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2490 table
= bgp_node_get_bgp_table_info(rd_rn
);
2495 json_rd
= json_object_new_object();
2496 json_object_string_add(json_rd
, "rd", rd_str
);
2499 /* Display all prefixes with this RD. */
2500 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2501 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2502 json_object
*json_prefix
= NULL
;
2503 json_object
*json_paths
= NULL
;
2504 char prefix_str
[BUFSIZ
];
2505 int add_prefix_to_json
= 0;
2507 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2508 sizeof(prefix_str
));
2510 if (type
&& evp
->prefix
.route_type
!= type
)
2514 json_prefix
= json_object_new_object();
2516 pi
= bgp_node_get_bgp_path_info(rn
);
2518 /* RD header and legend - once overall. */
2519 if (rd_header
&& !json
) {
2521 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2523 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2525 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2529 /* Prefix and num paths displayed once per prefix. */
2530 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2537 json_paths
= json_object_new_array();
2539 /* Display each path for this prefix. */
2540 for (; pi
; pi
= pi
->next
) {
2541 json_object
*json_path
= NULL
;
2544 json_path
= json_object_new_array();
2546 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2550 json_object_array_add(json_paths
, json_path
);
2553 add_prefix_to_json
= 1;
2557 if (json
&& add_prefix_to_json
) {
2558 json_object_object_add(json_prefix
, "paths",
2560 json_object_object_add(json_rd
, prefix_str
,
2565 if (json
&& add_rd_to_json
)
2566 json_object_object_add(json
, rd_str
, json_rd
);
2569 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2570 json_object_int_add(json
, "numPaths", path_cnt
);
2572 if (prefix_cnt
== 0)
2573 vty_out(vty
, "No prefixes exist with this RD%s\n",
2574 type
? " (of requested type)" : "");
2577 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2578 prefix_cnt
, path_cnt
,
2579 type
? " (of requested type)" : "");
2584 * Display BGP EVPN routing table - all routes (vty handler).
2585 * If 'type' is non-zero, only routes matching that type are shown.
2587 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2588 json_object
*json
, int detail
)
2590 struct bgp_node
*rd_rn
;
2591 struct bgp_table
*table
;
2592 struct bgp_node
*rn
;
2593 struct bgp_path_info
*pi
;
2594 int header
= detail
? 0 : 1;
2598 uint32_t prefix_cnt
, path_cnt
;
2602 prefix_cnt
= path_cnt
= 0;
2604 /* EVPN routing table is a 2-level table with the first level being
2607 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2608 rd_rn
= bgp_route_next(rd_rn
)) {
2609 char rd_str
[RD_ADDRSTRLEN
];
2610 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2611 int add_rd_to_json
= 0;
2614 table
= bgp_node_get_bgp_table_info(rd_rn
);
2618 tbl_ver
= table
->version
;
2619 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2623 json_rd
= json_object_new_object();
2624 json_object_string_add(json_rd
, "rd", rd_str
);
2629 /* Display all prefixes for an RD */
2630 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2631 json_object
*json_prefix
=
2632 NULL
; /* contains prefix under a RD */
2633 json_object
*json_paths
=
2634 NULL
; /* array of paths under a prefix*/
2635 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2636 char prefix_str
[BUFSIZ
];
2637 int add_prefix_to_json
= 0;
2639 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2640 prefix_str
, sizeof(prefix_str
));
2642 if (type
&& evp
->prefix
.route_type
!= type
)
2645 pi
= bgp_node_get_bgp_path_info(rn
);
2647 /* Overall header/legend displayed once. */
2649 bgp_evpn_show_route_header(vty
, bgp
,
2654 "%19s Extended Community\n"
2659 /* RD header - per RD. */
2661 bgp_evpn_show_route_rd_header(
2662 vty
, rd_rn
, NULL
, rd_str
,
2671 json_prefix
= json_object_new_object();
2672 json_paths
= json_object_new_array();
2673 json_object_string_add(json_prefix
, "prefix",
2675 json_object_int_add(json_prefix
, "prefixLen",
2679 /* Prefix and num paths displayed once per prefix. */
2681 route_vty_out_detail_header(
2683 (struct prefix_rd
*)&rd_rn
->p
,
2684 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2686 /* For EVPN, the prefix is displayed for each path (to
2688 * with code that already exists).
2690 for (; pi
; pi
= pi
->next
) {
2691 json_object
*json_path
= NULL
;
2693 add_prefix_to_json
= 1;
2697 json_path
= json_object_new_array();
2700 route_vty_out_detail(
2701 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2702 SAFI_EVPN
, json_path
);
2704 route_vty_out(vty
, &rn
->p
, pi
, 0,
2705 SAFI_EVPN
, json_path
);
2708 json_object_array_add(json_paths
,
2712 if (json
&& add_prefix_to_json
) {
2713 json_object_object_add(json_prefix
, "paths",
2715 json_object_object_add(json_rd
, prefix_str
,
2720 if (json
&& add_rd_to_json
)
2721 json_object_object_add(json
, rd_str
, json_rd
);
2725 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2726 json_object_int_add(json
, "numPaths", path_cnt
);
2728 if (prefix_cnt
== 0) {
2729 vty_out(vty
, "No EVPN prefixes %sexist\n",
2730 type
? "(of requested type) " : "");
2732 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2733 prefix_cnt
, path_cnt
,
2734 type
? " (of requested type)" : "");
2739 /* Display specific ES */
2740 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2743 struct evpnes
*es
= NULL
;
2745 es
= bgp_evpn_lookup_es(bgp
, esi
);
2747 display_es(vty
, es
, json
);
2750 vty_out(vty
, "{}\n");
2752 vty_out(vty
, "ESI not found\n");
2758 /* Display all ESs */
2759 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2765 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2766 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2771 hash_iterate(bgp
->esihash
,
2772 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2777 * Display specified VNI (vty handler)
2779 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2783 struct bgpevpn
*vpn
;
2785 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2788 display_vni(vty
, vpn
, json
);
2790 struct bgp
*bgp_temp
;
2791 struct listnode
*node
= NULL
;
2793 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2794 if (bgp_temp
->l3vni
== vni
) {
2796 display_l3vni(vty
, bgp_temp
, json
);
2803 vty_out(vty
, "{}\n");
2805 vty_out(vty
, "VNI not found\n");
2812 * Display a VNI (upon user query).
2814 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2818 struct bgp
*bgp_temp
= NULL
;
2819 struct listnode
*node
;
2823 vty_out(vty
, "Flags: * - Kernel\n");
2824 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2825 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2828 /* print all L2 VNIS */
2831 hash_iterate(bgp
->vnihash
,
2832 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2835 /* print all L3 VNIs */
2836 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2837 show_l3vni_entry(vty
, bgp_temp
, json
);
2841 * evpn - enable advertisement of svi MAC-IP
2843 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2847 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2849 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2852 bgp
->evpn_info
->advertise_svi_macip
= set
;
2853 bgp_zebra_advertise_svi_macip(bgp
,
2854 bgp
->evpn_info
->advertise_svi_macip
, 0);
2856 if (set
&& vpn
->advertise_svi_macip
)
2858 else if (!set
&& !vpn
->advertise_svi_macip
)
2861 vpn
->advertise_svi_macip
= set
;
2862 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2868 * evpn - enable advertisement of default g/w
2870 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2873 if (bgp
->advertise_gw_macip
)
2876 bgp
->advertise_gw_macip
= 1;
2877 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2879 if (vpn
->advertise_gw_macip
)
2882 vpn
->advertise_gw_macip
= 1;
2883 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2890 * evpn - disable advertisement of default g/w
2892 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2893 struct bgpevpn
*vpn
)
2896 if (!bgp
->advertise_gw_macip
)
2899 bgp
->advertise_gw_macip
= 0;
2900 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2902 if (!vpn
->advertise_gw_macip
)
2905 vpn
->advertise_gw_macip
= 0;
2906 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2913 * evpn - enable advertisement of default g/w
2915 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2916 afi_t afi
, bool add
)
2918 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2921 /* bail if we are already advertising default route */
2922 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2926 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2927 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2928 else if (afi
== AFI_IP6
)
2929 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2930 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2932 /* bail out if we havent advertised the default route */
2933 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2936 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2937 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2938 else if (afi
== AFI_IP6
)
2939 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2940 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2943 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2947 * evpn - enable advertisement of default g/w
2949 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2950 struct bgpevpn
*vpn
)
2952 if (vpn
->advertise_subnet
)
2955 vpn
->advertise_subnet
= 1;
2956 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2960 * evpn - disable advertisement of default g/w
2962 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2964 if (!vpn
->advertise_subnet
)
2967 vpn
->advertise_subnet
= 0;
2968 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2972 * EVPN (VNI advertisement) enabled. Register with zebra.
2974 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2976 bgp
->advertise_all_vni
= 1;
2978 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2982 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2983 * cache, EVPN routes (delete and withdraw from peers).
2985 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2987 bgp
->advertise_all_vni
= 0;
2988 bgp_set_evpn(bgp_get_default());
2989 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2990 bgp_evpn_cleanup_on_disable(bgp
);
2994 * EVPN - use RFC8365 to auto-derive RT
2996 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2998 bgp
->advertise_autort_rfc8365
= 1;
2999 bgp_evpn_handle_autort_change(bgp
);
3003 * EVPN - don't use RFC8365 to auto-derive RT
3005 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3007 bgp
->advertise_autort_rfc8365
= 0;
3008 bgp_evpn_handle_autort_change(bgp
);
3011 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3013 char buf1
[RD_ADDRSTRLEN
];
3015 struct listnode
*node
, *nnode
;
3016 struct ecommunity
*ecom
;
3018 if (is_vni_configured(vpn
)) {
3019 vty_out(vty
, " vni %d\n", vpn
->vni
);
3020 if (is_rd_configured(vpn
))
3021 vty_out(vty
, " rd %s\n",
3022 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3024 if (is_import_rt_configured(vpn
)) {
3025 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3027 ecom_str
= ecommunity_ecom2str(
3028 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3029 vty_out(vty
, " route-target import %s\n",
3031 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3035 if (is_export_rt_configured(vpn
)) {
3036 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3038 ecom_str
= ecommunity_ecom2str(
3039 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3040 vty_out(vty
, " route-target export %s\n",
3042 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3046 if (vpn
->advertise_gw_macip
)
3047 vty_out(vty
, " advertise-default-gw\n");
3049 if (vpn
->advertise_svi_macip
)
3050 vty_out(vty
, " advertise-svi-ip\n");
3052 if (vpn
->advertise_subnet
)
3053 vty_out(vty
, " advertise-subnet\n");
3055 vty_out(vty
, " exit-vni\n");
3059 #ifndef VTYSH_EXTRACT_PL
3060 #include "bgpd/bgp_evpn_vty_clippy.c"
3063 DEFPY(bgp_evpn_flood_control
,
3064 bgp_evpn_flood_control_cmd
,
3065 "[no$no] flooding <disable$disable|head-end-replication$her>",
3067 "Specify handling for BUM packets\n"
3068 "Do not flood any BUM packets\n"
3069 "Flood BUM packets using head-end replication\n")
3071 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3072 enum vxlan_flood_control flood_ctrl
;
3078 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3080 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3084 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3087 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3088 bgp_evpn_flood_control_change(bgp
);
3093 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3094 bgp_evpn_advertise_default_gw_vni_cmd
,
3095 "advertise-default-gw",
3096 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3098 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3099 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3104 evpn_set_advertise_default_gw(bgp
, vpn
);
3109 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3110 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3111 "no advertise-default-gw",
3113 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3115 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3116 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3121 evpn_unset_advertise_default_gw(bgp
, vpn
);
3127 DEFUN (bgp_evpn_advertise_default_gw
,
3128 bgp_evpn_advertise_default_gw_cmd
,
3129 "advertise-default-gw",
3130 "Advertise All default g/w mac-ip routes in EVPN\n")
3132 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3137 if (!EVPN_ENABLED(bgp
)) {
3139 "This command is only supported under the EVPN VRF\n");
3143 evpn_set_advertise_default_gw(bgp
, NULL
);
3148 DEFUN (no_bgp_evpn_advertise_default_gw
,
3149 no_bgp_evpn_advertise_default_gw_cmd
,
3150 "no advertise-default-gw",
3152 "Withdraw All default g/w mac-ip routes from EVPN\n")
3154 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3159 if (!EVPN_ENABLED(bgp
)) {
3161 "This command is only supported under the EVPN VRF\n");
3165 evpn_unset_advertise_default_gw(bgp
, NULL
);
3170 DEFUN (bgp_evpn_advertise_all_vni
,
3171 bgp_evpn_advertise_all_vni_cmd
,
3172 "advertise-all-vni",
3173 "Advertise All local VNIs\n")
3175 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3176 struct bgp
*bgp_evpn
= NULL
;
3181 bgp_evpn
= bgp_get_evpn();
3182 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3183 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3185 return CMD_WARNING_CONFIG_FAILED
;
3188 evpn_set_advertise_all_vni(bgp
);
3192 DEFUN (no_bgp_evpn_advertise_all_vni
,
3193 no_bgp_evpn_advertise_all_vni_cmd
,
3194 "no advertise-all-vni",
3196 "Advertise All local VNIs\n")
3198 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3202 evpn_unset_advertise_all_vni(bgp
);
3206 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3207 bgp_evpn_advertise_autort_rfc8365_cmd
,
3208 "autort rfc8365-compatible",
3209 "Auto-derivation of RT\n"
3210 "Auto-derivation of RT using RFC8365\n")
3212 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3216 evpn_set_advertise_autort_rfc8365(bgp
);
3220 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3221 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3222 "no autort rfc8365-compatible",
3224 "Auto-derivation of RT\n"
3225 "Auto-derivation of RT using RFC8365\n")
3227 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3231 evpn_unset_advertise_autort_rfc8365(bgp
);
3235 DEFUN (bgp_evpn_default_originate
,
3236 bgp_evpn_default_originate_cmd
,
3237 "default-originate <ipv4 | ipv6>",
3238 "originate a default route\n"
3239 "ipv4 address family\n"
3240 "ipv6 address family\n")
3244 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3248 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3249 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3253 DEFUN (no_bgp_evpn_default_originate
,
3254 no_bgp_evpn_default_originate_cmd
,
3255 "no default-originate <ipv4 | ipv6>",
3257 "withdraw a default route\n"
3258 "ipv4 address family\n"
3259 "ipv6 address family\n")
3263 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3267 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3268 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3272 DEFPY (dup_addr_detection
,
3273 dup_addr_detection_cmd
,
3274 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3275 "Duplicate address detection\n"
3276 "Max allowed moves before address detected as duplicate\n"
3277 "Num of max allowed moves (2-1000) default 5\n"
3278 "Duplicate address detection time\n"
3279 "Time in seconds (2-1800) default 180\n")
3281 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3286 if (!EVPN_ENABLED(bgp_vrf
)) {
3288 "This command is only supported under the EVPN VRF\n");
3292 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3295 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3297 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3299 bgp_zebra_dup_addr_detection(bgp_vrf
);
3304 DEFPY (dup_addr_detection_auto_recovery
,
3305 dup_addr_detection_auto_recovery_cmd
,
3306 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3307 "Duplicate address detection\n"
3308 "Duplicate address detection freeze\n"
3309 "Duplicate address detection permanent freeze\n"
3310 "Duplicate address detection freeze time (30-3600)\n")
3312 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3313 uint32_t freeze_time
= freeze_time_val
;
3318 if (!EVPN_ENABLED(bgp_vrf
)) {
3320 "This command is only supported under the EVPN VRF\n");
3324 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3325 bgp_vrf
->evpn_info
->dad_freeze
= true;
3326 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3328 bgp_zebra_dup_addr_detection(bgp_vrf
);
3333 DEFPY (no_dup_addr_detection
,
3334 no_dup_addr_detection_cmd
,
3335 "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>]",
3337 "Duplicate address detection\n"
3338 "Max allowed moves before address detected as duplicate\n"
3339 "Num of max allowed moves (2-1000) default 5\n"
3340 "Duplicate address detection time\n"
3341 "Time in seconds (2-1800) default 180\n"
3342 "Duplicate address detection freeze\n"
3343 "Duplicate address detection permanent freeze\n"
3344 "Duplicate address detection freeze time (30-3600)\n")
3346 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3347 uint32_t max_moves
= (uint32_t)max_moves_val
;
3348 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3353 if (!EVPN_ENABLED(bgp_vrf
)) {
3355 "This command is only supported under the EVPN VRF\n");
3360 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3362 /* Reset all parameters to default. */
3363 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3364 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3365 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3366 bgp_vrf
->evpn_info
->dad_freeze
= false;
3367 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3370 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3372 "%% Value does not match with config\n");
3375 bgp_vrf
->evpn_info
->dad_max_moves
=
3376 EVPN_DAD_DEFAULT_MAX_MOVES
;
3380 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3382 "%% Value does not match with config\n");
3385 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3389 if (bgp_vrf
->evpn_info
->dad_freeze_time
3392 "%% Value does not match with config\n");
3395 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3396 bgp_vrf
->evpn_info
->dad_freeze
= false;
3399 if (permanent_val
) {
3400 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3402 "%% Value does not match with config\n");
3405 bgp_vrf
->evpn_info
->dad_freeze
= false;
3409 bgp_zebra_dup_addr_detection(bgp_vrf
);
3414 DEFPY(bgp_evpn_advertise_svi_ip
,
3415 bgp_evpn_advertise_svi_ip_cmd
,
3416 "[no$no] advertise-svi-ip",
3418 "Advertise svi mac-ip routes in EVPN\n")
3420 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3425 if (!EVPN_ENABLED(bgp
)) {
3427 "This command is only supported under EVPN VRF\n");
3432 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3434 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3439 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3440 bgp_evpn_advertise_svi_ip_vni_cmd
,
3441 "[no$no] advertise-svi-ip",
3443 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3445 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3446 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3452 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3454 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3459 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3460 bgp_evpn_advertise_vni_subnet_cmd
,
3462 "Advertise the subnet corresponding to VNI\n")
3464 struct bgp
*bgp_vrf
= NULL
;
3465 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3466 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3471 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3475 evpn_set_advertise_subnet(bgp
, vpn
);
3479 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3480 no_bgp_evpn_advertise_vni_subnet_cmd
,
3481 "no advertise-subnet",
3483 "Advertise All local VNIs\n")
3485 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3486 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3491 evpn_unset_advertise_subnet(bgp
, vpn
);
3495 DEFUN (bgp_evpn_advertise_type5
,
3496 bgp_evpn_advertise_type5_cmd
,
3497 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3498 "Advertise prefix routes\n"
3501 "route-map for filtering specific routes\n"
3502 "Name of the route map\n")
3504 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3511 int rmap_changed
= 0;
3513 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3514 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3515 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3517 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3519 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3520 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3523 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3527 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3529 "%%only ipv4 or ipv6 address families are supported");
3533 if (safi
!= SAFI_UNICAST
) {
3535 "%%only ipv4 unicast or ipv6 unicast are supported");
3539 if (afi
== AFI_IP
) {
3541 /* if we are already advertising ipv4 prefix as type-5
3544 if (!rmap_changed
&&
3545 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3546 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3548 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3549 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3552 /* if we are already advertising ipv6 prefix as type-5
3555 if (!rmap_changed
&&
3556 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3557 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3559 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3560 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3564 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3565 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3566 XFREE(MTYPE_ROUTE_MAP_NAME
,
3567 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3568 route_map_counter_decrement(
3569 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3570 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3571 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3575 /* set the route-map for advertise command */
3576 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3577 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3578 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3579 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3580 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3581 route_map_counter_increment(
3582 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3585 /* advertise type-5 routes */
3586 if (advertise_type5_routes(bgp_vrf
, afi
))
3587 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3591 DEFUN (no_bgp_evpn_advertise_type5
,
3592 no_bgp_evpn_advertise_type5_cmd
,
3593 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3595 "Advertise prefix routes\n"
3599 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3605 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3606 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3608 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3610 "%%only ipv4 or ipv6 address families are supported");
3614 if (safi
!= SAFI_UNICAST
) {
3616 "%%only ipv4 unicast or ipv6 unicast are supported");
3620 if (afi
== AFI_IP
) {
3622 /* if we are not advertising ipv4 prefix as type-5
3625 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3626 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3627 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3628 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3629 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3633 /* if we are not advertising ipv6 prefix as type-5
3636 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3637 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3638 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3639 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3640 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3644 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3645 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3646 XFREE(MTYPE_ROUTE_MAP_NAME
,
3647 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3648 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3649 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3656 * Display VNI information - for all or a specific VNI
3658 DEFUN(show_bgp_l2vpn_evpn_vni
,
3659 show_bgp_l2vpn_evpn_vni_cmd
,
3660 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3669 struct bgp
*bgp_evpn
;
3673 json_object
*json
= NULL
;
3674 uint32_t num_l2vnis
= 0;
3675 uint32_t num_l3vnis
= 0;
3676 uint32_t num_vnis
= 0;
3677 struct listnode
*node
= NULL
;
3678 struct bgp
*bgp_temp
= NULL
;
3680 uj
= use_json(argc
, argv
);
3682 bgp_evpn
= bgp_get_evpn();
3686 if (!argv_find(argv
, argc
, "evpn", &idx
))
3690 json
= json_object_new_object();
3692 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3694 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3696 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3697 if (bgp_temp
->l3vni
)
3700 num_vnis
= num_l2vnis
+ num_l3vnis
;
3702 json_object_string_add(json
, "advertiseGatewayMacip",
3703 bgp_evpn
->advertise_gw_macip
3706 json_object_string_add(json
, "advertiseSviMacip",
3707 bgp_evpn
->evpn_info
->advertise_svi_macip
3708 ? "Enabled" : "Disabled");
3709 json_object_string_add(json
, "advertiseAllVnis",
3710 is_evpn_enabled() ? "Enabled"
3712 json_object_string_add(
3714 bgp_evpn
->vxlan_flood_ctrl
3715 == VXLAN_FLOOD_HEAD_END_REPL
3716 ? "Head-end replication"
3718 json_object_int_add(json
, "numVnis", num_vnis
);
3719 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3720 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3722 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3723 bgp_evpn
->advertise_gw_macip
? "Enabled"
3725 vty_out(vty
, "Advertise SVI Macip: %s\n",
3726 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3728 vty_out(vty
, "Advertise All VNI flag: %s\n",
3729 is_evpn_enabled() ? "Enabled" : "Disabled");
3730 vty_out(vty
, "BUM flooding: %s\n",
3731 bgp_evpn
->vxlan_flood_ctrl
3732 == VXLAN_FLOOD_HEAD_END_REPL
3733 ? "Head-end replication"
3735 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3736 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3738 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3742 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3745 /* Display specific VNI */
3746 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3747 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3751 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3752 json
, JSON_C_TO_STRING_PRETTY
));
3753 json_object_free(json
);
3760 DEFUN(show_bgp_l2vpn_evpn_es
,
3761 show_bgp_l2vpn_evpn_es_cmd
,
3762 "show bgp l2vpn evpn es [ESI] [json]",
3767 "ethernet-Segment\n"
3768 "Ethernet-Segment Identifier\n"
3774 json_object
*json
= NULL
;
3775 struct bgp
*bgp
= NULL
;
3777 memset(&esi
, 0, sizeof(esi
));
3778 uj
= use_json(argc
, argv
);
3780 bgp
= bgp_get_evpn();
3784 if (!argv_find(argv
, argc
, "evpn", &idx
))
3787 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3788 (!uj
&& argc
== (idx
+ 1) + 1)) {
3791 evpn_show_all_es(vty
, bgp
, json
);
3794 /* show a specific ES */
3796 /* get the ESI - ESI-ID is at argv[5] */
3797 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3798 vty_out(vty
, "%% Malformed ESI\n");
3801 evpn_show_es(vty
, bgp
, &esi
, json
);
3805 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3806 json
, JSON_C_TO_STRING_PRETTY
));
3807 json_object_free(json
);
3814 * Display EVPN neighbor summary.
3816 DEFUN(show_bgp_l2vpn_evpn_summary
,
3817 show_bgp_l2vpn_evpn_summary_cmd
,
3818 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3825 "Summary of BGP neighbor status\n"
3826 "Show only sessions not in Established state\n"
3830 bool uj
= use_json(argc
, argv
);
3832 bool show_failed
= false;
3834 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3835 vrf
= argv
[++idx_vrf
]->arg
;
3836 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3838 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3843 * Display global EVPN routing table.
3845 DEFUN(show_bgp_l2vpn_evpn_route
,
3846 show_bgp_l2vpn_evpn_route_cmd
,
3847 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3852 "EVPN route information\n"
3853 "Display Detailed Information\n"
3854 "Specify Route type\n"
3855 "MAC-IP (Type-2) route\n"
3856 "Multicast (Type-3) route\n"
3857 "Ethernet Segment (type-4) route \n"
3858 "Prefix (type-5 )route\n"
3866 json_object
*json
= NULL
;
3868 uj
= use_json(argc
, argv
);
3870 bgp
= bgp_get_evpn();
3875 json
= json_object_new_object();
3878 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3879 /* Specific type is requested */
3880 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3881 type
= BGP_EVPN_MAC_IP_ROUTE
;
3882 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3883 type
= BGP_EVPN_IMET_ROUTE
;
3884 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
3885 type
= BGP_EVPN_ES_ROUTE
;
3886 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
3887 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3892 if (argv_find(argv
, argc
, "detail", &detail
))
3895 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3899 json
, JSON_C_TO_STRING_PRETTY
));
3900 json_object_free(json
);
3906 * Display global EVPN routing table for specific RD.
3908 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3909 show_bgp_l2vpn_evpn_route_rd_cmd
,
3910 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3915 "EVPN route information\n"
3916 "Route Distinguisher\n"
3917 "ASN:XX or A.B.C.D:XX\n"
3918 "Specify Route type\n"
3919 "MAC-IP (Type-2) route\n"
3920 "Multicast (Type-3) route\n"
3921 "Ethernet Segment route\n"
3927 struct prefix_rd prd
;
3932 json_object
*json
= NULL
;
3934 bgp
= bgp_get_evpn();
3938 /* check if we need json output */
3939 uj
= use_json(argc
, argv
);
3941 json
= json_object_new_object();
3944 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3945 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3948 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3954 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3955 /* Specific type is requested */
3956 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3957 type
= BGP_EVPN_MAC_IP_ROUTE
;
3958 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3959 type
= BGP_EVPN_IMET_ROUTE
;
3960 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3961 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3966 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3969 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3970 json
, JSON_C_TO_STRING_PRETTY
));
3971 json_object_free(json
);
3978 * Display global EVPN routing table for specific RD and MACIP.
3980 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3981 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3982 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3987 "EVPN route information\n"
3988 "Route Distinguisher\n"
3989 "ASN:XX or A.B.C.D:XX\n"
3991 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3993 "IP address (IPv4 or IPv6)\n"
3998 struct prefix_rd prd
;
4005 json_object
*json
= NULL
;
4007 memset(&mac
, 0, sizeof(struct ethaddr
));
4008 memset(&ip
, 0, sizeof(struct ipaddr
));
4010 bgp
= bgp_get_evpn();
4014 /* check if we need json output */
4015 uj
= use_json(argc
, argv
);
4017 json
= json_object_new_object();
4020 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4021 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4023 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4029 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4030 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4031 vty_out(vty
, "%% Malformed MAC address\n");
4036 /* get the ip if specified */
4037 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4038 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4039 vty_out(vty
, "%% Malformed IP address\n");
4044 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4047 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4048 json
, JSON_C_TO_STRING_PRETTY
));
4049 json_object_free(json
);
4055 /* Display per ESI routing table */
4056 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4057 show_bgp_l2vpn_evpn_route_esi_cmd
,
4058 "show bgp l2vpn evpn route esi ESI [json]",
4063 "EVPN route information\n"
4064 "Ethernet Segment Identifier\n"
4070 struct bgp
*bgp
= NULL
;
4071 json_object
*json
= NULL
;
4073 memset(&esi
, 0, sizeof(esi
));
4074 bgp
= bgp_get_evpn();
4078 uj
= use_json(argc
, argv
);
4080 json
= json_object_new_object();
4082 /* get the ESI - ESI-ID is at argv[6] */
4083 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4084 vty_out(vty
, "%% Malformed ESI\n");
4088 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4091 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4092 json
, JSON_C_TO_STRING_PRETTY
));
4093 json_object_free(json
);
4101 * Display per-VNI EVPN routing table.
4103 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4104 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4109 "EVPN route information\n"
4110 "VXLAN Network Identifier\n"
4112 "Specify Route type\n"
4113 "MAC-IP (Type-2) route\n"
4114 "Multicast (Type-3) route\n"
4116 "Remote VTEP IP address\n"
4121 struct in_addr vtep_ip
;
4125 json_object
*json
= NULL
;
4127 bgp
= bgp_get_evpn();
4131 /* check if we need json output */
4132 uj
= use_json(argc
, argv
);
4134 json
= json_object_new_object();
4136 if (!argv_find(argv
, argc
, "evpn", &idx
))
4141 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4143 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4144 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4145 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4146 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4147 type
= BGP_EVPN_MAC_IP_ROUTE
;
4148 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4149 type
= BGP_EVPN_IMET_ROUTE
;
4152 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4153 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4154 vty_out(vty
, "%% Malformed VTEP IP address\n");
4161 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4164 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4165 json
, JSON_C_TO_STRING_PRETTY
));
4166 json_object_free(json
);
4173 * Display per-VNI EVPN routing table for specific MACIP.
4175 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4176 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4177 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4182 "EVPN route information\n"
4183 "VXLAN Network Identifier\n"
4186 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4188 "IP address (IPv4 or IPv6)\n"
4197 json_object
*json
= NULL
;
4199 bgp
= bgp_get_evpn();
4203 /* check if we need json output */
4204 uj
= use_json(argc
, argv
);
4206 json
= json_object_new_object();
4208 if (!argv_find(argv
, argc
, "evpn", &idx
))
4212 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4215 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4216 vty_out(vty
, "%% Malformed MAC address\n");
4221 memset(&ip
, 0, sizeof(ip
));
4222 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4224 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4225 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4226 vty_out(vty
, "%% Malformed IP address\n");
4231 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4234 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4235 json
, JSON_C_TO_STRING_PRETTY
));
4236 json_object_free(json
);
4243 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4245 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4246 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4247 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4252 "EVPN route information\n"
4253 "VXLAN Network Identifier\n"
4255 "Multicast (Type-3) route\n"
4256 "Originating Router IP address\n"
4262 struct in_addr orig_ip
;
4265 json_object
*json
= NULL
;
4267 bgp
= bgp_get_evpn();
4271 /* check if we need json output */
4272 uj
= use_json(argc
, argv
);
4274 json
= json_object_new_object();
4276 if (!argv_find(argv
, argc
, "evpn", &idx
))
4280 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4283 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4285 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4289 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4292 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4293 json
, JSON_C_TO_STRING_PRETTY
));
4294 json_object_free(json
);
4301 * Display per-VNI EVPN routing table - for all VNIs.
4303 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4304 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4305 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4310 "EVPN route information\n"
4311 "VXLAN Network Identifier\n"
4313 "Print Detailed Output\n"
4315 "Remote VTEP IP address\n"
4319 struct in_addr vtep_ip
;
4322 json_object
*json
= NULL
;
4323 /* Detail Adjust. Adjust indexes according to detail option */
4326 bgp
= bgp_get_evpn();
4330 /* check if we need json output */
4331 uj
= use_json(argc
, argv
);
4333 json
= json_object_new_object();
4335 if (!argv_find(argv
, argc
, "evpn", &idx
))
4338 if (argv_find(argv
, argc
, "detail", &da
))
4341 /* vtep-ip position depends on detail option */
4343 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4345 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4346 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4347 vty_out(vty
, "%% Malformed VTEP IP address\n");
4352 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4355 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4356 json
, JSON_C_TO_STRING_PRETTY
));
4357 json_object_free(json
);
4364 * Display EVPN import route-target hash table
4366 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4367 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4368 "show bgp l2vpn evpn vrf-import-rt [json]",
4373 "Show vrf import route target\n"
4377 struct bgp
*bgp_evpn
= NULL
;
4378 json_object
*json
= NULL
;
4380 bgp_evpn
= bgp_get_evpn();
4384 uj
= use_json(argc
, argv
);
4386 json
= json_object_new_object();
4388 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4391 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4392 json
, JSON_C_TO_STRING_PRETTY
));
4393 json_object_free(json
);
4400 * Display EVPN import route-target hash table
4402 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4403 show_bgp_l2vpn_evpn_import_rt_cmd
,
4404 "show bgp l2vpn evpn import-rt [json]",
4409 "Show import route target\n"
4414 json_object
*json
= NULL
;
4416 bgp
= bgp_get_evpn();
4420 uj
= use_json(argc
, argv
);
4422 json
= json_object_new_object();
4424 evpn_show_import_rts(vty
, bgp
, json
);
4427 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4428 json
, JSON_C_TO_STRING_PRETTY
));
4429 json_object_free(json
);
4435 DEFUN(test_adv_evpn_type4_route
,
4436 test_adv_evpn_type4_route_cmd
,
4438 "Advertise EVPN ES route\n"
4439 "Ethernet-segment\n"
4440 "Ethernet-Segment Identifier\n")
4445 struct ipaddr vtep_ip
;
4447 bgp
= bgp_get_evpn();
4449 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4453 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4454 vty_out(vty
, "%%Malformed ESI\n");
4458 vtep_ip
.ipa_type
= IPADDR_V4
;
4459 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4461 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4463 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4469 DEFUN(test_withdraw_evpn_type4_route
,
4470 test_withdraw_evpn_type4_route_cmd
,
4472 "Advertise EVPN ES route\n"
4473 "Ethernet-segment\n"
4474 "Ethernet-Segment Identifier\n")
4479 struct ipaddr vtep_ip
;
4481 bgp
= bgp_get_evpn();
4483 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4487 if (!bgp
->peer_self
) {
4488 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4492 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4493 vty_out(vty
, "%%Malformed ESI\n");
4497 vtep_ip
.ipa_type
= IPADDR_V4
;
4498 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4499 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4501 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4507 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4508 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4512 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4513 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4514 "Summary of BGP neighbor status\n" JSON_STR
)
4516 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4517 "show bgp evpn route [detail] [type <macip|multicast>]",
4518 SHOW_STR BGP_STR EVPN_HELP_STR
4519 "EVPN route information\n"
4520 "Display Detailed Information\n"
4521 "Specify Route type\n"
4522 "MAC-IP (Type-2) route\n"
4523 "Multicast (Type-3) route\n")
4526 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4527 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4528 SHOW_STR BGP_STR EVPN_HELP_STR
4529 "EVPN route information\n"
4530 "Route Distinguisher\n"
4531 "ASN:XX or A.B.C.D:XX\n"
4532 "Specify Route type\n"
4533 "MAC-IP (Type-2) route\n"
4534 "Multicast (Type-3) route\n")
4537 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4538 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4539 SHOW_STR BGP_STR EVPN_HELP_STR
4540 "EVPN route information\n"
4541 "Route Distinguisher\n"
4542 "ASN:XX or A.B.C.D:XX\n"
4544 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4546 "IP address (IPv4 or IPv6)\n")
4549 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4550 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4551 SHOW_STR BGP_STR EVPN_HELP_STR
4552 "EVPN route information\n"
4553 "VXLAN Network Identifier\n"
4555 "Specify Route type\n"
4556 "MAC-IP (Type-2) route\n"
4557 "Multicast (Type-3) route\n"
4559 "Remote VTEP IP address\n")
4561 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4562 show_bgp_evpn_route_vni_macip_cmd
,
4563 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4564 SHOW_STR BGP_STR EVPN_HELP_STR
4565 "EVPN route information\n"
4566 "VXLAN Network Identifier\n"
4569 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4571 "IP address (IPv4 or IPv6)\n")
4573 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4574 show_bgp_evpn_route_vni_multicast_cmd
,
4575 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4576 SHOW_STR BGP_STR EVPN_HELP_STR
4577 "EVPN route information\n"
4578 "VXLAN Network Identifier\n"
4580 "Multicast (Type-3) route\n"
4581 "Originating Router IP address\n")
4583 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4584 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4585 SHOW_STR BGP_STR EVPN_HELP_STR
4586 "EVPN route information\n"
4587 "VXLAN Network Identifier\n"
4589 "Print Detailed Output\n"
4591 "Remote VTEP IP address\n")
4593 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4594 "show bgp evpn import-rt",
4595 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4597 DEFUN_NOSH (bgp_evpn_vni
,
4599 "vni " CMD_VNI_RANGE
,
4600 "VXLAN Network Identifier\n"
4604 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4605 struct bgpevpn
*vpn
;
4610 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4612 /* Create VNI, or mark as configured. */
4613 vpn
= evpn_create_update_vni(bgp
, vni
);
4615 vty_out(vty
, "%% Failed to create VNI \n");
4619 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4623 DEFUN (no_bgp_evpn_vni
,
4624 no_bgp_evpn_vni_cmd
,
4625 "no vni " CMD_VNI_RANGE
,
4627 "VXLAN Network Identifier\n"
4631 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4632 struct bgpevpn
*vpn
;
4637 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4639 /* Check if we should disallow. */
4640 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4642 vty_out(vty
, "%% Specified VNI does not exist\n");
4645 if (!is_vni_configured(vpn
)) {
4646 vty_out(vty
, "%% Specified VNI is not configured\n");
4650 evpn_delete_vni(bgp
, vpn
);
4654 DEFUN_NOSH (exit_vni
,
4657 "Exit from VNI mode\n")
4659 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4660 vty
->node
= BGP_EVPN_NODE
;
4664 DEFUN (bgp_evpn_vrf_rd
,
4665 bgp_evpn_vrf_rd_cmd
,
4666 "rd ASN:NN_OR_IP-ADDRESS:NN",
4667 "Route Distinguisher\n"
4668 "ASN:XX or A.B.C.D:XX\n")
4671 struct prefix_rd prd
;
4672 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4677 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4679 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4683 /* If same as existing value, there is nothing more to do. */
4684 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4687 /* Configure or update the RD. */
4688 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4692 DEFUN (no_bgp_evpn_vrf_rd
,
4693 no_bgp_evpn_vrf_rd_cmd
,
4694 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4696 "Route Distinguisher\n"
4697 "ASN:XX or A.B.C.D:XX\n")
4700 struct prefix_rd prd
;
4701 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4706 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4708 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4712 /* Check if we should disallow. */
4713 if (!is_vrf_rd_configured(bgp_vrf
)) {
4714 vty_out(vty
, "%% RD is not configured for this VRF\n");
4718 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4720 "%% RD specified does not match configuration for this VRF\n");
4724 evpn_unconfigure_vrf_rd(bgp_vrf
);
4728 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4729 no_bgp_evpn_vrf_rd_without_val_cmd
,
4732 "Route Distinguisher\n")
4734 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4739 /* Check if we should disallow. */
4740 if (!is_vrf_rd_configured(bgp_vrf
)) {
4741 vty_out(vty
, "%% RD is not configured for this VRF\n");
4745 evpn_unconfigure_vrf_rd(bgp_vrf
);
4749 DEFUN (bgp_evpn_vni_rd
,
4750 bgp_evpn_vni_rd_cmd
,
4751 "rd ASN:NN_OR_IP-ADDRESS:NN",
4752 "Route Distinguisher\n"
4753 "ASN:XX or A.B.C.D:XX\n")
4755 struct prefix_rd prd
;
4756 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4757 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4763 if (!EVPN_ENABLED(bgp
)) {
4765 "This command is only supported under EVPN VRF\n");
4769 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4771 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4775 /* If same as existing value, there is nothing more to do. */
4776 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4779 /* Configure or update the RD. */
4780 evpn_configure_rd(bgp
, vpn
, &prd
);
4784 DEFUN (no_bgp_evpn_vni_rd
,
4785 no_bgp_evpn_vni_rd_cmd
,
4786 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4788 "Route Distinguisher\n"
4789 "ASN:XX or A.B.C.D:XX\n")
4791 struct prefix_rd prd
;
4792 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4793 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4799 if (!EVPN_ENABLED(bgp
)) {
4801 "This command is only supported under EVPN VRF\n");
4805 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4807 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4811 /* Check if we should disallow. */
4812 if (!is_rd_configured(vpn
)) {
4813 vty_out(vty
, "%% RD is not configured for this VNI\n");
4817 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4819 "%% RD specified does not match configuration for this VNI\n");
4823 evpn_unconfigure_rd(bgp
, vpn
);
4827 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4828 no_bgp_evpn_vni_rd_without_val_cmd
,
4831 "Route Distinguisher\n")
4833 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4834 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4839 if (!EVPN_ENABLED(bgp
)) {
4841 "This command is only supported under EVPN VRF\n");
4845 /* Check if we should disallow. */
4846 if (!is_rd_configured(vpn
)) {
4847 vty_out(vty
, "%% RD is not configured for this VNI\n");
4851 evpn_unconfigure_rd(bgp
, vpn
);
4856 * Loop over all extended-communities in the route-target list rtl and
4857 * return 1 if we find ecomtarget
4859 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4860 struct ecommunity
*ecomtarget
)
4862 struct listnode
*node
, *nnode
;
4863 struct ecommunity
*ecom
;
4865 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4866 if (ecommunity_match(ecom
, ecomtarget
))
4873 /* display L3VNI related info for a VRF instance */
4874 DEFUN (show_bgp_vrf_l3vni_info
,
4875 show_bgp_vrf_l3vni_info_cmd
,
4876 "show bgp vrf VRFNAME vni [json]",
4884 char buf
[ETHER_ADDR_STRLEN
];
4885 char buf1
[INET6_ADDRSTRLEN
];
4887 const char *name
= NULL
;
4888 struct bgp
*bgp
= NULL
;
4889 struct listnode
*node
= NULL
;
4890 struct bgpevpn
*vpn
= NULL
;
4891 struct ecommunity
*ecom
= NULL
;
4892 json_object
*json
= NULL
;
4893 json_object
*json_vnis
= NULL
;
4894 json_object
*json_export_rts
= NULL
;
4895 json_object
*json_import_rts
= NULL
;
4896 bool uj
= use_json(argc
, argv
);
4899 json
= json_object_new_object();
4900 json_vnis
= json_object_new_array();
4901 json_export_rts
= json_object_new_array();
4902 json_import_rts
= json_object_new_array();
4905 name
= argv
[idx_vrf
]->arg
;
4906 bgp
= bgp_lookup_by_name(name
);
4909 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4911 json_object_string_add(json
, "warning",
4912 "BGP instance not found");
4913 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4914 json_object_free(json
);
4920 vty_out(vty
, "BGP VRF: %s\n", name
);
4921 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4922 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4923 vty_out(vty
, " Rmac: %s\n",
4924 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4925 vty_out(vty
, " VNI Filter: %s\n",
4926 CHECK_FLAG(bgp
->vrf_flags
,
4927 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4928 ? "prefix-routes-only"
4930 vty_out(vty
, " L2-VNI List:\n");
4932 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4933 vty_out(vty
, "%u ", vpn
->vni
);
4935 vty_out(vty
, " Export-RTs:\n");
4937 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4938 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4940 vty_out(vty
, " Import-RTs:\n");
4942 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4943 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4945 vty_out(vty
, " RD: %s\n",
4946 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4948 json_object_string_add(json
, "vrf", name
);
4949 json_object_string_add(json
, "local-ip",
4950 inet_ntoa(bgp
->originator_ip
));
4951 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4952 json_object_string_add(
4954 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4955 json_object_string_add(
4957 CHECK_FLAG(bgp
->vrf_flags
,
4958 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4959 ? "prefix-routes-only"
4961 /* list of l2vnis */
4962 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4963 json_object_array_add(json_vnis
,
4964 json_object_new_int(vpn
->vni
));
4965 json_object_object_add(json
, "l2vnis", json_vnis
);
4968 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4969 json_object_array_add(
4971 json_object_new_string(ecommunity_str(ecom
)));
4972 json_object_object_add(json
, "export-rts", json_export_rts
);
4975 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4976 json_object_array_add(
4978 json_object_new_string(ecommunity_str(ecom
)));
4979 json_object_object_add(json
, "import-rts", json_import_rts
);
4980 json_object_string_add(
4982 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4986 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4987 json
, JSON_C_TO_STRING_PRETTY
));
4988 json_object_free(json
);
4993 /* import/export rt for l3vni-vrf */
4994 DEFUN (bgp_evpn_vrf_rt
,
4995 bgp_evpn_vrf_rt_cmd
,
4996 "route-target <both|import|export> RT",
4998 "import and export\n"
5001 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5004 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5005 struct ecommunity
*ecomadd
= NULL
;
5010 if (!strcmp(argv
[1]->arg
, "import"))
5011 rt_type
= RT_TYPE_IMPORT
;
5012 else if (!strcmp(argv
[1]->arg
, "export"))
5013 rt_type
= RT_TYPE_EXPORT
;
5014 else if (!strcmp(argv
[1]->arg
, "both"))
5015 rt_type
= RT_TYPE_BOTH
;
5017 vty_out(vty
, "%% Invalid Route Target type\n");
5021 /* Add/update the import route-target */
5022 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5023 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5024 ECOMMUNITY_ROUTE_TARGET
, 0);
5026 vty_out(vty
, "%% Malformed Route Target list\n");
5029 ecommunity_str(ecomadd
);
5031 /* Do nothing if we already have this import route-target */
5032 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5033 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5036 /* Add/update the export route-target */
5037 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5038 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5039 ECOMMUNITY_ROUTE_TARGET
, 0);
5041 vty_out(vty
, "%% Malformed Route Target list\n");
5044 ecommunity_str(ecomadd
);
5046 /* Do nothing if we already have this export route-target */
5047 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5048 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5054 DEFUN (no_bgp_evpn_vrf_rt
,
5055 no_bgp_evpn_vrf_rt_cmd
,
5056 "no route-target <both|import|export> RT",
5059 "import and export\n"
5062 "ASN:XX or A.B.C.D:XX\n")
5064 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5065 int rt_type
, found_ecomdel
;
5066 struct ecommunity
*ecomdel
= NULL
;
5071 if (!strcmp(argv
[2]->arg
, "import"))
5072 rt_type
= RT_TYPE_IMPORT
;
5073 else if (!strcmp(argv
[2]->arg
, "export"))
5074 rt_type
= RT_TYPE_EXPORT
;
5075 else if (!strcmp(argv
[2]->arg
, "both"))
5076 rt_type
= RT_TYPE_BOTH
;
5078 vty_out(vty
, "%% Invalid Route Target type\n");
5082 if (rt_type
== RT_TYPE_IMPORT
) {
5083 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5085 "%% Import RT is not configured for this VRF\n");
5088 } else if (rt_type
== RT_TYPE_EXPORT
) {
5089 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5091 "%% Export RT is not configured for this VRF\n");
5094 } else if (rt_type
== RT_TYPE_BOTH
) {
5095 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5096 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5098 "%% Import/Export RT is not configured for this VRF\n");
5103 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5105 vty_out(vty
, "%% Malformed Route Target list\n");
5108 ecommunity_str(ecomdel
);
5110 if (rt_type
== RT_TYPE_IMPORT
) {
5111 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5114 "%% RT specified does not match configuration for this VRF\n");
5117 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5118 } else if (rt_type
== RT_TYPE_EXPORT
) {
5119 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5122 "%% RT specified does not match configuration for this VRF\n");
5125 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5126 } else if (rt_type
== RT_TYPE_BOTH
) {
5129 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5131 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5135 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5137 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5141 if (!found_ecomdel
) {
5143 "%% RT specified does not match configuration for this VRF\n");
5151 DEFUN (bgp_evpn_vni_rt
,
5152 bgp_evpn_vni_rt_cmd
,
5153 "route-target <both|import|export> RT",
5155 "import and export\n"
5158 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5160 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5161 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5163 struct ecommunity
*ecomadd
= NULL
;
5168 if (!EVPN_ENABLED(bgp
)) {
5170 "This command is only supported under EVPN VRF\n");
5174 if (!strcmp(argv
[1]->text
, "import"))
5175 rt_type
= RT_TYPE_IMPORT
;
5176 else if (!strcmp(argv
[1]->text
, "export"))
5177 rt_type
= RT_TYPE_EXPORT
;
5178 else if (!strcmp(argv
[1]->text
, "both"))
5179 rt_type
= RT_TYPE_BOTH
;
5181 vty_out(vty
, "%% Invalid Route Target type\n");
5185 /* Add/update the import route-target */
5186 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5187 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5188 ECOMMUNITY_ROUTE_TARGET
, 0);
5190 vty_out(vty
, "%% Malformed Route Target list\n");
5193 ecommunity_str(ecomadd
);
5195 /* Do nothing if we already have this import route-target */
5196 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5197 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5200 /* Add/update the export route-target */
5201 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5202 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5203 ECOMMUNITY_ROUTE_TARGET
, 0);
5205 vty_out(vty
, "%% Malformed Route Target list\n");
5208 ecommunity_str(ecomadd
);
5210 /* Do nothing if we already have this export route-target */
5211 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5212 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5218 DEFUN (no_bgp_evpn_vni_rt
,
5219 no_bgp_evpn_vni_rt_cmd
,
5220 "no route-target <both|import|export> RT",
5223 "import and export\n"
5226 "ASN:XX or A.B.C.D:XX\n")
5228 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5229 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5230 int rt_type
, found_ecomdel
;
5231 struct ecommunity
*ecomdel
= NULL
;
5236 if (!EVPN_ENABLED(bgp
)) {
5238 "This command is only supported under EVPN VRF\n");
5242 if (!strcmp(argv
[2]->text
, "import"))
5243 rt_type
= RT_TYPE_IMPORT
;
5244 else if (!strcmp(argv
[2]->text
, "export"))
5245 rt_type
= RT_TYPE_EXPORT
;
5246 else if (!strcmp(argv
[2]->text
, "both"))
5247 rt_type
= RT_TYPE_BOTH
;
5249 vty_out(vty
, "%% Invalid Route Target type\n");
5253 /* The user did "no route-target import", check to see if there are any
5254 * import route-targets configured. */
5255 if (rt_type
== RT_TYPE_IMPORT
) {
5256 if (!is_import_rt_configured(vpn
)) {
5258 "%% Import RT is not configured for this VNI\n");
5261 } else if (rt_type
== RT_TYPE_EXPORT
) {
5262 if (!is_export_rt_configured(vpn
)) {
5264 "%% Export RT is not configured for this VNI\n");
5267 } else if (rt_type
== RT_TYPE_BOTH
) {
5268 if (!is_import_rt_configured(vpn
)
5269 && !is_export_rt_configured(vpn
)) {
5271 "%% Import/Export RT is not configured for this VNI\n");
5276 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5278 vty_out(vty
, "%% Malformed Route Target list\n");
5281 ecommunity_str(ecomdel
);
5283 if (rt_type
== RT_TYPE_IMPORT
) {
5284 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5286 "%% RT specified does not match configuration for this VNI\n");
5289 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5290 } else if (rt_type
== RT_TYPE_EXPORT
) {
5291 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5293 "%% RT specified does not match configuration for this VNI\n");
5296 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5297 } else if (rt_type
== RT_TYPE_BOTH
) {
5300 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5301 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5305 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5306 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5310 if (!found_ecomdel
) {
5312 "%% RT specified does not match configuration for this VNI\n");
5320 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5321 no_bgp_evpn_vni_rt_without_val_cmd
,
5322 "no route-target <import|export>",
5328 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5329 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5335 if (!EVPN_ENABLED(bgp
)) {
5337 "This command is only supported under EVPN VRF\n");
5341 if (!strcmp(argv
[2]->text
, "import")) {
5342 rt_type
= RT_TYPE_IMPORT
;
5343 } else if (!strcmp(argv
[2]->text
, "export")) {
5344 rt_type
= RT_TYPE_EXPORT
;
5346 vty_out(vty
, "%% Invalid Route Target type\n");
5350 /* Check if we should disallow. */
5351 if (rt_type
== RT_TYPE_IMPORT
) {
5352 if (!is_import_rt_configured(vpn
)) {
5354 "%% Import RT is not configured for this VNI\n");
5358 if (!is_export_rt_configured(vpn
)) {
5360 "%% Export RT is not configured for this VNI\n");
5365 /* Unconfigure the RT. */
5366 if (rt_type
== RT_TYPE_IMPORT
)
5367 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5369 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5373 static int vni_cmp(const void **a
, const void **b
)
5375 const struct bgpevpn
*first
= *a
;
5376 const struct bgpevpn
*secnd
= *b
;
5378 return secnd
->vni
- first
->vni
;
5382 * Output EVPN configuration information.
5384 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5387 char buf1
[RD_ADDRSTRLEN
];
5390 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5391 struct listnode
*ln
;
5392 struct bgpevpn
*data
;
5394 list_sort(vnilist
, vni_cmp
);
5395 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5396 write_vni_config(vty
, data
);
5398 list_delete(&vnilist
);
5401 if (bgp
->advertise_all_vni
)
5402 vty_out(vty
, " advertise-all-vni\n");
5404 if (bgp
->advertise_autort_rfc8365
)
5405 vty_out(vty
, " autort rfc8365-compatible\n");
5407 if (bgp
->advertise_gw_macip
)
5408 vty_out(vty
, " advertise-default-gw\n");
5410 if (bgp
->evpn_info
->advertise_svi_macip
)
5411 vty_out(vty
, " advertise-svi-ip\n");
5413 if (!bgp
->evpn_info
->dup_addr_detect
)
5414 vty_out(vty
, " no dup-addr-detection\n");
5416 if (bgp
->evpn_info
->dad_max_moves
!=
5417 EVPN_DAD_DEFAULT_MAX_MOVES
||
5418 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5419 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5420 bgp
->evpn_info
->dad_max_moves
,
5421 bgp
->evpn_info
->dad_time
);
5423 if (bgp
->evpn_info
->dad_freeze
) {
5424 if (bgp
->evpn_info
->dad_freeze_time
)
5426 " dup-addr-detection freeze %u\n",
5427 bgp
->evpn_info
->dad_freeze_time
);
5430 " dup-addr-detection freeze permanent\n");
5433 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5434 vty_out(vty
, " flooding disable\n");
5436 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5437 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5438 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5439 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5440 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5442 vty_out(vty
, " advertise ipv4 unicast\n");
5445 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5446 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5447 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5448 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5449 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5451 vty_out(vty
, " advertise ipv6 unicast\n");
5454 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5455 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5456 vty_out(vty
, " default-originate ipv4\n");
5458 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5459 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5460 vty_out(vty
, " default-originate ipv6\n");
5462 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5463 vty_out(vty
, " rd %s\n",
5464 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5466 /* import route-target */
5467 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5469 struct listnode
*node
, *nnode
;
5470 struct ecommunity
*ecom
;
5472 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5474 ecom_str
= ecommunity_ecom2str(
5475 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5476 vty_out(vty
, " route-target import %s\n", ecom_str
);
5477 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5481 /* export route-target */
5482 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5484 struct listnode
*node
, *nnode
;
5485 struct ecommunity
*ecom
;
5487 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5489 ecom_str
= ecommunity_ecom2str(
5490 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5491 vty_out(vty
, " route-target export %s\n", ecom_str
);
5492 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5497 void bgp_ethernetvpn_init(void)
5499 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5500 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5501 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5502 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5503 install_element(VIEW_NODE
,
5504 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5505 install_element(VIEW_NODE
,
5506 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5509 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5512 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5513 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5514 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5515 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5516 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5517 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5518 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5519 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5520 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5521 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5522 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5523 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5524 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5525 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5526 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5527 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5528 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5529 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5530 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5531 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5534 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5535 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5537 /* "show bgp l2vpn evpn" commands. */
5538 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5539 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5540 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5541 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5542 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5543 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5544 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5545 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5546 install_element(VIEW_NODE
,
5547 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5548 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5549 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5550 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5551 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5553 /* "show bgp evpn" commands. */
5554 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5555 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5556 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5557 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5558 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5559 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5560 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5561 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5562 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5563 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5564 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5565 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5567 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5568 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5569 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5570 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5571 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5572 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5573 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5574 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5575 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5576 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5577 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5578 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5579 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5580 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5581 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5582 install_element(BGP_EVPN_VNI_NODE
,
5583 &bgp_evpn_advertise_default_gw_vni_cmd
);
5584 install_element(BGP_EVPN_VNI_NODE
,
5585 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5586 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5587 install_element(BGP_EVPN_VNI_NODE
,
5588 &no_bgp_evpn_advertise_vni_subnet_cmd
);