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
, bool self_orig
)
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 if (self_orig
&& (pi
->peer
!= bgp
->peer_self
))
3098 /* Overall header/legend displayed once. */
3100 bgp_evpn_show_route_header(vty
, bgp
,
3105 "%19s Extended Community\n"
3110 /* RD header - per RD. */
3112 bgp_evpn_show_route_rd_header(
3113 vty
, rd_dest
, json_rd
, rd_str
,
3122 json_prefix
= json_object_new_object();
3123 json_paths
= json_object_new_array();
3124 json_object_string_addf(json_prefix
, "prefix",
3126 json_object_int_add(json_prefix
, "prefixLen",
3130 /* Prefix and num paths displayed once per prefix. */
3132 route_vty_out_detail_header(
3134 bgp_dest_get_prefix(dest
),
3135 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3136 SAFI_EVPN
, json_prefix
, false);
3138 /* For EVPN, the prefix is displayed for each path (to
3140 * with code that already exists).
3142 for (; pi
; pi
= pi
->next
) {
3143 json_object
*json_path
= NULL
;
3146 add_prefix_to_json
= 1;
3150 json_path
= json_object_new_array();
3153 route_vty_out_detail(
3155 bgp_dest_get_prefix(dest
), pi
,
3156 AFI_L2VPN
, SAFI_EVPN
,
3157 RPKI_NOT_BEING_USED
, json_path
);
3159 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3163 json_object_array_add(json_paths
,
3168 if (add_prefix_to_json
) {
3169 json_object_object_add(json_prefix
,
3172 json_object_object_addf(json_rd
,
3176 json_object_free(json_prefix
);
3177 json_object_free(json_paths
);
3186 json_object_object_add(json
, rd_str
, json_rd
);
3188 json_object_free(json_rd
);
3195 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3196 json_object_int_add(json
, "numPaths", path_cnt
);
3198 if (prefix_cnt
== 0) {
3199 vty_out(vty
, "No EVPN prefixes %sexist\n",
3200 type
? "(of requested type) " : "");
3202 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3203 prefix_cnt
, path_cnt
,
3204 type
? " (of requested type)" : "");
3209 int bgp_evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3210 bool use_json
, int detail
)
3212 json_object
*json
= NULL
;
3215 json
= json_object_new_object();
3217 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
, false);
3220 vty_json(vty
, json
);
3225 * Display specified VNI (vty handler)
3227 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3231 struct bgpevpn
*vpn
;
3233 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3236 display_vni(vty
, vpn
, json
);
3238 struct bgp
*bgp_temp
;
3239 struct listnode
*node
= NULL
;
3241 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3242 if (bgp_temp
->l3vni
== vni
) {
3244 display_l3vni(vty
, bgp_temp
, json
);
3251 vty_out(vty
, "{}\n");
3253 vty_out(vty
, "VNI not found\n");
3260 * Display a VNI (upon user query).
3262 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3266 struct bgp
*bgp_temp
= NULL
;
3267 struct listnode
*node
;
3271 vty_out(vty
, "Flags: * - Kernel\n");
3272 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3273 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3276 /* print all L2 VNIS */
3279 hash_iterate(bgp
->vnihash
,
3280 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3283 /* print all L3 VNIs */
3284 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3285 show_l3vni_entry(vty
, bgp_temp
, json
);
3289 * evpn - enable advertisement of svi MAC-IP
3291 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3295 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3297 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3300 bgp
->evpn_info
->advertise_svi_macip
= set
;
3301 bgp_zebra_advertise_svi_macip(bgp
,
3302 bgp
->evpn_info
->advertise_svi_macip
, 0);
3304 if (set
&& vpn
->advertise_svi_macip
)
3306 else if (!set
&& !vpn
->advertise_svi_macip
)
3309 vpn
->advertise_svi_macip
= set
;
3310 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3316 * evpn - enable advertisement of default g/w
3318 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3321 if (bgp
->advertise_gw_macip
)
3324 bgp
->advertise_gw_macip
= 1;
3325 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3327 if (vpn
->advertise_gw_macip
)
3330 vpn
->advertise_gw_macip
= 1;
3331 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3338 * evpn - disable advertisement of default g/w
3340 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3341 struct bgpevpn
*vpn
)
3344 if (!bgp
->advertise_gw_macip
)
3347 bgp
->advertise_gw_macip
= 0;
3348 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3350 if (!vpn
->advertise_gw_macip
)
3353 vpn
->advertise_gw_macip
= 0;
3354 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3361 * evpn - enable advertisement of default g/w
3363 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3364 afi_t afi
, bool add
)
3366 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3369 /* bail if we are already advertising default route */
3370 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3374 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3375 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3376 else if (afi
== AFI_IP6
)
3377 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3378 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3380 /* bail out if we havent advertised the default route */
3381 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3384 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3385 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3386 else if (afi
== AFI_IP6
)
3387 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3388 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3391 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3395 * evpn - enable advertisement of default g/w
3397 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3398 struct bgpevpn
*vpn
)
3400 if (vpn
->advertise_subnet
)
3403 vpn
->advertise_subnet
= 1;
3404 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3408 * evpn - disable advertisement of default g/w
3410 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3412 if (!vpn
->advertise_subnet
)
3415 vpn
->advertise_subnet
= 0;
3416 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3420 * EVPN (VNI advertisement) enabled. Register with zebra.
3422 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3424 bgp
->advertise_all_vni
= 1;
3426 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3430 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3431 * cache, EVPN routes (delete and withdraw from peers).
3433 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3435 bgp
->advertise_all_vni
= 0;
3436 bgp_set_evpn(bgp_get_default());
3437 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3438 bgp_evpn_cleanup_on_disable(bgp
);
3441 /* Set resolve overlay index flag */
3442 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3444 if (set
== bgp
->resolve_overlay_index
)
3448 bgp
->resolve_overlay_index
= true;
3449 hash_iterate(bgp
->vnihash
,
3450 (void (*)(struct hash_bucket
*, void *))
3451 bgp_evpn_handle_resolve_overlay_index_set
,
3456 (void (*)(struct hash_bucket
*, void *))
3457 bgp_evpn_handle_resolve_overlay_index_unset
,
3459 bgp
->resolve_overlay_index
= false;
3464 * EVPN - use RFC8365 to auto-derive RT
3466 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3468 bgp
->advertise_autort_rfc8365
= 1;
3469 bgp_evpn_handle_autort_change(bgp
);
3473 * EVPN - don't use RFC8365 to auto-derive RT
3475 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3477 bgp
->advertise_autort_rfc8365
= 0;
3478 bgp_evpn_handle_autort_change(bgp
);
3481 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3484 struct listnode
*node
, *nnode
;
3485 struct ecommunity
*ecom
;
3487 if (is_vni_configured(vpn
)) {
3488 vty_out(vty
, " vni %u\n", vpn
->vni
);
3489 if (is_rd_configured(vpn
))
3490 vty_out(vty
, " rd %s\n", vpn
->prd_pretty
);
3492 if (is_import_rt_configured(vpn
)) {
3493 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3495 ecom_str
= ecommunity_ecom2str(
3496 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3497 vty_out(vty
, " route-target import %s\n",
3499 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3503 if (is_export_rt_configured(vpn
)) {
3504 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3506 ecom_str
= ecommunity_ecom2str(
3507 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3508 vty_out(vty
, " route-target export %s\n",
3510 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3514 if (vpn
->advertise_gw_macip
)
3515 vty_out(vty
, " advertise-default-gw\n");
3517 if (vpn
->advertise_svi_macip
)
3518 vty_out(vty
, " advertise-svi-ip\n");
3520 if (vpn
->advertise_subnet
)
3521 vty_out(vty
, " advertise-subnet\n");
3523 vty_out(vty
, " exit-vni\n");
3527 #include "bgpd/bgp_evpn_vty_clippy.c"
3529 DEFPY(bgp_evpn_flood_control
,
3530 bgp_evpn_flood_control_cmd
,
3531 "[no$no] flooding <disable$disable|head-end-replication$her>",
3533 "Specify handling for BUM packets\n"
3534 "Do not flood any BUM packets\n"
3535 "Flood BUM packets using head-end replication\n")
3537 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3538 enum vxlan_flood_control flood_ctrl
;
3544 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3546 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3550 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3553 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3554 bgp_evpn_flood_control_change(bgp
);
3559 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3560 bgp_evpn_advertise_default_gw_vni_cmd
,
3561 "advertise-default-gw",
3562 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3564 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3565 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3570 evpn_set_advertise_default_gw(bgp
, vpn
);
3575 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3576 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3577 "no advertise-default-gw",
3579 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3581 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3582 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3587 evpn_unset_advertise_default_gw(bgp
, vpn
);
3593 DEFUN (bgp_evpn_advertise_default_gw
,
3594 bgp_evpn_advertise_default_gw_cmd
,
3595 "advertise-default-gw",
3596 "Advertise All default g/w mac-ip routes in EVPN\n")
3598 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3603 if (!EVPN_ENABLED(bgp
)) {
3605 "This command is only supported under the EVPN VRF\n");
3609 evpn_set_advertise_default_gw(bgp
, NULL
);
3614 DEFUN (no_bgp_evpn_advertise_default_gw
,
3615 no_bgp_evpn_advertise_default_gw_cmd
,
3616 "no advertise-default-gw",
3618 "Withdraw All default g/w mac-ip routes from EVPN\n")
3620 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3625 evpn_unset_advertise_default_gw(bgp
, NULL
);
3630 DEFUN (bgp_evpn_advertise_all_vni
,
3631 bgp_evpn_advertise_all_vni_cmd
,
3632 "advertise-all-vni",
3633 "Advertise All local VNIs\n")
3635 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3636 struct bgp
*bgp_evpn
= NULL
;
3641 bgp_evpn
= bgp_get_evpn();
3642 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3643 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3644 bgp_evpn
->name_pretty
);
3645 return CMD_WARNING_CONFIG_FAILED
;
3648 evpn_set_advertise_all_vni(bgp
);
3652 DEFUN (no_bgp_evpn_advertise_all_vni
,
3653 no_bgp_evpn_advertise_all_vni_cmd
,
3654 "no advertise-all-vni",
3656 "Advertise All local VNIs\n")
3658 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3662 evpn_unset_advertise_all_vni(bgp
);
3666 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3667 bgp_evpn_advertise_autort_rfc8365_cmd
,
3668 "autort rfc8365-compatible",
3669 "Auto-derivation of RT\n"
3670 "Auto-derivation of RT using RFC8365\n")
3672 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3676 evpn_set_advertise_autort_rfc8365(bgp
);
3680 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3681 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3682 "no autort rfc8365-compatible",
3684 "Auto-derivation of RT\n"
3685 "Auto-derivation of RT using RFC8365\n")
3687 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3691 evpn_unset_advertise_autort_rfc8365(bgp
);
3695 DEFUN (bgp_evpn_default_originate
,
3696 bgp_evpn_default_originate_cmd
,
3697 "default-originate <ipv4 | ipv6>",
3698 "originate a default route\n"
3699 "ipv4 address family\n"
3700 "ipv6 address family\n")
3704 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3708 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3709 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3713 DEFUN (no_bgp_evpn_default_originate
,
3714 no_bgp_evpn_default_originate_cmd
,
3715 "no default-originate <ipv4 | ipv6>",
3717 "withdraw a default route\n"
3718 "ipv4 address family\n"
3719 "ipv6 address family\n")
3723 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3727 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3728 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3732 DEFPY (dup_addr_detection
,
3733 dup_addr_detection_cmd
,
3734 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3735 "Duplicate address detection\n"
3736 "Max allowed moves before address detected as duplicate\n"
3737 "Num of max allowed moves (2-1000) default 5\n"
3738 "Duplicate address detection time\n"
3739 "Time in seconds (2-1800) default 180\n")
3741 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3746 if (!EVPN_ENABLED(bgp_vrf
)) {
3748 "This command is only supported under the EVPN VRF\n");
3752 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3755 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3757 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3759 bgp_zebra_dup_addr_detection(bgp_vrf
);
3764 DEFPY (dup_addr_detection_auto_recovery
,
3765 dup_addr_detection_auto_recovery_cmd
,
3766 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3767 "Duplicate address detection\n"
3768 "Duplicate address detection freeze\n"
3769 "Duplicate address detection permanent freeze\n"
3770 "Duplicate address detection freeze time (30-3600)\n")
3772 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3773 uint32_t freeze_time
= freeze_time_val
;
3778 if (!EVPN_ENABLED(bgp_vrf
)) {
3780 "This command is only supported under the EVPN VRF\n");
3784 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3785 bgp_vrf
->evpn_info
->dad_freeze
= true;
3786 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3788 bgp_zebra_dup_addr_detection(bgp_vrf
);
3793 DEFPY (no_dup_addr_detection
,
3794 no_dup_addr_detection_cmd
,
3795 "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>]",
3797 "Duplicate address detection\n"
3798 "Max allowed moves before address detected as duplicate\n"
3799 "Num of max allowed moves (2-1000) default 5\n"
3800 "Duplicate address detection time\n"
3801 "Time in seconds (2-1800) default 180\n"
3802 "Duplicate address detection freeze\n"
3803 "Duplicate address detection permanent freeze\n"
3804 "Duplicate address detection freeze time (30-3600)\n")
3806 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3807 uint32_t max_moves
= (uint32_t)max_moves_val
;
3808 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3813 if (!EVPN_ENABLED(bgp_vrf
)) {
3815 "This command is only supported under the EVPN VRF\n");
3820 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3822 /* Reset all parameters to default. */
3823 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3824 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3825 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3826 bgp_vrf
->evpn_info
->dad_freeze
= false;
3827 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3830 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3832 "%% Value does not match with config\n");
3835 bgp_vrf
->evpn_info
->dad_max_moves
=
3836 EVPN_DAD_DEFAULT_MAX_MOVES
;
3840 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3842 "%% Value does not match with config\n");
3845 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3849 if (bgp_vrf
->evpn_info
->dad_freeze_time
3852 "%% Value does not match with config\n");
3855 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3856 bgp_vrf
->evpn_info
->dad_freeze
= false;
3859 if (permanent_val
) {
3860 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3862 "%% Value does not match with config\n");
3865 bgp_vrf
->evpn_info
->dad_freeze
= false;
3869 bgp_zebra_dup_addr_detection(bgp_vrf
);
3874 DEFPY(bgp_evpn_advertise_svi_ip
,
3875 bgp_evpn_advertise_svi_ip_cmd
,
3876 "[no$no] advertise-svi-ip",
3878 "Advertise svi mac-ip routes in EVPN\n")
3880 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3886 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3888 if (!EVPN_ENABLED(bgp
)) {
3890 "This command is only supported under EVPN VRF\n");
3893 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3899 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3900 bgp_evpn_advertise_svi_ip_vni_cmd
,
3901 "[no$no] advertise-svi-ip",
3903 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3905 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3906 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3912 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3914 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3919 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3920 bgp_evpn_advertise_vni_subnet_cmd
,
3922 "Advertise the subnet corresponding to VNI\n")
3924 struct bgp
*bgp_vrf
= NULL
;
3925 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3926 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3931 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3935 evpn_set_advertise_subnet(bgp
, vpn
);
3939 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3940 no_bgp_evpn_advertise_vni_subnet_cmd
,
3941 "no advertise-subnet",
3943 "Advertise All local VNIs\n")
3945 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3946 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3951 evpn_unset_advertise_subnet(bgp
, vpn
);
3955 DEFUN (bgp_evpn_advertise_type5
,
3956 bgp_evpn_advertise_type5_cmd
,
3957 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3958 "Advertise prefix routes\n"
3961 "advertise gateway IP overlay index\n"
3962 "route-map for filtering specific routes\n"
3963 "Name of the route map\n")
3965 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3972 int rmap_changed
= 0;
3973 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3975 bool adv_flag_changed
= false;
3977 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3978 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3979 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3981 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3983 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3985 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3986 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3989 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3993 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3995 "%% Only ipv4 or ipv6 address families are supported\n");
3999 if (safi
!= SAFI_UNICAST
) {
4001 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4005 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
4006 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
4007 vty_out(vty
, "%% Unknown overlay-index type specified\n");
4011 if (afi
== AFI_IP
) {
4012 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4013 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
4014 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4015 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4018 * this is the case for first time ever configuration
4019 * adv ipv4 unicast is enabled for the first time.
4020 * So no need to reset any flag
4022 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4024 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4025 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4026 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4028 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4029 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4030 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4032 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4033 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
4036 * This is modify case from gateway-ip
4037 * to no overlay index
4039 adv_flag_changed
= true;
4040 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4041 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4042 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4043 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4044 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4046 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4047 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4050 * This is modify case from no overlay index
4053 adv_flag_changed
= true;
4054 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4055 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4056 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4057 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4061 * Command is issued with the same option
4062 * (no overlay index or gateway-ip) which was
4063 * already configured. So nothing to do.
4064 * However, route-map may have been modified.
4065 * check if route-map has been modified.
4066 * If not, return an error
4072 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4073 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
4074 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4075 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4078 * this is the case for first time ever configuration
4079 * adv ipv6 unicast is enabled for the first time.
4080 * So no need to reset any flag
4082 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4084 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4085 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4086 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4088 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4089 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4090 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4092 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4093 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
4096 * This is modify case from gateway-ip
4097 * to no overlay index
4099 adv_flag_changed
= true;
4100 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4101 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4102 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4103 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4104 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4106 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4107 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4110 * This is modify case from no overlay index
4113 adv_flag_changed
= true;
4114 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4115 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4116 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4117 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4121 * Command is issued with the same option
4122 * (no overlay index or gateway-ip) which was
4123 * already configured. So nothing to do.
4124 * However, route-map may have been modified.
4125 * check if route-map has been modified.
4126 * If not, return an error
4133 if ((rmap_changed
) || (adv_flag_changed
)) {
4135 /* If either of these are changed, then FRR needs to
4136 * withdraw already advertised type5 routes.
4138 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4140 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4141 XFREE(MTYPE_ROUTE_MAP_NAME
,
4142 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4143 route_map_counter_decrement(
4144 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4145 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4146 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4151 /* set the route-map for advertise command */
4152 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4153 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4154 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4155 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4156 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4157 route_map_counter_increment(
4158 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4161 /* advertise type-5 routes */
4162 if (advertise_type5_routes(bgp_vrf
, afi
))
4163 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4167 DEFUN (no_bgp_evpn_advertise_type5
,
4168 no_bgp_evpn_advertise_type5_cmd
,
4169 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
4171 "Advertise prefix routes\n"
4174 "route-map for filtering specific routes\n"
4175 "Name of the route map\n")
4177 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4186 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4187 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4189 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4191 "%% Only ipv4 or ipv6 address families are supported\n");
4195 if (safi
!= SAFI_UNICAST
) {
4197 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4201 if (afi
== AFI_IP
) {
4203 /* if we are not advertising ipv4 prefix as type-5
4206 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4207 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4208 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4209 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4210 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4211 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4212 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4213 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4214 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4218 /* if we are not advertising ipv6 prefix as type-5
4221 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4222 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4223 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4224 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4225 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4226 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4227 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4228 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4229 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4233 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4234 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4235 XFREE(MTYPE_ROUTE_MAP_NAME
,
4236 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4237 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4238 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4244 DEFPY (bgp_evpn_use_es_l3nhg
,
4245 bgp_evpn_use_es_l3nhg_cmd
,
4246 "[no$no] use-es-l3nhg",
4248 "use L3 nexthop group for host routes with ES destination\n")
4250 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4254 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4255 bgp_evpn_ead_evi_rx_disable_cmd
,
4256 "[no$no] disable-ead-evi-rx",
4258 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4260 bool ead_evi_rx
= no
? true :false;
4262 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4263 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4264 bgp_evpn_switch_ead_evi_rx();
4269 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4270 bgp_evpn_ead_evi_tx_disable_cmd
,
4271 "[no$no] disable-ead-evi-tx",
4273 "Don't advertise EAD-EVI for local ESs\n")
4275 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4279 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4280 bgp_evpn_enable_resolve_overlay_index_cmd
,
4281 "[no$no] enable-resolve-overlay-index",
4283 "Enable Recursive Resolution of type-5 route overlay index\n")
4285 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4287 if (bgp
!= bgp_get_evpn()) {
4288 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4292 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4296 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4297 bgp_evpn_advertise_pip_ip_mac_cmd
,
4298 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4300 "evpn system primary IP\n"
4303 MAC_STR MAC_STR MAC_STR
)
4305 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4306 struct bgp
*bgp_evpn
= NULL
;
4308 if (EVPN_ENABLED(bgp_vrf
)) {
4310 "This command is supported under L3VNI BGP EVPN VRF\n");
4311 return CMD_WARNING_CONFIG_FAILED
;
4313 bgp_evpn
= bgp_get_evpn();
4316 /* pip is already enabled */
4317 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4320 bgp_vrf
->evpn_info
->advertise_pip
= true;
4321 if (ip
.s_addr
!= INADDR_ANY
) {
4322 /* Already configured with same IP */
4323 if (IPV4_ADDR_SAME(&ip
,
4324 &bgp_vrf
->evpn_info
->pip_ip_static
))
4327 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4328 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4330 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4332 /* default instance router-id assignemt */
4334 bgp_vrf
->evpn_info
->pip_ip
=
4335 bgp_evpn
->router_id
;
4338 if (!is_zero_mac(&mac
->eth_addr
)) {
4339 /* Already configured with same MAC */
4340 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4341 &mac
->eth_addr
, ETH_ALEN
) == 0)
4344 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4345 &mac
->eth_addr
, ETH_ALEN
);
4346 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4347 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4350 /* Copy zebra sys mac */
4351 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4352 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4353 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4358 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4360 /* Disable PIP feature */
4361 bgp_vrf
->evpn_info
->advertise_pip
= false;
4362 /* copy anycast mac */
4363 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4364 &bgp_vrf
->rmac
, ETH_ALEN
);
4366 /* remove MAC-IP option retain PIP knob. */
4367 if ((ip
.s_addr
!= INADDR_ANY
) &&
4368 !IPV4_ADDR_SAME(&ip
,
4369 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4371 "%% BGP EVPN PIP IP does not match\n");
4372 return CMD_WARNING_CONFIG_FAILED
;
4375 if (!is_zero_mac(&mac
->eth_addr
) &&
4376 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4377 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4379 "%% BGP EVPN PIP MAC does not match\n");
4380 return CMD_WARNING_CONFIG_FAILED
;
4382 /* pip_rmac can carry vrr_rmac reset only if it matches
4383 * with static value.
4385 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4386 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4388 /* Copy zebra sys mac */
4390 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4391 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4392 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4395 /* copy anycast mac */
4396 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4397 &bgp_vrf
->rmac
, ETH_ALEN
);
4401 /* reset user configured sys MAC */
4402 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4403 /* reset user configured sys IP */
4404 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4405 /* Assign default PIP IP (bgp instance router-id) */
4407 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4409 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4412 if (is_evpn_enabled()) {
4413 struct listnode
*node
= NULL
;
4414 struct bgpevpn
*vpn
= NULL
;
4417 * At this point if bgp_evpn is NULL and evpn is enabled
4418 * something stupid has gone wrong
4422 update_advertise_vrf_routes(bgp_vrf
);
4424 /* Update (svi) type-2 routes */
4425 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4426 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4428 update_routes_for_vni(bgp_evpn
, vpn
);
4436 * Display VNI information - for all or a specific VNI
4438 DEFUN(show_bgp_l2vpn_evpn_vni
,
4439 show_bgp_l2vpn_evpn_vni_cmd
,
4440 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4449 struct bgp
*bgp_evpn
;
4453 json_object
*json
= NULL
;
4454 uint32_t num_l2vnis
= 0;
4455 uint32_t num_l3vnis
= 0;
4456 uint32_t num_vnis
= 0;
4457 struct listnode
*node
= NULL
;
4458 struct bgp
*bgp_temp
= NULL
;
4460 uj
= use_json(argc
, argv
);
4462 bgp_evpn
= bgp_get_evpn();
4466 if (!argv_find(argv
, argc
, "evpn", &idx
))
4470 json
= json_object_new_object();
4472 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4474 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4476 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4477 if (bgp_temp
->l3vni
)
4480 num_vnis
= num_l2vnis
+ num_l3vnis
;
4482 json_object_string_add(json
, "advertiseGatewayMacip",
4483 bgp_evpn
->advertise_gw_macip
4486 json_object_string_add(json
, "advertiseSviMacIp",
4487 bgp_evpn
->evpn_info
->advertise_svi_macip
4488 ? "Enabled" : "Disabled");
4489 json_object_string_add(json
, "advertiseAllVnis",
4490 is_evpn_enabled() ? "Enabled"
4492 json_object_string_add(
4494 bgp_evpn
->vxlan_flood_ctrl
==
4495 VXLAN_FLOOD_HEAD_END_REPL
4496 ? "Head-end replication"
4498 json_object_string_add(
4499 json
, "vxlanFlooding",
4500 bgp_evpn
->vxlan_flood_ctrl
==
4501 VXLAN_FLOOD_HEAD_END_REPL
4504 json_object_int_add(json
, "numVnis", num_vnis
);
4505 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4506 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4508 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4509 bgp_evpn
->advertise_gw_macip
? "Enabled"
4511 vty_out(vty
, "Advertise SVI Macip: %s\n",
4512 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4514 vty_out(vty
, "Advertise All VNI flag: %s\n",
4515 is_evpn_enabled() ? "Enabled" : "Disabled");
4516 vty_out(vty
, "BUM flooding: %s\n",
4517 bgp_evpn
->vxlan_flood_ctrl
==
4518 VXLAN_FLOOD_HEAD_END_REPL
4519 ? "Head-end replication"
4521 vty_out(vty
, "VXLAN flooding: %s\n",
4522 bgp_evpn
->vxlan_flood_ctrl
==
4523 VXLAN_FLOOD_HEAD_END_REPL
4526 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4527 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4529 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4533 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4536 /* Display specific VNI */
4537 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4538 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4542 vty_json(vty
, json
);
4547 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4548 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4549 "show bgp l2vpn evpn vni remote-ip-hash",
4557 struct bgp
*bgp_evpn
;
4560 bgp_evpn
= bgp_get_evpn();
4564 if (!argv_find(argv
, argc
, "evpn", &idx
))
4567 hash_iterate(bgp_evpn
->vnihash
,
4568 (void (*)(struct hash_bucket
*,
4569 void *))bgp_evpn_show_remote_ip_hash
,
4575 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4576 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4577 "show bgp l2vpn evpn vni-svi-hash",
4582 "Show vni-svi-hash\n")
4584 struct bgp
*bgp_evpn
;
4587 bgp_evpn
= bgp_get_evpn();
4591 if (!argv_find(argv
, argc
, "evpn", &idx
))
4594 hash_iterate(bgp_evpn
->vni_svi_hash
,
4595 (void (*)(struct hash_bucket
*,
4596 void *))bgp_evpn_show_vni_svi_hash
,
4602 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4603 show_bgp_l2vpn_evpn_es_evi_cmd
,
4604 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4610 "VxLAN Network Identifier\n"
4613 "Detailed information\n")
4616 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4618 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4623 DEFPY(show_bgp_l2vpn_evpn_es
,
4624 show_bgp_l2vpn_evpn_es_cmd
,
4625 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4630 "Ethernet Segment\n"
4632 "Detailed information\n"
4638 if (!str_to_esi(esi_str
, &esi
)) {
4639 vty_out(vty
, "%% Malformed ESI\n");
4642 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4645 bgp_evpn_es_show(vty
, uj
, !!detail
);
4651 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4652 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4653 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4654 "Ethernet Segment\n"
4660 if (!str_to_esi(esi_str
, &esi
)) {
4661 vty_out(vty
, "%% Malformed ESI\n");
4664 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4667 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4673 DEFPY(show_bgp_l2vpn_evpn_nh
,
4674 show_bgp_l2vpn_evpn_nh_cmd
,
4675 "show bgp l2vpn evpn next-hops [json$uj]",
4683 bgp_evpn_nh_show(vty
, uj
);
4689 * Display EVPN neighbor summary.
4691 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4692 "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]",
4695 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4696 "Summary of BGP neighbor status\n"
4697 "Show only sessions in Established state\n"
4698 "Show only sessions not in Established state\n"
4699 "Show only the specified neighbor session\n"
4700 "Neighbor to display information about\n"
4701 "Neighbor to display information about\n"
4702 "Neighbor on BGP configured interface\n"
4703 "Show only the specified remote AS sessions\n"
4705 "Internal (iBGP) AS sessions\n"
4706 "External (eBGP) AS sessions\n"
4707 "Shorten the information on BGP instances\n"
4708 "Increase table width for longer output\n" JSON_STR
)
4713 char *neighbor
= NULL
;
4714 as_t as
= 0; /* 0 means AS filter not set */
4715 int as_type
= AS_UNSPECIFIED
;
4716 uint16_t show_flags
= 0;
4718 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4719 vrf
= argv
[++idx_vrf
]->arg
;
4721 if (argv_find(argv
, argc
, "failed", &idx
))
4722 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4724 if (argv_find(argv
, argc
, "established", &idx
))
4725 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4728 if (argv_find(argv
, argc
, "neighbor", &idx
))
4729 neighbor
= argv
[idx
+ 1]->arg
;
4731 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4732 if (argv
[idx
+ 1]->arg
[0] == 'i')
4733 as_type
= AS_INTERNAL
;
4734 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4735 as_type
= AS_EXTERNAL
;
4737 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4740 if (argv_find(argv
, argc
, "terse", &idx
))
4741 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4743 if (argv_find(argv
, argc
, "wide", &idx
))
4744 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4746 if (use_json(argc
, argv
))
4747 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4749 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4750 as_type
, as
, show_flags
);
4753 static int bgp_evpn_cli_parse_type_cmp(int *type
, const char *type_str
)
4755 if ((strncmp(type_str
, "ma", 2) == 0) || (strmatch(type_str
, "2")))
4756 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4757 else if ((strncmp(type_str
, "mu", 2) == 0) || (strmatch(type_str
, "3")))
4758 *type
= BGP_EVPN_IMET_ROUTE
;
4759 else if ((strncmp(type_str
, "es", 2) == 0) || (strmatch(type_str
, "4")))
4760 *type
= BGP_EVPN_ES_ROUTE
;
4761 else if ((strncmp(type_str
, "ea", 2) == 0) || (strmatch(type_str
, "1")))
4762 *type
= BGP_EVPN_AD_ROUTE
;
4763 else if ((strncmp(type_str
, "p", 1) == 0) || (strmatch(type_str
, "5")))
4764 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4771 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4775 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4776 /* Specific type is requested */
4777 if (bgp_evpn_cli_parse_type_cmp(type
,
4778 argv
[type_idx
+ 1]->arg
) != 0)
4786 * Display global EVPN routing table.
4788 DEFUN(show_bgp_l2vpn_evpn_route
,
4789 show_bgp_l2vpn_evpn_route_cmd
,
4790 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] ["BGP_SELF_ORIG_CMD_STR
"] [json]",
4796 "Display Detailed Information\n"
4798 EVPN_TYPE_ALL_LIST_HELP_STR
4799 BGP_SELF_ORIG_HELP_STR
4807 bool self_orig
= false;
4808 json_object
*json
= NULL
;
4810 uj
= use_json(argc
, argv
);
4812 bgp
= bgp_get_evpn();
4817 json
= json_object_new_object();
4819 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4822 if (argv_find(argv
, argc
, "detail", &detail
))
4825 if (argv_find(argv
, argc
, BGP_SELF_ORIG_CMD_STR
, &arg_idx
))
4828 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
, self_orig
);
4831 * This is an extremely expensive operation at scale
4832 * and as such we need to save as much time as is
4836 vty_json_no_pretty(vty
, json
);
4842 * Display global EVPN routing table for specific RD.
4844 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4845 show_bgp_l2vpn_evpn_route_rd_cmd
,
4846 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4852 EVPN_RT_DIST_HELP_STR
4853 EVPN_ASN_IP_HELP_STR
4854 "All VPN Route Distinguishers\n"
4856 EVPN_TYPE_ALL_LIST_HELP_STR
4861 struct prefix_rd prd
;
4864 json_object
*json
= NULL
;
4865 int idx_ext_community
= 0;
4868 bgp
= bgp_get_evpn();
4872 /* check if we need json output */
4873 uj
= use_json(argc
, argv
);
4875 json
= json_object_new_object();
4877 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4879 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4880 &idx_ext_community
)) {
4881 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4884 "%% Malformed Route Distinguisher\n");
4890 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4894 evpn_show_all_routes(vty
, bgp
, type
, json
, 1, false);
4896 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4899 vty_json(vty
, json
);
4905 * Display global EVPN routing table for specific RD and MACIP.
4907 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4908 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4909 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4915 EVPN_RT_DIST_HELP_STR
4916 EVPN_ASN_IP_HELP_STR
4917 "All VPN Route Distinguishers\n"
4919 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4921 "IP address (IPv4 or IPv6)\n"
4926 struct prefix_rd prd
;
4929 int idx_ext_community
= 0;
4933 json_object
*json
= NULL
;
4936 memset(&mac
, 0, sizeof(struct ethaddr
));
4937 memset(&ip
, 0, sizeof(struct ipaddr
));
4939 bgp
= bgp_get_evpn();
4943 /* check if we need json output */
4944 uj
= use_json(argc
, argv
);
4946 json
= json_object_new_object();
4949 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4950 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4951 &idx_ext_community
)) {
4952 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4955 "%% Malformed Route Distinguisher\n");
4962 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4963 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4964 vty_out(vty
, "%% Malformed MAC address\n");
4969 /* get the ip if specified */
4970 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4971 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4972 vty_out(vty
, "%% Malformed IP address\n");
4978 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4980 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4983 vty_json(vty
, json
);
4988 /* Display per ESI routing table */
4989 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4990 show_bgp_l2vpn_evpn_route_esi_cmd
,
4991 "show bgp l2vpn evpn route esi ESI [json]",
4997 "Ethernet Segment Identifier\n"
5003 struct bgp
*bgp
= NULL
;
5004 json_object
*json
= NULL
;
5006 memset(&esi
, 0, sizeof(esi
));
5007 bgp
= bgp_get_evpn();
5011 uj
= use_json(argc
, argv
);
5013 json
= json_object_new_object();
5015 /* get the ESI - ESI-ID is at argv[6] */
5016 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
5017 vty_out(vty
, "%% Malformed ESI\n");
5021 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
5024 vty_json(vty
, json
);
5031 * Display per-VNI EVPN routing table.
5033 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
5034 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5040 "VXLAN Network Identifier\n"
5043 EVPN_TYPE_1_HELP_STR
5044 EVPN_TYPE_1_HELP_STR
5045 EVPN_TYPE_2_HELP_STR
5046 EVPN_TYPE_2_HELP_STR
5047 EVPN_TYPE_3_HELP_STR
5048 EVPN_TYPE_3_HELP_STR
5050 "Remote VTEP IP address\n"
5055 struct in_addr vtep_ip
;
5060 json_object
*json
= NULL
;
5062 bgp
= bgp_get_evpn();
5066 /* check if we need json output */
5067 uj
= use_json(argc
, argv
);
5069 json
= json_object_new_object();
5071 if (!argv_find(argv
, argc
, "evpn", &idx
))
5076 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5078 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
5081 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
5082 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
5083 vty_out(vty
, "%% Malformed VTEP IP address\n");
5088 evpn_show_routes_vni(vty
, bgp
, vni
, type
, false, vtep_ip
, json
);
5091 vty_json(vty
, json
);
5097 * Display per-VNI EVPN routing table for specific MACIP.
5099 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
5100 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
5101 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
5107 "VXLAN Network Identifier\n"
5110 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5112 "IP address (IPv4 or IPv6)\n"
5121 json_object
*json
= NULL
;
5123 bgp
= bgp_get_evpn();
5127 /* check if we need json output */
5128 uj
= use_json(argc
, argv
);
5130 json
= json_object_new_object();
5132 if (!argv_find(argv
, argc
, "evpn", &idx
))
5136 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5139 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5140 vty_out(vty
, "%% Malformed MAC address\n");
5145 memset(&ip
, 0, sizeof(ip
));
5146 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5148 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5149 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5150 vty_out(vty
, "%% Malformed IP address\n");
5155 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5158 vty_json(vty
, json
);
5164 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5166 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5167 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5168 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5174 "VXLAN Network Identifier\n"
5176 EVPN_TYPE_3_HELP_STR
5177 "Originating Router IP address\n"
5183 struct in_addr orig_ip
;
5186 json_object
*json
= NULL
;
5188 bgp
= bgp_get_evpn();
5192 /* check if we need json output */
5193 uj
= use_json(argc
, argv
);
5195 json
= json_object_new_object();
5197 if (!argv_find(argv
, argc
, "evpn", &idx
))
5201 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5204 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5206 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5210 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5213 vty_json(vty
, json
);
5219 * Display per-VNI EVPN routing table - for all VNIs.
5221 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5222 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5223 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5229 "VXLAN Network Identifier\n"
5231 "Print Detailed Output\n"
5233 "Remote VTEP IP address\n"
5237 struct in_addr vtep_ip
;
5240 json_object
*json
= NULL
;
5241 /* Detail Adjust. Adjust indexes according to detail option */
5244 bgp
= bgp_get_evpn();
5248 /* check if we need json output */
5249 uj
= use_json(argc
, argv
);
5251 json
= json_object_new_object();
5253 if (!argv_find(argv
, argc
, "evpn", &idx
))
5256 if (argv_find(argv
, argc
, "detail", &da
))
5259 /* vtep-ip position depends on detail option */
5261 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5263 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5264 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5265 vty_out(vty
, "%% Malformed VTEP IP address\n");
5270 evpn_show_routes_vni_all(vty
, bgp
, 0, false, vtep_ip
, json
, da
);
5273 vty_json(vty
, json
);
5274 json_object_free(json
);
5281 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5283 DEFPY(show_bgp_vni_all
,
5284 show_bgp_vni_all_cmd
,
5285 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5296 json_object
*json
= NULL
;
5298 bgp
= bgp_get_evpn();
5302 /* check if we need json output */
5304 json
= json_object_new_object();
5306 evpn_show_routes_vni_all_type_all(vty
, bgp
, addr
, json
, !!detail
);
5309 vty_json(vty
, json
);
5315 * Display per-VNI EVPN EAD routing table - for all VNIs.
5317 DEFPY(show_bgp_vni_all_ead
,
5318 show_bgp_vni_all_ead_cmd
,
5319 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5325 EVPN_TYPE_1_HELP_STR
5326 EVPN_TYPE_1_HELP_STR
5333 json_object
*json
= NULL
;
5335 bgp
= bgp_get_evpn();
5339 /* check if we need json output */
5341 json
= json_object_new_object();
5343 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_AD_ROUTE
, false, addr
, json
,
5347 vty_json(vty
, json
);
5353 * Display per-VNI EVPN MAC routing table - for all VNIs.
5355 DEFPY(show_bgp_vni_all_macip_mac
,
5356 show_bgp_vni_all_macip_mac_cmd
,
5357 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5363 EVPN_TYPE_2_HELP_STR
5364 EVPN_TYPE_2_HELP_STR
5372 json_object
*json
= NULL
;
5374 bgp
= bgp_get_evpn();
5378 /* check if we need json output */
5380 json
= json_object_new_object();
5382 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5386 vty_json(vty
, json
);
5392 * Display per-VNI EVPN IP routing table - for all VNIs.
5394 DEFPY(show_bgp_vni_all_macip_ip
,
5395 show_bgp_vni_all_macip_ip_cmd
,
5396 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5402 EVPN_TYPE_2_HELP_STR
5403 EVPN_TYPE_2_HELP_STR
5411 json_object
*json
= NULL
;
5413 bgp
= bgp_get_evpn();
5417 /* check if we need json output */
5419 json
= json_object_new_object();
5421 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5425 vty_json(vty
, json
);
5431 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5433 DEFPY(show_bgp_vni_all_imet
,
5434 show_bgp_vni_all_imet_cmd
,
5435 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5441 EVPN_TYPE_3_HELP_STR
5442 EVPN_TYPE_3_HELP_STR
5449 json_object
*json
= NULL
;
5451 bgp
= bgp_get_evpn();
5455 /* check if we need json output */
5457 json
= json_object_new_object();
5459 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5463 vty_json(vty
, json
);
5469 * Display per-VNI EVPN ALL routing tables - for select VNI
5473 "show bgp vni "CMD_VNI_RANGE
"$vni [vtep A.B.C.D$addr] [json$uj]",
5483 json_object
*json
= NULL
;
5484 json_object
*json_mac
= NULL
;
5486 bgp
= bgp_get_evpn();
5490 /* check if we need json output */
5492 json
= json_object_new_object();
5493 json_mac
= json_object_new_object();
5496 evpn_show_routes_vni(vty
, bgp
, vni
, 0, false, addr
, json
);
5499 vty_out(vty
, "\n\nMAC Table:\n\n");
5501 evpn_show_routes_vni(vty
, bgp
, vni
, 0, true, addr
, json_mac
);
5504 json_object_object_add(json
, "macTable", json_mac
);
5505 vty_json(vty
, json
);
5512 * Display per-VNI EVPN EAD routing table - for select VNI
5514 DEFPY(show_bgp_vni_ead
,
5515 show_bgp_vni_ead_cmd
,
5516 "show bgp vni "CMD_VNI_RANGE
"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5522 EVPN_TYPE_1_HELP_STR
5523 EVPN_TYPE_1_HELP_STR
5529 json_object
*json
= NULL
;
5531 bgp
= bgp_get_evpn();
5535 /* check if we need json output */
5537 json
= json_object_new_object();
5539 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_AD_ROUTE
, false, addr
,
5543 vty_json(vty
, json
);
5549 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5551 DEFPY(show_bgp_vni_macip_mac
,
5552 show_bgp_vni_macip_mac_cmd
,
5553 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5559 EVPN_TYPE_2_HELP_STR
5560 EVPN_TYPE_2_HELP_STR
5567 json_object
*json
= NULL
;
5569 bgp
= bgp_get_evpn();
5573 /* check if we need json output */
5575 json
= json_object_new_object();
5577 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5581 vty_json(vty
, json
);
5587 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5589 DEFPY(show_bgp_vni_macip_ip
,
5590 show_bgp_vni_macip_ip_cmd
,
5591 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5597 EVPN_TYPE_2_HELP_STR
5598 EVPN_TYPE_2_HELP_STR
5605 json_object
*json
= NULL
;
5607 bgp
= bgp_get_evpn();
5611 /* check if we need json output */
5613 json
= json_object_new_object();
5615 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5619 vty_json(vty
, json
);
5625 * Display per-VNI EVPN Multicast routing table - for select VNI
5627 DEFPY(show_bgp_vni_imet
,
5628 show_bgp_vni_imet_cmd
,
5629 "show bgp vni "CMD_VNI_RANGE
"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5635 EVPN_TYPE_3_HELP_STR
5636 EVPN_TYPE_3_HELP_STR
5642 json_object
*json
= NULL
;
5644 bgp
= bgp_get_evpn();
5648 /* check if we need json output */
5650 json
= json_object_new_object();
5652 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5656 vty_json(vty
, json
);
5662 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5664 DEFPY(show_bgp_vni_macip_mac_addr
,
5665 show_bgp_vni_macip_mac_addr_cmd
,
5666 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5672 EVPN_TYPE_2_HELP_STR
5673 EVPN_TYPE_2_HELP_STR
5679 json_object
*json
= NULL
;
5681 bgp
= bgp_get_evpn();
5685 /* check if we need json output */
5687 json
= json_object_new_object();
5689 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
->eth_addr
, NULL
, json
);
5692 vty_json(vty
, json
);
5698 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5700 DEFPY(show_bgp_vni_macip_ip_addr
, show_bgp_vni_macip_ip_addr_cmd
,
5701 "show bgp vni " CMD_VNI_RANGE
5702 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5703 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5704 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5705 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR
)
5708 json_object
*json
= NULL
;
5709 struct ipaddr ip_addr
= {.ipa_type
= IPADDR_NONE
};
5711 bgp
= bgp_get_evpn();
5715 /* check if we need json output */
5717 json
= json_object_new_object();
5719 if (sockunion_family(ip
) == AF_INET
) {
5720 ip_addr
.ipa_type
= IPADDR_V4
;
5721 ip_addr
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
5723 ip_addr
.ipa_type
= IPADDR_V6
;
5724 memcpy(&ip_addr
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
5725 sizeof(struct in6_addr
));
5727 evpn_show_route_vni_macip(vty
, bgp
, vni
, NULL
, &ip_addr
, json
);
5730 vty_json(vty
, json
);
5736 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5737 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5738 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5739 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5740 "EVPN route information\n"
5741 "MAC IP routes in the EVI tables linked to the ES\n"
5743 "Detailed information\n" JSON_STR
)
5747 json_object
*json
= NULL
;
5750 if (!str_to_esi(esi_str
, &esi
)) {
5751 vty_out(vty
, "%% Malformed ESI\n");
5760 json
= json_object_new_object();
5761 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5763 vty_json(vty
, json
);
5769 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5770 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5771 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5772 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5773 "EVPN route information\n"
5774 "MAC IP routes in the global table linked to the ES\n"
5776 "Detailed information\n" JSON_STR
)
5780 json_object
*json
= NULL
;
5783 if (!str_to_esi(esi_str
, &esi
)) {
5784 vty_out(vty
, "%% Malformed ESI\n");
5793 json
= json_object_new_object();
5794 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5796 vty_json(vty
, json
);
5802 * Display EVPN import route-target hash table
5804 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5805 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5806 "show bgp l2vpn evpn vrf-import-rt [json]",
5811 "Show vrf import route target\n"
5815 struct bgp
*bgp_evpn
= NULL
;
5816 json_object
*json
= NULL
;
5818 bgp_evpn
= bgp_get_evpn();
5822 uj
= use_json(argc
, argv
);
5824 json
= json_object_new_object();
5826 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5829 vty_json(vty
, json
);
5835 * Display EVPN import route-target hash table
5837 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5838 show_bgp_l2vpn_evpn_import_rt_cmd
,
5839 "show bgp l2vpn evpn import-rt [json]",
5844 "Show import route target\n"
5849 json_object
*json
= NULL
;
5851 bgp
= bgp_get_evpn();
5855 uj
= use_json(argc
, argv
);
5857 json
= json_object_new_object();
5859 evpn_show_import_rts(vty
, bgp
, json
);
5862 vty_json(vty
, json
);
5867 DEFPY_HIDDEN(test_es_add
,
5869 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5872 "Ethernet-segment\n"
5873 "Ethernet-Segment Identifier\n"
5881 struct in_addr vtep_ip
;
5884 bgp
= bgp_get_evpn();
5886 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5890 if (!str_to_esi(esi_str
, &esi
)) {
5891 vty_out(vty
, "%% Malformed ESI\n");
5896 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5898 vty_out(vty
, "%% Failed to delete ES\n");
5902 if (state_str
&& !strcmp(state_str
, "up"))
5906 vtep_ip
= bgp
->router_id
;
5908 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5909 EVPN_MH_DF_PREF_MIN
, false);
5911 vty_out(vty
, "%% Failed to add ES\n");
5918 DEFPY_HIDDEN(test_es_vni_add
,
5919 test_es_vni_add_cmd
,
5920 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5923 "Ethernet-segment\n"
5924 "Ethernet-Segment Identifier\n"
5933 bgp
= bgp_get_evpn();
5935 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5939 if (!str_to_esi(esi_str
, &esi
)) {
5940 vty_out(vty
, "%% Malformed ESI\n");
5945 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5947 vty_out(vty
, "%% Failed to deref ES VNI\n");
5951 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5953 vty_out(vty
, "%% Failed to ref ES VNI\n");
5960 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5961 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5965 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5966 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5967 "Summary of BGP neighbor status\n" JSON_STR
)
5969 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5970 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5971 SHOW_STR BGP_STR EVPN_HELP_STR
5973 "Display Detailed Information\n"
5975 EVPN_TYPE_2_HELP_STR
5976 EVPN_TYPE_2_HELP_STR
5977 EVPN_TYPE_3_HELP_STR
5978 EVPN_TYPE_3_HELP_STR
)
5981 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5982 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5983 SHOW_STR BGP_STR EVPN_HELP_STR
5985 EVPN_RT_DIST_HELP_STR
5986 EVPN_ASN_IP_HELP_STR
5988 EVPN_TYPE_2_HELP_STR
5989 EVPN_TYPE_2_HELP_STR
5990 EVPN_TYPE_3_HELP_STR
5991 EVPN_TYPE_3_HELP_STR
)
5994 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5995 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5996 SHOW_STR BGP_STR EVPN_HELP_STR
5998 EVPN_RT_DIST_HELP_STR
5999 EVPN_ASN_IP_HELP_STR
6001 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6003 "IP address (IPv4 or IPv6)\n")
6006 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
6007 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
6008 SHOW_STR BGP_STR EVPN_HELP_STR
6010 "VXLAN Network Identifier\n"
6013 EVPN_TYPE_2_HELP_STR
6014 EVPN_TYPE_2_HELP_STR
6015 EVPN_TYPE_3_HELP_STR
6016 EVPN_TYPE_3_HELP_STR
6018 "Remote VTEP IP address\n")
6020 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
6021 show_bgp_evpn_route_vni_macip_cmd
,
6022 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
6023 SHOW_STR BGP_STR EVPN_HELP_STR
6025 "VXLAN Network Identifier\n"
6028 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
6030 "IP address (IPv4 or IPv6)\n")
6032 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
6033 show_bgp_evpn_route_vni_multicast_cmd
,
6034 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
6035 SHOW_STR BGP_STR EVPN_HELP_STR
6037 "VXLAN Network Identifier\n"
6039 EVPN_TYPE_3_HELP_STR
6040 "Originating Router IP address\n")
6042 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
6043 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6044 SHOW_STR BGP_STR EVPN_HELP_STR
6046 "VXLAN Network Identifier\n"
6048 "Print Detailed Output\n"
6050 "Remote VTEP IP address\n")
6052 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
6053 "show bgp evpn import-rt",
6054 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
6056 DEFUN_NOSH (bgp_evpn_vni
,
6058 "vni " CMD_VNI_RANGE
,
6059 "VXLAN Network Identifier\n"
6063 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6064 struct bgpevpn
*vpn
;
6069 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
6071 /* Create VNI, or mark as configured. */
6072 vpn
= evpn_create_update_vni(bgp
, vni
);
6074 vty_out(vty
, "%% Failed to create VNI \n");
6078 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
6082 DEFUN (no_bgp_evpn_vni
,
6083 no_bgp_evpn_vni_cmd
,
6084 "no vni " CMD_VNI_RANGE
,
6086 "VXLAN Network Identifier\n"
6090 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6091 struct bgpevpn
*vpn
;
6096 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
6098 /* Check if we should disallow. */
6099 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
6101 vty_out(vty
, "%% Specified VNI does not exist\n");
6104 if (!is_vni_configured(vpn
)) {
6105 vty_out(vty
, "%% Specified VNI is not configured\n");
6109 evpn_delete_vni(bgp
, vpn
);
6113 DEFUN_NOSH (exit_vni
,
6116 "Exit from VNI mode\n")
6118 if (vty
->node
== BGP_EVPN_VNI_NODE
)
6119 vty
->node
= BGP_EVPN_NODE
;
6123 DEFUN (bgp_evpn_vrf_rd
,
6124 bgp_evpn_vrf_rd_cmd
,
6125 "rd ASN:NN_OR_IP-ADDRESS:NN",
6126 EVPN_RT_DIST_HELP_STR
6127 EVPN_ASN_IP_HELP_STR
)
6130 struct prefix_rd prd
;
6131 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6136 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6138 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6142 /* If same as existing value, there is nothing more to do. */
6143 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
6146 /* Configure or update the RD. */
6147 evpn_configure_vrf_rd(bgp_vrf
, &prd
, argv
[1]->arg
);
6151 DEFUN (no_bgp_evpn_vrf_rd
,
6152 no_bgp_evpn_vrf_rd_cmd
,
6153 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6155 EVPN_RT_DIST_HELP_STR
6156 EVPN_ASN_IP_HELP_STR
)
6159 struct prefix_rd prd
;
6160 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6165 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6167 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6171 /* Check if we should disallow. */
6172 if (!is_vrf_rd_configured(bgp_vrf
)) {
6173 vty_out(vty
, "%% RD is not configured for this VRF\n");
6177 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
6179 "%% RD specified does not match configuration for this VRF\n");
6183 evpn_unconfigure_vrf_rd(bgp_vrf
);
6187 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
6188 no_bgp_evpn_vrf_rd_without_val_cmd
,
6191 EVPN_RT_DIST_HELP_STR
)
6193 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6198 /* Check if we should disallow. */
6199 if (!is_vrf_rd_configured(bgp_vrf
)) {
6200 vty_out(vty
, "%% RD is not configured for this VRF\n");
6204 evpn_unconfigure_vrf_rd(bgp_vrf
);
6208 DEFUN (bgp_evpn_vni_rd
,
6209 bgp_evpn_vni_rd_cmd
,
6210 "rd ASN:NN_OR_IP-ADDRESS:NN",
6211 EVPN_RT_DIST_HELP_STR
6212 EVPN_ASN_IP_HELP_STR
)
6214 struct prefix_rd prd
;
6215 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6216 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6222 if (!EVPN_ENABLED(bgp
)) {
6224 "This command is only supported under EVPN VRF\n");
6228 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6230 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6234 /* If same as existing value, there is nothing more to do. */
6235 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
6238 /* Configure or update the RD. */
6239 evpn_configure_rd(bgp
, vpn
, &prd
, argv
[1]->arg
);
6243 DEFUN (no_bgp_evpn_vni_rd
,
6244 no_bgp_evpn_vni_rd_cmd
,
6245 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6247 EVPN_RT_DIST_HELP_STR
6248 EVPN_ASN_IP_HELP_STR
)
6250 struct prefix_rd prd
;
6251 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6252 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6258 if (!EVPN_ENABLED(bgp
)) {
6260 "This command is only supported under EVPN VRF\n");
6264 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6266 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6270 /* Check if we should disallow. */
6271 if (!is_rd_configured(vpn
)) {
6272 vty_out(vty
, "%% RD is not configured for this VNI\n");
6276 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
6278 "%% RD specified does not match configuration for this VNI\n");
6282 evpn_unconfigure_rd(bgp
, vpn
);
6286 DEFUN (no_bgp_evpn_vni_rd_without_val
,
6287 no_bgp_evpn_vni_rd_without_val_cmd
,
6290 EVPN_RT_DIST_HELP_STR
)
6292 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6293 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6298 if (!EVPN_ENABLED(bgp
)) {
6300 "This command is only supported under EVPN VRF\n");
6304 /* Check if we should disallow. */
6305 if (!is_rd_configured(vpn
)) {
6306 vty_out(vty
, "%% RD is not configured for this VNI\n");
6310 evpn_unconfigure_rd(bgp
, vpn
);
6315 * Loop over all extended-communities in the route-target list rtl and
6316 * return 1 if we find ecomtarget
6318 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
6319 struct ecommunity
*ecomtarget
)
6321 struct listnode
*node
;
6322 struct ecommunity
*ecom
;
6324 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
6325 if (ecommunity_match(ecom
, ecomtarget
))
6333 * L3 RT version of above.
6335 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
6336 struct ecommunity
*ecomtarget
)
6338 struct listnode
*node
;
6339 struct vrf_route_target
*l3rt
;
6341 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
6342 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
6349 /* display L3VNI related info for a VRF instance */
6350 DEFUN (show_bgp_vrf_l3vni_info
,
6351 show_bgp_vrf_l3vni_info_cmd
,
6352 "show bgp vrf VRFNAME vni [json]",
6360 char buf
[ETHER_ADDR_STRLEN
];
6362 const char *name
= NULL
;
6363 struct bgp
*bgp
= NULL
;
6364 struct listnode
*node
= NULL
;
6365 struct bgpevpn
*vpn
= NULL
;
6366 struct vrf_route_target
*l3rt
;
6367 json_object
*json
= NULL
;
6368 json_object
*json_vnis
= NULL
;
6369 json_object
*json_export_rts
= NULL
;
6370 json_object
*json_import_rts
= NULL
;
6371 bool uj
= use_json(argc
, argv
);
6374 json
= json_object_new_object();
6375 json_vnis
= json_object_new_array();
6376 json_export_rts
= json_object_new_array();
6377 json_import_rts
= json_object_new_array();
6380 name
= argv
[idx_vrf
]->arg
;
6381 bgp
= bgp_lookup_by_name(name
);
6382 if (strmatch(name
, VRF_DEFAULT_NAME
))
6383 bgp
= bgp_get_default();
6387 vty_out(vty
, "BGP instance for VRF %s not found\n",
6390 json_object_string_add(json
, "warning",
6391 "BGP instance not found");
6392 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
6393 json_object_free(json
);
6399 vty_out(vty
, "BGP VRF: %s\n", name
);
6400 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
6401 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
6402 vty_out(vty
, " Rmac: %s\n",
6403 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6404 vty_out(vty
, " VNI Filter: %s\n",
6405 CHECK_FLAG(bgp
->vrf_flags
,
6406 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6407 ? "prefix-routes-only"
6409 vty_out(vty
, " L2-VNI List:\n");
6411 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6412 vty_out(vty
, "%u ", vpn
->vni
);
6414 vty_out(vty
, " Export-RTs:\n");
6416 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6417 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6419 vty_out(vty
, " Import-RTs:\n");
6421 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6422 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6424 vty_out(vty
, " RD: ");
6425 vty_out(vty
, BGP_RD_AS_FORMAT(bgp
->asnotation
), &bgp
->vrf_prd
);
6428 json_object_string_add(json
, "vrf", name
);
6429 json_object_string_addf(json
, "local-ip", "%pI4",
6430 &bgp
->originator_ip
);
6431 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
6432 json_object_string_add(
6434 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6435 json_object_string_add(
6437 CHECK_FLAG(bgp
->vrf_flags
,
6438 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6439 ? "prefix-routes-only"
6441 /* list of l2vnis */
6442 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6443 json_object_array_add(json_vnis
,
6444 json_object_new_int(vpn
->vni
));
6445 json_object_object_add(json
, "l2vnis", json_vnis
);
6448 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6449 json_object_array_add(
6451 json_object_new_string(
6452 ecommunity_str(l3rt
->ecom
)));
6453 json_object_object_add(json
, "export-rts", json_export_rts
);
6456 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6457 json_object_array_add(
6459 json_object_new_string(
6460 ecommunity_str(l3rt
->ecom
)));
6461 json_object_object_add(json
, "import-rts", json_import_rts
);
6462 json_object_string_addf(json
, "rd",
6463 BGP_RD_AS_FORMAT(bgp
->asnotation
),
6468 vty_json(vty
, json
);
6472 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
6475 /* Do nothing if we already have this route-target */
6477 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6479 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
6484 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6486 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
6494 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
6496 /* Verify we already have this route-target */
6498 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6502 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
6504 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6508 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
6514 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
6515 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
6518 int ret
= CMD_SUCCESS
;
6519 bool is_wildcard
= false;
6520 struct ecommunity
*ecom
= NULL
;
6522 for (int i
= rt_idx
; i
< argc
; i
++) {
6523 is_wildcard
= false;
6526 * Special handling for wildcard '*' here.
6528 * Let's just convert it to 0 here so we dont have to modify
6529 * the ecommunity parser.
6531 if ((argv
[i
]->arg
)[0] == '*') {
6532 (argv
[i
]->arg
)[0] = '0';
6536 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
6539 /* Put it back as was */
6541 (argv
[i
]->arg
)[0] = '*';
6544 vty_out(vty
, "%% Malformed Route Target list\n");
6549 ecommunity_str(ecom
);
6552 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
6554 "%% RT specified already configured for this VRF: %s\n",
6556 ecommunity_free(&ecom
);
6561 if (del_rt(bgp
, ecom
, is_import
) != 0) {
6563 "%% RT specified does not match configuration for this VRF: %s\n",
6568 ecommunity_free(&ecom
);
6575 /* import/export rt for l3vni-vrf */
6576 DEFUN (bgp_evpn_vrf_rt
,
6577 bgp_evpn_vrf_rt_cmd
,
6578 "route-target <both|import|export> RTLIST...",
6580 "import and export\n"
6583 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6585 int ret
= CMD_SUCCESS
;
6586 int tmp_ret
= CMD_SUCCESS
;
6588 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6591 return CMD_WARNING_CONFIG_FAILED
;
6593 if (!strcmp(argv
[1]->arg
, "import"))
6594 rt_type
= RT_TYPE_IMPORT
;
6595 else if (!strcmp(argv
[1]->arg
, "export"))
6596 rt_type
= RT_TYPE_EXPORT
;
6597 else if (!strcmp(argv
[1]->arg
, "both"))
6598 rt_type
= RT_TYPE_BOTH
;
6600 vty_out(vty
, "%% Invalid Route Target type\n");
6601 return CMD_WARNING_CONFIG_FAILED
;
6604 if (strmatch(argv
[2]->arg
, "auto")) {
6605 vty_out(vty
, "%% `auto` cannot be configured via list\n");
6606 return CMD_WARNING_CONFIG_FAILED
;
6609 if (rt_type
!= RT_TYPE_IMPORT
) {
6610 for (int i
= 2; i
< argc
; i
++) {
6611 if ((argv
[i
]->arg
)[0] == '*') {
6613 "%% Wildcard '*' only applicable for import\n");
6614 return CMD_WARNING_CONFIG_FAILED
;
6619 /* Add/update the import route-target */
6620 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6621 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
6623 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6626 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6627 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
6629 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6635 DEFPY (bgp_evpn_vrf_rt_auto
,
6636 bgp_evpn_vrf_rt_auto_cmd
,
6637 "route-target <both|import|export>$type auto",
6639 "import and export\n"
6642 "Automatically derive route target\n")
6644 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6648 return CMD_WARNING_CONFIG_FAILED
;
6650 if (strmatch(type
, "import"))
6651 rt_type
= RT_TYPE_IMPORT
;
6652 else if (strmatch(type
, "export"))
6653 rt_type
= RT_TYPE_EXPORT
;
6654 else if (strmatch(type
, "both"))
6655 rt_type
= RT_TYPE_BOTH
;
6657 vty_out(vty
, "%% Invalid Route Target type\n");
6658 return CMD_WARNING_CONFIG_FAILED
;
6661 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6662 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6664 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6665 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6670 DEFUN (no_bgp_evpn_vrf_rt
,
6671 no_bgp_evpn_vrf_rt_cmd
,
6672 "no route-target <both|import|export> RTLIST...",
6675 "import and export\n"
6678 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6680 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6681 int ret
= CMD_SUCCESS
;
6682 int tmp_ret
= CMD_SUCCESS
;
6686 return CMD_WARNING_CONFIG_FAILED
;
6688 if (!strcmp(argv
[2]->arg
, "import"))
6689 rt_type
= RT_TYPE_IMPORT
;
6690 else if (!strcmp(argv
[2]->arg
, "export"))
6691 rt_type
= RT_TYPE_EXPORT
;
6692 else if (!strcmp(argv
[2]->arg
, "both"))
6693 rt_type
= RT_TYPE_BOTH
;
6695 vty_out(vty
, "%% Invalid Route Target type\n");
6696 return CMD_WARNING_CONFIG_FAILED
;
6699 if (!strcmp(argv
[3]->arg
, "auto")) {
6700 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6701 return CMD_WARNING_CONFIG_FAILED
;
6704 if (rt_type
== RT_TYPE_IMPORT
) {
6705 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6707 "%% Import RT is not configured for this VRF\n");
6708 return CMD_WARNING_CONFIG_FAILED
;
6710 } else if (rt_type
== RT_TYPE_EXPORT
) {
6711 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6713 "%% Export RT is not configured for this VRF\n");
6714 return CMD_WARNING_CONFIG_FAILED
;
6716 } else if (rt_type
== RT_TYPE_BOTH
) {
6717 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6718 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6720 "%% Import/Export RT is not configured for this VRF\n");
6721 return CMD_WARNING_CONFIG_FAILED
;
6725 if (rt_type
!= RT_TYPE_IMPORT
) {
6726 for (int i
= 3; i
< argc
; i
++) {
6727 if ((argv
[i
]->arg
)[0] == '*') {
6729 "%% Wildcard '*' only applicable for import\n");
6730 return CMD_WARNING_CONFIG_FAILED
;
6735 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6736 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6738 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6741 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6742 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6744 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6750 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6751 no_bgp_evpn_vrf_rt_auto_cmd
,
6752 "no route-target <both|import|export>$type auto",
6755 "import and export\n"
6758 "Automatically derive route target\n")
6760 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6764 return CMD_WARNING_CONFIG_FAILED
;
6766 if (strmatch(type
, "import"))
6767 rt_type
= RT_TYPE_IMPORT
;
6768 else if (strmatch(type
, "export"))
6769 rt_type
= RT_TYPE_EXPORT
;
6770 else if (strmatch(type
, "both"))
6771 rt_type
= RT_TYPE_BOTH
;
6773 vty_out(vty
, "%% Invalid Route Target type\n");
6774 return CMD_WARNING_CONFIG_FAILED
;
6777 if (rt_type
== RT_TYPE_IMPORT
) {
6778 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6780 "%% Import AUTO RT is not configured for this VRF\n");
6781 return CMD_WARNING_CONFIG_FAILED
;
6783 } else if (rt_type
== RT_TYPE_EXPORT
) {
6784 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6786 "%% Export AUTO RT is not configured for this VRF\n");
6787 return CMD_WARNING_CONFIG_FAILED
;
6789 } else if (rt_type
== RT_TYPE_BOTH
) {
6790 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6791 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6793 "%% Import/Export AUTO RT is not configured for this VRF\n");
6794 return CMD_WARNING_CONFIG_FAILED
;
6798 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6799 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6801 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6802 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6807 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6808 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6810 "EAD ES fragment config\n"
6811 "EVIs per-fragment\n"
6814 bgp_mh_info
->evi_per_es_frag
=
6815 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6820 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6821 "ead-es-route-target export RT",
6822 "EAD ES Route Target\n"
6824 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6826 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6827 struct ecommunity
*ecomadd
= NULL
;
6832 if (!EVPN_ENABLED(bgp
)) {
6833 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6837 /* Add/update the export route-target */
6838 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6840 vty_out(vty
, "%% Malformed Route Target list\n");
6843 ecommunity_str(ecomadd
);
6845 /* Do nothing if we already have this export route-target */
6846 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6848 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6853 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6854 "no ead-es-route-target export RT",
6856 "EAD ES Route Target\n"
6857 "export\n" EVPN_ASN_IP_HELP_STR
)
6859 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6860 struct ecommunity
*ecomdel
= NULL
;
6865 if (!EVPN_ENABLED(bgp
)) {
6866 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6870 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6872 vty_out(vty
, "%% Malformed Route Target list\n");
6875 ecommunity_str(ecomdel
);
6877 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6879 ecommunity_free(&ecomdel
);
6881 "%% RT specified does not match EAD-ES RT configuration\n");
6884 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6889 DEFUN (bgp_evpn_vni_rt
,
6890 bgp_evpn_vni_rt_cmd
,
6891 "route-target <both|import|export> RT",
6893 "import and export\n"
6896 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6898 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6899 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6901 struct ecommunity
*ecomadd
= NULL
;
6906 if (!EVPN_ENABLED(bgp
)) {
6908 "This command is only supported under EVPN VRF\n");
6912 if (!strcmp(argv
[1]->text
, "import"))
6913 rt_type
= RT_TYPE_IMPORT
;
6914 else if (!strcmp(argv
[1]->text
, "export"))
6915 rt_type
= RT_TYPE_EXPORT
;
6916 else if (!strcmp(argv
[1]->text
, "both"))
6917 rt_type
= RT_TYPE_BOTH
;
6919 vty_out(vty
, "%% Invalid Route Target type\n");
6923 /* Add/update the import route-target */
6924 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6925 /* Note that first of the two RTs is created for "both" type */
6926 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6927 ECOMMUNITY_ROUTE_TARGET
, 0);
6929 vty_out(vty
, "%% Malformed Route Target list\n");
6932 ecommunity_str(ecomadd
);
6934 /* Do nothing if we already have this import route-target */
6935 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6936 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6939 /* Add/update the export route-target */
6940 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6941 /* Note that second of the two RTs is created for "both" type */
6942 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6943 ECOMMUNITY_ROUTE_TARGET
, 0);
6945 vty_out(vty
, "%% Malformed Route Target list\n");
6948 ecommunity_str(ecomadd
);
6950 /* Do nothing if we already have this export route-target */
6951 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6952 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6958 DEFUN (no_bgp_evpn_vni_rt
,
6959 no_bgp_evpn_vni_rt_cmd
,
6960 "no route-target <both|import|export> RT",
6963 "import and export\n"
6966 EVPN_ASN_IP_HELP_STR
)
6968 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6969 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6970 int rt_type
, found_ecomdel
;
6971 struct ecommunity
*ecomdel
= NULL
;
6976 if (!EVPN_ENABLED(bgp
)) {
6978 "This command is only supported under EVPN VRF\n");
6982 if (!strcmp(argv
[2]->text
, "import"))
6983 rt_type
= RT_TYPE_IMPORT
;
6984 else if (!strcmp(argv
[2]->text
, "export"))
6985 rt_type
= RT_TYPE_EXPORT
;
6986 else if (!strcmp(argv
[2]->text
, "both"))
6987 rt_type
= RT_TYPE_BOTH
;
6989 vty_out(vty
, "%% Invalid Route Target type\n");
6993 /* The user did "no route-target import", check to see if there are any
6994 * import route-targets configured. */
6995 if (rt_type
== RT_TYPE_IMPORT
) {
6996 if (!is_import_rt_configured(vpn
)) {
6998 "%% Import RT is not configured for this VNI\n");
7001 } else if (rt_type
== RT_TYPE_EXPORT
) {
7002 if (!is_export_rt_configured(vpn
)) {
7004 "%% Export RT is not configured for this VNI\n");
7007 } else if (rt_type
== RT_TYPE_BOTH
) {
7008 if (!is_import_rt_configured(vpn
)
7009 && !is_export_rt_configured(vpn
)) {
7011 "%% Import/Export RT is not configured for this VNI\n");
7016 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
7018 vty_out(vty
, "%% Malformed Route Target list\n");
7021 ecommunity_str(ecomdel
);
7023 if (rt_type
== RT_TYPE_IMPORT
) {
7024 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7025 ecommunity_free(&ecomdel
);
7027 "%% RT specified does not match configuration for this VNI\n");
7030 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7031 } else if (rt_type
== RT_TYPE_EXPORT
) {
7032 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7033 ecommunity_free(&ecomdel
);
7035 "%% RT specified does not match configuration for this VNI\n");
7038 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7039 } else if (rt_type
== RT_TYPE_BOTH
) {
7042 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7043 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7047 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7048 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7052 if (!found_ecomdel
) {
7053 ecommunity_free(&ecomdel
);
7055 "%% RT specified does not match configuration for this VNI\n");
7063 DEFUN (no_bgp_evpn_vni_rt_without_val
,
7064 no_bgp_evpn_vni_rt_without_val_cmd
,
7065 "no route-target <import|export>",
7071 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
7072 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
7078 if (!EVPN_ENABLED(bgp
)) {
7080 "This command is only supported under EVPN VRF\n");
7084 if (!strcmp(argv
[2]->text
, "import")) {
7085 rt_type
= RT_TYPE_IMPORT
;
7086 } else if (!strcmp(argv
[2]->text
, "export")) {
7087 rt_type
= RT_TYPE_EXPORT
;
7089 vty_out(vty
, "%% Invalid Route Target type\n");
7093 /* Check if we should disallow. */
7094 if (rt_type
== RT_TYPE_IMPORT
) {
7095 if (!is_import_rt_configured(vpn
)) {
7097 "%% Import RT is not configured for this VNI\n");
7101 if (!is_export_rt_configured(vpn
)) {
7103 "%% Export RT is not configured for this VNI\n");
7108 /* Unconfigure the RT. */
7109 if (rt_type
== RT_TYPE_IMPORT
)
7110 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
7112 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
7116 static int vni_cmp(const void **a
, const void **b
)
7118 const struct bgpevpn
*first
= *a
;
7119 const struct bgpevpn
*secnd
= *b
;
7121 return secnd
->vni
- first
->vni
;
7125 * Output EVPN configuration information.
7127 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7130 if (bgp
->advertise_all_vni
)
7131 vty_out(vty
, " advertise-all-vni\n");
7133 if (hashcount(bgp
->vnihash
)) {
7134 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
7135 struct listnode
*ln
;
7136 struct bgpevpn
*data
;
7138 list_sort(vnilist
, vni_cmp
);
7139 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
7140 write_vni_config(vty
, data
);
7142 list_delete(&vnilist
);
7145 if (bgp
->advertise_autort_rfc8365
)
7146 vty_out(vty
, " autort rfc8365-compatible\n");
7148 if (bgp
->advertise_gw_macip
)
7149 vty_out(vty
, " advertise-default-gw\n");
7151 if (bgp
->evpn_info
->advertise_svi_macip
)
7152 vty_out(vty
, " advertise-svi-ip\n");
7154 if (bgp
->resolve_overlay_index
)
7155 vty_out(vty
, " enable-resolve-overlay-index\n");
7157 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
7158 vty_out(vty
, " ead-es-frag evi-limit %u\n",
7159 bgp_mh_info
->evi_per_es_frag
);
7161 if (bgp_mh_info
->host_routes_use_l3nhg
!=
7162 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
7163 if (bgp_mh_info
->host_routes_use_l3nhg
)
7164 vty_out(vty
, " use-es-l3nhg\n");
7166 vty_out(vty
, " no use-es-l3nhg\n");
7169 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
7170 if (bgp_mh_info
->ead_evi_rx
)
7171 vty_out(vty
, " no disable-ead-evi-rx\n");
7173 vty_out(vty
, " disable-ead-evi-rx\n");
7176 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
7177 if (bgp_mh_info
->ead_evi_tx
)
7178 vty_out(vty
, " no disable-ead-evi-tx\n");
7180 vty_out(vty
, " disable-ead-evi-tx\n");
7183 if (!bgp
->evpn_info
->dup_addr_detect
)
7184 vty_out(vty
, " no dup-addr-detection\n");
7186 if (bgp
->evpn_info
->dad_max_moves
!=
7187 EVPN_DAD_DEFAULT_MAX_MOVES
||
7188 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
7189 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
7190 bgp
->evpn_info
->dad_max_moves
,
7191 bgp
->evpn_info
->dad_time
);
7193 if (bgp
->evpn_info
->dad_freeze
) {
7194 if (bgp
->evpn_info
->dad_freeze_time
)
7196 " dup-addr-detection freeze %u\n",
7197 bgp
->evpn_info
->dad_freeze_time
);
7200 " dup-addr-detection freeze permanent\n");
7203 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
7204 vty_out(vty
, " flooding disable\n");
7206 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7207 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
7208 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7209 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
7210 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7213 " advertise ipv4 unicast\n");
7214 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7215 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
7216 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7218 " advertise ipv4 unicast gateway-ip route-map %s\n",
7219 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7221 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
7224 /* EAD ES export route-target */
7225 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
7226 struct ecommunity
*ecom
;
7228 struct listnode
*node
;
7230 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
7233 ecom_str
= ecommunity_ecom2str(
7234 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7235 vty_out(vty
, " ead-es-route-target export %s\n",
7237 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7241 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7242 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
7243 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7245 " advertise ipv6 unicast route-map %s\n",
7246 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7249 " advertise ipv6 unicast\n");
7250 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7251 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
7252 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7254 " advertise ipv6 unicast gateway-ip route-map %s\n",
7255 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7257 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
7260 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7261 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
7262 vty_out(vty
, " default-originate ipv4\n");
7264 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7265 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
7266 vty_out(vty
, " default-originate ipv6\n");
7268 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
7269 if (!bgp
->evpn_info
->advertise_pip
)
7270 vty_out(vty
, " no advertise-pip\n");
7271 if (bgp
->evpn_info
->advertise_pip
) {
7272 if (bgp
->evpn_info
->pip_ip_static
.s_addr
7274 vty_out(vty
, " advertise-pip ip %pI4",
7275 &bgp
->evpn_info
->pip_ip_static
);
7277 bgp
->evpn_info
->pip_rmac_static
))) {
7278 char buf
[ETHER_ADDR_STRLEN
];
7280 vty_out(vty
, " mac %s",
7290 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
7291 vty_out(vty
, " rd %s\n", bgp
->vrf_prd_pretty
);
7293 /* import route-target */
7294 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
7296 struct listnode
*node
, *nnode
;
7297 struct vrf_route_target
*l3rt
;
7299 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
7302 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7305 ecom_str
= ecommunity_ecom2str(
7306 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7308 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
7309 char *vni_str
= NULL
;
7311 vni_str
= strchr(ecom_str
, ':');
7313 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7317 /* Move pointer to vni */
7320 vty_out(vty
, " route-target import *:%s\n",
7324 vty_out(vty
, " route-target import %s\n",
7327 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7331 /* import route-target auto */
7332 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
7333 vty_out(vty
, " route-target import auto\n");
7335 /* export route-target */
7336 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
7338 struct listnode
*node
, *nnode
;
7339 struct vrf_route_target
*l3rt
;
7341 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
7344 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7347 ecom_str
= ecommunity_ecom2str(
7348 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7349 vty_out(vty
, " route-target export %s\n", ecom_str
);
7350 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7354 /* export route-target auto */
7355 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
7356 vty_out(vty
, " route-target export auto\n");
7359 void bgp_ethernetvpn_init(void)
7361 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
7362 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
7363 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
7364 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
7365 install_element(VIEW_NODE
,
7366 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
7367 install_element(VIEW_NODE
,
7368 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
7371 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
7374 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
7375 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
7376 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
7377 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
7378 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
7379 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
7380 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
7381 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
7382 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
7383 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
7384 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
7385 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
7386 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
7387 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
7388 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
7389 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
7390 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
7391 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
7392 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
7393 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
7394 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
7395 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
7396 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
7397 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
7398 install_element(BGP_EVPN_NODE
,
7399 &bgp_evpn_enable_resolve_overlay_index_cmd
);
7402 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
7403 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
7405 /* "show bgp l2vpn evpn" commands. */
7406 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
7407 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
7408 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
7409 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
7410 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
7411 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
7412 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
7413 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
7414 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
7415 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
7416 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
7417 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
7418 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
7419 install_element(VIEW_NODE
,
7420 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
7421 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
7422 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
7423 install_element(VIEW_NODE
,
7424 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
7425 install_element(VIEW_NODE
,
7426 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
7427 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
7428 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
7430 /* "show bgp vni" commands. */
7431 install_element(VIEW_NODE
, &show_bgp_vni_all_cmd
);
7432 install_element(VIEW_NODE
, &show_bgp_vni_all_ead_cmd
);
7433 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_mac_cmd
);
7434 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_ip_cmd
);
7435 install_element(VIEW_NODE
, &show_bgp_vni_all_imet_cmd
);
7436 install_element(VIEW_NODE
, &show_bgp_vni_cmd
);
7437 install_element(VIEW_NODE
, &show_bgp_vni_ead_cmd
);
7438 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_cmd
);
7439 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_cmd
);
7440 install_element(VIEW_NODE
, &show_bgp_vni_imet_cmd
);
7441 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_addr_cmd
);
7442 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_addr_cmd
);
7444 /* "show bgp evpn" commands. */
7445 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
7446 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
7447 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
7448 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
7449 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
7450 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
7451 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
7452 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
7453 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
7454 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
7455 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
7456 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
7458 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
7459 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
7460 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
7461 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
7462 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
7463 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
7464 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
7465 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
7466 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
7467 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
7468 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
7469 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
7470 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
7471 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
7472 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
7473 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
7474 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
7475 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
7476 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
7477 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
7478 install_element(BGP_EVPN_VNI_NODE
,
7479 &bgp_evpn_advertise_default_gw_vni_cmd
);
7480 install_element(BGP_EVPN_VNI_NODE
,
7481 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
7482 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
7483 install_element(BGP_EVPN_VNI_NODE
,
7484 &no_bgp_evpn_advertise_vni_subnet_cmd
);