1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
49 * Context for VNI hash walk - used by callbacks.
54 struct in_addr vtep_ip
;
59 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
63 uint8_t type
, sub_type
;
64 struct ecommunity_as eas
;
65 struct ecommunity_ip eip
;
66 struct listnode
*node
, *nnode
;
67 struct bgp
*tmp_bgp_vrf
= NULL
;
68 json_object
*json_rt
= NULL
;
69 json_object
*json_vrfs
= NULL
;
70 char rt_buf
[RT_ADDRSTRLEN
];
73 json_rt
= json_object_new_object();
74 json_vrfs
= json_object_new_array();
77 pnt
= (uint8_t *)&irt
->rt
.val
;
80 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
83 memset(&eas
, 0, sizeof(eas
));
85 case ECOMMUNITY_ENCODE_AS
:
86 eas
.as
= (*pnt
++ << 8);
88 ptr_get_be32(pnt
, &eas
.val
);
90 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
93 json_object_string_add(json_rt
, "rt", rt_buf
);
95 vty_out(vty
, "Route-target: %s", rt_buf
);
99 case ECOMMUNITY_ENCODE_IP
:
100 memcpy(&eip
.ip
, pnt
, 4);
102 eip
.val
= (*pnt
++ << 8);
105 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
109 json_object_string_add(json_rt
, "rt", rt_buf
);
111 vty_out(vty
, "Route-target: %s", rt_buf
);
115 case ECOMMUNITY_ENCODE_AS4
:
116 pnt
= ptr_get_be32(pnt
, &eas
.val
);
117 eas
.val
= (*pnt
++ << 8);
120 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
123 json_object_string_add(json_rt
, "rt", rt_buf
);
125 vty_out(vty
, "Route-target: %s", rt_buf
);
135 "\nList of VRFs importing routes with this route-target:\n");
138 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
140 json_object_array_add(
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
145 vty_out(vty
, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
150 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
151 json_object_object_add(json
, rt_buf
, json_rt
);
155 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 uint8_t type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (uint8_t *)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
219 json_object_string_add(json_rt
, "rt", rt_buf
);
221 vty_out(vty
, "Route-target: %s", rt_buf
);
225 case ECOMMUNITY_ENCODE_AS4
:
226 pnt
= ptr_get_be32(pnt
, &eas
.val
);
227 eas
.val
= (*pnt
++ << 8);
230 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
233 json_object_string_add(json_rt
, "rt", rt_buf
);
235 vty_out(vty
, "Route-target: %s", rt_buf
);
245 "\nList of VNIs importing routes with this route-target:\n");
248 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
250 json_object_array_add(
251 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
253 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
257 json_object_object_add(json_rt
, "vnis", json_vnis
);
258 json_object_object_add(json
, rt_buf
, json_rt
);
262 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
264 json_object
*json
= NULL
;
265 struct vty
*vty
= NULL
;
266 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
271 display_import_rt(vty
, irt
, json
);
276 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
277 struct bgp_node
*rd_rn
,
284 char rd_str
[RD_ADDRSTRLEN
];
286 pnt
= rd_rn
->p
.u
.val
;
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
294 vty_out(vty
, "Route Distinguisher: ");
298 decode_rd_as(pnt
+ 2, &rd_as
);
299 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
303 decode_rd_ip(pnt
+ 2, &rd_ip
);
304 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
309 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
313 vty_out(vty
, "%s\n", rd_str
);
316 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
317 uint64_t tbl_ver
, json_object
*json
)
320 " Network Next Hop Metric LocPrf Weight Path\n";
325 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
326 tbl_ver
, inet_ntoa(bgp
->router_id
));
328 "Status codes: s suppressed, d damped, h history, "
329 "* valid, > best, i - internal\n");
330 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
332 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
333 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
334 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
335 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
336 vty_out(vty
, "%s", ri_header
);
339 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
342 char buf1
[INET6_ADDRSTRLEN
];
344 struct listnode
*node
, *nnode
;
345 struct ecommunity
*ecom
;
346 json_object
*json_import_rtl
= NULL
;
347 json_object
*json_export_rtl
= NULL
;
349 json_import_rtl
= json_export_rtl
= 0;
352 json_import_rtl
= json_object_new_array();
353 json_export_rtl
= json_object_new_array();
354 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
355 json_object_string_add(json
, "type", "L3");
356 json_object_string_add(json
, "kernelFlag", "Yes");
357 json_object_string_add(
359 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
360 json_object_string_add(json
, "originatorIp",
361 inet_ntoa(bgp_vrf
->originator_ip
));
362 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
363 json_object_string_add(json
, "advertiseSviMacip", "n/a");
364 json_object_to_json_string_ext(json
,
365 JSON_C_TO_STRING_NOSLASHESCAPE
);
367 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
368 vty_out(vty
, " (known to the kernel)");
371 vty_out(vty
, " Type: %s\n", "L3");
372 vty_out(vty
, " Tenant VRF: %s\n",
373 vrf_id_to_name(bgp_vrf
->vrf_id
));
374 vty_out(vty
, " RD: %s\n",
375 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
376 vty_out(vty
, " Originator IP: %s\n",
377 inet_ntoa(bgp_vrf
->originator_ip
));
378 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
379 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
383 vty_out(vty
, " Import Route Target:\n");
385 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
386 ecom_str
= ecommunity_ecom2str(ecom
,
387 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
390 json_object_array_add(json_import_rtl
,
391 json_object_new_string(ecom_str
));
393 vty_out(vty
, " %s\n", ecom_str
);
395 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
399 json_object_object_add(json
, "importRts", json_import_rtl
);
401 vty_out(vty
, " Export Route Target:\n");
403 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
404 ecom_str
= ecommunity_ecom2str(ecom
,
405 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
408 json_object_array_add(json_export_rtl
,
409 json_object_new_string(ecom_str
));
411 vty_out(vty
, " %s\n", ecom_str
);
413 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
417 json_object_object_add(json
, "exportRts", json_export_rtl
);
420 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
422 struct in_addr
*vtep
;
423 char buf
[ESI_STR_LEN
];
424 char buf1
[RD_ADDRSTRLEN
];
425 char buf2
[INET6_ADDRSTRLEN
];
426 struct listnode
*node
= NULL
;
427 json_object
*json_vteps
= NULL
;
430 json_vteps
= json_object_new_array();
431 json_object_string_add(json
, "esi",
432 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
433 json_object_string_add(json
, "rd",
434 prefix_rd2str(&es
->prd
, buf1
,
436 json_object_string_add(
437 json
, "originatorIp",
438 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
440 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
441 json_object_array_add(
442 json_vteps
, json_object_new_string(
445 json_object_object_add(json
, "vteps", json_vteps
);
447 vty_out(vty
, "ESI: %s\n",
448 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
449 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
451 vty_out(vty
, " Originator-IP: %s\n",
452 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
454 vty_out(vty
, " VTEP List:\n");
455 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
456 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
461 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
463 char buf1
[RD_ADDRSTRLEN
];
465 struct listnode
*node
, *nnode
;
466 struct ecommunity
*ecom
;
467 json_object
*json_import_rtl
= NULL
;
468 json_object
*json_export_rtl
= NULL
;
469 struct bgp
*bgp_evpn
;
471 bgp_evpn
= bgp_get_evpn();
474 json_import_rtl
= json_object_new_array();
475 json_export_rtl
= json_object_new_array();
476 json_object_int_add(json
, "vni", vpn
->vni
);
477 json_object_string_add(json
, "type", "L2");
478 json_object_string_add(json
, "kernelFlag",
479 is_vni_live(vpn
) ? "Yes" : "No");
480 json_object_string_add(
482 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
483 json_object_string_add(json
, "originatorIp",
484 inet_ntoa(vpn
->originator_ip
));
485 json_object_string_add(json
, "mcastGroup",
486 inet_ntoa(vpn
->mcast_grp
));
487 /* per vni knob is enabled -- Enabled
488 * Global knob is enabled -- Active
489 * default -- Disabled
491 if (!vpn
->advertise_gw_macip
&&
492 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
493 json_object_string_add(json
, "advertiseGatewayMacip",
495 else if (vpn
->advertise_gw_macip
)
496 json_object_string_add(json
, "advertiseGatewayMacip",
499 json_object_string_add(json
, "advertiseGatewayMacip",
501 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
502 bgp_evpn
->evpn_info
->advertise_svi_macip
)
503 json_object_string_add(json
, "advertiseSviMacip",
505 else if (vpn
->advertise_svi_macip
)
506 json_object_string_add(json
, "advertiseSviMacip",
509 json_object_string_add(json
, "advertiseSviMacip",
512 vty_out(vty
, "VNI: %d", vpn
->vni
);
513 if (is_vni_live(vpn
))
514 vty_out(vty
, " (known to the kernel)");
517 vty_out(vty
, " Type: %s\n", "L2");
518 vty_out(vty
, " Tenant-Vrf: %s\n",
519 vrf_id_to_name(vpn
->tenant_vrf_id
));
520 vty_out(vty
, " RD: %s\n",
521 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
522 vty_out(vty
, " Originator IP: %s\n",
523 inet_ntoa(vpn
->originator_ip
));
524 vty_out(vty
, " Mcast group: %s\n",
525 inet_ntoa(vpn
->mcast_grp
));
526 if (!vpn
->advertise_gw_macip
&&
527 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
528 vty_out(vty
, " Advertise-gw-macip : %s\n",
530 else if (vpn
->advertise_gw_macip
)
531 vty_out(vty
, " Advertise-gw-macip : %s\n",
534 vty_out(vty
, " Advertise-gw-macip : %s\n",
536 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
537 bgp_evpn
->evpn_info
->advertise_svi_macip
)
538 vty_out(vty
, " Advertise-svi-macip : %s\n",
540 else if (vpn
->advertise_svi_macip
)
541 vty_out(vty
, " Advertise-svi-macip : %s\n",
544 vty_out(vty
, " Advertise-svi-macip : %s\n",
549 vty_out(vty
, " Import Route Target:\n");
551 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
552 ecom_str
= ecommunity_ecom2str(ecom
,
553 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
556 json_object_array_add(json_import_rtl
,
557 json_object_new_string(ecom_str
));
559 vty_out(vty
, " %s\n", ecom_str
);
561 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
565 json_object_object_add(json
, "importRts", json_import_rtl
);
567 vty_out(vty
, " Export Route Target:\n");
569 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
570 ecom_str
= ecommunity_ecom2str(ecom
,
571 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
574 json_object_array_add(json_export_rtl
,
575 json_object_new_string(ecom_str
));
577 vty_out(vty
, " %s\n", ecom_str
);
579 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
583 json_object_object_add(json
, "exportRts", json_export_rtl
);
586 static void show_esi_routes(struct bgp
*bgp
,
593 struct bgp_path_info
*pi
;
594 uint32_t prefix_cnt
, path_cnt
;
597 prefix_cnt
= path_cnt
= 0;
599 tbl_ver
= es
->route_table
->version
;
600 for (rn
= bgp_table_top(es
->route_table
); rn
;
601 rn
= bgp_route_next(rn
)) {
602 int add_prefix_to_json
= 0;
603 char prefix_str
[BUFSIZ
];
604 json_object
*json_paths
= NULL
;
605 json_object
*json_prefix
= NULL
;
607 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
611 json_prefix
= json_object_new_object();
613 pi
= bgp_node_get_bgp_path_info(rn
);
615 /* Overall header/legend displayed once. */
617 bgp_evpn_show_route_header(vty
, bgp
,
626 json_paths
= json_object_new_array();
628 /* For EVPN, the prefix is displayed for each path (to fit in
629 * with code that already exists).
631 for (; pi
; pi
= pi
->next
) {
632 json_object
*json_path
= NULL
;
635 json_path
= json_object_new_array();
637 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
640 json_object_array_add(json_paths
, json_path
);
643 add_prefix_to_json
= 1;
646 if (json
&& add_prefix_to_json
) {
647 json_object_string_add(json_prefix
, "prefix",
649 json_object_int_add(json_prefix
, "prefixLen",
651 json_object_object_add(json_prefix
, "paths",
653 json_object_object_add(json
, prefix_str
, json_prefix
);
658 json_object_int_add(json
, "numPrefix", prefix_cnt
);
659 json_object_int_add(json
, "numPaths", path_cnt
);
662 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
664 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
665 prefix_cnt
, path_cnt
);
669 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
670 struct vty
*vty
, struct in_addr vtep_ip
,
671 json_object
*json
, int detail
)
674 struct bgp_path_info
*pi
;
675 struct bgp_table
*table
;
676 int header
= detail
? 0 : 1;
678 uint32_t prefix_cnt
, path_cnt
;
680 prefix_cnt
= path_cnt
= 0;
682 table
= vpn
->route_table
;
683 tbl_ver
= table
->version
;
684 for (rn
= bgp_table_top(table
); rn
;
685 rn
= bgp_route_next(rn
)) {
686 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
687 int add_prefix_to_json
= 0;
688 char prefix_str
[BUFSIZ
];
689 json_object
*json_paths
= NULL
;
690 json_object
*json_prefix
= NULL
;
692 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
695 if (type
&& evp
->prefix
.route_type
!= type
)
699 json_prefix
= json_object_new_object();
701 pi
= bgp_node_get_bgp_path_info(rn
);
703 /* Overall header/legend displayed once. */
705 bgp_evpn_show_route_header(vty
, bgp
,
714 json_paths
= json_object_new_array();
716 /* For EVPN, the prefix is displayed for each path (to fit in
717 * with code that already exists).
719 for (; pi
; pi
= pi
->next
) {
720 json_object
*json_path
= NULL
;
723 && !IPV4_ADDR_SAME(&(vtep_ip
),
724 &(pi
->attr
->nexthop
)))
728 json_path
= json_object_new_array();
731 route_vty_out_detail(vty
, bgp
, rn
, pi
,
732 AFI_L2VPN
, SAFI_EVPN
,
735 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
739 json_object_array_add(json_paths
, json_path
);
742 add_prefix_to_json
= 1;
745 if (json
&& add_prefix_to_json
) {
746 json_object_string_add(json_prefix
, "prefix",
748 json_object_int_add(json_prefix
, "prefixLen",
750 json_object_object_add(json_prefix
, "paths",
752 json_object_object_add(json
, prefix_str
, json_prefix
);
757 json_object_int_add(json
, "numPrefix", prefix_cnt
);
758 json_object_int_add(json
, "numPaths", path_cnt
);
761 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
762 type
? "(of requested type) " : "");
764 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
765 prefix_cnt
, path_cnt
,
766 type
? " (of requested type)" : "");
771 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
773 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
774 struct vni_walk_ctx
*wctx
= arg
;
775 struct vty
*vty
= wctx
->vty
;
776 json_object
*json
= wctx
->json
;
777 json_object
*json_vni
= NULL
;
778 char vni_str
[VNI_STR_LEN
];
780 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
782 json_vni
= json_object_new_object();
783 json_object_int_add(json_vni
, "vni", vpn
->vni
);
785 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
788 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
792 json_object_object_add(json
, vni_str
, json_vni
);
795 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
798 json_object
*json_vni
= NULL
;
799 json_object
*json_import_rtl
= NULL
;
800 json_object
*json_export_rtl
= NULL
;
802 char buf2
[INET6_ADDRSTRLEN
];
805 struct listnode
*node
, *nnode
;
806 struct ecommunity
*ecom
;
812 json_vni
= json_object_new_object();
813 json_import_rtl
= json_object_new_array();
814 json_export_rtl
= json_object_new_array();
817 /* if an l3vni is present in bgp it is live */
822 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
823 json_object_string_add(json_vni
, "type", "L3");
824 json_object_string_add(json_vni
, "inKernel", "True");
825 json_object_string_add(json_vni
, "originatorIp",
826 inet_ntoa(bgp
->originator_ip
));
827 json_object_string_add(
829 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
831 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
832 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
835 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
836 ecom_str
= ecommunity_ecom2str(ecom
,
837 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
840 json_object_array_add(json_import_rtl
,
841 json_object_new_string(ecom_str
));
843 if (listcount(bgp
->vrf_import_rtl
) > 1)
844 sprintf(rt_buf
, "%s, ...", ecom_str
);
846 sprintf(rt_buf
, "%s", ecom_str
);
847 vty_out(vty
, " %-25s", rt_buf
);
850 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
852 /* If there are multiple import RTs we break here and show only
859 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
861 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
862 ecom_str
= ecommunity_ecom2str(ecom
,
863 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
866 json_object_array_add(json_export_rtl
,
867 json_object_new_string(ecom_str
));
869 if (listcount(bgp
->vrf_export_rtl
) > 1)
870 sprintf(rt_buf
, "%s, ...", ecom_str
);
872 sprintf(rt_buf
, "%s", ecom_str
);
873 vty_out(vty
, " %-25s", rt_buf
);
876 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
878 /* If there are multiple export RTs we break here and show only
885 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
888 char vni_str
[VNI_STR_LEN
];
890 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
891 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
892 json_object_object_add(json
, vni_str
, json_vni
);
898 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
900 char buf
[ESI_STR_LEN
];
901 char buf1
[RD_ADDRSTRLEN
];
902 char buf2
[INET6_ADDRSTRLEN
];
903 struct in_addr
*vtep
= NULL
;
904 struct vty
*vty
= args
[0];
905 json_object
*json
= args
[1];
906 json_object
*json_vteps
= NULL
;
907 struct listnode
*node
= NULL
;
908 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
911 json_vteps
= json_object_new_array();
912 json_object_string_add(json
, "esi",
913 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
914 json_object_string_add(json
, "type",
915 is_es_local(es
) ? "Local" : "Remote");
916 json_object_string_add(json
, "rd",
917 prefix_rd2str(&es
->prd
, buf1
,
919 json_object_string_add(
920 json
, "originatorIp",
921 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
923 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
924 json_object_array_add(json_vteps
,
925 json_object_new_string(
928 json_object_object_add(json
, "vteps", json_vteps
);
930 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
931 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
932 is_es_local(es
) ? "Local" : "Remote",
933 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
934 ipaddr2str(&es
->originator_ip
, buf2
,
936 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
940 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
944 json_object
*json_vni
= NULL
;
945 json_object
*json_import_rtl
= NULL
;
946 json_object
*json_export_rtl
= NULL
;
947 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
949 char buf2
[RD_ADDRSTRLEN
];
952 struct listnode
*node
, *nnode
;
953 struct ecommunity
*ecom
;
959 json_vni
= json_object_new_object();
960 json_import_rtl
= json_object_new_array();
961 json_export_rtl
= json_object_new_array();
965 if (is_vni_live(vpn
))
969 json_object_int_add(json_vni
, "vni", vpn
->vni
);
970 json_object_string_add(json_vni
, "type", "L2");
971 json_object_string_add(json_vni
, "inKernel",
972 is_vni_live(vpn
) ? "True" : "False");
973 json_object_string_add(json_vni
, "originatorIp",
974 inet_ntoa(vpn
->originator_ip
));
975 json_object_string_add(json_vni
, "originatorIp",
976 inet_ntoa(vpn
->originator_ip
));
977 json_object_string_add(
979 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
981 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
982 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
985 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
986 ecom_str
= ecommunity_ecom2str(ecom
,
987 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
990 json_object_array_add(json_import_rtl
,
991 json_object_new_string(ecom_str
));
993 if (listcount(vpn
->import_rtl
) > 1)
994 sprintf(rt_buf
, "%s, ...", ecom_str
);
996 sprintf(rt_buf
, "%s", ecom_str
);
997 vty_out(vty
, " %-25s", rt_buf
);
1000 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1002 /* If there are multiple import RTs we break here and show only
1009 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1011 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1012 ecom_str
= ecommunity_ecom2str(ecom
,
1013 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1016 json_object_array_add(json_export_rtl
,
1017 json_object_new_string(ecom_str
));
1019 if (listcount(vpn
->export_rtl
) > 1)
1020 sprintf(rt_buf
, "%s, ...", ecom_str
);
1022 sprintf(rt_buf
, "%s", ecom_str
);
1023 vty_out(vty
, " %-25s", rt_buf
);
1026 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1028 /* If there are multiple export RTs we break here and show only
1035 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1038 char vni_str
[VNI_STR_LEN
];
1040 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1041 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1042 json_object_object_add(json
, vni_str
, json_vni
);
1048 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1049 enum bgp_show_type type
, void *output_arg
,
1050 int option
, bool use_json
)
1052 afi_t afi
= AFI_L2VPN
;
1054 struct bgp_table
*table
;
1055 struct bgp_node
*rn
;
1056 struct bgp_node
*rm
;
1057 struct bgp_path_info
*pi
;
1060 char rd_str
[BUFSIZ
];
1064 unsigned long output_count
= 0;
1065 unsigned long total_count
= 0;
1066 json_object
*json
= NULL
;
1067 json_object
*json_nroute
= NULL
;
1068 json_object
*json_array
= NULL
;
1069 json_object
*json_prefix_info
= NULL
;
1071 memset(rd_str
, 0, BUFSIZ
);
1073 bgp
= bgp_get_evpn();
1076 vty_out(vty
, "No BGP process is configured\n");
1078 vty_out(vty
, "{}\n");
1083 json
= json_object_new_object();
1085 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1086 rn
= bgp_route_next(rn
)) {
1089 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1092 table
= bgp_node_get_bgp_table_info(rn
);
1097 tbl_ver
= table
->version
;
1099 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1100 pi
= bgp_node_get_bgp_path_info(rm
);
1106 json_array
= json_object_new_array();
1107 json_prefix_info
= json_object_new_object();
1109 json_object_string_add(json_prefix_info
,
1110 "prefix", bgp_evpn_route2str(
1111 (struct prefix_evpn
*)&rm
->p
, buf
,
1114 json_object_int_add(json_prefix_info
,
1115 "prefixLen", rm
->p
.prefixlen
);
1118 json_nroute
= json_object_new_object();
1121 for (; pi
; pi
= pi
->next
) {
1123 if (type
== bgp_show_type_neighbor
) {
1124 struct peer
*peer
= output_arg
;
1126 if (peer_cmp(peer
, pi
->peer
) != 0)
1129 if (type
== bgp_show_type_lcommunity_exact
) {
1130 struct lcommunity
*lcom
= output_arg
;
1132 if (!pi
->attr
->lcommunity
||
1134 pi
->attr
->lcommunity
, lcom
))
1137 if (type
== bgp_show_type_lcommunity
) {
1138 struct lcommunity
*lcom
= output_arg
;
1140 if (!pi
->attr
->lcommunity
||
1142 pi
->attr
->lcommunity
, lcom
))
1145 if (type
== bgp_show_type_community
) {
1146 struct community
*com
= output_arg
;
1148 if (!pi
->attr
->community
||
1150 pi
->attr
->community
, com
))
1153 if (type
== bgp_show_type_community_exact
) {
1154 struct community
*com
= output_arg
;
1156 if (!pi
->attr
->community
||
1158 pi
->attr
->community
, com
))
1163 json_object_int_add(
1164 json
, "bgpTableVersion",
1166 json_object_string_add(
1171 json_object_int_add(
1174 bgp
->default_local_pref
);
1175 json_object_int_add(
1179 if (option
== SHOW_DISPLAY_TAGS
)
1184 == SHOW_DISPLAY_OVERLAY
)
1188 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1201 /* Decode RD type. */
1202 type
= decode_rd_type(pnt
);
1203 /* Decode RD value. */
1204 if (type
== RD_TYPE_AS
)
1205 decode_rd_as(pnt
+ 2, &rd_as
);
1206 else if (type
== RD_TYPE_AS4
)
1207 decode_rd_as4(pnt
+ 2, &rd_as
);
1208 else if (type
== RD_TYPE_IP
)
1209 decode_rd_ip(pnt
+ 2, &rd_ip
);
1211 if (type
== RD_TYPE_AS
1212 || type
== RD_TYPE_AS4
)
1213 sprintf(rd_str
, "%u:%d",
1216 else if (type
== RD_TYPE_IP
)
1217 sprintf(rd_str
, "%s:%d",
1221 json_object_string_add(
1228 "Route Distinguisher: ");
1229 if (type
== RD_TYPE_AS
)
1234 else if (type
== RD_TYPE_AS4
)
1239 else if (type
== RD_TYPE_IP
)
1240 vty_out(vty
, "ip %s:%d",
1244 vty_out(vty
, "\n\n");
1249 if (option
== SHOW_DISPLAY_TAGS
)
1250 route_vty_out_tag(vty
, &rm
->p
, pi
,
1251 no_display
, SAFI_EVPN
,
1253 else if (option
== SHOW_DISPLAY_OVERLAY
)
1254 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1258 route_vty_out(vty
, &rm
->p
, pi
,
1259 no_display
, SAFI_EVPN
,
1268 json_object_object_add(json_prefix_info
,
1269 "paths", json_array
);
1270 json_object_object_add(json_nroute
, buf
,
1276 json_object_object_add(json
, rd_str
, json_nroute
);
1280 json_object_int_add(json
, "numPrefix", output_count
);
1281 json_object_int_add(json
, "totalPrefix", total_count
);
1282 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1283 json
, JSON_C_TO_STRING_PRETTY
));
1284 json_object_free(json
);
1286 if (output_count
== 0)
1287 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1291 "\nDisplayed %ld out of %ld total prefixes\n",
1292 output_count
, total_count
);
1297 DEFUN(show_ip_bgp_l2vpn_evpn
,
1298 show_ip_bgp_l2vpn_evpn_cmd
,
1299 "show [ip] bgp l2vpn evpn [json]",
1300 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1302 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1303 use_json(argc
, argv
));
1306 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1307 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1308 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1314 "Display information for a route distinguisher\n"
1315 "VPN Route Distinguisher\n" JSON_STR
)
1317 int idx_ext_community
= 0;
1319 struct prefix_rd prd
;
1321 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1323 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1325 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1328 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1329 use_json(argc
, argv
));
1332 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1333 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1334 "show [ip] bgp l2vpn evpn all tags",
1340 "Display information about all EVPN NLRIs\n"
1341 "Display BGP tags for prefixes\n")
1343 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1347 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1348 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1349 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1355 "Display information for a route distinguisher\n"
1356 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1358 int idx_ext_community
= 0;
1360 struct prefix_rd prd
;
1362 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1364 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1366 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1369 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1373 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1374 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1375 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1381 "Detailed information on TCP and BGP neighbor connections\n"
1382 "IPv4 Neighbor to display information about\n"
1383 "IPv6 Neighbor to display information about\n"
1384 "Neighbor on BGP configured interface\n"
1385 "Display routes learned from neighbor\n" JSON_STR
)
1389 char *peerstr
= NULL
;
1390 bool uj
= use_json(argc
, argv
);
1391 afi_t afi
= AFI_L2VPN
;
1392 safi_t safi
= SAFI_EVPN
;
1393 struct bgp
*bgp
= NULL
;
1395 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1398 vty_out(vty
, "No index\n");
1402 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1403 argv_find(argv
, argc
, "neighbors", &idx
);
1404 peerstr
= argv
[++idx
]->arg
;
1406 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1409 json_object
*json_no
= NULL
;
1410 json_no
= json_object_new_object();
1411 json_object_string_add(json_no
, "warning",
1412 "Malformed address");
1413 vty_out(vty
, "%s\n",
1414 json_object_to_json_string(json_no
));
1415 json_object_free(json_no
);
1417 vty_out(vty
, "Malformed address: %s\n",
1421 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1423 json_object
*json_no
= NULL
;
1424 json_no
= json_object_new_object();
1425 json_object_string_add(
1427 "No such neighbor or address family");
1428 vty_out(vty
, "%s\n",
1429 json_object_to_json_string(json_no
));
1430 json_object_free(json_no
);
1432 vty_out(vty
, "%% No such neighbor or address family\n");
1436 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1440 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1441 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1442 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1448 "Display information for a route distinguisher\n"
1449 "VPN Route Distinguisher\n"
1450 "Detailed information on TCP and BGP neighbor connections\n"
1451 "IPv4 Neighbor to display information about\n"
1452 "IPv6 Neighbor to display information about\n"
1453 "Neighbor on BGP configured interface\n"
1454 "Display routes learned from neighbor\n" JSON_STR
)
1456 int idx_ext_community
= 0;
1460 char *peerstr
= NULL
;
1461 struct prefix_rd prd
;
1462 bool uj
= use_json(argc
, argv
);
1463 afi_t afi
= AFI_L2VPN
;
1464 safi_t safi
= SAFI_EVPN
;
1465 struct bgp
*bgp
= NULL
;
1467 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1470 vty_out(vty
, "No index\n");
1474 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1475 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1478 json_object
*json_no
= NULL
;
1479 json_no
= json_object_new_object();
1480 json_object_string_add(json_no
, "warning",
1481 "Malformed Route Distinguisher");
1482 vty_out(vty
, "%s\n",
1483 json_object_to_json_string(json_no
));
1484 json_object_free(json_no
);
1486 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1490 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1491 argv_find(argv
, argc
, "neighbors", &idx
);
1492 peerstr
= argv
[++idx
]->arg
;
1494 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1497 json_object
*json_no
= NULL
;
1498 json_no
= json_object_new_object();
1499 json_object_string_add(json_no
, "warning",
1500 "Malformed address");
1501 vty_out(vty
, "%s\n",
1502 json_object_to_json_string(json_no
));
1503 json_object_free(json_no
);
1505 vty_out(vty
, "Malformed address: %s\n",
1509 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1511 json_object
*json_no
= NULL
;
1512 json_no
= json_object_new_object();
1513 json_object_string_add(
1515 "No such neighbor or address family");
1516 vty_out(vty
, "%s\n",
1517 json_object_to_json_string(json_no
));
1518 json_object_free(json_no
);
1520 vty_out(vty
, "%% No such neighbor or address family\n");
1524 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1528 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1529 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1530 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1536 "Detailed information on TCP and BGP neighbor connections\n"
1537 "IPv4 Neighbor to display information about\n"
1538 "IPv6 Neighbor to display information about\n"
1539 "Neighbor on BGP configured interface\n"
1540 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1544 bool uj
= use_json(argc
, argv
);
1545 struct bgp
*bgp
= NULL
;
1546 afi_t afi
= AFI_L2VPN
;
1547 safi_t safi
= SAFI_EVPN
;
1548 char *peerstr
= NULL
;
1553 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1556 vty_out(vty
, "No index\n");
1560 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1561 argv_find(argv
, argc
, "neighbors", &idx
);
1562 peerstr
= argv
[++idx
]->arg
;
1564 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1567 json_object
*json_no
= NULL
;
1568 json_no
= json_object_new_object();
1569 json_object_string_add(json_no
, "warning",
1570 "Malformed address");
1571 vty_out(vty
, "%s\n",
1572 json_object_to_json_string(json_no
));
1573 json_object_free(json_no
);
1575 vty_out(vty
, "Malformed address: %s\n",
1579 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1581 json_object
*json_no
= NULL
;
1582 json_no
= json_object_new_object();
1583 json_object_string_add(
1585 "No such neighbor or address family");
1586 vty_out(vty
, "%s\n",
1587 json_object_to_json_string(json_no
));
1588 json_object_free(json_no
);
1590 vty_out(vty
, "%% No such neighbor or address family\n");
1594 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1597 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1598 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1599 "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]",
1605 "Display information for a route distinguisher\n"
1606 "VPN Route Distinguisher\n"
1607 "Detailed information on TCP and BGP neighbor connections\n"
1608 "IPv4 Neighbor to display information about\n"
1609 "IPv6 Neighbor to display information about\n"
1610 "Neighbor on BGP configured interface\n"
1611 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1613 int idx_ext_community
= 0;
1617 struct prefix_rd prd
;
1618 struct bgp
*bgp
= NULL
;
1619 bool uj
= use_json(argc
, argv
);
1620 char *peerstr
= NULL
;
1621 afi_t afi
= AFI_L2VPN
;
1622 safi_t safi
= SAFI_EVPN
;
1630 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1633 vty_out(vty
, "No index\n");
1637 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1639 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1640 argv_find(argv
, argc
, "neighbors", &idx
);
1641 peerstr
= argv
[++idx
]->arg
;
1643 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1646 json_object
*json_no
= NULL
;
1647 json_no
= json_object_new_object();
1648 json_object_string_add(json_no
, "warning",
1649 "Malformed address");
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 address: %s\n",
1658 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1660 json_object
*json_no
= NULL
;
1661 json_no
= json_object_new_object();
1662 json_object_string_add(
1664 "No such neighbor or address family");
1665 vty_out(vty
, "%s\n",
1666 json_object_to_json_string(json_no
));
1667 json_object_free(json_no
);
1669 vty_out(vty
, "%% No such neighbor or address family\n");
1673 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1676 json_object
*json_no
= NULL
;
1677 json_no
= json_object_new_object();
1678 json_object_string_add(json_no
, "warning",
1679 "Malformed Route Distinguisher");
1680 vty_out(vty
, "%s\n",
1681 json_object_to_json_string(json_no
));
1682 json_object_free(json_no
);
1684 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1688 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1691 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1692 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1693 "show [ip] bgp l2vpn evpn all overlay [json]",
1699 "Display information about all EVPN NLRIs\n"
1700 "Display BGP Overlay Information for prefixes\n"
1703 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1704 SHOW_DISPLAY_OVERLAY
,
1705 use_json(argc
, argv
));
1708 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1709 show_ip_bgp_evpn_rd_overlay_cmd
,
1710 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1716 "Display information for a route distinguisher\n"
1717 "VPN Route Distinguisher\n"
1718 "Display BGP Overlay Information for prefixes\n")
1720 int idx_ext_community
= 0;
1722 struct prefix_rd prd
;
1724 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1726 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1728 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1731 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1732 SHOW_DISPLAY_OVERLAY
,
1733 use_json(argc
, argv
));
1736 DEFUN(show_bgp_l2vpn_evpn_com
,
1737 show_bgp_l2vpn_evpn_com_cmd
,
1738 "show bgp l2vpn evpn \
1739 <community AA:NN|large-community AA:BB:CC> \
1740 [exact-match] [json]",
1745 "Display routes matching the community\n"
1746 "Community number where AA and NN are (0-65535)\n"
1747 "Display routes matching the large-community\n"
1748 "List of large-community numbers\n"
1749 "Exact match of the communities\n"
1754 const char *clist_number_or_name
;
1755 int show_type
= bgp_show_type_normal
;
1756 struct community
*com
;
1757 struct lcommunity
*lcom
;
1759 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1760 clist_number_or_name
= argv
[++idx
]->arg
;
1761 show_type
= bgp_show_type_lcommunity
;
1763 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1764 show_type
= bgp_show_type_lcommunity_exact
;
1766 lcom
= lcommunity_str2com(clist_number_or_name
);
1768 vty_out(vty
, "%% Large-community malformed\n");
1772 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1773 SHOW_DISPLAY_STANDARD
,
1774 use_json(argc
, argv
));
1776 lcommunity_free(&lcom
);
1777 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1778 clist_number_or_name
= argv
[++idx
]->arg
;
1779 show_type
= bgp_show_type_community
;
1781 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1782 show_type
= bgp_show_type_community_exact
;
1784 com
= community_str2com(clist_number_or_name
);
1787 vty_out(vty
, "%% Community malformed: %s\n",
1788 clist_number_or_name
);
1792 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1793 SHOW_DISPLAY_STANDARD
,
1794 use_json(argc
, argv
));
1795 community_free(&com
);
1801 /* For testing purpose, static route of EVPN RT-5. */
1802 DEFUN(evpnrt5_network
,
1803 evpnrt5_network_cmd
,
1804 "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]",
1805 "Specify a network to announce via BGP\n"
1808 "Specify Route Distinguisher\n"
1809 "VPN Route Distinguisher\n"
1811 "Ethernet Tag Value\n"
1814 "Ethernet Segment Identifier\n"
1815 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1817 "Gateway IP ( A.B.C.D )\n"
1818 "Gateway IPv6 ( X:X::X:X )\n"
1819 "Router Mac Ext Comm\n"
1820 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1821 "Route-map to modify the attributes\n"
1822 "Name of the route map\n")
1824 int idx_ipv4_prefixlen
= 1;
1825 int idx_route_distinguisher
= 3;
1830 int idx_routermac
= 13;
1832 return bgp_static_set_safi(
1833 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1834 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1835 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1836 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1837 argv
[idx_routermac
]->arg
);
1840 /* For testing purpose, static route of EVPN RT-5. */
1841 DEFUN(no_evpnrt5_network
,
1842 no_evpnrt5_network_cmd
,
1843 "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>",
1845 "Specify a network to announce via BGP\n"
1848 "Specify Route Distinguisher\n"
1849 "VPN Route Distinguisher\n"
1851 "Ethernet Tag Value\n"
1854 "Ethernet Segment Identifier\n"
1855 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1856 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1858 int idx_ipv4_prefixlen
= 2;
1859 int idx_ext_community
= 4;
1864 return bgp_static_unset_safi(
1865 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1866 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1867 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1868 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1871 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1873 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1876 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1878 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1882 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1883 * check that this is a change.
1885 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1886 struct ecommunity
*ecomadd
)
1888 /* If the VNI is "live", we need to uninstall routes using the current
1889 * import RT(s) first before we update the import RT, and subsequently
1892 if (is_vni_live(vpn
))
1893 bgp_evpn_uninstall_routes(bgp
, vpn
);
1895 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1896 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1898 /* If the auto route-target is in use we must remove it */
1899 evpn_import_rt_delete_auto(bgp
, vpn
);
1901 /* Add new RT and rebuild the RT to VNI mapping */
1902 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1904 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1905 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1907 /* Install routes that match new import RT */
1908 if (is_vni_live(vpn
))
1909 bgp_evpn_install_routes(bgp
, vpn
);
1913 * Unconfigure Import RT(s) for a VNI (vty handler).
1915 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1916 struct ecommunity
*ecomdel
)
1918 struct listnode
*node
, *nnode
, *node_to_del
;
1919 struct ecommunity
*ecom
;
1921 /* Along the lines of "configure" except we have to reset to the
1924 if (is_vni_live(vpn
))
1925 bgp_evpn_uninstall_routes(bgp
, vpn
);
1927 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1928 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1930 /* Delete all import RTs */
1931 if (ecomdel
== NULL
) {
1932 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1933 ecommunity_free(&ecom
);
1934 list_delete_node(vpn
->import_rtl
, node
);
1938 /* Delete a specific import RT */
1942 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1943 if (ecommunity_match(ecom
, ecomdel
)) {
1944 ecommunity_free(&ecom
);
1951 list_delete_node(vpn
->import_rtl
, node_to_del
);
1954 assert(vpn
->import_rtl
);
1955 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1956 if (list_isempty(vpn
->import_rtl
)) {
1957 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1958 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1960 /* Rebuild the RT to VNI mapping */
1962 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1964 /* Install routes that match new import RT */
1965 if (is_vni_live(vpn
))
1966 bgp_evpn_install_routes(bgp
, vpn
);
1970 * Configure the Export RT for a VNI (vty handler). Caller expected to
1971 * check that this is a change. Note that only a single export RT is
1972 * allowed for a VNI and any change to configuration is implemented as
1973 * a "replace" (similar to other configuration).
1975 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1976 struct ecommunity
*ecomadd
)
1978 /* If the auto route-target is in use we must remove it */
1979 evpn_export_rt_delete_auto(bgp
, vpn
);
1981 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1982 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1984 if (is_vni_live(vpn
))
1985 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1989 * Unconfigure the Export RT for a VNI (vty handler)
1991 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1992 struct ecommunity
*ecomdel
)
1994 struct listnode
*node
, *nnode
, *node_to_del
;
1995 struct ecommunity
*ecom
;
1997 /* Delete all export RTs */
1998 if (ecomdel
== NULL
) {
1999 /* Reset to default and process all routes. */
2000 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2001 ecommunity_free(&ecom
);
2002 list_delete_node(vpn
->export_rtl
, node
);
2006 /* Delete a specific export RT */
2010 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2011 if (ecommunity_match(ecom
, ecomdel
)) {
2012 ecommunity_free(&ecom
);
2019 list_delete_node(vpn
->export_rtl
, node_to_del
);
2022 assert(vpn
->export_rtl
);
2023 if (list_isempty(vpn
->export_rtl
)) {
2024 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2025 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2028 if (is_vni_live(vpn
))
2029 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2033 * Configure RD for VRF
2035 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2037 /* If we have already advertise type-5 routes with a diffrent RD, we
2038 * have to delete and withdraw them firs
2040 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2043 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2044 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2046 /* We have a new RD for VRF.
2047 * Advertise all type-5 routes again with the new RD
2049 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2053 * Unconfigure RD for VRF
2055 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2057 /* If we have already advertise type-5 routes with a diffrent RD, we
2058 * have to delete and withdraw them firs
2060 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2062 /* fall back to default RD */
2063 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2064 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2066 /* We have a new RD for VRF.
2067 * Advertise all type-5 routes again with the new RD
2069 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2073 * Configure RD for a VNI (vty handler)
2075 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2076 struct prefix_rd
*rd
)
2078 /* If the VNI is "live", we need to delete and withdraw this VNI's
2079 * local routes with the prior RD first. Then, after updating RD,
2080 * need to re-advertise.
2082 if (is_vni_live(vpn
))
2083 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2086 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2087 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2089 if (is_vni_live(vpn
))
2090 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2094 * Unconfigure RD for a VNI (vty handler)
2096 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2098 /* If the VNI is "live", we need to delete and withdraw this VNI's
2099 * local routes with the prior RD first. Then, after resetting RD
2100 * to automatic value, need to re-advertise.
2102 if (is_vni_live(vpn
))
2103 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2105 /* reset RD to default */
2106 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2108 if (is_vni_live(vpn
))
2109 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2113 * Create VNI, if not already present (VTY handler). Mark as configured.
2115 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2117 struct bgpevpn
*vpn
;
2118 struct in_addr mcast_grp
= {INADDR_ANY
};
2123 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2125 /* Check if this L2VNI is already configured as L3VNI */
2126 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2129 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2134 /* tenant vrf will be updated when we get local_vni_add from
2137 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2141 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2147 /* Mark as configured. */
2148 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2153 * Delete VNI. If VNI does not exist in the system (i.e., just
2154 * configuration), all that is needed is to free it. Otherwise,
2155 * any parameters configured for the VNI need to be reset (with
2156 * appropriate action) and the VNI marked as unconfigured; the
2157 * VNI will continue to exist, purely as a "learnt" entity.
2159 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2161 assert(bgp
->vnihash
);
2163 if (!is_vni_live(vpn
)) {
2164 bgp_evpn_free(bgp
, vpn
);
2168 /* We need to take the unconfigure action for each parameter of this VNI
2169 * that is configured. Some optimization is possible, but not worth the
2170 * additional code for an operation that should be pretty rare.
2172 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2174 /* First, deal with the export side - RD and export RT changes. */
2175 if (is_rd_configured(vpn
))
2176 evpn_unconfigure_rd(bgp
, vpn
);
2177 if (is_export_rt_configured(vpn
))
2178 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2180 /* Next, deal with the import side. */
2181 if (is_import_rt_configured(vpn
))
2182 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2188 * Display import RT mapping to VRFs (vty handler)
2189 * bgp_evpn: evpn bgp instance
2191 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2199 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2200 (void (*)(struct hash_bucket
*,
2201 void *))show_vrf_import_rt_entry
,
2206 * Display import RT mapping to VNIs (vty handler)
2208 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2217 bgp
->import_rt_hash
,
2218 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2223 * Display EVPN routes for all VNIs - vty handler.
2225 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2226 struct in_addr vtep_ip
, json_object
*json
,
2230 struct vni_walk_ctx wctx
;
2232 num_vnis
= hashcount(bgp
->vnihash
);
2235 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2238 wctx
.vtep_ip
= vtep_ip
;
2240 wctx
.detail
= detail
;
2241 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2242 void *))show_vni_routes_hash
,
2247 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2249 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2250 vni_t vni
, struct in_addr orig_ip
,
2253 struct bgpevpn
*vpn
;
2254 struct prefix_evpn p
;
2255 struct bgp_node
*rn
;
2256 struct bgp_path_info
*pi
;
2257 uint32_t path_cnt
= 0;
2260 json_object
*json_paths
= NULL
;
2266 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2268 vty_out(vty
, "VNI not found\n");
2272 /* See if route exists. */
2273 build_evpn_type3_prefix(&p
, orig_ip
);
2274 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2275 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2277 vty_out(vty
, "%% Network not in table\n");
2282 json_paths
= json_object_new_array();
2284 /* Prefix and num paths displayed once per prefix. */
2285 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2287 /* Display each path for this prefix. */
2288 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2289 json_object
*json_path
= NULL
;
2292 json_path
= json_object_new_array();
2294 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2298 json_object_array_add(json_paths
, json_path
);
2305 json_object_object_add(json
, "paths", json_paths
);
2307 json_object_int_add(json
, "numPaths", path_cnt
);
2309 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2315 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2316 * By definition, only matching type-2 route will be displayed.
2318 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2319 vni_t vni
, struct ethaddr
*mac
,
2320 struct ipaddr
*ip
, json_object
*json
)
2322 struct bgpevpn
*vpn
;
2323 struct prefix_evpn p
;
2324 struct bgp_node
*rn
;
2325 struct bgp_path_info
*pi
;
2326 uint32_t path_cnt
= 0;
2329 json_object
*json_paths
= NULL
;
2335 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2338 vty_out(vty
, "VNI not found\n");
2342 /* See if route exists. Look for both non-sticky and sticky. */
2343 build_evpn_type2_prefix(&p
, mac
, ip
);
2344 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2345 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2347 vty_out(vty
, "%% Network not in table\n");
2352 json_paths
= json_object_new_array();
2354 /* Prefix and num paths displayed once per prefix. */
2355 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2357 /* Display each path for this prefix. */
2358 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2359 json_object
*json_path
= NULL
;
2362 json_path
= json_object_new_array();
2364 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2368 json_object_array_add(json_paths
, json_path
);
2375 json_object_object_add(json
, "paths", json_paths
);
2377 json_object_int_add(json
, "numPaths", path_cnt
);
2379 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2384 /* Disaplay EVPN routes for a ESI - VTY handler */
2385 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2386 esi_t
*esi
, json_object
*json
)
2388 struct evpnes
*es
= NULL
;
2391 es
= bgp_evpn_lookup_es(bgp
, esi
);
2394 vty_out(vty
, "ESI not found\n");
2398 show_esi_routes(bgp
, es
, vty
, json
);
2402 * Display EVPN routes for a VNI - vty handler.
2403 * If 'type' is non-zero, only routes matching that type are shown.
2404 * If the vtep_ip is non zero, only routes behind that vtep are shown
2406 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2407 int type
, struct in_addr vtep_ip
,
2410 struct bgpevpn
*vpn
;
2413 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2416 vty_out(vty
, "VNI not found\n");
2420 /* Walk this VNI's route table and display appropriate routes. */
2421 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2425 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2426 * IP (vty handler). By definition, only matching type-2 route will be
2429 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2430 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2431 struct ipaddr
*ip
, json_object
*json
)
2433 struct prefix_evpn p
;
2434 struct bgp_node
*rn
;
2435 struct bgp_path_info
*pi
;
2438 uint32_t path_cnt
= 0;
2439 json_object
*json_paths
= NULL
;
2440 char prefix_str
[BUFSIZ
];
2445 /* See if route exists. Look for both non-sticky and sticky. */
2446 build_evpn_type2_prefix(&p
, mac
, ip
);
2447 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2448 (struct prefix
*)&p
, prd
);
2449 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2451 vty_out(vty
, "%% Network not in table\n");
2455 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2456 sizeof(prefix_str
));
2458 /* Prefix and num paths displayed once per prefix. */
2459 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2462 json_paths
= json_object_new_array();
2464 /* Display each path for this prefix. */
2465 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2466 json_object
*json_path
= NULL
;
2469 json_path
= json_object_new_array();
2471 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2475 json_object_array_add(json_paths
, json_path
);
2480 if (json
&& path_cnt
) {
2482 json_object_object_add(json
, prefix_str
, json_paths
);
2483 json_object_int_add(json
, "numPaths", path_cnt
);
2485 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2491 * Display BGP EVPN routing table -- for specific RD (vty handler)
2492 * If 'type' is non-zero, only routes matching that type are shown.
2494 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2495 struct prefix_rd
*prd
, int type
,
2498 struct bgp_node
*rd_rn
;
2499 struct bgp_table
*table
;
2500 struct bgp_node
*rn
;
2501 struct bgp_path_info
*pi
;
2505 uint32_t prefix_cnt
, path_cnt
;
2506 char rd_str
[RD_ADDRSTRLEN
];
2507 json_object
*json_rd
= NULL
;
2508 int add_rd_to_json
= 0;
2512 prefix_cnt
= path_cnt
= 0;
2514 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2516 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2520 table
= bgp_node_get_bgp_table_info(rd_rn
);
2525 json_rd
= json_object_new_object();
2526 json_object_string_add(json_rd
, "rd", rd_str
);
2529 /* Display all prefixes with this RD. */
2530 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2531 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2532 json_object
*json_prefix
= NULL
;
2533 json_object
*json_paths
= NULL
;
2534 char prefix_str
[BUFSIZ
];
2535 int add_prefix_to_json
= 0;
2537 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2538 sizeof(prefix_str
));
2540 if (type
&& evp
->prefix
.route_type
!= type
)
2544 json_prefix
= json_object_new_object();
2546 pi
= bgp_node_get_bgp_path_info(rn
);
2548 /* RD header and legend - once overall. */
2549 if (rd_header
&& !json
) {
2551 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2553 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2555 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2559 /* Prefix and num paths displayed once per prefix. */
2560 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2567 json_paths
= json_object_new_array();
2569 /* Display each path for this prefix. */
2570 for (; pi
; pi
= pi
->next
) {
2571 json_object
*json_path
= NULL
;
2574 json_path
= json_object_new_array();
2576 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2580 json_object_array_add(json_paths
, json_path
);
2583 add_prefix_to_json
= 1;
2587 if (json
&& add_prefix_to_json
) {
2588 json_object_object_add(json_prefix
, "paths",
2590 json_object_object_add(json_rd
, prefix_str
,
2595 if (json
&& add_rd_to_json
)
2596 json_object_object_add(json
, rd_str
, json_rd
);
2599 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2600 json_object_int_add(json
, "numPaths", path_cnt
);
2602 if (prefix_cnt
== 0)
2603 vty_out(vty
, "No prefixes exist with this RD%s\n",
2604 type
? " (of requested type)" : "");
2607 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2608 prefix_cnt
, path_cnt
,
2609 type
? " (of requested type)" : "");
2614 * Display BGP EVPN routing table - all routes (vty handler).
2615 * If 'type' is non-zero, only routes matching that type are shown.
2617 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2618 json_object
*json
, int detail
)
2620 struct bgp_node
*rd_rn
;
2621 struct bgp_table
*table
;
2622 struct bgp_node
*rn
;
2623 struct bgp_path_info
*pi
;
2624 int header
= detail
? 0 : 1;
2628 uint32_t prefix_cnt
, path_cnt
;
2632 prefix_cnt
= path_cnt
= 0;
2634 /* EVPN routing table is a 2-level table with the first level being
2637 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2638 rd_rn
= bgp_route_next(rd_rn
)) {
2639 char rd_str
[RD_ADDRSTRLEN
];
2640 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2641 int add_rd_to_json
= 0;
2644 table
= bgp_node_get_bgp_table_info(rd_rn
);
2648 tbl_ver
= table
->version
;
2649 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2653 json_rd
= json_object_new_object();
2654 json_object_string_add(json_rd
, "rd", rd_str
);
2659 /* Display all prefixes for an RD */
2660 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2661 json_object
*json_prefix
=
2662 NULL
; /* contains prefix under a RD */
2663 json_object
*json_paths
=
2664 NULL
; /* array of paths under a prefix*/
2665 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2666 char prefix_str
[BUFSIZ
];
2667 int add_prefix_to_json
= 0;
2669 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2670 prefix_str
, sizeof(prefix_str
));
2672 if (type
&& evp
->prefix
.route_type
!= type
)
2675 pi
= bgp_node_get_bgp_path_info(rn
);
2677 /* Overall header/legend displayed once. */
2679 bgp_evpn_show_route_header(vty
, bgp
,
2684 "%19s Extended Community\n"
2689 /* RD header - per RD. */
2691 bgp_evpn_show_route_rd_header(
2700 json_prefix
= json_object_new_object();
2701 json_paths
= json_object_new_array();
2702 json_object_string_add(json_prefix
, "prefix",
2704 json_object_int_add(json_prefix
, "prefixLen",
2708 /* Prefix and num paths displayed once per prefix. */
2710 route_vty_out_detail_header(
2712 (struct prefix_rd
*)&rd_rn
->p
,
2713 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2715 /* For EVPN, the prefix is displayed for each path (to
2717 * with code that already exists).
2719 for (; pi
; pi
= pi
->next
) {
2720 json_object
*json_path
= NULL
;
2722 add_prefix_to_json
= 1;
2726 json_path
= json_object_new_array();
2729 route_vty_out_detail(
2730 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2731 SAFI_EVPN
, json_path
);
2733 route_vty_out(vty
, &rn
->p
, pi
, 0,
2734 SAFI_EVPN
, json_path
);
2737 json_object_array_add(json_paths
,
2741 if (json
&& add_prefix_to_json
) {
2742 json_object_object_add(json_prefix
, "paths",
2744 json_object_object_add(json_rd
, prefix_str
,
2749 if (json
&& add_rd_to_json
)
2750 json_object_object_add(json
, rd_str
, json_rd
);
2754 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2755 json_object_int_add(json
, "numPaths", path_cnt
);
2757 if (prefix_cnt
== 0) {
2758 vty_out(vty
, "No EVPN prefixes %sexist\n",
2759 type
? "(of requested type) " : "");
2761 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2762 prefix_cnt
, path_cnt
,
2763 type
? " (of requested type)" : "");
2768 /* Display specific ES */
2769 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2772 struct evpnes
*es
= NULL
;
2774 es
= bgp_evpn_lookup_es(bgp
, esi
);
2776 display_es(vty
, es
, json
);
2779 vty_out(vty
, "{}\n");
2781 vty_out(vty
, "ESI not found\n");
2787 /* Display all ESs */
2788 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2794 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2795 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2800 hash_iterate(bgp
->esihash
,
2801 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2806 * Display specified VNI (vty handler)
2808 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2812 struct bgpevpn
*vpn
;
2814 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2817 display_vni(vty
, vpn
, json
);
2819 struct bgp
*bgp_temp
;
2820 struct listnode
*node
= NULL
;
2822 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2823 if (bgp_temp
->l3vni
== vni
) {
2825 display_l3vni(vty
, bgp_temp
, json
);
2832 vty_out(vty
, "{}\n");
2834 vty_out(vty
, "VNI not found\n");
2841 * Display a VNI (upon user query).
2843 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2847 struct bgp
*bgp_temp
= NULL
;
2848 struct listnode
*node
;
2852 vty_out(vty
, "Flags: * - Kernel\n");
2853 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2854 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2857 /* print all L2 VNIS */
2860 hash_iterate(bgp
->vnihash
,
2861 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2864 /* print all L3 VNIs */
2865 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2866 show_l3vni_entry(vty
, bgp_temp
, json
);
2870 * evpn - enable advertisement of svi MAC-IP
2872 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2876 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2878 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2881 bgp
->evpn_info
->advertise_svi_macip
= set
;
2882 bgp_zebra_advertise_svi_macip(bgp
,
2883 bgp
->evpn_info
->advertise_svi_macip
, 0);
2885 if (set
&& vpn
->advertise_svi_macip
)
2887 else if (!set
&& !vpn
->advertise_svi_macip
)
2890 vpn
->advertise_svi_macip
= set
;
2891 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2897 * evpn - enable advertisement of default g/w
2899 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2902 if (bgp
->advertise_gw_macip
)
2905 bgp
->advertise_gw_macip
= 1;
2906 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2908 if (vpn
->advertise_gw_macip
)
2911 vpn
->advertise_gw_macip
= 1;
2912 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2919 * evpn - disable advertisement of default g/w
2921 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2922 struct bgpevpn
*vpn
)
2925 if (!bgp
->advertise_gw_macip
)
2928 bgp
->advertise_gw_macip
= 0;
2929 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2931 if (!vpn
->advertise_gw_macip
)
2934 vpn
->advertise_gw_macip
= 0;
2935 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2942 * evpn - enable advertisement of default g/w
2944 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2945 afi_t afi
, bool add
)
2947 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2950 /* bail if we are already advertising default route */
2951 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2955 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2956 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2957 else if (afi
== AFI_IP6
)
2958 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2959 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2961 /* bail out if we havent advertised the default route */
2962 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2965 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2966 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2967 else if (afi
== AFI_IP6
)
2968 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2969 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2972 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2976 * evpn - enable advertisement of default g/w
2978 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2979 struct bgpevpn
*vpn
)
2981 if (vpn
->advertise_subnet
)
2984 vpn
->advertise_subnet
= 1;
2985 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2989 * evpn - disable advertisement of default g/w
2991 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2993 if (!vpn
->advertise_subnet
)
2996 vpn
->advertise_subnet
= 0;
2997 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3001 * EVPN (VNI advertisement) enabled. Register with zebra.
3003 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3005 bgp
->advertise_all_vni
= 1;
3007 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3011 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3012 * cache, EVPN routes (delete and withdraw from peers).
3014 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3016 bgp
->advertise_all_vni
= 0;
3017 bgp_set_evpn(bgp_get_default());
3018 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3019 bgp_evpn_cleanup_on_disable(bgp
);
3023 * EVPN - use RFC8365 to auto-derive RT
3025 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3027 bgp
->advertise_autort_rfc8365
= 1;
3028 bgp_evpn_handle_autort_change(bgp
);
3032 * EVPN - don't use RFC8365 to auto-derive RT
3034 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3036 bgp
->advertise_autort_rfc8365
= 0;
3037 bgp_evpn_handle_autort_change(bgp
);
3040 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3042 char buf1
[RD_ADDRSTRLEN
];
3044 struct listnode
*node
, *nnode
;
3045 struct ecommunity
*ecom
;
3047 if (is_vni_configured(vpn
)) {
3048 vty_out(vty
, " vni %d\n", vpn
->vni
);
3049 if (is_rd_configured(vpn
))
3050 vty_out(vty
, " rd %s\n",
3051 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3053 if (is_import_rt_configured(vpn
)) {
3054 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3056 ecom_str
= ecommunity_ecom2str(
3057 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3058 vty_out(vty
, " route-target import %s\n",
3060 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3064 if (is_export_rt_configured(vpn
)) {
3065 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3067 ecom_str
= ecommunity_ecom2str(
3068 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3069 vty_out(vty
, " route-target export %s\n",
3071 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3075 if (vpn
->advertise_gw_macip
)
3076 vty_out(vty
, " advertise-default-gw\n");
3078 if (vpn
->advertise_svi_macip
)
3079 vty_out(vty
, " advertise-svi-ip\n");
3081 if (vpn
->advertise_subnet
)
3082 vty_out(vty
, " advertise-subnet\n");
3084 vty_out(vty
, " exit-vni\n");
3088 #ifndef VTYSH_EXTRACT_PL
3089 #include "bgpd/bgp_evpn_vty_clippy.c"
3092 DEFPY(bgp_evpn_flood_control
,
3093 bgp_evpn_flood_control_cmd
,
3094 "[no$no] flooding <disable$disable|head-end-replication$her>",
3096 "Specify handling for BUM packets\n"
3097 "Do not flood any BUM packets\n"
3098 "Flood BUM packets using head-end replication\n")
3100 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3101 enum vxlan_flood_control flood_ctrl
;
3107 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3109 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3113 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3116 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3117 bgp_evpn_flood_control_change(bgp
);
3122 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3123 bgp_evpn_advertise_default_gw_vni_cmd
,
3124 "advertise-default-gw",
3125 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3127 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3128 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3133 evpn_set_advertise_default_gw(bgp
, vpn
);
3138 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3139 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3140 "no advertise-default-gw",
3142 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3144 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3145 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3150 evpn_unset_advertise_default_gw(bgp
, vpn
);
3156 DEFUN (bgp_evpn_advertise_default_gw
,
3157 bgp_evpn_advertise_default_gw_cmd
,
3158 "advertise-default-gw",
3159 "Advertise All default g/w mac-ip routes in EVPN\n")
3161 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3166 if (!EVPN_ENABLED(bgp
)) {
3168 "This command is only supported under the EVPN VRF\n");
3172 evpn_set_advertise_default_gw(bgp
, NULL
);
3177 DEFUN (no_bgp_evpn_advertise_default_gw
,
3178 no_bgp_evpn_advertise_default_gw_cmd
,
3179 "no advertise-default-gw",
3181 "Withdraw All default g/w mac-ip routes from EVPN\n")
3183 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3188 if (!EVPN_ENABLED(bgp
)) {
3190 "This command is only supported under the EVPN VRF\n");
3194 evpn_unset_advertise_default_gw(bgp
, NULL
);
3199 DEFUN (bgp_evpn_advertise_all_vni
,
3200 bgp_evpn_advertise_all_vni_cmd
,
3201 "advertise-all-vni",
3202 "Advertise All local VNIs\n")
3204 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3205 struct bgp
*bgp_evpn
= NULL
;
3210 bgp_evpn
= bgp_get_evpn();
3211 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3212 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3214 return CMD_WARNING_CONFIG_FAILED
;
3217 evpn_set_advertise_all_vni(bgp
);
3221 DEFUN (no_bgp_evpn_advertise_all_vni
,
3222 no_bgp_evpn_advertise_all_vni_cmd
,
3223 "no advertise-all-vni",
3225 "Advertise All local VNIs\n")
3227 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3231 evpn_unset_advertise_all_vni(bgp
);
3235 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3236 bgp_evpn_advertise_autort_rfc8365_cmd
,
3237 "autort rfc8365-compatible",
3238 "Auto-derivation of RT\n"
3239 "Auto-derivation of RT using RFC8365\n")
3241 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3245 evpn_set_advertise_autort_rfc8365(bgp
);
3249 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3250 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3251 "no autort rfc8365-compatible",
3253 "Auto-derivation of RT\n"
3254 "Auto-derivation of RT using RFC8365\n")
3256 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3260 evpn_unset_advertise_autort_rfc8365(bgp
);
3264 DEFUN (bgp_evpn_default_originate
,
3265 bgp_evpn_default_originate_cmd
,
3266 "default-originate <ipv4 | ipv6>",
3267 "originate a default route\n"
3268 "ipv4 address family\n"
3269 "ipv6 address family\n")
3273 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3277 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3278 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3282 DEFUN (no_bgp_evpn_default_originate
,
3283 no_bgp_evpn_default_originate_cmd
,
3284 "no default-originate <ipv4 | ipv6>",
3286 "withdraw a default route\n"
3287 "ipv4 address family\n"
3288 "ipv6 address family\n")
3292 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3296 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3297 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3301 DEFPY (dup_addr_detection
,
3302 dup_addr_detection_cmd
,
3303 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3304 "Duplicate address detection\n"
3305 "Max allowed moves before address detected as duplicate\n"
3306 "Num of max allowed moves (2-1000) default 5\n"
3307 "Duplicate address detection time\n"
3308 "Time in seconds (2-1800) default 180\n")
3310 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3315 if (!EVPN_ENABLED(bgp_vrf
)) {
3317 "This command is only supported under the EVPN VRF\n");
3321 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3324 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3326 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3328 bgp_zebra_dup_addr_detection(bgp_vrf
);
3333 DEFPY (dup_addr_detection_auto_recovery
,
3334 dup_addr_detection_auto_recovery_cmd
,
3335 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3336 "Duplicate address detection\n"
3337 "Duplicate address detection freeze\n"
3338 "Duplicate address detection permanent freeze\n"
3339 "Duplicate address detection freeze time (30-3600)\n")
3341 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3342 uint32_t freeze_time
= freeze_time_val
;
3347 if (!EVPN_ENABLED(bgp_vrf
)) {
3349 "This command is only supported under the EVPN VRF\n");
3353 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3354 bgp_vrf
->evpn_info
->dad_freeze
= true;
3355 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3357 bgp_zebra_dup_addr_detection(bgp_vrf
);
3362 DEFPY (no_dup_addr_detection
,
3363 no_dup_addr_detection_cmd
,
3364 "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>]",
3366 "Duplicate address detection\n"
3367 "Max allowed moves before address detected as duplicate\n"
3368 "Num of max allowed moves (2-1000) default 5\n"
3369 "Duplicate address detection time\n"
3370 "Time in seconds (2-1800) default 180\n"
3371 "Duplicate address detection freeze\n"
3372 "Duplicate address detection permanent freeze\n"
3373 "Duplicate address detection freeze time (30-3600)\n")
3375 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3376 uint32_t max_moves
= (uint32_t)max_moves_val
;
3377 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3382 if (!EVPN_ENABLED(bgp_vrf
)) {
3384 "This command is only supported under the EVPN VRF\n");
3389 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3391 /* Reset all parameters to default. */
3392 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3393 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3394 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3395 bgp_vrf
->evpn_info
->dad_freeze
= false;
3396 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3399 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3401 "%% Value does not match with config\n");
3404 bgp_vrf
->evpn_info
->dad_max_moves
=
3405 EVPN_DAD_DEFAULT_MAX_MOVES
;
3409 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3411 "%% Value does not match with config\n");
3414 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3418 if (bgp_vrf
->evpn_info
->dad_freeze_time
3421 "%% Value does not match with config\n");
3424 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3425 bgp_vrf
->evpn_info
->dad_freeze
= false;
3428 if (permanent_val
) {
3429 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3431 "%% Value does not match with config\n");
3434 bgp_vrf
->evpn_info
->dad_freeze
= false;
3438 bgp_zebra_dup_addr_detection(bgp_vrf
);
3443 DEFPY(bgp_evpn_advertise_svi_ip
,
3444 bgp_evpn_advertise_svi_ip_cmd
,
3445 "[no$no] advertise-svi-ip",
3447 "Advertise svi mac-ip routes in EVPN\n")
3449 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3454 if (!EVPN_ENABLED(bgp
)) {
3456 "This command is only supported under EVPN VRF\n");
3461 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3463 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3468 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3469 bgp_evpn_advertise_svi_ip_vni_cmd
,
3470 "[no$no] advertise-svi-ip",
3472 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3474 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3475 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3481 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3483 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3488 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3489 bgp_evpn_advertise_vni_subnet_cmd
,
3491 "Advertise the subnet corresponding to VNI\n")
3493 struct bgp
*bgp_vrf
= NULL
;
3494 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3495 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3500 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3504 evpn_set_advertise_subnet(bgp
, vpn
);
3508 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3509 no_bgp_evpn_advertise_vni_subnet_cmd
,
3510 "no advertise-subnet",
3512 "Advertise All local VNIs\n")
3514 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3515 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3520 evpn_unset_advertise_subnet(bgp
, vpn
);
3524 DEFUN (bgp_evpn_advertise_type5
,
3525 bgp_evpn_advertise_type5_cmd
,
3526 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3527 "Advertise prefix routes\n"
3530 "route-map for filtering specific routes\n"
3531 "Name of the route map\n")
3533 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3540 int rmap_changed
= 0;
3542 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3543 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3544 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3546 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3548 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3549 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3552 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3556 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3558 "%%only ipv4 or ipv6 address families are supported");
3562 if (safi
!= SAFI_UNICAST
) {
3564 "%%only ipv4 unicast or ipv6 unicast are supported");
3568 if (afi
== AFI_IP
) {
3570 /* if we are already advertising ipv4 prefix as type-5
3573 if (!rmap_changed
&&
3574 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3575 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3577 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3578 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3581 /* if we are already advertising ipv6 prefix as type-5
3584 if (!rmap_changed
&&
3585 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3586 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3588 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3589 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3593 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3594 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3595 XFREE(MTYPE_ROUTE_MAP_NAME
,
3596 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3597 route_map_counter_decrement(
3598 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3599 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3600 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3604 /* set the route-map for advertise command */
3605 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3606 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3607 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3608 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3609 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3610 route_map_counter_increment(
3611 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3614 /* advertise type-5 routes */
3615 if (advertise_type5_routes(bgp_vrf
, afi
))
3616 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3620 DEFUN (no_bgp_evpn_advertise_type5
,
3621 no_bgp_evpn_advertise_type5_cmd
,
3622 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3624 "Advertise prefix routes\n"
3628 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3634 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3635 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3637 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3639 "%%only ipv4 or ipv6 address families are supported");
3643 if (safi
!= SAFI_UNICAST
) {
3645 "%%only ipv4 unicast or ipv6 unicast are supported");
3649 if (afi
== AFI_IP
) {
3651 /* if we are not advertising ipv4 prefix as type-5
3654 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3655 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3656 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3657 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3658 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3662 /* if we are not advertising ipv6 prefix as type-5
3665 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3666 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3667 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3668 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3669 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3673 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3674 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3675 XFREE(MTYPE_ROUTE_MAP_NAME
,
3676 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3677 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3678 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3685 * Display VNI information - for all or a specific VNI
3687 DEFUN(show_bgp_l2vpn_evpn_vni
,
3688 show_bgp_l2vpn_evpn_vni_cmd
,
3689 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3698 struct bgp
*bgp_evpn
;
3702 json_object
*json
= NULL
;
3703 uint32_t num_l2vnis
= 0;
3704 uint32_t num_l3vnis
= 0;
3705 uint32_t num_vnis
= 0;
3706 struct listnode
*node
= NULL
;
3707 struct bgp
*bgp_temp
= NULL
;
3709 uj
= use_json(argc
, argv
);
3711 bgp_evpn
= bgp_get_evpn();
3715 if (!argv_find(argv
, argc
, "evpn", &idx
))
3719 json
= json_object_new_object();
3721 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3723 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3725 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3726 if (bgp_temp
->l3vni
)
3729 num_vnis
= num_l2vnis
+ num_l3vnis
;
3731 json_object_string_add(json
, "advertiseGatewayMacip",
3732 bgp_evpn
->advertise_gw_macip
3735 json_object_string_add(json
, "advertiseSviMacip",
3736 bgp_evpn
->evpn_info
->advertise_svi_macip
3737 ? "Enabled" : "Disabled");
3738 json_object_string_add(json
, "advertiseAllVnis",
3739 is_evpn_enabled() ? "Enabled"
3741 json_object_string_add(
3743 bgp_evpn
->vxlan_flood_ctrl
3744 == VXLAN_FLOOD_HEAD_END_REPL
3745 ? "Head-end replication"
3747 json_object_int_add(json
, "numVnis", num_vnis
);
3748 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3749 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3751 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3752 bgp_evpn
->advertise_gw_macip
? "Enabled"
3754 vty_out(vty
, "Advertise SVI Macip: %s\n",
3755 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3757 vty_out(vty
, "Advertise All VNI flag: %s\n",
3758 is_evpn_enabled() ? "Enabled" : "Disabled");
3759 vty_out(vty
, "BUM flooding: %s\n",
3760 bgp_evpn
->vxlan_flood_ctrl
3761 == VXLAN_FLOOD_HEAD_END_REPL
3762 ? "Head-end replication"
3764 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3765 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3767 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3771 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3774 /* Display specific VNI */
3775 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3776 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3780 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3781 json
, JSON_C_TO_STRING_PRETTY
));
3782 json_object_free(json
);
3789 DEFUN(show_bgp_l2vpn_evpn_es
,
3790 show_bgp_l2vpn_evpn_es_cmd
,
3791 "show bgp l2vpn evpn es [ESI] [json]",
3796 "ethernet-Segment\n"
3797 "Ethernet-Segment Identifier\n"
3803 json_object
*json
= NULL
;
3804 struct bgp
*bgp
= NULL
;
3806 memset(&esi
, 0, sizeof(esi
));
3807 uj
= use_json(argc
, argv
);
3809 bgp
= bgp_get_evpn();
3813 if (!argv_find(argv
, argc
, "evpn", &idx
))
3816 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3817 (!uj
&& argc
== (idx
+ 1) + 1)) {
3820 evpn_show_all_es(vty
, bgp
, json
);
3823 /* show a specific ES */
3825 /* get the ESI - ESI-ID is at argv[5] */
3826 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3827 vty_out(vty
, "%% Malformed ESI\n");
3830 evpn_show_es(vty
, bgp
, &esi
, json
);
3834 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3835 json
, JSON_C_TO_STRING_PRETTY
));
3836 json_object_free(json
);
3843 * Display EVPN neighbor summary.
3845 DEFUN(show_bgp_l2vpn_evpn_summary
,
3846 show_bgp_l2vpn_evpn_summary_cmd
,
3847 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3854 "Summary of BGP neighbor status\n"
3855 "Show only sessions not in Established state\n"
3859 bool uj
= use_json(argc
, argv
);
3861 bool show_failed
= false;
3863 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3864 vrf
= argv
[++idx_vrf
]->arg
;
3865 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3867 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3872 * Display global EVPN routing table.
3874 DEFUN(show_bgp_l2vpn_evpn_route
,
3875 show_bgp_l2vpn_evpn_route_cmd
,
3876 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
3881 "EVPN route information\n"
3882 "Display Detailed Information\n"
3883 "Specify Route type\n"
3884 "MAC-IP (Type-2) route\n"
3885 "Multicast (Type-3) route\n"
3886 "Ethernet Segment (type-4) route \n"
3887 "Prefix (type-5 )route\n"
3895 json_object
*json
= NULL
;
3897 uj
= use_json(argc
, argv
);
3899 bgp
= bgp_get_evpn();
3904 json
= json_object_new_object();
3907 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3908 /* Specific type is requested */
3909 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3910 type
= BGP_EVPN_MAC_IP_ROUTE
;
3911 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3912 type
= BGP_EVPN_IMET_ROUTE
;
3913 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
3914 type
= BGP_EVPN_ES_ROUTE
;
3915 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
3916 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3921 if (argv_find(argv
, argc
, "detail", &detail
))
3924 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3927 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3928 json
, JSON_C_TO_STRING_PRETTY
));
3929 json_object_free(json
);
3935 * Display global EVPN routing table for specific RD.
3937 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3938 show_bgp_l2vpn_evpn_route_rd_cmd
,
3939 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3944 "EVPN route information\n"
3945 "Route Distinguisher\n"
3946 "ASN:XX or A.B.C.D:XX\n"
3947 "Specify Route type\n"
3948 "MAC-IP (Type-2) route\n"
3949 "Multicast (Type-3) route\n"
3950 "Ethernet Segment route\n"
3956 struct prefix_rd prd
;
3961 json_object
*json
= NULL
;
3963 bgp
= bgp_get_evpn();
3967 /* check if we need json output */
3968 uj
= use_json(argc
, argv
);
3970 json
= json_object_new_object();
3973 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3974 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3977 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3983 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3984 /* Specific type is requested */
3985 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3986 type
= BGP_EVPN_MAC_IP_ROUTE
;
3987 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3988 type
= BGP_EVPN_IMET_ROUTE
;
3989 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3990 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3995 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3998 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3999 json
, JSON_C_TO_STRING_PRETTY
));
4000 json_object_free(json
);
4007 * Display global EVPN routing table for specific RD and MACIP.
4009 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4010 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4011 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4016 "EVPN route information\n"
4017 "Route Distinguisher\n"
4018 "ASN:XX or A.B.C.D:XX\n"
4020 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4022 "IP address (IPv4 or IPv6)\n"
4027 struct prefix_rd prd
;
4034 json_object
*json
= NULL
;
4036 memset(&mac
, 0, sizeof(struct ethaddr
));
4037 memset(&ip
, 0, sizeof(struct ipaddr
));
4039 bgp
= bgp_get_evpn();
4043 /* check if we need json output */
4044 uj
= use_json(argc
, argv
);
4046 json
= json_object_new_object();
4049 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4050 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4052 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4058 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4059 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4060 vty_out(vty
, "%% Malformed MAC address\n");
4065 /* get the ip if specified */
4066 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4067 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4068 vty_out(vty
, "%% Malformed IP address\n");
4073 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4076 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4077 json
, JSON_C_TO_STRING_PRETTY
));
4078 json_object_free(json
);
4084 /* Display per ESI routing table */
4085 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4086 show_bgp_l2vpn_evpn_route_esi_cmd
,
4087 "show bgp l2vpn evpn route esi ESI [json]",
4092 "EVPN route information\n"
4093 "Ethernet Segment Identifier\n"
4099 struct bgp
*bgp
= NULL
;
4100 json_object
*json
= NULL
;
4102 memset(&esi
, 0, sizeof(esi
));
4103 bgp
= bgp_get_evpn();
4107 uj
= use_json(argc
, argv
);
4109 json
= json_object_new_object();
4111 /* get the ESI - ESI-ID is at argv[6] */
4112 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4113 vty_out(vty
, "%% Malformed ESI\n");
4117 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4120 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4121 json
, JSON_C_TO_STRING_PRETTY
));
4122 json_object_free(json
);
4130 * Display per-VNI EVPN routing table.
4132 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4133 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4138 "EVPN route information\n"
4139 "VXLAN Network Identifier\n"
4141 "Specify Route type\n"
4142 "MAC-IP (Type-2) route\n"
4143 "Multicast (Type-3) route\n"
4145 "Remote VTEP IP address\n"
4150 struct in_addr vtep_ip
;
4154 json_object
*json
= NULL
;
4156 bgp
= bgp_get_evpn();
4160 /* check if we need json output */
4161 uj
= use_json(argc
, argv
);
4163 json
= json_object_new_object();
4165 if (!argv_find(argv
, argc
, "evpn", &idx
))
4170 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4172 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4173 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4174 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4175 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4176 type
= BGP_EVPN_MAC_IP_ROUTE
;
4177 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4178 type
= BGP_EVPN_IMET_ROUTE
;
4181 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4182 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4183 vty_out(vty
, "%% Malformed VTEP IP address\n");
4190 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4193 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4194 json
, JSON_C_TO_STRING_PRETTY
));
4195 json_object_free(json
);
4202 * Display per-VNI EVPN routing table for specific MACIP.
4204 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4205 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4206 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4211 "EVPN route information\n"
4212 "VXLAN Network Identifier\n"
4215 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4217 "IP address (IPv4 or IPv6)\n"
4226 json_object
*json
= NULL
;
4228 bgp
= bgp_get_evpn();
4232 /* check if we need json output */
4233 uj
= use_json(argc
, argv
);
4235 json
= json_object_new_object();
4237 if (!argv_find(argv
, argc
, "evpn", &idx
))
4241 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4244 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4245 vty_out(vty
, "%% Malformed MAC address\n");
4250 memset(&ip
, 0, sizeof(ip
));
4251 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4253 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4254 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4255 vty_out(vty
, "%% Malformed IP address\n");
4260 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4263 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4264 json
, JSON_C_TO_STRING_PRETTY
));
4265 json_object_free(json
);
4272 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4274 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4275 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4276 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4281 "EVPN route information\n"
4282 "VXLAN Network Identifier\n"
4284 "Multicast (Type-3) route\n"
4285 "Originating Router IP address\n"
4291 struct in_addr orig_ip
;
4294 json_object
*json
= NULL
;
4296 bgp
= bgp_get_evpn();
4300 /* check if we need json output */
4301 uj
= use_json(argc
, argv
);
4303 json
= json_object_new_object();
4305 if (!argv_find(argv
, argc
, "evpn", &idx
))
4309 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4312 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4314 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4318 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4321 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4322 json
, JSON_C_TO_STRING_PRETTY
));
4323 json_object_free(json
);
4330 * Display per-VNI EVPN routing table - for all VNIs.
4332 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4333 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4334 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4339 "EVPN route information\n"
4340 "VXLAN Network Identifier\n"
4342 "Print Detailed Output\n"
4344 "Remote VTEP IP address\n"
4348 struct in_addr vtep_ip
;
4351 json_object
*json
= NULL
;
4352 /* Detail Adjust. Adjust indexes according to detail option */
4355 bgp
= bgp_get_evpn();
4359 /* check if we need json output */
4360 uj
= use_json(argc
, argv
);
4362 json
= json_object_new_object();
4364 if (!argv_find(argv
, argc
, "evpn", &idx
))
4367 if (argv_find(argv
, argc
, "detail", &da
))
4370 /* vtep-ip position depends on detail option */
4372 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4374 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4375 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4376 vty_out(vty
, "%% Malformed VTEP IP address\n");
4381 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4384 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4385 json
, JSON_C_TO_STRING_PRETTY
));
4386 json_object_free(json
);
4393 * Display EVPN import route-target hash table
4395 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4396 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4397 "show bgp l2vpn evpn vrf-import-rt [json]",
4402 "Show vrf import route target\n"
4406 struct bgp
*bgp_evpn
= NULL
;
4407 json_object
*json
= NULL
;
4409 bgp_evpn
= bgp_get_evpn();
4413 uj
= use_json(argc
, argv
);
4415 json
= json_object_new_object();
4417 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4420 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4421 json
, JSON_C_TO_STRING_PRETTY
));
4422 json_object_free(json
);
4429 * Display EVPN import route-target hash table
4431 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4432 show_bgp_l2vpn_evpn_import_rt_cmd
,
4433 "show bgp l2vpn evpn import-rt [json]",
4438 "Show import route target\n"
4443 json_object
*json
= NULL
;
4445 bgp
= bgp_get_evpn();
4449 uj
= use_json(argc
, argv
);
4451 json
= json_object_new_object();
4453 evpn_show_import_rts(vty
, bgp
, json
);
4456 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4457 json
, JSON_C_TO_STRING_PRETTY
));
4458 json_object_free(json
);
4464 DEFUN(test_adv_evpn_type4_route
,
4465 test_adv_evpn_type4_route_cmd
,
4467 "Advertise EVPN ES route\n"
4468 "Ethernet-segment\n"
4469 "Ethernet-Segment Identifier\n")
4474 struct ipaddr vtep_ip
;
4476 bgp
= bgp_get_evpn();
4478 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4482 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4483 vty_out(vty
, "%%Malformed ESI\n");
4487 vtep_ip
.ipa_type
= IPADDR_V4
;
4488 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4490 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4492 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4498 DEFUN(test_withdraw_evpn_type4_route
,
4499 test_withdraw_evpn_type4_route_cmd
,
4501 "Advertise EVPN ES route\n"
4502 "Ethernet-segment\n"
4503 "Ethernet-Segment Identifier\n")
4508 struct ipaddr vtep_ip
;
4510 bgp
= bgp_get_evpn();
4512 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4516 if (!bgp
->peer_self
) {
4517 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4521 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4522 vty_out(vty
, "%%Malformed ESI\n");
4526 vtep_ip
.ipa_type
= IPADDR_V4
;
4527 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4528 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4530 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4536 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4537 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4541 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4542 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4543 "Summary of BGP neighbor status\n" JSON_STR
)
4545 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4546 "show bgp evpn route [detail] [type <macip|multicast>]",
4547 SHOW_STR BGP_STR EVPN_HELP_STR
4548 "EVPN route information\n"
4549 "Display Detailed Information\n"
4550 "Specify Route type\n"
4551 "MAC-IP (Type-2) route\n"
4552 "Multicast (Type-3) route\n")
4555 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4556 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4557 SHOW_STR BGP_STR EVPN_HELP_STR
4558 "EVPN route information\n"
4559 "Route Distinguisher\n"
4560 "ASN:XX or A.B.C.D:XX\n"
4561 "Specify Route type\n"
4562 "MAC-IP (Type-2) route\n"
4563 "Multicast (Type-3) route\n")
4566 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4567 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4568 SHOW_STR BGP_STR EVPN_HELP_STR
4569 "EVPN route information\n"
4570 "Route Distinguisher\n"
4571 "ASN:XX or A.B.C.D:XX\n"
4573 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4575 "IP address (IPv4 or IPv6)\n")
4578 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4579 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4580 SHOW_STR BGP_STR EVPN_HELP_STR
4581 "EVPN route information\n"
4582 "VXLAN Network Identifier\n"
4584 "Specify Route type\n"
4585 "MAC-IP (Type-2) route\n"
4586 "Multicast (Type-3) route\n"
4588 "Remote VTEP IP address\n")
4590 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4591 show_bgp_evpn_route_vni_macip_cmd
,
4592 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4593 SHOW_STR BGP_STR EVPN_HELP_STR
4594 "EVPN route information\n"
4595 "VXLAN Network Identifier\n"
4598 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4600 "IP address (IPv4 or IPv6)\n")
4602 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4603 show_bgp_evpn_route_vni_multicast_cmd
,
4604 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4605 SHOW_STR BGP_STR EVPN_HELP_STR
4606 "EVPN route information\n"
4607 "VXLAN Network Identifier\n"
4609 "Multicast (Type-3) route\n"
4610 "Originating Router IP address\n")
4612 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4613 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4614 SHOW_STR BGP_STR EVPN_HELP_STR
4615 "EVPN route information\n"
4616 "VXLAN Network Identifier\n"
4618 "Print Detailed Output\n"
4620 "Remote VTEP IP address\n")
4622 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4623 "show bgp evpn import-rt",
4624 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4626 DEFUN_NOSH (bgp_evpn_vni
,
4628 "vni " CMD_VNI_RANGE
,
4629 "VXLAN Network Identifier\n"
4633 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4634 struct bgpevpn
*vpn
;
4639 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4641 /* Create VNI, or mark as configured. */
4642 vpn
= evpn_create_update_vni(bgp
, vni
);
4644 vty_out(vty
, "%% Failed to create VNI \n");
4648 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4652 DEFUN (no_bgp_evpn_vni
,
4653 no_bgp_evpn_vni_cmd
,
4654 "no vni " CMD_VNI_RANGE
,
4656 "VXLAN Network Identifier\n"
4660 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4661 struct bgpevpn
*vpn
;
4666 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4668 /* Check if we should disallow. */
4669 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4671 vty_out(vty
, "%% Specified VNI does not exist\n");
4674 if (!is_vni_configured(vpn
)) {
4675 vty_out(vty
, "%% Specified VNI is not configured\n");
4679 evpn_delete_vni(bgp
, vpn
);
4683 DEFUN_NOSH (exit_vni
,
4686 "Exit from VNI mode\n")
4688 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4689 vty
->node
= BGP_EVPN_NODE
;
4693 DEFUN (bgp_evpn_vrf_rd
,
4694 bgp_evpn_vrf_rd_cmd
,
4695 "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
[1]->arg
, &prd
);
4708 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4712 /* If same as existing value, there is nothing more to do. */
4713 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4716 /* Configure or update the RD. */
4717 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4721 DEFUN (no_bgp_evpn_vrf_rd
,
4722 no_bgp_evpn_vrf_rd_cmd
,
4723 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4725 "Route Distinguisher\n"
4726 "ASN:XX or A.B.C.D:XX\n")
4729 struct prefix_rd prd
;
4730 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4735 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4737 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4741 /* Check if we should disallow. */
4742 if (!is_vrf_rd_configured(bgp_vrf
)) {
4743 vty_out(vty
, "%% RD is not configured for this VRF\n");
4747 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4749 "%% RD specified does not match configuration for this VRF\n");
4753 evpn_unconfigure_vrf_rd(bgp_vrf
);
4757 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4758 no_bgp_evpn_vrf_rd_without_val_cmd
,
4761 "Route Distinguisher\n")
4763 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4768 /* Check if we should disallow. */
4769 if (!is_vrf_rd_configured(bgp_vrf
)) {
4770 vty_out(vty
, "%% RD is not configured for this VRF\n");
4774 evpn_unconfigure_vrf_rd(bgp_vrf
);
4778 DEFUN (bgp_evpn_vni_rd
,
4779 bgp_evpn_vni_rd_cmd
,
4780 "rd ASN:NN_OR_IP-ADDRESS:NN",
4781 "Route Distinguisher\n"
4782 "ASN:XX or A.B.C.D:XX\n")
4784 struct prefix_rd prd
;
4785 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4786 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4792 if (!EVPN_ENABLED(bgp
)) {
4794 "This command is only supported under EVPN VRF\n");
4798 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4800 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4804 /* If same as existing value, there is nothing more to do. */
4805 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4808 /* Configure or update the RD. */
4809 evpn_configure_rd(bgp
, vpn
, &prd
);
4813 DEFUN (no_bgp_evpn_vni_rd
,
4814 no_bgp_evpn_vni_rd_cmd
,
4815 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4817 "Route Distinguisher\n"
4818 "ASN:XX or A.B.C.D:XX\n")
4820 struct prefix_rd prd
;
4821 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4822 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4828 if (!EVPN_ENABLED(bgp
)) {
4830 "This command is only supported under EVPN VRF\n");
4834 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4836 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4840 /* Check if we should disallow. */
4841 if (!is_rd_configured(vpn
)) {
4842 vty_out(vty
, "%% RD is not configured for this VNI\n");
4846 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4848 "%% RD specified does not match configuration for this VNI\n");
4852 evpn_unconfigure_rd(bgp
, vpn
);
4856 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4857 no_bgp_evpn_vni_rd_without_val_cmd
,
4860 "Route Distinguisher\n")
4862 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4863 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4868 if (!EVPN_ENABLED(bgp
)) {
4870 "This command is only supported under EVPN VRF\n");
4874 /* Check if we should disallow. */
4875 if (!is_rd_configured(vpn
)) {
4876 vty_out(vty
, "%% RD is not configured for this VNI\n");
4880 evpn_unconfigure_rd(bgp
, vpn
);
4885 * Loop over all extended-communities in the route-target list rtl and
4886 * return 1 if we find ecomtarget
4888 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4889 struct ecommunity
*ecomtarget
)
4891 struct listnode
*node
, *nnode
;
4892 struct ecommunity
*ecom
;
4894 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4895 if (ecommunity_match(ecom
, ecomtarget
))
4902 /* display L3VNI related info for a VRF instance */
4903 DEFUN (show_bgp_vrf_l3vni_info
,
4904 show_bgp_vrf_l3vni_info_cmd
,
4905 "show bgp vrf VRFNAME vni [json]",
4913 char buf
[ETHER_ADDR_STRLEN
];
4914 char buf1
[INET6_ADDRSTRLEN
];
4916 const char *name
= NULL
;
4917 struct bgp
*bgp
= NULL
;
4918 struct listnode
*node
= NULL
;
4919 struct bgpevpn
*vpn
= NULL
;
4920 struct ecommunity
*ecom
= NULL
;
4921 json_object
*json
= NULL
;
4922 json_object
*json_vnis
= NULL
;
4923 json_object
*json_export_rts
= NULL
;
4924 json_object
*json_import_rts
= NULL
;
4925 bool uj
= use_json(argc
, argv
);
4928 json
= json_object_new_object();
4929 json_vnis
= json_object_new_array();
4930 json_export_rts
= json_object_new_array();
4931 json_import_rts
= json_object_new_array();
4934 name
= argv
[idx_vrf
]->arg
;
4935 bgp
= bgp_lookup_by_name(name
);
4938 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4940 json_object_string_add(json
, "warning",
4941 "BGP instance not found");
4942 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4943 json_object_free(json
);
4949 vty_out(vty
, "BGP VRF: %s\n", name
);
4950 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4951 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4952 vty_out(vty
, " Rmac: %s\n",
4953 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4954 vty_out(vty
, " VNI Filter: %s\n",
4955 CHECK_FLAG(bgp
->vrf_flags
,
4956 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4957 ? "prefix-routes-only"
4959 vty_out(vty
, " L2-VNI List:\n");
4961 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4962 vty_out(vty
, "%u ", vpn
->vni
);
4964 vty_out(vty
, " Export-RTs:\n");
4966 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4967 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4969 vty_out(vty
, " Import-RTs:\n");
4971 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4972 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4974 vty_out(vty
, " RD: %s\n",
4975 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4977 json_object_string_add(json
, "vrf", name
);
4978 json_object_string_add(json
, "local-ip",
4979 inet_ntoa(bgp
->originator_ip
));
4980 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4981 json_object_string_add(
4983 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4984 json_object_string_add(
4986 CHECK_FLAG(bgp
->vrf_flags
,
4987 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4988 ? "prefix-routes-only"
4990 /* list of l2vnis */
4991 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4992 json_object_array_add(json_vnis
,
4993 json_object_new_int(vpn
->vni
));
4994 json_object_object_add(json
, "l2vnis", json_vnis
);
4997 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4998 json_object_array_add(
5000 json_object_new_string(ecommunity_str(ecom
)));
5001 json_object_object_add(json
, "export-rts", json_export_rts
);
5004 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5005 json_object_array_add(
5007 json_object_new_string(ecommunity_str(ecom
)));
5008 json_object_object_add(json
, "import-rts", json_import_rts
);
5009 json_object_string_add(
5011 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5015 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5016 json
, JSON_C_TO_STRING_PRETTY
));
5017 json_object_free(json
);
5022 /* import/export rt for l3vni-vrf */
5023 DEFUN (bgp_evpn_vrf_rt
,
5024 bgp_evpn_vrf_rt_cmd
,
5025 "route-target <both|import|export> RT",
5027 "import and export\n"
5030 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5033 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5034 struct ecommunity
*ecomadd
= NULL
;
5039 if (!strcmp(argv
[1]->arg
, "import"))
5040 rt_type
= RT_TYPE_IMPORT
;
5041 else if (!strcmp(argv
[1]->arg
, "export"))
5042 rt_type
= RT_TYPE_EXPORT
;
5043 else if (!strcmp(argv
[1]->arg
, "both"))
5044 rt_type
= RT_TYPE_BOTH
;
5046 vty_out(vty
, "%% Invalid Route Target type\n");
5050 /* Add/update the import route-target */
5051 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5052 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5053 ECOMMUNITY_ROUTE_TARGET
, 0);
5055 vty_out(vty
, "%% Malformed Route Target list\n");
5058 ecommunity_str(ecomadd
);
5060 /* Do nothing if we already have this import route-target */
5061 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5062 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5065 /* Add/update the export route-target */
5066 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5067 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5068 ECOMMUNITY_ROUTE_TARGET
, 0);
5070 vty_out(vty
, "%% Malformed Route Target list\n");
5073 ecommunity_str(ecomadd
);
5075 /* Do nothing if we already have this export route-target */
5076 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5077 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5083 DEFUN (no_bgp_evpn_vrf_rt
,
5084 no_bgp_evpn_vrf_rt_cmd
,
5085 "no route-target <both|import|export> RT",
5088 "import and export\n"
5091 "ASN:XX or A.B.C.D:XX\n")
5093 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5094 int rt_type
, found_ecomdel
;
5095 struct ecommunity
*ecomdel
= NULL
;
5100 if (!strcmp(argv
[2]->arg
, "import"))
5101 rt_type
= RT_TYPE_IMPORT
;
5102 else if (!strcmp(argv
[2]->arg
, "export"))
5103 rt_type
= RT_TYPE_EXPORT
;
5104 else if (!strcmp(argv
[2]->arg
, "both"))
5105 rt_type
= RT_TYPE_BOTH
;
5107 vty_out(vty
, "%% Invalid Route Target type\n");
5111 if (rt_type
== RT_TYPE_IMPORT
) {
5112 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5114 "%% Import RT is not configured for this VRF\n");
5117 } else if (rt_type
== RT_TYPE_EXPORT
) {
5118 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5120 "%% Export RT is not configured for this VRF\n");
5123 } else if (rt_type
== RT_TYPE_BOTH
) {
5124 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5125 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5127 "%% Import/Export RT is not configured for this VRF\n");
5132 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5134 vty_out(vty
, "%% Malformed Route Target list\n");
5137 ecommunity_str(ecomdel
);
5139 if (rt_type
== RT_TYPE_IMPORT
) {
5140 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5143 "%% RT specified does not match configuration for this VRF\n");
5146 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5147 } else if (rt_type
== RT_TYPE_EXPORT
) {
5148 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5151 "%% RT specified does not match configuration for this VRF\n");
5154 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5155 } else if (rt_type
== RT_TYPE_BOTH
) {
5158 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5160 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5164 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5166 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5170 if (!found_ecomdel
) {
5172 "%% RT specified does not match configuration for this VRF\n");
5180 DEFUN (bgp_evpn_vni_rt
,
5181 bgp_evpn_vni_rt_cmd
,
5182 "route-target <both|import|export> RT",
5184 "import and export\n"
5187 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5189 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5190 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5192 struct ecommunity
*ecomadd
= NULL
;
5197 if (!EVPN_ENABLED(bgp
)) {
5199 "This command is only supported under EVPN VRF\n");
5203 if (!strcmp(argv
[1]->text
, "import"))
5204 rt_type
= RT_TYPE_IMPORT
;
5205 else if (!strcmp(argv
[1]->text
, "export"))
5206 rt_type
= RT_TYPE_EXPORT
;
5207 else if (!strcmp(argv
[1]->text
, "both"))
5208 rt_type
= RT_TYPE_BOTH
;
5210 vty_out(vty
, "%% Invalid Route Target type\n");
5214 /* Add/update the import route-target */
5215 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5216 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5217 ECOMMUNITY_ROUTE_TARGET
, 0);
5219 vty_out(vty
, "%% Malformed Route Target list\n");
5222 ecommunity_str(ecomadd
);
5224 /* Do nothing if we already have this import route-target */
5225 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5226 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5229 /* Add/update the export route-target */
5230 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5231 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5232 ECOMMUNITY_ROUTE_TARGET
, 0);
5234 vty_out(vty
, "%% Malformed Route Target list\n");
5237 ecommunity_str(ecomadd
);
5239 /* Do nothing if we already have this export route-target */
5240 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5241 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5247 DEFUN (no_bgp_evpn_vni_rt
,
5248 no_bgp_evpn_vni_rt_cmd
,
5249 "no route-target <both|import|export> RT",
5252 "import and export\n"
5255 "ASN:XX or A.B.C.D:XX\n")
5257 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5258 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5259 int rt_type
, found_ecomdel
;
5260 struct ecommunity
*ecomdel
= NULL
;
5265 if (!EVPN_ENABLED(bgp
)) {
5267 "This command is only supported under EVPN VRF\n");
5271 if (!strcmp(argv
[2]->text
, "import"))
5272 rt_type
= RT_TYPE_IMPORT
;
5273 else if (!strcmp(argv
[2]->text
, "export"))
5274 rt_type
= RT_TYPE_EXPORT
;
5275 else if (!strcmp(argv
[2]->text
, "both"))
5276 rt_type
= RT_TYPE_BOTH
;
5278 vty_out(vty
, "%% Invalid Route Target type\n");
5282 /* The user did "no route-target import", check to see if there are any
5283 * import route-targets configured. */
5284 if (rt_type
== RT_TYPE_IMPORT
) {
5285 if (!is_import_rt_configured(vpn
)) {
5287 "%% Import RT is not configured for this VNI\n");
5290 } else if (rt_type
== RT_TYPE_EXPORT
) {
5291 if (!is_export_rt_configured(vpn
)) {
5293 "%% Export RT is not configured for this VNI\n");
5296 } else if (rt_type
== RT_TYPE_BOTH
) {
5297 if (!is_import_rt_configured(vpn
)
5298 && !is_export_rt_configured(vpn
)) {
5300 "%% Import/Export RT is not configured for this VNI\n");
5305 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5307 vty_out(vty
, "%% Malformed Route Target list\n");
5310 ecommunity_str(ecomdel
);
5312 if (rt_type
== RT_TYPE_IMPORT
) {
5313 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5315 "%% RT specified does not match configuration for this VNI\n");
5318 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5319 } else if (rt_type
== RT_TYPE_EXPORT
) {
5320 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5322 "%% RT specified does not match configuration for this VNI\n");
5325 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5326 } else if (rt_type
== RT_TYPE_BOTH
) {
5329 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5330 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5334 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5335 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5339 if (!found_ecomdel
) {
5341 "%% RT specified does not match configuration for this VNI\n");
5349 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5350 no_bgp_evpn_vni_rt_without_val_cmd
,
5351 "no route-target <import|export>",
5357 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5358 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5364 if (!EVPN_ENABLED(bgp
)) {
5366 "This command is only supported under EVPN VRF\n");
5370 if (!strcmp(argv
[2]->text
, "import")) {
5371 rt_type
= RT_TYPE_IMPORT
;
5372 } else if (!strcmp(argv
[2]->text
, "export")) {
5373 rt_type
= RT_TYPE_EXPORT
;
5375 vty_out(vty
, "%% Invalid Route Target type\n");
5379 /* Check if we should disallow. */
5380 if (rt_type
== RT_TYPE_IMPORT
) {
5381 if (!is_import_rt_configured(vpn
)) {
5383 "%% Import RT is not configured for this VNI\n");
5387 if (!is_export_rt_configured(vpn
)) {
5389 "%% Export RT is not configured for this VNI\n");
5394 /* Unconfigure the RT. */
5395 if (rt_type
== RT_TYPE_IMPORT
)
5396 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5398 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5402 static int vni_cmp(const void **a
, const void **b
)
5404 const struct bgpevpn
*first
= *a
;
5405 const struct bgpevpn
*secnd
= *b
;
5407 return secnd
->vni
- first
->vni
;
5411 * Output EVPN configuration information.
5413 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5416 char buf1
[RD_ADDRSTRLEN
];
5419 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5420 struct listnode
*ln
;
5421 struct bgpevpn
*data
;
5423 list_sort(vnilist
, vni_cmp
);
5424 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5425 write_vni_config(vty
, data
);
5427 list_delete(&vnilist
);
5430 if (bgp
->advertise_all_vni
)
5431 vty_out(vty
, " advertise-all-vni\n");
5433 if (bgp
->advertise_autort_rfc8365
)
5434 vty_out(vty
, " autort rfc8365-compatible\n");
5436 if (bgp
->advertise_gw_macip
)
5437 vty_out(vty
, " advertise-default-gw\n");
5439 if (bgp
->evpn_info
->advertise_svi_macip
)
5440 vty_out(vty
, " advertise-svi-ip\n");
5442 if (!bgp
->evpn_info
->dup_addr_detect
)
5443 vty_out(vty
, " no dup-addr-detection\n");
5445 if (bgp
->evpn_info
->dad_max_moves
!=
5446 EVPN_DAD_DEFAULT_MAX_MOVES
||
5447 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5448 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5449 bgp
->evpn_info
->dad_max_moves
,
5450 bgp
->evpn_info
->dad_time
);
5452 if (bgp
->evpn_info
->dad_freeze
) {
5453 if (bgp
->evpn_info
->dad_freeze_time
)
5455 " dup-addr-detection freeze %u\n",
5456 bgp
->evpn_info
->dad_freeze_time
);
5459 " dup-addr-detection freeze permanent\n");
5462 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5463 vty_out(vty
, " flooding disable\n");
5465 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5466 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5467 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5468 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5469 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5471 vty_out(vty
, " advertise ipv4 unicast\n");
5474 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5475 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5476 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5477 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5478 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5480 vty_out(vty
, " advertise ipv6 unicast\n");
5483 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5484 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5485 vty_out(vty
, " default-originate ipv4\n");
5487 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5488 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5489 vty_out(vty
, " default-originate ipv6\n");
5491 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5492 vty_out(vty
, " rd %s\n",
5493 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5495 /* import route-target */
5496 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5498 struct listnode
*node
, *nnode
;
5499 struct ecommunity
*ecom
;
5501 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5503 ecom_str
= ecommunity_ecom2str(
5504 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5505 vty_out(vty
, " route-target import %s\n", ecom_str
);
5506 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5510 /* export route-target */
5511 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5513 struct listnode
*node
, *nnode
;
5514 struct ecommunity
*ecom
;
5516 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5518 ecom_str
= ecommunity_ecom2str(
5519 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5520 vty_out(vty
, " route-target export %s\n", ecom_str
);
5521 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5526 void bgp_ethernetvpn_init(void)
5528 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5529 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5530 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5531 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5532 install_element(VIEW_NODE
,
5533 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5534 install_element(VIEW_NODE
,
5535 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5538 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5541 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5542 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5543 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5544 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5545 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5546 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5547 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5548 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5549 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5550 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5551 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5552 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5553 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5554 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5555 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5556 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5557 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5558 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5559 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5560 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5563 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5564 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5566 /* "show bgp l2vpn evpn" commands. */
5567 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5568 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5569 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5570 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5571 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5572 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5573 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5574 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5575 install_element(VIEW_NODE
,
5576 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5577 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5578 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5579 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5580 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5582 /* "show bgp evpn" commands. */
5583 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5584 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5585 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5586 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5587 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5588 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5589 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5590 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5591 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5592 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5593 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5594 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5596 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5597 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5598 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5599 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5600 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5601 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5602 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5603 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5604 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5605 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5606 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5607 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5608 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5609 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5610 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5611 install_element(BGP_EVPN_VNI_NODE
,
5612 &bgp_evpn_advertise_default_gw_vni_cmd
);
5613 install_element(BGP_EVPN_VNI_NODE
,
5614 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5615 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5616 install_element(BGP_EVPN_VNI_NODE
,
5617 &no_bgp_evpn_advertise_vni_subnet_cmd
);