1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Ethernet-VPN Packet and vty Processing File
3 * Copyright (C) 2017 6WIND
5 * This file is part of FRRouting
12 #include "lib/printfrr.h"
13 #include "lib/vxlan.h"
16 #include "bgpd/bgpd.h"
17 #include "bgpd/bgp_table.h"
18 #include "bgpd/bgp_attr.h"
19 #include "bgpd/bgp_route.h"
20 #include "bgpd/bgp_mplsvpn.h"
21 #include "bgpd/bgp_vpn.h"
22 #include "bgpd/bgp_evpn_vty.h"
23 #include "bgpd/bgp_evpn.h"
24 #include "bgpd/bgp_evpn_private.h"
25 #include "bgpd/bgp_evpn_mh.h"
26 #include "bgpd/bgp_zebra.h"
27 #include "bgpd/bgp_vty.h"
28 #include "bgpd/bgp_errors.h"
29 #include "bgpd/bgp_ecommunity.h"
30 #include "bgpd/bgp_lcommunity.h"
31 #include "bgpd/bgp_community.h"
33 #define SHOW_DISPLAY_STANDARD 0
34 #define SHOW_DISPLAY_TAGS 1
35 #define SHOW_DISPLAY_OVERLAY 2
36 #define VNI_STR_LEN 32
39 * Context for VNI hash walk - used by callbacks.
44 struct in_addr vtep_ip
;
51 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
52 enum overlay_index_type
*oly
)
54 *oly
= OVERLAY_INDEX_TYPE_NONE
;
55 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
56 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
60 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
64 uint8_t type
, sub_type
;
65 struct ecommunity_as eas
;
66 struct ecommunity_ip eip
;
67 struct listnode
*node
, *nnode
;
68 struct bgp
*tmp_bgp_vrf
= NULL
;
69 json_object
*json_rt
= NULL
;
70 json_object
*json_vrfs
= NULL
;
71 char rt_buf
[RT_ADDRSTRLEN
];
74 json_rt
= json_object_new_object();
75 json_vrfs
= json_object_new_array();
78 pnt
= (uint8_t *)&irt
->rt
.val
;
81 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
84 memset(&eas
, 0, sizeof(eas
));
86 case ECOMMUNITY_ENCODE_AS
:
87 eas
.as
= (*pnt
++ << 8);
89 ptr_get_be32(pnt
, &eas
.val
);
91 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
94 json_object_string_add(json_rt
, "rt", rt_buf
);
96 vty_out(vty
, "Route-target: %s", rt_buf
);
100 case ECOMMUNITY_ENCODE_IP
:
101 memcpy(&eip
.ip
, pnt
, 4);
103 eip
.val
= (*pnt
++ << 8);
106 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
109 json_object_string_add(json_rt
, "rt", rt_buf
);
111 vty_out(vty
, "Route-target: %s", rt_buf
);
115 case ECOMMUNITY_ENCODE_AS4
:
116 pnt
= ptr_get_be32(pnt
, &eas
.val
);
117 eas
.val
= (*pnt
++ << 8);
120 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
123 json_object_string_add(json_rt
, "rt", rt_buf
);
125 vty_out(vty
, "Route-target: %s", rt_buf
);
135 "\nList of VRFs importing routes with this route-target:\n");
138 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
140 json_object_array_add(
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
145 vty_out(vty
, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
150 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
151 json_object_object_add(json
, rt_buf
, json_rt
);
155 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 uint8_t type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (uint8_t *)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
218 json_object_string_add(json_rt
, "rt", rt_buf
);
220 vty_out(vty
, "Route-target: %s", rt_buf
);
224 case ECOMMUNITY_ENCODE_AS4
:
225 pnt
= ptr_get_be32(pnt
, &eas
.val
);
226 eas
.val
= (*pnt
++ << 8);
229 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
232 json_object_string_add(json_rt
, "rt", rt_buf
);
234 vty_out(vty
, "Route-target: %s", rt_buf
);
244 "\nList of VNIs importing routes with this route-target:\n");
247 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
249 json_object_array_add(
250 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
252 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
256 json_object_object_add(json_rt
, "vnis", json_vnis
);
257 json_object_object_add(json
, rt_buf
, json_rt
);
261 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
263 json_object
*json
= NULL
;
264 struct vty
*vty
= NULL
;
265 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
270 display_import_rt(vty
, irt
, json
);
275 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
276 struct bgp_dest
*rd_dest
,
277 json_object
*json
, char *rd_str
,
284 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
292 vty_out(vty
, "Route Distinguisher: ");
296 decode_rd_as(pnt
+ 2, &rd_as
);
297 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
299 json_object_string_add(json
, "rd", rd_str
);
301 vty_out(vty
, "%s\n", rd_str
);
305 decode_rd_as4(pnt
+ 2, &rd_as
);
306 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
308 json_object_string_add(json
, "rd", rd_str
);
310 vty_out(vty
, "%s\n", rd_str
);
314 decode_rd_ip(pnt
+ 2, &rd_ip
);
315 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
317 json_object_string_add(json
, "rd", rd_str
);
319 vty_out(vty
, "%s\n", rd_str
);
324 snprintf(rd_str
, len
, "Unknown");
325 json_object_string_add(json
, "rd", rd_str
);
327 snprintf(rd_str
, len
, "Unknown RD type");
328 vty_out(vty
, "%s\n", rd_str
);
334 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
335 uint64_t tbl_ver
, json_object
*json
)
338 " Network Next Hop Metric LocPrf Weight Path\n";
344 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
345 tbl_ver
, &bgp
->router_id
);
347 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
348 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
350 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
352 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
353 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
354 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
355 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
356 vty_out(vty
, "%s", ri_header
);
359 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
363 struct listnode
*node
, *nnode
;
364 struct vrf_route_target
*l3rt
;
365 json_object
*json_import_rtl
= NULL
;
366 json_object
*json_export_rtl
= NULL
;
367 char buf2
[ETHER_ADDR_STRLEN
];
369 json_import_rtl
= json_export_rtl
= 0;
372 json_import_rtl
= json_object_new_array();
373 json_export_rtl
= json_object_new_array();
374 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
375 json_object_string_add(json
, "type", "L3");
376 json_object_string_add(json
, "inKernel", "True");
377 json_object_string_addf(json
, "rd",
378 BGP_RD_AS_FORMAT(bgp_vrf
->asnotation
),
380 json_object_string_addf(json
, "originatorIp", "%pI4",
381 &bgp_vrf
->originator_ip
);
382 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
383 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
384 json_object_string_add(json
, "advertisePip",
385 bgp_vrf
->evpn_info
->advertise_pip
?
386 "Enabled" : "Disabled");
387 json_object_string_addf(json
, "sysIP", "%pI4",
388 &bgp_vrf
->evpn_info
->pip_ip
);
389 json_object_string_add(json
, "sysMac",
390 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
391 buf2
, sizeof(buf2
)));
392 json_object_string_add(json
, "rmac",
393 prefix_mac2str(&bgp_vrf
->rmac
,
394 buf2
, sizeof(buf2
)));
396 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
397 vty_out(vty
, " (known to the kernel)");
400 vty_out(vty
, " Type: %s\n", "L3");
401 vty_out(vty
, " Tenant VRF: %s\n",
402 vrf_id_to_name(bgp_vrf
->vrf_id
));
403 vty_out(vty
, " RD: ");
404 vty_out(vty
, BGP_RD_AS_FORMAT(bgp_vrf
->asnotation
),
407 vty_out(vty
, " Originator IP: %pI4\n",
408 &bgp_vrf
->originator_ip
);
409 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
410 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
411 vty_out(vty
, " Advertise-pip: %s\n",
412 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
413 vty_out(vty
, " System-IP: %pI4\n",
414 &bgp_vrf
->evpn_info
->pip_ip
);
415 vty_out(vty
, " System-MAC: %s\n",
416 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
417 buf2
, sizeof(buf2
)));
418 vty_out(vty
, " Router-MAC: %s\n",
419 prefix_mac2str(&bgp_vrf
->rmac
,
420 buf2
, sizeof(buf2
)));
424 vty_out(vty
, " Import Route Target:\n");
426 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
427 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
428 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
431 json_object_array_add(json_import_rtl
,
432 json_object_new_string(ecom_str
));
434 vty_out(vty
, " %s\n", ecom_str
);
436 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
440 json_object_object_add(json
, "importRts", json_import_rtl
);
442 vty_out(vty
, " Export Route Target:\n");
444 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
445 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
446 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
449 json_object_array_add(json_export_rtl
,
450 json_object_new_string(ecom_str
));
452 vty_out(vty
, " %s\n", ecom_str
);
454 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
458 json_object_object_add(json
, "exportRts", json_export_rtl
);
461 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
464 struct listnode
*node
, *nnode
;
465 struct ecommunity
*ecom
;
466 json_object
*json_import_rtl
= NULL
;
467 json_object
*json_export_rtl
= NULL
;
468 struct bgp
*bgp_evpn
;
469 enum asnotation_mode asnotation
;
471 bgp_evpn
= bgp_get_evpn();
472 asnotation
= bgp_get_asnotation(bgp_evpn
);
475 json_import_rtl
= json_object_new_array();
476 json_export_rtl
= json_object_new_array();
477 json_object_int_add(json
, "vni", vpn
->vni
);
478 json_object_string_add(json
, "type", "L2");
479 json_object_string_add(json
, "inKernel",
480 is_vni_live(vpn
) ? "True" : "False");
481 json_object_string_addf(
482 json
, "rd", BGP_RD_AS_FORMAT(asnotation
), &vpn
->prd
);
483 json_object_string_addf(json
, "originatorIp", "%pI4",
484 &vpn
->originator_ip
);
485 json_object_string_addf(json
, "mcastGroup", "%pI4",
487 /* per vni knob is enabled -- Enabled
488 * Global knob is enabled -- Active
489 * default -- Disabled
491 if (!vpn
->advertise_gw_macip
&&
492 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
493 json_object_string_add(json
, "advertiseGatewayMacip",
495 else if (vpn
->advertise_gw_macip
)
496 json_object_string_add(json
, "advertiseGatewayMacip",
499 json_object_string_add(json
, "advertiseGatewayMacip",
501 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
502 bgp_evpn
->evpn_info
->advertise_svi_macip
)
503 json_object_string_add(json
, "advertiseSviMacIp",
505 else if (vpn
->advertise_svi_macip
)
506 json_object_string_add(json
, "advertiseSviMacIp",
509 json_object_string_add(json
, "advertiseSviMacIp",
511 json_object_string_add(
512 json
, "sviInterface",
513 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
515 vty_out(vty
, "VNI: %u", vpn
->vni
);
516 if (is_vni_live(vpn
))
517 vty_out(vty
, " (known to the kernel)");
520 vty_out(vty
, " Type: %s\n", "L2");
521 vty_out(vty
, " Tenant-Vrf: %s\n",
522 vrf_id_to_name(vpn
->tenant_vrf_id
));
523 vty_out(vty
, " RD: ");
524 vty_out(vty
, BGP_RD_AS_FORMAT(asnotation
), &vpn
->prd
);
526 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
527 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
528 if (!vpn
->advertise_gw_macip
&&
529 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
530 vty_out(vty
, " Advertise-gw-macip : %s\n",
532 else if (vpn
->advertise_gw_macip
)
533 vty_out(vty
, " Advertise-gw-macip : %s\n",
536 vty_out(vty
, " Advertise-gw-macip : %s\n",
538 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
539 bgp_evpn
->evpn_info
->advertise_svi_macip
)
540 vty_out(vty
, " Advertise-svi-macip : %s\n",
542 else if (vpn
->advertise_svi_macip
)
543 vty_out(vty
, " Advertise-svi-macip : %s\n",
546 vty_out(vty
, " Advertise-svi-macip : %s\n",
548 vty_out(vty
, " SVI interface : %s\n",
549 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
553 vty_out(vty
, " Import Route Target:\n");
555 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
556 ecom_str
= ecommunity_ecom2str(ecom
,
557 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
560 json_object_array_add(json_import_rtl
,
561 json_object_new_string(ecom_str
));
563 vty_out(vty
, " %s\n", ecom_str
);
565 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
569 json_object_object_add(json
, "importRts", json_import_rtl
);
571 vty_out(vty
, " Export Route Target:\n");
573 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
574 ecom_str
= ecommunity_ecom2str(ecom
,
575 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
578 json_object_array_add(json_export_rtl
,
579 json_object_new_string(ecom_str
));
581 vty_out(vty
, " %s\n", ecom_str
);
583 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
587 json_object_object_add(json
, "exportRts", json_export_rtl
);
590 static void show_esi_routes(struct bgp
*bgp
,
591 struct bgp_evpn_es
*es
,
596 struct bgp_dest
*dest
;
597 struct bgp_path_info
*pi
;
598 uint32_t prefix_cnt
, path_cnt
;
601 prefix_cnt
= path_cnt
= 0;
603 tbl_ver
= es
->route_table
->version
;
604 for (dest
= bgp_table_top(es
->route_table
); dest
;
605 dest
= bgp_route_next(dest
)) {
606 int add_prefix_to_json
= 0;
607 json_object
*json_paths
= NULL
;
608 json_object
*json_prefix
= NULL
;
609 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
612 json_prefix
= json_object_new_object();
614 pi
= bgp_dest_get_bgp_path_info(dest
);
616 /* Overall header/legend displayed once. */
618 bgp_evpn_show_route_header(vty
, bgp
,
627 json_paths
= json_object_new_array();
629 /* For EVPN, the prefix is displayed for each path (to fit in
630 * with code that already exists).
632 for (; pi
; pi
= pi
->next
) {
633 json_object
*json_path
= NULL
;
636 json_path
= json_object_new_array();
638 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
642 json_object_array_add(json_paths
, json_path
);
645 add_prefix_to_json
= 1;
649 if (add_prefix_to_json
) {
650 json_object_string_addf(json_prefix
, "prefix",
652 json_object_int_add(json_prefix
, "prefixLen",
654 json_object_object_add(json_prefix
, "paths",
656 json_object_object_addf(json
, json_prefix
,
659 json_object_free(json_paths
);
660 json_object_free(json_prefix
);
668 json_object_int_add(json
, "numPrefix", prefix_cnt
);
669 json_object_int_add(json
, "numPaths", path_cnt
);
672 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
674 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
675 prefix_cnt
, path_cnt
);
679 /* Display all MAC-IP VNI routes linked to an ES */
680 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
681 json_object
*json
, int detail
,
685 struct bgp_path_info
*pi
;
686 int header
= detail
? 0 : 1;
688 struct listnode
*node
;
689 struct bgp_evpn_es
*es
;
690 struct bgp_path_es_info
*es_info
;
691 struct bgp
*bgp
= bgp_get_evpn();
692 json_object
*json_paths
= NULL
;
700 json_paths
= json_object_new_array();
702 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
703 struct list
*es_list
;
705 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
709 es_list
= es
->macip_global_path_list
;
711 es_list
= es
->macip_evi_path_list
;
713 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
714 json_object
*json_path
= NULL
;
719 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
722 /* Overall header/legend displayed once. */
724 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
731 json_path
= json_object_new_array();
734 route_vty_out_detail(
735 vty
, bgp
, rn
, bgp_dest_get_prefix(rn
),
736 pi
, AFI_L2VPN
, SAFI_EVPN
,
737 RPKI_NOT_BEING_USED
, json_path
);
739 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
743 json_object_array_add(json_paths
, json_path
);
748 json_object_object_add(json
, "paths", json_paths
);
749 json_object_int_add(json
, "numPaths", path_cnt
);
752 vty_out(vty
, "There are no MAC-IP ES paths");
754 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
759 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
760 json_object
*json
, int detail
)
762 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
765 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
766 json_object
*json
, int detail
)
768 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
771 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
,
772 struct vty
*vty
, int type
, bool mac_table
,
773 struct in_addr vtep_ip
, json_object
*json
,
776 struct bgp_dest
*dest
;
777 struct bgp_path_info
*pi
;
778 struct bgp_table
*table
;
779 int header
= detail
? 0 : 1;
781 uint32_t prefix_cnt
, path_cnt
;
783 prefix_cnt
= path_cnt
= 0;
786 table
= vpn
->mac_table
;
788 table
= vpn
->ip_table
;
790 tbl_ver
= table
->version
;
791 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
792 const struct prefix_evpn
*evp
=
793 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
794 int add_prefix_to_json
= 0;
795 json_object
*json_paths
= NULL
;
796 json_object
*json_prefix
= NULL
;
797 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
799 if (type
&& evp
->prefix
.route_type
!= type
)
803 json_prefix
= json_object_new_object();
805 pi
= bgp_dest_get_bgp_path_info(dest
);
807 /* Overall header/legend displayed once. */
809 bgp_evpn_show_route_header(vty
, bgp
,
818 json_paths
= json_object_new_array();
820 /* For EVPN, the prefix is displayed for each path (to fit in
821 * with code that already exists).
823 for (; pi
; pi
= pi
->next
) {
825 json_object
*json_path
= NULL
;
827 if (vtep_ip
.s_addr
!= INADDR_ANY
828 && !IPV4_ADDR_SAME(&(vtep_ip
),
829 &(pi
->attr
->nexthop
)))
832 if (evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
834 * VNI IP/MAC table prefixes don't have MAC/IP
835 * respectively so make sure it's set from path
838 if (is_evpn_prefix_ipaddr_none(evp
)) {
839 /* VNI MAC -> Global */
840 evpn_type2_prefix_global_copy(
841 (struct prefix_evpn
*)&tmp_p
,
843 evpn_type2_path_info_get_ip(
846 /* VNI IP -> Global */
847 evpn_type2_prefix_global_copy(
848 (struct prefix_evpn
*)&tmp_p
,
850 evpn_type2_path_info_get_mac(
855 memcpy(&tmp_p
, p
, sizeof(tmp_p
));
859 json_path
= json_object_new_array();
862 route_vty_out_detail(vty
, bgp
, dest
, &tmp_p
, pi
,
863 AFI_L2VPN
, SAFI_EVPN
,
868 route_vty_out(vty
, &tmp_p
, pi
, 0, SAFI_EVPN
,
872 json_object_array_add(json_paths
, json_path
);
875 add_prefix_to_json
= 1;
879 if (add_prefix_to_json
) {
880 json_object_string_addf(json_prefix
, "prefix",
882 json_object_int_add(json_prefix
, "prefixLen",
884 json_object_object_add(json_prefix
, "paths",
886 json_object_object_addf(json
, json_prefix
,
889 json_object_free(json_paths
);
890 json_object_free(json_prefix
);
898 json_object_int_add(json
, "numPrefix", prefix_cnt
);
899 json_object_int_add(json
, "numPaths", path_cnt
);
902 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
903 type
? "(of requested type) " : "");
905 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
906 prefix_cnt
, path_cnt
,
907 type
? " (of requested type)" : "");
912 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
914 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
915 struct vni_walk_ctx
*wctx
= arg
;
916 struct vty
*vty
= wctx
->vty
;
917 json_object
*json
= wctx
->json
;
918 json_object
*json_vni
= NULL
;
919 char vni_str
[VNI_STR_LEN
];
921 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
923 json_vni
= json_object_new_object();
924 json_object_int_add(json_vni
, "vni", vpn
->vni
);
926 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
929 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, wctx
->type
, wctx
->mac_table
,
930 wctx
->vtep_ip
, json_vni
, wctx
->detail
);
933 json_object_object_add(json
, vni_str
, json_vni
);
936 static void show_vni_routes_all_hash(struct hash_bucket
*bucket
, void *arg
)
938 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
939 struct vni_walk_ctx
*wctx
= arg
;
940 struct vty
*vty
= wctx
->vty
;
941 json_object
*json
= wctx
->json
;
942 json_object
*json_vni
= NULL
;
943 json_object
*json_vni_mac
= NULL
;
944 char vni_str
[VNI_STR_LEN
];
946 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
948 json_vni
= json_object_new_object();
949 json_object_int_add(json_vni
, "vni", vpn
->vni
);
951 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
954 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, false, wctx
->vtep_ip
,
955 json_vni
, wctx
->detail
);
958 json_object_object_add(json
, vni_str
, json_vni
);
961 json_vni_mac
= json_object_new_object();
963 vty_out(vty
, "\nVNI: %u MAC Table\n\n", vpn
->vni
);
965 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, true, wctx
->vtep_ip
,
966 json_vni_mac
, wctx
->detail
);
969 json_object_object_add(json_vni
, "macTable", json_vni_mac
);
972 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
975 json_object
*json_vni
= NULL
;
976 json_object
*json_import_rtl
= NULL
;
977 json_object
*json_export_rtl
= NULL
;
979 char buf2
[INET6_ADDRSTRLEN
];
982 struct listnode
*node
, *nnode
;
983 struct vrf_route_target
*l3rt
;
989 json_vni
= json_object_new_object();
990 json_import_rtl
= json_object_new_array();
991 json_export_rtl
= json_object_new_array();
994 /* if an l3vni is present in bgp it is live */
996 snprintf(buf1
, sizeof(buf1
), "*");
999 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
1000 json_object_string_add(json_vni
, "type", "L3");
1001 json_object_string_add(json_vni
, "inKernel", "True");
1002 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1003 &bgp
->originator_ip
);
1004 json_object_string_addf(json_vni
, "rd",
1005 BGP_RD_AS_FORMAT(bgp
->asnotation
),
1007 json_object_string_add(json_vni
, "advertiseGatewayMacip",
1009 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
1010 json_object_string_add(
1011 json_vni
, "advertisePip",
1012 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
1013 json_object_string_addf(json_vni
, "sysIP", "%pI4",
1014 &bgp
->evpn_info
->pip_ip
);
1015 json_object_string_add(json_vni
, "sysMAC",
1016 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
1017 buf2
, sizeof(buf2
)));
1018 json_object_string_add(
1020 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
1022 vty_out(vty
, "%-1s %-10u %-4s ", buf1
, bgp
->l3vni
, "L3");
1023 vty_out(vty
, BGP_RD_AS_FORMAT_SPACE(bgp
->asnotation
),
1027 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
1028 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1029 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1032 json_object_array_add(json_import_rtl
,
1033 json_object_new_string(ecom_str
));
1035 if (listcount(bgp
->vrf_import_rtl
) > 1)
1036 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1039 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1041 vty_out(vty
, " %-25s", rt_buf
);
1044 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1046 /* If there are multiple import RTs we break here and show only
1053 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1055 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
1056 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1057 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1060 json_object_array_add(json_export_rtl
,
1061 json_object_new_string(ecom_str
));
1063 if (listcount(bgp
->vrf_export_rtl
) > 1)
1064 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1067 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1069 vty_out(vty
, " %-25s", rt_buf
);
1072 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1074 /* If there are multiple export RTs we break here and show only
1077 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1083 char vni_str
[VNI_STR_LEN
];
1085 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1086 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1087 json_object_object_add(json
, vni_str
, json_vni
);
1093 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1097 json_object
*json_vni
= NULL
;
1098 json_object
*json_import_rtl
= NULL
;
1099 json_object
*json_export_rtl
= NULL
;
1100 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1104 struct listnode
*node
, *nnode
;
1105 struct ecommunity
*ecom
;
1106 struct bgp
*bgp_evpn
;
1107 enum asnotation_mode asnotation
;
1112 bgp_evpn
= bgp_get_evpn();
1113 asnotation
= bgp_get_asnotation(bgp_evpn
);
1116 json_vni
= json_object_new_object();
1117 json_import_rtl
= json_object_new_array();
1118 json_export_rtl
= json_object_new_array();
1122 if (is_vni_live(vpn
))
1123 snprintf(buf1
, sizeof(buf1
), "*");
1126 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1127 json_object_string_add(json_vni
, "type", "L2");
1128 json_object_string_add(json_vni
, "inKernel",
1129 is_vni_live(vpn
) ? "True" : "False");
1130 json_object_string_addf(json_vni
, "rd",
1131 BGP_RD_AS_FORMAT(asnotation
),
1133 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1134 &vpn
->originator_ip
);
1135 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1137 /* per vni knob is enabled -- Enabled
1138 * Global knob is enabled -- Active
1139 * default -- Disabled
1141 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1142 && bgp_evpn
->advertise_gw_macip
)
1143 json_object_string_add(
1144 json_vni
, "advertiseGatewayMacip", "Active");
1145 else if (vpn
->advertise_gw_macip
)
1146 json_object_string_add(
1147 json_vni
, "advertiseGatewayMacip", "Enabled");
1149 json_object_string_add(
1150 json_vni
, "advertiseGatewayMacip", "Disabled");
1151 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1152 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1153 json_object_string_add(json_vni
, "advertiseSviMacIp",
1155 else if (vpn
->advertise_svi_macip
)
1156 json_object_string_add(json_vni
, "advertiseSviMacIp",
1159 json_object_string_add(json_vni
, "advertiseSviMacIp",
1162 vty_out(vty
, "%-1s %-10u %-4s ", buf1
, vpn
->vni
, "L2");
1163 vty_out(vty
, BGP_RD_AS_FORMAT_SPACE(asnotation
), &vpn
->prd
);
1166 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1167 ecom_str
= ecommunity_ecom2str(ecom
,
1168 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1171 json_object_array_add(json_import_rtl
,
1172 json_object_new_string(ecom_str
));
1174 if (listcount(vpn
->import_rtl
) > 1)
1175 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1178 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1180 vty_out(vty
, " %-25s", rt_buf
);
1183 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1185 /* If there are multiple import RTs we break here and show only
1192 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1194 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1195 ecom_str
= ecommunity_ecom2str(ecom
,
1196 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1199 json_object_array_add(json_export_rtl
,
1200 json_object_new_string(ecom_str
));
1202 if (listcount(vpn
->export_rtl
) > 1)
1203 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1206 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1208 vty_out(vty
, " %-25s", rt_buf
);
1211 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1213 /* If there are multiple export RTs we break here and show only
1216 vty_out(vty
, "%-37s",
1217 vrf_id_to_name(vpn
->tenant_vrf_id
));
1223 char vni_str
[VNI_STR_LEN
];
1225 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1226 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1227 json_object_object_add(json
, vni_str
, json_vni
);
1233 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1234 enum bgp_show_type type
, void *output_arg
,
1235 int option
, bool use_json
)
1237 afi_t afi
= AFI_L2VPN
;
1239 struct bgp_table
*table
;
1240 struct bgp_dest
*dest
;
1241 struct bgp_dest
*rm
;
1242 struct bgp_path_info
*pi
;
1245 char rd_str
[RD_ADDRSTRLEN
];
1248 unsigned long output_count
= 0;
1249 unsigned long total_count
= 0;
1250 json_object
*json
= NULL
;
1251 json_object
*json_array
= NULL
;
1252 json_object
*json_prefix_info
= NULL
;
1254 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1256 bgp
= bgp_get_evpn();
1259 vty_out(vty
, "No BGP process is configured\n");
1261 vty_out(vty
, "{}\n");
1266 json
= json_object_new_object();
1268 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1269 dest
= bgp_route_next(dest
)) {
1271 json_object
*json_nroute
= NULL
;
1272 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1274 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1277 table
= bgp_dest_get_bgp_table_info(dest
);
1282 tbl_ver
= table
->version
;
1284 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1285 pi
= bgp_dest_get_bgp_path_info(rm
);
1290 for (; pi
; pi
= pi
->next
) {
1291 struct community
*picomm
= NULL
;
1293 picomm
= bgp_attr_get_community(pi
->attr
);
1296 if (type
== bgp_show_type_neighbor
) {
1297 struct peer
*peer
= output_arg
;
1299 if (peer_cmp(peer
, pi
->peer
) != 0)
1302 if (type
== bgp_show_type_lcommunity_exact
) {
1303 struct lcommunity
*lcom
= output_arg
;
1305 if (!bgp_attr_get_lcommunity(
1308 bgp_attr_get_lcommunity(
1313 if (type
== bgp_show_type_lcommunity
) {
1314 struct lcommunity
*lcom
= output_arg
;
1316 if (!bgp_attr_get_lcommunity(
1319 bgp_attr_get_lcommunity(
1324 if (type
== bgp_show_type_community
) {
1325 struct community
*com
= output_arg
;
1328 !community_match(picomm
, com
))
1331 if (type
== bgp_show_type_community_exact
) {
1332 struct community
*com
= output_arg
;
1335 !community_cmp(picomm
, com
))
1340 json_object_int_add(
1341 json
, "bgpTableVersion",
1343 json_object_string_addf(
1348 json_object_int_add(
1351 bgp
->default_local_pref
);
1352 asn_asn2json(json
, "localAS",
1356 if (option
== SHOW_DISPLAY_TAGS
)
1361 == SHOW_DISPLAY_OVERLAY
)
1365 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1373 json_object_new_object();
1374 bgp_evpn_show_route_rd_header(
1375 vty
, dest
, json_nroute
, rd_str
,
1379 if (use_json
&& !json_array
)
1380 json_array
= json_object_new_array();
1382 if (option
== SHOW_DISPLAY_TAGS
)
1384 vty
, bgp_dest_get_prefix(rm
),
1385 pi
, no_display
, SAFI_EVPN
,
1387 else if (option
== SHOW_DISPLAY_OVERLAY
)
1388 route_vty_out_overlay(
1389 vty
, bgp_dest_get_prefix(rm
),
1390 pi
, no_display
, json_array
);
1393 bgp_dest_get_prefix(rm
),
1394 pi
, no_display
, SAFI_EVPN
,
1402 if (use_json
&& json_array
) {
1403 const struct prefix
*p
=
1404 bgp_dest_get_prefix(rm
);
1406 json_prefix_info
= json_object_new_object();
1408 json_object_string_addf(json_prefix_info
,
1409 "prefix", "%pFX", p
);
1411 json_object_int_add(json_prefix_info
,
1412 "prefixLen", p
->prefixlen
);
1414 json_object_object_add(json_prefix_info
,
1415 "paths", json_array
);
1416 json_object_object_addf(json_nroute
,
1423 if (use_json
&& json_nroute
)
1424 json_object_object_add(json
, rd_str
, json_nroute
);
1428 json_object_int_add(json
, "numPrefix", output_count
);
1429 json_object_int_add(json
, "totalPrefix", total_count
);
1430 vty_json(vty
, json
);
1432 if (output_count
== 0)
1433 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1437 "\nDisplayed %ld out of %ld total prefixes\n",
1438 output_count
, total_count
);
1443 DEFUN(show_ip_bgp_l2vpn_evpn
,
1444 show_ip_bgp_l2vpn_evpn_cmd
,
1445 "show [ip] bgp l2vpn evpn [json]",
1446 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1448 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1449 SHOW_DISPLAY_STANDARD
,
1450 use_json(argc
, argv
));
1453 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1454 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1455 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1461 "Display information for a route distinguisher\n"
1462 "VPN Route Distinguisher\n"
1463 "All VPN Route Distinguishers\n"
1466 int idx_ext_community
= 0;
1468 struct prefix_rd prd
;
1471 if (argv_find(argv
, argc
, "all", &rd_all
))
1472 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1473 NULL
, SHOW_DISPLAY_STANDARD
,
1474 use_json(argc
, argv
));
1476 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1477 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1479 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1482 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1483 SHOW_DISPLAY_STANDARD
,
1484 use_json(argc
, argv
));
1487 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1488 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1489 "show [ip] bgp l2vpn evpn all tags",
1495 "Display information about all EVPN NLRIs\n"
1496 "Display BGP tags for prefixes\n")
1498 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1499 SHOW_DISPLAY_TAGS
, 0);
1502 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1503 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1504 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1510 "Display information for a route distinguisher\n"
1511 "VPN Route Distinguisher\n"
1512 "All VPN Route Distinguishers\n"
1513 "Display BGP tags for prefixes\n")
1515 int idx_ext_community
= 0;
1517 struct prefix_rd prd
;
1520 if (argv_find(argv
, argc
, "all", &rd_all
))
1521 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1522 NULL
, SHOW_DISPLAY_TAGS
, 0);
1524 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1525 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1527 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1530 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1531 SHOW_DISPLAY_TAGS
, 0);
1534 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1535 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1536 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1542 "Detailed information on TCP and BGP neighbor connections\n"
1543 "IPv4 Neighbor to display information about\n"
1544 "IPv6 Neighbor to display information about\n"
1545 "Neighbor on BGP configured interface\n"
1546 "Display routes learned from neighbor\n" JSON_STR
)
1550 char *peerstr
= NULL
;
1551 bool uj
= use_json(argc
, argv
);
1552 afi_t afi
= AFI_L2VPN
;
1553 safi_t safi
= SAFI_EVPN
;
1554 struct bgp
*bgp
= NULL
;
1556 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1559 vty_out(vty
, "No index\n");
1563 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1564 argv_find(argv
, argc
, "neighbors", &idx
);
1565 peerstr
= argv
[++idx
]->arg
;
1567 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1570 json_object
*json_no
= NULL
;
1571 json_no
= json_object_new_object();
1572 json_object_string_add(json_no
, "warning",
1573 "Malformed address");
1574 vty_out(vty
, "%s\n",
1575 json_object_to_json_string(json_no
));
1576 json_object_free(json_no
);
1578 vty_out(vty
, "Malformed address: %s\n",
1582 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1584 json_object
*json_no
= NULL
;
1585 json_no
= json_object_new_object();
1586 json_object_string_add(
1588 "No such neighbor or address family");
1589 vty_out(vty
, "%s\n",
1590 json_object_to_json_string(json_no
));
1591 json_object_free(json_no
);
1593 vty_out(vty
, "%% No such neighbor or address family\n");
1597 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1598 SHOW_DISPLAY_STANDARD
, uj
);
1601 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1602 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1603 "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]",
1609 "Display information for a route distinguisher\n"
1610 "VPN Route Distinguisher\n"
1611 "All VPN Route Distinguishers\n"
1612 "Detailed information on TCP and BGP neighbor connections\n"
1613 "IPv4 Neighbor to display information about\n"
1614 "IPv6 Neighbor to display information about\n"
1615 "Neighbor on BGP configured interface\n"
1616 "Display routes learned from neighbor\n" JSON_STR
)
1618 int idx_ext_community
= 0;
1622 char *peerstr
= NULL
;
1623 struct prefix_rd prd
= {};
1624 bool uj
= use_json(argc
, argv
);
1625 afi_t afi
= AFI_L2VPN
;
1626 safi_t safi
= SAFI_EVPN
;
1627 struct bgp
*bgp
= NULL
;
1630 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1633 vty_out(vty
, "No index\n");
1637 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1638 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1639 &idx_ext_community
);
1640 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1643 json_object
*json_no
= NULL
;
1644 json_no
= json_object_new_object();
1645 json_object_string_add(
1647 "Malformed Route Distinguisher");
1648 vty_out(vty
, "%s\n",
1649 json_object_to_json_string(json_no
));
1650 json_object_free(json_no
);
1653 "%% Malformed Route Distinguisher\n");
1658 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1659 argv_find(argv
, argc
, "neighbors", &idx
);
1660 peerstr
= argv
[++idx
]->arg
;
1662 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1665 json_object
*json_no
= NULL
;
1666 json_no
= json_object_new_object();
1667 json_object_string_add(json_no
, "warning",
1668 "Malformed address");
1669 vty_out(vty
, "%s\n",
1670 json_object_to_json_string(json_no
));
1671 json_object_free(json_no
);
1673 vty_out(vty
, "Malformed address: %s\n",
1677 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1679 json_object
*json_no
= NULL
;
1680 json_no
= json_object_new_object();
1681 json_object_string_add(
1683 "No such neighbor or address family");
1684 vty_out(vty
, "%s\n",
1685 json_object_to_json_string(json_no
));
1686 json_object_free(json_no
);
1688 vty_out(vty
, "%% No such neighbor or address family\n");
1694 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1695 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1697 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1698 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1701 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1702 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1703 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1709 "Detailed information on TCP and BGP neighbor connections\n"
1710 "IPv4 Neighbor to display information about\n"
1711 "IPv6 Neighbor to display information about\n"
1712 "Neighbor on BGP configured interface\n"
1713 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1717 bool uj
= use_json(argc
, argv
);
1718 struct bgp
*bgp
= NULL
;
1719 afi_t afi
= AFI_L2VPN
;
1720 safi_t safi
= SAFI_EVPN
;
1721 char *peerstr
= NULL
;
1726 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1729 vty_out(vty
, "No index\n");
1733 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1734 argv_find(argv
, argc
, "neighbors", &idx
);
1735 peerstr
= argv
[++idx
]->arg
;
1737 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1740 json_object
*json_no
= NULL
;
1741 json_no
= json_object_new_object();
1742 json_object_string_add(json_no
, "warning",
1743 "Malformed address");
1744 vty_out(vty
, "%s\n",
1745 json_object_to_json_string(json_no
));
1746 json_object_free(json_no
);
1748 vty_out(vty
, "Malformed address: %s\n",
1752 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1754 json_object
*json_no
= NULL
;
1755 json_no
= json_object_new_object();
1756 json_object_string_add(
1758 "No such neighbor or address family");
1759 vty_out(vty
, "%s\n",
1760 json_object_to_json_string(json_no
));
1761 json_object_free(json_no
);
1763 vty_out(vty
, "%% No such neighbor or address family\n");
1767 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1770 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1771 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1772 "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]",
1778 "Display information for a route distinguisher\n"
1779 "VPN Route Distinguisher\n"
1780 "All VPN Route Distinguishers\n"
1781 "Detailed information on TCP and BGP neighbor connections\n"
1782 "IPv4 Neighbor to display information about\n"
1783 "IPv6 Neighbor to display information about\n"
1784 "Neighbor on BGP configured interface\n"
1785 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1787 int idx_ext_community
= 0;
1791 struct prefix_rd prd
;
1792 struct bgp
*bgp
= NULL
;
1793 bool uj
= use_json(argc
, argv
);
1794 char *peerstr
= NULL
;
1795 afi_t afi
= AFI_L2VPN
;
1796 safi_t safi
= SAFI_EVPN
;
1805 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1808 vty_out(vty
, "No index\n");
1812 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1813 argv_find(argv
, argc
, "neighbors", &idx
);
1814 peerstr
= argv
[++idx
]->arg
;
1816 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1819 json_object
*json_no
= NULL
;
1820 json_no
= json_object_new_object();
1821 json_object_string_add(json_no
, "warning",
1822 "Malformed address");
1823 vty_out(vty
, "%s\n",
1824 json_object_to_json_string(json_no
));
1825 json_object_free(json_no
);
1827 vty_out(vty
, "Malformed address: %s\n",
1831 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1833 json_object
*json_no
= NULL
;
1834 json_no
= json_object_new_object();
1835 json_object_string_add(
1837 "No such neighbor or address family");
1838 vty_out(vty
, "%s\n",
1839 json_object_to_json_string(json_no
));
1840 json_object_free(json_no
);
1842 vty_out(vty
, "%% No such neighbor or address family\n");
1846 if (argv_find(argv
, argc
, "all", &rd_all
))
1847 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1850 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1851 &idx_ext_community
);
1852 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1855 json_object
*json_no
= NULL
;
1856 json_no
= json_object_new_object();
1857 json_object_string_add(
1859 "Malformed Route Distinguisher");
1860 vty_out(vty
, "%s\n",
1861 json_object_to_json_string(json_no
));
1862 json_object_free(json_no
);
1865 "%% Malformed Route Distinguisher\n");
1870 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1873 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1874 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1875 "show [ip] bgp l2vpn evpn all overlay [json]",
1881 "Display information about all EVPN NLRIs\n"
1882 "Display BGP Overlay Information for prefixes\n"
1885 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1886 SHOW_DISPLAY_OVERLAY
,
1887 use_json(argc
, argv
));
1890 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1891 show_ip_bgp_evpn_rd_overlay_cmd
,
1892 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1898 "Display information for a route distinguisher\n"
1899 "VPN Route Distinguisher\n"
1900 "All VPN Route Distinguishers\n"
1901 "Display BGP Overlay Information for prefixes\n")
1903 int idx_ext_community
= 0;
1905 struct prefix_rd prd
;
1908 if (argv_find(argv
, argc
, "all", &rd_all
))
1909 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1910 NULL
, SHOW_DISPLAY_OVERLAY
,
1911 use_json(argc
, argv
));
1913 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1914 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1916 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1919 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1920 SHOW_DISPLAY_OVERLAY
,
1921 use_json(argc
, argv
));
1924 DEFUN(show_bgp_l2vpn_evpn_com
,
1925 show_bgp_l2vpn_evpn_com_cmd
,
1926 "show bgp l2vpn evpn \
1927 <community AA:NN|large-community AA:BB:CC> \
1928 [exact-match] [json]",
1933 "Display routes matching the community\n"
1934 "Community number where AA and NN are (0-65535)\n"
1935 "Display routes matching the large-community\n"
1936 "List of large-community numbers\n"
1937 "Exact match of the communities\n"
1942 const char *clist_number_or_name
;
1943 int show_type
= bgp_show_type_normal
;
1944 struct community
*com
;
1945 struct lcommunity
*lcom
;
1947 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1948 clist_number_or_name
= argv
[++idx
]->arg
;
1949 show_type
= bgp_show_type_lcommunity
;
1951 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1952 show_type
= bgp_show_type_lcommunity_exact
;
1954 lcom
= lcommunity_str2com(clist_number_or_name
);
1956 vty_out(vty
, "%% Large-community malformed\n");
1960 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1961 SHOW_DISPLAY_STANDARD
,
1962 use_json(argc
, argv
));
1964 lcommunity_free(&lcom
);
1965 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1966 clist_number_or_name
= argv
[++idx
]->arg
;
1967 show_type
= bgp_show_type_community
;
1969 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1970 show_type
= bgp_show_type_community_exact
;
1972 com
= community_str2com(clist_number_or_name
);
1975 vty_out(vty
, "%% Community malformed: %s\n",
1976 clist_number_or_name
);
1980 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1981 SHOW_DISPLAY_STANDARD
,
1982 use_json(argc
, argv
));
1983 community_free(&com
);
1989 /* For testing purpose, static route of EVPN RT-5. */
1990 DEFUN(evpnrt5_network
,
1991 evpnrt5_network_cmd
,
1992 "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]",
1993 "Specify a network to announce via BGP\n"
1996 "Specify Route Distinguisher\n"
1997 "VPN Route Distinguisher\n"
1999 "Ethernet Tag Value\n"
2002 "Ethernet Segment Identifier\n"
2003 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2005 "Gateway IP ( A.B.C.D )\n"
2006 "Gateway IPv6 ( X:X::X:X )\n"
2007 "Router Mac Ext Comm\n"
2008 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
2009 "Route-map to modify the attributes\n"
2010 "Name of the route map\n")
2012 int idx_ipv4_prefixlen
= 1;
2013 int idx_route_distinguisher
= 3;
2018 int idx_routermac
= 13;
2020 return bgp_static_set_safi(
2021 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2022 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
2023 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2024 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
2025 argv
[idx_routermac
]->arg
);
2028 /* For testing purpose, static route of EVPN RT-5. */
2029 DEFUN(no_evpnrt5_network
,
2030 no_evpnrt5_network_cmd
,
2031 "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>",
2033 "Specify a network to announce via BGP\n"
2036 "Specify Route Distinguisher\n"
2037 "VPN Route Distinguisher\n"
2039 "Ethernet Tag Value\n"
2042 "Ethernet Segment Identifier\n"
2043 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2044 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2046 int idx_ipv4_prefixlen
= 2;
2047 int idx_ext_community
= 4;
2052 return bgp_static_unset_safi(
2053 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2054 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2055 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2056 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2059 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2061 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
, false);
2064 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2066 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
, false);
2070 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2071 * check that this is a change.
2073 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2074 struct ecommunity
*ecomadd
)
2076 /* If the VNI is "live", we need to uninstall routes using the current
2077 * import RT(s) first before we update the import RT, and subsequently
2080 if (is_vni_live(vpn
))
2081 bgp_evpn_uninstall_routes(bgp
, vpn
);
2083 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2084 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2086 /* If the auto route-target is in use we must remove it */
2087 evpn_import_rt_delete_auto(bgp
, vpn
);
2089 /* Add new RT and rebuild the RT to VNI mapping */
2090 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2092 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2093 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2095 /* Install routes that match new import RT */
2096 if (is_vni_live(vpn
))
2097 bgp_evpn_install_routes(bgp
, vpn
);
2101 * Unconfigure Import RT(s) for a VNI (vty handler).
2103 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2104 struct ecommunity
*ecomdel
)
2106 struct listnode
*node
, *nnode
, *node_to_del
;
2107 struct ecommunity
*ecom
;
2109 /* Along the lines of "configure" except we have to reset to the
2112 if (is_vni_live(vpn
))
2113 bgp_evpn_uninstall_routes(bgp
, vpn
);
2115 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2116 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2118 /* Delete all import RTs */
2119 if (ecomdel
== NULL
) {
2120 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2121 ecommunity_free(&ecom
);
2122 list_delete_node(vpn
->import_rtl
, node
);
2126 /* Delete a specific import RT */
2130 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2131 if (ecommunity_match(ecom
, ecomdel
)) {
2132 ecommunity_free(&ecom
);
2139 list_delete_node(vpn
->import_rtl
, node_to_del
);
2142 assert(vpn
->import_rtl
);
2143 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2144 if (list_isempty(vpn
->import_rtl
)) {
2145 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2146 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2148 /* Rebuild the RT to VNI mapping */
2150 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2152 /* Install routes that match new import RT */
2153 if (is_vni_live(vpn
))
2154 bgp_evpn_install_routes(bgp
, vpn
);
2158 * Configure the Export RT for a VNI (vty handler). Caller expected to
2159 * check that this is a change. Note that only a single export RT is
2160 * allowed for a VNI and any change to configuration is implemented as
2161 * a "replace" (similar to other configuration).
2163 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2164 struct ecommunity
*ecomadd
)
2166 /* If the auto route-target is in use we must remove it */
2167 evpn_export_rt_delete_auto(bgp
, vpn
);
2169 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2170 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2172 if (is_vni_live(vpn
))
2173 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2177 * Unconfigure the Export RT for a VNI (vty handler)
2179 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2180 struct ecommunity
*ecomdel
)
2182 struct listnode
*node
, *nnode
, *node_to_del
;
2183 struct ecommunity
*ecom
;
2185 /* Delete all export RTs */
2186 if (ecomdel
== NULL
) {
2187 /* Reset to default and process all routes. */
2188 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2189 ecommunity_free(&ecom
);
2190 list_delete_node(vpn
->export_rtl
, node
);
2194 /* Delete a specific export RT */
2198 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2199 if (ecommunity_match(ecom
, ecomdel
)) {
2200 ecommunity_free(&ecom
);
2207 list_delete_node(vpn
->export_rtl
, node_to_del
);
2210 assert(vpn
->export_rtl
);
2211 if (list_isempty(vpn
->export_rtl
)) {
2212 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2213 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2216 if (is_vni_live(vpn
))
2217 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2221 * Configure RD for VRF
2223 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
,
2224 const char *rd_pretty
)
2226 /* If we have already advertise type-5 routes with a diffrent RD, we
2227 * have to delete and withdraw them firs
2229 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2232 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2233 bgp_vrf
->vrf_prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_pretty
);
2234 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2236 /* We have a new RD for VRF.
2237 * Advertise all type-5 routes again with the new RD
2239 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2243 * Unconfigure RD for VRF
2245 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2247 /* If we have already advertise type-5 routes with a diffrent RD, we
2248 * have to delete and withdraw them firs
2250 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2252 /* fall back to default RD */
2253 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2254 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2255 if (bgp_vrf
->vrf_prd_pretty
)
2256 XFREE(MTYPE_BGP
, bgp_vrf
->vrf_prd_pretty
);
2257 /* We have a new RD for VRF.
2258 * Advertise all type-5 routes again with the new RD
2260 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2264 * Configure RD for a VNI (vty handler)
2266 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2267 struct prefix_rd
*rd
, const char *rd_pretty
)
2269 /* If the VNI is "live", we need to delete and withdraw this VNI's
2270 * local routes with the prior RD first. Then, after updating RD,
2271 * need to re-advertise.
2273 if (is_vni_live(vpn
))
2274 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2277 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2278 vpn
->prd_pretty
= XSTRDUP(MTYPE_BGP
, rd_pretty
);
2279 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2281 if (is_vni_live(vpn
))
2282 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2286 * Unconfigure RD for a VNI (vty handler)
2288 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2290 /* If the VNI is "live", we need to delete and withdraw this VNI's
2291 * local routes with the prior RD first. Then, after resetting RD
2292 * to automatic value, need to re-advertise.
2294 if (is_vni_live(vpn
))
2295 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2297 /* reset RD to default */
2298 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2300 if (is_vni_live(vpn
))
2301 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2305 * Create VNI, if not already present (VTY handler). Mark as configured.
2307 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2309 struct bgpevpn
*vpn
;
2310 struct in_addr mcast_grp
= {INADDR_ANY
};
2312 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2314 /* Check if this L2VNI is already configured as L3VNI */
2315 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2318 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2323 /* tenant vrf will be updated when we get local_vni_add from
2326 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2329 /* Mark as configured. */
2330 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2335 * Delete VNI. If VNI does not exist in the system (i.e., just
2336 * configuration), all that is needed is to free it. Otherwise,
2337 * any parameters configured for the VNI need to be reset (with
2338 * appropriate action) and the VNI marked as unconfigured; the
2339 * VNI will continue to exist, purely as a "learnt" entity.
2341 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2343 if (!is_vni_live(vpn
)) {
2344 bgp_evpn_free(bgp
, vpn
);
2348 /* We need to take the unconfigure action for each parameter of this VNI
2349 * that is configured. Some optimization is possible, but not worth the
2350 * additional code for an operation that should be pretty rare.
2352 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2354 /* First, deal with the export side - RD and export RT changes. */
2355 if (is_rd_configured(vpn
))
2356 evpn_unconfigure_rd(bgp
, vpn
);
2357 if (is_export_rt_configured(vpn
))
2358 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2360 /* Next, deal with the import side. */
2361 if (is_import_rt_configured(vpn
))
2362 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2366 * Display import RT mapping to VRFs (vty handler)
2367 * bgp_evpn: evpn bgp instance
2369 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2377 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2378 (void (*)(struct hash_bucket
*,
2379 void *))show_vrf_import_rt_entry
,
2384 * Display import RT mapping to VNIs (vty handler)
2386 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2395 bgp
->import_rt_hash
,
2396 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2401 * Display EVPN routes for all VNIs - vty handler.
2403 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
, int type
,
2404 bool mac_table
, struct in_addr vtep_ip
,
2405 json_object
*json
, int detail
)
2408 struct vni_walk_ctx wctx
;
2410 num_vnis
= hashcount(bgp
->vnihash
);
2413 memset(&wctx
, 0, sizeof(wctx
));
2417 wctx
.mac_table
= mac_table
;
2418 wctx
.vtep_ip
= vtep_ip
;
2420 wctx
.detail
= detail
;
2421 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2422 void *))show_vni_routes_hash
,
2427 * Display EVPN routes for all VNIs & all types - vty handler.
2429 static void evpn_show_routes_vni_all_type_all(struct vty
*vty
, struct bgp
*bgp
,
2430 struct in_addr vtep_ip
,
2431 json_object
*json
, int detail
)
2434 struct vni_walk_ctx wctx
;
2436 num_vnis
= hashcount(bgp
->vnihash
);
2440 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2443 wctx
.vtep_ip
= vtep_ip
;
2445 wctx
.detail
= detail
;
2446 hash_iterate(bgp
->vnihash
,
2447 (void (*)(struct hash_bucket
*,
2448 void *))show_vni_routes_all_hash
,
2453 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2455 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2456 vni_t vni
, struct in_addr orig_ip
,
2459 struct bgpevpn
*vpn
;
2460 struct prefix_evpn p
;
2461 struct bgp_dest
*dest
;
2462 struct bgp_path_info
*pi
;
2463 uint32_t path_cnt
= 0;
2466 json_object
*json_paths
= NULL
;
2472 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2474 vty_out(vty
, "VNI not found\n");
2478 /* See if route exists. */
2479 build_evpn_type3_prefix(&p
, orig_ip
);
2480 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2481 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2483 vty_out(vty
, "%% Network not in table\n");
2486 bgp_dest_unlock_node(dest
);
2492 json_paths
= json_object_new_array();
2494 /* Prefix and num paths displayed once per prefix. */
2495 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2496 NULL
, afi
, safi
, json
, false);
2498 /* Display each path for this prefix. */
2499 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2500 json_object
*json_path
= NULL
;
2503 json_path
= json_object_new_array();
2505 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2506 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2510 json_object_array_add(json_paths
, json_path
);
2517 json_object_object_add(json
, "paths", json_paths
);
2519 json_object_int_add(json
, "numPaths", path_cnt
);
2521 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2525 bgp_dest_unlock_node(dest
);
2529 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2530 * By definition, only matching type-2 route will be displayed.
2532 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2533 vni_t vni
, struct ethaddr
*mac
,
2534 struct ipaddr
*ip
, json_object
*json
)
2536 struct bgpevpn
*vpn
;
2537 struct prefix_evpn p
;
2538 struct prefix_evpn tmp_p
;
2539 struct bgp_dest
*dest
;
2540 struct bgp_path_info
*pi
;
2541 uint32_t path_cnt
= 0;
2544 json_object
*json_paths
= NULL
;
2545 struct ethaddr empty_mac
= {};
2546 struct ipaddr empty_ip
= {};
2547 const struct prefix_evpn
*evp
;
2553 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2556 vty_out(vty
, "VNI not found\n");
2560 build_evpn_type2_prefix(&p
, mac
? mac
: &empty_mac
,
2561 ip
? ip
: &empty_ip
);
2563 /* See if route exists. Look for both non-sticky and sticky. */
2564 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2565 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2567 vty_out(vty
, "%% Network not in table\n");
2570 bgp_dest_unlock_node(dest
);
2576 * MAC is per-path, we have to walk the path_info's and look for it
2580 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2581 if (memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2588 vty_out(vty
, "%% Network not in table\n");
2594 json_paths
= json_object_new_array();
2596 /* Prefix and num paths displayed once per prefix. */
2597 route_vty_out_detail_header(vty
, bgp
, dest
, (struct prefix
*)&p
, NULL
,
2598 afi
, safi
, json
, false);
2600 evp
= (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2602 /* Display each path for this prefix. */
2603 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2604 json_object
*json_path
= NULL
;
2606 /* skip non-matching MACs */
2608 memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2613 json_path
= json_object_new_array();
2616 * VNI table MAC-IP prefixes don't have MAC so
2617 * make sure it's set from path info
2620 if (is_evpn_prefix_ipaddr_none(evp
)) {
2621 /* VNI MAC -> Global */
2622 evpn_type2_prefix_global_copy(
2623 (struct prefix_evpn
*)&tmp_p
, evp
,
2625 evpn_type2_path_info_get_ip(pi
));
2627 /* VNI IP -> Global */
2628 evpn_type2_prefix_global_copy(
2629 (struct prefix_evpn
*)&tmp_p
, evp
,
2630 evpn_type2_path_info_get_mac(pi
),
2634 route_vty_out_detail(vty
, bgp
, dest
, (struct prefix
*)&tmp_p
,
2635 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2639 json_object_array_add(json_paths
, json_path
);
2646 json_object_object_add(json
, "paths", json_paths
);
2648 json_object_int_add(json
, "numPaths", path_cnt
);
2650 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2654 bgp_dest_unlock_node(dest
);
2657 /* Disaplay EVPN routes for a ESI - VTY handler */
2658 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2659 esi_t
*esi
, json_object
*json
)
2661 struct bgp_evpn_es
*es
= NULL
;
2664 es
= bgp_evpn_es_find(esi
);
2667 vty_out(vty
, "ESI not found\n");
2671 show_esi_routes(bgp
, es
, vty
, json
);
2675 * Display EVPN routes for a VNI - vty handler.
2676 * If 'type' is non-zero, only routes matching that type are shown.
2677 * If the vtep_ip is non zero, only routes behind that vtep are shown
2679 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2680 int type
, bool mac_table
,
2681 struct in_addr vtep_ip
, json_object
*json
)
2683 struct bgpevpn
*vpn
;
2686 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2689 vty_out(vty
, "VNI not found\n");
2693 /* Walk this VNI's route table and display appropriate routes. */
2694 show_vni_routes(bgp
, vpn
, vty
, type
, mac_table
, vtep_ip
, json
, 0);
2698 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2699 * IP (vty handler). By definition, only matching type-2 route will be
2702 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2703 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2704 struct ipaddr
*ip
, json_object
*json
)
2706 struct prefix_evpn p
;
2707 struct bgp_dest
*dest
;
2708 struct bgp_path_info
*pi
;
2711 uint32_t path_cnt
= 0;
2712 json_object
*json_paths
= NULL
;
2717 /* See if route exists. Look for both non-sticky and sticky. */
2718 build_evpn_type2_prefix(&p
, mac
, ip
);
2719 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2720 (struct prefix
*)&p
, prd
);
2721 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2723 vty_out(vty
, "%% Network not in table\n");
2726 bgp_dest_unlock_node(dest
);
2731 /* Prefix and num paths displayed once per prefix. */
2732 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2733 prd
, afi
, safi
, json
, false);
2736 json_paths
= json_object_new_array();
2738 /* Display each path for this prefix. */
2739 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2740 json_object
*json_path
= NULL
;
2743 json_path
= json_object_new_array();
2745 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2746 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2750 json_object_array_add(json_paths
, json_path
);
2755 if (json
&& path_cnt
) {
2757 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2758 json_object_int_add(json
, "numPaths", path_cnt
);
2760 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2764 bgp_dest_unlock_node(dest
);
2768 * Display BGP EVPN routing table -- for specific RD (vty handler)
2769 * If 'type' is non-zero, only routes matching that type are shown.
2771 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2772 struct prefix_rd
*prd
, int type
,
2775 struct bgp_dest
*rd_dest
;
2776 struct bgp_table
*table
;
2777 struct bgp_dest
*dest
;
2778 struct bgp_path_info
*pi
;
2782 uint32_t prefix_cnt
, path_cnt
;
2783 json_object
*json_rd
= NULL
;
2784 int add_rd_to_json
= 0;
2788 prefix_cnt
= path_cnt
= 0;
2790 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2794 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2795 if (table
== NULL
) {
2796 bgp_dest_unlock_node(rd_dest
);
2801 json_rd
= json_object_new_object();
2802 json_object_string_addf(json_rd
, "rd",
2803 BGP_RD_AS_FORMAT(bgp
->asnotation
), prd
);
2806 bgp_dest_unlock_node(rd_dest
);
2808 /* Display all prefixes with this RD. */
2809 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2810 const struct prefix_evpn
*evp
=
2811 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2812 json_object
*json_prefix
= NULL
;
2813 json_object
*json_paths
= NULL
;
2814 int add_prefix_to_json
= 0;
2816 if (type
&& evp
->prefix
.route_type
!= type
)
2820 json_prefix
= json_object_new_object();
2822 pi
= bgp_dest_get_bgp_path_info(dest
);
2824 /* RD header and legend - once overall. */
2825 if (rd_header
&& !json
) {
2827 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2829 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2831 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2833 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2835 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2839 /* Prefix and num paths displayed once per prefix. */
2840 route_vty_out_detail_header(
2841 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), prd
,
2842 afi
, safi
, json_prefix
, false);
2848 json_paths
= json_object_new_array();
2850 /* Display each path for this prefix. */
2851 for (; pi
; pi
= pi
->next
) {
2852 json_object
*json_path
= NULL
;
2855 json_path
= json_object_new_array();
2857 route_vty_out_detail(
2858 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), pi
,
2859 afi
, safi
, RPKI_NOT_BEING_USED
, json_path
);
2862 json_object_array_add(json_paths
, json_path
);
2865 add_prefix_to_json
= 1;
2870 if (add_prefix_to_json
) {
2871 json_object_object_add(json_prefix
, "paths",
2873 json_object_object_addf(json_rd
, json_prefix
,
2876 json_object_free(json_paths
);
2877 json_object_free(json_prefix
);
2886 json_object_object_addf(
2888 BGP_RD_AS_FORMAT(bgp
->asnotation
), prd
);
2890 json_object_free(json_rd
);
2894 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2895 json_object_int_add(json
, "numPaths", path_cnt
);
2897 if (prefix_cnt
== 0)
2898 vty_out(vty
, "No prefixes exist with this RD%s\n",
2899 type
? " (of requested type)" : "");
2902 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2903 prefix_cnt
, path_cnt
,
2904 type
? " (of requested type)" : "");
2909 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2910 * (vty handler). Only matching type-2 routes will be displayed.
2912 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2913 struct ethaddr
*mac
, struct ipaddr
*ip
,
2916 struct bgp_dest
*rd_dest
;
2917 struct bgp_table
*table
;
2918 struct bgp_dest
*dest
;
2919 struct bgp_path_info
*pi
;
2920 afi_t afi
= AFI_L2VPN
;
2921 safi_t safi
= SAFI_EVPN
;
2922 uint32_t prefix_cnt
, path_cnt
;
2923 prefix_cnt
= path_cnt
= 0;
2925 /* EVPN routing table is a 2-level table with the first level being
2926 * the RD. We need to look in every RD we know about.
2928 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2929 rd_dest
= bgp_route_next(rd_dest
)) {
2930 json_object
*json_paths
= NULL
; /* paths array for prefix */
2931 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2932 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2933 char rd_str
[RD_ADDRSTRLEN
];
2934 int add_rd_to_json
= 0;
2935 struct prefix_evpn ep
;
2936 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2938 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2942 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2943 sizeof(rd_str
), bgp
->asnotation
);
2945 /* Construct an RT-2 from the user-supplied mac(ip),
2946 * then search the l2vpn evpn table for it.
2948 build_evpn_type2_prefix(&ep
, mac
, ip
);
2949 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2950 (struct prefix
*)&ep
,
2951 (struct prefix_rd
*)rd_destp
);
2956 json_rd
= json_object_new_object();
2958 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2960 pi
= bgp_dest_get_bgp_path_info(dest
);
2962 /* RD header - per RD. */
2963 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2964 rd_str
, RD_ADDRSTRLEN
);
2969 json_prefix
= json_object_new_object();
2970 json_paths
= json_object_new_array();
2971 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2973 json_object_int_add(json_prefix
, "prefixLen",
2976 /* Prefix and num paths displayed once per prefix. */
2977 route_vty_out_detail_header(
2978 vty
, bgp
, dest
, p
, (struct prefix_rd
*)rd_destp
,
2979 AFI_L2VPN
, SAFI_EVPN
, json_prefix
, false);
2981 /* For EVPN, the prefix is displayed for each path (to
2982 * fit in with code that already exists).
2984 for (; pi
; pi
= pi
->next
) {
2985 json_object
*json_path
= NULL
;
2991 json_path
= json_object_new_array();
2993 route_vty_out_detail(vty
, bgp
, dest
, p
, pi
, AFI_L2VPN
,
2994 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2998 json_object_array_add(json_paths
, json_path
);
3004 json_object_object_add(json_prefix
, "paths",
3006 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
3009 json_object_object_add(json
, rd_str
, json_rd
);
3011 json_object_free(json_rd
);
3016 bgp_dest_unlock_node(dest
);
3020 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3021 json_object_int_add(json
, "numPaths", path_cnt
);
3023 if (prefix_cnt
== 0) {
3024 vty_out(vty
, "No Matching EVPN prefixes exist\n");
3026 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
3027 prefix_cnt
, path_cnt
);
3033 * Display BGP EVPN routing table - all routes (vty handler).
3034 * If 'type' is non-zero, only routes matching that type are shown.
3036 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3037 json_object
*json
, int detail
)
3039 struct bgp_dest
*rd_dest
;
3040 struct bgp_table
*table
;
3041 struct bgp_dest
*dest
;
3042 struct bgp_path_info
*pi
;
3043 int header
= detail
? 0 : 1;
3047 uint32_t prefix_cnt
, path_cnt
;
3051 prefix_cnt
= path_cnt
= 0;
3053 /* EVPN routing table is a 2-level table with the first level being
3056 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
3057 rd_dest
= bgp_route_next(rd_dest
)) {
3058 char rd_str
[RD_ADDRSTRLEN
];
3059 json_object
*json_rd
= NULL
; /* contains routes for an RD */
3060 int add_rd_to_json
= 0;
3062 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
3064 table
= bgp_dest_get_bgp_table_info(rd_dest
);
3068 tbl_ver
= table
->version
;
3069 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
3070 sizeof(rd_str
), bgp
->asnotation
);
3073 json_rd
= json_object_new_object();
3077 /* Display all prefixes for an RD */
3078 for (dest
= bgp_table_top(table
); dest
;
3079 dest
= bgp_route_next(dest
)) {
3080 json_object
*json_prefix
=
3081 NULL
; /* contains prefix under a RD */
3082 json_object
*json_paths
=
3083 NULL
; /* array of paths under a prefix*/
3084 const struct prefix_evpn
*evp
=
3085 (const struct prefix_evpn
*)bgp_dest_get_prefix(
3087 int add_prefix_to_json
= 0;
3088 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3090 if (type
&& evp
->prefix
.route_type
!= type
)
3093 pi
= bgp_dest_get_bgp_path_info(dest
);
3095 /* Overall header/legend displayed once. */
3097 bgp_evpn_show_route_header(vty
, bgp
,
3102 "%19s Extended Community\n"
3107 /* RD header - per RD. */
3109 bgp_evpn_show_route_rd_header(
3110 vty
, rd_dest
, json_rd
, rd_str
,
3119 json_prefix
= json_object_new_object();
3120 json_paths
= json_object_new_array();
3121 json_object_string_addf(json_prefix
, "prefix",
3123 json_object_int_add(json_prefix
, "prefixLen",
3127 /* Prefix and num paths displayed once per prefix. */
3129 route_vty_out_detail_header(
3131 bgp_dest_get_prefix(dest
),
3132 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3133 SAFI_EVPN
, json_prefix
, false);
3135 /* For EVPN, the prefix is displayed for each path (to
3137 * with code that already exists).
3139 for (; pi
; pi
= pi
->next
) {
3140 json_object
*json_path
= NULL
;
3143 add_prefix_to_json
= 1;
3147 json_path
= json_object_new_array();
3150 route_vty_out_detail(
3152 bgp_dest_get_prefix(dest
), pi
,
3153 AFI_L2VPN
, SAFI_EVPN
,
3154 RPKI_NOT_BEING_USED
, json_path
);
3156 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3160 json_object_array_add(json_paths
,
3165 if (add_prefix_to_json
) {
3166 json_object_object_add(json_prefix
,
3169 json_object_object_addf(json_rd
,
3173 json_object_free(json_prefix
);
3174 json_object_free(json_paths
);
3183 json_object_object_add(json
, rd_str
, json_rd
);
3185 json_object_free(json_rd
);
3192 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3193 json_object_int_add(json
, "numPaths", path_cnt
);
3195 if (prefix_cnt
== 0) {
3196 vty_out(vty
, "No EVPN prefixes %sexist\n",
3197 type
? "(of requested type) " : "");
3199 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3200 prefix_cnt
, path_cnt
,
3201 type
? " (of requested type)" : "");
3206 int bgp_evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3207 bool use_json
, int detail
)
3209 json_object
*json
= NULL
;
3212 json
= json_object_new_object();
3214 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3217 vty_json(vty
, json
);
3222 * Display specified VNI (vty handler)
3224 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3228 struct bgpevpn
*vpn
;
3230 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3233 display_vni(vty
, vpn
, json
);
3235 struct bgp
*bgp_temp
;
3236 struct listnode
*node
= NULL
;
3238 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3239 if (bgp_temp
->l3vni
== vni
) {
3241 display_l3vni(vty
, bgp_temp
, json
);
3248 vty_out(vty
, "{}\n");
3250 vty_out(vty
, "VNI not found\n");
3257 * Display a VNI (upon user query).
3259 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3263 struct bgp
*bgp_temp
= NULL
;
3264 struct listnode
*node
;
3268 vty_out(vty
, "Flags: * - Kernel\n");
3269 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3270 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3273 /* print all L2 VNIS */
3276 hash_iterate(bgp
->vnihash
,
3277 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3280 /* print all L3 VNIs */
3281 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3282 show_l3vni_entry(vty
, bgp_temp
, json
);
3286 * evpn - enable advertisement of svi MAC-IP
3288 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3292 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3294 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3297 bgp
->evpn_info
->advertise_svi_macip
= set
;
3298 bgp_zebra_advertise_svi_macip(bgp
,
3299 bgp
->evpn_info
->advertise_svi_macip
, 0);
3301 if (set
&& vpn
->advertise_svi_macip
)
3303 else if (!set
&& !vpn
->advertise_svi_macip
)
3306 vpn
->advertise_svi_macip
= set
;
3307 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3313 * evpn - enable advertisement of default g/w
3315 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3318 if (bgp
->advertise_gw_macip
)
3321 bgp
->advertise_gw_macip
= 1;
3322 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3324 if (vpn
->advertise_gw_macip
)
3327 vpn
->advertise_gw_macip
= 1;
3328 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3335 * evpn - disable advertisement of default g/w
3337 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3338 struct bgpevpn
*vpn
)
3341 if (!bgp
->advertise_gw_macip
)
3344 bgp
->advertise_gw_macip
= 0;
3345 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3347 if (!vpn
->advertise_gw_macip
)
3350 vpn
->advertise_gw_macip
= 0;
3351 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3358 * evpn - enable advertisement of default g/w
3360 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3361 afi_t afi
, bool add
)
3363 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3366 /* bail if we are already advertising default route */
3367 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3371 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3372 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3373 else if (afi
== AFI_IP6
)
3374 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3375 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3377 /* bail out if we havent advertised the default route */
3378 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3381 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3382 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3383 else if (afi
== AFI_IP6
)
3384 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3388 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3392 * evpn - enable advertisement of default g/w
3394 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3395 struct bgpevpn
*vpn
)
3397 if (vpn
->advertise_subnet
)
3400 vpn
->advertise_subnet
= 1;
3401 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3405 * evpn - disable advertisement of default g/w
3407 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3409 if (!vpn
->advertise_subnet
)
3412 vpn
->advertise_subnet
= 0;
3413 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3417 * EVPN (VNI advertisement) enabled. Register with zebra.
3419 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3421 bgp
->advertise_all_vni
= 1;
3423 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3427 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3428 * cache, EVPN routes (delete and withdraw from peers).
3430 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3432 bgp
->advertise_all_vni
= 0;
3433 bgp_set_evpn(bgp_get_default());
3434 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3435 bgp_evpn_cleanup_on_disable(bgp
);
3438 /* Set resolve overlay index flag */
3439 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3441 if (set
== bgp
->resolve_overlay_index
)
3445 bgp
->resolve_overlay_index
= true;
3446 hash_iterate(bgp
->vnihash
,
3447 (void (*)(struct hash_bucket
*, void *))
3448 bgp_evpn_handle_resolve_overlay_index_set
,
3453 (void (*)(struct hash_bucket
*, void *))
3454 bgp_evpn_handle_resolve_overlay_index_unset
,
3456 bgp
->resolve_overlay_index
= false;
3461 * EVPN - use RFC8365 to auto-derive RT
3463 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3465 bgp
->advertise_autort_rfc8365
= 1;
3466 bgp_evpn_handle_autort_change(bgp
);
3470 * EVPN - don't use RFC8365 to auto-derive RT
3472 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3474 bgp
->advertise_autort_rfc8365
= 0;
3475 bgp_evpn_handle_autort_change(bgp
);
3478 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3481 struct listnode
*node
, *nnode
;
3482 struct ecommunity
*ecom
;
3484 if (is_vni_configured(vpn
)) {
3485 vty_out(vty
, " vni %u\n", vpn
->vni
);
3486 if (is_rd_configured(vpn
))
3487 vty_out(vty
, " rd %s\n", vpn
->prd_pretty
);
3489 if (is_import_rt_configured(vpn
)) {
3490 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3492 ecom_str
= ecommunity_ecom2str(
3493 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3494 vty_out(vty
, " route-target import %s\n",
3496 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3500 if (is_export_rt_configured(vpn
)) {
3501 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3503 ecom_str
= ecommunity_ecom2str(
3504 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3505 vty_out(vty
, " route-target export %s\n",
3507 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3511 if (vpn
->advertise_gw_macip
)
3512 vty_out(vty
, " advertise-default-gw\n");
3514 if (vpn
->advertise_svi_macip
)
3515 vty_out(vty
, " advertise-svi-ip\n");
3517 if (vpn
->advertise_subnet
)
3518 vty_out(vty
, " advertise-subnet\n");
3520 vty_out(vty
, " exit-vni\n");
3524 #include "bgpd/bgp_evpn_vty_clippy.c"
3526 DEFPY(bgp_evpn_flood_control
,
3527 bgp_evpn_flood_control_cmd
,
3528 "[no$no] flooding <disable$disable|head-end-replication$her>",
3530 "Specify handling for BUM packets\n"
3531 "Do not flood any BUM packets\n"
3532 "Flood BUM packets using head-end replication\n")
3534 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3535 enum vxlan_flood_control flood_ctrl
;
3541 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3543 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3547 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3550 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3551 bgp_evpn_flood_control_change(bgp
);
3556 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3557 bgp_evpn_advertise_default_gw_vni_cmd
,
3558 "advertise-default-gw",
3559 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3561 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3562 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3567 evpn_set_advertise_default_gw(bgp
, vpn
);
3572 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3573 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3574 "no advertise-default-gw",
3576 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3578 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3579 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3584 evpn_unset_advertise_default_gw(bgp
, vpn
);
3590 DEFUN (bgp_evpn_advertise_default_gw
,
3591 bgp_evpn_advertise_default_gw_cmd
,
3592 "advertise-default-gw",
3593 "Advertise All default g/w mac-ip routes in EVPN\n")
3595 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3600 if (!EVPN_ENABLED(bgp
)) {
3602 "This command is only supported under the EVPN VRF\n");
3606 evpn_set_advertise_default_gw(bgp
, NULL
);
3611 DEFUN (no_bgp_evpn_advertise_default_gw
,
3612 no_bgp_evpn_advertise_default_gw_cmd
,
3613 "no advertise-default-gw",
3615 "Withdraw All default g/w mac-ip routes from EVPN\n")
3617 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3622 evpn_unset_advertise_default_gw(bgp
, NULL
);
3627 DEFUN (bgp_evpn_advertise_all_vni
,
3628 bgp_evpn_advertise_all_vni_cmd
,
3629 "advertise-all-vni",
3630 "Advertise All local VNIs\n")
3632 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3633 struct bgp
*bgp_evpn
= NULL
;
3638 bgp_evpn
= bgp_get_evpn();
3639 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3640 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3641 bgp_evpn
->name_pretty
);
3642 return CMD_WARNING_CONFIG_FAILED
;
3645 evpn_set_advertise_all_vni(bgp
);
3649 DEFUN (no_bgp_evpn_advertise_all_vni
,
3650 no_bgp_evpn_advertise_all_vni_cmd
,
3651 "no advertise-all-vni",
3653 "Advertise All local VNIs\n")
3655 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3659 evpn_unset_advertise_all_vni(bgp
);
3663 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3664 bgp_evpn_advertise_autort_rfc8365_cmd
,
3665 "autort rfc8365-compatible",
3666 "Auto-derivation of RT\n"
3667 "Auto-derivation of RT using RFC8365\n")
3669 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3673 evpn_set_advertise_autort_rfc8365(bgp
);
3677 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3678 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3679 "no autort rfc8365-compatible",
3681 "Auto-derivation of RT\n"
3682 "Auto-derivation of RT using RFC8365\n")
3684 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3688 evpn_unset_advertise_autort_rfc8365(bgp
);
3692 DEFUN (bgp_evpn_default_originate
,
3693 bgp_evpn_default_originate_cmd
,
3694 "default-originate <ipv4 | ipv6>",
3695 "originate a default route\n"
3696 "ipv4 address family\n"
3697 "ipv6 address family\n")
3701 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3705 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3706 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3710 DEFUN (no_bgp_evpn_default_originate
,
3711 no_bgp_evpn_default_originate_cmd
,
3712 "no default-originate <ipv4 | ipv6>",
3714 "withdraw a default route\n"
3715 "ipv4 address family\n"
3716 "ipv6 address family\n")
3720 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3724 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3725 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3729 DEFPY (dup_addr_detection
,
3730 dup_addr_detection_cmd
,
3731 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3732 "Duplicate address detection\n"
3733 "Max allowed moves before address detected as duplicate\n"
3734 "Num of max allowed moves (2-1000) default 5\n"
3735 "Duplicate address detection time\n"
3736 "Time in seconds (2-1800) default 180\n")
3738 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3743 if (!EVPN_ENABLED(bgp_vrf
)) {
3745 "This command is only supported under the EVPN VRF\n");
3749 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3752 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3754 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3756 bgp_zebra_dup_addr_detection(bgp_vrf
);
3761 DEFPY (dup_addr_detection_auto_recovery
,
3762 dup_addr_detection_auto_recovery_cmd
,
3763 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3764 "Duplicate address detection\n"
3765 "Duplicate address detection freeze\n"
3766 "Duplicate address detection permanent freeze\n"
3767 "Duplicate address detection freeze time (30-3600)\n")
3769 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3770 uint32_t freeze_time
= freeze_time_val
;
3775 if (!EVPN_ENABLED(bgp_vrf
)) {
3777 "This command is only supported under the EVPN VRF\n");
3781 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3782 bgp_vrf
->evpn_info
->dad_freeze
= true;
3783 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3785 bgp_zebra_dup_addr_detection(bgp_vrf
);
3790 DEFPY (no_dup_addr_detection
,
3791 no_dup_addr_detection_cmd
,
3792 "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>]",
3794 "Duplicate address detection\n"
3795 "Max allowed moves before address detected as duplicate\n"
3796 "Num of max allowed moves (2-1000) default 5\n"
3797 "Duplicate address detection time\n"
3798 "Time in seconds (2-1800) default 180\n"
3799 "Duplicate address detection freeze\n"
3800 "Duplicate address detection permanent freeze\n"
3801 "Duplicate address detection freeze time (30-3600)\n")
3803 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3804 uint32_t max_moves
= (uint32_t)max_moves_val
;
3805 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3810 if (!EVPN_ENABLED(bgp_vrf
)) {
3812 "This command is only supported under the EVPN VRF\n");
3817 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3819 /* Reset all parameters to default. */
3820 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3821 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3822 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3823 bgp_vrf
->evpn_info
->dad_freeze
= false;
3824 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3827 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3829 "%% Value does not match with config\n");
3832 bgp_vrf
->evpn_info
->dad_max_moves
=
3833 EVPN_DAD_DEFAULT_MAX_MOVES
;
3837 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3839 "%% Value does not match with config\n");
3842 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3846 if (bgp_vrf
->evpn_info
->dad_freeze_time
3849 "%% Value does not match with config\n");
3852 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3853 bgp_vrf
->evpn_info
->dad_freeze
= false;
3856 if (permanent_val
) {
3857 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3859 "%% Value does not match with config\n");
3862 bgp_vrf
->evpn_info
->dad_freeze
= false;
3866 bgp_zebra_dup_addr_detection(bgp_vrf
);
3871 DEFPY(bgp_evpn_advertise_svi_ip
,
3872 bgp_evpn_advertise_svi_ip_cmd
,
3873 "[no$no] advertise-svi-ip",
3875 "Advertise svi mac-ip routes in EVPN\n")
3877 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3883 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3885 if (!EVPN_ENABLED(bgp
)) {
3887 "This command is only supported under EVPN VRF\n");
3890 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3896 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3897 bgp_evpn_advertise_svi_ip_vni_cmd
,
3898 "[no$no] advertise-svi-ip",
3900 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3902 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3903 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3909 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3911 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3916 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3917 bgp_evpn_advertise_vni_subnet_cmd
,
3919 "Advertise the subnet corresponding to VNI\n")
3921 struct bgp
*bgp_vrf
= NULL
;
3922 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3923 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3928 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3932 evpn_set_advertise_subnet(bgp
, vpn
);
3936 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3937 no_bgp_evpn_advertise_vni_subnet_cmd
,
3938 "no advertise-subnet",
3940 "Advertise All local VNIs\n")
3942 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3943 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3948 evpn_unset_advertise_subnet(bgp
, vpn
);
3952 DEFUN (bgp_evpn_advertise_type5
,
3953 bgp_evpn_advertise_type5_cmd
,
3954 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3955 "Advertise prefix routes\n"
3958 "advertise gateway IP overlay index\n"
3959 "route-map for filtering specific routes\n"
3960 "Name of the route map\n")
3962 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3969 int rmap_changed
= 0;
3970 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3972 bool adv_flag_changed
= false;
3974 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3975 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3976 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3978 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3980 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3982 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3983 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3986 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3990 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3992 "%% Only ipv4 or ipv6 address families are supported\n");
3996 if (safi
!= SAFI_UNICAST
) {
3998 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4002 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
4003 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
4004 vty_out(vty
, "%% Unknown overlay-index type specified\n");
4008 if (afi
== AFI_IP
) {
4009 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4010 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
4011 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4012 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4015 * this is the case for first time ever configuration
4016 * adv ipv4 unicast is enabled for the first time.
4017 * So no need to reset any flag
4019 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4021 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4022 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4023 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4025 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4027 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4029 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4030 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
4033 * This is modify case from gateway-ip
4034 * to no overlay index
4036 adv_flag_changed
= true;
4037 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4038 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4039 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4040 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4041 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4043 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4044 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4047 * This is modify case from no overlay index
4050 adv_flag_changed
= true;
4051 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4052 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4053 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4054 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4058 * Command is issued with the same option
4059 * (no overlay index or gateway-ip) which was
4060 * already configured. So nothing to do.
4061 * However, route-map may have been modified.
4062 * check if route-map has been modified.
4063 * If not, return an error
4069 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4070 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
4071 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4072 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4075 * this is the case for first time ever configuration
4076 * adv ipv6 unicast is enabled for the first time.
4077 * So no need to reset any flag
4079 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4081 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4083 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4085 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4086 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4087 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4089 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4090 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
4093 * This is modify case from gateway-ip
4094 * to no overlay index
4096 adv_flag_changed
= true;
4097 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4098 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4099 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4100 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4101 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4103 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4104 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4107 * This is modify case from no overlay index
4110 adv_flag_changed
= true;
4111 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4112 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4113 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4114 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4118 * Command is issued with the same option
4119 * (no overlay index or gateway-ip) which was
4120 * already configured. So nothing to do.
4121 * However, route-map may have been modified.
4122 * check if route-map has been modified.
4123 * If not, return an error
4130 if ((rmap_changed
) || (adv_flag_changed
)) {
4132 /* If either of these are changed, then FRR needs to
4133 * withdraw already advertised type5 routes.
4135 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4137 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4138 XFREE(MTYPE_ROUTE_MAP_NAME
,
4139 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4140 route_map_counter_decrement(
4141 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4142 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4143 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4148 /* set the route-map for advertise command */
4149 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4150 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4151 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4152 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4153 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4154 route_map_counter_increment(
4155 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4158 /* advertise type-5 routes */
4159 if (advertise_type5_routes(bgp_vrf
, afi
))
4160 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4164 DEFUN (no_bgp_evpn_advertise_type5
,
4165 no_bgp_evpn_advertise_type5_cmd
,
4166 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
4168 "Advertise prefix routes\n"
4171 "route-map for filtering specific routes\n"
4172 "Name of the route map\n")
4174 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4183 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4184 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4186 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4188 "%% Only ipv4 or ipv6 address families are supported\n");
4192 if (safi
!= SAFI_UNICAST
) {
4194 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4198 if (afi
== AFI_IP
) {
4200 /* if we are not advertising ipv4 prefix as type-5
4203 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4204 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4205 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4207 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4208 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4209 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4210 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4211 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4215 /* if we are not advertising ipv6 prefix as type-5
4218 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4219 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4220 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4221 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4222 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4223 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4224 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4225 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4226 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4230 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4231 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4232 XFREE(MTYPE_ROUTE_MAP_NAME
,
4233 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4234 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4235 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4241 DEFPY (bgp_evpn_use_es_l3nhg
,
4242 bgp_evpn_use_es_l3nhg_cmd
,
4243 "[no$no] use-es-l3nhg",
4245 "use L3 nexthop group for host routes with ES destination\n")
4247 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4251 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4252 bgp_evpn_ead_evi_rx_disable_cmd
,
4253 "[no$no] disable-ead-evi-rx",
4255 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4257 bool ead_evi_rx
= no
? true :false;
4259 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4260 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4261 bgp_evpn_switch_ead_evi_rx();
4266 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4267 bgp_evpn_ead_evi_tx_disable_cmd
,
4268 "[no$no] disable-ead-evi-tx",
4270 "Don't advertise EAD-EVI for local ESs\n")
4272 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4276 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4277 bgp_evpn_enable_resolve_overlay_index_cmd
,
4278 "[no$no] enable-resolve-overlay-index",
4280 "Enable Recursive Resolution of type-5 route overlay index\n")
4282 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4284 if (bgp
!= bgp_get_evpn()) {
4285 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4289 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4293 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4294 bgp_evpn_advertise_pip_ip_mac_cmd
,
4295 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4297 "evpn system primary IP\n"
4300 MAC_STR MAC_STR MAC_STR
)
4302 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4303 struct bgp
*bgp_evpn
= NULL
;
4305 if (EVPN_ENABLED(bgp_vrf
)) {
4307 "This command is supported under L3VNI BGP EVPN VRF\n");
4308 return CMD_WARNING_CONFIG_FAILED
;
4310 bgp_evpn
= bgp_get_evpn();
4313 /* pip is already enabled */
4314 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4317 bgp_vrf
->evpn_info
->advertise_pip
= true;
4318 if (ip
.s_addr
!= INADDR_ANY
) {
4319 /* Already configured with same IP */
4320 if (IPV4_ADDR_SAME(&ip
,
4321 &bgp_vrf
->evpn_info
->pip_ip_static
))
4324 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4325 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4327 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4329 /* default instance router-id assignemt */
4331 bgp_vrf
->evpn_info
->pip_ip
=
4332 bgp_evpn
->router_id
;
4335 if (!is_zero_mac(&mac
->eth_addr
)) {
4336 /* Already configured with same MAC */
4337 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4338 &mac
->eth_addr
, ETH_ALEN
) == 0)
4341 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4342 &mac
->eth_addr
, ETH_ALEN
);
4343 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4344 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4347 /* Copy zebra sys mac */
4348 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4349 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4350 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4355 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4357 /* Disable PIP feature */
4358 bgp_vrf
->evpn_info
->advertise_pip
= false;
4359 /* copy anycast mac */
4360 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4361 &bgp_vrf
->rmac
, ETH_ALEN
);
4363 /* remove MAC-IP option retain PIP knob. */
4364 if ((ip
.s_addr
!= INADDR_ANY
) &&
4365 !IPV4_ADDR_SAME(&ip
,
4366 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4368 "%% BGP EVPN PIP IP does not match\n");
4369 return CMD_WARNING_CONFIG_FAILED
;
4372 if (!is_zero_mac(&mac
->eth_addr
) &&
4373 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4374 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4376 "%% BGP EVPN PIP MAC does not match\n");
4377 return CMD_WARNING_CONFIG_FAILED
;
4379 /* pip_rmac can carry vrr_rmac reset only if it matches
4380 * with static value.
4382 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4383 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4385 /* Copy zebra sys mac */
4387 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4388 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4389 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4392 /* copy anycast mac */
4393 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4394 &bgp_vrf
->rmac
, ETH_ALEN
);
4398 /* reset user configured sys MAC */
4399 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4400 /* reset user configured sys IP */
4401 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4402 /* Assign default PIP IP (bgp instance router-id) */
4404 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4406 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4409 if (is_evpn_enabled()) {
4410 struct listnode
*node
= NULL
;
4411 struct bgpevpn
*vpn
= NULL
;
4414 * At this point if bgp_evpn is NULL and evpn is enabled
4415 * something stupid has gone wrong
4419 update_advertise_vrf_routes(bgp_vrf
);
4421 /* Update (svi) type-2 routes */
4422 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4423 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4425 update_routes_for_vni(bgp_evpn
, vpn
);
4433 * Display VNI information - for all or a specific VNI
4435 DEFUN(show_bgp_l2vpn_evpn_vni
,
4436 show_bgp_l2vpn_evpn_vni_cmd
,
4437 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4446 struct bgp
*bgp_evpn
;
4450 json_object
*json
= NULL
;
4451 uint32_t num_l2vnis
= 0;
4452 uint32_t num_l3vnis
= 0;
4453 uint32_t num_vnis
= 0;
4454 struct listnode
*node
= NULL
;
4455 struct bgp
*bgp_temp
= NULL
;
4457 uj
= use_json(argc
, argv
);
4459 bgp_evpn
= bgp_get_evpn();
4463 if (!argv_find(argv
, argc
, "evpn", &idx
))
4467 json
= json_object_new_object();
4469 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4471 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4473 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4474 if (bgp_temp
->l3vni
)
4477 num_vnis
= num_l2vnis
+ num_l3vnis
;
4479 json_object_string_add(json
, "advertiseGatewayMacip",
4480 bgp_evpn
->advertise_gw_macip
4483 json_object_string_add(json
, "advertiseSviMacIp",
4484 bgp_evpn
->evpn_info
->advertise_svi_macip
4485 ? "Enabled" : "Disabled");
4486 json_object_string_add(json
, "advertiseAllVnis",
4487 is_evpn_enabled() ? "Enabled"
4489 json_object_string_add(
4491 bgp_evpn
->vxlan_flood_ctrl
==
4492 VXLAN_FLOOD_HEAD_END_REPL
4493 ? "Head-end replication"
4495 json_object_string_add(
4496 json
, "vxlanFlooding",
4497 bgp_evpn
->vxlan_flood_ctrl
==
4498 VXLAN_FLOOD_HEAD_END_REPL
4501 json_object_int_add(json
, "numVnis", num_vnis
);
4502 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4503 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4505 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4506 bgp_evpn
->advertise_gw_macip
? "Enabled"
4508 vty_out(vty
, "Advertise SVI Macip: %s\n",
4509 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4511 vty_out(vty
, "Advertise All VNI flag: %s\n",
4512 is_evpn_enabled() ? "Enabled" : "Disabled");
4513 vty_out(vty
, "BUM flooding: %s\n",
4514 bgp_evpn
->vxlan_flood_ctrl
==
4515 VXLAN_FLOOD_HEAD_END_REPL
4516 ? "Head-end replication"
4518 vty_out(vty
, "VXLAN flooding: %s\n",
4519 bgp_evpn
->vxlan_flood_ctrl
==
4520 VXLAN_FLOOD_HEAD_END_REPL
4523 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4524 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4526 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4530 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4533 /* Display specific VNI */
4534 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4535 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4539 vty_json(vty
, json
);
4544 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4545 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4546 "show bgp l2vpn evpn vni remote-ip-hash",
4554 struct bgp
*bgp_evpn
;
4557 bgp_evpn
= bgp_get_evpn();
4561 if (!argv_find(argv
, argc
, "evpn", &idx
))
4564 hash_iterate(bgp_evpn
->vnihash
,
4565 (void (*)(struct hash_bucket
*,
4566 void *))bgp_evpn_show_remote_ip_hash
,
4572 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4573 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4574 "show bgp l2vpn evpn vni-svi-hash",
4579 "Show vni-svi-hash\n")
4581 struct bgp
*bgp_evpn
;
4584 bgp_evpn
= bgp_get_evpn();
4588 if (!argv_find(argv
, argc
, "evpn", &idx
))
4591 hash_iterate(bgp_evpn
->vni_svi_hash
,
4592 (void (*)(struct hash_bucket
*,
4593 void *))bgp_evpn_show_vni_svi_hash
,
4599 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4600 show_bgp_l2vpn_evpn_es_evi_cmd
,
4601 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4607 "VxLAN Network Identifier\n"
4610 "Detailed information\n")
4613 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4615 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4620 DEFPY(show_bgp_l2vpn_evpn_es
,
4621 show_bgp_l2vpn_evpn_es_cmd
,
4622 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4627 "Ethernet Segment\n"
4629 "Detailed information\n"
4635 if (!str_to_esi(esi_str
, &esi
)) {
4636 vty_out(vty
, "%% Malformed ESI\n");
4639 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4642 bgp_evpn_es_show(vty
, uj
, !!detail
);
4648 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4649 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4650 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4651 "Ethernet Segment\n"
4657 if (!str_to_esi(esi_str
, &esi
)) {
4658 vty_out(vty
, "%% Malformed ESI\n");
4661 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4664 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4670 DEFPY(show_bgp_l2vpn_evpn_nh
,
4671 show_bgp_l2vpn_evpn_nh_cmd
,
4672 "show bgp l2vpn evpn next-hops [json$uj]",
4680 bgp_evpn_nh_show(vty
, uj
);
4686 * Display EVPN neighbor summary.
4688 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4689 "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]",
4692 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4693 "Summary of BGP neighbor status\n"
4694 "Show only sessions in Established state\n"
4695 "Show only sessions not in Established state\n"
4696 "Show only the specified neighbor session\n"
4697 "Neighbor to display information about\n"
4698 "Neighbor to display information about\n"
4699 "Neighbor on BGP configured interface\n"
4700 "Show only the specified remote AS sessions\n"
4702 "Internal (iBGP) AS sessions\n"
4703 "External (eBGP) AS sessions\n"
4704 "Shorten the information on BGP instances\n"
4705 "Increase table width for longer output\n" JSON_STR
)
4710 char *neighbor
= NULL
;
4711 as_t as
= 0; /* 0 means AS filter not set */
4712 int as_type
= AS_UNSPECIFIED
;
4713 uint16_t show_flags
= 0;
4715 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4716 vrf
= argv
[++idx_vrf
]->arg
;
4718 if (argv_find(argv
, argc
, "failed", &idx
))
4719 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4721 if (argv_find(argv
, argc
, "established", &idx
))
4722 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4725 if (argv_find(argv
, argc
, "neighbor", &idx
))
4726 neighbor
= argv
[idx
+ 1]->arg
;
4728 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4729 if (argv
[idx
+ 1]->arg
[0] == 'i')
4730 as_type
= AS_INTERNAL
;
4731 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4732 as_type
= AS_EXTERNAL
;
4734 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4737 if (argv_find(argv
, argc
, "terse", &idx
))
4738 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4740 if (argv_find(argv
, argc
, "wide", &idx
))
4741 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4743 if (use_json(argc
, argv
))
4744 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4746 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4747 as_type
, as
, show_flags
);
4750 static int bgp_evpn_cli_parse_type_cmp(int *type
, const char *type_str
)
4752 if ((strncmp(type_str
, "ma", 2) == 0) || (strmatch(type_str
, "2")))
4753 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4754 else if ((strncmp(type_str
, "mu", 2) == 0) || (strmatch(type_str
, "3")))
4755 *type
= BGP_EVPN_IMET_ROUTE
;
4756 else if ((strncmp(type_str
, "es", 2) == 0) || (strmatch(type_str
, "4")))
4757 *type
= BGP_EVPN_ES_ROUTE
;
4758 else if ((strncmp(type_str
, "ea", 2) == 0) || (strmatch(type_str
, "1")))
4759 *type
= BGP_EVPN_AD_ROUTE
;
4760 else if ((strncmp(type_str
, "p", 1) == 0) || (strmatch(type_str
, "5")))
4761 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4768 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4772 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4773 /* Specific type is requested */
4774 if (bgp_evpn_cli_parse_type_cmp(type
,
4775 argv
[type_idx
+ 1]->arg
) != 0)
4783 * Display global EVPN routing table.
4785 DEFUN(show_bgp_l2vpn_evpn_route
,
4786 show_bgp_l2vpn_evpn_route_cmd
,
4787 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4793 "Display Detailed Information\n"
4795 EVPN_TYPE_ALL_LIST_HELP_STR
4802 json_object
*json
= NULL
;
4804 uj
= use_json(argc
, argv
);
4806 bgp
= bgp_get_evpn();
4811 json
= json_object_new_object();
4813 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4816 if (argv_find(argv
, argc
, "detail", &detail
))
4819 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4822 * This is an extremely expensive operation at scale
4823 * and as such we need to save as much time as is
4827 vty_json_no_pretty(vty
, json
);
4833 * Display global EVPN routing table for specific RD.
4835 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4836 show_bgp_l2vpn_evpn_route_rd_cmd
,
4837 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4843 EVPN_RT_DIST_HELP_STR
4844 EVPN_ASN_IP_HELP_STR
4845 "All VPN Route Distinguishers\n"
4847 EVPN_TYPE_ALL_LIST_HELP_STR
4852 struct prefix_rd prd
;
4855 json_object
*json
= NULL
;
4856 int idx_ext_community
= 0;
4859 bgp
= bgp_get_evpn();
4863 /* check if we need json output */
4864 uj
= use_json(argc
, argv
);
4866 json
= json_object_new_object();
4868 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4870 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4871 &idx_ext_community
)) {
4872 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4875 "%% Malformed Route Distinguisher\n");
4881 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4885 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4887 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4890 vty_json(vty
, json
);
4896 * Display global EVPN routing table for specific RD and MACIP.
4898 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4899 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4900 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4906 EVPN_RT_DIST_HELP_STR
4907 EVPN_ASN_IP_HELP_STR
4908 "All VPN Route Distinguishers\n"
4910 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4912 "IP address (IPv4 or IPv6)\n"
4917 struct prefix_rd prd
;
4920 int idx_ext_community
= 0;
4924 json_object
*json
= NULL
;
4927 memset(&mac
, 0, sizeof(struct ethaddr
));
4928 memset(&ip
, 0, sizeof(struct ipaddr
));
4930 bgp
= bgp_get_evpn();
4934 /* check if we need json output */
4935 uj
= use_json(argc
, argv
);
4937 json
= json_object_new_object();
4940 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4941 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4942 &idx_ext_community
)) {
4943 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4946 "%% Malformed Route Distinguisher\n");
4953 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4954 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4955 vty_out(vty
, "%% Malformed MAC address\n");
4960 /* get the ip if specified */
4961 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4962 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4963 vty_out(vty
, "%% Malformed IP address\n");
4969 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4971 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4974 vty_json(vty
, json
);
4979 /* Display per ESI routing table */
4980 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4981 show_bgp_l2vpn_evpn_route_esi_cmd
,
4982 "show bgp l2vpn evpn route esi ESI [json]",
4988 "Ethernet Segment Identifier\n"
4994 struct bgp
*bgp
= NULL
;
4995 json_object
*json
= NULL
;
4997 memset(&esi
, 0, sizeof(esi
));
4998 bgp
= bgp_get_evpn();
5002 uj
= use_json(argc
, argv
);
5004 json
= json_object_new_object();
5006 /* get the ESI - ESI-ID is at argv[6] */
5007 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
5008 vty_out(vty
, "%% Malformed ESI\n");
5012 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
5015 vty_json(vty
, json
);
5022 * Display per-VNI EVPN routing table.
5024 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
5025 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5031 "VXLAN Network Identifier\n"
5034 EVPN_TYPE_1_HELP_STR
5035 EVPN_TYPE_1_HELP_STR
5036 EVPN_TYPE_2_HELP_STR
5037 EVPN_TYPE_2_HELP_STR
5038 EVPN_TYPE_3_HELP_STR
5039 EVPN_TYPE_3_HELP_STR
5041 "Remote VTEP IP address\n"
5046 struct in_addr vtep_ip
;
5051 json_object
*json
= NULL
;
5053 bgp
= bgp_get_evpn();
5057 /* check if we need json output */
5058 uj
= use_json(argc
, argv
);
5060 json
= json_object_new_object();
5062 if (!argv_find(argv
, argc
, "evpn", &idx
))
5067 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5069 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
5072 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
5073 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
5074 vty_out(vty
, "%% Malformed VTEP IP address\n");
5079 evpn_show_routes_vni(vty
, bgp
, vni
, type
, false, vtep_ip
, json
);
5082 vty_json(vty
, json
);
5088 * Display per-VNI EVPN routing table for specific MACIP.
5090 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
5091 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
5092 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
5098 "VXLAN Network Identifier\n"
5101 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5103 "IP address (IPv4 or IPv6)\n"
5112 json_object
*json
= NULL
;
5114 bgp
= bgp_get_evpn();
5118 /* check if we need json output */
5119 uj
= use_json(argc
, argv
);
5121 json
= json_object_new_object();
5123 if (!argv_find(argv
, argc
, "evpn", &idx
))
5127 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5130 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5131 vty_out(vty
, "%% Malformed MAC address\n");
5136 memset(&ip
, 0, sizeof(ip
));
5137 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5139 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5140 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5141 vty_out(vty
, "%% Malformed IP address\n");
5146 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5149 vty_json(vty
, json
);
5155 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5157 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5158 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5159 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5165 "VXLAN Network Identifier\n"
5167 EVPN_TYPE_3_HELP_STR
5168 "Originating Router IP address\n"
5174 struct in_addr orig_ip
;
5177 json_object
*json
= NULL
;
5179 bgp
= bgp_get_evpn();
5183 /* check if we need json output */
5184 uj
= use_json(argc
, argv
);
5186 json
= json_object_new_object();
5188 if (!argv_find(argv
, argc
, "evpn", &idx
))
5192 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5195 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5197 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5201 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5204 vty_json(vty
, json
);
5210 * Display per-VNI EVPN routing table - for all VNIs.
5212 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5213 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5214 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5220 "VXLAN Network Identifier\n"
5222 "Print Detailed Output\n"
5224 "Remote VTEP IP address\n"
5228 struct in_addr vtep_ip
;
5231 json_object
*json
= NULL
;
5232 /* Detail Adjust. Adjust indexes according to detail option */
5235 bgp
= bgp_get_evpn();
5239 /* check if we need json output */
5240 uj
= use_json(argc
, argv
);
5242 json
= json_object_new_object();
5244 if (!argv_find(argv
, argc
, "evpn", &idx
))
5247 if (argv_find(argv
, argc
, "detail", &da
))
5250 /* vtep-ip position depends on detail option */
5252 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5254 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5255 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5256 vty_out(vty
, "%% Malformed VTEP IP address\n");
5261 evpn_show_routes_vni_all(vty
, bgp
, 0, false, vtep_ip
, json
, da
);
5264 vty_json(vty
, json
);
5265 json_object_free(json
);
5272 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5274 DEFPY(show_bgp_vni_all
,
5275 show_bgp_vni_all_cmd
,
5276 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5287 json_object
*json
= NULL
;
5289 bgp
= bgp_get_evpn();
5293 /* check if we need json output */
5295 json
= json_object_new_object();
5297 evpn_show_routes_vni_all_type_all(vty
, bgp
, addr
, json
, !!detail
);
5300 vty_json(vty
, json
);
5306 * Display per-VNI EVPN EAD routing table - for all VNIs.
5308 DEFPY(show_bgp_vni_all_ead
,
5309 show_bgp_vni_all_ead_cmd
,
5310 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5316 EVPN_TYPE_1_HELP_STR
5317 EVPN_TYPE_1_HELP_STR
5324 json_object
*json
= NULL
;
5326 bgp
= bgp_get_evpn();
5330 /* check if we need json output */
5332 json
= json_object_new_object();
5334 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_AD_ROUTE
, false, addr
, json
,
5338 vty_json(vty
, json
);
5344 * Display per-VNI EVPN MAC routing table - for all VNIs.
5346 DEFPY(show_bgp_vni_all_macip_mac
,
5347 show_bgp_vni_all_macip_mac_cmd
,
5348 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5354 EVPN_TYPE_2_HELP_STR
5355 EVPN_TYPE_2_HELP_STR
5363 json_object
*json
= NULL
;
5365 bgp
= bgp_get_evpn();
5369 /* check if we need json output */
5371 json
= json_object_new_object();
5373 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5377 vty_json(vty
, json
);
5383 * Display per-VNI EVPN IP routing table - for all VNIs.
5385 DEFPY(show_bgp_vni_all_macip_ip
,
5386 show_bgp_vni_all_macip_ip_cmd
,
5387 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5393 EVPN_TYPE_2_HELP_STR
5394 EVPN_TYPE_2_HELP_STR
5402 json_object
*json
= NULL
;
5404 bgp
= bgp_get_evpn();
5408 /* check if we need json output */
5410 json
= json_object_new_object();
5412 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5416 vty_json(vty
, json
);
5422 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5424 DEFPY(show_bgp_vni_all_imet
,
5425 show_bgp_vni_all_imet_cmd
,
5426 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5432 EVPN_TYPE_3_HELP_STR
5433 EVPN_TYPE_3_HELP_STR
5440 json_object
*json
= NULL
;
5442 bgp
= bgp_get_evpn();
5446 /* check if we need json output */
5448 json
= json_object_new_object();
5450 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5454 vty_json(vty
, json
);
5460 * Display per-VNI EVPN ALL routing tables - for select VNI
5464 "show bgp vni "CMD_VNI_RANGE
"$vni [vtep A.B.C.D$addr] [json$uj]",
5474 json_object
*json
= NULL
;
5475 json_object
*json_mac
= NULL
;
5477 bgp
= bgp_get_evpn();
5481 /* check if we need json output */
5483 json
= json_object_new_object();
5484 json_mac
= json_object_new_object();
5487 evpn_show_routes_vni(vty
, bgp
, vni
, 0, false, addr
, json
);
5490 vty_out(vty
, "\n\nMAC Table:\n\n");
5492 evpn_show_routes_vni(vty
, bgp
, vni
, 0, true, addr
, json_mac
);
5495 json_object_object_add(json
, "macTable", json_mac
);
5496 vty_json(vty
, json
);
5503 * Display per-VNI EVPN EAD routing table - for select VNI
5505 DEFPY(show_bgp_vni_ead
,
5506 show_bgp_vni_ead_cmd
,
5507 "show bgp vni "CMD_VNI_RANGE
"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5513 EVPN_TYPE_1_HELP_STR
5514 EVPN_TYPE_1_HELP_STR
5520 json_object
*json
= NULL
;
5522 bgp
= bgp_get_evpn();
5526 /* check if we need json output */
5528 json
= json_object_new_object();
5530 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_AD_ROUTE
, false, addr
,
5534 vty_json(vty
, json
);
5540 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5542 DEFPY(show_bgp_vni_macip_mac
,
5543 show_bgp_vni_macip_mac_cmd
,
5544 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5550 EVPN_TYPE_2_HELP_STR
5551 EVPN_TYPE_2_HELP_STR
5558 json_object
*json
= NULL
;
5560 bgp
= bgp_get_evpn();
5564 /* check if we need json output */
5566 json
= json_object_new_object();
5568 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5572 vty_json(vty
, json
);
5578 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5580 DEFPY(show_bgp_vni_macip_ip
,
5581 show_bgp_vni_macip_ip_cmd
,
5582 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5588 EVPN_TYPE_2_HELP_STR
5589 EVPN_TYPE_2_HELP_STR
5596 json_object
*json
= NULL
;
5598 bgp
= bgp_get_evpn();
5602 /* check if we need json output */
5604 json
= json_object_new_object();
5606 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5610 vty_json(vty
, json
);
5616 * Display per-VNI EVPN Multicast routing table - for select VNI
5618 DEFPY(show_bgp_vni_imet
,
5619 show_bgp_vni_imet_cmd
,
5620 "show bgp vni "CMD_VNI_RANGE
"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5626 EVPN_TYPE_3_HELP_STR
5627 EVPN_TYPE_3_HELP_STR
5633 json_object
*json
= NULL
;
5635 bgp
= bgp_get_evpn();
5639 /* check if we need json output */
5641 json
= json_object_new_object();
5643 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5647 vty_json(vty
, json
);
5653 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5655 DEFPY(show_bgp_vni_macip_mac_addr
,
5656 show_bgp_vni_macip_mac_addr_cmd
,
5657 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5663 EVPN_TYPE_2_HELP_STR
5664 EVPN_TYPE_2_HELP_STR
5670 json_object
*json
= NULL
;
5672 bgp
= bgp_get_evpn();
5676 /* check if we need json output */
5678 json
= json_object_new_object();
5680 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
->eth_addr
, NULL
, json
);
5683 vty_json(vty
, json
);
5689 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5691 DEFPY(show_bgp_vni_macip_ip_addr
, show_bgp_vni_macip_ip_addr_cmd
,
5692 "show bgp vni " CMD_VNI_RANGE
5693 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5694 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5695 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5696 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR
)
5699 json_object
*json
= NULL
;
5700 struct ipaddr ip_addr
= {.ipa_type
= IPADDR_NONE
};
5702 bgp
= bgp_get_evpn();
5706 /* check if we need json output */
5708 json
= json_object_new_object();
5710 if (sockunion_family(ip
) == AF_INET
) {
5711 ip_addr
.ipa_type
= IPADDR_V4
;
5712 ip_addr
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
5714 ip_addr
.ipa_type
= IPADDR_V6
;
5715 memcpy(&ip_addr
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
5716 sizeof(struct in6_addr
));
5718 evpn_show_route_vni_macip(vty
, bgp
, vni
, NULL
, &ip_addr
, json
);
5721 vty_json(vty
, json
);
5727 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5728 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5729 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5730 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5731 "EVPN route information\n"
5732 "MAC IP routes in the EVI tables linked to the ES\n"
5734 "Detailed information\n" JSON_STR
)
5738 json_object
*json
= NULL
;
5741 if (!str_to_esi(esi_str
, &esi
)) {
5742 vty_out(vty
, "%% Malformed ESI\n");
5751 json
= json_object_new_object();
5752 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5754 vty_json(vty
, json
);
5760 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5761 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5762 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5763 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5764 "EVPN route information\n"
5765 "MAC IP routes in the global table linked to the ES\n"
5767 "Detailed information\n" JSON_STR
)
5771 json_object
*json
= NULL
;
5774 if (!str_to_esi(esi_str
, &esi
)) {
5775 vty_out(vty
, "%% Malformed ESI\n");
5784 json
= json_object_new_object();
5785 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5787 vty_json(vty
, json
);
5793 * Display EVPN import route-target hash table
5795 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5796 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5797 "show bgp l2vpn evpn vrf-import-rt [json]",
5802 "Show vrf import route target\n"
5806 struct bgp
*bgp_evpn
= NULL
;
5807 json_object
*json
= NULL
;
5809 bgp_evpn
= bgp_get_evpn();
5813 uj
= use_json(argc
, argv
);
5815 json
= json_object_new_object();
5817 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5820 vty_json(vty
, json
);
5826 * Display EVPN import route-target hash table
5828 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5829 show_bgp_l2vpn_evpn_import_rt_cmd
,
5830 "show bgp l2vpn evpn import-rt [json]",
5835 "Show import route target\n"
5840 json_object
*json
= NULL
;
5842 bgp
= bgp_get_evpn();
5846 uj
= use_json(argc
, argv
);
5848 json
= json_object_new_object();
5850 evpn_show_import_rts(vty
, bgp
, json
);
5853 vty_json(vty
, json
);
5858 DEFPY_HIDDEN(test_es_add
,
5860 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5863 "Ethernet-segment\n"
5864 "Ethernet-Segment Identifier\n"
5872 struct in_addr vtep_ip
;
5875 bgp
= bgp_get_evpn();
5877 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5881 if (!str_to_esi(esi_str
, &esi
)) {
5882 vty_out(vty
, "%% Malformed ESI\n");
5887 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5889 vty_out(vty
, "%% Failed to delete ES\n");
5893 if (state_str
&& !strcmp(state_str
, "up"))
5897 vtep_ip
= bgp
->router_id
;
5899 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5900 EVPN_MH_DF_PREF_MIN
, false);
5902 vty_out(vty
, "%% Failed to add ES\n");
5909 DEFPY_HIDDEN(test_es_vni_add
,
5910 test_es_vni_add_cmd
,
5911 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5914 "Ethernet-segment\n"
5915 "Ethernet-Segment Identifier\n"
5924 bgp
= bgp_get_evpn();
5926 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5930 if (!str_to_esi(esi_str
, &esi
)) {
5931 vty_out(vty
, "%% Malformed ESI\n");
5936 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5938 vty_out(vty
, "%% Failed to deref ES VNI\n");
5942 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5944 vty_out(vty
, "%% Failed to ref ES VNI\n");
5951 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5952 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5956 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5957 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5958 "Summary of BGP neighbor status\n" JSON_STR
)
5960 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5961 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5962 SHOW_STR BGP_STR EVPN_HELP_STR
5964 "Display Detailed Information\n"
5966 EVPN_TYPE_2_HELP_STR
5967 EVPN_TYPE_2_HELP_STR
5968 EVPN_TYPE_3_HELP_STR
5969 EVPN_TYPE_3_HELP_STR
)
5972 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5973 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5974 SHOW_STR BGP_STR EVPN_HELP_STR
5976 EVPN_RT_DIST_HELP_STR
5977 EVPN_ASN_IP_HELP_STR
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_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5986 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5987 SHOW_STR BGP_STR EVPN_HELP_STR
5989 EVPN_RT_DIST_HELP_STR
5990 EVPN_ASN_IP_HELP_STR
5992 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5994 "IP address (IPv4 or IPv6)\n")
5997 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5998 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5999 SHOW_STR BGP_STR EVPN_HELP_STR
6001 "VXLAN Network Identifier\n"
6004 EVPN_TYPE_2_HELP_STR
6005 EVPN_TYPE_2_HELP_STR
6006 EVPN_TYPE_3_HELP_STR
6007 EVPN_TYPE_3_HELP_STR
6009 "Remote VTEP IP address\n")
6011 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
6012 show_bgp_evpn_route_vni_macip_cmd
,
6013 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
6014 SHOW_STR BGP_STR EVPN_HELP_STR
6016 "VXLAN Network Identifier\n"
6019 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6021 "IP address (IPv4 or IPv6)\n")
6023 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
6024 show_bgp_evpn_route_vni_multicast_cmd
,
6025 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
6026 SHOW_STR BGP_STR EVPN_HELP_STR
6028 "VXLAN Network Identifier\n"
6030 EVPN_TYPE_3_HELP_STR
6031 "Originating Router IP address\n")
6033 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
6034 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6035 SHOW_STR BGP_STR EVPN_HELP_STR
6037 "VXLAN Network Identifier\n"
6039 "Print Detailed Output\n"
6041 "Remote VTEP IP address\n")
6043 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
6044 "show bgp evpn import-rt",
6045 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
6047 DEFUN_NOSH (bgp_evpn_vni
,
6049 "vni " CMD_VNI_RANGE
,
6050 "VXLAN Network Identifier\n"
6054 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6055 struct bgpevpn
*vpn
;
6060 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
6062 /* Create VNI, or mark as configured. */
6063 vpn
= evpn_create_update_vni(bgp
, vni
);
6065 vty_out(vty
, "%% Failed to create VNI \n");
6069 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
6073 DEFUN (no_bgp_evpn_vni
,
6074 no_bgp_evpn_vni_cmd
,
6075 "no vni " CMD_VNI_RANGE
,
6077 "VXLAN Network Identifier\n"
6081 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6082 struct bgpevpn
*vpn
;
6087 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
6089 /* Check if we should disallow. */
6090 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
6092 vty_out(vty
, "%% Specified VNI does not exist\n");
6095 if (!is_vni_configured(vpn
)) {
6096 vty_out(vty
, "%% Specified VNI is not configured\n");
6100 evpn_delete_vni(bgp
, vpn
);
6104 DEFUN_NOSH (exit_vni
,
6107 "Exit from VNI mode\n")
6109 if (vty
->node
== BGP_EVPN_VNI_NODE
)
6110 vty
->node
= BGP_EVPN_NODE
;
6114 DEFUN (bgp_evpn_vrf_rd
,
6115 bgp_evpn_vrf_rd_cmd
,
6116 "rd ASN:NN_OR_IP-ADDRESS:NN",
6117 EVPN_RT_DIST_HELP_STR
6118 EVPN_ASN_IP_HELP_STR
)
6121 struct prefix_rd prd
;
6122 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6127 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6129 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6133 /* If same as existing value, there is nothing more to do. */
6134 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
6137 /* Configure or update the RD. */
6138 evpn_configure_vrf_rd(bgp_vrf
, &prd
, argv
[1]->arg
);
6142 DEFUN (no_bgp_evpn_vrf_rd
,
6143 no_bgp_evpn_vrf_rd_cmd
,
6144 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6146 EVPN_RT_DIST_HELP_STR
6147 EVPN_ASN_IP_HELP_STR
)
6150 struct prefix_rd prd
;
6151 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6156 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6158 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6162 /* Check if we should disallow. */
6163 if (!is_vrf_rd_configured(bgp_vrf
)) {
6164 vty_out(vty
, "%% RD is not configured for this VRF\n");
6168 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
6170 "%% RD specified does not match configuration for this VRF\n");
6174 evpn_unconfigure_vrf_rd(bgp_vrf
);
6178 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
6179 no_bgp_evpn_vrf_rd_without_val_cmd
,
6182 EVPN_RT_DIST_HELP_STR
)
6184 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6189 /* Check if we should disallow. */
6190 if (!is_vrf_rd_configured(bgp_vrf
)) {
6191 vty_out(vty
, "%% RD is not configured for this VRF\n");
6195 evpn_unconfigure_vrf_rd(bgp_vrf
);
6199 DEFUN (bgp_evpn_vni_rd
,
6200 bgp_evpn_vni_rd_cmd
,
6201 "rd ASN:NN_OR_IP-ADDRESS:NN",
6202 EVPN_RT_DIST_HELP_STR
6203 EVPN_ASN_IP_HELP_STR
)
6205 struct prefix_rd prd
;
6206 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6207 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6213 if (!EVPN_ENABLED(bgp
)) {
6215 "This command is only supported under EVPN VRF\n");
6219 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6221 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6225 /* If same as existing value, there is nothing more to do. */
6226 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
6229 /* Configure or update the RD. */
6230 evpn_configure_rd(bgp
, vpn
, &prd
, argv
[1]->arg
);
6234 DEFUN (no_bgp_evpn_vni_rd
,
6235 no_bgp_evpn_vni_rd_cmd
,
6236 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6238 EVPN_RT_DIST_HELP_STR
6239 EVPN_ASN_IP_HELP_STR
)
6241 struct prefix_rd prd
;
6242 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6243 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6249 if (!EVPN_ENABLED(bgp
)) {
6251 "This command is only supported under EVPN VRF\n");
6255 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6257 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6261 /* Check if we should disallow. */
6262 if (!is_rd_configured(vpn
)) {
6263 vty_out(vty
, "%% RD is not configured for this VNI\n");
6267 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
6269 "%% RD specified does not match configuration for this VNI\n");
6273 evpn_unconfigure_rd(bgp
, vpn
);
6277 DEFUN (no_bgp_evpn_vni_rd_without_val
,
6278 no_bgp_evpn_vni_rd_without_val_cmd
,
6281 EVPN_RT_DIST_HELP_STR
)
6283 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6284 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6289 if (!EVPN_ENABLED(bgp
)) {
6291 "This command is only supported under EVPN VRF\n");
6295 /* Check if we should disallow. */
6296 if (!is_rd_configured(vpn
)) {
6297 vty_out(vty
, "%% RD is not configured for this VNI\n");
6301 evpn_unconfigure_rd(bgp
, vpn
);
6306 * Loop over all extended-communities in the route-target list rtl and
6307 * return 1 if we find ecomtarget
6309 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
6310 struct ecommunity
*ecomtarget
)
6312 struct listnode
*node
;
6313 struct ecommunity
*ecom
;
6315 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
6316 if (ecommunity_match(ecom
, ecomtarget
))
6324 * L3 RT version of above.
6326 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
6327 struct ecommunity
*ecomtarget
)
6329 struct listnode
*node
;
6330 struct vrf_route_target
*l3rt
;
6332 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
6333 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
6340 /* display L3VNI related info for a VRF instance */
6341 DEFUN (show_bgp_vrf_l3vni_info
,
6342 show_bgp_vrf_l3vni_info_cmd
,
6343 "show bgp vrf VRFNAME vni [json]",
6351 char buf
[ETHER_ADDR_STRLEN
];
6353 const char *name
= NULL
;
6354 struct bgp
*bgp
= NULL
;
6355 struct listnode
*node
= NULL
;
6356 struct bgpevpn
*vpn
= NULL
;
6357 struct vrf_route_target
*l3rt
;
6358 json_object
*json
= NULL
;
6359 json_object
*json_vnis
= NULL
;
6360 json_object
*json_export_rts
= NULL
;
6361 json_object
*json_import_rts
= NULL
;
6362 bool uj
= use_json(argc
, argv
);
6365 json
= json_object_new_object();
6366 json_vnis
= json_object_new_array();
6367 json_export_rts
= json_object_new_array();
6368 json_import_rts
= json_object_new_array();
6371 name
= argv
[idx_vrf
]->arg
;
6372 bgp
= bgp_lookup_by_name(name
);
6373 if (strmatch(name
, VRF_DEFAULT_NAME
))
6374 bgp
= bgp_get_default();
6378 vty_out(vty
, "BGP instance for VRF %s not found\n",
6381 json_object_string_add(json
, "warning",
6382 "BGP instance not found");
6383 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
6384 json_object_free(json
);
6390 vty_out(vty
, "BGP VRF: %s\n", name
);
6391 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
6392 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
6393 vty_out(vty
, " Rmac: %s\n",
6394 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6395 vty_out(vty
, " VNI Filter: %s\n",
6396 CHECK_FLAG(bgp
->vrf_flags
,
6397 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6398 ? "prefix-routes-only"
6400 vty_out(vty
, " L2-VNI List:\n");
6402 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6403 vty_out(vty
, "%u ", vpn
->vni
);
6405 vty_out(vty
, " Export-RTs:\n");
6407 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6408 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6410 vty_out(vty
, " Import-RTs:\n");
6412 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6413 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6415 vty_out(vty
, " RD: ");
6416 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
), &bgp
->vrf_prd
);
6419 json_object_string_add(json
, "vrf", name
);
6420 json_object_string_addf(json
, "local-ip", "%pI4",
6421 &bgp
->originator_ip
);
6422 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
6423 json_object_string_add(
6425 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6426 json_object_string_add(
6428 CHECK_FLAG(bgp
->vrf_flags
,
6429 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6430 ? "prefix-routes-only"
6432 /* list of l2vnis */
6433 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6434 json_object_array_add(json_vnis
,
6435 json_object_new_int(vpn
->vni
));
6436 json_object_object_add(json
, "l2vnis", json_vnis
);
6439 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6440 json_object_array_add(
6442 json_object_new_string(
6443 ecommunity_str(l3rt
->ecom
)));
6444 json_object_object_add(json
, "export-rts", json_export_rts
);
6447 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6448 json_object_array_add(
6450 json_object_new_string(
6451 ecommunity_str(l3rt
->ecom
)));
6452 json_object_object_add(json
, "import-rts", json_import_rts
);
6453 json_object_string_addf(json
, "rd",
6454 BGP_RD_AS_FORMAT(bgp
->asnotation
),
6459 vty_json(vty
, json
);
6463 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
6466 /* Do nothing if we already have this route-target */
6468 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6470 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
6475 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6477 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
6485 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
6487 /* Verify we already have this route-target */
6489 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6493 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
6495 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6499 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
6505 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
6506 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
6509 int ret
= CMD_SUCCESS
;
6510 bool is_wildcard
= false;
6511 struct ecommunity
*ecom
= NULL
;
6513 for (int i
= rt_idx
; i
< argc
; i
++) {
6514 is_wildcard
= false;
6517 * Special handling for wildcard '*' here.
6519 * Let's just convert it to 0 here so we dont have to modify
6520 * the ecommunity parser.
6522 if ((argv
[i
]->arg
)[0] == '*') {
6523 (argv
[i
]->arg
)[0] = '0';
6527 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
6530 /* Put it back as was */
6532 (argv
[i
]->arg
)[0] = '*';
6535 vty_out(vty
, "%% Malformed Route Target list\n");
6540 ecommunity_str(ecom
);
6543 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
6545 "%% RT specified already configured for this VRF: %s\n",
6547 ecommunity_free(&ecom
);
6552 if (del_rt(bgp
, ecom
, is_import
) != 0) {
6554 "%% RT specified does not match configuration for this VRF: %s\n",
6559 ecommunity_free(&ecom
);
6566 /* import/export rt for l3vni-vrf */
6567 DEFUN (bgp_evpn_vrf_rt
,
6568 bgp_evpn_vrf_rt_cmd
,
6569 "route-target <both|import|export> RTLIST...",
6571 "import and export\n"
6574 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6576 int ret
= CMD_SUCCESS
;
6577 int tmp_ret
= CMD_SUCCESS
;
6579 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6582 return CMD_WARNING_CONFIG_FAILED
;
6584 if (!strcmp(argv
[1]->arg
, "import"))
6585 rt_type
= RT_TYPE_IMPORT
;
6586 else if (!strcmp(argv
[1]->arg
, "export"))
6587 rt_type
= RT_TYPE_EXPORT
;
6588 else if (!strcmp(argv
[1]->arg
, "both"))
6589 rt_type
= RT_TYPE_BOTH
;
6591 vty_out(vty
, "%% Invalid Route Target type\n");
6592 return CMD_WARNING_CONFIG_FAILED
;
6595 if (strmatch(argv
[2]->arg
, "auto")) {
6596 vty_out(vty
, "%% `auto` cannot be configured via list\n");
6597 return CMD_WARNING_CONFIG_FAILED
;
6600 if (rt_type
!= RT_TYPE_IMPORT
) {
6601 for (int i
= 2; i
< argc
; i
++) {
6602 if ((argv
[i
]->arg
)[0] == '*') {
6604 "%% Wildcard '*' only applicable for import\n");
6605 return CMD_WARNING_CONFIG_FAILED
;
6610 /* Add/update the import route-target */
6611 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6612 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
6614 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6617 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6618 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
6620 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6626 DEFPY (bgp_evpn_vrf_rt_auto
,
6627 bgp_evpn_vrf_rt_auto_cmd
,
6628 "route-target <both|import|export>$type auto",
6630 "import and export\n"
6633 "Automatically derive route target\n")
6635 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6639 return CMD_WARNING_CONFIG_FAILED
;
6641 if (strmatch(type
, "import"))
6642 rt_type
= RT_TYPE_IMPORT
;
6643 else if (strmatch(type
, "export"))
6644 rt_type
= RT_TYPE_EXPORT
;
6645 else if (strmatch(type
, "both"))
6646 rt_type
= RT_TYPE_BOTH
;
6648 vty_out(vty
, "%% Invalid Route Target type\n");
6649 return CMD_WARNING_CONFIG_FAILED
;
6652 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6653 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6655 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6656 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6661 DEFUN (no_bgp_evpn_vrf_rt
,
6662 no_bgp_evpn_vrf_rt_cmd
,
6663 "no route-target <both|import|export> RTLIST...",
6666 "import and export\n"
6669 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6671 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6672 int ret
= CMD_SUCCESS
;
6673 int tmp_ret
= CMD_SUCCESS
;
6677 return CMD_WARNING_CONFIG_FAILED
;
6679 if (!strcmp(argv
[2]->arg
, "import"))
6680 rt_type
= RT_TYPE_IMPORT
;
6681 else if (!strcmp(argv
[2]->arg
, "export"))
6682 rt_type
= RT_TYPE_EXPORT
;
6683 else if (!strcmp(argv
[2]->arg
, "both"))
6684 rt_type
= RT_TYPE_BOTH
;
6686 vty_out(vty
, "%% Invalid Route Target type\n");
6687 return CMD_WARNING_CONFIG_FAILED
;
6690 if (!strcmp(argv
[3]->arg
, "auto")) {
6691 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6692 return CMD_WARNING_CONFIG_FAILED
;
6695 if (rt_type
== RT_TYPE_IMPORT
) {
6696 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6698 "%% Import RT is not configured for this VRF\n");
6699 return CMD_WARNING_CONFIG_FAILED
;
6701 } else if (rt_type
== RT_TYPE_EXPORT
) {
6702 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6704 "%% Export RT is not configured for this VRF\n");
6705 return CMD_WARNING_CONFIG_FAILED
;
6707 } else if (rt_type
== RT_TYPE_BOTH
) {
6708 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6709 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6711 "%% Import/Export RT is not configured for this VRF\n");
6712 return CMD_WARNING_CONFIG_FAILED
;
6716 if (rt_type
!= RT_TYPE_IMPORT
) {
6717 for (int i
= 3; i
< argc
; i
++) {
6718 if ((argv
[i
]->arg
)[0] == '*') {
6720 "%% Wildcard '*' only applicable for import\n");
6721 return CMD_WARNING_CONFIG_FAILED
;
6726 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6727 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6729 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6732 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6733 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6735 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6741 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6742 no_bgp_evpn_vrf_rt_auto_cmd
,
6743 "no route-target <both|import|export>$type auto",
6746 "import and export\n"
6749 "Automatically derive route target\n")
6751 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6755 return CMD_WARNING_CONFIG_FAILED
;
6757 if (strmatch(type
, "import"))
6758 rt_type
= RT_TYPE_IMPORT
;
6759 else if (strmatch(type
, "export"))
6760 rt_type
= RT_TYPE_EXPORT
;
6761 else if (strmatch(type
, "both"))
6762 rt_type
= RT_TYPE_BOTH
;
6764 vty_out(vty
, "%% Invalid Route Target type\n");
6765 return CMD_WARNING_CONFIG_FAILED
;
6768 if (rt_type
== RT_TYPE_IMPORT
) {
6769 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6771 "%% Import AUTO RT is not configured for this VRF\n");
6772 return CMD_WARNING_CONFIG_FAILED
;
6774 } else if (rt_type
== RT_TYPE_EXPORT
) {
6775 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6777 "%% Export AUTO RT is not configured for this VRF\n");
6778 return CMD_WARNING_CONFIG_FAILED
;
6780 } else if (rt_type
== RT_TYPE_BOTH
) {
6781 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6782 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6784 "%% Import/Export AUTO RT is not configured for this VRF\n");
6785 return CMD_WARNING_CONFIG_FAILED
;
6789 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6790 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6792 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6793 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6798 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6799 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6801 "EAD ES fragment config\n"
6802 "EVIs per-fragment\n"
6805 bgp_mh_info
->evi_per_es_frag
=
6806 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6811 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6812 "ead-es-route-target export RT",
6813 "EAD ES Route Target\n"
6815 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6817 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6818 struct ecommunity
*ecomadd
= NULL
;
6823 if (!EVPN_ENABLED(bgp
)) {
6824 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6828 /* Add/update the export route-target */
6829 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6831 vty_out(vty
, "%% Malformed Route Target list\n");
6834 ecommunity_str(ecomadd
);
6836 /* Do nothing if we already have this export route-target */
6837 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6839 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6844 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6845 "no ead-es-route-target export RT",
6847 "EAD ES Route Target\n"
6848 "export\n" EVPN_ASN_IP_HELP_STR
)
6850 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6851 struct ecommunity
*ecomdel
= NULL
;
6856 if (!EVPN_ENABLED(bgp
)) {
6857 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6861 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6863 vty_out(vty
, "%% Malformed Route Target list\n");
6866 ecommunity_str(ecomdel
);
6868 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6870 ecommunity_free(&ecomdel
);
6872 "%% RT specified does not match EAD-ES RT configuration\n");
6875 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6880 DEFUN (bgp_evpn_vni_rt
,
6881 bgp_evpn_vni_rt_cmd
,
6882 "route-target <both|import|export> RT",
6884 "import and export\n"
6887 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6889 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6890 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6892 struct ecommunity
*ecomadd
= NULL
;
6897 if (!EVPN_ENABLED(bgp
)) {
6899 "This command is only supported under EVPN VRF\n");
6903 if (!strcmp(argv
[1]->text
, "import"))
6904 rt_type
= RT_TYPE_IMPORT
;
6905 else if (!strcmp(argv
[1]->text
, "export"))
6906 rt_type
= RT_TYPE_EXPORT
;
6907 else if (!strcmp(argv
[1]->text
, "both"))
6908 rt_type
= RT_TYPE_BOTH
;
6910 vty_out(vty
, "%% Invalid Route Target type\n");
6914 /* Add/update the import route-target */
6915 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6916 /* Note that first of the two RTs is created for "both" type */
6917 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6918 ECOMMUNITY_ROUTE_TARGET
, 0);
6920 vty_out(vty
, "%% Malformed Route Target list\n");
6923 ecommunity_str(ecomadd
);
6925 /* Do nothing if we already have this import route-target */
6926 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6927 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6930 /* Add/update the export route-target */
6931 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6932 /* Note that second of the two RTs is created for "both" type */
6933 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6934 ECOMMUNITY_ROUTE_TARGET
, 0);
6936 vty_out(vty
, "%% Malformed Route Target list\n");
6939 ecommunity_str(ecomadd
);
6941 /* Do nothing if we already have this export route-target */
6942 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6943 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6949 DEFUN (no_bgp_evpn_vni_rt
,
6950 no_bgp_evpn_vni_rt_cmd
,
6951 "no route-target <both|import|export> RT",
6954 "import and export\n"
6957 EVPN_ASN_IP_HELP_STR
)
6959 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6960 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6961 int rt_type
, found_ecomdel
;
6962 struct ecommunity
*ecomdel
= NULL
;
6967 if (!EVPN_ENABLED(bgp
)) {
6969 "This command is only supported under EVPN VRF\n");
6973 if (!strcmp(argv
[2]->text
, "import"))
6974 rt_type
= RT_TYPE_IMPORT
;
6975 else if (!strcmp(argv
[2]->text
, "export"))
6976 rt_type
= RT_TYPE_EXPORT
;
6977 else if (!strcmp(argv
[2]->text
, "both"))
6978 rt_type
= RT_TYPE_BOTH
;
6980 vty_out(vty
, "%% Invalid Route Target type\n");
6984 /* The user did "no route-target import", check to see if there are any
6985 * import route-targets configured. */
6986 if (rt_type
== RT_TYPE_IMPORT
) {
6987 if (!is_import_rt_configured(vpn
)) {
6989 "%% Import RT is not configured for this VNI\n");
6992 } else if (rt_type
== RT_TYPE_EXPORT
) {
6993 if (!is_export_rt_configured(vpn
)) {
6995 "%% Export RT is not configured for this VNI\n");
6998 } else if (rt_type
== RT_TYPE_BOTH
) {
6999 if (!is_import_rt_configured(vpn
)
7000 && !is_export_rt_configured(vpn
)) {
7002 "%% Import/Export RT is not configured for this VNI\n");
7007 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
7009 vty_out(vty
, "%% Malformed Route Target list\n");
7012 ecommunity_str(ecomdel
);
7014 if (rt_type
== RT_TYPE_IMPORT
) {
7015 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7016 ecommunity_free(&ecomdel
);
7018 "%% RT specified does not match configuration for this VNI\n");
7021 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7022 } else if (rt_type
== RT_TYPE_EXPORT
) {
7023 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7024 ecommunity_free(&ecomdel
);
7026 "%% RT specified does not match configuration for this VNI\n");
7029 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7030 } else if (rt_type
== RT_TYPE_BOTH
) {
7033 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7034 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7038 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7039 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7043 if (!found_ecomdel
) {
7044 ecommunity_free(&ecomdel
);
7046 "%% RT specified does not match configuration for this VNI\n");
7054 DEFUN (no_bgp_evpn_vni_rt_without_val
,
7055 no_bgp_evpn_vni_rt_without_val_cmd
,
7056 "no route-target <import|export>",
7062 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
7063 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
7069 if (!EVPN_ENABLED(bgp
)) {
7071 "This command is only supported under EVPN VRF\n");
7075 if (!strcmp(argv
[2]->text
, "import")) {
7076 rt_type
= RT_TYPE_IMPORT
;
7077 } else if (!strcmp(argv
[2]->text
, "export")) {
7078 rt_type
= RT_TYPE_EXPORT
;
7080 vty_out(vty
, "%% Invalid Route Target type\n");
7084 /* Check if we should disallow. */
7085 if (rt_type
== RT_TYPE_IMPORT
) {
7086 if (!is_import_rt_configured(vpn
)) {
7088 "%% Import RT is not configured for this VNI\n");
7092 if (!is_export_rt_configured(vpn
)) {
7094 "%% Export RT is not configured for this VNI\n");
7099 /* Unconfigure the RT. */
7100 if (rt_type
== RT_TYPE_IMPORT
)
7101 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
7103 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
7107 static int vni_cmp(const void **a
, const void **b
)
7109 const struct bgpevpn
*first
= *a
;
7110 const struct bgpevpn
*secnd
= *b
;
7112 return secnd
->vni
- first
->vni
;
7116 * Output EVPN configuration information.
7118 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7121 if (bgp
->advertise_all_vni
)
7122 vty_out(vty
, " advertise-all-vni\n");
7124 if (hashcount(bgp
->vnihash
)) {
7125 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
7126 struct listnode
*ln
;
7127 struct bgpevpn
*data
;
7129 list_sort(vnilist
, vni_cmp
);
7130 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
7131 write_vni_config(vty
, data
);
7133 list_delete(&vnilist
);
7136 if (bgp
->advertise_autort_rfc8365
)
7137 vty_out(vty
, " autort rfc8365-compatible\n");
7139 if (bgp
->advertise_gw_macip
)
7140 vty_out(vty
, " advertise-default-gw\n");
7142 if (bgp
->evpn_info
->advertise_svi_macip
)
7143 vty_out(vty
, " advertise-svi-ip\n");
7145 if (bgp
->resolve_overlay_index
)
7146 vty_out(vty
, " enable-resolve-overlay-index\n");
7148 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
7149 vty_out(vty
, " ead-es-frag evi-limit %u\n",
7150 bgp_mh_info
->evi_per_es_frag
);
7152 if (bgp_mh_info
->host_routes_use_l3nhg
!=
7153 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
7154 if (bgp_mh_info
->host_routes_use_l3nhg
)
7155 vty_out(vty
, " use-es-l3nhg\n");
7157 vty_out(vty
, " no use-es-l3nhg\n");
7160 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
7161 if (bgp_mh_info
->ead_evi_rx
)
7162 vty_out(vty
, " no disable-ead-evi-rx\n");
7164 vty_out(vty
, " disable-ead-evi-rx\n");
7167 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
7168 if (bgp_mh_info
->ead_evi_tx
)
7169 vty_out(vty
, " no disable-ead-evi-tx\n");
7171 vty_out(vty
, " disable-ead-evi-tx\n");
7174 if (!bgp
->evpn_info
->dup_addr_detect
)
7175 vty_out(vty
, " no dup-addr-detection\n");
7177 if (bgp
->evpn_info
->dad_max_moves
!=
7178 EVPN_DAD_DEFAULT_MAX_MOVES
||
7179 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
7180 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
7181 bgp
->evpn_info
->dad_max_moves
,
7182 bgp
->evpn_info
->dad_time
);
7184 if (bgp
->evpn_info
->dad_freeze
) {
7185 if (bgp
->evpn_info
->dad_freeze_time
)
7187 " dup-addr-detection freeze %u\n",
7188 bgp
->evpn_info
->dad_freeze_time
);
7191 " dup-addr-detection freeze permanent\n");
7194 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
7195 vty_out(vty
, " flooding disable\n");
7197 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7198 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
7199 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7200 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
7201 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7204 " advertise ipv4 unicast\n");
7205 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7206 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
7207 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7209 " advertise ipv4 unicast gateway-ip route-map %s\n",
7210 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7212 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
7215 /* EAD ES export route-target */
7216 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
7217 struct ecommunity
*ecom
;
7219 struct listnode
*node
;
7221 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
7224 ecom_str
= ecommunity_ecom2str(
7225 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7226 vty_out(vty
, " ead-es-route-target export %s\n",
7228 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7232 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7233 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
7234 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7236 " advertise ipv6 unicast route-map %s\n",
7237 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7240 " advertise ipv6 unicast\n");
7241 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7242 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
7243 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7245 " advertise ipv6 unicast gateway-ip route-map %s\n",
7246 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7248 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
7251 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7252 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
7253 vty_out(vty
, " default-originate ipv4\n");
7255 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7256 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
7257 vty_out(vty
, " default-originate ipv6\n");
7259 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
7260 if (!bgp
->evpn_info
->advertise_pip
)
7261 vty_out(vty
, " no advertise-pip\n");
7262 if (bgp
->evpn_info
->advertise_pip
) {
7263 if (bgp
->evpn_info
->pip_ip_static
.s_addr
7265 vty_out(vty
, " advertise-pip ip %pI4",
7266 &bgp
->evpn_info
->pip_ip_static
);
7268 bgp
->evpn_info
->pip_rmac_static
))) {
7269 char buf
[ETHER_ADDR_STRLEN
];
7271 vty_out(vty
, " mac %s",
7281 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
7282 vty_out(vty
, " rd %s\n", bgp
->vrf_prd_pretty
);
7284 /* import route-target */
7285 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
7287 struct listnode
*node
, *nnode
;
7288 struct vrf_route_target
*l3rt
;
7290 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
7293 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7296 ecom_str
= ecommunity_ecom2str(
7297 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7299 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
7300 char *vni_str
= NULL
;
7302 vni_str
= strchr(ecom_str
, ':');
7304 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7308 /* Move pointer to vni */
7311 vty_out(vty
, " route-target import *:%s\n",
7315 vty_out(vty
, " route-target import %s\n",
7318 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7322 /* import route-target auto */
7323 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
7324 vty_out(vty
, " route-target import auto\n");
7326 /* export route-target */
7327 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
7329 struct listnode
*node
, *nnode
;
7330 struct vrf_route_target
*l3rt
;
7332 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
7335 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7338 ecom_str
= ecommunity_ecom2str(
7339 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7340 vty_out(vty
, " route-target export %s\n", ecom_str
);
7341 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7345 /* export route-target auto */
7346 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
7347 vty_out(vty
, " route-target export auto\n");
7350 void bgp_ethernetvpn_init(void)
7352 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
7353 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
7354 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
7355 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
7356 install_element(VIEW_NODE
,
7357 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
7358 install_element(VIEW_NODE
,
7359 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
7362 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
7365 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
7366 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
7367 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
7368 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
7369 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
7370 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
7371 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
7372 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
7373 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
7374 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
7375 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
7376 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
7377 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
7378 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
7379 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
7380 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
7381 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
7382 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
7383 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
7384 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
7385 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
7386 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
7387 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
7388 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
7389 install_element(BGP_EVPN_NODE
,
7390 &bgp_evpn_enable_resolve_overlay_index_cmd
);
7393 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
7394 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
7396 /* "show bgp l2vpn evpn" commands. */
7397 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
7398 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
7399 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
7400 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
7401 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
7402 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
7403 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
7404 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
7405 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
7406 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
7407 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
7408 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
7409 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
7410 install_element(VIEW_NODE
,
7411 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
7412 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
7413 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
7414 install_element(VIEW_NODE
,
7415 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
7416 install_element(VIEW_NODE
,
7417 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
7418 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
7419 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
7421 /* "show bgp vni" commands. */
7422 install_element(VIEW_NODE
, &show_bgp_vni_all_cmd
);
7423 install_element(VIEW_NODE
, &show_bgp_vni_all_ead_cmd
);
7424 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_mac_cmd
);
7425 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_ip_cmd
);
7426 install_element(VIEW_NODE
, &show_bgp_vni_all_imet_cmd
);
7427 install_element(VIEW_NODE
, &show_bgp_vni_cmd
);
7428 install_element(VIEW_NODE
, &show_bgp_vni_ead_cmd
);
7429 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_cmd
);
7430 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_cmd
);
7431 install_element(VIEW_NODE
, &show_bgp_vni_imet_cmd
);
7432 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_addr_cmd
);
7433 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_addr_cmd
);
7435 /* "show bgp evpn" commands. */
7436 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
7437 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
7438 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
7439 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
7440 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
7441 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
7442 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
7443 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
7444 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
7445 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
7446 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
7447 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
7449 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
7450 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
7451 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
7452 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
7453 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
7454 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
7455 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
7456 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
7457 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
7458 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
7459 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
7460 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
7461 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
7462 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
7463 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
7464 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
7465 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
7466 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
7467 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
7468 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
7469 install_element(BGP_EVPN_VNI_NODE
,
7470 &bgp_evpn_advertise_default_gw_vni_cmd
);
7471 install_element(BGP_EVPN_VNI_NODE
,
7472 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
7473 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
7474 install_element(BGP_EVPN_VNI_NODE
,
7475 &no_bgp_evpn_advertise_vni_subnet_cmd
);