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
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
64 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
65 enum overlay_index_type
*oly
)
67 *oly
= OVERLAY_INDEX_TYPE_NONE
;
68 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
69 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
73 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
77 uint8_t type
, sub_type
;
78 struct ecommunity_as eas
;
79 struct ecommunity_ip eip
;
80 struct listnode
*node
, *nnode
;
81 struct bgp
*tmp_bgp_vrf
= NULL
;
82 json_object
*json_rt
= NULL
;
83 json_object
*json_vrfs
= NULL
;
84 char rt_buf
[RT_ADDRSTRLEN
];
87 json_rt
= json_object_new_object();
88 json_vrfs
= json_object_new_array();
91 pnt
= (uint8_t *)&irt
->rt
.val
;
94 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
97 memset(&eas
, 0, sizeof(eas
));
99 case ECOMMUNITY_ENCODE_AS
:
100 eas
.as
= (*pnt
++ << 8);
102 ptr_get_be32(pnt
, &eas
.val
);
104 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
107 json_object_string_add(json_rt
, "rt", rt_buf
);
109 vty_out(vty
, "Route-target: %s", rt_buf
);
113 case ECOMMUNITY_ENCODE_IP
:
114 memcpy(&eip
.ip
, pnt
, 4);
116 eip
.val
= (*pnt
++ << 8);
119 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
122 json_object_string_add(json_rt
, "rt", rt_buf
);
124 vty_out(vty
, "Route-target: %s", rt_buf
);
128 case ECOMMUNITY_ENCODE_AS4
:
129 pnt
= ptr_get_be32(pnt
, &eas
.val
);
130 eas
.val
= (*pnt
++ << 8);
133 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
136 json_object_string_add(json_rt
, "rt", rt_buf
);
138 vty_out(vty
, "Route-target: %s", rt_buf
);
148 "\nList of VRFs importing routes with this route-target:\n");
151 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
153 json_object_array_add(
155 json_object_new_string(
156 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
158 vty_out(vty
, " %s\n",
159 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
163 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
164 json_object_object_add(json
, rt_buf
, json_rt
);
168 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
170 json_object
*json
= NULL
;
171 struct vty
*vty
= NULL
;
172 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
174 vty
= (struct vty
*)args
[0];
175 json
= (struct json_object
*)args
[1];
177 display_vrf_import_rt(vty
, irt
, json
);
180 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
184 uint8_t type
, sub_type
;
185 struct ecommunity_as eas
;
186 struct ecommunity_ip eip
;
187 struct listnode
*node
, *nnode
;
188 struct bgpevpn
*tmp_vpn
;
189 json_object
*json_rt
= NULL
;
190 json_object
*json_vnis
= NULL
;
191 char rt_buf
[RT_ADDRSTRLEN
];
194 json_rt
= json_object_new_object();
195 json_vnis
= json_object_new_array();
198 /* TODO: This needs to go into a function */
200 pnt
= (uint8_t *)&irt
->rt
.val
;
203 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
206 memset(&eas
, 0, sizeof(eas
));
208 case ECOMMUNITY_ENCODE_AS
:
209 eas
.as
= (*pnt
++ << 8);
211 ptr_get_be32(pnt
, &eas
.val
);
213 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
216 json_object_string_add(json_rt
, "rt", rt_buf
);
218 vty_out(vty
, "Route-target: %s", rt_buf
);
222 case ECOMMUNITY_ENCODE_IP
:
223 memcpy(&eip
.ip
, pnt
, 4);
225 eip
.val
= (*pnt
++ << 8);
228 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
231 json_object_string_add(json_rt
, "rt", rt_buf
);
233 vty_out(vty
, "Route-target: %s", rt_buf
);
237 case ECOMMUNITY_ENCODE_AS4
:
238 pnt
= ptr_get_be32(pnt
, &eas
.val
);
239 eas
.val
= (*pnt
++ << 8);
242 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
245 json_object_string_add(json_rt
, "rt", rt_buf
);
247 vty_out(vty
, "Route-target: %s", rt_buf
);
257 "\nList of VNIs importing routes with this route-target:\n");
260 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
262 json_object_array_add(
263 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
265 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
269 json_object_object_add(json_rt
, "vnis", json_vnis
);
270 json_object_object_add(json
, rt_buf
, json_rt
);
274 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
276 json_object
*json
= NULL
;
277 struct vty
*vty
= NULL
;
278 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
283 display_import_rt(vty
, irt
, json
);
288 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
289 struct bgp_dest
*rd_dest
,
290 json_object
*json
, char *rd_str
,
297 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
301 /* Decode RD type. */
302 type
= decode_rd_type(pnt
);
305 vty_out(vty
, "Route Distinguisher: ");
309 decode_rd_as(pnt
+ 2, &rd_as
);
310 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
312 json_object_string_add(json
, "rd", rd_str
);
314 vty_out(vty
, "%s\n", rd_str
);
318 decode_rd_as4(pnt
+ 2, &rd_as
);
319 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
321 json_object_string_add(json
, "rd", rd_str
);
323 vty_out(vty
, "%s\n", rd_str
);
327 decode_rd_ip(pnt
+ 2, &rd_ip
);
328 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
330 json_object_string_add(json
, "rd", rd_str
);
332 vty_out(vty
, "%s\n", rd_str
);
337 snprintf(rd_str
, len
, "Unknown");
338 json_object_string_add(json
, "rd", rd_str
);
340 snprintf(rd_str
, len
, "Unknown RD type");
341 vty_out(vty
, "%s\n", rd_str
);
347 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
348 uint64_t tbl_ver
, json_object
*json
)
351 " Network Next Hop Metric LocPrf Weight Path\n";
357 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
358 tbl_ver
, &bgp
->router_id
);
360 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
361 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
363 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
365 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
366 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
367 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
368 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
369 vty_out(vty
, "%s", ri_header
);
372 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
376 struct listnode
*node
, *nnode
;
377 struct vrf_route_target
*l3rt
;
378 json_object
*json_import_rtl
= NULL
;
379 json_object
*json_export_rtl
= NULL
;
380 char buf2
[ETHER_ADDR_STRLEN
];
382 json_import_rtl
= json_export_rtl
= 0;
385 json_import_rtl
= json_object_new_array();
386 json_export_rtl
= json_object_new_array();
387 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
388 json_object_string_add(json
, "type", "L3");
389 json_object_string_add(json
, "inKernel", "True");
390 json_object_string_addf(json
, "rd",
391 BGP_RD_AS_FORMAT(bgp_vrf
->asnotation
),
393 json_object_string_addf(json
, "originatorIp", "%pI4",
394 &bgp_vrf
->originator_ip
);
395 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
396 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
397 json_object_string_add(json
, "advertisePip",
398 bgp_vrf
->evpn_info
->advertise_pip
?
399 "Enabled" : "Disabled");
400 json_object_string_addf(json
, "sysIP", "%pI4",
401 &bgp_vrf
->evpn_info
->pip_ip
);
402 json_object_string_add(json
, "sysMac",
403 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
404 buf2
, sizeof(buf2
)));
405 json_object_string_add(json
, "rmac",
406 prefix_mac2str(&bgp_vrf
->rmac
,
407 buf2
, sizeof(buf2
)));
409 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
410 vty_out(vty
, " (known to the kernel)");
413 vty_out(vty
, " Type: %s\n", "L3");
414 vty_out(vty
, " Tenant VRF: %s\n",
415 vrf_id_to_name(bgp_vrf
->vrf_id
));
416 vty_out(vty
, " RD: ");
417 vty_out(vty
, BGP_RD_AS_FORMAT(bgp_vrf
->asnotation
),
420 vty_out(vty
, " Originator IP: %pI4\n",
421 &bgp_vrf
->originator_ip
);
422 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
423 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
424 vty_out(vty
, " Advertise-pip: %s\n",
425 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
426 vty_out(vty
, " System-IP: %pI4\n",
427 &bgp_vrf
->evpn_info
->pip_ip
);
428 vty_out(vty
, " System-MAC: %s\n",
429 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
430 buf2
, sizeof(buf2
)));
431 vty_out(vty
, " Router-MAC: %s\n",
432 prefix_mac2str(&bgp_vrf
->rmac
,
433 buf2
, sizeof(buf2
)));
437 vty_out(vty
, " Import Route Target:\n");
439 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
440 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
441 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
444 json_object_array_add(json_import_rtl
,
445 json_object_new_string(ecom_str
));
447 vty_out(vty
, " %s\n", ecom_str
);
449 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
453 json_object_object_add(json
, "importRts", json_import_rtl
);
455 vty_out(vty
, " Export Route Target:\n");
457 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
458 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
459 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
462 json_object_array_add(json_export_rtl
,
463 json_object_new_string(ecom_str
));
465 vty_out(vty
, " %s\n", ecom_str
);
467 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
471 json_object_object_add(json
, "exportRts", json_export_rtl
);
474 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
477 struct listnode
*node
, *nnode
;
478 struct ecommunity
*ecom
;
479 json_object
*json_import_rtl
= NULL
;
480 json_object
*json_export_rtl
= NULL
;
481 struct bgp
*bgp_evpn
;
482 enum asnotation_mode asnotation
;
484 bgp_evpn
= bgp_get_evpn();
485 asnotation
= bgp_get_asnotation(bgp_evpn
);
488 json_import_rtl
= json_object_new_array();
489 json_export_rtl
= json_object_new_array();
490 json_object_int_add(json
, "vni", vpn
->vni
);
491 json_object_string_add(json
, "type", "L2");
492 json_object_string_add(json
, "inKernel",
493 is_vni_live(vpn
) ? "True" : "False");
494 json_object_string_addf(
495 json
, "rd", BGP_RD_AS_FORMAT(asnotation
), &vpn
->prd
);
496 json_object_string_addf(json
, "originatorIp", "%pI4",
497 &vpn
->originator_ip
);
498 json_object_string_addf(json
, "mcastGroup", "%pI4",
500 /* per vni knob is enabled -- Enabled
501 * Global knob is enabled -- Active
502 * default -- Disabled
504 if (!vpn
->advertise_gw_macip
&&
505 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
506 json_object_string_add(json
, "advertiseGatewayMacip",
508 else if (vpn
->advertise_gw_macip
)
509 json_object_string_add(json
, "advertiseGatewayMacip",
512 json_object_string_add(json
, "advertiseGatewayMacip",
514 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
515 bgp_evpn
->evpn_info
->advertise_svi_macip
)
516 json_object_string_add(json
, "advertiseSviMacIp",
518 else if (vpn
->advertise_svi_macip
)
519 json_object_string_add(json
, "advertiseSviMacIp",
522 json_object_string_add(json
, "advertiseSviMacIp",
524 json_object_string_add(
525 json
, "sviInterface",
526 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
528 vty_out(vty
, "VNI: %u", vpn
->vni
);
529 if (is_vni_live(vpn
))
530 vty_out(vty
, " (known to the kernel)");
533 vty_out(vty
, " Type: %s\n", "L2");
534 vty_out(vty
, " Tenant-Vrf: %s\n",
535 vrf_id_to_name(vpn
->tenant_vrf_id
));
536 vty_out(vty
, " RD: ");
537 vty_out(vty
, BGP_RD_AS_FORMAT(asnotation
), &vpn
->prd
);
539 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
540 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
541 if (!vpn
->advertise_gw_macip
&&
542 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
543 vty_out(vty
, " Advertise-gw-macip : %s\n",
545 else if (vpn
->advertise_gw_macip
)
546 vty_out(vty
, " Advertise-gw-macip : %s\n",
549 vty_out(vty
, " Advertise-gw-macip : %s\n",
551 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
552 bgp_evpn
->evpn_info
->advertise_svi_macip
)
553 vty_out(vty
, " Advertise-svi-macip : %s\n",
555 else if (vpn
->advertise_svi_macip
)
556 vty_out(vty
, " Advertise-svi-macip : %s\n",
559 vty_out(vty
, " Advertise-svi-macip : %s\n",
561 vty_out(vty
, " SVI interface : %s\n",
562 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
566 vty_out(vty
, " Import Route Target:\n");
568 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
569 ecom_str
= ecommunity_ecom2str(ecom
,
570 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
573 json_object_array_add(json_import_rtl
,
574 json_object_new_string(ecom_str
));
576 vty_out(vty
, " %s\n", ecom_str
);
578 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
582 json_object_object_add(json
, "importRts", json_import_rtl
);
584 vty_out(vty
, " Export Route Target:\n");
586 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
587 ecom_str
= ecommunity_ecom2str(ecom
,
588 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
591 json_object_array_add(json_export_rtl
,
592 json_object_new_string(ecom_str
));
594 vty_out(vty
, " %s\n", ecom_str
);
596 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
600 json_object_object_add(json
, "exportRts", json_export_rtl
);
603 static void show_esi_routes(struct bgp
*bgp
,
604 struct bgp_evpn_es
*es
,
609 struct bgp_dest
*dest
;
610 struct bgp_path_info
*pi
;
611 uint32_t prefix_cnt
, path_cnt
;
614 prefix_cnt
= path_cnt
= 0;
616 tbl_ver
= es
->route_table
->version
;
617 for (dest
= bgp_table_top(es
->route_table
); dest
;
618 dest
= bgp_route_next(dest
)) {
619 int add_prefix_to_json
= 0;
620 json_object
*json_paths
= NULL
;
621 json_object
*json_prefix
= NULL
;
622 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
625 json_prefix
= json_object_new_object();
627 pi
= bgp_dest_get_bgp_path_info(dest
);
629 /* Overall header/legend displayed once. */
631 bgp_evpn_show_route_header(vty
, bgp
,
640 json_paths
= json_object_new_array();
642 /* For EVPN, the prefix is displayed for each path (to fit in
643 * with code that already exists).
645 for (; pi
; pi
= pi
->next
) {
646 json_object
*json_path
= NULL
;
649 json_path
= json_object_new_array();
651 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
655 json_object_array_add(json_paths
, json_path
);
658 add_prefix_to_json
= 1;
662 if (add_prefix_to_json
) {
663 json_object_string_addf(json_prefix
, "prefix",
665 json_object_int_add(json_prefix
, "prefixLen",
667 json_object_object_add(json_prefix
, "paths",
669 json_object_object_addf(json
, json_prefix
,
672 json_object_free(json_paths
);
673 json_object_free(json_prefix
);
681 json_object_int_add(json
, "numPrefix", prefix_cnt
);
682 json_object_int_add(json
, "numPaths", path_cnt
);
685 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
687 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
688 prefix_cnt
, path_cnt
);
692 /* Display all MAC-IP VNI routes linked to an ES */
693 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
694 json_object
*json
, int detail
,
698 struct bgp_path_info
*pi
;
699 int header
= detail
? 0 : 1;
701 struct listnode
*node
;
702 struct bgp_evpn_es
*es
;
703 struct bgp_path_es_info
*es_info
;
704 struct bgp
*bgp
= bgp_get_evpn();
705 json_object
*json_paths
= NULL
;
713 json_paths
= json_object_new_array();
715 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
716 struct list
*es_list
;
718 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
722 es_list
= es
->macip_global_path_list
;
724 es_list
= es
->macip_evi_path_list
;
726 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
727 json_object
*json_path
= NULL
;
732 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
735 /* Overall header/legend displayed once. */
737 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
744 json_path
= json_object_new_array();
747 route_vty_out_detail(
748 vty
, bgp
, rn
, bgp_dest_get_prefix(rn
),
749 pi
, AFI_L2VPN
, SAFI_EVPN
,
750 RPKI_NOT_BEING_USED
, json_path
);
752 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
756 json_object_array_add(json_paths
, json_path
);
761 json_object_object_add(json
, "paths", json_paths
);
762 json_object_int_add(json
, "numPaths", path_cnt
);
765 vty_out(vty
, "There are no MAC-IP ES paths");
767 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
772 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
773 json_object
*json
, int detail
)
775 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
778 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
779 json_object
*json
, int detail
)
781 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
784 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
,
785 struct vty
*vty
, int type
, bool mac_table
,
786 struct in_addr vtep_ip
, json_object
*json
,
789 struct bgp_dest
*dest
;
790 struct bgp_path_info
*pi
;
791 struct bgp_table
*table
;
792 int header
= detail
? 0 : 1;
794 uint32_t prefix_cnt
, path_cnt
;
796 prefix_cnt
= path_cnt
= 0;
799 table
= vpn
->mac_table
;
801 table
= vpn
->ip_table
;
803 tbl_ver
= table
->version
;
804 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
805 const struct prefix_evpn
*evp
=
806 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
807 int add_prefix_to_json
= 0;
808 json_object
*json_paths
= NULL
;
809 json_object
*json_prefix
= NULL
;
810 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
812 if (type
&& evp
->prefix
.route_type
!= type
)
816 json_prefix
= json_object_new_object();
818 pi
= bgp_dest_get_bgp_path_info(dest
);
820 /* Overall header/legend displayed once. */
822 bgp_evpn_show_route_header(vty
, bgp
,
831 json_paths
= json_object_new_array();
833 /* For EVPN, the prefix is displayed for each path (to fit in
834 * with code that already exists).
836 for (; pi
; pi
= pi
->next
) {
838 json_object
*json_path
= NULL
;
840 if (vtep_ip
.s_addr
!= INADDR_ANY
841 && !IPV4_ADDR_SAME(&(vtep_ip
),
842 &(pi
->attr
->nexthop
)))
845 if (evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
847 * VNI IP/MAC table prefixes don't have MAC/IP
848 * respectively so make sure it's set from path
851 if (is_evpn_prefix_ipaddr_none(evp
)) {
852 /* VNI MAC -> Global */
853 evpn_type2_prefix_global_copy(
854 (struct prefix_evpn
*)&tmp_p
,
856 evpn_type2_path_info_get_ip(
859 /* VNI IP -> Global */
860 evpn_type2_prefix_global_copy(
861 (struct prefix_evpn
*)&tmp_p
,
863 evpn_type2_path_info_get_mac(
868 memcpy(&tmp_p
, p
, sizeof(tmp_p
));
872 json_path
= json_object_new_array();
875 route_vty_out_detail(vty
, bgp
, dest
, &tmp_p
, pi
,
876 AFI_L2VPN
, SAFI_EVPN
,
881 route_vty_out(vty
, &tmp_p
, pi
, 0, SAFI_EVPN
,
885 json_object_array_add(json_paths
, json_path
);
888 add_prefix_to_json
= 1;
892 if (add_prefix_to_json
) {
893 json_object_string_addf(json_prefix
, "prefix",
895 json_object_int_add(json_prefix
, "prefixLen",
897 json_object_object_add(json_prefix
, "paths",
899 json_object_object_addf(json
, json_prefix
,
902 json_object_free(json_paths
);
903 json_object_free(json_prefix
);
911 json_object_int_add(json
, "numPrefix", prefix_cnt
);
912 json_object_int_add(json
, "numPaths", path_cnt
);
915 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
916 type
? "(of requested type) " : "");
918 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
919 prefix_cnt
, path_cnt
,
920 type
? " (of requested type)" : "");
925 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
927 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
928 struct vni_walk_ctx
*wctx
= arg
;
929 struct vty
*vty
= wctx
->vty
;
930 json_object
*json
= wctx
->json
;
931 json_object
*json_vni
= NULL
;
932 char vni_str
[VNI_STR_LEN
];
934 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
936 json_vni
= json_object_new_object();
937 json_object_int_add(json_vni
, "vni", vpn
->vni
);
939 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
942 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, wctx
->type
, wctx
->mac_table
,
943 wctx
->vtep_ip
, json_vni
, wctx
->detail
);
946 json_object_object_add(json
, vni_str
, json_vni
);
949 static void show_vni_routes_all_hash(struct hash_bucket
*bucket
, void *arg
)
951 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
952 struct vni_walk_ctx
*wctx
= arg
;
953 struct vty
*vty
= wctx
->vty
;
954 json_object
*json
= wctx
->json
;
955 json_object
*json_vni
= NULL
;
956 json_object
*json_vni_mac
= NULL
;
957 char vni_str
[VNI_STR_LEN
];
959 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
961 json_vni
= json_object_new_object();
962 json_object_int_add(json_vni
, "vni", vpn
->vni
);
964 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
967 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, false, wctx
->vtep_ip
,
968 json_vni
, wctx
->detail
);
971 json_object_object_add(json
, vni_str
, json_vni
);
974 json_vni_mac
= json_object_new_object();
976 vty_out(vty
, "\nVNI: %u MAC Table\n\n", vpn
->vni
);
978 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, true, wctx
->vtep_ip
,
979 json_vni_mac
, wctx
->detail
);
982 json_object_object_add(json_vni
, "macTable", json_vni_mac
);
985 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
988 json_object
*json_vni
= NULL
;
989 json_object
*json_import_rtl
= NULL
;
990 json_object
*json_export_rtl
= NULL
;
992 char buf2
[INET6_ADDRSTRLEN
];
995 struct listnode
*node
, *nnode
;
996 struct vrf_route_target
*l3rt
;
1002 json_vni
= json_object_new_object();
1003 json_import_rtl
= json_object_new_array();
1004 json_export_rtl
= json_object_new_array();
1007 /* if an l3vni is present in bgp it is live */
1009 snprintf(buf1
, sizeof(buf1
), "*");
1012 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
1013 json_object_string_add(json_vni
, "type", "L3");
1014 json_object_string_add(json_vni
, "inKernel", "True");
1015 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1016 &bgp
->originator_ip
);
1017 json_object_string_addf(json_vni
, "rd",
1018 BGP_RD_AS_FORMAT(bgp
->asnotation
),
1020 json_object_string_add(json_vni
, "advertiseGatewayMacip",
1022 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
1023 json_object_string_add(
1024 json_vni
, "advertisePip",
1025 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
1026 json_object_string_addf(json_vni
, "sysIP", "%pI4",
1027 &bgp
->evpn_info
->pip_ip
);
1028 json_object_string_add(json_vni
, "sysMAC",
1029 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
1030 buf2
, sizeof(buf2
)));
1031 json_object_string_add(
1033 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
1035 vty_out(vty
, "%-1s %-10u %-4s ", buf1
, bgp
->l3vni
, "L3");
1036 vty_out(vty
, BGP_RD_AS_FORMAT_SPACE(bgp
->asnotation
),
1040 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
1041 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1042 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1045 json_object_array_add(json_import_rtl
,
1046 json_object_new_string(ecom_str
));
1048 if (listcount(bgp
->vrf_import_rtl
) > 1)
1049 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1052 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1054 vty_out(vty
, " %-25s", rt_buf
);
1057 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1059 /* If there are multiple import RTs we break here and show only
1066 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1068 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
1069 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1070 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1073 json_object_array_add(json_export_rtl
,
1074 json_object_new_string(ecom_str
));
1076 if (listcount(bgp
->vrf_export_rtl
) > 1)
1077 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1080 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1082 vty_out(vty
, " %-25s", rt_buf
);
1085 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1087 /* If there are multiple export RTs we break here and show only
1090 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1096 char vni_str
[VNI_STR_LEN
];
1098 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1099 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1100 json_object_object_add(json
, vni_str
, json_vni
);
1106 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1110 json_object
*json_vni
= NULL
;
1111 json_object
*json_import_rtl
= NULL
;
1112 json_object
*json_export_rtl
= NULL
;
1113 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1117 struct listnode
*node
, *nnode
;
1118 struct ecommunity
*ecom
;
1119 struct bgp
*bgp_evpn
;
1120 enum asnotation_mode asnotation
;
1125 bgp_evpn
= bgp_get_evpn();
1126 asnotation
= bgp_get_asnotation(bgp_evpn
);
1129 json_vni
= json_object_new_object();
1130 json_import_rtl
= json_object_new_array();
1131 json_export_rtl
= json_object_new_array();
1135 if (is_vni_live(vpn
))
1136 snprintf(buf1
, sizeof(buf1
), "*");
1139 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1140 json_object_string_add(json_vni
, "type", "L2");
1141 json_object_string_add(json_vni
, "inKernel",
1142 is_vni_live(vpn
) ? "True" : "False");
1143 json_object_string_addf(json_vni
, "rd",
1144 BGP_RD_AS_FORMAT(asnotation
),
1146 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1147 &vpn
->originator_ip
);
1148 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1150 /* per vni knob is enabled -- Enabled
1151 * Global knob is enabled -- Active
1152 * default -- Disabled
1154 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1155 && bgp_evpn
->advertise_gw_macip
)
1156 json_object_string_add(
1157 json_vni
, "advertiseGatewayMacip", "Active");
1158 else if (vpn
->advertise_gw_macip
)
1159 json_object_string_add(
1160 json_vni
, "advertiseGatewayMacip", "Enabled");
1162 json_object_string_add(
1163 json_vni
, "advertiseGatewayMacip", "Disabled");
1164 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1165 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1166 json_object_string_add(json_vni
, "advertiseSviMacIp",
1168 else if (vpn
->advertise_svi_macip
)
1169 json_object_string_add(json_vni
, "advertiseSviMacIp",
1172 json_object_string_add(json_vni
, "advertiseSviMacIp",
1175 vty_out(vty
, "%-1s %-10u %-4s ", buf1
, vpn
->vni
, "L2");
1176 vty_out(vty
, BGP_RD_AS_FORMAT_SPACE(asnotation
), &vpn
->prd
);
1179 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1180 ecom_str
= ecommunity_ecom2str(ecom
,
1181 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1184 json_object_array_add(json_import_rtl
,
1185 json_object_new_string(ecom_str
));
1187 if (listcount(vpn
->import_rtl
) > 1)
1188 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1191 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1193 vty_out(vty
, " %-25s", rt_buf
);
1196 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1198 /* If there are multiple import RTs we break here and show only
1205 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1207 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1208 ecom_str
= ecommunity_ecom2str(ecom
,
1209 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1212 json_object_array_add(json_export_rtl
,
1213 json_object_new_string(ecom_str
));
1215 if (listcount(vpn
->export_rtl
) > 1)
1216 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1219 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1221 vty_out(vty
, " %-25s", rt_buf
);
1224 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1226 /* If there are multiple export RTs we break here and show only
1229 vty_out(vty
, "%-37s",
1230 vrf_id_to_name(vpn
->tenant_vrf_id
));
1236 char vni_str
[VNI_STR_LEN
];
1238 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1239 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1240 json_object_object_add(json
, vni_str
, json_vni
);
1246 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1247 enum bgp_show_type type
, void *output_arg
,
1248 int option
, bool use_json
)
1250 afi_t afi
= AFI_L2VPN
;
1252 struct bgp_table
*table
;
1253 struct bgp_dest
*dest
;
1254 struct bgp_dest
*rm
;
1255 struct bgp_path_info
*pi
;
1258 char rd_str
[RD_ADDRSTRLEN
];
1261 unsigned long output_count
= 0;
1262 unsigned long total_count
= 0;
1263 json_object
*json
= NULL
;
1264 json_object
*json_array
= NULL
;
1265 json_object
*json_prefix_info
= NULL
;
1267 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1269 bgp
= bgp_get_evpn();
1272 vty_out(vty
, "No BGP process is configured\n");
1274 vty_out(vty
, "{}\n");
1279 json
= json_object_new_object();
1281 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1282 dest
= bgp_route_next(dest
)) {
1284 json_object
*json_nroute
= NULL
;
1285 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1287 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1290 table
= bgp_dest_get_bgp_table_info(dest
);
1295 tbl_ver
= table
->version
;
1297 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1298 pi
= bgp_dest_get_bgp_path_info(rm
);
1303 for (; pi
; pi
= pi
->next
) {
1304 struct community
*picomm
= NULL
;
1306 picomm
= bgp_attr_get_community(pi
->attr
);
1309 if (type
== bgp_show_type_neighbor
) {
1310 struct peer
*peer
= output_arg
;
1312 if (peer_cmp(peer
, pi
->peer
) != 0)
1315 if (type
== bgp_show_type_lcommunity_exact
) {
1316 struct lcommunity
*lcom
= output_arg
;
1318 if (!bgp_attr_get_lcommunity(
1321 bgp_attr_get_lcommunity(
1326 if (type
== bgp_show_type_lcommunity
) {
1327 struct lcommunity
*lcom
= output_arg
;
1329 if (!bgp_attr_get_lcommunity(
1332 bgp_attr_get_lcommunity(
1337 if (type
== bgp_show_type_community
) {
1338 struct community
*com
= output_arg
;
1341 !community_match(picomm
, com
))
1344 if (type
== bgp_show_type_community_exact
) {
1345 struct community
*com
= output_arg
;
1348 !community_cmp(picomm
, com
))
1353 json_object_int_add(
1354 json
, "bgpTableVersion",
1356 json_object_string_addf(
1361 json_object_int_add(
1364 bgp
->default_local_pref
);
1365 asn_asn2json(json
, "localAS",
1369 if (option
== SHOW_DISPLAY_TAGS
)
1374 == SHOW_DISPLAY_OVERLAY
)
1378 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1386 json_object_new_object();
1387 bgp_evpn_show_route_rd_header(
1388 vty
, dest
, json_nroute
, rd_str
,
1392 if (use_json
&& !json_array
)
1393 json_array
= json_object_new_array();
1395 if (option
== SHOW_DISPLAY_TAGS
)
1397 vty
, bgp_dest_get_prefix(rm
),
1398 pi
, no_display
, SAFI_EVPN
,
1400 else if (option
== SHOW_DISPLAY_OVERLAY
)
1401 route_vty_out_overlay(
1402 vty
, bgp_dest_get_prefix(rm
),
1403 pi
, no_display
, json_array
);
1406 bgp_dest_get_prefix(rm
),
1407 pi
, no_display
, SAFI_EVPN
,
1415 if (use_json
&& json_array
) {
1416 const struct prefix
*p
=
1417 bgp_dest_get_prefix(rm
);
1419 json_prefix_info
= json_object_new_object();
1421 json_object_string_addf(json_prefix_info
,
1422 "prefix", "%pFX", p
);
1424 json_object_int_add(json_prefix_info
,
1425 "prefixLen", p
->prefixlen
);
1427 json_object_object_add(json_prefix_info
,
1428 "paths", json_array
);
1429 json_object_object_addf(json_nroute
,
1436 if (use_json
&& json_nroute
)
1437 json_object_object_add(json
, rd_str
, json_nroute
);
1441 json_object_int_add(json
, "numPrefix", output_count
);
1442 json_object_int_add(json
, "totalPrefix", total_count
);
1443 vty_json(vty
, json
);
1445 if (output_count
== 0)
1446 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1450 "\nDisplayed %ld out of %ld total prefixes\n",
1451 output_count
, total_count
);
1456 DEFUN(show_ip_bgp_l2vpn_evpn
,
1457 show_ip_bgp_l2vpn_evpn_cmd
,
1458 "show [ip] bgp l2vpn evpn [json]",
1459 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1461 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1462 SHOW_DISPLAY_STANDARD
,
1463 use_json(argc
, argv
));
1466 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1467 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1468 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1474 "Display information for a route distinguisher\n"
1475 "VPN Route Distinguisher\n"
1476 "All VPN Route Distinguishers\n"
1479 int idx_ext_community
= 0;
1481 struct prefix_rd prd
;
1484 if (argv_find(argv
, argc
, "all", &rd_all
))
1485 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1486 NULL
, SHOW_DISPLAY_STANDARD
,
1487 use_json(argc
, argv
));
1489 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1490 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1492 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1495 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1496 SHOW_DISPLAY_STANDARD
,
1497 use_json(argc
, argv
));
1500 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1501 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1502 "show [ip] bgp l2vpn evpn all tags",
1508 "Display information about all EVPN NLRIs\n"
1509 "Display BGP tags for prefixes\n")
1511 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1512 SHOW_DISPLAY_TAGS
, 0);
1515 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1516 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1517 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1523 "Display information for a route distinguisher\n"
1524 "VPN Route Distinguisher\n"
1525 "All VPN Route Distinguishers\n"
1526 "Display BGP tags for prefixes\n")
1528 int idx_ext_community
= 0;
1530 struct prefix_rd prd
;
1533 if (argv_find(argv
, argc
, "all", &rd_all
))
1534 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1535 NULL
, SHOW_DISPLAY_TAGS
, 0);
1537 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1538 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1540 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1543 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1544 SHOW_DISPLAY_TAGS
, 0);
1547 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1548 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1549 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1555 "Detailed information on TCP and BGP neighbor connections\n"
1556 "IPv4 Neighbor to display information about\n"
1557 "IPv6 Neighbor to display information about\n"
1558 "Neighbor on BGP configured interface\n"
1559 "Display routes learned from neighbor\n" JSON_STR
)
1563 char *peerstr
= NULL
;
1564 bool uj
= use_json(argc
, argv
);
1565 afi_t afi
= AFI_L2VPN
;
1566 safi_t safi
= SAFI_EVPN
;
1567 struct bgp
*bgp
= NULL
;
1569 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1572 vty_out(vty
, "No index\n");
1576 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1577 argv_find(argv
, argc
, "neighbors", &idx
);
1578 peerstr
= argv
[++idx
]->arg
;
1580 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1583 json_object
*json_no
= NULL
;
1584 json_no
= json_object_new_object();
1585 json_object_string_add(json_no
, "warning",
1586 "Malformed address");
1587 vty_out(vty
, "%s\n",
1588 json_object_to_json_string(json_no
));
1589 json_object_free(json_no
);
1591 vty_out(vty
, "Malformed address: %s\n",
1595 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1597 json_object
*json_no
= NULL
;
1598 json_no
= json_object_new_object();
1599 json_object_string_add(
1601 "No such neighbor or address family");
1602 vty_out(vty
, "%s\n",
1603 json_object_to_json_string(json_no
));
1604 json_object_free(json_no
);
1606 vty_out(vty
, "%% No such neighbor or address family\n");
1610 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1611 SHOW_DISPLAY_STANDARD
, uj
);
1614 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1615 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1616 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1622 "Display information for a route distinguisher\n"
1623 "VPN Route Distinguisher\n"
1624 "All VPN Route Distinguishers\n"
1625 "Detailed information on TCP and BGP neighbor connections\n"
1626 "IPv4 Neighbor to display information about\n"
1627 "IPv6 Neighbor to display information about\n"
1628 "Neighbor on BGP configured interface\n"
1629 "Display routes learned from neighbor\n" JSON_STR
)
1631 int idx_ext_community
= 0;
1635 char *peerstr
= NULL
;
1636 struct prefix_rd prd
= {};
1637 bool uj
= use_json(argc
, argv
);
1638 afi_t afi
= AFI_L2VPN
;
1639 safi_t safi
= SAFI_EVPN
;
1640 struct bgp
*bgp
= NULL
;
1643 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1646 vty_out(vty
, "No index\n");
1650 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1651 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1652 &idx_ext_community
);
1653 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1656 json_object
*json_no
= NULL
;
1657 json_no
= json_object_new_object();
1658 json_object_string_add(
1660 "Malformed Route Distinguisher");
1661 vty_out(vty
, "%s\n",
1662 json_object_to_json_string(json_no
));
1663 json_object_free(json_no
);
1666 "%% Malformed Route Distinguisher\n");
1671 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1672 argv_find(argv
, argc
, "neighbors", &idx
);
1673 peerstr
= argv
[++idx
]->arg
;
1675 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1678 json_object
*json_no
= NULL
;
1679 json_no
= json_object_new_object();
1680 json_object_string_add(json_no
, "warning",
1681 "Malformed address");
1682 vty_out(vty
, "%s\n",
1683 json_object_to_json_string(json_no
));
1684 json_object_free(json_no
);
1686 vty_out(vty
, "Malformed address: %s\n",
1690 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1692 json_object
*json_no
= NULL
;
1693 json_no
= json_object_new_object();
1694 json_object_string_add(
1696 "No such neighbor or address family");
1697 vty_out(vty
, "%s\n",
1698 json_object_to_json_string(json_no
));
1699 json_object_free(json_no
);
1701 vty_out(vty
, "%% No such neighbor or address family\n");
1707 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1708 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1710 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1711 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1714 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1715 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1716 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1722 "Detailed information on TCP and BGP neighbor connections\n"
1723 "IPv4 Neighbor to display information about\n"
1724 "IPv6 Neighbor to display information about\n"
1725 "Neighbor on BGP configured interface\n"
1726 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1730 bool uj
= use_json(argc
, argv
);
1731 struct bgp
*bgp
= NULL
;
1732 afi_t afi
= AFI_L2VPN
;
1733 safi_t safi
= SAFI_EVPN
;
1734 char *peerstr
= NULL
;
1739 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1742 vty_out(vty
, "No index\n");
1746 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1747 argv_find(argv
, argc
, "neighbors", &idx
);
1748 peerstr
= argv
[++idx
]->arg
;
1750 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1753 json_object
*json_no
= NULL
;
1754 json_no
= json_object_new_object();
1755 json_object_string_add(json_no
, "warning",
1756 "Malformed address");
1757 vty_out(vty
, "%s\n",
1758 json_object_to_json_string(json_no
));
1759 json_object_free(json_no
);
1761 vty_out(vty
, "Malformed address: %s\n",
1765 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1767 json_object
*json_no
= NULL
;
1768 json_no
= json_object_new_object();
1769 json_object_string_add(
1771 "No such neighbor or address family");
1772 vty_out(vty
, "%s\n",
1773 json_object_to_json_string(json_no
));
1774 json_object_free(json_no
);
1776 vty_out(vty
, "%% No such neighbor or address family\n");
1780 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1783 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1784 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1785 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1791 "Display information for a route distinguisher\n"
1792 "VPN Route Distinguisher\n"
1793 "All VPN Route Distinguishers\n"
1794 "Detailed information on TCP and BGP neighbor connections\n"
1795 "IPv4 Neighbor to display information about\n"
1796 "IPv6 Neighbor to display information about\n"
1797 "Neighbor on BGP configured interface\n"
1798 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1800 int idx_ext_community
= 0;
1804 struct prefix_rd prd
;
1805 struct bgp
*bgp
= NULL
;
1806 bool uj
= use_json(argc
, argv
);
1807 char *peerstr
= NULL
;
1808 afi_t afi
= AFI_L2VPN
;
1809 safi_t safi
= SAFI_EVPN
;
1818 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1821 vty_out(vty
, "No index\n");
1825 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1826 argv_find(argv
, argc
, "neighbors", &idx
);
1827 peerstr
= argv
[++idx
]->arg
;
1829 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1832 json_object
*json_no
= NULL
;
1833 json_no
= json_object_new_object();
1834 json_object_string_add(json_no
, "warning",
1835 "Malformed address");
1836 vty_out(vty
, "%s\n",
1837 json_object_to_json_string(json_no
));
1838 json_object_free(json_no
);
1840 vty_out(vty
, "Malformed address: %s\n",
1844 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1846 json_object
*json_no
= NULL
;
1847 json_no
= json_object_new_object();
1848 json_object_string_add(
1850 "No such neighbor or address family");
1851 vty_out(vty
, "%s\n",
1852 json_object_to_json_string(json_no
));
1853 json_object_free(json_no
);
1855 vty_out(vty
, "%% No such neighbor or address family\n");
1859 if (argv_find(argv
, argc
, "all", &rd_all
))
1860 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1863 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1864 &idx_ext_community
);
1865 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1868 json_object
*json_no
= NULL
;
1869 json_no
= json_object_new_object();
1870 json_object_string_add(
1872 "Malformed Route Distinguisher");
1873 vty_out(vty
, "%s\n",
1874 json_object_to_json_string(json_no
));
1875 json_object_free(json_no
);
1878 "%% Malformed Route Distinguisher\n");
1883 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1886 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1887 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1888 "show [ip] bgp l2vpn evpn all overlay [json]",
1894 "Display information about all EVPN NLRIs\n"
1895 "Display BGP Overlay Information for prefixes\n"
1898 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1899 SHOW_DISPLAY_OVERLAY
,
1900 use_json(argc
, argv
));
1903 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1904 show_ip_bgp_evpn_rd_overlay_cmd
,
1905 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1911 "Display information for a route distinguisher\n"
1912 "VPN Route Distinguisher\n"
1913 "All VPN Route Distinguishers\n"
1914 "Display BGP Overlay Information for prefixes\n")
1916 int idx_ext_community
= 0;
1918 struct prefix_rd prd
;
1921 if (argv_find(argv
, argc
, "all", &rd_all
))
1922 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1923 NULL
, SHOW_DISPLAY_OVERLAY
,
1924 use_json(argc
, argv
));
1926 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1927 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1929 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1932 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1933 SHOW_DISPLAY_OVERLAY
,
1934 use_json(argc
, argv
));
1937 DEFUN(show_bgp_l2vpn_evpn_com
,
1938 show_bgp_l2vpn_evpn_com_cmd
,
1939 "show bgp l2vpn evpn \
1940 <community AA:NN|large-community AA:BB:CC> \
1941 [exact-match] [json]",
1946 "Display routes matching the community\n"
1947 "Community number where AA and NN are (0-65535)\n"
1948 "Display routes matching the large-community\n"
1949 "List of large-community numbers\n"
1950 "Exact match of the communities\n"
1955 const char *clist_number_or_name
;
1956 int show_type
= bgp_show_type_normal
;
1957 struct community
*com
;
1958 struct lcommunity
*lcom
;
1960 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1961 clist_number_or_name
= argv
[++idx
]->arg
;
1962 show_type
= bgp_show_type_lcommunity
;
1964 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1965 show_type
= bgp_show_type_lcommunity_exact
;
1967 lcom
= lcommunity_str2com(clist_number_or_name
);
1969 vty_out(vty
, "%% Large-community malformed\n");
1973 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1974 SHOW_DISPLAY_STANDARD
,
1975 use_json(argc
, argv
));
1977 lcommunity_free(&lcom
);
1978 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1979 clist_number_or_name
= argv
[++idx
]->arg
;
1980 show_type
= bgp_show_type_community
;
1982 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1983 show_type
= bgp_show_type_community_exact
;
1985 com
= community_str2com(clist_number_or_name
);
1988 vty_out(vty
, "%% Community malformed: %s\n",
1989 clist_number_or_name
);
1993 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1994 SHOW_DISPLAY_STANDARD
,
1995 use_json(argc
, argv
));
1996 community_free(&com
);
2002 /* For testing purpose, static route of EVPN RT-5. */
2003 DEFUN(evpnrt5_network
,
2004 evpnrt5_network_cmd
,
2005 "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 RMAP_NAME]",
2006 "Specify a network to announce via BGP\n"
2009 "Specify Route Distinguisher\n"
2010 "VPN Route Distinguisher\n"
2012 "Ethernet Tag Value\n"
2015 "Ethernet Segment Identifier\n"
2016 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2018 "Gateway IP ( A.B.C.D )\n"
2019 "Gateway IPv6 ( X:X::X:X )\n"
2020 "Router Mac Ext Comm\n"
2021 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
2022 "Route-map to modify the attributes\n"
2023 "Name of the route map\n")
2025 int idx_ipv4_prefixlen
= 1;
2026 int idx_route_distinguisher
= 3;
2031 int idx_routermac
= 13;
2033 return bgp_static_set_safi(
2034 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2035 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
2036 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2037 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
2038 argv
[idx_routermac
]->arg
);
2041 /* For testing purpose, static route of EVPN RT-5. */
2042 DEFUN(no_evpnrt5_network
,
2043 no_evpnrt5_network_cmd
,
2044 "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>",
2046 "Specify a network to announce via BGP\n"
2049 "Specify Route Distinguisher\n"
2050 "VPN Route Distinguisher\n"
2052 "Ethernet Tag Value\n"
2055 "Ethernet Segment Identifier\n"
2056 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2057 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2059 int idx_ipv4_prefixlen
= 2;
2060 int idx_ext_community
= 4;
2065 return bgp_static_unset_safi(
2066 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2067 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2068 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2069 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2072 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2074 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
, false);
2077 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2079 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
, false);
2083 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2084 * check that this is a change.
2086 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2087 struct ecommunity
*ecomadd
)
2089 /* If the VNI is "live", we need to uninstall routes using the current
2090 * import RT(s) first before we update the import RT, and subsequently
2093 if (is_vni_live(vpn
))
2094 bgp_evpn_uninstall_routes(bgp
, vpn
);
2096 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2097 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2099 /* If the auto route-target is in use we must remove it */
2100 evpn_import_rt_delete_auto(bgp
, vpn
);
2102 /* Add new RT and rebuild the RT to VNI mapping */
2103 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2105 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2106 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2108 /* Install routes that match new import RT */
2109 if (is_vni_live(vpn
))
2110 bgp_evpn_install_routes(bgp
, vpn
);
2114 * Unconfigure Import RT(s) for a VNI (vty handler).
2116 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2117 struct ecommunity
*ecomdel
)
2119 struct listnode
*node
, *nnode
, *node_to_del
;
2120 struct ecommunity
*ecom
;
2122 /* Along the lines of "configure" except we have to reset to the
2125 if (is_vni_live(vpn
))
2126 bgp_evpn_uninstall_routes(bgp
, vpn
);
2128 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2129 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2131 /* Delete all import RTs */
2132 if (ecomdel
== NULL
) {
2133 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2134 ecommunity_free(&ecom
);
2135 list_delete_node(vpn
->import_rtl
, node
);
2139 /* Delete a specific import RT */
2143 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2144 if (ecommunity_match(ecom
, ecomdel
)) {
2145 ecommunity_free(&ecom
);
2152 list_delete_node(vpn
->import_rtl
, node_to_del
);
2155 assert(vpn
->import_rtl
);
2156 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2157 if (list_isempty(vpn
->import_rtl
)) {
2158 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2159 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2161 /* Rebuild the RT to VNI mapping */
2163 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2165 /* Install routes that match new import RT */
2166 if (is_vni_live(vpn
))
2167 bgp_evpn_install_routes(bgp
, vpn
);
2171 * Configure the Export RT for a VNI (vty handler). Caller expected to
2172 * check that this is a change. Note that only a single export RT is
2173 * allowed for a VNI and any change to configuration is implemented as
2174 * a "replace" (similar to other configuration).
2176 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2177 struct ecommunity
*ecomadd
)
2179 /* If the auto route-target is in use we must remove it */
2180 evpn_export_rt_delete_auto(bgp
, vpn
);
2182 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2183 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2185 if (is_vni_live(vpn
))
2186 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2190 * Unconfigure the Export RT for a VNI (vty handler)
2192 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2193 struct ecommunity
*ecomdel
)
2195 struct listnode
*node
, *nnode
, *node_to_del
;
2196 struct ecommunity
*ecom
;
2198 /* Delete all export RTs */
2199 if (ecomdel
== NULL
) {
2200 /* Reset to default and process all routes. */
2201 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2202 ecommunity_free(&ecom
);
2203 list_delete_node(vpn
->export_rtl
, node
);
2207 /* Delete a specific export RT */
2211 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2212 if (ecommunity_match(ecom
, ecomdel
)) {
2213 ecommunity_free(&ecom
);
2220 list_delete_node(vpn
->export_rtl
, node_to_del
);
2223 assert(vpn
->export_rtl
);
2224 if (list_isempty(vpn
->export_rtl
)) {
2225 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2226 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2229 if (is_vni_live(vpn
))
2230 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2234 * Configure RD for VRF
2236 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
,
2237 const char *rd_pretty
)
2239 /* If we have already advertise type-5 routes with a diffrent RD, we
2240 * have to delete and withdraw them firs
2242 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2245 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2246 bgp_vrf
->vrf_prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_pretty
);
2247 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2249 /* We have a new RD for VRF.
2250 * Advertise all type-5 routes again with the new RD
2252 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2256 * Unconfigure RD for VRF
2258 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2260 /* If we have already advertise type-5 routes with a diffrent RD, we
2261 * have to delete and withdraw them firs
2263 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2265 /* fall back to default RD */
2266 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2267 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2268 if (bgp_vrf
->vrf_prd_pretty
)
2269 XFREE(MTYPE_BGP
, bgp_vrf
->vrf_prd_pretty
);
2270 /* We have a new RD for VRF.
2271 * Advertise all type-5 routes again with the new RD
2273 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2277 * Configure RD for a VNI (vty handler)
2279 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2280 struct prefix_rd
*rd
, const char *rd_pretty
)
2282 /* If the VNI is "live", we need to delete and withdraw this VNI's
2283 * local routes with the prior RD first. Then, after updating RD,
2284 * need to re-advertise.
2286 if (is_vni_live(vpn
))
2287 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2290 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2291 vpn
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_pretty
);
2292 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2294 if (is_vni_live(vpn
))
2295 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2299 * Unconfigure RD for a VNI (vty handler)
2301 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2303 /* If the VNI is "live", we need to delete and withdraw this VNI's
2304 * local routes with the prior RD first. Then, after resetting RD
2305 * to automatic value, need to re-advertise.
2307 if (is_vni_live(vpn
))
2308 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2310 /* reset RD to default */
2311 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2313 if (is_vni_live(vpn
))
2314 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2318 * Create VNI, if not already present (VTY handler). Mark as configured.
2320 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2322 struct bgpevpn
*vpn
;
2323 struct in_addr mcast_grp
= {INADDR_ANY
};
2325 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2327 /* Check if this L2VNI is already configured as L3VNI */
2328 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2331 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2336 /* tenant vrf will be updated when we get local_vni_add from
2339 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2342 /* Mark as configured. */
2343 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2348 * Delete VNI. If VNI does not exist in the system (i.e., just
2349 * configuration), all that is needed is to free it. Otherwise,
2350 * any parameters configured for the VNI need to be reset (with
2351 * appropriate action) and the VNI marked as unconfigured; the
2352 * VNI will continue to exist, purely as a "learnt" entity.
2354 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2356 if (!is_vni_live(vpn
)) {
2357 bgp_evpn_free(bgp
, vpn
);
2361 /* We need to take the unconfigure action for each parameter of this VNI
2362 * that is configured. Some optimization is possible, but not worth the
2363 * additional code for an operation that should be pretty rare.
2365 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2367 /* First, deal with the export side - RD and export RT changes. */
2368 if (is_rd_configured(vpn
))
2369 evpn_unconfigure_rd(bgp
, vpn
);
2370 if (is_export_rt_configured(vpn
))
2371 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2373 /* Next, deal with the import side. */
2374 if (is_import_rt_configured(vpn
))
2375 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2379 * Display import RT mapping to VRFs (vty handler)
2380 * bgp_evpn: evpn bgp instance
2382 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2390 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2391 (void (*)(struct hash_bucket
*,
2392 void *))show_vrf_import_rt_entry
,
2397 * Display import RT mapping to VNIs (vty handler)
2399 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2408 bgp
->import_rt_hash
,
2409 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2414 * Display EVPN routes for all VNIs - vty handler.
2416 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
, int type
,
2417 bool mac_table
, struct in_addr vtep_ip
,
2418 json_object
*json
, int detail
)
2421 struct vni_walk_ctx wctx
;
2423 num_vnis
= hashcount(bgp
->vnihash
);
2426 memset(&wctx
, 0, sizeof(wctx
));
2430 wctx
.mac_table
= mac_table
;
2431 wctx
.vtep_ip
= vtep_ip
;
2433 wctx
.detail
= detail
;
2434 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2435 void *))show_vni_routes_hash
,
2440 * Display EVPN routes for all VNIs & all types - vty handler.
2442 static void evpn_show_routes_vni_all_type_all(struct vty
*vty
, struct bgp
*bgp
,
2443 struct in_addr vtep_ip
,
2444 json_object
*json
, int detail
)
2447 struct vni_walk_ctx wctx
;
2449 num_vnis
= hashcount(bgp
->vnihash
);
2453 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2456 wctx
.vtep_ip
= vtep_ip
;
2458 wctx
.detail
= detail
;
2459 hash_iterate(bgp
->vnihash
,
2460 (void (*)(struct hash_bucket
*,
2461 void *))show_vni_routes_all_hash
,
2466 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2468 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2469 vni_t vni
, struct in_addr orig_ip
,
2472 struct bgpevpn
*vpn
;
2473 struct prefix_evpn p
;
2474 struct bgp_dest
*dest
;
2475 struct bgp_path_info
*pi
;
2476 uint32_t path_cnt
= 0;
2479 json_object
*json_paths
= NULL
;
2485 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2487 vty_out(vty
, "VNI not found\n");
2491 /* See if route exists. */
2492 build_evpn_type3_prefix(&p
, orig_ip
);
2493 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2494 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2496 vty_out(vty
, "%% Network not in table\n");
2499 bgp_dest_unlock_node(dest
);
2505 json_paths
= json_object_new_array();
2507 /* Prefix and num paths displayed once per prefix. */
2508 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2509 NULL
, afi
, safi
, json
);
2511 /* Display each path for this prefix. */
2512 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2513 json_object
*json_path
= NULL
;
2516 json_path
= json_object_new_array();
2518 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2519 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2523 json_object_array_add(json_paths
, json_path
);
2530 json_object_object_add(json
, "paths", json_paths
);
2532 json_object_int_add(json
, "numPaths", path_cnt
);
2534 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2538 bgp_dest_unlock_node(dest
);
2542 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2543 * By definition, only matching type-2 route will be displayed.
2545 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2546 vni_t vni
, struct ethaddr
*mac
,
2547 struct ipaddr
*ip
, json_object
*json
)
2549 struct bgpevpn
*vpn
;
2550 struct prefix_evpn p
;
2551 struct prefix_evpn tmp_p
;
2552 struct bgp_dest
*dest
;
2553 struct bgp_path_info
*pi
;
2554 uint32_t path_cnt
= 0;
2557 json_object
*json_paths
= NULL
;
2558 struct ethaddr empty_mac
= {};
2559 struct ipaddr empty_ip
= {};
2560 const struct prefix_evpn
*evp
;
2566 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2569 vty_out(vty
, "VNI not found\n");
2573 build_evpn_type2_prefix(&p
, mac
? mac
: &empty_mac
,
2574 ip
? ip
: &empty_ip
);
2576 /* See if route exists. Look for both non-sticky and sticky. */
2577 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2578 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2580 vty_out(vty
, "%% Network not in table\n");
2583 bgp_dest_unlock_node(dest
);
2589 * MAC is per-path, we have to walk the path_info's and look for it
2593 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2594 if (memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2601 vty_out(vty
, "%% Network not in table\n");
2607 json_paths
= json_object_new_array();
2609 /* Prefix and num paths displayed once per prefix. */
2610 route_vty_out_detail_header(vty
, bgp
, dest
, (struct prefix
*)&p
, NULL
,
2613 evp
= (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2615 /* Display each path for this prefix. */
2616 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2617 json_object
*json_path
= NULL
;
2619 /* skip non-matching MACs */
2621 memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2626 json_path
= json_object_new_array();
2629 * VNI table MAC-IP prefixes don't have MAC so
2630 * make sure it's set from path info
2633 if (is_evpn_prefix_ipaddr_none(evp
)) {
2634 /* VNI MAC -> Global */
2635 evpn_type2_prefix_global_copy(
2636 (struct prefix_evpn
*)&tmp_p
, evp
,
2638 evpn_type2_path_info_get_ip(pi
));
2640 /* VNI IP -> Global */
2641 evpn_type2_prefix_global_copy(
2642 (struct prefix_evpn
*)&tmp_p
, evp
,
2643 evpn_type2_path_info_get_mac(pi
),
2647 route_vty_out_detail(vty
, bgp
, dest
, (struct prefix
*)&tmp_p
,
2648 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2652 json_object_array_add(json_paths
, json_path
);
2659 json_object_object_add(json
, "paths", json_paths
);
2661 json_object_int_add(json
, "numPaths", path_cnt
);
2663 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2667 bgp_dest_unlock_node(dest
);
2670 /* Disaplay EVPN routes for a ESI - VTY handler */
2671 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2672 esi_t
*esi
, json_object
*json
)
2674 struct bgp_evpn_es
*es
= NULL
;
2677 es
= bgp_evpn_es_find(esi
);
2680 vty_out(vty
, "ESI not found\n");
2684 show_esi_routes(bgp
, es
, vty
, json
);
2688 * Display EVPN routes for a VNI - vty handler.
2689 * If 'type' is non-zero, only routes matching that type are shown.
2690 * If the vtep_ip is non zero, only routes behind that vtep are shown
2692 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2693 int type
, bool mac_table
,
2694 struct in_addr vtep_ip
, json_object
*json
)
2696 struct bgpevpn
*vpn
;
2699 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2702 vty_out(vty
, "VNI not found\n");
2706 /* Walk this VNI's route table and display appropriate routes. */
2707 show_vni_routes(bgp
, vpn
, vty
, type
, mac_table
, vtep_ip
, json
, 0);
2711 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2712 * IP (vty handler). By definition, only matching type-2 route will be
2715 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2716 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2717 struct ipaddr
*ip
, json_object
*json
)
2719 struct prefix_evpn p
;
2720 struct bgp_dest
*dest
;
2721 struct bgp_path_info
*pi
;
2724 uint32_t path_cnt
= 0;
2725 json_object
*json_paths
= NULL
;
2730 /* See if route exists. Look for both non-sticky and sticky. */
2731 build_evpn_type2_prefix(&p
, mac
, ip
);
2732 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2733 (struct prefix
*)&p
, prd
);
2734 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2736 vty_out(vty
, "%% Network not in table\n");
2739 bgp_dest_unlock_node(dest
);
2744 /* Prefix and num paths displayed once per prefix. */
2745 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2746 prd
, afi
, safi
, json
);
2749 json_paths
= json_object_new_array();
2751 /* Display each path for this prefix. */
2752 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2753 json_object
*json_path
= NULL
;
2756 json_path
= json_object_new_array();
2758 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2759 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2763 json_object_array_add(json_paths
, json_path
);
2768 if (json
&& path_cnt
) {
2770 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2771 json_object_int_add(json
, "numPaths", path_cnt
);
2773 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2777 bgp_dest_unlock_node(dest
);
2781 * Display BGP EVPN routing table -- for specific RD (vty handler)
2782 * If 'type' is non-zero, only routes matching that type are shown.
2784 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2785 struct prefix_rd
*prd
, int type
,
2788 struct bgp_dest
*rd_dest
;
2789 struct bgp_table
*table
;
2790 struct bgp_dest
*dest
;
2791 struct bgp_path_info
*pi
;
2795 uint32_t prefix_cnt
, path_cnt
;
2796 json_object
*json_rd
= NULL
;
2797 int add_rd_to_json
= 0;
2801 prefix_cnt
= path_cnt
= 0;
2803 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2807 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2808 if (table
== NULL
) {
2809 bgp_dest_unlock_node(rd_dest
);
2814 json_rd
= json_object_new_object();
2815 json_object_string_addf(json_rd
, "rd",
2816 BGP_RD_AS_FORMAT(bgp
->asnotation
), prd
);
2819 bgp_dest_unlock_node(rd_dest
);
2821 /* Display all prefixes with this RD. */
2822 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2823 const struct prefix_evpn
*evp
=
2824 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2825 json_object
*json_prefix
= NULL
;
2826 json_object
*json_paths
= NULL
;
2827 int add_prefix_to_json
= 0;
2829 if (type
&& evp
->prefix
.route_type
!= type
)
2833 json_prefix
= json_object_new_object();
2835 pi
= bgp_dest_get_bgp_path_info(dest
);
2837 /* RD header and legend - once overall. */
2838 if (rd_header
&& !json
) {
2840 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2842 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2844 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2846 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2848 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2852 /* Prefix and num paths displayed once per prefix. */
2853 route_vty_out_detail_header(
2854 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), prd
,
2855 afi
, safi
, json_prefix
);
2861 json_paths
= json_object_new_array();
2863 /* Display each path for this prefix. */
2864 for (; pi
; pi
= pi
->next
) {
2865 json_object
*json_path
= NULL
;
2868 json_path
= json_object_new_array();
2870 route_vty_out_detail(
2871 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), pi
,
2872 afi
, safi
, RPKI_NOT_BEING_USED
, json_path
);
2875 json_object_array_add(json_paths
, json_path
);
2878 add_prefix_to_json
= 1;
2883 if (add_prefix_to_json
) {
2884 json_object_object_add(json_prefix
, "paths",
2886 json_object_object_addf(json_rd
, json_prefix
,
2889 json_object_free(json_paths
);
2890 json_object_free(json_prefix
);
2899 json_object_object_addf(
2901 BGP_RD_AS_FORMAT(bgp
->asnotation
), prd
);
2903 json_object_free(json_rd
);
2907 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2908 json_object_int_add(json
, "numPaths", path_cnt
);
2910 if (prefix_cnt
== 0)
2911 vty_out(vty
, "No prefixes exist with this RD%s\n",
2912 type
? " (of requested type)" : "");
2915 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2916 prefix_cnt
, path_cnt
,
2917 type
? " (of requested type)" : "");
2922 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2923 * (vty handler). Only matching type-2 routes will be displayed.
2925 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2926 struct ethaddr
*mac
, struct ipaddr
*ip
,
2929 struct bgp_dest
*rd_dest
;
2930 struct bgp_table
*table
;
2931 struct bgp_dest
*dest
;
2932 struct bgp_path_info
*pi
;
2933 afi_t afi
= AFI_L2VPN
;
2934 safi_t safi
= SAFI_EVPN
;
2935 uint32_t prefix_cnt
, path_cnt
;
2936 prefix_cnt
= path_cnt
= 0;
2938 /* EVPN routing table is a 2-level table with the first level being
2939 * the RD. We need to look in every RD we know about.
2941 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2942 rd_dest
= bgp_route_next(rd_dest
)) {
2943 json_object
*json_paths
= NULL
; /* paths array for prefix */
2944 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2945 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2946 char rd_str
[RD_ADDRSTRLEN
];
2947 int add_rd_to_json
= 0;
2948 struct prefix_evpn ep
;
2949 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2951 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2955 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2956 sizeof(rd_str
), bgp
->asnotation
);
2958 /* Construct an RT-2 from the user-supplied mac(ip),
2959 * then search the l2vpn evpn table for it.
2961 build_evpn_type2_prefix(&ep
, mac
, ip
);
2962 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2963 (struct prefix
*)&ep
,
2964 (struct prefix_rd
*)rd_destp
);
2969 json_rd
= json_object_new_object();
2971 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2973 pi
= bgp_dest_get_bgp_path_info(dest
);
2975 /* RD header - per RD. */
2976 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2977 rd_str
, RD_ADDRSTRLEN
);
2982 json_prefix
= json_object_new_object();
2983 json_paths
= json_object_new_array();
2984 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2986 json_object_int_add(json_prefix
, "prefixLen",
2989 /* Prefix and num paths displayed once per prefix. */
2990 route_vty_out_detail_header(
2991 vty
, bgp
, dest
, p
, (struct prefix_rd
*)rd_destp
,
2992 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2994 /* For EVPN, the prefix is displayed for each path (to
2995 * fit in with code that already exists).
2997 for (; pi
; pi
= pi
->next
) {
2998 json_object
*json_path
= NULL
;
3004 json_path
= json_object_new_array();
3006 route_vty_out_detail(vty
, bgp
, dest
, p
, pi
, AFI_L2VPN
,
3007 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3011 json_object_array_add(json_paths
, json_path
);
3017 json_object_object_add(json_prefix
, "paths",
3019 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
3022 json_object_object_add(json
, rd_str
, json_rd
);
3024 json_object_free(json_rd
);
3029 bgp_dest_unlock_node(dest
);
3033 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3034 json_object_int_add(json
, "numPaths", path_cnt
);
3036 if (prefix_cnt
== 0) {
3037 vty_out(vty
, "No Matching EVPN prefixes exist\n");
3039 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
3040 prefix_cnt
, path_cnt
);
3046 * Display BGP EVPN routing table - all routes (vty handler).
3047 * If 'type' is non-zero, only routes matching that type are shown.
3049 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3050 json_object
*json
, int detail
)
3052 struct bgp_dest
*rd_dest
;
3053 struct bgp_table
*table
;
3054 struct bgp_dest
*dest
;
3055 struct bgp_path_info
*pi
;
3056 int header
= detail
? 0 : 1;
3060 uint32_t prefix_cnt
, path_cnt
;
3064 prefix_cnt
= path_cnt
= 0;
3066 /* EVPN routing table is a 2-level table with the first level being
3069 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
3070 rd_dest
= bgp_route_next(rd_dest
)) {
3071 char rd_str
[RD_ADDRSTRLEN
];
3072 json_object
*json_rd
= NULL
; /* contains routes for an RD */
3073 int add_rd_to_json
= 0;
3075 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
3077 table
= bgp_dest_get_bgp_table_info(rd_dest
);
3081 tbl_ver
= table
->version
;
3082 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
3083 sizeof(rd_str
), bgp
->asnotation
);
3086 json_rd
= json_object_new_object();
3090 /* Display all prefixes for an RD */
3091 for (dest
= bgp_table_top(table
); dest
;
3092 dest
= bgp_route_next(dest
)) {
3093 json_object
*json_prefix
=
3094 NULL
; /* contains prefix under a RD */
3095 json_object
*json_paths
=
3096 NULL
; /* array of paths under a prefix*/
3097 const struct prefix_evpn
*evp
=
3098 (const struct prefix_evpn
*)bgp_dest_get_prefix(
3100 int add_prefix_to_json
= 0;
3101 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3103 if (type
&& evp
->prefix
.route_type
!= type
)
3106 pi
= bgp_dest_get_bgp_path_info(dest
);
3108 /* Overall header/legend displayed once. */
3110 bgp_evpn_show_route_header(vty
, bgp
,
3115 "%19s Extended Community\n"
3120 /* RD header - per RD. */
3122 bgp_evpn_show_route_rd_header(
3123 vty
, rd_dest
, json_rd
, rd_str
,
3132 json_prefix
= json_object_new_object();
3133 json_paths
= json_object_new_array();
3134 json_object_string_addf(json_prefix
, "prefix",
3136 json_object_int_add(json_prefix
, "prefixLen",
3140 /* Prefix and num paths displayed once per prefix. */
3142 route_vty_out_detail_header(
3144 bgp_dest_get_prefix(dest
),
3145 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3146 SAFI_EVPN
, json_prefix
);
3148 /* For EVPN, the prefix is displayed for each path (to
3150 * with code that already exists).
3152 for (; pi
; pi
= pi
->next
) {
3153 json_object
*json_path
= NULL
;
3156 add_prefix_to_json
= 1;
3160 json_path
= json_object_new_array();
3163 route_vty_out_detail(
3165 bgp_dest_get_prefix(dest
), pi
,
3166 AFI_L2VPN
, SAFI_EVPN
,
3167 RPKI_NOT_BEING_USED
, json_path
);
3169 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3173 json_object_array_add(json_paths
,
3178 if (add_prefix_to_json
) {
3179 json_object_object_add(json_prefix
,
3182 json_object_object_addf(json_rd
,
3186 json_object_free(json_prefix
);
3187 json_object_free(json_paths
);
3196 json_object_object_add(json
, rd_str
, json_rd
);
3198 json_object_free(json_rd
);
3205 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3206 json_object_int_add(json
, "numPaths", path_cnt
);
3208 if (prefix_cnt
== 0) {
3209 vty_out(vty
, "No EVPN prefixes %sexist\n",
3210 type
? "(of requested type) " : "");
3212 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3213 prefix_cnt
, path_cnt
,
3214 type
? " (of requested type)" : "");
3219 int bgp_evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3220 bool use_json
, int detail
)
3222 json_object
*json
= NULL
;
3225 json
= json_object_new_object();
3227 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3230 vty_json(vty
, json
);
3235 * Display specified VNI (vty handler)
3237 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3241 struct bgpevpn
*vpn
;
3243 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3246 display_vni(vty
, vpn
, json
);
3248 struct bgp
*bgp_temp
;
3249 struct listnode
*node
= NULL
;
3251 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3252 if (bgp_temp
->l3vni
== vni
) {
3254 display_l3vni(vty
, bgp_temp
, json
);
3261 vty_out(vty
, "{}\n");
3263 vty_out(vty
, "VNI not found\n");
3270 * Display a VNI (upon user query).
3272 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3276 struct bgp
*bgp_temp
= NULL
;
3277 struct listnode
*node
;
3281 vty_out(vty
, "Flags: * - Kernel\n");
3282 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3283 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3286 /* print all L2 VNIS */
3289 hash_iterate(bgp
->vnihash
,
3290 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3293 /* print all L3 VNIs */
3294 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3295 show_l3vni_entry(vty
, bgp_temp
, json
);
3299 * evpn - enable advertisement of svi MAC-IP
3301 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3305 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3307 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3310 bgp
->evpn_info
->advertise_svi_macip
= set
;
3311 bgp_zebra_advertise_svi_macip(bgp
,
3312 bgp
->evpn_info
->advertise_svi_macip
, 0);
3314 if (set
&& vpn
->advertise_svi_macip
)
3316 else if (!set
&& !vpn
->advertise_svi_macip
)
3319 vpn
->advertise_svi_macip
= set
;
3320 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3326 * evpn - enable advertisement of default g/w
3328 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3331 if (bgp
->advertise_gw_macip
)
3334 bgp
->advertise_gw_macip
= 1;
3335 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3337 if (vpn
->advertise_gw_macip
)
3340 vpn
->advertise_gw_macip
= 1;
3341 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3348 * evpn - disable advertisement of default g/w
3350 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3351 struct bgpevpn
*vpn
)
3354 if (!bgp
->advertise_gw_macip
)
3357 bgp
->advertise_gw_macip
= 0;
3358 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3360 if (!vpn
->advertise_gw_macip
)
3363 vpn
->advertise_gw_macip
= 0;
3364 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3371 * evpn - enable advertisement of default g/w
3373 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3374 afi_t afi
, bool add
)
3376 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3379 /* bail if we are already advertising default route */
3380 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3384 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3386 else if (afi
== AFI_IP6
)
3387 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3388 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3390 /* bail out if we havent advertised the default route */
3391 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3394 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3395 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3396 else if (afi
== AFI_IP6
)
3397 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3398 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3401 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3405 * evpn - enable advertisement of default g/w
3407 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3408 struct bgpevpn
*vpn
)
3410 if (vpn
->advertise_subnet
)
3413 vpn
->advertise_subnet
= 1;
3414 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3418 * evpn - disable advertisement of default g/w
3420 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3422 if (!vpn
->advertise_subnet
)
3425 vpn
->advertise_subnet
= 0;
3426 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3430 * EVPN (VNI advertisement) enabled. Register with zebra.
3432 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3434 bgp
->advertise_all_vni
= 1;
3436 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3440 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3441 * cache, EVPN routes (delete and withdraw from peers).
3443 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3445 bgp
->advertise_all_vni
= 0;
3446 bgp_set_evpn(bgp_get_default());
3447 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3448 bgp_evpn_cleanup_on_disable(bgp
);
3451 /* Set resolve overlay index flag */
3452 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3454 if (set
== bgp
->resolve_overlay_index
)
3458 bgp
->resolve_overlay_index
= true;
3459 hash_iterate(bgp
->vnihash
,
3460 (void (*)(struct hash_bucket
*, void *))
3461 bgp_evpn_handle_resolve_overlay_index_set
,
3466 (void (*)(struct hash_bucket
*, void *))
3467 bgp_evpn_handle_resolve_overlay_index_unset
,
3469 bgp
->resolve_overlay_index
= false;
3474 * EVPN - use RFC8365 to auto-derive RT
3476 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3478 bgp
->advertise_autort_rfc8365
= 1;
3479 bgp_evpn_handle_autort_change(bgp
);
3483 * EVPN - don't use RFC8365 to auto-derive RT
3485 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3487 bgp
->advertise_autort_rfc8365
= 0;
3488 bgp_evpn_handle_autort_change(bgp
);
3491 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3494 struct listnode
*node
, *nnode
;
3495 struct ecommunity
*ecom
;
3497 if (is_vni_configured(vpn
)) {
3498 vty_out(vty
, " vni %u\n", vpn
->vni
);
3499 if (is_rd_configured(vpn
))
3500 vty_out(vty
, " rd %s\n", vpn
->prd_pretty
);
3502 if (is_import_rt_configured(vpn
)) {
3503 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3505 ecom_str
= ecommunity_ecom2str(
3506 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3507 vty_out(vty
, " route-target import %s\n",
3509 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3513 if (is_export_rt_configured(vpn
)) {
3514 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3516 ecom_str
= ecommunity_ecom2str(
3517 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3518 vty_out(vty
, " route-target export %s\n",
3520 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3524 if (vpn
->advertise_gw_macip
)
3525 vty_out(vty
, " advertise-default-gw\n");
3527 if (vpn
->advertise_svi_macip
)
3528 vty_out(vty
, " advertise-svi-ip\n");
3530 if (vpn
->advertise_subnet
)
3531 vty_out(vty
, " advertise-subnet\n");
3533 vty_out(vty
, " exit-vni\n");
3537 #include "bgpd/bgp_evpn_vty_clippy.c"
3539 DEFPY(bgp_evpn_flood_control
,
3540 bgp_evpn_flood_control_cmd
,
3541 "[no$no] flooding <disable$disable|head-end-replication$her>",
3543 "Specify handling for BUM packets\n"
3544 "Do not flood any BUM packets\n"
3545 "Flood BUM packets using head-end replication\n")
3547 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3548 enum vxlan_flood_control flood_ctrl
;
3554 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3556 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3560 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3563 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3564 bgp_evpn_flood_control_change(bgp
);
3569 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3570 bgp_evpn_advertise_default_gw_vni_cmd
,
3571 "advertise-default-gw",
3572 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3574 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3575 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3580 evpn_set_advertise_default_gw(bgp
, vpn
);
3585 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3586 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3587 "no advertise-default-gw",
3589 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3591 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3592 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3597 evpn_unset_advertise_default_gw(bgp
, vpn
);
3603 DEFUN (bgp_evpn_advertise_default_gw
,
3604 bgp_evpn_advertise_default_gw_cmd
,
3605 "advertise-default-gw",
3606 "Advertise All default g/w mac-ip routes in EVPN\n")
3608 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3613 if (!EVPN_ENABLED(bgp
)) {
3615 "This command is only supported under the EVPN VRF\n");
3619 evpn_set_advertise_default_gw(bgp
, NULL
);
3624 DEFUN (no_bgp_evpn_advertise_default_gw
,
3625 no_bgp_evpn_advertise_default_gw_cmd
,
3626 "no advertise-default-gw",
3628 "Withdraw All default g/w mac-ip routes from EVPN\n")
3630 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3635 evpn_unset_advertise_default_gw(bgp
, NULL
);
3640 DEFUN (bgp_evpn_advertise_all_vni
,
3641 bgp_evpn_advertise_all_vni_cmd
,
3642 "advertise-all-vni",
3643 "Advertise All local VNIs\n")
3645 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3646 struct bgp
*bgp_evpn
= NULL
;
3651 bgp_evpn
= bgp_get_evpn();
3652 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3653 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3654 bgp_evpn
->name_pretty
);
3655 return CMD_WARNING_CONFIG_FAILED
;
3658 evpn_set_advertise_all_vni(bgp
);
3662 DEFUN (no_bgp_evpn_advertise_all_vni
,
3663 no_bgp_evpn_advertise_all_vni_cmd
,
3664 "no advertise-all-vni",
3666 "Advertise All local VNIs\n")
3668 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3672 evpn_unset_advertise_all_vni(bgp
);
3676 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3677 bgp_evpn_advertise_autort_rfc8365_cmd
,
3678 "autort rfc8365-compatible",
3679 "Auto-derivation of RT\n"
3680 "Auto-derivation of RT using RFC8365\n")
3682 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3686 evpn_set_advertise_autort_rfc8365(bgp
);
3690 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3691 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3692 "no autort rfc8365-compatible",
3694 "Auto-derivation of RT\n"
3695 "Auto-derivation of RT using RFC8365\n")
3697 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3701 evpn_unset_advertise_autort_rfc8365(bgp
);
3705 DEFUN (bgp_evpn_default_originate
,
3706 bgp_evpn_default_originate_cmd
,
3707 "default-originate <ipv4 | ipv6>",
3708 "originate a default route\n"
3709 "ipv4 address family\n"
3710 "ipv6 address family\n")
3714 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3718 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3719 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3723 DEFUN (no_bgp_evpn_default_originate
,
3724 no_bgp_evpn_default_originate_cmd
,
3725 "no default-originate <ipv4 | ipv6>",
3727 "withdraw a default route\n"
3728 "ipv4 address family\n"
3729 "ipv6 address family\n")
3733 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3737 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3738 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3742 DEFPY (dup_addr_detection
,
3743 dup_addr_detection_cmd
,
3744 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3745 "Duplicate address detection\n"
3746 "Max allowed moves before address detected as duplicate\n"
3747 "Num of max allowed moves (2-1000) default 5\n"
3748 "Duplicate address detection time\n"
3749 "Time in seconds (2-1800) default 180\n")
3751 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3756 if (!EVPN_ENABLED(bgp_vrf
)) {
3758 "This command is only supported under the EVPN VRF\n");
3762 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3765 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3767 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3769 bgp_zebra_dup_addr_detection(bgp_vrf
);
3774 DEFPY (dup_addr_detection_auto_recovery
,
3775 dup_addr_detection_auto_recovery_cmd
,
3776 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3777 "Duplicate address detection\n"
3778 "Duplicate address detection freeze\n"
3779 "Duplicate address detection permanent freeze\n"
3780 "Duplicate address detection freeze time (30-3600)\n")
3782 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3783 uint32_t freeze_time
= freeze_time_val
;
3788 if (!EVPN_ENABLED(bgp_vrf
)) {
3790 "This command is only supported under the EVPN VRF\n");
3794 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3795 bgp_vrf
->evpn_info
->dad_freeze
= true;
3796 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3798 bgp_zebra_dup_addr_detection(bgp_vrf
);
3803 DEFPY (no_dup_addr_detection
,
3804 no_dup_addr_detection_cmd
,
3805 "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>]",
3807 "Duplicate address detection\n"
3808 "Max allowed moves before address detected as duplicate\n"
3809 "Num of max allowed moves (2-1000) default 5\n"
3810 "Duplicate address detection time\n"
3811 "Time in seconds (2-1800) default 180\n"
3812 "Duplicate address detection freeze\n"
3813 "Duplicate address detection permanent freeze\n"
3814 "Duplicate address detection freeze time (30-3600)\n")
3816 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3817 uint32_t max_moves
= (uint32_t)max_moves_val
;
3818 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3823 if (!EVPN_ENABLED(bgp_vrf
)) {
3825 "This command is only supported under the EVPN VRF\n");
3830 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3832 /* Reset all parameters to default. */
3833 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3834 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3835 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3836 bgp_vrf
->evpn_info
->dad_freeze
= false;
3837 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3840 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3842 "%% Value does not match with config\n");
3845 bgp_vrf
->evpn_info
->dad_max_moves
=
3846 EVPN_DAD_DEFAULT_MAX_MOVES
;
3850 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3852 "%% Value does not match with config\n");
3855 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3859 if (bgp_vrf
->evpn_info
->dad_freeze_time
3862 "%% Value does not match with config\n");
3865 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3866 bgp_vrf
->evpn_info
->dad_freeze
= false;
3869 if (permanent_val
) {
3870 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3872 "%% Value does not match with config\n");
3875 bgp_vrf
->evpn_info
->dad_freeze
= false;
3879 bgp_zebra_dup_addr_detection(bgp_vrf
);
3884 DEFPY(bgp_evpn_advertise_svi_ip
,
3885 bgp_evpn_advertise_svi_ip_cmd
,
3886 "[no$no] advertise-svi-ip",
3888 "Advertise svi mac-ip routes in EVPN\n")
3890 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3896 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3898 if (!EVPN_ENABLED(bgp
)) {
3900 "This command is only supported under EVPN VRF\n");
3903 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3909 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3910 bgp_evpn_advertise_svi_ip_vni_cmd
,
3911 "[no$no] advertise-svi-ip",
3913 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3915 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3916 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3922 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3924 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3929 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3930 bgp_evpn_advertise_vni_subnet_cmd
,
3932 "Advertise the subnet corresponding to VNI\n")
3934 struct bgp
*bgp_vrf
= NULL
;
3935 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3936 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3941 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3945 evpn_set_advertise_subnet(bgp
, vpn
);
3949 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3950 no_bgp_evpn_advertise_vni_subnet_cmd
,
3951 "no advertise-subnet",
3953 "Advertise All local VNIs\n")
3955 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3956 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3961 evpn_unset_advertise_subnet(bgp
, vpn
);
3965 DEFUN (bgp_evpn_advertise_type5
,
3966 bgp_evpn_advertise_type5_cmd
,
3967 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3968 "Advertise prefix routes\n"
3971 "advertise gateway IP overlay index\n"
3972 "route-map for filtering specific routes\n"
3973 "Name of the route map\n")
3975 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3982 int rmap_changed
= 0;
3983 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3985 bool adv_flag_changed
= false;
3987 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3988 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3989 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3991 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3993 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3995 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3996 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3999 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4003 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4005 "%% Only ipv4 or ipv6 address families are supported\n");
4009 if (safi
!= SAFI_UNICAST
) {
4011 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4015 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
4016 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
4017 vty_out(vty
, "%% Unknown overlay-index type specified\n");
4021 if (afi
== AFI_IP
) {
4022 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4023 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
4024 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4025 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4028 * this is the case for first time ever configuration
4029 * adv ipv4 unicast is enabled for the first time.
4030 * So no need to reset any flag
4032 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4034 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4035 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4036 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4038 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4039 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4040 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4042 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4043 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
4046 * This is modify case from gateway-ip
4047 * to no overlay index
4049 adv_flag_changed
= true;
4050 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4051 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4052 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4053 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4054 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4056 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4057 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4060 * This is modify case from no overlay index
4063 adv_flag_changed
= true;
4064 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4065 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4066 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4067 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4071 * Command is issued with the same option
4072 * (no overlay index or gateway-ip) which was
4073 * already configured. So nothing to do.
4074 * However, route-map may have been modified.
4075 * check if route-map has been modified.
4076 * If not, return an error
4082 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4083 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
4084 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4085 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4088 * this is the case for first time ever configuration
4089 * adv ipv6 unicast is enabled for the first time.
4090 * So no need to reset any flag
4092 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4094 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4095 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4096 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4098 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4099 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4100 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4102 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4103 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
4106 * This is modify case from gateway-ip
4107 * to no overlay index
4109 adv_flag_changed
= true;
4110 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4111 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4112 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4113 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4114 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4116 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4117 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4120 * This is modify case from no overlay index
4123 adv_flag_changed
= true;
4124 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4125 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4126 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4127 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4131 * Command is issued with the same option
4132 * (no overlay index or gateway-ip) which was
4133 * already configured. So nothing to do.
4134 * However, route-map may have been modified.
4135 * check if route-map has been modified.
4136 * If not, return an error
4143 if ((rmap_changed
) || (adv_flag_changed
)) {
4145 /* If either of these are changed, then FRR needs to
4146 * withdraw already advertised type5 routes.
4148 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4150 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4151 XFREE(MTYPE_ROUTE_MAP_NAME
,
4152 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4153 route_map_counter_decrement(
4154 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4155 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4156 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4161 /* set the route-map for advertise command */
4162 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4163 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4164 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4165 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4166 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4167 route_map_counter_increment(
4168 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4171 /* advertise type-5 routes */
4172 if (advertise_type5_routes(bgp_vrf
, afi
))
4173 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4177 DEFUN (no_bgp_evpn_advertise_type5
,
4178 no_bgp_evpn_advertise_type5_cmd
,
4179 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
4181 "Advertise prefix routes\n"
4184 "route-map for filtering specific routes\n"
4185 "Name of the route map\n")
4187 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4196 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4197 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4199 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4201 "%% Only ipv4 or ipv6 address families are supported\n");
4205 if (safi
!= SAFI_UNICAST
) {
4207 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4211 if (afi
== AFI_IP
) {
4213 /* if we are not advertising ipv4 prefix as type-5
4216 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4217 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4218 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4219 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4220 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4221 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4222 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4223 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4224 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4228 /* if we are not advertising ipv6 prefix as type-5
4231 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4232 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4233 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4234 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4235 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4236 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4237 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4238 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4239 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4243 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4244 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4245 XFREE(MTYPE_ROUTE_MAP_NAME
,
4246 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4247 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4248 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4254 DEFPY (bgp_evpn_use_es_l3nhg
,
4255 bgp_evpn_use_es_l3nhg_cmd
,
4256 "[no$no] use-es-l3nhg",
4258 "use L3 nexthop group for host routes with ES destination\n")
4260 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4264 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4265 bgp_evpn_ead_evi_rx_disable_cmd
,
4266 "[no$no] disable-ead-evi-rx",
4268 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4270 bool ead_evi_rx
= no
? true :false;
4272 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4273 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4274 bgp_evpn_switch_ead_evi_rx();
4279 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4280 bgp_evpn_ead_evi_tx_disable_cmd
,
4281 "[no$no] disable-ead-evi-tx",
4283 "Don't advertise EAD-EVI for local ESs\n")
4285 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4289 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4290 bgp_evpn_enable_resolve_overlay_index_cmd
,
4291 "[no$no] enable-resolve-overlay-index",
4293 "Enable Recursive Resolution of type-5 route overlay index\n")
4295 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4297 if (bgp
!= bgp_get_evpn()) {
4298 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4302 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4306 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4307 bgp_evpn_advertise_pip_ip_mac_cmd
,
4308 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4310 "evpn system primary IP\n"
4313 MAC_STR MAC_STR MAC_STR
)
4315 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4316 struct bgp
*bgp_evpn
= NULL
;
4318 if (EVPN_ENABLED(bgp_vrf
)) {
4320 "This command is supported under L3VNI BGP EVPN VRF\n");
4321 return CMD_WARNING_CONFIG_FAILED
;
4323 bgp_evpn
= bgp_get_evpn();
4326 /* pip is already enabled */
4327 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4330 bgp_vrf
->evpn_info
->advertise_pip
= true;
4331 if (ip
.s_addr
!= INADDR_ANY
) {
4332 /* Already configured with same IP */
4333 if (IPV4_ADDR_SAME(&ip
,
4334 &bgp_vrf
->evpn_info
->pip_ip_static
))
4337 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4338 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4340 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4342 /* default instance router-id assignemt */
4344 bgp_vrf
->evpn_info
->pip_ip
=
4345 bgp_evpn
->router_id
;
4348 if (!is_zero_mac(&mac
->eth_addr
)) {
4349 /* Already configured with same MAC */
4350 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4351 &mac
->eth_addr
, ETH_ALEN
) == 0)
4354 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4355 &mac
->eth_addr
, ETH_ALEN
);
4356 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4357 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4360 /* Copy zebra sys mac */
4361 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4362 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4363 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4368 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4370 /* Disable PIP feature */
4371 bgp_vrf
->evpn_info
->advertise_pip
= false;
4372 /* copy anycast mac */
4373 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4374 &bgp_vrf
->rmac
, ETH_ALEN
);
4376 /* remove MAC-IP option retain PIP knob. */
4377 if ((ip
.s_addr
!= INADDR_ANY
) &&
4378 !IPV4_ADDR_SAME(&ip
,
4379 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4381 "%% BGP EVPN PIP IP does not match\n");
4382 return CMD_WARNING_CONFIG_FAILED
;
4385 if (!is_zero_mac(&mac
->eth_addr
) &&
4386 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4387 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4389 "%% BGP EVPN PIP MAC does not match\n");
4390 return CMD_WARNING_CONFIG_FAILED
;
4392 /* pip_rmac can carry vrr_rmac reset only if it matches
4393 * with static value.
4395 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4396 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4398 /* Copy zebra sys mac */
4400 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4401 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4402 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4405 /* copy anycast mac */
4406 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4407 &bgp_vrf
->rmac
, ETH_ALEN
);
4411 /* reset user configured sys MAC */
4412 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4413 /* reset user configured sys IP */
4414 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4415 /* Assign default PIP IP (bgp instance router-id) */
4417 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4419 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4422 if (is_evpn_enabled()) {
4423 struct listnode
*node
= NULL
;
4424 struct bgpevpn
*vpn
= NULL
;
4427 * At this point if bgp_evpn is NULL and evpn is enabled
4428 * something stupid has gone wrong
4432 update_advertise_vrf_routes(bgp_vrf
);
4434 /* Update (svi) type-2 routes */
4435 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4436 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4438 update_routes_for_vni(bgp_evpn
, vpn
);
4446 * Display VNI information - for all or a specific VNI
4448 DEFUN(show_bgp_l2vpn_evpn_vni
,
4449 show_bgp_l2vpn_evpn_vni_cmd
,
4450 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4459 struct bgp
*bgp_evpn
;
4463 json_object
*json
= NULL
;
4464 uint32_t num_l2vnis
= 0;
4465 uint32_t num_l3vnis
= 0;
4466 uint32_t num_vnis
= 0;
4467 struct listnode
*node
= NULL
;
4468 struct bgp
*bgp_temp
= NULL
;
4470 uj
= use_json(argc
, argv
);
4472 bgp_evpn
= bgp_get_evpn();
4476 if (!argv_find(argv
, argc
, "evpn", &idx
))
4480 json
= json_object_new_object();
4482 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4484 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4486 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4487 if (bgp_temp
->l3vni
)
4490 num_vnis
= num_l2vnis
+ num_l3vnis
;
4492 json_object_string_add(json
, "advertiseGatewayMacip",
4493 bgp_evpn
->advertise_gw_macip
4496 json_object_string_add(json
, "advertiseSviMacIp",
4497 bgp_evpn
->evpn_info
->advertise_svi_macip
4498 ? "Enabled" : "Disabled");
4499 json_object_string_add(json
, "advertiseAllVnis",
4500 is_evpn_enabled() ? "Enabled"
4502 json_object_string_add(
4504 bgp_evpn
->vxlan_flood_ctrl
==
4505 VXLAN_FLOOD_HEAD_END_REPL
4506 ? "Head-end replication"
4508 json_object_string_add(
4509 json
, "vxlanFlooding",
4510 bgp_evpn
->vxlan_flood_ctrl
==
4511 VXLAN_FLOOD_HEAD_END_REPL
4514 json_object_int_add(json
, "numVnis", num_vnis
);
4515 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4516 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4518 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4519 bgp_evpn
->advertise_gw_macip
? "Enabled"
4521 vty_out(vty
, "Advertise SVI Macip: %s\n",
4522 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4524 vty_out(vty
, "Advertise All VNI flag: %s\n",
4525 is_evpn_enabled() ? "Enabled" : "Disabled");
4526 vty_out(vty
, "BUM flooding: %s\n",
4527 bgp_evpn
->vxlan_flood_ctrl
==
4528 VXLAN_FLOOD_HEAD_END_REPL
4529 ? "Head-end replication"
4531 vty_out(vty
, "VXLAN flooding: %s\n",
4532 bgp_evpn
->vxlan_flood_ctrl
==
4533 VXLAN_FLOOD_HEAD_END_REPL
4536 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4537 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4539 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4543 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4546 /* Display specific VNI */
4547 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4548 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4552 vty_json(vty
, json
);
4557 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4558 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4559 "show bgp l2vpn evpn vni remote-ip-hash",
4567 struct bgp
*bgp_evpn
;
4570 bgp_evpn
= bgp_get_evpn();
4574 if (!argv_find(argv
, argc
, "evpn", &idx
))
4577 hash_iterate(bgp_evpn
->vnihash
,
4578 (void (*)(struct hash_bucket
*,
4579 void *))bgp_evpn_show_remote_ip_hash
,
4585 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4586 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4587 "show bgp l2vpn evpn vni-svi-hash",
4592 "Show vni-svi-hash\n")
4594 struct bgp
*bgp_evpn
;
4597 bgp_evpn
= bgp_get_evpn();
4601 if (!argv_find(argv
, argc
, "evpn", &idx
))
4604 hash_iterate(bgp_evpn
->vni_svi_hash
,
4605 (void (*)(struct hash_bucket
*,
4606 void *))bgp_evpn_show_vni_svi_hash
,
4612 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4613 show_bgp_l2vpn_evpn_es_evi_cmd
,
4614 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4620 "VxLAN Network Identifier\n"
4623 "Detailed information\n")
4626 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4628 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4633 DEFPY(show_bgp_l2vpn_evpn_es
,
4634 show_bgp_l2vpn_evpn_es_cmd
,
4635 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4640 "Ethernet Segment\n"
4642 "Detailed information\n"
4648 if (!str_to_esi(esi_str
, &esi
)) {
4649 vty_out(vty
, "%% Malformed ESI\n");
4652 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4655 bgp_evpn_es_show(vty
, uj
, !!detail
);
4661 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4662 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4663 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4664 "Ethernet Segment\n"
4670 if (!str_to_esi(esi_str
, &esi
)) {
4671 vty_out(vty
, "%% Malformed ESI\n");
4674 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4677 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4683 DEFPY(show_bgp_l2vpn_evpn_nh
,
4684 show_bgp_l2vpn_evpn_nh_cmd
,
4685 "show bgp l2vpn evpn next-hops [json$uj]",
4693 bgp_evpn_nh_show(vty
, uj
);
4699 * Display EVPN neighbor summary.
4701 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4702 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
4705 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4706 "Summary of BGP neighbor status\n"
4707 "Show only sessions in Established state\n"
4708 "Show only sessions not in Established state\n"
4709 "Show only the specified neighbor session\n"
4710 "Neighbor to display information about\n"
4711 "Neighbor to display information about\n"
4712 "Neighbor on BGP configured interface\n"
4713 "Show only the specified remote AS sessions\n"
4715 "Internal (iBGP) AS sessions\n"
4716 "External (eBGP) AS sessions\n"
4717 "Shorten the information on BGP instances\n"
4718 "Increase table width for longer output\n" JSON_STR
)
4723 char *neighbor
= NULL
;
4724 as_t as
= 0; /* 0 means AS filter not set */
4725 int as_type
= AS_UNSPECIFIED
;
4726 uint16_t show_flags
= 0;
4728 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4729 vrf
= argv
[++idx_vrf
]->arg
;
4731 if (argv_find(argv
, argc
, "failed", &idx
))
4732 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4734 if (argv_find(argv
, argc
, "established", &idx
))
4735 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4738 if (argv_find(argv
, argc
, "neighbor", &idx
))
4739 neighbor
= argv
[idx
+ 1]->arg
;
4741 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4742 if (argv
[idx
+ 1]->arg
[0] == 'i')
4743 as_type
= AS_INTERNAL
;
4744 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4745 as_type
= AS_EXTERNAL
;
4747 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4750 if (argv_find(argv
, argc
, "terse", &idx
))
4751 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4753 if (argv_find(argv
, argc
, "wide", &idx
))
4754 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4756 if (use_json(argc
, argv
))
4757 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4759 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4760 as_type
, as
, show_flags
);
4763 static int bgp_evpn_cli_parse_type_cmp(int *type
, const char *type_str
)
4765 if ((strncmp(type_str
, "ma", 2) == 0) || (strmatch(type_str
, "2")))
4766 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4767 else if ((strncmp(type_str
, "mu", 2) == 0) || (strmatch(type_str
, "3")))
4768 *type
= BGP_EVPN_IMET_ROUTE
;
4769 else if ((strncmp(type_str
, "es", 2) == 0) || (strmatch(type_str
, "4")))
4770 *type
= BGP_EVPN_ES_ROUTE
;
4771 else if ((strncmp(type_str
, "ea", 2) == 0) || (strmatch(type_str
, "1")))
4772 *type
= BGP_EVPN_AD_ROUTE
;
4773 else if ((strncmp(type_str
, "p", 1) == 0) || (strmatch(type_str
, "5")))
4774 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4781 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4785 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4786 /* Specific type is requested */
4787 if (bgp_evpn_cli_parse_type_cmp(type
,
4788 argv
[type_idx
+ 1]->arg
) != 0)
4796 * Display global EVPN routing table.
4798 DEFUN(show_bgp_l2vpn_evpn_route
,
4799 show_bgp_l2vpn_evpn_route_cmd
,
4800 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4806 "Display Detailed Information\n"
4808 EVPN_TYPE_ALL_LIST_HELP_STR
4815 json_object
*json
= NULL
;
4817 uj
= use_json(argc
, argv
);
4819 bgp
= bgp_get_evpn();
4824 json
= json_object_new_object();
4826 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4829 if (argv_find(argv
, argc
, "detail", &detail
))
4832 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4835 * This is an extremely expensive operation at scale
4836 * and as such we need to save as much time as is
4840 vty_json_no_pretty(vty
, json
);
4846 * Display global EVPN routing table for specific RD.
4848 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4849 show_bgp_l2vpn_evpn_route_rd_cmd
,
4850 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4856 EVPN_RT_DIST_HELP_STR
4857 EVPN_ASN_IP_HELP_STR
4858 "All VPN Route Distinguishers\n"
4860 EVPN_TYPE_ALL_LIST_HELP_STR
4865 struct prefix_rd prd
;
4868 json_object
*json
= NULL
;
4869 int idx_ext_community
= 0;
4872 bgp
= bgp_get_evpn();
4876 /* check if we need json output */
4877 uj
= use_json(argc
, argv
);
4879 json
= json_object_new_object();
4881 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4883 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4884 &idx_ext_community
)) {
4885 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4888 "%% Malformed Route Distinguisher\n");
4894 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4898 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4900 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4903 vty_json(vty
, json
);
4909 * Display global EVPN routing table for specific RD and MACIP.
4911 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4912 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4913 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4919 EVPN_RT_DIST_HELP_STR
4920 EVPN_ASN_IP_HELP_STR
4921 "All VPN Route Distinguishers\n"
4923 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4925 "IP address (IPv4 or IPv6)\n"
4930 struct prefix_rd prd
;
4933 int idx_ext_community
= 0;
4937 json_object
*json
= NULL
;
4940 memset(&mac
, 0, sizeof(struct ethaddr
));
4941 memset(&ip
, 0, sizeof(struct ipaddr
));
4943 bgp
= bgp_get_evpn();
4947 /* check if we need json output */
4948 uj
= use_json(argc
, argv
);
4950 json
= json_object_new_object();
4953 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4954 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4955 &idx_ext_community
)) {
4956 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4959 "%% Malformed Route Distinguisher\n");
4966 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4967 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4968 vty_out(vty
, "%% Malformed MAC address\n");
4973 /* get the ip if specified */
4974 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4975 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4976 vty_out(vty
, "%% Malformed IP address\n");
4982 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4984 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4987 vty_json(vty
, json
);
4992 /* Display per ESI routing table */
4993 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4994 show_bgp_l2vpn_evpn_route_esi_cmd
,
4995 "show bgp l2vpn evpn route esi ESI [json]",
5001 "Ethernet Segment Identifier\n"
5007 struct bgp
*bgp
= NULL
;
5008 json_object
*json
= NULL
;
5010 memset(&esi
, 0, sizeof(esi
));
5011 bgp
= bgp_get_evpn();
5015 uj
= use_json(argc
, argv
);
5017 json
= json_object_new_object();
5019 /* get the ESI - ESI-ID is at argv[6] */
5020 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
5021 vty_out(vty
, "%% Malformed ESI\n");
5025 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
5028 vty_json(vty
, json
);
5035 * Display per-VNI EVPN routing table.
5037 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
5038 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5044 "VXLAN Network Identifier\n"
5047 EVPN_TYPE_1_HELP_STR
5048 EVPN_TYPE_1_HELP_STR
5049 EVPN_TYPE_2_HELP_STR
5050 EVPN_TYPE_2_HELP_STR
5051 EVPN_TYPE_3_HELP_STR
5052 EVPN_TYPE_3_HELP_STR
5054 "Remote VTEP IP address\n"
5059 struct in_addr vtep_ip
;
5064 json_object
*json
= NULL
;
5066 bgp
= bgp_get_evpn();
5070 /* check if we need json output */
5071 uj
= use_json(argc
, argv
);
5073 json
= json_object_new_object();
5075 if (!argv_find(argv
, argc
, "evpn", &idx
))
5080 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5082 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
5085 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
5086 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
5087 vty_out(vty
, "%% Malformed VTEP IP address\n");
5092 evpn_show_routes_vni(vty
, bgp
, vni
, type
, false, vtep_ip
, json
);
5095 vty_json(vty
, json
);
5101 * Display per-VNI EVPN routing table for specific MACIP.
5103 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
5104 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
5105 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
5111 "VXLAN Network Identifier\n"
5114 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5116 "IP address (IPv4 or IPv6)\n"
5125 json_object
*json
= NULL
;
5127 bgp
= bgp_get_evpn();
5131 /* check if we need json output */
5132 uj
= use_json(argc
, argv
);
5134 json
= json_object_new_object();
5136 if (!argv_find(argv
, argc
, "evpn", &idx
))
5140 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5143 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5144 vty_out(vty
, "%% Malformed MAC address\n");
5149 memset(&ip
, 0, sizeof(ip
));
5150 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5152 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5153 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5154 vty_out(vty
, "%% Malformed IP address\n");
5159 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5162 vty_json(vty
, json
);
5168 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5170 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5171 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5172 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5178 "VXLAN Network Identifier\n"
5180 EVPN_TYPE_3_HELP_STR
5181 "Originating Router IP address\n"
5187 struct in_addr orig_ip
;
5190 json_object
*json
= NULL
;
5192 bgp
= bgp_get_evpn();
5196 /* check if we need json output */
5197 uj
= use_json(argc
, argv
);
5199 json
= json_object_new_object();
5201 if (!argv_find(argv
, argc
, "evpn", &idx
))
5205 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5208 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5210 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5214 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5217 vty_json(vty
, json
);
5223 * Display per-VNI EVPN routing table - for all VNIs.
5225 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5226 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5227 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5233 "VXLAN Network Identifier\n"
5235 "Print Detailed Output\n"
5237 "Remote VTEP IP address\n"
5241 struct in_addr vtep_ip
;
5244 json_object
*json
= NULL
;
5245 /* Detail Adjust. Adjust indexes according to detail option */
5248 bgp
= bgp_get_evpn();
5252 /* check if we need json output */
5253 uj
= use_json(argc
, argv
);
5255 json
= json_object_new_object();
5257 if (!argv_find(argv
, argc
, "evpn", &idx
))
5260 if (argv_find(argv
, argc
, "detail", &da
))
5263 /* vtep-ip position depends on detail option */
5265 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5267 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5268 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5269 vty_out(vty
, "%% Malformed VTEP IP address\n");
5274 evpn_show_routes_vni_all(vty
, bgp
, 0, false, vtep_ip
, json
, da
);
5277 vty_json(vty
, json
);
5278 json_object_free(json
);
5285 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5287 DEFPY(show_bgp_vni_all
,
5288 show_bgp_vni_all_cmd
,
5289 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5300 json_object
*json
= NULL
;
5302 bgp
= bgp_get_evpn();
5306 /* check if we need json output */
5308 json
= json_object_new_object();
5310 evpn_show_routes_vni_all_type_all(vty
, bgp
, addr
, json
, !!detail
);
5313 vty_json(vty
, json
);
5319 * Display per-VNI EVPN EAD routing table - for all VNIs.
5321 DEFPY(show_bgp_vni_all_ead
,
5322 show_bgp_vni_all_ead_cmd
,
5323 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5329 EVPN_TYPE_1_HELP_STR
5330 EVPN_TYPE_1_HELP_STR
5337 json_object
*json
= NULL
;
5339 bgp
= bgp_get_evpn();
5343 /* check if we need json output */
5345 json
= json_object_new_object();
5347 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_AD_ROUTE
, false, addr
, json
,
5351 vty_json(vty
, json
);
5357 * Display per-VNI EVPN MAC routing table - for all VNIs.
5359 DEFPY(show_bgp_vni_all_macip_mac
,
5360 show_bgp_vni_all_macip_mac_cmd
,
5361 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5367 EVPN_TYPE_2_HELP_STR
5368 EVPN_TYPE_2_HELP_STR
5376 json_object
*json
= NULL
;
5378 bgp
= bgp_get_evpn();
5382 /* check if we need json output */
5384 json
= json_object_new_object();
5386 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5390 vty_json(vty
, json
);
5396 * Display per-VNI EVPN IP routing table - for all VNIs.
5398 DEFPY(show_bgp_vni_all_macip_ip
,
5399 show_bgp_vni_all_macip_ip_cmd
,
5400 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5406 EVPN_TYPE_2_HELP_STR
5407 EVPN_TYPE_2_HELP_STR
5415 json_object
*json
= NULL
;
5417 bgp
= bgp_get_evpn();
5421 /* check if we need json output */
5423 json
= json_object_new_object();
5425 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5429 vty_json(vty
, json
);
5435 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5437 DEFPY(show_bgp_vni_all_imet
,
5438 show_bgp_vni_all_imet_cmd
,
5439 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5445 EVPN_TYPE_3_HELP_STR
5446 EVPN_TYPE_3_HELP_STR
5453 json_object
*json
= NULL
;
5455 bgp
= bgp_get_evpn();
5459 /* check if we need json output */
5461 json
= json_object_new_object();
5463 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5467 vty_json(vty
, json
);
5473 * Display per-VNI EVPN ALL routing tables - for select VNI
5477 "show bgp vni "CMD_VNI_RANGE
"$vni [vtep A.B.C.D$addr] [json$uj]",
5487 json_object
*json
= NULL
;
5488 json_object
*json_mac
= NULL
;
5490 bgp
= bgp_get_evpn();
5494 /* check if we need json output */
5496 json
= json_object_new_object();
5497 json_mac
= json_object_new_object();
5500 evpn_show_routes_vni(vty
, bgp
, vni
, 0, false, addr
, json
);
5503 vty_out(vty
, "\n\nMAC Table:\n\n");
5505 evpn_show_routes_vni(vty
, bgp
, vni
, 0, true, addr
, json_mac
);
5508 json_object_object_add(json
, "macTable", json_mac
);
5509 vty_json(vty
, json
);
5516 * Display per-VNI EVPN EAD routing table - for select VNI
5518 DEFPY(show_bgp_vni_ead
,
5519 show_bgp_vni_ead_cmd
,
5520 "show bgp vni "CMD_VNI_RANGE
"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5526 EVPN_TYPE_1_HELP_STR
5527 EVPN_TYPE_1_HELP_STR
5533 json_object
*json
= NULL
;
5535 bgp
= bgp_get_evpn();
5539 /* check if we need json output */
5541 json
= json_object_new_object();
5543 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_AD_ROUTE
, false, addr
,
5547 vty_json(vty
, json
);
5553 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5555 DEFPY(show_bgp_vni_macip_mac
,
5556 show_bgp_vni_macip_mac_cmd
,
5557 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5563 EVPN_TYPE_2_HELP_STR
5564 EVPN_TYPE_2_HELP_STR
5571 json_object
*json
= NULL
;
5573 bgp
= bgp_get_evpn();
5577 /* check if we need json output */
5579 json
= json_object_new_object();
5581 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5585 vty_json(vty
, json
);
5591 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5593 DEFPY(show_bgp_vni_macip_ip
,
5594 show_bgp_vni_macip_ip_cmd
,
5595 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5601 EVPN_TYPE_2_HELP_STR
5602 EVPN_TYPE_2_HELP_STR
5609 json_object
*json
= NULL
;
5611 bgp
= bgp_get_evpn();
5615 /* check if we need json output */
5617 json
= json_object_new_object();
5619 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5623 vty_json(vty
, json
);
5629 * Display per-VNI EVPN Multicast routing table - for select VNI
5631 DEFPY(show_bgp_vni_imet
,
5632 show_bgp_vni_imet_cmd
,
5633 "show bgp vni "CMD_VNI_RANGE
"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5639 EVPN_TYPE_3_HELP_STR
5640 EVPN_TYPE_3_HELP_STR
5646 json_object
*json
= NULL
;
5648 bgp
= bgp_get_evpn();
5652 /* check if we need json output */
5654 json
= json_object_new_object();
5656 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5660 vty_json(vty
, json
);
5666 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5668 DEFPY(show_bgp_vni_macip_mac_addr
,
5669 show_bgp_vni_macip_mac_addr_cmd
,
5670 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5676 EVPN_TYPE_2_HELP_STR
5677 EVPN_TYPE_2_HELP_STR
5683 json_object
*json
= NULL
;
5685 bgp
= bgp_get_evpn();
5689 /* check if we need json output */
5691 json
= json_object_new_object();
5693 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
->eth_addr
, NULL
, json
);
5696 vty_json(vty
, json
);
5702 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5704 DEFPY(show_bgp_vni_macip_ip_addr
, show_bgp_vni_macip_ip_addr_cmd
,
5705 "show bgp vni " CMD_VNI_RANGE
5706 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5707 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5708 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5709 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR
)
5712 json_object
*json
= NULL
;
5713 struct ipaddr ip_addr
= {.ipa_type
= IPADDR_NONE
};
5715 bgp
= bgp_get_evpn();
5719 /* check if we need json output */
5721 json
= json_object_new_object();
5723 if (sockunion_family(ip
) == AF_INET
) {
5724 ip_addr
.ipa_type
= IPADDR_V4
;
5725 ip_addr
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
5727 ip_addr
.ipa_type
= IPADDR_V6
;
5728 memcpy(&ip_addr
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
5729 sizeof(struct in6_addr
));
5731 evpn_show_route_vni_macip(vty
, bgp
, vni
, NULL
, &ip_addr
, json
);
5734 vty_json(vty
, json
);
5740 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5741 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5742 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5743 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5744 "EVPN route information\n"
5745 "MAC IP routes in the EVI tables linked to the ES\n"
5747 "Detailed information\n" JSON_STR
)
5751 json_object
*json
= NULL
;
5754 if (!str_to_esi(esi_str
, &esi
)) {
5755 vty_out(vty
, "%% Malformed ESI\n");
5764 json
= json_object_new_object();
5765 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5767 vty_json(vty
, json
);
5773 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5774 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5775 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5776 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5777 "EVPN route information\n"
5778 "MAC IP routes in the global table linked to the ES\n"
5780 "Detailed information\n" JSON_STR
)
5784 json_object
*json
= NULL
;
5787 if (!str_to_esi(esi_str
, &esi
)) {
5788 vty_out(vty
, "%% Malformed ESI\n");
5797 json
= json_object_new_object();
5798 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5800 vty_json(vty
, json
);
5806 * Display EVPN import route-target hash table
5808 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5809 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5810 "show bgp l2vpn evpn vrf-import-rt [json]",
5815 "Show vrf import route target\n"
5819 struct bgp
*bgp_evpn
= NULL
;
5820 json_object
*json
= NULL
;
5822 bgp_evpn
= bgp_get_evpn();
5826 uj
= use_json(argc
, argv
);
5828 json
= json_object_new_object();
5830 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5833 vty_json(vty
, json
);
5839 * Display EVPN import route-target hash table
5841 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5842 show_bgp_l2vpn_evpn_import_rt_cmd
,
5843 "show bgp l2vpn evpn import-rt [json]",
5848 "Show import route target\n"
5853 json_object
*json
= NULL
;
5855 bgp
= bgp_get_evpn();
5859 uj
= use_json(argc
, argv
);
5861 json
= json_object_new_object();
5863 evpn_show_import_rts(vty
, bgp
, json
);
5866 vty_json(vty
, json
);
5871 DEFPY_HIDDEN(test_es_add
,
5873 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5876 "Ethernet-segment\n"
5877 "Ethernet-Segment Identifier\n"
5885 struct in_addr vtep_ip
;
5888 bgp
= bgp_get_evpn();
5890 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5894 if (!str_to_esi(esi_str
, &esi
)) {
5895 vty_out(vty
, "%% Malformed ESI\n");
5900 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5902 vty_out(vty
, "%% Failed to delete ES\n");
5906 if (state_str
&& !strcmp(state_str
, "up"))
5910 vtep_ip
= bgp
->router_id
;
5912 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5913 EVPN_MH_DF_PREF_MIN
, false);
5915 vty_out(vty
, "%% Failed to add ES\n");
5922 DEFPY_HIDDEN(test_es_vni_add
,
5923 test_es_vni_add_cmd
,
5924 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5927 "Ethernet-segment\n"
5928 "Ethernet-Segment Identifier\n"
5937 bgp
= bgp_get_evpn();
5939 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5943 if (!str_to_esi(esi_str
, &esi
)) {
5944 vty_out(vty
, "%% Malformed ESI\n");
5949 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5951 vty_out(vty
, "%% Failed to deref ES VNI\n");
5955 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5957 vty_out(vty
, "%% Failed to ref ES VNI\n");
5964 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5965 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5969 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5970 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5971 "Summary of BGP neighbor status\n" JSON_STR
)
5973 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5974 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5975 SHOW_STR BGP_STR EVPN_HELP_STR
5977 "Display Detailed Information\n"
5979 EVPN_TYPE_2_HELP_STR
5980 EVPN_TYPE_2_HELP_STR
5981 EVPN_TYPE_3_HELP_STR
5982 EVPN_TYPE_3_HELP_STR
)
5985 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5986 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5987 SHOW_STR BGP_STR EVPN_HELP_STR
5989 EVPN_RT_DIST_HELP_STR
5990 EVPN_ASN_IP_HELP_STR
5992 EVPN_TYPE_2_HELP_STR
5993 EVPN_TYPE_2_HELP_STR
5994 EVPN_TYPE_3_HELP_STR
5995 EVPN_TYPE_3_HELP_STR
)
5998 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5999 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
6000 SHOW_STR BGP_STR EVPN_HELP_STR
6002 EVPN_RT_DIST_HELP_STR
6003 EVPN_ASN_IP_HELP_STR
6005 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6007 "IP address (IPv4 or IPv6)\n")
6010 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
6011 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
6012 SHOW_STR BGP_STR EVPN_HELP_STR
6014 "VXLAN Network Identifier\n"
6017 EVPN_TYPE_2_HELP_STR
6018 EVPN_TYPE_2_HELP_STR
6019 EVPN_TYPE_3_HELP_STR
6020 EVPN_TYPE_3_HELP_STR
6022 "Remote VTEP IP address\n")
6024 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
6025 show_bgp_evpn_route_vni_macip_cmd
,
6026 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
6027 SHOW_STR BGP_STR EVPN_HELP_STR
6029 "VXLAN Network Identifier\n"
6032 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6034 "IP address (IPv4 or IPv6)\n")
6036 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
6037 show_bgp_evpn_route_vni_multicast_cmd
,
6038 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
6039 SHOW_STR BGP_STR EVPN_HELP_STR
6041 "VXLAN Network Identifier\n"
6043 EVPN_TYPE_3_HELP_STR
6044 "Originating Router IP address\n")
6046 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
6047 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6048 SHOW_STR BGP_STR EVPN_HELP_STR
6050 "VXLAN Network Identifier\n"
6052 "Print Detailed Output\n"
6054 "Remote VTEP IP address\n")
6056 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
6057 "show bgp evpn import-rt",
6058 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
6060 DEFUN_NOSH (bgp_evpn_vni
,
6062 "vni " CMD_VNI_RANGE
,
6063 "VXLAN Network Identifier\n"
6067 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6068 struct bgpevpn
*vpn
;
6073 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
6075 /* Create VNI, or mark as configured. */
6076 vpn
= evpn_create_update_vni(bgp
, vni
);
6078 vty_out(vty
, "%% Failed to create VNI \n");
6082 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
6086 DEFUN (no_bgp_evpn_vni
,
6087 no_bgp_evpn_vni_cmd
,
6088 "no vni " CMD_VNI_RANGE
,
6090 "VXLAN Network Identifier\n"
6094 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6095 struct bgpevpn
*vpn
;
6100 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
6102 /* Check if we should disallow. */
6103 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
6105 vty_out(vty
, "%% Specified VNI does not exist\n");
6108 if (!is_vni_configured(vpn
)) {
6109 vty_out(vty
, "%% Specified VNI is not configured\n");
6113 evpn_delete_vni(bgp
, vpn
);
6117 DEFUN_NOSH (exit_vni
,
6120 "Exit from VNI mode\n")
6122 if (vty
->node
== BGP_EVPN_VNI_NODE
)
6123 vty
->node
= BGP_EVPN_NODE
;
6127 DEFUN (bgp_evpn_vrf_rd
,
6128 bgp_evpn_vrf_rd_cmd
,
6129 "rd ASN:NN_OR_IP-ADDRESS:NN",
6130 EVPN_RT_DIST_HELP_STR
6131 EVPN_ASN_IP_HELP_STR
)
6134 struct prefix_rd prd
;
6135 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6140 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6142 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6146 /* If same as existing value, there is nothing more to do. */
6147 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
6150 /* Configure or update the RD. */
6151 evpn_configure_vrf_rd(bgp_vrf
, &prd
, argv
[1]->arg
);
6155 DEFUN (no_bgp_evpn_vrf_rd
,
6156 no_bgp_evpn_vrf_rd_cmd
,
6157 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6159 EVPN_RT_DIST_HELP_STR
6160 EVPN_ASN_IP_HELP_STR
)
6163 struct prefix_rd prd
;
6164 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6169 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6171 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6175 /* Check if we should disallow. */
6176 if (!is_vrf_rd_configured(bgp_vrf
)) {
6177 vty_out(vty
, "%% RD is not configured for this VRF\n");
6181 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
6183 "%% RD specified does not match configuration for this VRF\n");
6187 evpn_unconfigure_vrf_rd(bgp_vrf
);
6191 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
6192 no_bgp_evpn_vrf_rd_without_val_cmd
,
6195 EVPN_RT_DIST_HELP_STR
)
6197 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6202 /* Check if we should disallow. */
6203 if (!is_vrf_rd_configured(bgp_vrf
)) {
6204 vty_out(vty
, "%% RD is not configured for this VRF\n");
6208 evpn_unconfigure_vrf_rd(bgp_vrf
);
6212 DEFUN (bgp_evpn_vni_rd
,
6213 bgp_evpn_vni_rd_cmd
,
6214 "rd ASN:NN_OR_IP-ADDRESS:NN",
6215 EVPN_RT_DIST_HELP_STR
6216 EVPN_ASN_IP_HELP_STR
)
6218 struct prefix_rd prd
;
6219 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6220 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6226 if (!EVPN_ENABLED(bgp
)) {
6228 "This command is only supported under EVPN VRF\n");
6232 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6234 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6238 /* If same as existing value, there is nothing more to do. */
6239 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
6242 /* Configure or update the RD. */
6243 evpn_configure_rd(bgp
, vpn
, &prd
, argv
[1]->arg
);
6247 DEFUN (no_bgp_evpn_vni_rd
,
6248 no_bgp_evpn_vni_rd_cmd
,
6249 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6251 EVPN_RT_DIST_HELP_STR
6252 EVPN_ASN_IP_HELP_STR
)
6254 struct prefix_rd prd
;
6255 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6256 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6262 if (!EVPN_ENABLED(bgp
)) {
6264 "This command is only supported under EVPN VRF\n");
6268 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6270 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6274 /* Check if we should disallow. */
6275 if (!is_rd_configured(vpn
)) {
6276 vty_out(vty
, "%% RD is not configured for this VNI\n");
6280 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
6282 "%% RD specified does not match configuration for this VNI\n");
6286 evpn_unconfigure_rd(bgp
, vpn
);
6290 DEFUN (no_bgp_evpn_vni_rd_without_val
,
6291 no_bgp_evpn_vni_rd_without_val_cmd
,
6294 EVPN_RT_DIST_HELP_STR
)
6296 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6297 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6302 if (!EVPN_ENABLED(bgp
)) {
6304 "This command is only supported under EVPN VRF\n");
6308 /* Check if we should disallow. */
6309 if (!is_rd_configured(vpn
)) {
6310 vty_out(vty
, "%% RD is not configured for this VNI\n");
6314 evpn_unconfigure_rd(bgp
, vpn
);
6319 * Loop over all extended-communities in the route-target list rtl and
6320 * return 1 if we find ecomtarget
6322 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
6323 struct ecommunity
*ecomtarget
)
6325 struct listnode
*node
;
6326 struct ecommunity
*ecom
;
6328 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
6329 if (ecommunity_match(ecom
, ecomtarget
))
6337 * L3 RT version of above.
6339 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
6340 struct ecommunity
*ecomtarget
)
6342 struct listnode
*node
;
6343 struct vrf_route_target
*l3rt
;
6345 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
6346 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
6353 /* display L3VNI related info for a VRF instance */
6354 DEFUN (show_bgp_vrf_l3vni_info
,
6355 show_bgp_vrf_l3vni_info_cmd
,
6356 "show bgp vrf VRFNAME vni [json]",
6364 char buf
[ETHER_ADDR_STRLEN
];
6366 const char *name
= NULL
;
6367 struct bgp
*bgp
= NULL
;
6368 struct listnode
*node
= NULL
;
6369 struct bgpevpn
*vpn
= NULL
;
6370 struct vrf_route_target
*l3rt
;
6371 json_object
*json
= NULL
;
6372 json_object
*json_vnis
= NULL
;
6373 json_object
*json_export_rts
= NULL
;
6374 json_object
*json_import_rts
= NULL
;
6375 bool uj
= use_json(argc
, argv
);
6378 json
= json_object_new_object();
6379 json_vnis
= json_object_new_array();
6380 json_export_rts
= json_object_new_array();
6381 json_import_rts
= json_object_new_array();
6384 name
= argv
[idx_vrf
]->arg
;
6385 bgp
= bgp_lookup_by_name(name
);
6386 if (strmatch(name
, VRF_DEFAULT_NAME
))
6387 bgp
= bgp_get_default();
6391 vty_out(vty
, "BGP instance for VRF %s not found\n",
6394 json_object_string_add(json
, "warning",
6395 "BGP instance not found");
6396 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
6397 json_object_free(json
);
6403 vty_out(vty
, "BGP VRF: %s\n", name
);
6404 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
6405 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
6406 vty_out(vty
, " Rmac: %s\n",
6407 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6408 vty_out(vty
, " VNI Filter: %s\n",
6409 CHECK_FLAG(bgp
->vrf_flags
,
6410 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6411 ? "prefix-routes-only"
6413 vty_out(vty
, " L2-VNI List:\n");
6415 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6416 vty_out(vty
, "%u ", vpn
->vni
);
6418 vty_out(vty
, " Export-RTs:\n");
6420 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6421 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6423 vty_out(vty
, " Import-RTs:\n");
6425 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6426 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6428 vty_out(vty
, " RD: ");
6429 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
), &bgp
->vrf_prd
);
6432 json_object_string_add(json
, "vrf", name
);
6433 json_object_string_addf(json
, "local-ip", "%pI4",
6434 &bgp
->originator_ip
);
6435 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
6436 json_object_string_add(
6438 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6439 json_object_string_add(
6441 CHECK_FLAG(bgp
->vrf_flags
,
6442 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6443 ? "prefix-routes-only"
6445 /* list of l2vnis */
6446 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6447 json_object_array_add(json_vnis
,
6448 json_object_new_int(vpn
->vni
));
6449 json_object_object_add(json
, "l2vnis", json_vnis
);
6452 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6453 json_object_array_add(
6455 json_object_new_string(
6456 ecommunity_str(l3rt
->ecom
)));
6457 json_object_object_add(json
, "export-rts", json_export_rts
);
6460 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6461 json_object_array_add(
6463 json_object_new_string(
6464 ecommunity_str(l3rt
->ecom
)));
6465 json_object_object_add(json
, "import-rts", json_import_rts
);
6466 json_object_string_addf(json
, "rd",
6467 BGP_RD_AS_FORMAT(bgp
->asnotation
),
6472 vty_json(vty
, json
);
6476 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
6479 /* Do nothing if we already have this route-target */
6481 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6483 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
6488 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6490 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
6498 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
6500 /* Verify we already have this route-target */
6502 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6506 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
6508 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6512 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
6518 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
6519 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
6522 int ret
= CMD_SUCCESS
;
6523 bool is_wildcard
= false;
6524 struct ecommunity
*ecom
= NULL
;
6526 for (int i
= rt_idx
; i
< argc
; i
++) {
6527 is_wildcard
= false;
6530 * Special handling for wildcard '*' here.
6532 * Let's just convert it to 0 here so we dont have to modify
6533 * the ecommunity parser.
6535 if ((argv
[i
]->arg
)[0] == '*') {
6536 (argv
[i
]->arg
)[0] = '0';
6540 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
6543 /* Put it back as was */
6545 (argv
[i
]->arg
)[0] = '*';
6548 vty_out(vty
, "%% Malformed Route Target list\n");
6553 ecommunity_str(ecom
);
6556 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
6558 "%% RT specified already configured for this VRF: %s\n",
6560 ecommunity_free(&ecom
);
6565 if (del_rt(bgp
, ecom
, is_import
) != 0) {
6567 "%% RT specified does not match configuration for this VRF: %s\n",
6572 ecommunity_free(&ecom
);
6579 /* import/export rt for l3vni-vrf */
6580 DEFUN (bgp_evpn_vrf_rt
,
6581 bgp_evpn_vrf_rt_cmd
,
6582 "route-target <both|import|export> RTLIST...",
6584 "import and export\n"
6587 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6589 int ret
= CMD_SUCCESS
;
6590 int tmp_ret
= CMD_SUCCESS
;
6592 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6595 return CMD_WARNING_CONFIG_FAILED
;
6597 if (!strcmp(argv
[1]->arg
, "import"))
6598 rt_type
= RT_TYPE_IMPORT
;
6599 else if (!strcmp(argv
[1]->arg
, "export"))
6600 rt_type
= RT_TYPE_EXPORT
;
6601 else if (!strcmp(argv
[1]->arg
, "both"))
6602 rt_type
= RT_TYPE_BOTH
;
6604 vty_out(vty
, "%% Invalid Route Target type\n");
6605 return CMD_WARNING_CONFIG_FAILED
;
6608 if (strmatch(argv
[2]->arg
, "auto")) {
6609 vty_out(vty
, "%% `auto` cannot be configured via list\n");
6610 return CMD_WARNING_CONFIG_FAILED
;
6613 if (rt_type
!= RT_TYPE_IMPORT
) {
6614 for (int i
= 2; i
< argc
; i
++) {
6615 if ((argv
[i
]->arg
)[0] == '*') {
6617 "%% Wildcard '*' only applicable for import\n");
6618 return CMD_WARNING_CONFIG_FAILED
;
6623 /* Add/update the import route-target */
6624 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6625 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
6627 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6630 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6631 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
6633 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6639 DEFPY (bgp_evpn_vrf_rt_auto
,
6640 bgp_evpn_vrf_rt_auto_cmd
,
6641 "route-target <both|import|export>$type auto",
6643 "import and export\n"
6646 "Automatically derive route target\n")
6648 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6652 return CMD_WARNING_CONFIG_FAILED
;
6654 if (strmatch(type
, "import"))
6655 rt_type
= RT_TYPE_IMPORT
;
6656 else if (strmatch(type
, "export"))
6657 rt_type
= RT_TYPE_EXPORT
;
6658 else if (strmatch(type
, "both"))
6659 rt_type
= RT_TYPE_BOTH
;
6661 vty_out(vty
, "%% Invalid Route Target type\n");
6662 return CMD_WARNING_CONFIG_FAILED
;
6665 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6666 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6668 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6669 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6674 DEFUN (no_bgp_evpn_vrf_rt
,
6675 no_bgp_evpn_vrf_rt_cmd
,
6676 "no route-target <both|import|export> RTLIST...",
6679 "import and export\n"
6682 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6684 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6685 int ret
= CMD_SUCCESS
;
6686 int tmp_ret
= CMD_SUCCESS
;
6690 return CMD_WARNING_CONFIG_FAILED
;
6692 if (!strcmp(argv
[2]->arg
, "import"))
6693 rt_type
= RT_TYPE_IMPORT
;
6694 else if (!strcmp(argv
[2]->arg
, "export"))
6695 rt_type
= RT_TYPE_EXPORT
;
6696 else if (!strcmp(argv
[2]->arg
, "both"))
6697 rt_type
= RT_TYPE_BOTH
;
6699 vty_out(vty
, "%% Invalid Route Target type\n");
6700 return CMD_WARNING_CONFIG_FAILED
;
6703 if (!strcmp(argv
[3]->arg
, "auto")) {
6704 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6705 return CMD_WARNING_CONFIG_FAILED
;
6708 if (rt_type
== RT_TYPE_IMPORT
) {
6709 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6711 "%% Import RT is not configured for this VRF\n");
6712 return CMD_WARNING_CONFIG_FAILED
;
6714 } else if (rt_type
== RT_TYPE_EXPORT
) {
6715 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6717 "%% Export RT is not configured for this VRF\n");
6718 return CMD_WARNING_CONFIG_FAILED
;
6720 } else if (rt_type
== RT_TYPE_BOTH
) {
6721 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6722 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6724 "%% Import/Export RT is not configured for this VRF\n");
6725 return CMD_WARNING_CONFIG_FAILED
;
6729 if (rt_type
!= RT_TYPE_IMPORT
) {
6730 for (int i
= 3; i
< argc
; i
++) {
6731 if ((argv
[i
]->arg
)[0] == '*') {
6733 "%% Wildcard '*' only applicable for import\n");
6734 return CMD_WARNING_CONFIG_FAILED
;
6739 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6740 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6742 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6745 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6746 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6748 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6754 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6755 no_bgp_evpn_vrf_rt_auto_cmd
,
6756 "no route-target <both|import|export>$type auto",
6759 "import and export\n"
6762 "Automatically derive route target\n")
6764 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6768 return CMD_WARNING_CONFIG_FAILED
;
6770 if (strmatch(type
, "import"))
6771 rt_type
= RT_TYPE_IMPORT
;
6772 else if (strmatch(type
, "export"))
6773 rt_type
= RT_TYPE_EXPORT
;
6774 else if (strmatch(type
, "both"))
6775 rt_type
= RT_TYPE_BOTH
;
6777 vty_out(vty
, "%% Invalid Route Target type\n");
6778 return CMD_WARNING_CONFIG_FAILED
;
6781 if (rt_type
== RT_TYPE_IMPORT
) {
6782 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6784 "%% Import AUTO RT is not configured for this VRF\n");
6785 return CMD_WARNING_CONFIG_FAILED
;
6787 } else if (rt_type
== RT_TYPE_EXPORT
) {
6788 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6790 "%% Export AUTO RT is not configured for this VRF\n");
6791 return CMD_WARNING_CONFIG_FAILED
;
6793 } else if (rt_type
== RT_TYPE_BOTH
) {
6794 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6795 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6797 "%% Import/Export AUTO RT is not configured for this VRF\n");
6798 return CMD_WARNING_CONFIG_FAILED
;
6802 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6803 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6805 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6806 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6811 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6812 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6814 "EAD ES fragment config\n"
6815 "EVIs per-fragment\n"
6818 bgp_mh_info
->evi_per_es_frag
=
6819 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6824 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6825 "ead-es-route-target export RT",
6826 "EAD ES Route Target\n"
6828 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6830 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6831 struct ecommunity
*ecomadd
= NULL
;
6836 if (!EVPN_ENABLED(bgp
)) {
6837 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6841 /* Add/update the export route-target */
6842 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6844 vty_out(vty
, "%% Malformed Route Target list\n");
6847 ecommunity_str(ecomadd
);
6849 /* Do nothing if we already have this export route-target */
6850 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6852 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6857 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6858 "no ead-es-route-target export RT",
6860 "EAD ES Route Target\n"
6861 "export\n" EVPN_ASN_IP_HELP_STR
)
6863 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6864 struct ecommunity
*ecomdel
= NULL
;
6869 if (!EVPN_ENABLED(bgp
)) {
6870 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6874 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6876 vty_out(vty
, "%% Malformed Route Target list\n");
6879 ecommunity_str(ecomdel
);
6881 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6883 ecommunity_free(&ecomdel
);
6885 "%% RT specified does not match EAD-ES RT configuration\n");
6888 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6893 DEFUN (bgp_evpn_vni_rt
,
6894 bgp_evpn_vni_rt_cmd
,
6895 "route-target <both|import|export> RT",
6897 "import and export\n"
6900 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6902 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6903 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6905 struct ecommunity
*ecomadd
= NULL
;
6910 if (!EVPN_ENABLED(bgp
)) {
6912 "This command is only supported under EVPN VRF\n");
6916 if (!strcmp(argv
[1]->text
, "import"))
6917 rt_type
= RT_TYPE_IMPORT
;
6918 else if (!strcmp(argv
[1]->text
, "export"))
6919 rt_type
= RT_TYPE_EXPORT
;
6920 else if (!strcmp(argv
[1]->text
, "both"))
6921 rt_type
= RT_TYPE_BOTH
;
6923 vty_out(vty
, "%% Invalid Route Target type\n");
6927 /* Add/update the import route-target */
6928 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6929 /* Note that first of the two RTs is created for "both" type */
6930 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6931 ECOMMUNITY_ROUTE_TARGET
, 0);
6933 vty_out(vty
, "%% Malformed Route Target list\n");
6936 ecommunity_str(ecomadd
);
6938 /* Do nothing if we already have this import route-target */
6939 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6940 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6943 /* Add/update the export route-target */
6944 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6945 /* Note that second of the two RTs is created for "both" type */
6946 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6947 ECOMMUNITY_ROUTE_TARGET
, 0);
6949 vty_out(vty
, "%% Malformed Route Target list\n");
6952 ecommunity_str(ecomadd
);
6954 /* Do nothing if we already have this export route-target */
6955 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6956 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6962 DEFUN (no_bgp_evpn_vni_rt
,
6963 no_bgp_evpn_vni_rt_cmd
,
6964 "no route-target <both|import|export> RT",
6967 "import and export\n"
6970 EVPN_ASN_IP_HELP_STR
)
6972 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6973 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6974 int rt_type
, found_ecomdel
;
6975 struct ecommunity
*ecomdel
= NULL
;
6980 if (!EVPN_ENABLED(bgp
)) {
6982 "This command is only supported under EVPN VRF\n");
6986 if (!strcmp(argv
[2]->text
, "import"))
6987 rt_type
= RT_TYPE_IMPORT
;
6988 else if (!strcmp(argv
[2]->text
, "export"))
6989 rt_type
= RT_TYPE_EXPORT
;
6990 else if (!strcmp(argv
[2]->text
, "both"))
6991 rt_type
= RT_TYPE_BOTH
;
6993 vty_out(vty
, "%% Invalid Route Target type\n");
6997 /* The user did "no route-target import", check to see if there are any
6998 * import route-targets configured. */
6999 if (rt_type
== RT_TYPE_IMPORT
) {
7000 if (!is_import_rt_configured(vpn
)) {
7002 "%% Import RT is not configured for this VNI\n");
7005 } else if (rt_type
== RT_TYPE_EXPORT
) {
7006 if (!is_export_rt_configured(vpn
)) {
7008 "%% Export RT is not configured for this VNI\n");
7011 } else if (rt_type
== RT_TYPE_BOTH
) {
7012 if (!is_import_rt_configured(vpn
)
7013 && !is_export_rt_configured(vpn
)) {
7015 "%% Import/Export RT is not configured for this VNI\n");
7020 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
7022 vty_out(vty
, "%% Malformed Route Target list\n");
7025 ecommunity_str(ecomdel
);
7027 if (rt_type
== RT_TYPE_IMPORT
) {
7028 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7029 ecommunity_free(&ecomdel
);
7031 "%% RT specified does not match configuration for this VNI\n");
7034 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7035 } else if (rt_type
== RT_TYPE_EXPORT
) {
7036 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7037 ecommunity_free(&ecomdel
);
7039 "%% RT specified does not match configuration for this VNI\n");
7042 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7043 } else if (rt_type
== RT_TYPE_BOTH
) {
7046 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7047 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7051 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7052 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7056 if (!found_ecomdel
) {
7057 ecommunity_free(&ecomdel
);
7059 "%% RT specified does not match configuration for this VNI\n");
7067 DEFUN (no_bgp_evpn_vni_rt_without_val
,
7068 no_bgp_evpn_vni_rt_without_val_cmd
,
7069 "no route-target <import|export>",
7075 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
7076 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
7082 if (!EVPN_ENABLED(bgp
)) {
7084 "This command is only supported under EVPN VRF\n");
7088 if (!strcmp(argv
[2]->text
, "import")) {
7089 rt_type
= RT_TYPE_IMPORT
;
7090 } else if (!strcmp(argv
[2]->text
, "export")) {
7091 rt_type
= RT_TYPE_EXPORT
;
7093 vty_out(vty
, "%% Invalid Route Target type\n");
7097 /* Check if we should disallow. */
7098 if (rt_type
== RT_TYPE_IMPORT
) {
7099 if (!is_import_rt_configured(vpn
)) {
7101 "%% Import RT is not configured for this VNI\n");
7105 if (!is_export_rt_configured(vpn
)) {
7107 "%% Export RT is not configured for this VNI\n");
7112 /* Unconfigure the RT. */
7113 if (rt_type
== RT_TYPE_IMPORT
)
7114 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
7116 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
7120 static int vni_cmp(const void **a
, const void **b
)
7122 const struct bgpevpn
*first
= *a
;
7123 const struct bgpevpn
*secnd
= *b
;
7125 return secnd
->vni
- first
->vni
;
7129 * Output EVPN configuration information.
7131 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7134 if (bgp
->advertise_all_vni
)
7135 vty_out(vty
, " advertise-all-vni\n");
7137 if (hashcount(bgp
->vnihash
)) {
7138 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
7139 struct listnode
*ln
;
7140 struct bgpevpn
*data
;
7142 list_sort(vnilist
, vni_cmp
);
7143 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
7144 write_vni_config(vty
, data
);
7146 list_delete(&vnilist
);
7149 if (bgp
->advertise_autort_rfc8365
)
7150 vty_out(vty
, " autort rfc8365-compatible\n");
7152 if (bgp
->advertise_gw_macip
)
7153 vty_out(vty
, " advertise-default-gw\n");
7155 if (bgp
->evpn_info
->advertise_svi_macip
)
7156 vty_out(vty
, " advertise-svi-ip\n");
7158 if (bgp
->resolve_overlay_index
)
7159 vty_out(vty
, " enable-resolve-overlay-index\n");
7161 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
7162 vty_out(vty
, " ead-es-frag evi-limit %u\n",
7163 bgp_mh_info
->evi_per_es_frag
);
7165 if (bgp_mh_info
->host_routes_use_l3nhg
!=
7166 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
7167 if (bgp_mh_info
->host_routes_use_l3nhg
)
7168 vty_out(vty
, " use-es-l3nhg\n");
7170 vty_out(vty
, " no use-es-l3nhg\n");
7173 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
7174 if (bgp_mh_info
->ead_evi_rx
)
7175 vty_out(vty
, " no disable-ead-evi-rx\n");
7177 vty_out(vty
, " disable-ead-evi-rx\n");
7180 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
7181 if (bgp_mh_info
->ead_evi_tx
)
7182 vty_out(vty
, " no disable-ead-evi-tx\n");
7184 vty_out(vty
, " disable-ead-evi-tx\n");
7187 if (!bgp
->evpn_info
->dup_addr_detect
)
7188 vty_out(vty
, " no dup-addr-detection\n");
7190 if (bgp
->evpn_info
->dad_max_moves
!=
7191 EVPN_DAD_DEFAULT_MAX_MOVES
||
7192 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
7193 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
7194 bgp
->evpn_info
->dad_max_moves
,
7195 bgp
->evpn_info
->dad_time
);
7197 if (bgp
->evpn_info
->dad_freeze
) {
7198 if (bgp
->evpn_info
->dad_freeze_time
)
7200 " dup-addr-detection freeze %u\n",
7201 bgp
->evpn_info
->dad_freeze_time
);
7204 " dup-addr-detection freeze permanent\n");
7207 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
7208 vty_out(vty
, " flooding disable\n");
7210 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7211 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
7212 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7213 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
7214 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7217 " advertise ipv4 unicast\n");
7218 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7219 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
7220 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7222 " advertise ipv4 unicast gateway-ip route-map %s\n",
7223 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7225 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
7228 /* EAD ES export route-target */
7229 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
7230 struct ecommunity
*ecom
;
7232 struct listnode
*node
;
7234 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
7237 ecom_str
= ecommunity_ecom2str(
7238 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7239 vty_out(vty
, " ead-es-route-target export %s\n",
7241 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7245 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7246 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
7247 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7249 " advertise ipv6 unicast route-map %s\n",
7250 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7253 " advertise ipv6 unicast\n");
7254 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7255 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
7256 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7258 " advertise ipv6 unicast gateway-ip route-map %s\n",
7259 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7261 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
7264 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7265 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
7266 vty_out(vty
, " default-originate ipv4\n");
7268 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7269 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
7270 vty_out(vty
, " default-originate ipv6\n");
7272 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
7273 if (!bgp
->evpn_info
->advertise_pip
)
7274 vty_out(vty
, " no advertise-pip\n");
7275 if (bgp
->evpn_info
->advertise_pip
) {
7276 if (bgp
->evpn_info
->pip_ip_static
.s_addr
7278 vty_out(vty
, " advertise-pip ip %pI4",
7279 &bgp
->evpn_info
->pip_ip_static
);
7281 bgp
->evpn_info
->pip_rmac_static
))) {
7282 char buf
[ETHER_ADDR_STRLEN
];
7284 vty_out(vty
, " mac %s",
7294 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
7295 vty_out(vty
, " rd %s\n", bgp
->vrf_prd_pretty
);
7297 /* import route-target */
7298 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
7300 struct listnode
*node
, *nnode
;
7301 struct vrf_route_target
*l3rt
;
7303 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
7306 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7309 ecom_str
= ecommunity_ecom2str(
7310 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7312 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
7313 char *vni_str
= NULL
;
7315 vni_str
= strchr(ecom_str
, ':');
7317 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7321 /* Move pointer to vni */
7324 vty_out(vty
, " route-target import *:%s\n",
7328 vty_out(vty
, " route-target import %s\n",
7331 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7335 /* import route-target auto */
7336 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
7337 vty_out(vty
, " route-target import auto\n");
7339 /* export route-target */
7340 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
7342 struct listnode
*node
, *nnode
;
7343 struct vrf_route_target
*l3rt
;
7345 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
7348 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7351 ecom_str
= ecommunity_ecom2str(
7352 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7353 vty_out(vty
, " route-target export %s\n", ecom_str
);
7354 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7358 /* export route-target auto */
7359 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
7360 vty_out(vty
, " route-target export auto\n");
7363 void bgp_ethernetvpn_init(void)
7365 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
7366 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
7367 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
7368 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
7369 install_element(VIEW_NODE
,
7370 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
7371 install_element(VIEW_NODE
,
7372 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
7375 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
7378 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
7379 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
7380 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
7381 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
7382 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
7383 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
7384 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
7385 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
7386 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
7387 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
7388 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
7389 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
7390 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
7391 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
7392 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
7393 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
7394 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
7395 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
7396 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
7397 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
7398 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
7399 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
7400 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
7401 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
7402 install_element(BGP_EVPN_NODE
,
7403 &bgp_evpn_enable_resolve_overlay_index_cmd
);
7406 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
7407 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
7409 /* "show bgp l2vpn evpn" commands. */
7410 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
7411 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
7412 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
7413 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
7414 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
7415 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
7416 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
7417 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
7418 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
7419 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
7420 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
7421 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
7422 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
7423 install_element(VIEW_NODE
,
7424 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
7425 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
7426 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
7427 install_element(VIEW_NODE
,
7428 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
7429 install_element(VIEW_NODE
,
7430 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
7431 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
7432 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
7434 /* "show bgp vni" commands. */
7435 install_element(VIEW_NODE
, &show_bgp_vni_all_cmd
);
7436 install_element(VIEW_NODE
, &show_bgp_vni_all_ead_cmd
);
7437 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_mac_cmd
);
7438 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_ip_cmd
);
7439 install_element(VIEW_NODE
, &show_bgp_vni_all_imet_cmd
);
7440 install_element(VIEW_NODE
, &show_bgp_vni_cmd
);
7441 install_element(VIEW_NODE
, &show_bgp_vni_ead_cmd
);
7442 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_cmd
);
7443 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_cmd
);
7444 install_element(VIEW_NODE
, &show_bgp_vni_imet_cmd
);
7445 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_addr_cmd
);
7446 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_addr_cmd
);
7448 /* "show bgp evpn" commands. */
7449 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
7450 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
7451 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
7452 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
7453 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
7454 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
7455 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
7456 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
7457 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
7458 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
7459 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
7460 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
7462 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
7463 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
7464 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
7465 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
7466 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
7467 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
7468 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
7469 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
7470 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
7471 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
7472 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
7473 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
7474 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
7475 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
7476 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
7477 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
7478 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
7479 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
7480 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
7481 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
7482 install_element(BGP_EVPN_VNI_NODE
,
7483 &bgp_evpn_advertise_default_gw_vni_cmd
);
7484 install_element(BGP_EVPN_VNI_NODE
,
7485 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
7486 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
7487 install_element(BGP_EVPN_VNI_NODE
,
7488 &no_bgp_evpn_advertise_vni_subnet_cmd
);