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", "%pRD", &bgp_vrf
->vrf_prd
);
378 json_object_string_addf(json
, "originatorIp", "%pI4",
379 &bgp_vrf
->originator_ip
);
380 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
381 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
382 json_object_string_add(json
, "advertisePip",
383 bgp_vrf
->evpn_info
->advertise_pip
?
384 "Enabled" : "Disabled");
385 json_object_string_addf(json
, "sysIP", "%pI4",
386 &bgp_vrf
->evpn_info
->pip_ip
);
387 json_object_string_add(json
, "sysMac",
388 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
389 buf2
, sizeof(buf2
)));
390 json_object_string_add(json
, "rmac",
391 prefix_mac2str(&bgp_vrf
->rmac
,
392 buf2
, sizeof(buf2
)));
394 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
395 vty_out(vty
, " (known to the kernel)");
398 vty_out(vty
, " Type: %s\n", "L3");
399 vty_out(vty
, " Tenant VRF: %s\n",
400 vrf_id_to_name(bgp_vrf
->vrf_id
));
401 vty_out(vty
, " RD: %pRD\n", &bgp_vrf
->vrf_prd
);
402 vty_out(vty
, " Originator IP: %pI4\n",
403 &bgp_vrf
->originator_ip
);
404 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
405 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
406 vty_out(vty
, " Advertise-pip: %s\n",
407 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
408 vty_out(vty
, " System-IP: %pI4\n",
409 &bgp_vrf
->evpn_info
->pip_ip
);
410 vty_out(vty
, " System-MAC: %s\n",
411 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
412 buf2
, sizeof(buf2
)));
413 vty_out(vty
, " Router-MAC: %s\n",
414 prefix_mac2str(&bgp_vrf
->rmac
,
415 buf2
, sizeof(buf2
)));
419 vty_out(vty
, " Import Route Target:\n");
421 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
422 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
423 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
426 json_object_array_add(json_import_rtl
,
427 json_object_new_string(ecom_str
));
429 vty_out(vty
, " %s\n", ecom_str
);
431 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
435 json_object_object_add(json
, "importRts", json_import_rtl
);
437 vty_out(vty
, " Export Route Target:\n");
439 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
440 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
441 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
444 json_object_array_add(json_export_rtl
,
445 json_object_new_string(ecom_str
));
447 vty_out(vty
, " %s\n", ecom_str
);
449 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
453 json_object_object_add(json
, "exportRts", json_export_rtl
);
456 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
459 struct listnode
*node
, *nnode
;
460 struct ecommunity
*ecom
;
461 json_object
*json_import_rtl
= NULL
;
462 json_object
*json_export_rtl
= NULL
;
463 struct bgp
*bgp_evpn
;
465 bgp_evpn
= bgp_get_evpn();
468 json_import_rtl
= json_object_new_array();
469 json_export_rtl
= json_object_new_array();
470 json_object_int_add(json
, "vni", vpn
->vni
);
471 json_object_string_add(json
, "type", "L2");
472 json_object_string_add(json
, "inKernel",
473 is_vni_live(vpn
) ? "True" : "False");
474 json_object_string_addf(json
, "rd", "%pRD", &vpn
->prd
);
475 json_object_string_addf(json
, "originatorIp", "%pI4",
476 &vpn
->originator_ip
);
477 json_object_string_addf(json
, "mcastGroup", "%pI4",
479 /* per vni knob is enabled -- Enabled
480 * Global knob is enabled -- Active
481 * default -- Disabled
483 if (!vpn
->advertise_gw_macip
&&
484 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
485 json_object_string_add(json
, "advertiseGatewayMacip",
487 else if (vpn
->advertise_gw_macip
)
488 json_object_string_add(json
, "advertiseGatewayMacip",
491 json_object_string_add(json
, "advertiseGatewayMacip",
493 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
494 bgp_evpn
->evpn_info
->advertise_svi_macip
)
495 json_object_string_add(json
, "advertiseSviMacIp",
497 else if (vpn
->advertise_svi_macip
)
498 json_object_string_add(json
, "advertiseSviMacIp",
501 json_object_string_add(json
, "advertiseSviMacIp",
503 json_object_string_add(
504 json
, "sviInterface",
505 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
507 vty_out(vty
, "VNI: %u", vpn
->vni
);
508 if (is_vni_live(vpn
))
509 vty_out(vty
, " (known to the kernel)");
512 vty_out(vty
, " Type: %s\n", "L2");
513 vty_out(vty
, " Tenant-Vrf: %s\n",
514 vrf_id_to_name(vpn
->tenant_vrf_id
));
515 vty_out(vty
, " RD: %pRD\n", &vpn
->prd
);
516 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
517 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
518 if (!vpn
->advertise_gw_macip
&&
519 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
520 vty_out(vty
, " Advertise-gw-macip : %s\n",
522 else if (vpn
->advertise_gw_macip
)
523 vty_out(vty
, " Advertise-gw-macip : %s\n",
526 vty_out(vty
, " Advertise-gw-macip : %s\n",
528 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
529 bgp_evpn
->evpn_info
->advertise_svi_macip
)
530 vty_out(vty
, " Advertise-svi-macip : %s\n",
532 else if (vpn
->advertise_svi_macip
)
533 vty_out(vty
, " Advertise-svi-macip : %s\n",
536 vty_out(vty
, " Advertise-svi-macip : %s\n",
538 vty_out(vty
, " SVI interface : %s\n",
539 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
543 vty_out(vty
, " Import Route Target:\n");
545 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
546 ecom_str
= ecommunity_ecom2str(ecom
,
547 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
550 json_object_array_add(json_import_rtl
,
551 json_object_new_string(ecom_str
));
553 vty_out(vty
, " %s\n", ecom_str
);
555 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
559 json_object_object_add(json
, "importRts", json_import_rtl
);
561 vty_out(vty
, " Export Route Target:\n");
563 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
564 ecom_str
= ecommunity_ecom2str(ecom
,
565 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
568 json_object_array_add(json_export_rtl
,
569 json_object_new_string(ecom_str
));
571 vty_out(vty
, " %s\n", ecom_str
);
573 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
577 json_object_object_add(json
, "exportRts", json_export_rtl
);
580 static void show_esi_routes(struct bgp
*bgp
,
581 struct bgp_evpn_es
*es
,
586 struct bgp_dest
*dest
;
587 struct bgp_path_info
*pi
;
588 uint32_t prefix_cnt
, path_cnt
;
591 prefix_cnt
= path_cnt
= 0;
593 tbl_ver
= es
->route_table
->version
;
594 for (dest
= bgp_table_top(es
->route_table
); dest
;
595 dest
= bgp_route_next(dest
)) {
596 int add_prefix_to_json
= 0;
597 json_object
*json_paths
= NULL
;
598 json_object
*json_prefix
= NULL
;
599 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
602 json_prefix
= json_object_new_object();
604 pi
= bgp_dest_get_bgp_path_info(dest
);
606 /* Overall header/legend displayed once. */
608 bgp_evpn_show_route_header(vty
, bgp
,
617 json_paths
= json_object_new_array();
619 /* For EVPN, the prefix is displayed for each path (to fit in
620 * with code that already exists).
622 for (; pi
; pi
= pi
->next
) {
623 json_object
*json_path
= NULL
;
626 json_path
= json_object_new_array();
628 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
632 json_object_array_add(json_paths
, json_path
);
635 add_prefix_to_json
= 1;
639 if (add_prefix_to_json
) {
640 json_object_string_addf(json_prefix
, "prefix",
642 json_object_int_add(json_prefix
, "prefixLen",
644 json_object_object_add(json_prefix
, "paths",
646 json_object_object_addf(json
, json_prefix
,
649 json_object_free(json_paths
);
650 json_object_free(json_prefix
);
658 json_object_int_add(json
, "numPrefix", prefix_cnt
);
659 json_object_int_add(json
, "numPaths", path_cnt
);
662 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
664 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
665 prefix_cnt
, path_cnt
);
669 /* Display all MAC-IP VNI routes linked to an ES */
670 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
671 json_object
*json
, int detail
,
675 struct bgp_path_info
*pi
;
676 int header
= detail
? 0 : 1;
678 struct listnode
*node
;
679 struct bgp_evpn_es
*es
;
680 struct bgp_path_es_info
*es_info
;
681 struct bgp
*bgp
= bgp_get_evpn();
682 json_object
*json_paths
= NULL
;
690 json_paths
= json_object_new_array();
692 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
693 struct list
*es_list
;
695 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
699 es_list
= es
->macip_global_path_list
;
701 es_list
= es
->macip_evi_path_list
;
703 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
704 json_object
*json_path
= NULL
;
709 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
712 /* Overall header/legend displayed once. */
714 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
721 json_path
= json_object_new_array();
724 route_vty_out_detail(
725 vty
, bgp
, rn
, bgp_dest_get_prefix(rn
),
726 pi
, AFI_L2VPN
, SAFI_EVPN
,
727 RPKI_NOT_BEING_USED
, json_path
);
729 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
733 json_object_array_add(json_paths
, json_path
);
738 json_object_object_add(json
, "paths", json_paths
);
739 json_object_int_add(json
, "numPaths", path_cnt
);
742 vty_out(vty
, "There are no MAC-IP ES paths");
744 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
749 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
750 json_object
*json
, int detail
)
752 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
755 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
756 json_object
*json
, int detail
)
758 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
761 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
,
762 struct vty
*vty
, int type
, bool mac_table
,
763 struct in_addr vtep_ip
, json_object
*json
,
766 struct bgp_dest
*dest
;
767 struct bgp_path_info
*pi
;
768 struct bgp_table
*table
;
769 int header
= detail
? 0 : 1;
771 uint32_t prefix_cnt
, path_cnt
;
773 prefix_cnt
= path_cnt
= 0;
776 table
= vpn
->mac_table
;
778 table
= vpn
->ip_table
;
780 tbl_ver
= table
->version
;
781 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
782 const struct prefix_evpn
*evp
=
783 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
784 int add_prefix_to_json
= 0;
785 json_object
*json_paths
= NULL
;
786 json_object
*json_prefix
= NULL
;
787 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
789 if (type
&& evp
->prefix
.route_type
!= type
)
793 json_prefix
= json_object_new_object();
795 pi
= bgp_dest_get_bgp_path_info(dest
);
797 /* Overall header/legend displayed once. */
799 bgp_evpn_show_route_header(vty
, bgp
,
808 json_paths
= json_object_new_array();
810 /* For EVPN, the prefix is displayed for each path (to fit in
811 * with code that already exists).
813 for (; pi
; pi
= pi
->next
) {
815 json_object
*json_path
= NULL
;
817 if (vtep_ip
.s_addr
!= INADDR_ANY
818 && !IPV4_ADDR_SAME(&(vtep_ip
),
819 &(pi
->attr
->nexthop
)))
822 if (evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
824 * VNI IP/MAC table prefixes don't have MAC/IP
825 * respectively so make sure it's set from path
828 if (is_evpn_prefix_ipaddr_none(evp
)) {
829 /* VNI MAC -> Global */
830 evpn_type2_prefix_global_copy(
831 (struct prefix_evpn
*)&tmp_p
,
833 evpn_type2_path_info_get_ip(
836 /* VNI IP -> Global */
837 evpn_type2_prefix_global_copy(
838 (struct prefix_evpn
*)&tmp_p
,
840 evpn_type2_path_info_get_mac(
845 memcpy(&tmp_p
, p
, sizeof(tmp_p
));
849 json_path
= json_object_new_array();
852 route_vty_out_detail(vty
, bgp
, dest
, &tmp_p
, pi
,
853 AFI_L2VPN
, SAFI_EVPN
,
858 route_vty_out(vty
, &tmp_p
, pi
, 0, SAFI_EVPN
,
862 json_object_array_add(json_paths
, json_path
);
865 add_prefix_to_json
= 1;
869 if (add_prefix_to_json
) {
870 json_object_string_addf(json_prefix
, "prefix",
872 json_object_int_add(json_prefix
, "prefixLen",
874 json_object_object_add(json_prefix
, "paths",
876 json_object_object_addf(json
, json_prefix
,
879 json_object_free(json_paths
);
880 json_object_free(json_prefix
);
888 json_object_int_add(json
, "numPrefix", prefix_cnt
);
889 json_object_int_add(json
, "numPaths", path_cnt
);
892 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
893 type
? "(of requested type) " : "");
895 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
896 prefix_cnt
, path_cnt
,
897 type
? " (of requested type)" : "");
902 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
904 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
905 struct vni_walk_ctx
*wctx
= arg
;
906 struct vty
*vty
= wctx
->vty
;
907 json_object
*json
= wctx
->json
;
908 json_object
*json_vni
= NULL
;
909 char vni_str
[VNI_STR_LEN
];
911 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
913 json_vni
= json_object_new_object();
914 json_object_int_add(json_vni
, "vni", vpn
->vni
);
916 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
919 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, wctx
->type
, wctx
->mac_table
,
920 wctx
->vtep_ip
, json_vni
, wctx
->detail
);
923 json_object_object_add(json
, vni_str
, json_vni
);
926 static void show_vni_routes_all_hash(struct hash_bucket
*bucket
, void *arg
)
928 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
929 struct vni_walk_ctx
*wctx
= arg
;
930 struct vty
*vty
= wctx
->vty
;
931 json_object
*json
= wctx
->json
;
932 json_object
*json_vni
= NULL
;
933 json_object
*json_vni_mac
= NULL
;
934 char vni_str
[VNI_STR_LEN
];
936 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
938 json_vni
= json_object_new_object();
939 json_object_int_add(json_vni
, "vni", vpn
->vni
);
941 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
944 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, false, wctx
->vtep_ip
,
945 json_vni
, wctx
->detail
);
948 json_object_object_add(json
, vni_str
, json_vni
);
951 json_vni_mac
= json_object_new_object();
953 vty_out(vty
, "\nVNI: %u MAC Table\n\n", vpn
->vni
);
955 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, true, wctx
->vtep_ip
,
956 json_vni_mac
, wctx
->detail
);
959 json_object_object_add(json_vni
, "macTable", json_vni_mac
);
962 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
965 json_object
*json_vni
= NULL
;
966 json_object
*json_import_rtl
= NULL
;
967 json_object
*json_export_rtl
= NULL
;
969 char buf2
[INET6_ADDRSTRLEN
];
972 struct listnode
*node
, *nnode
;
973 struct vrf_route_target
*l3rt
;
979 json_vni
= json_object_new_object();
980 json_import_rtl
= json_object_new_array();
981 json_export_rtl
= json_object_new_array();
984 /* if an l3vni is present in bgp it is live */
986 snprintf(buf1
, sizeof(buf1
), "*");
989 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
990 json_object_string_add(json_vni
, "type", "L3");
991 json_object_string_add(json_vni
, "inKernel", "True");
992 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
993 &bgp
->originator_ip
);
994 json_object_string_addf(json_vni
, "rd", "%pRD", &bgp
->vrf_prd
);
995 json_object_string_add(json_vni
, "advertiseGatewayMacip",
997 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
998 json_object_string_add(
999 json_vni
, "advertisePip",
1000 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
1001 json_object_string_addf(json_vni
, "sysIP", "%pI4",
1002 &bgp
->evpn_info
->pip_ip
);
1003 json_object_string_add(json_vni
, "sysMAC",
1004 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
1005 buf2
, sizeof(buf2
)));
1006 json_object_string_add(
1008 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
1010 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, bgp
->l3vni
, "L3",
1014 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
1015 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1016 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1019 json_object_array_add(json_import_rtl
,
1020 json_object_new_string(ecom_str
));
1022 if (listcount(bgp
->vrf_import_rtl
) > 1)
1023 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1026 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1028 vty_out(vty
, " %-25s", rt_buf
);
1031 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1033 /* If there are multiple import RTs we break here and show only
1040 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1042 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
1043 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1044 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1047 json_object_array_add(json_export_rtl
,
1048 json_object_new_string(ecom_str
));
1050 if (listcount(bgp
->vrf_export_rtl
) > 1)
1051 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1054 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1056 vty_out(vty
, " %-25s", rt_buf
);
1059 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1061 /* If there are multiple export RTs we break here and show only
1064 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1070 char vni_str
[VNI_STR_LEN
];
1072 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1073 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1074 json_object_object_add(json
, vni_str
, json_vni
);
1080 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1084 json_object
*json_vni
= NULL
;
1085 json_object
*json_import_rtl
= NULL
;
1086 json_object
*json_export_rtl
= NULL
;
1087 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1091 struct listnode
*node
, *nnode
;
1092 struct ecommunity
*ecom
;
1093 struct bgp
*bgp_evpn
;
1098 bgp_evpn
= bgp_get_evpn();
1101 json_vni
= json_object_new_object();
1102 json_import_rtl
= json_object_new_array();
1103 json_export_rtl
= json_object_new_array();
1107 if (is_vni_live(vpn
))
1108 snprintf(buf1
, sizeof(buf1
), "*");
1111 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1112 json_object_string_add(json_vni
, "type", "L2");
1113 json_object_string_add(json_vni
, "inKernel",
1114 is_vni_live(vpn
) ? "True" : "False");
1115 json_object_string_addf(json_vni
, "rd", "%pRD", &vpn
->prd
);
1116 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1117 &vpn
->originator_ip
);
1118 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1120 /* per vni knob is enabled -- Enabled
1121 * Global knob is enabled -- Active
1122 * default -- Disabled
1124 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1125 && bgp_evpn
->advertise_gw_macip
)
1126 json_object_string_add(
1127 json_vni
, "advertiseGatewayMacip", "Active");
1128 else if (vpn
->advertise_gw_macip
)
1129 json_object_string_add(
1130 json_vni
, "advertiseGatewayMacip", "Enabled");
1132 json_object_string_add(
1133 json_vni
, "advertiseGatewayMacip", "Disabled");
1134 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1135 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1136 json_object_string_add(json_vni
, "advertiseSviMacIp",
1138 else if (vpn
->advertise_svi_macip
)
1139 json_object_string_add(json_vni
, "advertiseSviMacIp",
1142 json_object_string_add(json_vni
, "advertiseSviMacIp",
1145 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, vpn
->vni
, "L2",
1149 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1150 ecom_str
= ecommunity_ecom2str(ecom
,
1151 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1154 json_object_array_add(json_import_rtl
,
1155 json_object_new_string(ecom_str
));
1157 if (listcount(vpn
->import_rtl
) > 1)
1158 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1161 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1163 vty_out(vty
, " %-25s", rt_buf
);
1166 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1168 /* If there are multiple import RTs we break here and show only
1175 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1177 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1178 ecom_str
= ecommunity_ecom2str(ecom
,
1179 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1182 json_object_array_add(json_export_rtl
,
1183 json_object_new_string(ecom_str
));
1185 if (listcount(vpn
->export_rtl
) > 1)
1186 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1189 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1191 vty_out(vty
, " %-25s", rt_buf
);
1194 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1196 /* If there are multiple export RTs we break here and show only
1199 vty_out(vty
, "%-37s",
1200 vrf_id_to_name(vpn
->tenant_vrf_id
));
1206 char vni_str
[VNI_STR_LEN
];
1208 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1209 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1210 json_object_object_add(json
, vni_str
, json_vni
);
1216 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1217 enum bgp_show_type type
, void *output_arg
,
1218 int option
, bool use_json
)
1220 afi_t afi
= AFI_L2VPN
;
1222 struct bgp_table
*table
;
1223 struct bgp_dest
*dest
;
1224 struct bgp_dest
*rm
;
1225 struct bgp_path_info
*pi
;
1228 char rd_str
[RD_ADDRSTRLEN
];
1231 unsigned long output_count
= 0;
1232 unsigned long total_count
= 0;
1233 json_object
*json
= NULL
;
1234 json_object
*json_array
= NULL
;
1235 json_object
*json_prefix_info
= NULL
;
1237 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1239 bgp
= bgp_get_evpn();
1242 vty_out(vty
, "No BGP process is configured\n");
1244 vty_out(vty
, "{}\n");
1249 json
= json_object_new_object();
1251 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1252 dest
= bgp_route_next(dest
)) {
1254 json_object
*json_nroute
= NULL
;
1255 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1257 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1260 table
= bgp_dest_get_bgp_table_info(dest
);
1265 tbl_ver
= table
->version
;
1267 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1268 pi
= bgp_dest_get_bgp_path_info(rm
);
1273 for (; pi
; pi
= pi
->next
) {
1274 struct community
*picomm
= NULL
;
1276 picomm
= bgp_attr_get_community(pi
->attr
);
1279 if (type
== bgp_show_type_neighbor
) {
1280 struct peer
*peer
= output_arg
;
1282 if (peer_cmp(peer
, pi
->peer
) != 0)
1285 if (type
== bgp_show_type_lcommunity_exact
) {
1286 struct lcommunity
*lcom
= output_arg
;
1288 if (!bgp_attr_get_lcommunity(
1291 bgp_attr_get_lcommunity(
1296 if (type
== bgp_show_type_lcommunity
) {
1297 struct lcommunity
*lcom
= output_arg
;
1299 if (!bgp_attr_get_lcommunity(
1302 bgp_attr_get_lcommunity(
1307 if (type
== bgp_show_type_community
) {
1308 struct community
*com
= output_arg
;
1311 !community_match(picomm
, com
))
1314 if (type
== bgp_show_type_community_exact
) {
1315 struct community
*com
= output_arg
;
1318 !community_cmp(picomm
, com
))
1323 json_object_int_add(
1324 json
, "bgpTableVersion",
1326 json_object_string_addf(
1331 json_object_int_add(
1334 bgp
->default_local_pref
);
1335 json_object_int_add(
1339 if (option
== SHOW_DISPLAY_TAGS
)
1344 == SHOW_DISPLAY_OVERLAY
)
1348 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1356 json_object_new_object();
1357 bgp_evpn_show_route_rd_header(
1358 vty
, dest
, json_nroute
, rd_str
,
1362 if (use_json
&& !json_array
)
1363 json_array
= json_object_new_array();
1365 if (option
== SHOW_DISPLAY_TAGS
)
1367 vty
, bgp_dest_get_prefix(rm
),
1368 pi
, no_display
, SAFI_EVPN
,
1370 else if (option
== SHOW_DISPLAY_OVERLAY
)
1371 route_vty_out_overlay(
1372 vty
, bgp_dest_get_prefix(rm
),
1373 pi
, no_display
, json_array
);
1376 bgp_dest_get_prefix(rm
),
1377 pi
, no_display
, SAFI_EVPN
,
1385 if (use_json
&& json_array
) {
1386 const struct prefix
*p
=
1387 bgp_dest_get_prefix(rm
);
1389 json_prefix_info
= json_object_new_object();
1391 json_object_string_addf(json_prefix_info
,
1392 "prefix", "%pFX", p
);
1394 json_object_int_add(json_prefix_info
,
1395 "prefixLen", p
->prefixlen
);
1397 json_object_object_add(json_prefix_info
,
1398 "paths", json_array
);
1399 json_object_object_addf(json_nroute
,
1406 if (use_json
&& json_nroute
)
1407 json_object_object_add(json
, rd_str
, json_nroute
);
1411 json_object_int_add(json
, "numPrefix", output_count
);
1412 json_object_int_add(json
, "totalPrefix", total_count
);
1413 vty_json(vty
, json
);
1415 if (output_count
== 0)
1416 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1420 "\nDisplayed %ld out of %ld total prefixes\n",
1421 output_count
, total_count
);
1426 DEFUN(show_ip_bgp_l2vpn_evpn
,
1427 show_ip_bgp_l2vpn_evpn_cmd
,
1428 "show [ip] bgp l2vpn evpn [json]",
1429 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1431 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1432 SHOW_DISPLAY_STANDARD
,
1433 use_json(argc
, argv
));
1436 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1437 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1438 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1444 "Display information for a route distinguisher\n"
1445 "VPN Route Distinguisher\n"
1446 "All VPN Route Distinguishers\n"
1449 int idx_ext_community
= 0;
1451 struct prefix_rd prd
;
1454 if (argv_find(argv
, argc
, "all", &rd_all
))
1455 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1456 NULL
, SHOW_DISPLAY_STANDARD
,
1457 use_json(argc
, argv
));
1459 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1460 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1462 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1465 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1466 SHOW_DISPLAY_STANDARD
,
1467 use_json(argc
, argv
));
1470 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1471 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1472 "show [ip] bgp l2vpn evpn all tags",
1478 "Display information about all EVPN NLRIs\n"
1479 "Display BGP tags for prefixes\n")
1481 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1482 SHOW_DISPLAY_TAGS
, 0);
1485 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1486 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1487 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1493 "Display information for a route distinguisher\n"
1494 "VPN Route Distinguisher\n"
1495 "All VPN Route Distinguishers\n"
1496 "Display BGP tags for prefixes\n")
1498 int idx_ext_community
= 0;
1500 struct prefix_rd prd
;
1503 if (argv_find(argv
, argc
, "all", &rd_all
))
1504 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1505 NULL
, SHOW_DISPLAY_TAGS
, 0);
1507 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1508 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1510 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1513 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1514 SHOW_DISPLAY_TAGS
, 0);
1517 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1518 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1519 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1525 "Detailed information on TCP and BGP neighbor connections\n"
1526 "IPv4 Neighbor to display information about\n"
1527 "IPv6 Neighbor to display information about\n"
1528 "Neighbor on BGP configured interface\n"
1529 "Display routes learned from neighbor\n" JSON_STR
)
1533 char *peerstr
= NULL
;
1534 bool uj
= use_json(argc
, argv
);
1535 afi_t afi
= AFI_L2VPN
;
1536 safi_t safi
= SAFI_EVPN
;
1537 struct bgp
*bgp
= NULL
;
1539 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1542 vty_out(vty
, "No index\n");
1546 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1547 argv_find(argv
, argc
, "neighbors", &idx
);
1548 peerstr
= argv
[++idx
]->arg
;
1550 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1553 json_object
*json_no
= NULL
;
1554 json_no
= json_object_new_object();
1555 json_object_string_add(json_no
, "warning",
1556 "Malformed address");
1557 vty_out(vty
, "%s\n",
1558 json_object_to_json_string(json_no
));
1559 json_object_free(json_no
);
1561 vty_out(vty
, "Malformed address: %s\n",
1565 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1567 json_object
*json_no
= NULL
;
1568 json_no
= json_object_new_object();
1569 json_object_string_add(
1571 "No such neighbor or address family");
1572 vty_out(vty
, "%s\n",
1573 json_object_to_json_string(json_no
));
1574 json_object_free(json_no
);
1576 vty_out(vty
, "%% No such neighbor or address family\n");
1580 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1581 SHOW_DISPLAY_STANDARD
, uj
);
1584 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1585 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1586 "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]",
1592 "Display information for a route distinguisher\n"
1593 "VPN Route Distinguisher\n"
1594 "All VPN Route Distinguishers\n"
1595 "Detailed information on TCP and BGP neighbor connections\n"
1596 "IPv4 Neighbor to display information about\n"
1597 "IPv6 Neighbor to display information about\n"
1598 "Neighbor on BGP configured interface\n"
1599 "Display routes learned from neighbor\n" JSON_STR
)
1601 int idx_ext_community
= 0;
1605 char *peerstr
= NULL
;
1606 struct prefix_rd prd
= {};
1607 bool uj
= use_json(argc
, argv
);
1608 afi_t afi
= AFI_L2VPN
;
1609 safi_t safi
= SAFI_EVPN
;
1610 struct bgp
*bgp
= NULL
;
1613 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1616 vty_out(vty
, "No index\n");
1620 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1621 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1622 &idx_ext_community
);
1623 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1626 json_object
*json_no
= NULL
;
1627 json_no
= json_object_new_object();
1628 json_object_string_add(
1630 "Malformed Route Distinguisher");
1631 vty_out(vty
, "%s\n",
1632 json_object_to_json_string(json_no
));
1633 json_object_free(json_no
);
1636 "%% Malformed Route Distinguisher\n");
1641 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1642 argv_find(argv
, argc
, "neighbors", &idx
);
1643 peerstr
= argv
[++idx
]->arg
;
1645 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1648 json_object
*json_no
= NULL
;
1649 json_no
= json_object_new_object();
1650 json_object_string_add(json_no
, "warning",
1651 "Malformed address");
1652 vty_out(vty
, "%s\n",
1653 json_object_to_json_string(json_no
));
1654 json_object_free(json_no
);
1656 vty_out(vty
, "Malformed address: %s\n",
1660 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1662 json_object
*json_no
= NULL
;
1663 json_no
= json_object_new_object();
1664 json_object_string_add(
1666 "No such neighbor or address family");
1667 vty_out(vty
, "%s\n",
1668 json_object_to_json_string(json_no
));
1669 json_object_free(json_no
);
1671 vty_out(vty
, "%% No such neighbor or address family\n");
1677 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1678 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1680 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1681 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1684 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1685 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1686 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1692 "Detailed information on TCP and BGP neighbor connections\n"
1693 "IPv4 Neighbor to display information about\n"
1694 "IPv6 Neighbor to display information about\n"
1695 "Neighbor on BGP configured interface\n"
1696 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1700 bool uj
= use_json(argc
, argv
);
1701 struct bgp
*bgp
= NULL
;
1702 afi_t afi
= AFI_L2VPN
;
1703 safi_t safi
= SAFI_EVPN
;
1704 char *peerstr
= NULL
;
1709 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1712 vty_out(vty
, "No index\n");
1716 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1717 argv_find(argv
, argc
, "neighbors", &idx
);
1718 peerstr
= argv
[++idx
]->arg
;
1720 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1723 json_object
*json_no
= NULL
;
1724 json_no
= json_object_new_object();
1725 json_object_string_add(json_no
, "warning",
1726 "Malformed address");
1727 vty_out(vty
, "%s\n",
1728 json_object_to_json_string(json_no
));
1729 json_object_free(json_no
);
1731 vty_out(vty
, "Malformed address: %s\n",
1735 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1737 json_object
*json_no
= NULL
;
1738 json_no
= json_object_new_object();
1739 json_object_string_add(
1741 "No such neighbor or address family");
1742 vty_out(vty
, "%s\n",
1743 json_object_to_json_string(json_no
));
1744 json_object_free(json_no
);
1746 vty_out(vty
, "%% No such neighbor or address family\n");
1750 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1753 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1754 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1755 "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]",
1761 "Display information for a route distinguisher\n"
1762 "VPN Route Distinguisher\n"
1763 "All VPN Route Distinguishers\n"
1764 "Detailed information on TCP and BGP neighbor connections\n"
1765 "IPv4 Neighbor to display information about\n"
1766 "IPv6 Neighbor to display information about\n"
1767 "Neighbor on BGP configured interface\n"
1768 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1770 int idx_ext_community
= 0;
1774 struct prefix_rd prd
;
1775 struct bgp
*bgp
= NULL
;
1776 bool uj
= use_json(argc
, argv
);
1777 char *peerstr
= NULL
;
1778 afi_t afi
= AFI_L2VPN
;
1779 safi_t safi
= SAFI_EVPN
;
1788 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1791 vty_out(vty
, "No index\n");
1795 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1796 argv_find(argv
, argc
, "neighbors", &idx
);
1797 peerstr
= argv
[++idx
]->arg
;
1799 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1802 json_object
*json_no
= NULL
;
1803 json_no
= json_object_new_object();
1804 json_object_string_add(json_no
, "warning",
1805 "Malformed address");
1806 vty_out(vty
, "%s\n",
1807 json_object_to_json_string(json_no
));
1808 json_object_free(json_no
);
1810 vty_out(vty
, "Malformed address: %s\n",
1814 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1816 json_object
*json_no
= NULL
;
1817 json_no
= json_object_new_object();
1818 json_object_string_add(
1820 "No such neighbor or address family");
1821 vty_out(vty
, "%s\n",
1822 json_object_to_json_string(json_no
));
1823 json_object_free(json_no
);
1825 vty_out(vty
, "%% No such neighbor or address family\n");
1829 if (argv_find(argv
, argc
, "all", &rd_all
))
1830 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1833 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1834 &idx_ext_community
);
1835 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1838 json_object
*json_no
= NULL
;
1839 json_no
= json_object_new_object();
1840 json_object_string_add(
1842 "Malformed Route Distinguisher");
1843 vty_out(vty
, "%s\n",
1844 json_object_to_json_string(json_no
));
1845 json_object_free(json_no
);
1848 "%% Malformed Route Distinguisher\n");
1853 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1856 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1857 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1858 "show [ip] bgp l2vpn evpn all overlay [json]",
1864 "Display information about all EVPN NLRIs\n"
1865 "Display BGP Overlay Information for prefixes\n"
1868 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1869 SHOW_DISPLAY_OVERLAY
,
1870 use_json(argc
, argv
));
1873 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1874 show_ip_bgp_evpn_rd_overlay_cmd
,
1875 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1881 "Display information for a route distinguisher\n"
1882 "VPN Route Distinguisher\n"
1883 "All VPN Route Distinguishers\n"
1884 "Display BGP Overlay Information for prefixes\n")
1886 int idx_ext_community
= 0;
1888 struct prefix_rd prd
;
1891 if (argv_find(argv
, argc
, "all", &rd_all
))
1892 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1893 NULL
, SHOW_DISPLAY_OVERLAY
,
1894 use_json(argc
, argv
));
1896 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1897 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1899 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1902 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1903 SHOW_DISPLAY_OVERLAY
,
1904 use_json(argc
, argv
));
1907 DEFUN(show_bgp_l2vpn_evpn_com
,
1908 show_bgp_l2vpn_evpn_com_cmd
,
1909 "show bgp l2vpn evpn \
1910 <community AA:NN|large-community AA:BB:CC> \
1911 [exact-match] [json]",
1916 "Display routes matching the community\n"
1917 "Community number where AA and NN are (0-65535)\n"
1918 "Display routes matching the large-community\n"
1919 "List of large-community numbers\n"
1920 "Exact match of the communities\n"
1925 const char *clist_number_or_name
;
1926 int show_type
= bgp_show_type_normal
;
1927 struct community
*com
;
1928 struct lcommunity
*lcom
;
1930 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1931 clist_number_or_name
= argv
[++idx
]->arg
;
1932 show_type
= bgp_show_type_lcommunity
;
1934 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1935 show_type
= bgp_show_type_lcommunity_exact
;
1937 lcom
= lcommunity_str2com(clist_number_or_name
);
1939 vty_out(vty
, "%% Large-community malformed\n");
1943 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1944 SHOW_DISPLAY_STANDARD
,
1945 use_json(argc
, argv
));
1947 lcommunity_free(&lcom
);
1948 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1949 clist_number_or_name
= argv
[++idx
]->arg
;
1950 show_type
= bgp_show_type_community
;
1952 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1953 show_type
= bgp_show_type_community_exact
;
1955 com
= community_str2com(clist_number_or_name
);
1958 vty_out(vty
, "%% Community malformed: %s\n",
1959 clist_number_or_name
);
1963 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1964 SHOW_DISPLAY_STANDARD
,
1965 use_json(argc
, argv
));
1966 community_free(&com
);
1972 /* For testing purpose, static route of EVPN RT-5. */
1973 DEFUN(evpnrt5_network
,
1974 evpnrt5_network_cmd
,
1975 "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]",
1976 "Specify a network to announce via BGP\n"
1979 "Specify Route Distinguisher\n"
1980 "VPN Route Distinguisher\n"
1982 "Ethernet Tag Value\n"
1985 "Ethernet Segment Identifier\n"
1986 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1988 "Gateway IP ( A.B.C.D )\n"
1989 "Gateway IPv6 ( X:X::X:X )\n"
1990 "Router Mac Ext Comm\n"
1991 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1992 "Route-map to modify the attributes\n"
1993 "Name of the route map\n")
1995 int idx_ipv4_prefixlen
= 1;
1996 int idx_route_distinguisher
= 3;
2001 int idx_routermac
= 13;
2003 return bgp_static_set_safi(
2004 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2005 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
2006 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2007 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
2008 argv
[idx_routermac
]->arg
);
2011 /* For testing purpose, static route of EVPN RT-5. */
2012 DEFUN(no_evpnrt5_network
,
2013 no_evpnrt5_network_cmd
,
2014 "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>",
2016 "Specify a network to announce via BGP\n"
2019 "Specify Route Distinguisher\n"
2020 "VPN Route Distinguisher\n"
2022 "Ethernet Tag Value\n"
2025 "Ethernet Segment Identifier\n"
2026 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2027 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2029 int idx_ipv4_prefixlen
= 2;
2030 int idx_ext_community
= 4;
2035 return bgp_static_unset_safi(
2036 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2037 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2038 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2039 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2042 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2044 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
, false);
2047 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2049 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
, false);
2053 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2054 * check that this is a change.
2056 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2057 struct ecommunity
*ecomadd
)
2059 /* If the VNI is "live", we need to uninstall routes using the current
2060 * import RT(s) first before we update the import RT, and subsequently
2063 if (is_vni_live(vpn
))
2064 bgp_evpn_uninstall_routes(bgp
, vpn
);
2066 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2067 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2069 /* If the auto route-target is in use we must remove it */
2070 evpn_import_rt_delete_auto(bgp
, vpn
);
2072 /* Add new RT and rebuild the RT to VNI mapping */
2073 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2075 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2076 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2078 /* Install routes that match new import RT */
2079 if (is_vni_live(vpn
))
2080 bgp_evpn_install_routes(bgp
, vpn
);
2084 * Unconfigure Import RT(s) for a VNI (vty handler).
2086 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2087 struct ecommunity
*ecomdel
)
2089 struct listnode
*node
, *nnode
, *node_to_del
;
2090 struct ecommunity
*ecom
;
2092 /* Along the lines of "configure" except we have to reset to the
2095 if (is_vni_live(vpn
))
2096 bgp_evpn_uninstall_routes(bgp
, vpn
);
2098 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2099 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2101 /* Delete all import RTs */
2102 if (ecomdel
== NULL
) {
2103 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2104 ecommunity_free(&ecom
);
2105 list_delete_node(vpn
->import_rtl
, node
);
2109 /* Delete a specific import RT */
2113 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2114 if (ecommunity_match(ecom
, ecomdel
)) {
2115 ecommunity_free(&ecom
);
2122 list_delete_node(vpn
->import_rtl
, node_to_del
);
2125 assert(vpn
->import_rtl
);
2126 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2127 if (list_isempty(vpn
->import_rtl
)) {
2128 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2129 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2131 /* Rebuild the RT to VNI mapping */
2133 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2135 /* Install routes that match new import RT */
2136 if (is_vni_live(vpn
))
2137 bgp_evpn_install_routes(bgp
, vpn
);
2141 * Configure the Export RT for a VNI (vty handler). Caller expected to
2142 * check that this is a change. Note that only a single export RT is
2143 * allowed for a VNI and any change to configuration is implemented as
2144 * a "replace" (similar to other configuration).
2146 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2147 struct ecommunity
*ecomadd
)
2149 /* If the auto route-target is in use we must remove it */
2150 evpn_export_rt_delete_auto(bgp
, vpn
);
2152 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2153 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2155 if (is_vni_live(vpn
))
2156 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2160 * Unconfigure the Export RT for a VNI (vty handler)
2162 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2163 struct ecommunity
*ecomdel
)
2165 struct listnode
*node
, *nnode
, *node_to_del
;
2166 struct ecommunity
*ecom
;
2168 /* Delete all export RTs */
2169 if (ecomdel
== NULL
) {
2170 /* Reset to default and process all routes. */
2171 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2172 ecommunity_free(&ecom
);
2173 list_delete_node(vpn
->export_rtl
, node
);
2177 /* Delete a specific export RT */
2181 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2182 if (ecommunity_match(ecom
, ecomdel
)) {
2183 ecommunity_free(&ecom
);
2190 list_delete_node(vpn
->export_rtl
, node_to_del
);
2193 assert(vpn
->export_rtl
);
2194 if (list_isempty(vpn
->export_rtl
)) {
2195 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2196 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2199 if (is_vni_live(vpn
))
2200 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2204 * Configure RD for VRF
2206 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2208 /* If we have already advertise type-5 routes with a diffrent RD, we
2209 * have to delete and withdraw them firs
2211 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2214 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2215 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2217 /* We have a new RD for VRF.
2218 * Advertise all type-5 routes again with the new RD
2220 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2224 * Unconfigure RD for VRF
2226 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2228 /* If we have already advertise type-5 routes with a diffrent RD, we
2229 * have to delete and withdraw them firs
2231 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2233 /* fall back to default RD */
2234 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2235 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2237 /* We have a new RD for VRF.
2238 * Advertise all type-5 routes again with the new RD
2240 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2244 * Configure RD for a VNI (vty handler)
2246 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2247 struct prefix_rd
*rd
)
2249 /* If the VNI is "live", we need to delete and withdraw this VNI's
2250 * local routes with the prior RD first. Then, after updating RD,
2251 * need to re-advertise.
2253 if (is_vni_live(vpn
))
2254 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2257 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2258 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2260 if (is_vni_live(vpn
))
2261 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2265 * Unconfigure RD for a VNI (vty handler)
2267 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
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 resetting RD
2271 * to automatic value, need to re-advertise.
2273 if (is_vni_live(vpn
))
2274 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2276 /* reset RD to default */
2277 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2279 if (is_vni_live(vpn
))
2280 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2284 * Create VNI, if not already present (VTY handler). Mark as configured.
2286 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2288 struct bgpevpn
*vpn
;
2289 struct in_addr mcast_grp
= {INADDR_ANY
};
2291 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2293 /* Check if this L2VNI is already configured as L3VNI */
2294 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2297 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2302 /* tenant vrf will be updated when we get local_vni_add from
2305 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2308 /* Mark as configured. */
2309 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2314 * Delete VNI. If VNI does not exist in the system (i.e., just
2315 * configuration), all that is needed is to free it. Otherwise,
2316 * any parameters configured for the VNI need to be reset (with
2317 * appropriate action) and the VNI marked as unconfigured; the
2318 * VNI will continue to exist, purely as a "learnt" entity.
2320 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2322 if (!is_vni_live(vpn
)) {
2323 bgp_evpn_free(bgp
, vpn
);
2327 /* We need to take the unconfigure action for each parameter of this VNI
2328 * that is configured. Some optimization is possible, but not worth the
2329 * additional code for an operation that should be pretty rare.
2331 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2333 /* First, deal with the export side - RD and export RT changes. */
2334 if (is_rd_configured(vpn
))
2335 evpn_unconfigure_rd(bgp
, vpn
);
2336 if (is_export_rt_configured(vpn
))
2337 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2339 /* Next, deal with the import side. */
2340 if (is_import_rt_configured(vpn
))
2341 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2345 * Display import RT mapping to VRFs (vty handler)
2346 * bgp_evpn: evpn bgp instance
2348 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2356 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2357 (void (*)(struct hash_bucket
*,
2358 void *))show_vrf_import_rt_entry
,
2363 * Display import RT mapping to VNIs (vty handler)
2365 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2374 bgp
->import_rt_hash
,
2375 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2380 * Display EVPN routes for all VNIs - vty handler.
2382 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
, int type
,
2383 bool mac_table
, struct in_addr vtep_ip
,
2384 json_object
*json
, int detail
)
2387 struct vni_walk_ctx wctx
;
2389 num_vnis
= hashcount(bgp
->vnihash
);
2392 memset(&wctx
, 0, sizeof(wctx
));
2396 wctx
.mac_table
= mac_table
;
2397 wctx
.vtep_ip
= vtep_ip
;
2399 wctx
.detail
= detail
;
2400 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2401 void *))show_vni_routes_hash
,
2406 * Display EVPN routes for all VNIs & all types - vty handler.
2408 static void evpn_show_routes_vni_all_type_all(struct vty
*vty
, struct bgp
*bgp
,
2409 struct in_addr vtep_ip
,
2410 json_object
*json
, int detail
)
2413 struct vni_walk_ctx wctx
;
2415 num_vnis
= hashcount(bgp
->vnihash
);
2419 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2422 wctx
.vtep_ip
= vtep_ip
;
2424 wctx
.detail
= detail
;
2425 hash_iterate(bgp
->vnihash
,
2426 (void (*)(struct hash_bucket
*,
2427 void *))show_vni_routes_all_hash
,
2432 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2434 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2435 vni_t vni
, struct in_addr orig_ip
,
2438 struct bgpevpn
*vpn
;
2439 struct prefix_evpn p
;
2440 struct bgp_dest
*dest
;
2441 struct bgp_path_info
*pi
;
2442 uint32_t path_cnt
= 0;
2445 json_object
*json_paths
= NULL
;
2451 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2453 vty_out(vty
, "VNI not found\n");
2457 /* See if route exists. */
2458 build_evpn_type3_prefix(&p
, orig_ip
);
2459 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2460 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2462 vty_out(vty
, "%% Network not in table\n");
2465 bgp_dest_unlock_node(dest
);
2471 json_paths
= json_object_new_array();
2473 /* Prefix and num paths displayed once per prefix. */
2474 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2475 NULL
, afi
, safi
, json
, false);
2477 /* Display each path for this prefix. */
2478 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2479 json_object
*json_path
= NULL
;
2482 json_path
= json_object_new_array();
2484 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2485 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2489 json_object_array_add(json_paths
, json_path
);
2496 json_object_object_add(json
, "paths", json_paths
);
2498 json_object_int_add(json
, "numPaths", path_cnt
);
2500 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2504 bgp_dest_unlock_node(dest
);
2508 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2509 * By definition, only matching type-2 route will be displayed.
2511 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2512 vni_t vni
, struct ethaddr
*mac
,
2513 struct ipaddr
*ip
, json_object
*json
)
2515 struct bgpevpn
*vpn
;
2516 struct prefix_evpn p
;
2517 struct prefix_evpn tmp_p
;
2518 struct bgp_dest
*dest
;
2519 struct bgp_path_info
*pi
;
2520 uint32_t path_cnt
= 0;
2523 json_object
*json_paths
= NULL
;
2524 struct ethaddr empty_mac
= {};
2525 struct ipaddr empty_ip
= {};
2526 const struct prefix_evpn
*evp
;
2532 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2535 vty_out(vty
, "VNI not found\n");
2539 build_evpn_type2_prefix(&p
, mac
? mac
: &empty_mac
,
2540 ip
? ip
: &empty_ip
);
2542 /* See if route exists. Look for both non-sticky and sticky. */
2543 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2544 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2546 vty_out(vty
, "%% Network not in table\n");
2549 bgp_dest_unlock_node(dest
);
2555 * MAC is per-path, we have to walk the path_info's and look for it
2559 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2560 if (memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2567 vty_out(vty
, "%% Network not in table\n");
2573 json_paths
= json_object_new_array();
2575 /* Prefix and num paths displayed once per prefix. */
2576 route_vty_out_detail_header(vty
, bgp
, dest
, (struct prefix
*)&p
, NULL
,
2577 afi
, safi
, json
, false);
2579 evp
= (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2581 /* Display each path for this prefix. */
2582 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2583 json_object
*json_path
= NULL
;
2585 /* skip non-matching MACs */
2587 memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2592 json_path
= json_object_new_array();
2595 * VNI table MAC-IP prefixes don't have MAC so
2596 * make sure it's set from path info
2599 if (is_evpn_prefix_ipaddr_none(evp
)) {
2600 /* VNI MAC -> Global */
2601 evpn_type2_prefix_global_copy(
2602 (struct prefix_evpn
*)&tmp_p
, evp
,
2604 evpn_type2_path_info_get_ip(pi
));
2606 /* VNI IP -> Global */
2607 evpn_type2_prefix_global_copy(
2608 (struct prefix_evpn
*)&tmp_p
, evp
,
2609 evpn_type2_path_info_get_mac(pi
),
2613 route_vty_out_detail(vty
, bgp
, dest
, (struct prefix
*)&tmp_p
,
2614 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2618 json_object_array_add(json_paths
, json_path
);
2625 json_object_object_add(json
, "paths", json_paths
);
2627 json_object_int_add(json
, "numPaths", path_cnt
);
2629 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2633 bgp_dest_unlock_node(dest
);
2636 /* Disaplay EVPN routes for a ESI - VTY handler */
2637 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2638 esi_t
*esi
, json_object
*json
)
2640 struct bgp_evpn_es
*es
= NULL
;
2643 es
= bgp_evpn_es_find(esi
);
2646 vty_out(vty
, "ESI not found\n");
2650 show_esi_routes(bgp
, es
, vty
, json
);
2654 * Display EVPN routes for a VNI - vty handler.
2655 * If 'type' is non-zero, only routes matching that type are shown.
2656 * If the vtep_ip is non zero, only routes behind that vtep are shown
2658 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2659 int type
, bool mac_table
,
2660 struct in_addr vtep_ip
, json_object
*json
)
2662 struct bgpevpn
*vpn
;
2665 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2668 vty_out(vty
, "VNI not found\n");
2672 /* Walk this VNI's route table and display appropriate routes. */
2673 show_vni_routes(bgp
, vpn
, vty
, type
, mac_table
, vtep_ip
, json
, 0);
2677 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2678 * IP (vty handler). By definition, only matching type-2 route will be
2681 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2682 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2683 struct ipaddr
*ip
, json_object
*json
)
2685 struct prefix_evpn p
;
2686 struct bgp_dest
*dest
;
2687 struct bgp_path_info
*pi
;
2690 uint32_t path_cnt
= 0;
2691 json_object
*json_paths
= NULL
;
2696 /* See if route exists. Look for both non-sticky and sticky. */
2697 build_evpn_type2_prefix(&p
, mac
, ip
);
2698 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2699 (struct prefix
*)&p
, prd
);
2700 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2702 vty_out(vty
, "%% Network not in table\n");
2705 bgp_dest_unlock_node(dest
);
2710 /* Prefix and num paths displayed once per prefix. */
2711 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2712 prd
, afi
, safi
, json
, false);
2715 json_paths
= json_object_new_array();
2717 /* Display each path for this prefix. */
2718 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2719 json_object
*json_path
= NULL
;
2722 json_path
= json_object_new_array();
2724 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2725 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2729 json_object_array_add(json_paths
, json_path
);
2734 if (json
&& path_cnt
) {
2736 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2737 json_object_int_add(json
, "numPaths", path_cnt
);
2739 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2743 bgp_dest_unlock_node(dest
);
2747 * Display BGP EVPN routing table -- for specific RD (vty handler)
2748 * If 'type' is non-zero, only routes matching that type are shown.
2750 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2751 struct prefix_rd
*prd
, int type
,
2754 struct bgp_dest
*rd_dest
;
2755 struct bgp_table
*table
;
2756 struct bgp_dest
*dest
;
2757 struct bgp_path_info
*pi
;
2761 uint32_t prefix_cnt
, path_cnt
;
2762 json_object
*json_rd
= NULL
;
2763 int add_rd_to_json
= 0;
2767 prefix_cnt
= path_cnt
= 0;
2769 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2773 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2774 if (table
== NULL
) {
2775 bgp_dest_unlock_node(rd_dest
);
2780 json_rd
= json_object_new_object();
2781 json_object_string_addf(json_rd
, "rd", "%pRD", prd
);
2784 bgp_dest_unlock_node(rd_dest
);
2786 /* Display all prefixes with this RD. */
2787 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2788 const struct prefix_evpn
*evp
=
2789 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2790 json_object
*json_prefix
= NULL
;
2791 json_object
*json_paths
= NULL
;
2792 int add_prefix_to_json
= 0;
2794 if (type
&& evp
->prefix
.route_type
!= type
)
2798 json_prefix
= json_object_new_object();
2800 pi
= bgp_dest_get_bgp_path_info(dest
);
2802 /* RD header and legend - once overall. */
2803 if (rd_header
&& !json
) {
2805 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2807 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2809 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2811 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2813 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2817 /* Prefix and num paths displayed once per prefix. */
2818 route_vty_out_detail_header(
2819 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), prd
,
2820 afi
, safi
, json_prefix
, false);
2826 json_paths
= json_object_new_array();
2828 /* Display each path for this prefix. */
2829 for (; pi
; pi
= pi
->next
) {
2830 json_object
*json_path
= NULL
;
2833 json_path
= json_object_new_array();
2835 route_vty_out_detail(
2836 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), pi
,
2837 afi
, safi
, RPKI_NOT_BEING_USED
, json_path
);
2840 json_object_array_add(json_paths
, json_path
);
2843 add_prefix_to_json
= 1;
2848 if (add_prefix_to_json
) {
2849 json_object_object_add(json_prefix
, "paths",
2851 json_object_object_addf(json_rd
, json_prefix
,
2854 json_object_free(json_paths
);
2855 json_object_free(json_prefix
);
2864 json_object_object_addf(json
, json_rd
, "%pRD", prd
);
2866 json_object_free(json_rd
);
2870 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2871 json_object_int_add(json
, "numPaths", path_cnt
);
2873 if (prefix_cnt
== 0)
2874 vty_out(vty
, "No prefixes exist with this RD%s\n",
2875 type
? " (of requested type)" : "");
2878 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2879 prefix_cnt
, path_cnt
,
2880 type
? " (of requested type)" : "");
2885 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2886 * (vty handler). Only matching type-2 routes will be displayed.
2888 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2889 struct ethaddr
*mac
, struct ipaddr
*ip
,
2892 struct bgp_dest
*rd_dest
;
2893 struct bgp_table
*table
;
2894 struct bgp_dest
*dest
;
2895 struct bgp_path_info
*pi
;
2896 afi_t afi
= AFI_L2VPN
;
2897 safi_t safi
= SAFI_EVPN
;
2898 uint32_t prefix_cnt
, path_cnt
;
2899 prefix_cnt
= path_cnt
= 0;
2901 /* EVPN routing table is a 2-level table with the first level being
2902 * the RD. We need to look in every RD we know about.
2904 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2905 rd_dest
= bgp_route_next(rd_dest
)) {
2906 json_object
*json_paths
= NULL
; /* paths array for prefix */
2907 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2908 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2909 char rd_str
[RD_ADDRSTRLEN
];
2910 int add_rd_to_json
= 0;
2911 struct prefix_evpn ep
;
2912 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2914 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2918 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2921 /* Construct an RT-2 from the user-supplied mac(ip),
2922 * then search the l2vpn evpn table for it.
2924 build_evpn_type2_prefix(&ep
, mac
, ip
);
2925 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2926 (struct prefix
*)&ep
,
2927 (struct prefix_rd
*)rd_destp
);
2932 json_rd
= json_object_new_object();
2934 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2936 pi
= bgp_dest_get_bgp_path_info(dest
);
2938 /* RD header - per RD. */
2939 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2940 rd_str
, RD_ADDRSTRLEN
);
2945 json_prefix
= json_object_new_object();
2946 json_paths
= json_object_new_array();
2947 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2949 json_object_int_add(json_prefix
, "prefixLen",
2952 /* Prefix and num paths displayed once per prefix. */
2953 route_vty_out_detail_header(
2954 vty
, bgp
, dest
, p
, (struct prefix_rd
*)rd_destp
,
2955 AFI_L2VPN
, SAFI_EVPN
, json_prefix
, false);
2957 /* For EVPN, the prefix is displayed for each path (to
2958 * fit in with code that already exists).
2960 for (; pi
; pi
= pi
->next
) {
2961 json_object
*json_path
= NULL
;
2967 json_path
= json_object_new_array();
2969 route_vty_out_detail(vty
, bgp
, dest
, p
, pi
, AFI_L2VPN
,
2970 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2974 json_object_array_add(json_paths
, json_path
);
2980 json_object_object_add(json_prefix
, "paths",
2982 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
2985 json_object_object_add(json
, rd_str
, json_rd
);
2987 json_object_free(json_rd
);
2992 bgp_dest_unlock_node(dest
);
2996 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2997 json_object_int_add(json
, "numPaths", path_cnt
);
2999 if (prefix_cnt
== 0) {
3000 vty_out(vty
, "No Matching EVPN prefixes exist\n");
3002 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
3003 prefix_cnt
, path_cnt
);
3009 * Display BGP EVPN routing table - all routes (vty handler).
3010 * If 'type' is non-zero, only routes matching that type are shown.
3012 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3013 json_object
*json
, int detail
)
3015 struct bgp_dest
*rd_dest
;
3016 struct bgp_table
*table
;
3017 struct bgp_dest
*dest
;
3018 struct bgp_path_info
*pi
;
3019 int header
= detail
? 0 : 1;
3023 uint32_t prefix_cnt
, path_cnt
;
3027 prefix_cnt
= path_cnt
= 0;
3029 /* EVPN routing table is a 2-level table with the first level being
3032 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
3033 rd_dest
= bgp_route_next(rd_dest
)) {
3034 char rd_str
[RD_ADDRSTRLEN
];
3035 json_object
*json_rd
= NULL
; /* contains routes for an RD */
3036 int add_rd_to_json
= 0;
3038 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
3040 table
= bgp_dest_get_bgp_table_info(rd_dest
);
3044 tbl_ver
= table
->version
;
3045 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
3049 json_rd
= json_object_new_object();
3053 /* Display all prefixes for an RD */
3054 for (dest
= bgp_table_top(table
); dest
;
3055 dest
= bgp_route_next(dest
)) {
3056 json_object
*json_prefix
=
3057 NULL
; /* contains prefix under a RD */
3058 json_object
*json_paths
=
3059 NULL
; /* array of paths under a prefix*/
3060 const struct prefix_evpn
*evp
=
3061 (const struct prefix_evpn
*)bgp_dest_get_prefix(
3063 int add_prefix_to_json
= 0;
3064 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3066 if (type
&& evp
->prefix
.route_type
!= type
)
3069 pi
= bgp_dest_get_bgp_path_info(dest
);
3071 /* Overall header/legend displayed once. */
3073 bgp_evpn_show_route_header(vty
, bgp
,
3078 "%19s Extended Community\n"
3083 /* RD header - per RD. */
3085 bgp_evpn_show_route_rd_header(
3086 vty
, rd_dest
, json_rd
, rd_str
,
3095 json_prefix
= json_object_new_object();
3096 json_paths
= json_object_new_array();
3097 json_object_string_addf(json_prefix
, "prefix",
3099 json_object_int_add(json_prefix
, "prefixLen",
3103 /* Prefix and num paths displayed once per prefix. */
3105 route_vty_out_detail_header(
3107 bgp_dest_get_prefix(dest
),
3108 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3109 SAFI_EVPN
, json_prefix
, false);
3111 /* For EVPN, the prefix is displayed for each path (to
3113 * with code that already exists).
3115 for (; pi
; pi
= pi
->next
) {
3116 json_object
*json_path
= NULL
;
3119 add_prefix_to_json
= 1;
3123 json_path
= json_object_new_array();
3126 route_vty_out_detail(
3128 bgp_dest_get_prefix(dest
), pi
,
3129 AFI_L2VPN
, SAFI_EVPN
,
3130 RPKI_NOT_BEING_USED
, json_path
);
3132 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3136 json_object_array_add(json_paths
,
3141 if (add_prefix_to_json
) {
3142 json_object_object_add(json_prefix
,
3145 json_object_object_addf(json_rd
,
3149 json_object_free(json_prefix
);
3150 json_object_free(json_paths
);
3159 json_object_object_add(json
, rd_str
, json_rd
);
3161 json_object_free(json_rd
);
3168 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3169 json_object_int_add(json
, "numPaths", path_cnt
);
3171 if (prefix_cnt
== 0) {
3172 vty_out(vty
, "No EVPN prefixes %sexist\n",
3173 type
? "(of requested type) " : "");
3175 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3176 prefix_cnt
, path_cnt
,
3177 type
? " (of requested type)" : "");
3182 int bgp_evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3183 bool use_json
, int detail
)
3185 json_object
*json
= NULL
;
3188 json
= json_object_new_object();
3190 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
3193 vty_json(vty
, json
);
3198 * Display specified VNI (vty handler)
3200 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3204 struct bgpevpn
*vpn
;
3206 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3209 display_vni(vty
, vpn
, json
);
3211 struct bgp
*bgp_temp
;
3212 struct listnode
*node
= NULL
;
3214 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3215 if (bgp_temp
->l3vni
== vni
) {
3217 display_l3vni(vty
, bgp_temp
, json
);
3224 vty_out(vty
, "{}\n");
3226 vty_out(vty
, "VNI not found\n");
3233 * Display a VNI (upon user query).
3235 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3239 struct bgp
*bgp_temp
= NULL
;
3240 struct listnode
*node
;
3244 vty_out(vty
, "Flags: * - Kernel\n");
3245 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3246 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3249 /* print all L2 VNIS */
3252 hash_iterate(bgp
->vnihash
,
3253 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3256 /* print all L3 VNIs */
3257 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3258 show_l3vni_entry(vty
, bgp_temp
, json
);
3262 * evpn - enable advertisement of svi MAC-IP
3264 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3268 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3270 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3273 bgp
->evpn_info
->advertise_svi_macip
= set
;
3274 bgp_zebra_advertise_svi_macip(bgp
,
3275 bgp
->evpn_info
->advertise_svi_macip
, 0);
3277 if (set
&& vpn
->advertise_svi_macip
)
3279 else if (!set
&& !vpn
->advertise_svi_macip
)
3282 vpn
->advertise_svi_macip
= set
;
3283 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3289 * evpn - enable advertisement of default g/w
3291 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3294 if (bgp
->advertise_gw_macip
)
3297 bgp
->advertise_gw_macip
= 1;
3298 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3300 if (vpn
->advertise_gw_macip
)
3303 vpn
->advertise_gw_macip
= 1;
3304 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3311 * evpn - disable advertisement of default g/w
3313 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3314 struct bgpevpn
*vpn
)
3317 if (!bgp
->advertise_gw_macip
)
3320 bgp
->advertise_gw_macip
= 0;
3321 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3323 if (!vpn
->advertise_gw_macip
)
3326 vpn
->advertise_gw_macip
= 0;
3327 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3334 * evpn - enable advertisement of default g/w
3336 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3337 afi_t afi
, bool add
)
3339 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3342 /* bail if we are already advertising default route */
3343 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3347 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3348 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3349 else if (afi
== AFI_IP6
)
3350 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3351 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3353 /* bail out if we havent advertised the default route */
3354 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3357 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3358 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3359 else if (afi
== AFI_IP6
)
3360 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3361 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3364 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3368 * evpn - enable advertisement of default g/w
3370 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3371 struct bgpevpn
*vpn
)
3373 if (vpn
->advertise_subnet
)
3376 vpn
->advertise_subnet
= 1;
3377 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3381 * evpn - disable advertisement of default g/w
3383 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3385 if (!vpn
->advertise_subnet
)
3388 vpn
->advertise_subnet
= 0;
3389 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3393 * EVPN (VNI advertisement) enabled. Register with zebra.
3395 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3397 bgp
->advertise_all_vni
= 1;
3399 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3403 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3404 * cache, EVPN routes (delete and withdraw from peers).
3406 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3408 bgp
->advertise_all_vni
= 0;
3409 bgp_set_evpn(bgp_get_default());
3410 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3411 bgp_evpn_cleanup_on_disable(bgp
);
3414 /* Set resolve overlay index flag */
3415 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3417 if (set
== bgp
->resolve_overlay_index
)
3421 bgp
->resolve_overlay_index
= true;
3422 hash_iterate(bgp
->vnihash
,
3423 (void (*)(struct hash_bucket
*, void *))
3424 bgp_evpn_handle_resolve_overlay_index_set
,
3429 (void (*)(struct hash_bucket
*, void *))
3430 bgp_evpn_handle_resolve_overlay_index_unset
,
3432 bgp
->resolve_overlay_index
= false;
3437 * EVPN - use RFC8365 to auto-derive RT
3439 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3441 bgp
->advertise_autort_rfc8365
= 1;
3442 bgp_evpn_handle_autort_change(bgp
);
3446 * EVPN - don't use RFC8365 to auto-derive RT
3448 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3450 bgp
->advertise_autort_rfc8365
= 0;
3451 bgp_evpn_handle_autort_change(bgp
);
3454 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3457 struct listnode
*node
, *nnode
;
3458 struct ecommunity
*ecom
;
3460 if (is_vni_configured(vpn
)) {
3461 vty_out(vty
, " vni %u\n", vpn
->vni
);
3462 if (is_rd_configured(vpn
))
3463 vty_out(vty
, " rd %pRD\n", &vpn
->prd
);
3465 if (is_import_rt_configured(vpn
)) {
3466 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3468 ecom_str
= ecommunity_ecom2str(
3469 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3470 vty_out(vty
, " route-target import %s\n",
3472 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3476 if (is_export_rt_configured(vpn
)) {
3477 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3479 ecom_str
= ecommunity_ecom2str(
3480 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3481 vty_out(vty
, " route-target export %s\n",
3483 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3487 if (vpn
->advertise_gw_macip
)
3488 vty_out(vty
, " advertise-default-gw\n");
3490 if (vpn
->advertise_svi_macip
)
3491 vty_out(vty
, " advertise-svi-ip\n");
3493 if (vpn
->advertise_subnet
)
3494 vty_out(vty
, " advertise-subnet\n");
3496 vty_out(vty
, " exit-vni\n");
3500 #include "bgpd/bgp_evpn_vty_clippy.c"
3502 DEFPY(bgp_evpn_flood_control
,
3503 bgp_evpn_flood_control_cmd
,
3504 "[no$no] flooding <disable$disable|head-end-replication$her>",
3506 "Specify handling for BUM packets\n"
3507 "Do not flood any BUM packets\n"
3508 "Flood BUM packets using head-end replication\n")
3510 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3511 enum vxlan_flood_control flood_ctrl
;
3517 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3519 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3523 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3526 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3527 bgp_evpn_flood_control_change(bgp
);
3532 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3533 bgp_evpn_advertise_default_gw_vni_cmd
,
3534 "advertise-default-gw",
3535 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3537 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3538 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3543 evpn_set_advertise_default_gw(bgp
, vpn
);
3548 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3549 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3550 "no advertise-default-gw",
3552 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3554 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3555 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3560 evpn_unset_advertise_default_gw(bgp
, vpn
);
3566 DEFUN (bgp_evpn_advertise_default_gw
,
3567 bgp_evpn_advertise_default_gw_cmd
,
3568 "advertise-default-gw",
3569 "Advertise All default g/w mac-ip routes in EVPN\n")
3571 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3576 if (!EVPN_ENABLED(bgp
)) {
3578 "This command is only supported under the EVPN VRF\n");
3582 evpn_set_advertise_default_gw(bgp
, NULL
);
3587 DEFUN (no_bgp_evpn_advertise_default_gw
,
3588 no_bgp_evpn_advertise_default_gw_cmd
,
3589 "no advertise-default-gw",
3591 "Withdraw All default g/w mac-ip routes from EVPN\n")
3593 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3598 evpn_unset_advertise_default_gw(bgp
, NULL
);
3603 DEFUN (bgp_evpn_advertise_all_vni
,
3604 bgp_evpn_advertise_all_vni_cmd
,
3605 "advertise-all-vni",
3606 "Advertise All local VNIs\n")
3608 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3609 struct bgp
*bgp_evpn
= NULL
;
3614 bgp_evpn
= bgp_get_evpn();
3615 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3616 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3617 bgp_evpn
->name_pretty
);
3618 return CMD_WARNING_CONFIG_FAILED
;
3621 evpn_set_advertise_all_vni(bgp
);
3625 DEFUN (no_bgp_evpn_advertise_all_vni
,
3626 no_bgp_evpn_advertise_all_vni_cmd
,
3627 "no advertise-all-vni",
3629 "Advertise All local VNIs\n")
3631 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3635 evpn_unset_advertise_all_vni(bgp
);
3639 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3640 bgp_evpn_advertise_autort_rfc8365_cmd
,
3641 "autort rfc8365-compatible",
3642 "Auto-derivation of RT\n"
3643 "Auto-derivation of RT using RFC8365\n")
3645 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3649 evpn_set_advertise_autort_rfc8365(bgp
);
3653 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3654 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3655 "no autort rfc8365-compatible",
3657 "Auto-derivation of RT\n"
3658 "Auto-derivation of RT using RFC8365\n")
3660 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3664 evpn_unset_advertise_autort_rfc8365(bgp
);
3668 DEFUN (bgp_evpn_default_originate
,
3669 bgp_evpn_default_originate_cmd
,
3670 "default-originate <ipv4 | ipv6>",
3671 "originate a default route\n"
3672 "ipv4 address family\n"
3673 "ipv6 address family\n")
3677 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3681 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3682 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3686 DEFUN (no_bgp_evpn_default_originate
,
3687 no_bgp_evpn_default_originate_cmd
,
3688 "no default-originate <ipv4 | ipv6>",
3690 "withdraw a default route\n"
3691 "ipv4 address family\n"
3692 "ipv6 address family\n")
3696 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3700 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3701 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3705 DEFPY (dup_addr_detection
,
3706 dup_addr_detection_cmd
,
3707 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3708 "Duplicate address detection\n"
3709 "Max allowed moves before address detected as duplicate\n"
3710 "Num of max allowed moves (2-1000) default 5\n"
3711 "Duplicate address detection time\n"
3712 "Time in seconds (2-1800) default 180\n")
3714 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3719 if (!EVPN_ENABLED(bgp_vrf
)) {
3721 "This command is only supported under the EVPN VRF\n");
3725 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3728 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3730 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3732 bgp_zebra_dup_addr_detection(bgp_vrf
);
3737 DEFPY (dup_addr_detection_auto_recovery
,
3738 dup_addr_detection_auto_recovery_cmd
,
3739 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3740 "Duplicate address detection\n"
3741 "Duplicate address detection freeze\n"
3742 "Duplicate address detection permanent freeze\n"
3743 "Duplicate address detection freeze time (30-3600)\n")
3745 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3746 uint32_t freeze_time
= freeze_time_val
;
3751 if (!EVPN_ENABLED(bgp_vrf
)) {
3753 "This command is only supported under the EVPN VRF\n");
3757 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3758 bgp_vrf
->evpn_info
->dad_freeze
= true;
3759 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3761 bgp_zebra_dup_addr_detection(bgp_vrf
);
3766 DEFPY (no_dup_addr_detection
,
3767 no_dup_addr_detection_cmd
,
3768 "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>]",
3770 "Duplicate address detection\n"
3771 "Max allowed moves before address detected as duplicate\n"
3772 "Num of max allowed moves (2-1000) default 5\n"
3773 "Duplicate address detection time\n"
3774 "Time in seconds (2-1800) default 180\n"
3775 "Duplicate address detection freeze\n"
3776 "Duplicate address detection permanent freeze\n"
3777 "Duplicate address detection freeze time (30-3600)\n")
3779 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3780 uint32_t max_moves
= (uint32_t)max_moves_val
;
3781 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3786 if (!EVPN_ENABLED(bgp_vrf
)) {
3788 "This command is only supported under the EVPN VRF\n");
3793 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3795 /* Reset all parameters to default. */
3796 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3797 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3798 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3799 bgp_vrf
->evpn_info
->dad_freeze
= false;
3800 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3803 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3805 "%% Value does not match with config\n");
3808 bgp_vrf
->evpn_info
->dad_max_moves
=
3809 EVPN_DAD_DEFAULT_MAX_MOVES
;
3813 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3815 "%% Value does not match with config\n");
3818 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3822 if (bgp_vrf
->evpn_info
->dad_freeze_time
3825 "%% Value does not match with config\n");
3828 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3829 bgp_vrf
->evpn_info
->dad_freeze
= false;
3832 if (permanent_val
) {
3833 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3835 "%% Value does not match with config\n");
3838 bgp_vrf
->evpn_info
->dad_freeze
= false;
3842 bgp_zebra_dup_addr_detection(bgp_vrf
);
3847 DEFPY(bgp_evpn_advertise_svi_ip
,
3848 bgp_evpn_advertise_svi_ip_cmd
,
3849 "[no$no] advertise-svi-ip",
3851 "Advertise svi mac-ip routes in EVPN\n")
3853 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3859 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3861 if (!EVPN_ENABLED(bgp
)) {
3863 "This command is only supported under EVPN VRF\n");
3866 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3872 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3873 bgp_evpn_advertise_svi_ip_vni_cmd
,
3874 "[no$no] advertise-svi-ip",
3876 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3878 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3879 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3885 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3887 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3892 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3893 bgp_evpn_advertise_vni_subnet_cmd
,
3895 "Advertise the subnet corresponding to VNI\n")
3897 struct bgp
*bgp_vrf
= NULL
;
3898 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3899 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3904 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3908 evpn_set_advertise_subnet(bgp
, vpn
);
3912 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3913 no_bgp_evpn_advertise_vni_subnet_cmd
,
3914 "no advertise-subnet",
3916 "Advertise All local VNIs\n")
3918 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3919 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3924 evpn_unset_advertise_subnet(bgp
, vpn
);
3928 DEFUN (bgp_evpn_advertise_type5
,
3929 bgp_evpn_advertise_type5_cmd
,
3930 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3931 "Advertise prefix routes\n"
3934 "advertise gateway IP overlay index\n"
3935 "route-map for filtering specific routes\n"
3936 "Name of the route map\n")
3938 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3945 int rmap_changed
= 0;
3946 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3948 bool adv_flag_changed
= false;
3950 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3951 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3952 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3954 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3956 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3958 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3959 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3962 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3966 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3968 "%% Only ipv4 or ipv6 address families are supported\n");
3972 if (safi
!= SAFI_UNICAST
) {
3974 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3978 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3979 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3980 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3984 if (afi
== AFI_IP
) {
3985 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3986 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3987 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3988 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3991 * this is the case for first time ever configuration
3992 * adv ipv4 unicast is enabled for the first time.
3993 * So no need to reset any flag
3995 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3997 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3998 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3999 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4001 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4002 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4003 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4005 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4006 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
4009 * This is modify case from gateway-ip
4010 * to no overlay index
4012 adv_flag_changed
= true;
4013 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4014 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4015 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4016 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4017 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4019 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4020 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4023 * This is modify case from no overlay index
4026 adv_flag_changed
= true;
4027 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4028 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4029 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4030 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4034 * Command is issued with the same option
4035 * (no overlay index or gateway-ip) which was
4036 * already configured. So nothing to do.
4037 * However, route-map may have been modified.
4038 * check if route-map has been modified.
4039 * If not, return an error
4045 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4046 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
4047 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4048 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4051 * this is the case for first time ever configuration
4052 * adv ipv6 unicast is enabled for the first time.
4053 * So no need to reset any flag
4055 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4057 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4058 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4059 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4061 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4062 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4063 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4065 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4066 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
4069 * This is modify case from gateway-ip
4070 * to no overlay index
4072 adv_flag_changed
= true;
4073 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4074 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4075 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4076 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4077 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4079 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4080 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4083 * This is modify case from no overlay index
4086 adv_flag_changed
= true;
4087 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4088 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4089 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4090 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4094 * Command is issued with the same option
4095 * (no overlay index or gateway-ip) which was
4096 * already configured. So nothing to do.
4097 * However, route-map may have been modified.
4098 * check if route-map has been modified.
4099 * If not, return an error
4106 if ((rmap_changed
) || (adv_flag_changed
)) {
4108 /* If either of these are changed, then FRR needs to
4109 * withdraw already advertised type5 routes.
4111 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4113 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4114 XFREE(MTYPE_ROUTE_MAP_NAME
,
4115 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4116 route_map_counter_decrement(
4117 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4118 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4119 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4124 /* set the route-map for advertise command */
4125 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4126 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4127 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4128 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4129 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4130 route_map_counter_increment(
4131 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4134 /* advertise type-5 routes */
4135 if (advertise_type5_routes(bgp_vrf
, afi
))
4136 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4140 DEFUN (no_bgp_evpn_advertise_type5
,
4141 no_bgp_evpn_advertise_type5_cmd
,
4142 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
4144 "Advertise prefix routes\n"
4147 "route-map for filtering specific routes\n"
4148 "Name of the route map\n")
4150 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4159 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4160 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4162 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4164 "%% Only ipv4 or ipv6 address families are supported\n");
4168 if (safi
!= SAFI_UNICAST
) {
4170 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4174 if (afi
== AFI_IP
) {
4176 /* if we are not advertising ipv4 prefix as type-5
4179 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4180 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4181 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4182 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4183 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4184 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4185 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4186 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4187 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4191 /* if we are not advertising ipv6 prefix as type-5
4194 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4195 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4196 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4197 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4198 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4199 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4200 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4201 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4202 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4206 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4207 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4208 XFREE(MTYPE_ROUTE_MAP_NAME
,
4209 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4210 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4211 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4217 DEFPY (bgp_evpn_use_es_l3nhg
,
4218 bgp_evpn_use_es_l3nhg_cmd
,
4219 "[no$no] use-es-l3nhg",
4221 "use L3 nexthop group for host routes with ES destination\n")
4223 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4227 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4228 bgp_evpn_ead_evi_rx_disable_cmd
,
4229 "[no$no] disable-ead-evi-rx",
4231 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4233 bool ead_evi_rx
= no
? true :false;
4235 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4236 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4237 bgp_evpn_switch_ead_evi_rx();
4242 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4243 bgp_evpn_ead_evi_tx_disable_cmd
,
4244 "[no$no] disable-ead-evi-tx",
4246 "Don't advertise EAD-EVI for local ESs\n")
4248 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4252 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4253 bgp_evpn_enable_resolve_overlay_index_cmd
,
4254 "[no$no] enable-resolve-overlay-index",
4256 "Enable Recursive Resolution of type-5 route overlay index\n")
4258 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4260 if (bgp
!= bgp_get_evpn()) {
4261 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4265 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4269 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4270 bgp_evpn_advertise_pip_ip_mac_cmd
,
4271 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4273 "evpn system primary IP\n"
4276 MAC_STR MAC_STR MAC_STR
)
4278 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4279 struct bgp
*bgp_evpn
= NULL
;
4281 if (EVPN_ENABLED(bgp_vrf
)) {
4283 "This command is supported under L3VNI BGP EVPN VRF\n");
4284 return CMD_WARNING_CONFIG_FAILED
;
4286 bgp_evpn
= bgp_get_evpn();
4289 /* pip is already enabled */
4290 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4293 bgp_vrf
->evpn_info
->advertise_pip
= true;
4294 if (ip
.s_addr
!= INADDR_ANY
) {
4295 /* Already configured with same IP */
4296 if (IPV4_ADDR_SAME(&ip
,
4297 &bgp_vrf
->evpn_info
->pip_ip_static
))
4300 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4301 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4303 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4305 /* default instance router-id assignemt */
4307 bgp_vrf
->evpn_info
->pip_ip
=
4308 bgp_evpn
->router_id
;
4311 if (!is_zero_mac(&mac
->eth_addr
)) {
4312 /* Already configured with same MAC */
4313 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4314 &mac
->eth_addr
, ETH_ALEN
) == 0)
4317 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4318 &mac
->eth_addr
, ETH_ALEN
);
4319 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4320 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4323 /* Copy zebra sys mac */
4324 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4325 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4326 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4331 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4333 /* Disable PIP feature */
4334 bgp_vrf
->evpn_info
->advertise_pip
= false;
4335 /* copy anycast mac */
4336 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4337 &bgp_vrf
->rmac
, ETH_ALEN
);
4339 /* remove MAC-IP option retain PIP knob. */
4340 if ((ip
.s_addr
!= INADDR_ANY
) &&
4341 !IPV4_ADDR_SAME(&ip
,
4342 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4344 "%% BGP EVPN PIP IP does not match\n");
4345 return CMD_WARNING_CONFIG_FAILED
;
4348 if (!is_zero_mac(&mac
->eth_addr
) &&
4349 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4350 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4352 "%% BGP EVPN PIP MAC does not match\n");
4353 return CMD_WARNING_CONFIG_FAILED
;
4355 /* pip_rmac can carry vrr_rmac reset only if it matches
4356 * with static value.
4358 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4359 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4361 /* Copy zebra sys mac */
4363 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4364 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4365 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4368 /* copy anycast mac */
4369 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4370 &bgp_vrf
->rmac
, ETH_ALEN
);
4374 /* reset user configured sys MAC */
4375 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4376 /* reset user configured sys IP */
4377 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4378 /* Assign default PIP IP (bgp instance router-id) */
4380 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4382 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4385 if (is_evpn_enabled()) {
4386 struct listnode
*node
= NULL
;
4387 struct bgpevpn
*vpn
= NULL
;
4390 * At this point if bgp_evpn is NULL and evpn is enabled
4391 * something stupid has gone wrong
4395 update_advertise_vrf_routes(bgp_vrf
);
4397 /* Update (svi) type-2 routes */
4398 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4399 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4401 update_routes_for_vni(bgp_evpn
, vpn
);
4409 * Display VNI information - for all or a specific VNI
4411 DEFUN(show_bgp_l2vpn_evpn_vni
,
4412 show_bgp_l2vpn_evpn_vni_cmd
,
4413 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4422 struct bgp
*bgp_evpn
;
4426 json_object
*json
= NULL
;
4427 uint32_t num_l2vnis
= 0;
4428 uint32_t num_l3vnis
= 0;
4429 uint32_t num_vnis
= 0;
4430 struct listnode
*node
= NULL
;
4431 struct bgp
*bgp_temp
= NULL
;
4433 uj
= use_json(argc
, argv
);
4435 bgp_evpn
= bgp_get_evpn();
4439 if (!argv_find(argv
, argc
, "evpn", &idx
))
4443 json
= json_object_new_object();
4445 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4447 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4449 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4450 if (bgp_temp
->l3vni
)
4453 num_vnis
= num_l2vnis
+ num_l3vnis
;
4455 json_object_string_add(json
, "advertiseGatewayMacip",
4456 bgp_evpn
->advertise_gw_macip
4459 json_object_string_add(json
, "advertiseSviMacIp",
4460 bgp_evpn
->evpn_info
->advertise_svi_macip
4461 ? "Enabled" : "Disabled");
4462 json_object_string_add(json
, "advertiseAllVnis",
4463 is_evpn_enabled() ? "Enabled"
4465 json_object_string_add(
4467 bgp_evpn
->vxlan_flood_ctrl
==
4468 VXLAN_FLOOD_HEAD_END_REPL
4469 ? "Head-end replication"
4471 json_object_string_add(
4472 json
, "vxlanFlooding",
4473 bgp_evpn
->vxlan_flood_ctrl
==
4474 VXLAN_FLOOD_HEAD_END_REPL
4477 json_object_int_add(json
, "numVnis", num_vnis
);
4478 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4479 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4481 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4482 bgp_evpn
->advertise_gw_macip
? "Enabled"
4484 vty_out(vty
, "Advertise SVI Macip: %s\n",
4485 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4487 vty_out(vty
, "Advertise All VNI flag: %s\n",
4488 is_evpn_enabled() ? "Enabled" : "Disabled");
4489 vty_out(vty
, "BUM flooding: %s\n",
4490 bgp_evpn
->vxlan_flood_ctrl
==
4491 VXLAN_FLOOD_HEAD_END_REPL
4492 ? "Head-end replication"
4494 vty_out(vty
, "VXLAN flooding: %s\n",
4495 bgp_evpn
->vxlan_flood_ctrl
==
4496 VXLAN_FLOOD_HEAD_END_REPL
4499 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4500 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4502 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4506 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4509 /* Display specific VNI */
4510 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4511 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4515 vty_json(vty
, json
);
4520 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4521 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4522 "show bgp l2vpn evpn vni remote-ip-hash",
4530 struct bgp
*bgp_evpn
;
4533 bgp_evpn
= bgp_get_evpn();
4537 if (!argv_find(argv
, argc
, "evpn", &idx
))
4540 hash_iterate(bgp_evpn
->vnihash
,
4541 (void (*)(struct hash_bucket
*,
4542 void *))bgp_evpn_show_remote_ip_hash
,
4548 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4549 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4550 "show bgp l2vpn evpn vni-svi-hash",
4555 "Show vni-svi-hash\n")
4557 struct bgp
*bgp_evpn
;
4560 bgp_evpn
= bgp_get_evpn();
4564 if (!argv_find(argv
, argc
, "evpn", &idx
))
4567 hash_iterate(bgp_evpn
->vni_svi_hash
,
4568 (void (*)(struct hash_bucket
*,
4569 void *))bgp_evpn_show_vni_svi_hash
,
4575 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4576 show_bgp_l2vpn_evpn_es_evi_cmd
,
4577 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4583 "VxLAN Network Identifier\n"
4586 "Detailed information\n")
4589 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4591 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4596 DEFPY(show_bgp_l2vpn_evpn_es
,
4597 show_bgp_l2vpn_evpn_es_cmd
,
4598 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4603 "Ethernet Segment\n"
4605 "Detailed information\n"
4611 if (!str_to_esi(esi_str
, &esi
)) {
4612 vty_out(vty
, "%% Malformed ESI\n");
4615 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4618 bgp_evpn_es_show(vty
, uj
, !!detail
);
4624 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4625 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4626 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4627 "Ethernet Segment\n"
4633 if (!str_to_esi(esi_str
, &esi
)) {
4634 vty_out(vty
, "%% Malformed ESI\n");
4637 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4640 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4646 DEFPY(show_bgp_l2vpn_evpn_nh
,
4647 show_bgp_l2vpn_evpn_nh_cmd
,
4648 "show bgp l2vpn evpn next-hops [json$uj]",
4656 bgp_evpn_nh_show(vty
, uj
);
4662 * Display EVPN neighbor summary.
4664 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4665 "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]",
4668 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4669 "Summary of BGP neighbor status\n"
4670 "Show only sessions in Established state\n"
4671 "Show only sessions not in Established state\n"
4672 "Show only the specified neighbor session\n"
4673 "Neighbor to display information about\n"
4674 "Neighbor to display information about\n"
4675 "Neighbor on BGP configured interface\n"
4676 "Show only the specified remote AS sessions\n"
4678 "Internal (iBGP) AS sessions\n"
4679 "External (eBGP) AS sessions\n"
4680 "Shorten the information on BGP instances\n"
4681 "Increase table width for longer output\n" JSON_STR
)
4686 char *neighbor
= NULL
;
4687 as_t as
= 0; /* 0 means AS filter not set */
4688 int as_type
= AS_UNSPECIFIED
;
4689 uint16_t show_flags
= 0;
4691 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4692 vrf
= argv
[++idx_vrf
]->arg
;
4694 if (argv_find(argv
, argc
, "failed", &idx
))
4695 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4697 if (argv_find(argv
, argc
, "established", &idx
))
4698 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4701 if (argv_find(argv
, argc
, "neighbor", &idx
))
4702 neighbor
= argv
[idx
+ 1]->arg
;
4704 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4705 if (argv
[idx
+ 1]->arg
[0] == 'i')
4706 as_type
= AS_INTERNAL
;
4707 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4708 as_type
= AS_EXTERNAL
;
4710 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4713 if (argv_find(argv
, argc
, "terse", &idx
))
4714 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4716 if (argv_find(argv
, argc
, "wide", &idx
))
4717 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4719 if (use_json(argc
, argv
))
4720 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4722 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4723 as_type
, as
, show_flags
);
4726 static int bgp_evpn_cli_parse_type_cmp(int *type
, const char *type_str
)
4728 if ((strncmp(type_str
, "ma", 2) == 0) || (strmatch(type_str
, "2")))
4729 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4730 else if ((strncmp(type_str
, "mu", 2) == 0) || (strmatch(type_str
, "3")))
4731 *type
= BGP_EVPN_IMET_ROUTE
;
4732 else if ((strncmp(type_str
, "es", 2) == 0) || (strmatch(type_str
, "4")))
4733 *type
= BGP_EVPN_ES_ROUTE
;
4734 else if ((strncmp(type_str
, "ea", 2) == 0) || (strmatch(type_str
, "1")))
4735 *type
= BGP_EVPN_AD_ROUTE
;
4736 else if ((strncmp(type_str
, "p", 1) == 0) || (strmatch(type_str
, "5")))
4737 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4744 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4748 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4749 /* Specific type is requested */
4750 if (bgp_evpn_cli_parse_type_cmp(type
,
4751 argv
[type_idx
+ 1]->arg
) != 0)
4759 * Display global EVPN routing table.
4761 DEFUN(show_bgp_l2vpn_evpn_route
,
4762 show_bgp_l2vpn_evpn_route_cmd
,
4763 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4769 "Display Detailed Information\n"
4771 EVPN_TYPE_ALL_LIST_HELP_STR
4778 json_object
*json
= NULL
;
4780 uj
= use_json(argc
, argv
);
4782 bgp
= bgp_get_evpn();
4787 json
= json_object_new_object();
4789 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4792 if (argv_find(argv
, argc
, "detail", &detail
))
4795 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4798 * This is an extremely expensive operation at scale
4799 * and as such we need to save as much time as is
4803 vty_json_no_pretty(vty
, json
);
4809 * Display global EVPN routing table for specific RD.
4811 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4812 show_bgp_l2vpn_evpn_route_rd_cmd
,
4813 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4819 EVPN_RT_DIST_HELP_STR
4820 EVPN_ASN_IP_HELP_STR
4821 "All VPN Route Distinguishers\n"
4823 EVPN_TYPE_ALL_LIST_HELP_STR
4828 struct prefix_rd prd
;
4831 json_object
*json
= NULL
;
4832 int idx_ext_community
= 0;
4835 bgp
= bgp_get_evpn();
4839 /* check if we need json output */
4840 uj
= use_json(argc
, argv
);
4842 json
= json_object_new_object();
4844 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4846 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4847 &idx_ext_community
)) {
4848 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4851 "%% Malformed Route Distinguisher\n");
4857 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4861 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4863 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4866 vty_json(vty
, json
);
4872 * Display global EVPN routing table for specific RD and MACIP.
4874 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4875 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4876 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4882 EVPN_RT_DIST_HELP_STR
4883 EVPN_ASN_IP_HELP_STR
4884 "All VPN Route Distinguishers\n"
4886 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4888 "IP address (IPv4 or IPv6)\n"
4893 struct prefix_rd prd
;
4896 int idx_ext_community
= 0;
4900 json_object
*json
= NULL
;
4903 memset(&mac
, 0, sizeof(struct ethaddr
));
4904 memset(&ip
, 0, sizeof(struct ipaddr
));
4906 bgp
= bgp_get_evpn();
4910 /* check if we need json output */
4911 uj
= use_json(argc
, argv
);
4913 json
= json_object_new_object();
4916 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4917 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4918 &idx_ext_community
)) {
4919 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4922 "%% Malformed Route Distinguisher\n");
4929 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4930 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4931 vty_out(vty
, "%% Malformed MAC address\n");
4936 /* get the ip if specified */
4937 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4938 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4939 vty_out(vty
, "%% Malformed IP address\n");
4945 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4947 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4950 vty_json(vty
, json
);
4955 /* Display per ESI routing table */
4956 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4957 show_bgp_l2vpn_evpn_route_esi_cmd
,
4958 "show bgp l2vpn evpn route esi ESI [json]",
4964 "Ethernet Segment Identifier\n"
4970 struct bgp
*bgp
= NULL
;
4971 json_object
*json
= NULL
;
4973 memset(&esi
, 0, sizeof(esi
));
4974 bgp
= bgp_get_evpn();
4978 uj
= use_json(argc
, argv
);
4980 json
= json_object_new_object();
4982 /* get the ESI - ESI-ID is at argv[6] */
4983 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4984 vty_out(vty
, "%% Malformed ESI\n");
4988 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4991 vty_json(vty
, json
);
4998 * Display per-VNI EVPN routing table.
5000 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
5001 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
5007 "VXLAN Network Identifier\n"
5010 EVPN_TYPE_1_HELP_STR
5011 EVPN_TYPE_1_HELP_STR
5012 EVPN_TYPE_2_HELP_STR
5013 EVPN_TYPE_2_HELP_STR
5014 EVPN_TYPE_3_HELP_STR
5015 EVPN_TYPE_3_HELP_STR
5017 "Remote VTEP IP address\n"
5022 struct in_addr vtep_ip
;
5027 json_object
*json
= NULL
;
5029 bgp
= bgp_get_evpn();
5033 /* check if we need json output */
5034 uj
= use_json(argc
, argv
);
5036 json
= json_object_new_object();
5038 if (!argv_find(argv
, argc
, "evpn", &idx
))
5043 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5045 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
5048 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
5049 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
5050 vty_out(vty
, "%% Malformed VTEP IP address\n");
5055 evpn_show_routes_vni(vty
, bgp
, vni
, type
, false, vtep_ip
, json
);
5058 vty_json(vty
, json
);
5064 * Display per-VNI EVPN routing table for specific MACIP.
5066 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
5067 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
5068 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
5074 "VXLAN Network Identifier\n"
5077 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5079 "IP address (IPv4 or IPv6)\n"
5088 json_object
*json
= NULL
;
5090 bgp
= bgp_get_evpn();
5094 /* check if we need json output */
5095 uj
= use_json(argc
, argv
);
5097 json
= json_object_new_object();
5099 if (!argv_find(argv
, argc
, "evpn", &idx
))
5103 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5106 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5107 vty_out(vty
, "%% Malformed MAC address\n");
5112 memset(&ip
, 0, sizeof(ip
));
5113 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5115 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5116 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5117 vty_out(vty
, "%% Malformed IP address\n");
5122 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5125 vty_json(vty
, json
);
5131 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5133 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5134 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5135 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5141 "VXLAN Network Identifier\n"
5143 EVPN_TYPE_3_HELP_STR
5144 "Originating Router IP address\n"
5150 struct in_addr orig_ip
;
5153 json_object
*json
= NULL
;
5155 bgp
= bgp_get_evpn();
5159 /* check if we need json output */
5160 uj
= use_json(argc
, argv
);
5162 json
= json_object_new_object();
5164 if (!argv_find(argv
, argc
, "evpn", &idx
))
5168 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5171 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5173 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5177 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5180 vty_json(vty
, json
);
5186 * Display per-VNI EVPN routing table - for all VNIs.
5188 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5189 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5190 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5196 "VXLAN Network Identifier\n"
5198 "Print Detailed Output\n"
5200 "Remote VTEP IP address\n"
5204 struct in_addr vtep_ip
;
5207 json_object
*json
= NULL
;
5208 /* Detail Adjust. Adjust indexes according to detail option */
5211 bgp
= bgp_get_evpn();
5215 /* check if we need json output */
5216 uj
= use_json(argc
, argv
);
5218 json
= json_object_new_object();
5220 if (!argv_find(argv
, argc
, "evpn", &idx
))
5223 if (argv_find(argv
, argc
, "detail", &da
))
5226 /* vtep-ip position depends on detail option */
5228 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5230 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5231 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5232 vty_out(vty
, "%% Malformed VTEP IP address\n");
5237 evpn_show_routes_vni_all(vty
, bgp
, 0, false, vtep_ip
, json
, da
);
5240 vty_json(vty
, json
);
5241 json_object_free(json
);
5248 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5250 DEFPY(show_bgp_vni_all
,
5251 show_bgp_vni_all_cmd
,
5252 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5263 json_object
*json
= NULL
;
5265 bgp
= bgp_get_evpn();
5269 /* check if we need json output */
5271 json
= json_object_new_object();
5273 evpn_show_routes_vni_all_type_all(vty
, bgp
, addr
, json
, !!detail
);
5276 vty_json(vty
, json
);
5282 * Display per-VNI EVPN EAD routing table - for all VNIs.
5284 DEFPY(show_bgp_vni_all_ead
,
5285 show_bgp_vni_all_ead_cmd
,
5286 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5292 EVPN_TYPE_1_HELP_STR
5293 EVPN_TYPE_1_HELP_STR
5300 json_object
*json
= NULL
;
5302 bgp
= bgp_get_evpn();
5306 /* check if we need json output */
5308 json
= json_object_new_object();
5310 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_AD_ROUTE
, false, addr
, json
,
5314 vty_json(vty
, json
);
5320 * Display per-VNI EVPN MAC routing table - for all VNIs.
5322 DEFPY(show_bgp_vni_all_macip_mac
,
5323 show_bgp_vni_all_macip_mac_cmd
,
5324 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5330 EVPN_TYPE_2_HELP_STR
5331 EVPN_TYPE_2_HELP_STR
5339 json_object
*json
= NULL
;
5341 bgp
= bgp_get_evpn();
5345 /* check if we need json output */
5347 json
= json_object_new_object();
5349 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5353 vty_json(vty
, json
);
5359 * Display per-VNI EVPN IP routing table - for all VNIs.
5361 DEFPY(show_bgp_vni_all_macip_ip
,
5362 show_bgp_vni_all_macip_ip_cmd
,
5363 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5369 EVPN_TYPE_2_HELP_STR
5370 EVPN_TYPE_2_HELP_STR
5378 json_object
*json
= NULL
;
5380 bgp
= bgp_get_evpn();
5384 /* check if we need json output */
5386 json
= json_object_new_object();
5388 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5392 vty_json(vty
, json
);
5398 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5400 DEFPY(show_bgp_vni_all_imet
,
5401 show_bgp_vni_all_imet_cmd
,
5402 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5408 EVPN_TYPE_3_HELP_STR
5409 EVPN_TYPE_3_HELP_STR
5416 json_object
*json
= NULL
;
5418 bgp
= bgp_get_evpn();
5422 /* check if we need json output */
5424 json
= json_object_new_object();
5426 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5430 vty_json(vty
, json
);
5436 * Display per-VNI EVPN ALL routing tables - for select VNI
5440 "show bgp vni "CMD_VNI_RANGE
"$vni [vtep A.B.C.D$addr] [json$uj]",
5450 json_object
*json
= NULL
;
5451 json_object
*json_mac
= NULL
;
5453 bgp
= bgp_get_evpn();
5457 /* check if we need json output */
5459 json
= json_object_new_object();
5460 json_mac
= json_object_new_object();
5463 evpn_show_routes_vni(vty
, bgp
, vni
, 0, false, addr
, json
);
5466 vty_out(vty
, "\n\nMAC Table:\n\n");
5468 evpn_show_routes_vni(vty
, bgp
, vni
, 0, true, addr
, json_mac
);
5471 json_object_object_add(json
, "macTable", json_mac
);
5472 vty_json(vty
, json
);
5479 * Display per-VNI EVPN EAD routing table - for select VNI
5481 DEFPY(show_bgp_vni_ead
,
5482 show_bgp_vni_ead_cmd
,
5483 "show bgp vni "CMD_VNI_RANGE
"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5489 EVPN_TYPE_1_HELP_STR
5490 EVPN_TYPE_1_HELP_STR
5496 json_object
*json
= NULL
;
5498 bgp
= bgp_get_evpn();
5502 /* check if we need json output */
5504 json
= json_object_new_object();
5506 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_AD_ROUTE
, false, addr
,
5510 vty_json(vty
, json
);
5516 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5518 DEFPY(show_bgp_vni_macip_mac
,
5519 show_bgp_vni_macip_mac_cmd
,
5520 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5526 EVPN_TYPE_2_HELP_STR
5527 EVPN_TYPE_2_HELP_STR
5534 json_object
*json
= NULL
;
5536 bgp
= bgp_get_evpn();
5540 /* check if we need json output */
5542 json
= json_object_new_object();
5544 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5548 vty_json(vty
, json
);
5554 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5556 DEFPY(show_bgp_vni_macip_ip
,
5557 show_bgp_vni_macip_ip_cmd
,
5558 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5564 EVPN_TYPE_2_HELP_STR
5565 EVPN_TYPE_2_HELP_STR
5572 json_object
*json
= NULL
;
5574 bgp
= bgp_get_evpn();
5578 /* check if we need json output */
5580 json
= json_object_new_object();
5582 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5586 vty_json(vty
, json
);
5592 * Display per-VNI EVPN Multicast routing table - for select VNI
5594 DEFPY(show_bgp_vni_imet
,
5595 show_bgp_vni_imet_cmd
,
5596 "show bgp vni "CMD_VNI_RANGE
"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5602 EVPN_TYPE_3_HELP_STR
5603 EVPN_TYPE_3_HELP_STR
5609 json_object
*json
= NULL
;
5611 bgp
= bgp_get_evpn();
5615 /* check if we need json output */
5617 json
= json_object_new_object();
5619 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5623 vty_json(vty
, json
);
5629 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5631 DEFPY(show_bgp_vni_macip_mac_addr
,
5632 show_bgp_vni_macip_mac_addr_cmd
,
5633 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5639 EVPN_TYPE_2_HELP_STR
5640 EVPN_TYPE_2_HELP_STR
5646 json_object
*json
= NULL
;
5648 bgp
= bgp_get_evpn();
5652 /* check if we need json output */
5654 json
= json_object_new_object();
5656 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
->eth_addr
, NULL
, json
);
5659 vty_json(vty
, json
);
5665 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5667 DEFPY(show_bgp_vni_macip_ip_addr
, show_bgp_vni_macip_ip_addr_cmd
,
5668 "show bgp vni " CMD_VNI_RANGE
5669 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5670 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5671 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5672 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR
)
5675 json_object
*json
= NULL
;
5676 struct ipaddr ip_addr
= {.ipa_type
= IPADDR_NONE
};
5678 bgp
= bgp_get_evpn();
5682 /* check if we need json output */
5684 json
= json_object_new_object();
5686 if (sockunion_family(ip
) == AF_INET
) {
5687 ip_addr
.ipa_type
= IPADDR_V4
;
5688 ip_addr
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
5690 ip_addr
.ipa_type
= IPADDR_V6
;
5691 memcpy(&ip_addr
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
5692 sizeof(struct in6_addr
));
5694 evpn_show_route_vni_macip(vty
, bgp
, vni
, NULL
, &ip_addr
, json
);
5697 vty_json(vty
, json
);
5703 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5704 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5705 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5706 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5707 "EVPN route information\n"
5708 "MAC IP routes in the EVI tables linked to the ES\n"
5710 "Detailed information\n" JSON_STR
)
5714 json_object
*json
= NULL
;
5717 if (!str_to_esi(esi_str
, &esi
)) {
5718 vty_out(vty
, "%% Malformed ESI\n");
5727 json
= json_object_new_object();
5728 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5730 vty_json(vty
, json
);
5736 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5737 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5738 "show bgp l2vpn evpn route mac-ip-global-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 global table 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_global_es(vty
, esi_p
, json
, !!detail
);
5763 vty_json(vty
, json
);
5769 * Display EVPN import route-target hash table
5771 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5772 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5773 "show bgp l2vpn evpn vrf-import-rt [json]",
5778 "Show vrf import route target\n"
5782 struct bgp
*bgp_evpn
= NULL
;
5783 json_object
*json
= NULL
;
5785 bgp_evpn
= bgp_get_evpn();
5789 uj
= use_json(argc
, argv
);
5791 json
= json_object_new_object();
5793 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5796 vty_json(vty
, json
);
5802 * Display EVPN import route-target hash table
5804 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5805 show_bgp_l2vpn_evpn_import_rt_cmd
,
5806 "show bgp l2vpn evpn import-rt [json]",
5811 "Show import route target\n"
5816 json_object
*json
= NULL
;
5818 bgp
= bgp_get_evpn();
5822 uj
= use_json(argc
, argv
);
5824 json
= json_object_new_object();
5826 evpn_show_import_rts(vty
, bgp
, json
);
5829 vty_json(vty
, json
);
5834 DEFPY_HIDDEN(test_es_add
,
5836 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5839 "Ethernet-segment\n"
5840 "Ethernet-Segment Identifier\n"
5848 struct in_addr vtep_ip
;
5851 bgp
= bgp_get_evpn();
5853 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5857 if (!str_to_esi(esi_str
, &esi
)) {
5858 vty_out(vty
, "%% Malformed ESI\n");
5863 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5865 vty_out(vty
, "%% Failed to delete ES\n");
5869 if (state_str
&& !strcmp(state_str
, "up"))
5873 vtep_ip
= bgp
->router_id
;
5875 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5876 EVPN_MH_DF_PREF_MIN
, false);
5878 vty_out(vty
, "%% Failed to add ES\n");
5885 DEFPY_HIDDEN(test_es_vni_add
,
5886 test_es_vni_add_cmd
,
5887 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5890 "Ethernet-segment\n"
5891 "Ethernet-Segment Identifier\n"
5900 bgp
= bgp_get_evpn();
5902 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5906 if (!str_to_esi(esi_str
, &esi
)) {
5907 vty_out(vty
, "%% Malformed ESI\n");
5912 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5914 vty_out(vty
, "%% Failed to deref ES VNI\n");
5918 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5920 vty_out(vty
, "%% Failed to ref ES VNI\n");
5927 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5928 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5932 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5933 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5934 "Summary of BGP neighbor status\n" JSON_STR
)
5936 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5937 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5938 SHOW_STR BGP_STR EVPN_HELP_STR
5940 "Display Detailed Information\n"
5942 EVPN_TYPE_2_HELP_STR
5943 EVPN_TYPE_2_HELP_STR
5944 EVPN_TYPE_3_HELP_STR
5945 EVPN_TYPE_3_HELP_STR
)
5948 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5949 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5950 SHOW_STR BGP_STR EVPN_HELP_STR
5952 EVPN_RT_DIST_HELP_STR
5953 EVPN_ASN_IP_HELP_STR
5955 EVPN_TYPE_2_HELP_STR
5956 EVPN_TYPE_2_HELP_STR
5957 EVPN_TYPE_3_HELP_STR
5958 EVPN_TYPE_3_HELP_STR
)
5961 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5962 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5963 SHOW_STR BGP_STR EVPN_HELP_STR
5965 EVPN_RT_DIST_HELP_STR
5966 EVPN_ASN_IP_HELP_STR
5968 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5970 "IP address (IPv4 or IPv6)\n")
5973 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5974 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5975 SHOW_STR BGP_STR EVPN_HELP_STR
5977 "VXLAN Network Identifier\n"
5980 EVPN_TYPE_2_HELP_STR
5981 EVPN_TYPE_2_HELP_STR
5982 EVPN_TYPE_3_HELP_STR
5983 EVPN_TYPE_3_HELP_STR
5985 "Remote VTEP IP address\n")
5987 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5988 show_bgp_evpn_route_vni_macip_cmd
,
5989 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5990 SHOW_STR BGP_STR EVPN_HELP_STR
5992 "VXLAN Network Identifier\n"
5995 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5997 "IP address (IPv4 or IPv6)\n")
5999 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
6000 show_bgp_evpn_route_vni_multicast_cmd
,
6001 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
6002 SHOW_STR BGP_STR EVPN_HELP_STR
6004 "VXLAN Network Identifier\n"
6006 EVPN_TYPE_3_HELP_STR
6007 "Originating Router IP address\n")
6009 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
6010 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6011 SHOW_STR BGP_STR EVPN_HELP_STR
6013 "VXLAN Network Identifier\n"
6015 "Print Detailed Output\n"
6017 "Remote VTEP IP address\n")
6019 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
6020 "show bgp evpn import-rt",
6021 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
6023 DEFUN_NOSH (bgp_evpn_vni
,
6025 "vni " CMD_VNI_RANGE
,
6026 "VXLAN Network Identifier\n"
6030 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6031 struct bgpevpn
*vpn
;
6036 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
6038 /* Create VNI, or mark as configured. */
6039 vpn
= evpn_create_update_vni(bgp
, vni
);
6041 vty_out(vty
, "%% Failed to create VNI \n");
6045 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
6049 DEFUN (no_bgp_evpn_vni
,
6050 no_bgp_evpn_vni_cmd
,
6051 "no vni " CMD_VNI_RANGE
,
6053 "VXLAN Network Identifier\n"
6057 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6058 struct bgpevpn
*vpn
;
6063 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
6065 /* Check if we should disallow. */
6066 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
6068 vty_out(vty
, "%% Specified VNI does not exist\n");
6071 if (!is_vni_configured(vpn
)) {
6072 vty_out(vty
, "%% Specified VNI is not configured\n");
6076 evpn_delete_vni(bgp
, vpn
);
6080 DEFUN_NOSH (exit_vni
,
6083 "Exit from VNI mode\n")
6085 if (vty
->node
== BGP_EVPN_VNI_NODE
)
6086 vty
->node
= BGP_EVPN_NODE
;
6090 DEFUN (bgp_evpn_vrf_rd
,
6091 bgp_evpn_vrf_rd_cmd
,
6092 "rd ASN:NN_OR_IP-ADDRESS:NN",
6093 EVPN_RT_DIST_HELP_STR
6094 EVPN_ASN_IP_HELP_STR
)
6097 struct prefix_rd prd
;
6098 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6103 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6105 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6109 /* If same as existing value, there is nothing more to do. */
6110 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
6113 /* Configure or update the RD. */
6114 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
6118 DEFUN (no_bgp_evpn_vrf_rd
,
6119 no_bgp_evpn_vrf_rd_cmd
,
6120 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6122 EVPN_RT_DIST_HELP_STR
6123 EVPN_ASN_IP_HELP_STR
)
6126 struct prefix_rd prd
;
6127 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6132 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6134 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6138 /* Check if we should disallow. */
6139 if (!is_vrf_rd_configured(bgp_vrf
)) {
6140 vty_out(vty
, "%% RD is not configured for this VRF\n");
6144 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
6146 "%% RD specified does not match configuration for this VRF\n");
6150 evpn_unconfigure_vrf_rd(bgp_vrf
);
6154 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
6155 no_bgp_evpn_vrf_rd_without_val_cmd
,
6158 EVPN_RT_DIST_HELP_STR
)
6160 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6165 /* Check if we should disallow. */
6166 if (!is_vrf_rd_configured(bgp_vrf
)) {
6167 vty_out(vty
, "%% RD is not configured for this VRF\n");
6171 evpn_unconfigure_vrf_rd(bgp_vrf
);
6175 DEFUN (bgp_evpn_vni_rd
,
6176 bgp_evpn_vni_rd_cmd
,
6177 "rd ASN:NN_OR_IP-ADDRESS:NN",
6178 EVPN_RT_DIST_HELP_STR
6179 EVPN_ASN_IP_HELP_STR
)
6181 struct prefix_rd prd
;
6182 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6183 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6189 if (!EVPN_ENABLED(bgp
)) {
6191 "This command is only supported under EVPN VRF\n");
6195 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6197 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6201 /* If same as existing value, there is nothing more to do. */
6202 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
6205 /* Configure or update the RD. */
6206 evpn_configure_rd(bgp
, vpn
, &prd
);
6210 DEFUN (no_bgp_evpn_vni_rd
,
6211 no_bgp_evpn_vni_rd_cmd
,
6212 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6214 EVPN_RT_DIST_HELP_STR
6215 EVPN_ASN_IP_HELP_STR
)
6217 struct prefix_rd prd
;
6218 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6219 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6225 if (!EVPN_ENABLED(bgp
)) {
6227 "This command is only supported under EVPN VRF\n");
6231 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6233 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6237 /* Check if we should disallow. */
6238 if (!is_rd_configured(vpn
)) {
6239 vty_out(vty
, "%% RD is not configured for this VNI\n");
6243 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
6245 "%% RD specified does not match configuration for this VNI\n");
6249 evpn_unconfigure_rd(bgp
, vpn
);
6253 DEFUN (no_bgp_evpn_vni_rd_without_val
,
6254 no_bgp_evpn_vni_rd_without_val_cmd
,
6257 EVPN_RT_DIST_HELP_STR
)
6259 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6260 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6265 if (!EVPN_ENABLED(bgp
)) {
6267 "This command is only supported under EVPN VRF\n");
6271 /* Check if we should disallow. */
6272 if (!is_rd_configured(vpn
)) {
6273 vty_out(vty
, "%% RD is not configured for this VNI\n");
6277 evpn_unconfigure_rd(bgp
, vpn
);
6282 * Loop over all extended-communities in the route-target list rtl and
6283 * return 1 if we find ecomtarget
6285 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
6286 struct ecommunity
*ecomtarget
)
6288 struct listnode
*node
;
6289 struct ecommunity
*ecom
;
6291 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
6292 if (ecommunity_match(ecom
, ecomtarget
))
6300 * L3 RT version of above.
6302 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
6303 struct ecommunity
*ecomtarget
)
6305 struct listnode
*node
;
6306 struct vrf_route_target
*l3rt
;
6308 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
6309 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
6316 /* display L3VNI related info for a VRF instance */
6317 DEFUN (show_bgp_vrf_l3vni_info
,
6318 show_bgp_vrf_l3vni_info_cmd
,
6319 "show bgp vrf VRFNAME vni [json]",
6327 char buf
[ETHER_ADDR_STRLEN
];
6329 const char *name
= NULL
;
6330 struct bgp
*bgp
= NULL
;
6331 struct listnode
*node
= NULL
;
6332 struct bgpevpn
*vpn
= NULL
;
6333 struct vrf_route_target
*l3rt
;
6334 json_object
*json
= NULL
;
6335 json_object
*json_vnis
= NULL
;
6336 json_object
*json_export_rts
= NULL
;
6337 json_object
*json_import_rts
= NULL
;
6338 bool uj
= use_json(argc
, argv
);
6341 json
= json_object_new_object();
6342 json_vnis
= json_object_new_array();
6343 json_export_rts
= json_object_new_array();
6344 json_import_rts
= json_object_new_array();
6347 name
= argv
[idx_vrf
]->arg
;
6348 bgp
= bgp_lookup_by_name(name
);
6349 if (strmatch(name
, VRF_DEFAULT_NAME
))
6350 bgp
= bgp_get_default();
6354 vty_out(vty
, "BGP instance for VRF %s not found\n",
6357 json_object_string_add(json
, "warning",
6358 "BGP instance not found");
6359 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
6360 json_object_free(json
);
6366 vty_out(vty
, "BGP VRF: %s\n", name
);
6367 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
6368 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
6369 vty_out(vty
, " Rmac: %s\n",
6370 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6371 vty_out(vty
, " VNI Filter: %s\n",
6372 CHECK_FLAG(bgp
->vrf_flags
,
6373 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6374 ? "prefix-routes-only"
6376 vty_out(vty
, " L2-VNI List:\n");
6378 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6379 vty_out(vty
, "%u ", vpn
->vni
);
6381 vty_out(vty
, " Export-RTs:\n");
6383 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6384 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6386 vty_out(vty
, " Import-RTs:\n");
6388 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6389 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6391 vty_out(vty
, " RD: %pRD\n", &bgp
->vrf_prd
);
6393 json_object_string_add(json
, "vrf", name
);
6394 json_object_string_addf(json
, "local-ip", "%pI4",
6395 &bgp
->originator_ip
);
6396 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
6397 json_object_string_add(
6399 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6400 json_object_string_add(
6402 CHECK_FLAG(bgp
->vrf_flags
,
6403 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6404 ? "prefix-routes-only"
6406 /* list of l2vnis */
6407 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6408 json_object_array_add(json_vnis
,
6409 json_object_new_int(vpn
->vni
));
6410 json_object_object_add(json
, "l2vnis", json_vnis
);
6413 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6414 json_object_array_add(
6416 json_object_new_string(
6417 ecommunity_str(l3rt
->ecom
)));
6418 json_object_object_add(json
, "export-rts", json_export_rts
);
6421 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6422 json_object_array_add(
6424 json_object_new_string(
6425 ecommunity_str(l3rt
->ecom
)));
6426 json_object_object_add(json
, "import-rts", json_import_rts
);
6427 json_object_string_addf(json
, "rd", "%pRD", &bgp
->vrf_prd
);
6431 vty_json(vty
, json
);
6435 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
6438 /* Do nothing if we already have this route-target */
6440 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6442 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
6447 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6449 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
6457 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
6459 /* Verify we already have this route-target */
6461 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6465 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
6467 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6471 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
6477 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
6478 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
6481 int ret
= CMD_SUCCESS
;
6482 bool is_wildcard
= false;
6483 struct ecommunity
*ecom
= NULL
;
6485 for (int i
= rt_idx
; i
< argc
; i
++) {
6486 is_wildcard
= false;
6489 * Special handling for wildcard '*' here.
6491 * Let's just convert it to 0 here so we dont have to modify
6492 * the ecommunity parser.
6494 if ((argv
[i
]->arg
)[0] == '*') {
6495 (argv
[i
]->arg
)[0] = '0';
6499 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
6502 /* Put it back as was */
6504 (argv
[i
]->arg
)[0] = '*';
6507 vty_out(vty
, "%% Malformed Route Target list\n");
6512 ecommunity_str(ecom
);
6515 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
6517 "%% RT specified already configured for this VRF: %s\n",
6519 ecommunity_free(&ecom
);
6524 if (del_rt(bgp
, ecom
, is_import
) != 0) {
6526 "%% RT specified does not match configuration for this VRF: %s\n",
6531 ecommunity_free(&ecom
);
6538 /* import/export rt for l3vni-vrf */
6539 DEFUN (bgp_evpn_vrf_rt
,
6540 bgp_evpn_vrf_rt_cmd
,
6541 "route-target <both|import|export> RTLIST...",
6543 "import and export\n"
6546 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6548 int ret
= CMD_SUCCESS
;
6549 int tmp_ret
= CMD_SUCCESS
;
6551 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6554 return CMD_WARNING_CONFIG_FAILED
;
6556 if (!strcmp(argv
[1]->arg
, "import"))
6557 rt_type
= RT_TYPE_IMPORT
;
6558 else if (!strcmp(argv
[1]->arg
, "export"))
6559 rt_type
= RT_TYPE_EXPORT
;
6560 else if (!strcmp(argv
[1]->arg
, "both"))
6561 rt_type
= RT_TYPE_BOTH
;
6563 vty_out(vty
, "%% Invalid Route Target type\n");
6564 return CMD_WARNING_CONFIG_FAILED
;
6567 if (strmatch(argv
[2]->arg
, "auto")) {
6568 vty_out(vty
, "%% `auto` cannot be configured via list\n");
6569 return CMD_WARNING_CONFIG_FAILED
;
6572 if (rt_type
!= RT_TYPE_IMPORT
) {
6573 for (int i
= 2; i
< argc
; i
++) {
6574 if ((argv
[i
]->arg
)[0] == '*') {
6576 "%% Wildcard '*' only applicable for import\n");
6577 return CMD_WARNING_CONFIG_FAILED
;
6582 /* Add/update the import route-target */
6583 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6584 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
6586 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6589 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6590 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
6592 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6598 DEFPY (bgp_evpn_vrf_rt_auto
,
6599 bgp_evpn_vrf_rt_auto_cmd
,
6600 "route-target <both|import|export>$type auto",
6602 "import and export\n"
6605 "Automatically derive route target\n")
6607 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6611 return CMD_WARNING_CONFIG_FAILED
;
6613 if (strmatch(type
, "import"))
6614 rt_type
= RT_TYPE_IMPORT
;
6615 else if (strmatch(type
, "export"))
6616 rt_type
= RT_TYPE_EXPORT
;
6617 else if (strmatch(type
, "both"))
6618 rt_type
= RT_TYPE_BOTH
;
6620 vty_out(vty
, "%% Invalid Route Target type\n");
6621 return CMD_WARNING_CONFIG_FAILED
;
6624 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6625 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6627 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6628 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6633 DEFUN (no_bgp_evpn_vrf_rt
,
6634 no_bgp_evpn_vrf_rt_cmd
,
6635 "no route-target <both|import|export> RTLIST...",
6638 "import and export\n"
6641 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6643 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6644 int ret
= CMD_SUCCESS
;
6645 int tmp_ret
= CMD_SUCCESS
;
6649 return CMD_WARNING_CONFIG_FAILED
;
6651 if (!strcmp(argv
[2]->arg
, "import"))
6652 rt_type
= RT_TYPE_IMPORT
;
6653 else if (!strcmp(argv
[2]->arg
, "export"))
6654 rt_type
= RT_TYPE_EXPORT
;
6655 else if (!strcmp(argv
[2]->arg
, "both"))
6656 rt_type
= RT_TYPE_BOTH
;
6658 vty_out(vty
, "%% Invalid Route Target type\n");
6659 return CMD_WARNING_CONFIG_FAILED
;
6662 if (!strcmp(argv
[3]->arg
, "auto")) {
6663 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6664 return CMD_WARNING_CONFIG_FAILED
;
6667 if (rt_type
== RT_TYPE_IMPORT
) {
6668 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6670 "%% Import RT is not configured for this VRF\n");
6671 return CMD_WARNING_CONFIG_FAILED
;
6673 } else if (rt_type
== RT_TYPE_EXPORT
) {
6674 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6676 "%% Export RT is not configured for this VRF\n");
6677 return CMD_WARNING_CONFIG_FAILED
;
6679 } else if (rt_type
== RT_TYPE_BOTH
) {
6680 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6681 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6683 "%% Import/Export RT is not configured for this VRF\n");
6684 return CMD_WARNING_CONFIG_FAILED
;
6688 if (rt_type
!= RT_TYPE_IMPORT
) {
6689 for (int i
= 3; i
< argc
; i
++) {
6690 if ((argv
[i
]->arg
)[0] == '*') {
6692 "%% Wildcard '*' only applicable for import\n");
6693 return CMD_WARNING_CONFIG_FAILED
;
6698 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6699 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6701 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6704 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6705 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6707 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6713 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6714 no_bgp_evpn_vrf_rt_auto_cmd
,
6715 "no route-target <both|import|export>$type auto",
6718 "import and export\n"
6721 "Automatically derive route target\n")
6723 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6727 return CMD_WARNING_CONFIG_FAILED
;
6729 if (strmatch(type
, "import"))
6730 rt_type
= RT_TYPE_IMPORT
;
6731 else if (strmatch(type
, "export"))
6732 rt_type
= RT_TYPE_EXPORT
;
6733 else if (strmatch(type
, "both"))
6734 rt_type
= RT_TYPE_BOTH
;
6736 vty_out(vty
, "%% Invalid Route Target type\n");
6737 return CMD_WARNING_CONFIG_FAILED
;
6740 if (rt_type
== RT_TYPE_IMPORT
) {
6741 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6743 "%% Import AUTO RT is not configured for this VRF\n");
6744 return CMD_WARNING_CONFIG_FAILED
;
6746 } else if (rt_type
== RT_TYPE_EXPORT
) {
6747 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6749 "%% Export AUTO RT is not configured for this VRF\n");
6750 return CMD_WARNING_CONFIG_FAILED
;
6752 } else if (rt_type
== RT_TYPE_BOTH
) {
6753 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6754 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6756 "%% Import/Export AUTO RT is not configured for this VRF\n");
6757 return CMD_WARNING_CONFIG_FAILED
;
6761 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6762 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6764 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6765 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6770 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6771 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6773 "EAD ES fragment config\n"
6774 "EVIs per-fragment\n"
6777 bgp_mh_info
->evi_per_es_frag
=
6778 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6783 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6784 "ead-es-route-target export RT",
6785 "EAD ES Route Target\n"
6787 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6789 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6790 struct ecommunity
*ecomadd
= NULL
;
6795 if (!EVPN_ENABLED(bgp
)) {
6796 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6800 /* Add/update the export route-target */
6801 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6803 vty_out(vty
, "%% Malformed Route Target list\n");
6806 ecommunity_str(ecomadd
);
6808 /* Do nothing if we already have this export route-target */
6809 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6811 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6816 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6817 "no ead-es-route-target export RT",
6819 "EAD ES Route Target\n"
6820 "export\n" EVPN_ASN_IP_HELP_STR
)
6822 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6823 struct ecommunity
*ecomdel
= NULL
;
6828 if (!EVPN_ENABLED(bgp
)) {
6829 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6833 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6835 vty_out(vty
, "%% Malformed Route Target list\n");
6838 ecommunity_str(ecomdel
);
6840 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6842 ecommunity_free(&ecomdel
);
6844 "%% RT specified does not match EAD-ES RT configuration\n");
6847 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6852 DEFUN (bgp_evpn_vni_rt
,
6853 bgp_evpn_vni_rt_cmd
,
6854 "route-target <both|import|export> RT",
6856 "import and export\n"
6859 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6861 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6862 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6864 struct ecommunity
*ecomadd
= NULL
;
6869 if (!EVPN_ENABLED(bgp
)) {
6871 "This command is only supported under EVPN VRF\n");
6875 if (!strcmp(argv
[1]->text
, "import"))
6876 rt_type
= RT_TYPE_IMPORT
;
6877 else if (!strcmp(argv
[1]->text
, "export"))
6878 rt_type
= RT_TYPE_EXPORT
;
6879 else if (!strcmp(argv
[1]->text
, "both"))
6880 rt_type
= RT_TYPE_BOTH
;
6882 vty_out(vty
, "%% Invalid Route Target type\n");
6886 /* Add/update the import route-target */
6887 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6888 /* Note that first of the two RTs is created for "both" type */
6889 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6890 ECOMMUNITY_ROUTE_TARGET
, 0);
6892 vty_out(vty
, "%% Malformed Route Target list\n");
6895 ecommunity_str(ecomadd
);
6897 /* Do nothing if we already have this import route-target */
6898 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6899 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6902 /* Add/update the export route-target */
6903 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6904 /* Note that second of the two RTs is created for "both" type */
6905 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6906 ECOMMUNITY_ROUTE_TARGET
, 0);
6908 vty_out(vty
, "%% Malformed Route Target list\n");
6911 ecommunity_str(ecomadd
);
6913 /* Do nothing if we already have this export route-target */
6914 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6915 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6921 DEFUN (no_bgp_evpn_vni_rt
,
6922 no_bgp_evpn_vni_rt_cmd
,
6923 "no route-target <both|import|export> RT",
6926 "import and export\n"
6929 EVPN_ASN_IP_HELP_STR
)
6931 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6932 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6933 int rt_type
, found_ecomdel
;
6934 struct ecommunity
*ecomdel
= NULL
;
6939 if (!EVPN_ENABLED(bgp
)) {
6941 "This command is only supported under EVPN VRF\n");
6945 if (!strcmp(argv
[2]->text
, "import"))
6946 rt_type
= RT_TYPE_IMPORT
;
6947 else if (!strcmp(argv
[2]->text
, "export"))
6948 rt_type
= RT_TYPE_EXPORT
;
6949 else if (!strcmp(argv
[2]->text
, "both"))
6950 rt_type
= RT_TYPE_BOTH
;
6952 vty_out(vty
, "%% Invalid Route Target type\n");
6956 /* The user did "no route-target import", check to see if there are any
6957 * import route-targets configured. */
6958 if (rt_type
== RT_TYPE_IMPORT
) {
6959 if (!is_import_rt_configured(vpn
)) {
6961 "%% Import RT is not configured for this VNI\n");
6964 } else if (rt_type
== RT_TYPE_EXPORT
) {
6965 if (!is_export_rt_configured(vpn
)) {
6967 "%% Export RT is not configured for this VNI\n");
6970 } else if (rt_type
== RT_TYPE_BOTH
) {
6971 if (!is_import_rt_configured(vpn
)
6972 && !is_export_rt_configured(vpn
)) {
6974 "%% Import/Export RT is not configured for this VNI\n");
6979 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6981 vty_out(vty
, "%% Malformed Route Target list\n");
6984 ecommunity_str(ecomdel
);
6986 if (rt_type
== RT_TYPE_IMPORT
) {
6987 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6988 ecommunity_free(&ecomdel
);
6990 "%% RT specified does not match configuration for this VNI\n");
6993 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6994 } else if (rt_type
== RT_TYPE_EXPORT
) {
6995 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6996 ecommunity_free(&ecomdel
);
6998 "%% RT specified does not match configuration for this VNI\n");
7001 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7002 } else if (rt_type
== RT_TYPE_BOTH
) {
7005 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
7006 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
7010 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
7011 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
7015 if (!found_ecomdel
) {
7016 ecommunity_free(&ecomdel
);
7018 "%% RT specified does not match configuration for this VNI\n");
7026 DEFUN (no_bgp_evpn_vni_rt_without_val
,
7027 no_bgp_evpn_vni_rt_without_val_cmd
,
7028 "no route-target <import|export>",
7034 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
7035 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
7041 if (!EVPN_ENABLED(bgp
)) {
7043 "This command is only supported under EVPN VRF\n");
7047 if (!strcmp(argv
[2]->text
, "import")) {
7048 rt_type
= RT_TYPE_IMPORT
;
7049 } else if (!strcmp(argv
[2]->text
, "export")) {
7050 rt_type
= RT_TYPE_EXPORT
;
7052 vty_out(vty
, "%% Invalid Route Target type\n");
7056 /* Check if we should disallow. */
7057 if (rt_type
== RT_TYPE_IMPORT
) {
7058 if (!is_import_rt_configured(vpn
)) {
7060 "%% Import RT is not configured for this VNI\n");
7064 if (!is_export_rt_configured(vpn
)) {
7066 "%% Export RT is not configured for this VNI\n");
7071 /* Unconfigure the RT. */
7072 if (rt_type
== RT_TYPE_IMPORT
)
7073 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
7075 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
7079 static int vni_cmp(const void **a
, const void **b
)
7081 const struct bgpevpn
*first
= *a
;
7082 const struct bgpevpn
*secnd
= *b
;
7084 return secnd
->vni
- first
->vni
;
7088 * Output EVPN configuration information.
7090 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7093 if (bgp
->advertise_all_vni
)
7094 vty_out(vty
, " advertise-all-vni\n");
7096 if (hashcount(bgp
->vnihash
)) {
7097 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
7098 struct listnode
*ln
;
7099 struct bgpevpn
*data
;
7101 list_sort(vnilist
, vni_cmp
);
7102 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
7103 write_vni_config(vty
, data
);
7105 list_delete(&vnilist
);
7108 if (bgp
->advertise_autort_rfc8365
)
7109 vty_out(vty
, " autort rfc8365-compatible\n");
7111 if (bgp
->advertise_gw_macip
)
7112 vty_out(vty
, " advertise-default-gw\n");
7114 if (bgp
->evpn_info
->advertise_svi_macip
)
7115 vty_out(vty
, " advertise-svi-ip\n");
7117 if (bgp
->resolve_overlay_index
)
7118 vty_out(vty
, " enable-resolve-overlay-index\n");
7120 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
7121 vty_out(vty
, " ead-es-frag evi-limit %u\n",
7122 bgp_mh_info
->evi_per_es_frag
);
7124 if (bgp_mh_info
->host_routes_use_l3nhg
!=
7125 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
7126 if (bgp_mh_info
->host_routes_use_l3nhg
)
7127 vty_out(vty
, " use-es-l3nhg\n");
7129 vty_out(vty
, " no use-es-l3nhg\n");
7132 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
7133 if (bgp_mh_info
->ead_evi_rx
)
7134 vty_out(vty
, " no disable-ead-evi-rx\n");
7136 vty_out(vty
, " disable-ead-evi-rx\n");
7139 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
7140 if (bgp_mh_info
->ead_evi_tx
)
7141 vty_out(vty
, " no disable-ead-evi-tx\n");
7143 vty_out(vty
, " disable-ead-evi-tx\n");
7146 if (!bgp
->evpn_info
->dup_addr_detect
)
7147 vty_out(vty
, " no dup-addr-detection\n");
7149 if (bgp
->evpn_info
->dad_max_moves
!=
7150 EVPN_DAD_DEFAULT_MAX_MOVES
||
7151 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
7152 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
7153 bgp
->evpn_info
->dad_max_moves
,
7154 bgp
->evpn_info
->dad_time
);
7156 if (bgp
->evpn_info
->dad_freeze
) {
7157 if (bgp
->evpn_info
->dad_freeze_time
)
7159 " dup-addr-detection freeze %u\n",
7160 bgp
->evpn_info
->dad_freeze_time
);
7163 " dup-addr-detection freeze permanent\n");
7166 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
7167 vty_out(vty
, " flooding disable\n");
7169 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7170 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
7171 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7172 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
7173 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7176 " advertise ipv4 unicast\n");
7177 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7178 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
7179 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7181 " advertise ipv4 unicast gateway-ip route-map %s\n",
7182 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7184 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
7187 /* EAD ES export route-target */
7188 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
7189 struct ecommunity
*ecom
;
7191 struct listnode
*node
;
7193 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
7196 ecom_str
= ecommunity_ecom2str(
7197 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7198 vty_out(vty
, " ead-es-route-target export %s\n",
7200 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7204 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7205 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
7206 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7208 " advertise ipv6 unicast route-map %s\n",
7209 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7212 " advertise ipv6 unicast\n");
7213 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7214 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
7215 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7217 " advertise ipv6 unicast gateway-ip route-map %s\n",
7218 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7220 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
7223 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7224 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
7225 vty_out(vty
, " default-originate ipv4\n");
7227 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7228 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
7229 vty_out(vty
, " default-originate ipv6\n");
7231 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
7232 if (!bgp
->evpn_info
->advertise_pip
)
7233 vty_out(vty
, " no advertise-pip\n");
7234 if (bgp
->evpn_info
->advertise_pip
) {
7235 if (bgp
->evpn_info
->pip_ip_static
.s_addr
7237 vty_out(vty
, " advertise-pip ip %pI4",
7238 &bgp
->evpn_info
->pip_ip_static
);
7240 bgp
->evpn_info
->pip_rmac_static
))) {
7241 char buf
[ETHER_ADDR_STRLEN
];
7243 vty_out(vty
, " mac %s",
7253 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
7254 vty_out(vty
, " rd %pRD\n", &bgp
->vrf_prd
);
7256 /* import route-target */
7257 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
7259 struct listnode
*node
, *nnode
;
7260 struct vrf_route_target
*l3rt
;
7262 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
7265 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7268 ecom_str
= ecommunity_ecom2str(
7269 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7271 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
7272 char *vni_str
= NULL
;
7274 vni_str
= strchr(ecom_str
, ':');
7276 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7280 /* Move pointer to vni */
7283 vty_out(vty
, " route-target import *:%s\n",
7287 vty_out(vty
, " route-target import %s\n",
7290 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7294 /* import route-target auto */
7295 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
7296 vty_out(vty
, " route-target import auto\n");
7298 /* export route-target */
7299 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
7301 struct listnode
*node
, *nnode
;
7302 struct vrf_route_target
*l3rt
;
7304 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
7307 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7310 ecom_str
= ecommunity_ecom2str(
7311 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7312 vty_out(vty
, " route-target export %s\n", ecom_str
);
7313 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7317 /* export route-target auto */
7318 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
7319 vty_out(vty
, " route-target export auto\n");
7322 void bgp_ethernetvpn_init(void)
7324 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
7325 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
7326 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
7327 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
7328 install_element(VIEW_NODE
,
7329 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
7330 install_element(VIEW_NODE
,
7331 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
7334 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
7337 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
7338 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
7339 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
7340 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
7341 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
7342 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
7343 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
7344 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
7345 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
7346 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
7347 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
7348 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
7349 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
7350 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
7351 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
7352 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
7353 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
7354 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
7355 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
7356 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
7357 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
7358 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
7359 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
7360 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
7361 install_element(BGP_EVPN_NODE
,
7362 &bgp_evpn_enable_resolve_overlay_index_cmd
);
7365 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
7366 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
7368 /* "show bgp l2vpn evpn" commands. */
7369 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
7370 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
7371 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
7372 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
7373 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
7374 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
7375 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
7376 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
7377 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
7378 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
7379 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
7380 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
7381 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
7382 install_element(VIEW_NODE
,
7383 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
7384 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
7385 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
7386 install_element(VIEW_NODE
,
7387 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
7388 install_element(VIEW_NODE
,
7389 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
7390 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
7391 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
7393 /* "show bgp vni" commands. */
7394 install_element(VIEW_NODE
, &show_bgp_vni_all_cmd
);
7395 install_element(VIEW_NODE
, &show_bgp_vni_all_ead_cmd
);
7396 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_mac_cmd
);
7397 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_ip_cmd
);
7398 install_element(VIEW_NODE
, &show_bgp_vni_all_imet_cmd
);
7399 install_element(VIEW_NODE
, &show_bgp_vni_cmd
);
7400 install_element(VIEW_NODE
, &show_bgp_vni_ead_cmd
);
7401 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_cmd
);
7402 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_cmd
);
7403 install_element(VIEW_NODE
, &show_bgp_vni_imet_cmd
);
7404 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_addr_cmd
);
7405 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_addr_cmd
);
7407 /* "show bgp evpn" commands. */
7408 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
7409 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
7410 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
7411 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
7412 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
7413 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
7414 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
7415 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
7416 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
7417 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
7418 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
7419 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
7421 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
7422 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
7423 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
7424 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
7425 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
7426 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
7427 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
7428 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
7429 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
7430 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
7431 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
7432 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
7433 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
7434 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
7435 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
7436 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
7437 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
7438 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
7439 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
7440 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
7441 install_element(BGP_EVPN_VNI_NODE
,
7442 &bgp_evpn_advertise_default_gw_vni_cmd
);
7443 install_element(BGP_EVPN_VNI_NODE
,
7444 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
7445 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
7446 install_element(BGP_EVPN_VNI_NODE
,
7447 &no_bgp_evpn_advertise_vni_subnet_cmd
);