1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
64 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
65 enum overlay_index_type
*oly
)
67 *oly
= OVERLAY_INDEX_TYPE_NONE
;
68 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
69 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
73 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
77 uint8_t type
, sub_type
;
78 struct ecommunity_as eas
;
79 struct ecommunity_ip eip
;
80 struct listnode
*node
, *nnode
;
81 struct bgp
*tmp_bgp_vrf
= NULL
;
82 json_object
*json_rt
= NULL
;
83 json_object
*json_vrfs
= NULL
;
84 char rt_buf
[RT_ADDRSTRLEN
];
87 json_rt
= json_object_new_object();
88 json_vrfs
= json_object_new_array();
91 pnt
= (uint8_t *)&irt
->rt
.val
;
94 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
97 memset(&eas
, 0, sizeof(eas
));
99 case ECOMMUNITY_ENCODE_AS
:
100 eas
.as
= (*pnt
++ << 8);
102 ptr_get_be32(pnt
, &eas
.val
);
104 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
107 json_object_string_add(json_rt
, "rt", rt_buf
);
109 vty_out(vty
, "Route-target: %s", rt_buf
);
113 case ECOMMUNITY_ENCODE_IP
:
114 memcpy(&eip
.ip
, pnt
, 4);
116 eip
.val
= (*pnt
++ << 8);
119 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
122 json_object_string_add(json_rt
, "rt", rt_buf
);
124 vty_out(vty
, "Route-target: %s", rt_buf
);
128 case ECOMMUNITY_ENCODE_AS4
:
129 pnt
= ptr_get_be32(pnt
, &eas
.val
);
130 eas
.val
= (*pnt
++ << 8);
133 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
136 json_object_string_add(json_rt
, "rt", rt_buf
);
138 vty_out(vty
, "Route-target: %s", rt_buf
);
148 "\nList of VRFs importing routes with this route-target:\n");
151 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
153 json_object_array_add(
155 json_object_new_string(
156 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
158 vty_out(vty
, " %s\n",
159 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
163 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
164 json_object_object_add(json
, rt_buf
, json_rt
);
168 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
170 json_object
*json
= NULL
;
171 struct vty
*vty
= NULL
;
172 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
174 vty
= (struct vty
*)args
[0];
175 json
= (struct json_object
*)args
[1];
177 display_vrf_import_rt(vty
, irt
, json
);
180 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
184 uint8_t type
, sub_type
;
185 struct ecommunity_as eas
;
186 struct ecommunity_ip eip
;
187 struct listnode
*node
, *nnode
;
188 struct bgpevpn
*tmp_vpn
;
189 json_object
*json_rt
= NULL
;
190 json_object
*json_vnis
= NULL
;
191 char rt_buf
[RT_ADDRSTRLEN
];
194 json_rt
= json_object_new_object();
195 json_vnis
= json_object_new_array();
198 /* TODO: This needs to go into a function */
200 pnt
= (uint8_t *)&irt
->rt
.val
;
203 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
206 memset(&eas
, 0, sizeof(eas
));
208 case ECOMMUNITY_ENCODE_AS
:
209 eas
.as
= (*pnt
++ << 8);
211 ptr_get_be32(pnt
, &eas
.val
);
213 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
216 json_object_string_add(json_rt
, "rt", rt_buf
);
218 vty_out(vty
, "Route-target: %s", rt_buf
);
222 case ECOMMUNITY_ENCODE_IP
:
223 memcpy(&eip
.ip
, pnt
, 4);
225 eip
.val
= (*pnt
++ << 8);
228 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
231 json_object_string_add(json_rt
, "rt", rt_buf
);
233 vty_out(vty
, "Route-target: %s", rt_buf
);
237 case ECOMMUNITY_ENCODE_AS4
:
238 pnt
= ptr_get_be32(pnt
, &eas
.val
);
239 eas
.val
= (*pnt
++ << 8);
242 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
245 json_object_string_add(json_rt
, "rt", rt_buf
);
247 vty_out(vty
, "Route-target: %s", rt_buf
);
257 "\nList of VNIs importing routes with this route-target:\n");
260 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
262 json_object_array_add(
263 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
265 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
269 json_object_object_add(json_rt
, "vnis", json_vnis
);
270 json_object_object_add(json
, rt_buf
, json_rt
);
274 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
276 json_object
*json
= NULL
;
277 struct vty
*vty
= NULL
;
278 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
283 display_import_rt(vty
, irt
, json
);
288 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
289 struct bgp_dest
*rd_dest
,
290 json_object
*json
, char *rd_str
,
297 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
301 /* Decode RD type. */
302 type
= decode_rd_type(pnt
);
305 vty_out(vty
, "Route Distinguisher: ");
309 decode_rd_as(pnt
+ 2, &rd_as
);
310 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
312 json_object_string_add(json
, "rd", rd_str
);
314 vty_out(vty
, "%s\n", rd_str
);
318 decode_rd_as4(pnt
+ 2, &rd_as
);
319 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
321 json_object_string_add(json
, "rd", rd_str
);
323 vty_out(vty
, "%s\n", rd_str
);
327 decode_rd_ip(pnt
+ 2, &rd_ip
);
328 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
330 json_object_string_add(json
, "rd", rd_str
);
332 vty_out(vty
, "%s\n", rd_str
);
337 snprintf(rd_str
, len
, "Unknown");
338 json_object_string_add(json
, "rd", rd_str
);
340 snprintf(rd_str
, len
, "Unknown RD type");
341 vty_out(vty
, "%s\n", rd_str
);
347 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
348 uint64_t tbl_ver
, json_object
*json
)
351 " Network Next Hop Metric LocPrf Weight Path\n";
357 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
358 tbl_ver
, &bgp
->router_id
);
360 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
361 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
363 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
365 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
366 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
367 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
368 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
369 vty_out(vty
, "%s", ri_header
);
372 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
375 char buf1
[INET6_ADDRSTRLEN
];
377 struct listnode
*node
, *nnode
;
378 struct vrf_route_target
*l3rt
;
379 json_object
*json_import_rtl
= NULL
;
380 json_object
*json_export_rtl
= NULL
;
381 char buf2
[ETHER_ADDR_STRLEN
];
383 json_import_rtl
= json_export_rtl
= 0;
386 json_import_rtl
= json_object_new_array();
387 json_export_rtl
= json_object_new_array();
388 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
389 json_object_string_add(json
, "type", "L3");
390 json_object_string_add(json
, "inKernel", "True");
391 json_object_string_addf(json
, "rd", "%pRD", &bgp_vrf
->vrf_prd
);
392 json_object_string_addf(json
, "originatorIp", "%pI4",
393 &bgp_vrf
->originator_ip
);
394 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
395 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
396 json_object_string_add(json
, "advertisePip",
397 bgp_vrf
->evpn_info
->advertise_pip
?
398 "Enabled" : "Disabled");
399 json_object_string_addf(json
, "sysIP", "%pI4",
400 &bgp_vrf
->evpn_info
->pip_ip
);
401 json_object_string_add(json
, "sysMac",
402 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
403 buf2
, sizeof(buf2
)));
404 json_object_string_add(json
, "rmac",
405 prefix_mac2str(&bgp_vrf
->rmac
,
406 buf2
, sizeof(buf2
)));
408 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
409 vty_out(vty
, " (known to the kernel)");
412 vty_out(vty
, " Type: %s\n", "L3");
413 vty_out(vty
, " Tenant VRF: %s\n",
414 vrf_id_to_name(bgp_vrf
->vrf_id
));
415 vty_out(vty
, " RD: %pRD\n", &bgp_vrf
->vrf_prd
);
416 vty_out(vty
, " Originator IP: %pI4\n",
417 &bgp_vrf
->originator_ip
);
418 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
419 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
420 vty_out(vty
, " Advertise-pip: %s\n",
421 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
422 vty_out(vty
, " System-IP: %s\n",
423 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
424 buf1
, INET_ADDRSTRLEN
));
425 vty_out(vty
, " System-MAC: %s\n",
426 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
427 buf2
, sizeof(buf2
)));
428 vty_out(vty
, " Router-MAC: %s\n",
429 prefix_mac2str(&bgp_vrf
->rmac
,
430 buf2
, sizeof(buf2
)));
434 vty_out(vty
, " Import Route Target:\n");
436 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
437 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
438 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
441 json_object_array_add(json_import_rtl
,
442 json_object_new_string(ecom_str
));
444 vty_out(vty
, " %s\n", ecom_str
);
446 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
450 json_object_object_add(json
, "importRts", json_import_rtl
);
452 vty_out(vty
, " Export Route Target:\n");
454 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
455 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
456 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
459 json_object_array_add(json_export_rtl
,
460 json_object_new_string(ecom_str
));
462 vty_out(vty
, " %s\n", ecom_str
);
464 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
468 json_object_object_add(json
, "exportRts", json_export_rtl
);
471 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
474 struct listnode
*node
, *nnode
;
475 struct ecommunity
*ecom
;
476 json_object
*json_import_rtl
= NULL
;
477 json_object
*json_export_rtl
= NULL
;
478 struct bgp
*bgp_evpn
;
480 bgp_evpn
= bgp_get_evpn();
483 json_import_rtl
= json_object_new_array();
484 json_export_rtl
= json_object_new_array();
485 json_object_int_add(json
, "vni", vpn
->vni
);
486 json_object_string_add(json
, "type", "L2");
487 json_object_string_add(json
, "inKernel",
488 is_vni_live(vpn
) ? "True" : "False");
489 json_object_string_addf(json
, "rd", "%pRD", &vpn
->prd
);
490 json_object_string_addf(json
, "originatorIp", "%pI4",
491 &vpn
->originator_ip
);
492 json_object_string_addf(json
, "mcastGroup", "%pI4",
494 /* per vni knob is enabled -- Enabled
495 * Global knob is enabled -- Active
496 * default -- Disabled
498 if (!vpn
->advertise_gw_macip
&&
499 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
500 json_object_string_add(json
, "advertiseGatewayMacip",
502 else if (vpn
->advertise_gw_macip
)
503 json_object_string_add(json
, "advertiseGatewayMacip",
506 json_object_string_add(json
, "advertiseGatewayMacip",
508 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
509 bgp_evpn
->evpn_info
->advertise_svi_macip
)
510 json_object_string_add(json
, "advertiseSviMacIp",
512 else if (vpn
->advertise_svi_macip
)
513 json_object_string_add(json
, "advertiseSviMacIp",
516 json_object_string_add(json
, "advertiseSviMacIp",
518 json_object_string_add(
519 json
, "sviInterface",
520 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
522 vty_out(vty
, "VNI: %u", vpn
->vni
);
523 if (is_vni_live(vpn
))
524 vty_out(vty
, " (known to the kernel)");
527 vty_out(vty
, " Type: %s\n", "L2");
528 vty_out(vty
, " Tenant-Vrf: %s\n",
529 vrf_id_to_name(vpn
->tenant_vrf_id
));
530 vty_out(vty
, " RD: %pRD\n", &vpn
->prd
);
531 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
532 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
533 if (!vpn
->advertise_gw_macip
&&
534 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
535 vty_out(vty
, " Advertise-gw-macip : %s\n",
537 else if (vpn
->advertise_gw_macip
)
538 vty_out(vty
, " Advertise-gw-macip : %s\n",
541 vty_out(vty
, " Advertise-gw-macip : %s\n",
543 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
544 bgp_evpn
->evpn_info
->advertise_svi_macip
)
545 vty_out(vty
, " Advertise-svi-macip : %s\n",
547 else if (vpn
->advertise_svi_macip
)
548 vty_out(vty
, " Advertise-svi-macip : %s\n",
551 vty_out(vty
, " Advertise-svi-macip : %s\n",
553 vty_out(vty
, " SVI interface : %s\n",
554 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
558 vty_out(vty
, " Import Route Target:\n");
560 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
561 ecom_str
= ecommunity_ecom2str(ecom
,
562 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
565 json_object_array_add(json_import_rtl
,
566 json_object_new_string(ecom_str
));
568 vty_out(vty
, " %s\n", ecom_str
);
570 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
574 json_object_object_add(json
, "importRts", json_import_rtl
);
576 vty_out(vty
, " Export Route Target:\n");
578 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
579 ecom_str
= ecommunity_ecom2str(ecom
,
580 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
583 json_object_array_add(json_export_rtl
,
584 json_object_new_string(ecom_str
));
586 vty_out(vty
, " %s\n", ecom_str
);
588 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
592 json_object_object_add(json
, "exportRts", json_export_rtl
);
595 static void show_esi_routes(struct bgp
*bgp
,
596 struct bgp_evpn_es
*es
,
601 struct bgp_dest
*dest
;
602 struct bgp_path_info
*pi
;
603 uint32_t prefix_cnt
, path_cnt
;
606 prefix_cnt
= path_cnt
= 0;
608 tbl_ver
= es
->route_table
->version
;
609 for (dest
= bgp_table_top(es
->route_table
); dest
;
610 dest
= bgp_route_next(dest
)) {
611 int add_prefix_to_json
= 0;
612 json_object
*json_paths
= NULL
;
613 json_object
*json_prefix
= NULL
;
614 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
617 json_prefix
= json_object_new_object();
619 pi
= bgp_dest_get_bgp_path_info(dest
);
621 /* Overall header/legend displayed once. */
623 bgp_evpn_show_route_header(vty
, bgp
,
632 json_paths
= json_object_new_array();
634 /* For EVPN, the prefix is displayed for each path (to fit in
635 * with code that already exists).
637 for (; pi
; pi
= pi
->next
) {
638 json_object
*json_path
= NULL
;
641 json_path
= json_object_new_array();
643 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
647 json_object_array_add(json_paths
, json_path
);
650 add_prefix_to_json
= 1;
654 if (add_prefix_to_json
) {
655 json_object_string_addf(json_prefix
, "prefix",
657 json_object_int_add(json_prefix
, "prefixLen",
659 json_object_object_add(json_prefix
, "paths",
661 json_object_object_addf(json
, json_prefix
,
664 json_object_free(json_paths
);
665 json_object_free(json_prefix
);
673 json_object_int_add(json
, "numPrefix", prefix_cnt
);
674 json_object_int_add(json
, "numPaths", path_cnt
);
677 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
679 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
680 prefix_cnt
, path_cnt
);
684 /* Display all MAC-IP VNI routes linked to an ES */
685 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
686 json_object
*json
, int detail
,
690 struct bgp_path_info
*pi
;
691 int header
= detail
? 0 : 1;
693 struct listnode
*node
;
694 struct bgp_evpn_es
*es
;
695 struct bgp_path_es_info
*es_info
;
696 struct bgp
*bgp
= bgp_get_evpn();
697 json_object
*json_paths
= NULL
;
705 json_paths
= json_object_new_array();
707 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
708 struct list
*es_list
;
710 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
714 es_list
= es
->macip_global_path_list
;
716 es_list
= es
->macip_evi_path_list
;
718 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
719 json_object
*json_path
= NULL
;
724 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
727 /* Overall header/legend displayed once. */
729 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
736 json_path
= json_object_new_array();
739 route_vty_out_detail(
740 vty
, bgp
, rn
, bgp_dest_get_prefix(rn
),
741 pi
, AFI_L2VPN
, SAFI_EVPN
,
742 RPKI_NOT_BEING_USED
, json_path
);
744 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
748 json_object_array_add(json_paths
, json_path
);
753 json_object_object_add(json
, "paths", json_paths
);
754 json_object_int_add(json
, "numPaths", path_cnt
);
757 vty_out(vty
, "There are no MAC-IP ES paths");
759 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
764 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
765 json_object
*json
, int detail
)
767 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
770 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
771 json_object
*json
, int detail
)
773 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
776 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
,
777 struct vty
*vty
, int type
, bool mac_table
,
778 struct in_addr vtep_ip
, json_object
*json
,
781 struct bgp_dest
*dest
;
782 struct bgp_path_info
*pi
;
783 struct bgp_table
*table
;
784 int header
= detail
? 0 : 1;
786 uint32_t prefix_cnt
, path_cnt
;
788 prefix_cnt
= path_cnt
= 0;
791 table
= vpn
->mac_table
;
793 table
= vpn
->ip_table
;
795 tbl_ver
= table
->version
;
796 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
797 const struct prefix_evpn
*evp
=
798 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
799 int add_prefix_to_json
= 0;
800 json_object
*json_paths
= NULL
;
801 json_object
*json_prefix
= NULL
;
802 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
804 if (type
&& evp
->prefix
.route_type
!= type
)
808 json_prefix
= json_object_new_object();
810 pi
= bgp_dest_get_bgp_path_info(dest
);
812 /* Overall header/legend displayed once. */
814 bgp_evpn_show_route_header(vty
, bgp
,
823 json_paths
= json_object_new_array();
825 /* For EVPN, the prefix is displayed for each path (to fit in
826 * with code that already exists).
828 for (; pi
; pi
= pi
->next
) {
830 json_object
*json_path
= NULL
;
832 if (vtep_ip
.s_addr
!= INADDR_ANY
833 && !IPV4_ADDR_SAME(&(vtep_ip
),
834 &(pi
->attr
->nexthop
)))
837 if (evp
->prefix
.route_type
== BGP_EVPN_MAC_IP_ROUTE
) {
839 * VNI IP/MAC table prefixes don't have MAC/IP
840 * respectively so make sure it's set from path
843 if (is_evpn_prefix_ipaddr_none(evp
)) {
844 /* VNI MAC -> Global */
845 evpn_type2_prefix_global_copy(
846 (struct prefix_evpn
*)&tmp_p
,
848 evpn_type2_path_info_get_ip(
851 /* VNI IP -> Global */
852 evpn_type2_prefix_global_copy(
853 (struct prefix_evpn
*)&tmp_p
,
855 evpn_type2_path_info_get_mac(
860 memcpy(&tmp_p
, p
, sizeof(tmp_p
));
864 json_path
= json_object_new_array();
867 route_vty_out_detail(vty
, bgp
, dest
, &tmp_p
, pi
,
868 AFI_L2VPN
, SAFI_EVPN
,
873 route_vty_out(vty
, &tmp_p
, pi
, 0, SAFI_EVPN
,
877 json_object_array_add(json_paths
, json_path
);
880 add_prefix_to_json
= 1;
884 if (add_prefix_to_json
) {
885 json_object_string_addf(json_prefix
, "prefix",
887 json_object_int_add(json_prefix
, "prefixLen",
889 json_object_object_add(json_prefix
, "paths",
891 json_object_object_addf(json
, json_prefix
,
894 json_object_free(json_paths
);
895 json_object_free(json_prefix
);
903 json_object_int_add(json
, "numPrefix", prefix_cnt
);
904 json_object_int_add(json
, "numPaths", path_cnt
);
907 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
908 type
? "(of requested type) " : "");
910 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
911 prefix_cnt
, path_cnt
,
912 type
? " (of requested type)" : "");
917 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
919 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
920 struct vni_walk_ctx
*wctx
= arg
;
921 struct vty
*vty
= wctx
->vty
;
922 json_object
*json
= wctx
->json
;
923 json_object
*json_vni
= NULL
;
924 char vni_str
[VNI_STR_LEN
];
926 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
928 json_vni
= json_object_new_object();
929 json_object_int_add(json_vni
, "vni", vpn
->vni
);
931 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
934 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, wctx
->type
, wctx
->mac_table
,
935 wctx
->vtep_ip
, json_vni
, wctx
->detail
);
938 json_object_object_add(json
, vni_str
, json_vni
);
941 static void show_vni_routes_all_hash(struct hash_bucket
*bucket
, void *arg
)
943 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
944 struct vni_walk_ctx
*wctx
= arg
;
945 struct vty
*vty
= wctx
->vty
;
946 json_object
*json
= wctx
->json
;
947 json_object
*json_vni
= NULL
;
948 json_object
*json_vni_mac
= NULL
;
949 char vni_str
[VNI_STR_LEN
];
951 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
953 json_vni
= json_object_new_object();
954 json_object_int_add(json_vni
, "vni", vpn
->vni
);
956 vty_out(vty
, "\nVNI: %u\n\n", vpn
->vni
);
959 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, false, wctx
->vtep_ip
,
960 json_vni
, wctx
->detail
);
963 json_object_object_add(json
, vni_str
, json_vni
);
966 json_vni_mac
= json_object_new_object();
968 vty_out(vty
, "\nVNI: %u MAC Table\n\n", vpn
->vni
);
970 show_vni_routes(wctx
->bgp
, vpn
, wctx
->vty
, 0, true, wctx
->vtep_ip
,
971 json_vni_mac
, wctx
->detail
);
974 json_object_object_add(json_vni
, "macTable", json_vni_mac
);
977 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
980 json_object
*json_vni
= NULL
;
981 json_object
*json_import_rtl
= NULL
;
982 json_object
*json_export_rtl
= NULL
;
984 char buf2
[INET6_ADDRSTRLEN
];
987 struct listnode
*node
, *nnode
;
988 struct vrf_route_target
*l3rt
;
994 json_vni
= json_object_new_object();
995 json_import_rtl
= json_object_new_array();
996 json_export_rtl
= json_object_new_array();
999 /* if an l3vni is present in bgp it is live */
1001 snprintf(buf1
, sizeof(buf1
), "*");
1004 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
1005 json_object_string_add(json_vni
, "type", "L3");
1006 json_object_string_add(json_vni
, "inKernel", "True");
1007 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1008 &bgp
->originator_ip
);
1009 json_object_string_addf(json_vni
, "rd", "%pRD", &bgp
->vrf_prd
);
1010 json_object_string_add(json_vni
, "advertiseGatewayMacip",
1012 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
1013 json_object_string_add(
1014 json_vni
, "advertisePip",
1015 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
1016 json_object_string_addf(json_vni
, "sysIP", "%pI4",
1017 &bgp
->evpn_info
->pip_ip
);
1018 json_object_string_add(json_vni
, "sysMAC",
1019 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
1020 buf2
, sizeof(buf2
)));
1021 json_object_string_add(
1023 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
1025 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, bgp
->l3vni
, "L3",
1029 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
1030 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1031 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1034 json_object_array_add(json_import_rtl
,
1035 json_object_new_string(ecom_str
));
1037 if (listcount(bgp
->vrf_import_rtl
) > 1)
1038 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1041 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1043 vty_out(vty
, " %-25s", rt_buf
);
1046 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1048 /* If there are multiple import RTs we break here and show only
1055 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1057 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
1058 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
1059 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1062 json_object_array_add(json_export_rtl
,
1063 json_object_new_string(ecom_str
));
1065 if (listcount(bgp
->vrf_export_rtl
) > 1)
1066 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1069 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1071 vty_out(vty
, " %-25s", rt_buf
);
1074 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1076 /* If there are multiple export RTs we break here and show only
1079 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1085 char vni_str
[VNI_STR_LEN
];
1087 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1088 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1089 json_object_object_add(json
, vni_str
, json_vni
);
1095 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1099 json_object
*json_vni
= NULL
;
1100 json_object
*json_import_rtl
= NULL
;
1101 json_object
*json_export_rtl
= NULL
;
1102 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1106 struct listnode
*node
, *nnode
;
1107 struct ecommunity
*ecom
;
1108 struct bgp
*bgp_evpn
;
1113 bgp_evpn
= bgp_get_evpn();
1116 json_vni
= json_object_new_object();
1117 json_import_rtl
= json_object_new_array();
1118 json_export_rtl
= json_object_new_array();
1122 if (is_vni_live(vpn
))
1123 snprintf(buf1
, sizeof(buf1
), "*");
1126 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1127 json_object_string_add(json_vni
, "type", "L2");
1128 json_object_string_add(json_vni
, "inKernel",
1129 is_vni_live(vpn
) ? "True" : "False");
1130 json_object_string_addf(json_vni
, "rd", "%pRD", &vpn
->prd
);
1131 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1132 &vpn
->originator_ip
);
1133 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1135 /* per vni knob is enabled -- Enabled
1136 * Global knob is enabled -- Active
1137 * default -- Disabled
1139 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1140 && bgp_evpn
->advertise_gw_macip
)
1141 json_object_string_add(
1142 json_vni
, "advertiseGatewayMacip", "Active");
1143 else if (vpn
->advertise_gw_macip
)
1144 json_object_string_add(
1145 json_vni
, "advertiseGatewayMacip", "Enabled");
1147 json_object_string_add(
1148 json_vni
, "advertiseGatewayMacip", "Disabled");
1149 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1150 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1151 json_object_string_add(json_vni
, "advertiseSviMacIp",
1153 else if (vpn
->advertise_svi_macip
)
1154 json_object_string_add(json_vni
, "advertiseSviMacIp",
1157 json_object_string_add(json_vni
, "advertiseSviMacIp",
1160 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, vpn
->vni
, "L2",
1164 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1165 ecom_str
= ecommunity_ecom2str(ecom
,
1166 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1169 json_object_array_add(json_import_rtl
,
1170 json_object_new_string(ecom_str
));
1172 if (listcount(vpn
->import_rtl
) > 1)
1173 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1176 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1178 vty_out(vty
, " %-25s", rt_buf
);
1181 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1183 /* If there are multiple import RTs we break here and show only
1190 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1192 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1193 ecom_str
= ecommunity_ecom2str(ecom
,
1194 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1197 json_object_array_add(json_export_rtl
,
1198 json_object_new_string(ecom_str
));
1200 if (listcount(vpn
->export_rtl
) > 1)
1201 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1204 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1206 vty_out(vty
, " %-25s", rt_buf
);
1209 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1211 /* If there are multiple export RTs we break here and show only
1214 vty_out(vty
, "%-37s",
1215 vrf_id_to_name(vpn
->tenant_vrf_id
));
1221 char vni_str
[VNI_STR_LEN
];
1223 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1224 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1225 json_object_object_add(json
, vni_str
, json_vni
);
1231 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1232 enum bgp_show_type type
, void *output_arg
,
1233 int option
, bool use_json
)
1235 afi_t afi
= AFI_L2VPN
;
1237 struct bgp_table
*table
;
1238 struct bgp_dest
*dest
;
1239 struct bgp_dest
*rm
;
1240 struct bgp_path_info
*pi
;
1243 char rd_str
[RD_ADDRSTRLEN
];
1246 unsigned long output_count
= 0;
1247 unsigned long total_count
= 0;
1248 json_object
*json
= NULL
;
1249 json_object
*json_array
= NULL
;
1250 json_object
*json_prefix_info
= NULL
;
1252 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1254 bgp
= bgp_get_evpn();
1257 vty_out(vty
, "No BGP process is configured\n");
1259 vty_out(vty
, "{}\n");
1264 json
= json_object_new_object();
1266 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1267 dest
= bgp_route_next(dest
)) {
1269 json_object
*json_nroute
= NULL
;
1270 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1272 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1275 table
= bgp_dest_get_bgp_table_info(dest
);
1280 tbl_ver
= table
->version
;
1282 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1283 pi
= bgp_dest_get_bgp_path_info(rm
);
1288 for (; pi
; pi
= pi
->next
) {
1289 struct community
*picomm
= NULL
;
1291 picomm
= bgp_attr_get_community(pi
->attr
);
1294 if (type
== bgp_show_type_neighbor
) {
1295 struct peer
*peer
= output_arg
;
1297 if (peer_cmp(peer
, pi
->peer
) != 0)
1300 if (type
== bgp_show_type_lcommunity_exact
) {
1301 struct lcommunity
*lcom
= output_arg
;
1303 if (!bgp_attr_get_lcommunity(
1306 bgp_attr_get_lcommunity(
1311 if (type
== bgp_show_type_lcommunity
) {
1312 struct lcommunity
*lcom
= output_arg
;
1314 if (!bgp_attr_get_lcommunity(
1317 bgp_attr_get_lcommunity(
1322 if (type
== bgp_show_type_community
) {
1323 struct community
*com
= output_arg
;
1326 !community_match(picomm
, com
))
1329 if (type
== bgp_show_type_community_exact
) {
1330 struct community
*com
= output_arg
;
1333 !community_cmp(picomm
, com
))
1338 json_object_int_add(
1339 json
, "bgpTableVersion",
1341 json_object_string_addf(
1346 json_object_int_add(
1349 bgp
->default_local_pref
);
1350 json_object_int_add(
1354 if (option
== SHOW_DISPLAY_TAGS
)
1359 == SHOW_DISPLAY_OVERLAY
)
1363 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1371 json_object_new_object();
1372 bgp_evpn_show_route_rd_header(
1373 vty
, dest
, json_nroute
, rd_str
,
1377 if (use_json
&& !json_array
)
1378 json_array
= json_object_new_array();
1380 if (option
== SHOW_DISPLAY_TAGS
)
1382 vty
, bgp_dest_get_prefix(rm
),
1383 pi
, no_display
, SAFI_EVPN
,
1385 else if (option
== SHOW_DISPLAY_OVERLAY
)
1386 route_vty_out_overlay(
1387 vty
, bgp_dest_get_prefix(rm
),
1388 pi
, no_display
, json_array
);
1391 bgp_dest_get_prefix(rm
),
1392 pi
, no_display
, SAFI_EVPN
,
1400 if (use_json
&& json_array
) {
1401 const struct prefix
*p
=
1402 bgp_dest_get_prefix(rm
);
1404 json_prefix_info
= json_object_new_object();
1406 json_object_string_addf(json_prefix_info
,
1407 "prefix", "%pFX", p
);
1409 json_object_int_add(json_prefix_info
,
1410 "prefixLen", p
->prefixlen
);
1412 json_object_object_add(json_prefix_info
,
1413 "paths", json_array
);
1414 json_object_object_addf(json_nroute
,
1421 if (use_json
&& json_nroute
)
1422 json_object_object_add(json
, rd_str
, json_nroute
);
1426 json_object_int_add(json
, "numPrefix", output_count
);
1427 json_object_int_add(json
, "totalPrefix", total_count
);
1428 vty_json(vty
, json
);
1430 if (output_count
== 0)
1431 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1435 "\nDisplayed %ld out of %ld total prefixes\n",
1436 output_count
, total_count
);
1441 DEFUN(show_ip_bgp_l2vpn_evpn
,
1442 show_ip_bgp_l2vpn_evpn_cmd
,
1443 "show [ip] bgp l2vpn evpn [json]",
1444 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1446 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1447 SHOW_DISPLAY_STANDARD
,
1448 use_json(argc
, argv
));
1451 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1452 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1453 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1459 "Display information for a route distinguisher\n"
1460 "VPN Route Distinguisher\n"
1461 "All VPN Route Distinguishers\n"
1464 int idx_ext_community
= 0;
1466 struct prefix_rd prd
;
1469 if (argv_find(argv
, argc
, "all", &rd_all
))
1470 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1471 NULL
, SHOW_DISPLAY_STANDARD
,
1472 use_json(argc
, argv
));
1474 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1475 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1477 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1480 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1481 SHOW_DISPLAY_STANDARD
,
1482 use_json(argc
, argv
));
1485 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1486 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1487 "show [ip] bgp l2vpn evpn all tags",
1493 "Display information about all EVPN NLRIs\n"
1494 "Display BGP tags for prefixes\n")
1496 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1497 SHOW_DISPLAY_TAGS
, 0);
1500 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1501 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1502 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1508 "Display information for a route distinguisher\n"
1509 "VPN Route Distinguisher\n"
1510 "All VPN Route Distinguishers\n"
1511 "Display BGP tags for prefixes\n")
1513 int idx_ext_community
= 0;
1515 struct prefix_rd prd
;
1518 if (argv_find(argv
, argc
, "all", &rd_all
))
1519 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1520 NULL
, SHOW_DISPLAY_TAGS
, 0);
1522 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1523 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1525 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1528 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1529 SHOW_DISPLAY_TAGS
, 0);
1532 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1533 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1534 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1540 "Detailed information on TCP and BGP neighbor connections\n"
1541 "IPv4 Neighbor to display information about\n"
1542 "IPv6 Neighbor to display information about\n"
1543 "Neighbor on BGP configured interface\n"
1544 "Display routes learned from neighbor\n" JSON_STR
)
1548 char *peerstr
= NULL
;
1549 bool uj
= use_json(argc
, argv
);
1550 afi_t afi
= AFI_L2VPN
;
1551 safi_t safi
= SAFI_EVPN
;
1552 struct bgp
*bgp
= NULL
;
1554 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1557 vty_out(vty
, "No index\n");
1561 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1562 argv_find(argv
, argc
, "neighbors", &idx
);
1563 peerstr
= argv
[++idx
]->arg
;
1565 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1568 json_object
*json_no
= NULL
;
1569 json_no
= json_object_new_object();
1570 json_object_string_add(json_no
, "warning",
1571 "Malformed address");
1572 vty_out(vty
, "%s\n",
1573 json_object_to_json_string(json_no
));
1574 json_object_free(json_no
);
1576 vty_out(vty
, "Malformed address: %s\n",
1580 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1582 json_object
*json_no
= NULL
;
1583 json_no
= json_object_new_object();
1584 json_object_string_add(
1586 "No such neighbor or address family");
1587 vty_out(vty
, "%s\n",
1588 json_object_to_json_string(json_no
));
1589 json_object_free(json_no
);
1591 vty_out(vty
, "%% No such neighbor or address family\n");
1595 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1596 SHOW_DISPLAY_STANDARD
, uj
);
1599 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1600 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1601 "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]",
1607 "Display information for a route distinguisher\n"
1608 "VPN Route Distinguisher\n"
1609 "All VPN Route Distinguishers\n"
1610 "Detailed information on TCP and BGP neighbor connections\n"
1611 "IPv4 Neighbor to display information about\n"
1612 "IPv6 Neighbor to display information about\n"
1613 "Neighbor on BGP configured interface\n"
1614 "Display routes learned from neighbor\n" JSON_STR
)
1616 int idx_ext_community
= 0;
1620 char *peerstr
= NULL
;
1621 struct prefix_rd prd
= {};
1622 bool uj
= use_json(argc
, argv
);
1623 afi_t afi
= AFI_L2VPN
;
1624 safi_t safi
= SAFI_EVPN
;
1625 struct bgp
*bgp
= NULL
;
1628 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1631 vty_out(vty
, "No index\n");
1635 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1636 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1637 &idx_ext_community
);
1638 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1641 json_object
*json_no
= NULL
;
1642 json_no
= json_object_new_object();
1643 json_object_string_add(
1645 "Malformed Route Distinguisher");
1646 vty_out(vty
, "%s\n",
1647 json_object_to_json_string(json_no
));
1648 json_object_free(json_no
);
1651 "%% Malformed Route Distinguisher\n");
1656 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1657 argv_find(argv
, argc
, "neighbors", &idx
);
1658 peerstr
= argv
[++idx
]->arg
;
1660 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1663 json_object
*json_no
= NULL
;
1664 json_no
= json_object_new_object();
1665 json_object_string_add(json_no
, "warning",
1666 "Malformed address");
1667 vty_out(vty
, "%s\n",
1668 json_object_to_json_string(json_no
));
1669 json_object_free(json_no
);
1671 vty_out(vty
, "Malformed address: %s\n",
1675 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1677 json_object
*json_no
= NULL
;
1678 json_no
= json_object_new_object();
1679 json_object_string_add(
1681 "No such neighbor or address family");
1682 vty_out(vty
, "%s\n",
1683 json_object_to_json_string(json_no
));
1684 json_object_free(json_no
);
1686 vty_out(vty
, "%% No such neighbor or address family\n");
1692 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1693 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1695 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1696 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1699 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1700 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1701 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1707 "Detailed information on TCP and BGP neighbor connections\n"
1708 "IPv4 Neighbor to display information about\n"
1709 "IPv6 Neighbor to display information about\n"
1710 "Neighbor on BGP configured interface\n"
1711 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1715 bool uj
= use_json(argc
, argv
);
1716 struct bgp
*bgp
= NULL
;
1717 afi_t afi
= AFI_L2VPN
;
1718 safi_t safi
= SAFI_EVPN
;
1719 char *peerstr
= NULL
;
1724 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1727 vty_out(vty
, "No index\n");
1731 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1732 argv_find(argv
, argc
, "neighbors", &idx
);
1733 peerstr
= argv
[++idx
]->arg
;
1735 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1738 json_object
*json_no
= NULL
;
1739 json_no
= json_object_new_object();
1740 json_object_string_add(json_no
, "warning",
1741 "Malformed address");
1742 vty_out(vty
, "%s\n",
1743 json_object_to_json_string(json_no
));
1744 json_object_free(json_no
);
1746 vty_out(vty
, "Malformed address: %s\n",
1750 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1752 json_object
*json_no
= NULL
;
1753 json_no
= json_object_new_object();
1754 json_object_string_add(
1756 "No such neighbor or address family");
1757 vty_out(vty
, "%s\n",
1758 json_object_to_json_string(json_no
));
1759 json_object_free(json_no
);
1761 vty_out(vty
, "%% No such neighbor or address family\n");
1765 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1768 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1769 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1770 "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]",
1776 "Display information for a route distinguisher\n"
1777 "VPN Route Distinguisher\n"
1778 "All VPN Route Distinguishers\n"
1779 "Detailed information on TCP and BGP neighbor connections\n"
1780 "IPv4 Neighbor to display information about\n"
1781 "IPv6 Neighbor to display information about\n"
1782 "Neighbor on BGP configured interface\n"
1783 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1785 int idx_ext_community
= 0;
1789 struct prefix_rd prd
;
1790 struct bgp
*bgp
= NULL
;
1791 bool uj
= use_json(argc
, argv
);
1792 char *peerstr
= NULL
;
1793 afi_t afi
= AFI_L2VPN
;
1794 safi_t safi
= SAFI_EVPN
;
1803 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1806 vty_out(vty
, "No index\n");
1810 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1811 argv_find(argv
, argc
, "neighbors", &idx
);
1812 peerstr
= argv
[++idx
]->arg
;
1814 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1817 json_object
*json_no
= NULL
;
1818 json_no
= json_object_new_object();
1819 json_object_string_add(json_no
, "warning",
1820 "Malformed address");
1821 vty_out(vty
, "%s\n",
1822 json_object_to_json_string(json_no
));
1823 json_object_free(json_no
);
1825 vty_out(vty
, "Malformed address: %s\n",
1829 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1831 json_object
*json_no
= NULL
;
1832 json_no
= json_object_new_object();
1833 json_object_string_add(
1835 "No such neighbor or address family");
1836 vty_out(vty
, "%s\n",
1837 json_object_to_json_string(json_no
));
1838 json_object_free(json_no
);
1840 vty_out(vty
, "%% No such neighbor or address family\n");
1844 if (argv_find(argv
, argc
, "all", &rd_all
))
1845 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1848 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1849 &idx_ext_community
);
1850 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1853 json_object
*json_no
= NULL
;
1854 json_no
= json_object_new_object();
1855 json_object_string_add(
1857 "Malformed Route Distinguisher");
1858 vty_out(vty
, "%s\n",
1859 json_object_to_json_string(json_no
));
1860 json_object_free(json_no
);
1863 "%% Malformed Route Distinguisher\n");
1868 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1871 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1872 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1873 "show [ip] bgp l2vpn evpn all overlay [json]",
1879 "Display information about all EVPN NLRIs\n"
1880 "Display BGP Overlay Information for prefixes\n"
1883 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1884 SHOW_DISPLAY_OVERLAY
,
1885 use_json(argc
, argv
));
1888 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1889 show_ip_bgp_evpn_rd_overlay_cmd
,
1890 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1896 "Display information for a route distinguisher\n"
1897 "VPN Route Distinguisher\n"
1898 "All VPN Route Distinguishers\n"
1899 "Display BGP Overlay Information for prefixes\n")
1901 int idx_ext_community
= 0;
1903 struct prefix_rd prd
;
1906 if (argv_find(argv
, argc
, "all", &rd_all
))
1907 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1908 NULL
, SHOW_DISPLAY_OVERLAY
,
1909 use_json(argc
, argv
));
1911 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1912 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1914 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1917 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1918 SHOW_DISPLAY_OVERLAY
,
1919 use_json(argc
, argv
));
1922 DEFUN(show_bgp_l2vpn_evpn_com
,
1923 show_bgp_l2vpn_evpn_com_cmd
,
1924 "show bgp l2vpn evpn \
1925 <community AA:NN|large-community AA:BB:CC> \
1926 [exact-match] [json]",
1931 "Display routes matching the community\n"
1932 "Community number where AA and NN are (0-65535)\n"
1933 "Display routes matching the large-community\n"
1934 "List of large-community numbers\n"
1935 "Exact match of the communities\n"
1940 const char *clist_number_or_name
;
1941 int show_type
= bgp_show_type_normal
;
1942 struct community
*com
;
1943 struct lcommunity
*lcom
;
1945 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1946 clist_number_or_name
= argv
[++idx
]->arg
;
1947 show_type
= bgp_show_type_lcommunity
;
1949 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1950 show_type
= bgp_show_type_lcommunity_exact
;
1952 lcom
= lcommunity_str2com(clist_number_or_name
);
1954 vty_out(vty
, "%% Large-community malformed\n");
1958 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1959 SHOW_DISPLAY_STANDARD
,
1960 use_json(argc
, argv
));
1962 lcommunity_free(&lcom
);
1963 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1964 clist_number_or_name
= argv
[++idx
]->arg
;
1965 show_type
= bgp_show_type_community
;
1967 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1968 show_type
= bgp_show_type_community_exact
;
1970 com
= community_str2com(clist_number_or_name
);
1973 vty_out(vty
, "%% Community malformed: %s\n",
1974 clist_number_or_name
);
1978 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1979 SHOW_DISPLAY_STANDARD
,
1980 use_json(argc
, argv
));
1981 community_free(&com
);
1987 /* For testing purpose, static route of EVPN RT-5. */
1988 DEFUN(evpnrt5_network
,
1989 evpnrt5_network_cmd
,
1990 "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]",
1991 "Specify a network to announce via BGP\n"
1994 "Specify Route Distinguisher\n"
1995 "VPN Route Distinguisher\n"
1997 "Ethernet Tag Value\n"
2000 "Ethernet Segment Identifier\n"
2001 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2003 "Gateway IP ( A.B.C.D )\n"
2004 "Gateway IPv6 ( X:X::X:X )\n"
2005 "Router Mac Ext Comm\n"
2006 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
2007 "Route-map to modify the attributes\n"
2008 "Name of the route map\n")
2010 int idx_ipv4_prefixlen
= 1;
2011 int idx_route_distinguisher
= 3;
2016 int idx_routermac
= 13;
2018 return bgp_static_set_safi(
2019 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2020 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
2021 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2022 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
2023 argv
[idx_routermac
]->arg
);
2026 /* For testing purpose, static route of EVPN RT-5. */
2027 DEFUN(no_evpnrt5_network
,
2028 no_evpnrt5_network_cmd
,
2029 "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>",
2031 "Specify a network to announce via BGP\n"
2034 "Specify Route Distinguisher\n"
2035 "VPN Route Distinguisher\n"
2037 "Ethernet Tag Value\n"
2040 "Ethernet Segment Identifier\n"
2041 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2042 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2044 int idx_ipv4_prefixlen
= 2;
2045 int idx_ext_community
= 4;
2050 return bgp_static_unset_safi(
2051 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2052 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2053 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2054 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2057 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2059 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
, false);
2062 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2064 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
, false);
2068 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2069 * check that this is a change.
2071 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2072 struct ecommunity
*ecomadd
)
2074 /* If the VNI is "live", we need to uninstall routes using the current
2075 * import RT(s) first before we update the import RT, and subsequently
2078 if (is_vni_live(vpn
))
2079 bgp_evpn_uninstall_routes(bgp
, vpn
);
2081 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2082 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2084 /* If the auto route-target is in use we must remove it */
2085 evpn_import_rt_delete_auto(bgp
, vpn
);
2087 /* Add new RT and rebuild the RT to VNI mapping */
2088 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2090 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2091 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2093 /* Install routes that match new import RT */
2094 if (is_vni_live(vpn
))
2095 bgp_evpn_install_routes(bgp
, vpn
);
2099 * Unconfigure Import RT(s) for a VNI (vty handler).
2101 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2102 struct ecommunity
*ecomdel
)
2104 struct listnode
*node
, *nnode
, *node_to_del
;
2105 struct ecommunity
*ecom
;
2107 /* Along the lines of "configure" except we have to reset to the
2110 if (is_vni_live(vpn
))
2111 bgp_evpn_uninstall_routes(bgp
, vpn
);
2113 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2114 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2116 /* Delete all import RTs */
2117 if (ecomdel
== NULL
) {
2118 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2119 ecommunity_free(&ecom
);
2120 list_delete_node(vpn
->import_rtl
, node
);
2124 /* Delete a specific import RT */
2128 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2129 if (ecommunity_match(ecom
, ecomdel
)) {
2130 ecommunity_free(&ecom
);
2137 list_delete_node(vpn
->import_rtl
, node_to_del
);
2140 assert(vpn
->import_rtl
);
2141 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2142 if (list_isempty(vpn
->import_rtl
)) {
2143 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2144 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2146 /* Rebuild the RT to VNI mapping */
2148 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2150 /* Install routes that match new import RT */
2151 if (is_vni_live(vpn
))
2152 bgp_evpn_install_routes(bgp
, vpn
);
2156 * Configure the Export RT for a VNI (vty handler). Caller expected to
2157 * check that this is a change. Note that only a single export RT is
2158 * allowed for a VNI and any change to configuration is implemented as
2159 * a "replace" (similar to other configuration).
2161 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2162 struct ecommunity
*ecomadd
)
2164 /* If the auto route-target is in use we must remove it */
2165 evpn_export_rt_delete_auto(bgp
, vpn
);
2167 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2168 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2170 if (is_vni_live(vpn
))
2171 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2175 * Unconfigure the Export RT for a VNI (vty handler)
2177 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2178 struct ecommunity
*ecomdel
)
2180 struct listnode
*node
, *nnode
, *node_to_del
;
2181 struct ecommunity
*ecom
;
2183 /* Delete all export RTs */
2184 if (ecomdel
== NULL
) {
2185 /* Reset to default and process all routes. */
2186 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2187 ecommunity_free(&ecom
);
2188 list_delete_node(vpn
->export_rtl
, node
);
2192 /* Delete a specific export RT */
2196 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2197 if (ecommunity_match(ecom
, ecomdel
)) {
2198 ecommunity_free(&ecom
);
2205 list_delete_node(vpn
->export_rtl
, node_to_del
);
2208 assert(vpn
->export_rtl
);
2209 if (list_isempty(vpn
->export_rtl
)) {
2210 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2211 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2214 if (is_vni_live(vpn
))
2215 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2219 * Configure RD for VRF
2221 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2223 /* If we have already advertise type-5 routes with a diffrent RD, we
2224 * have to delete and withdraw them firs
2226 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2229 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2230 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2232 /* We have a new RD for VRF.
2233 * Advertise all type-5 routes again with the new RD
2235 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2239 * Unconfigure RD for VRF
2241 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2243 /* If we have already advertise type-5 routes with a diffrent RD, we
2244 * have to delete and withdraw them firs
2246 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2248 /* fall back to default RD */
2249 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2250 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2252 /* We have a new RD for VRF.
2253 * Advertise all type-5 routes again with the new RD
2255 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2259 * Configure RD for a VNI (vty handler)
2261 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2262 struct prefix_rd
*rd
)
2264 /* If the VNI is "live", we need to delete and withdraw this VNI's
2265 * local routes with the prior RD first. Then, after updating RD,
2266 * need to re-advertise.
2268 if (is_vni_live(vpn
))
2269 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2272 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2273 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2275 if (is_vni_live(vpn
))
2276 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2280 * Unconfigure RD for a VNI (vty handler)
2282 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2284 /* If the VNI is "live", we need to delete and withdraw this VNI's
2285 * local routes with the prior RD first. Then, after resetting RD
2286 * to automatic value, need to re-advertise.
2288 if (is_vni_live(vpn
))
2289 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2291 /* reset RD to default */
2292 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2294 if (is_vni_live(vpn
))
2295 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2299 * Create VNI, if not already present (VTY handler). Mark as configured.
2301 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2303 struct bgpevpn
*vpn
;
2304 struct in_addr mcast_grp
= {INADDR_ANY
};
2306 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2308 /* Check if this L2VNI is already configured as L3VNI */
2309 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2312 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2317 /* tenant vrf will be updated when we get local_vni_add from
2320 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2323 /* Mark as configured. */
2324 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2329 * Delete VNI. If VNI does not exist in the system (i.e., just
2330 * configuration), all that is needed is to free it. Otherwise,
2331 * any parameters configured for the VNI need to be reset (with
2332 * appropriate action) and the VNI marked as unconfigured; the
2333 * VNI will continue to exist, purely as a "learnt" entity.
2335 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2337 if (!is_vni_live(vpn
)) {
2338 bgp_evpn_free(bgp
, vpn
);
2342 /* We need to take the unconfigure action for each parameter of this VNI
2343 * that is configured. Some optimization is possible, but not worth the
2344 * additional code for an operation that should be pretty rare.
2346 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2348 /* First, deal with the export side - RD and export RT changes. */
2349 if (is_rd_configured(vpn
))
2350 evpn_unconfigure_rd(bgp
, vpn
);
2351 if (is_export_rt_configured(vpn
))
2352 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2354 /* Next, deal with the import side. */
2355 if (is_import_rt_configured(vpn
))
2356 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2360 * Display import RT mapping to VRFs (vty handler)
2361 * bgp_evpn: evpn bgp instance
2363 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2371 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2372 (void (*)(struct hash_bucket
*,
2373 void *))show_vrf_import_rt_entry
,
2378 * Display import RT mapping to VNIs (vty handler)
2380 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2389 bgp
->import_rt_hash
,
2390 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2395 * Display EVPN routes for all VNIs - vty handler.
2397 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
, int type
,
2398 bool mac_table
, struct in_addr vtep_ip
,
2399 json_object
*json
, int detail
)
2402 struct vni_walk_ctx wctx
;
2404 num_vnis
= hashcount(bgp
->vnihash
);
2407 memset(&wctx
, 0, sizeof(wctx
));
2411 wctx
.mac_table
= mac_table
;
2412 wctx
.vtep_ip
= vtep_ip
;
2414 wctx
.detail
= detail
;
2415 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2416 void *))show_vni_routes_hash
,
2421 * Display EVPN routes for all VNIs & all types - vty handler.
2423 static void evpn_show_routes_vni_all_type_all(struct vty
*vty
, struct bgp
*bgp
,
2424 struct in_addr vtep_ip
,
2425 json_object
*json
, int detail
)
2428 struct vni_walk_ctx wctx
;
2430 num_vnis
= hashcount(bgp
->vnihash
);
2434 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2437 wctx
.vtep_ip
= vtep_ip
;
2439 wctx
.detail
= detail
;
2440 hash_iterate(bgp
->vnihash
,
2441 (void (*)(struct hash_bucket
*,
2442 void *))show_vni_routes_all_hash
,
2447 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2449 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2450 vni_t vni
, struct in_addr orig_ip
,
2453 struct bgpevpn
*vpn
;
2454 struct prefix_evpn p
;
2455 struct bgp_dest
*dest
;
2456 struct bgp_path_info
*pi
;
2457 uint32_t path_cnt
= 0;
2460 json_object
*json_paths
= NULL
;
2466 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2468 vty_out(vty
, "VNI not found\n");
2472 /* See if route exists. */
2473 build_evpn_type3_prefix(&p
, orig_ip
);
2474 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2475 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2477 vty_out(vty
, "%% Network not in table\n");
2480 bgp_dest_unlock_node(dest
);
2486 json_paths
= json_object_new_array();
2488 /* Prefix and num paths displayed once per prefix. */
2489 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2490 NULL
, afi
, safi
, json
);
2492 /* Display each path for this prefix. */
2493 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2494 json_object
*json_path
= NULL
;
2497 json_path
= json_object_new_array();
2499 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2500 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2504 json_object_array_add(json_paths
, json_path
);
2511 json_object_object_add(json
, "paths", json_paths
);
2513 json_object_int_add(json
, "numPaths", path_cnt
);
2515 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2519 bgp_dest_unlock_node(dest
);
2523 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2524 * By definition, only matching type-2 route will be displayed.
2526 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2527 vni_t vni
, struct ethaddr
*mac
,
2528 struct ipaddr
*ip
, json_object
*json
)
2530 struct bgpevpn
*vpn
;
2531 struct prefix_evpn p
;
2532 struct prefix_evpn tmp_p
;
2533 struct bgp_dest
*dest
;
2534 struct bgp_path_info
*pi
;
2535 uint32_t path_cnt
= 0;
2538 json_object
*json_paths
= NULL
;
2539 struct ethaddr empty_mac
= {};
2540 const struct prefix_evpn
*evp
;
2546 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2549 vty_out(vty
, "VNI not found\n");
2553 build_evpn_type2_prefix(&p
, mac
? mac
: &empty_mac
, ip
);
2555 /* See if route exists. Look for both non-sticky and sticky. */
2556 dest
= bgp_evpn_vni_node_lookup(vpn
, &p
, NULL
);
2557 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2559 vty_out(vty
, "%% Network not in table\n");
2562 bgp_dest_unlock_node(dest
);
2568 * MAC is per-path, we have to walk the path_info's and look for it
2572 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2573 if (memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2580 vty_out(vty
, "%% Network not in table\n");
2586 json_paths
= json_object_new_array();
2588 /* Prefix and num paths displayed once per prefix. */
2589 route_vty_out_detail_header(vty
, bgp
, dest
, (struct prefix
*)&p
, NULL
,
2592 evp
= (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2594 /* Display each path for this prefix. */
2595 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2596 json_object
*json_path
= NULL
;
2598 /* skip non-matching MACs */
2600 memcmp(mac
, evpn_type2_path_info_get_mac(pi
),
2605 json_path
= json_object_new_array();
2608 * VNI table MAC-IP prefixes don't have MAC so
2609 * make sure it's set from path info
2612 if (is_evpn_prefix_ipaddr_none(evp
)) {
2613 /* VNI MAC -> Global */
2614 evpn_type2_prefix_global_copy(
2615 (struct prefix_evpn
*)&tmp_p
, evp
,
2617 evpn_type2_path_info_get_ip(pi
));
2619 /* VNI IP -> Global */
2620 evpn_type2_prefix_global_copy(
2621 (struct prefix_evpn
*)&tmp_p
, evp
,
2622 evpn_type2_path_info_get_mac(pi
),
2626 route_vty_out_detail(vty
, bgp
, dest
, (struct prefix
*)&tmp_p
,
2627 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2631 json_object_array_add(json_paths
, json_path
);
2638 json_object_object_add(json
, "paths", json_paths
);
2640 json_object_int_add(json
, "numPaths", path_cnt
);
2642 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2646 bgp_dest_unlock_node(dest
);
2649 /* Disaplay EVPN routes for a ESI - VTY handler */
2650 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2651 esi_t
*esi
, json_object
*json
)
2653 struct bgp_evpn_es
*es
= NULL
;
2656 es
= bgp_evpn_es_find(esi
);
2659 vty_out(vty
, "ESI not found\n");
2663 show_esi_routes(bgp
, es
, vty
, json
);
2667 * Display EVPN routes for a VNI - vty handler.
2668 * If 'type' is non-zero, only routes matching that type are shown.
2669 * If the vtep_ip is non zero, only routes behind that vtep are shown
2671 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2672 int type
, bool mac_table
,
2673 struct in_addr vtep_ip
, json_object
*json
)
2675 struct bgpevpn
*vpn
;
2678 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2681 vty_out(vty
, "VNI not found\n");
2685 /* Walk this VNI's route table and display appropriate routes. */
2686 show_vni_routes(bgp
, vpn
, vty
, type
, mac_table
, vtep_ip
, json
, 0);
2690 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2691 * IP (vty handler). By definition, only matching type-2 route will be
2694 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2695 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2696 struct ipaddr
*ip
, json_object
*json
)
2698 struct prefix_evpn p
;
2699 struct bgp_dest
*dest
;
2700 struct bgp_path_info
*pi
;
2703 uint32_t path_cnt
= 0;
2704 json_object
*json_paths
= NULL
;
2709 /* See if route exists. Look for both non-sticky and sticky. */
2710 build_evpn_type2_prefix(&p
, mac
, ip
);
2711 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2712 (struct prefix
*)&p
, prd
);
2713 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2715 vty_out(vty
, "%% Network not in table\n");
2718 bgp_dest_unlock_node(dest
);
2723 /* Prefix and num paths displayed once per prefix. */
2724 route_vty_out_detail_header(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2725 prd
, afi
, safi
, json
);
2728 json_paths
= json_object_new_array();
2730 /* Display each path for this prefix. */
2731 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2732 json_object
*json_path
= NULL
;
2735 json_path
= json_object_new_array();
2737 route_vty_out_detail(vty
, bgp
, dest
, bgp_dest_get_prefix(dest
),
2738 pi
, afi
, safi
, RPKI_NOT_BEING_USED
,
2742 json_object_array_add(json_paths
, json_path
);
2747 if (json
&& path_cnt
) {
2749 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2750 json_object_int_add(json
, "numPaths", path_cnt
);
2752 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2756 bgp_dest_unlock_node(dest
);
2760 * Display BGP EVPN routing table -- for specific RD (vty handler)
2761 * If 'type' is non-zero, only routes matching that type are shown.
2763 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2764 struct prefix_rd
*prd
, int type
,
2767 struct bgp_dest
*rd_dest
;
2768 struct bgp_table
*table
;
2769 struct bgp_dest
*dest
;
2770 struct bgp_path_info
*pi
;
2774 uint32_t prefix_cnt
, path_cnt
;
2775 json_object
*json_rd
= NULL
;
2776 int add_rd_to_json
= 0;
2780 prefix_cnt
= path_cnt
= 0;
2782 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2786 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2787 if (table
== NULL
) {
2788 bgp_dest_unlock_node(rd_dest
);
2793 json_rd
= json_object_new_object();
2794 json_object_string_addf(json_rd
, "rd", "%pRD", prd
);
2797 bgp_dest_unlock_node(rd_dest
);
2799 /* Display all prefixes with this RD. */
2800 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2801 const struct prefix_evpn
*evp
=
2802 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2803 json_object
*json_prefix
= NULL
;
2804 json_object
*json_paths
= NULL
;
2805 int add_prefix_to_json
= 0;
2807 if (type
&& evp
->prefix
.route_type
!= type
)
2811 json_prefix
= json_object_new_object();
2813 pi
= bgp_dest_get_bgp_path_info(dest
);
2815 /* RD header and legend - once overall. */
2816 if (rd_header
&& !json
) {
2818 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2820 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2822 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2824 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2826 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2830 /* Prefix and num paths displayed once per prefix. */
2831 route_vty_out_detail_header(
2832 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), prd
,
2833 afi
, safi
, json_prefix
);
2839 json_paths
= json_object_new_array();
2841 /* Display each path for this prefix. */
2842 for (; pi
; pi
= pi
->next
) {
2843 json_object
*json_path
= NULL
;
2846 json_path
= json_object_new_array();
2848 route_vty_out_detail(
2849 vty
, bgp
, dest
, bgp_dest_get_prefix(dest
), pi
,
2850 afi
, safi
, RPKI_NOT_BEING_USED
, json_path
);
2853 json_object_array_add(json_paths
, json_path
);
2856 add_prefix_to_json
= 1;
2861 if (add_prefix_to_json
) {
2862 json_object_object_add(json_prefix
, "paths",
2864 json_object_object_addf(json_rd
, json_prefix
,
2867 json_object_free(json_paths
);
2868 json_object_free(json_prefix
);
2877 json_object_object_addf(json
, json_rd
, "%pRD", prd
);
2879 json_object_free(json_rd
);
2883 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2884 json_object_int_add(json
, "numPaths", path_cnt
);
2886 if (prefix_cnt
== 0)
2887 vty_out(vty
, "No prefixes exist with this RD%s\n",
2888 type
? " (of requested type)" : "");
2891 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2892 prefix_cnt
, path_cnt
,
2893 type
? " (of requested type)" : "");
2898 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2899 * (vty handler). Only matching type-2 routes will be displayed.
2901 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2902 struct ethaddr
*mac
, struct ipaddr
*ip
,
2905 struct bgp_dest
*rd_dest
;
2906 struct bgp_table
*table
;
2907 struct bgp_dest
*dest
;
2908 struct bgp_path_info
*pi
;
2909 afi_t afi
= AFI_L2VPN
;
2910 safi_t safi
= SAFI_EVPN
;
2911 uint32_t prefix_cnt
, path_cnt
;
2912 prefix_cnt
= path_cnt
= 0;
2914 /* EVPN routing table is a 2-level table with the first level being
2915 * the RD. We need to look in every RD we know about.
2917 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2918 rd_dest
= bgp_route_next(rd_dest
)) {
2919 json_object
*json_paths
= NULL
; /* paths array for prefix */
2920 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2921 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2922 char rd_str
[RD_ADDRSTRLEN
];
2923 int add_rd_to_json
= 0;
2924 struct prefix_evpn ep
;
2925 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2927 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2931 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2934 /* Construct an RT-2 from the user-supplied mac(ip),
2935 * then search the l2vpn evpn table for it.
2937 build_evpn_type2_prefix(&ep
, mac
, ip
);
2938 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2939 (struct prefix
*)&ep
,
2940 (struct prefix_rd
*)rd_destp
);
2945 json_rd
= json_object_new_object();
2947 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2949 pi
= bgp_dest_get_bgp_path_info(dest
);
2951 /* RD header - per RD. */
2952 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2953 rd_str
, RD_ADDRSTRLEN
);
2958 json_prefix
= json_object_new_object();
2959 json_paths
= json_object_new_array();
2960 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2962 json_object_int_add(json_prefix
, "prefixLen",
2965 /* Prefix and num paths displayed once per prefix. */
2966 route_vty_out_detail_header(
2967 vty
, bgp
, dest
, p
, (struct prefix_rd
*)rd_destp
,
2968 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2970 /* For EVPN, the prefix is displayed for each path (to
2971 * fit in with code that already exists).
2973 for (; pi
; pi
= pi
->next
) {
2974 json_object
*json_path
= NULL
;
2980 json_path
= json_object_new_array();
2982 route_vty_out_detail(vty
, bgp
, dest
, p
, pi
, AFI_L2VPN
,
2983 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2987 json_object_array_add(json_paths
, json_path
);
2993 json_object_object_add(json_prefix
, "paths",
2995 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
2998 json_object_object_add(json
, rd_str
, json_rd
);
3000 json_object_free(json_rd
);
3005 bgp_dest_unlock_node(dest
);
3009 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3010 json_object_int_add(json
, "numPaths", path_cnt
);
3012 if (prefix_cnt
== 0) {
3013 vty_out(vty
, "No Matching EVPN prefixes exist\n");
3015 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
3016 prefix_cnt
, path_cnt
);
3022 * Display BGP EVPN routing table - all routes (vty handler).
3023 * If 'type' is non-zero, only routes matching that type are shown.
3025 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
3026 json_object
*json
, int detail
)
3028 struct bgp_dest
*rd_dest
;
3029 struct bgp_table
*table
;
3030 struct bgp_dest
*dest
;
3031 struct bgp_path_info
*pi
;
3032 int header
= detail
? 0 : 1;
3036 uint32_t prefix_cnt
, path_cnt
;
3040 prefix_cnt
= path_cnt
= 0;
3042 /* EVPN routing table is a 2-level table with the first level being
3045 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
3046 rd_dest
= bgp_route_next(rd_dest
)) {
3047 char rd_str
[RD_ADDRSTRLEN
];
3048 json_object
*json_rd
= NULL
; /* contains routes for an RD */
3049 int add_rd_to_json
= 0;
3051 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
3053 table
= bgp_dest_get_bgp_table_info(rd_dest
);
3057 tbl_ver
= table
->version
;
3058 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
3062 json_rd
= json_object_new_object();
3066 /* Display all prefixes for an RD */
3067 for (dest
= bgp_table_top(table
); dest
;
3068 dest
= bgp_route_next(dest
)) {
3069 json_object
*json_prefix
=
3070 NULL
; /* contains prefix under a RD */
3071 json_object
*json_paths
=
3072 NULL
; /* array of paths under a prefix*/
3073 const struct prefix_evpn
*evp
=
3074 (const struct prefix_evpn
*)bgp_dest_get_prefix(
3076 int add_prefix_to_json
= 0;
3077 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
3079 if (type
&& evp
->prefix
.route_type
!= type
)
3082 pi
= bgp_dest_get_bgp_path_info(dest
);
3084 /* Overall header/legend displayed once. */
3086 bgp_evpn_show_route_header(vty
, bgp
,
3091 "%19s Extended Community\n"
3096 /* RD header - per RD. */
3098 bgp_evpn_show_route_rd_header(
3099 vty
, rd_dest
, json_rd
, rd_str
,
3108 json_prefix
= json_object_new_object();
3109 json_paths
= json_object_new_array();
3110 json_object_string_addf(json_prefix
, "prefix",
3112 json_object_int_add(json_prefix
, "prefixLen",
3116 /* Prefix and num paths displayed once per prefix. */
3118 route_vty_out_detail_header(
3120 bgp_dest_get_prefix(dest
),
3121 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3122 SAFI_EVPN
, json_prefix
);
3124 /* For EVPN, the prefix is displayed for each path (to
3126 * with code that already exists).
3128 for (; pi
; pi
= pi
->next
) {
3129 json_object
*json_path
= NULL
;
3132 add_prefix_to_json
= 1;
3136 json_path
= json_object_new_array();
3139 route_vty_out_detail(
3141 bgp_dest_get_prefix(dest
), pi
,
3142 AFI_L2VPN
, SAFI_EVPN
,
3143 RPKI_NOT_BEING_USED
, json_path
);
3145 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3149 json_object_array_add(json_paths
,
3154 if (add_prefix_to_json
) {
3155 json_object_object_add(json_prefix
,
3158 json_object_object_addf(json_rd
,
3162 json_object_free(json_prefix
);
3163 json_object_free(json_paths
);
3172 json_object_object_add(json
, rd_str
, json_rd
);
3174 json_object_free(json_rd
);
3181 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3182 json_object_int_add(json
, "numPaths", path_cnt
);
3184 if (prefix_cnt
== 0) {
3185 vty_out(vty
, "No EVPN prefixes %sexist\n",
3186 type
? "(of requested type) " : "");
3188 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3189 prefix_cnt
, path_cnt
,
3190 type
? " (of requested type)" : "");
3196 * Display specified VNI (vty handler)
3198 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3202 struct bgpevpn
*vpn
;
3204 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3207 display_vni(vty
, vpn
, json
);
3209 struct bgp
*bgp_temp
;
3210 struct listnode
*node
= NULL
;
3212 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3213 if (bgp_temp
->l3vni
== vni
) {
3215 display_l3vni(vty
, bgp_temp
, json
);
3222 vty_out(vty
, "{}\n");
3224 vty_out(vty
, "VNI not found\n");
3231 * Display a VNI (upon user query).
3233 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3237 struct bgp
*bgp_temp
= NULL
;
3238 struct listnode
*node
;
3242 vty_out(vty
, "Flags: * - Kernel\n");
3243 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3244 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3247 /* print all L2 VNIS */
3250 hash_iterate(bgp
->vnihash
,
3251 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3254 /* print all L3 VNIs */
3255 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3256 show_l3vni_entry(vty
, bgp_temp
, json
);
3260 * evpn - enable advertisement of svi MAC-IP
3262 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3266 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3268 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3271 bgp
->evpn_info
->advertise_svi_macip
= set
;
3272 bgp_zebra_advertise_svi_macip(bgp
,
3273 bgp
->evpn_info
->advertise_svi_macip
, 0);
3275 if (set
&& vpn
->advertise_svi_macip
)
3277 else if (!set
&& !vpn
->advertise_svi_macip
)
3280 vpn
->advertise_svi_macip
= set
;
3281 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3287 * evpn - enable advertisement of default g/w
3289 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3292 if (bgp
->advertise_gw_macip
)
3295 bgp
->advertise_gw_macip
= 1;
3296 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3298 if (vpn
->advertise_gw_macip
)
3301 vpn
->advertise_gw_macip
= 1;
3302 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3309 * evpn - disable advertisement of default g/w
3311 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3312 struct bgpevpn
*vpn
)
3315 if (!bgp
->advertise_gw_macip
)
3318 bgp
->advertise_gw_macip
= 0;
3319 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3321 if (!vpn
->advertise_gw_macip
)
3324 vpn
->advertise_gw_macip
= 0;
3325 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3332 * evpn - enable advertisement of default g/w
3334 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3335 afi_t afi
, bool add
)
3337 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3340 /* bail if we are already advertising default route */
3341 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3345 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3346 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3347 else if (afi
== AFI_IP6
)
3348 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3349 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3351 /* bail out if we havent advertised the default route */
3352 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3355 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3356 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3357 else if (afi
== AFI_IP6
)
3358 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3359 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3362 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3366 * evpn - enable advertisement of default g/w
3368 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3369 struct bgpevpn
*vpn
)
3371 if (vpn
->advertise_subnet
)
3374 vpn
->advertise_subnet
= 1;
3375 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3379 * evpn - disable advertisement of default g/w
3381 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3383 if (!vpn
->advertise_subnet
)
3386 vpn
->advertise_subnet
= 0;
3387 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3391 * EVPN (VNI advertisement) enabled. Register with zebra.
3393 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3395 bgp
->advertise_all_vni
= 1;
3397 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3401 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3402 * cache, EVPN routes (delete and withdraw from peers).
3404 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3406 bgp
->advertise_all_vni
= 0;
3407 bgp_set_evpn(bgp_get_default());
3408 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3409 bgp_evpn_cleanup_on_disable(bgp
);
3412 /* Set resolve overlay index flag */
3413 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3415 if (set
== bgp
->resolve_overlay_index
)
3419 bgp
->resolve_overlay_index
= true;
3420 hash_iterate(bgp
->vnihash
,
3421 (void (*)(struct hash_bucket
*, void *))
3422 bgp_evpn_handle_resolve_overlay_index_set
,
3427 (void (*)(struct hash_bucket
*, void *))
3428 bgp_evpn_handle_resolve_overlay_index_unset
,
3430 bgp
->resolve_overlay_index
= false;
3435 * EVPN - use RFC8365 to auto-derive RT
3437 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3439 bgp
->advertise_autort_rfc8365
= 1;
3440 bgp_evpn_handle_autort_change(bgp
);
3444 * EVPN - don't use RFC8365 to auto-derive RT
3446 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3448 bgp
->advertise_autort_rfc8365
= 0;
3449 bgp_evpn_handle_autort_change(bgp
);
3452 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3455 struct listnode
*node
, *nnode
;
3456 struct ecommunity
*ecom
;
3458 if (is_vni_configured(vpn
)) {
3459 vty_out(vty
, " vni %u\n", vpn
->vni
);
3460 if (is_rd_configured(vpn
))
3461 vty_out(vty
, " rd %pRD\n", &vpn
->prd
);
3463 if (is_import_rt_configured(vpn
)) {
3464 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3466 ecom_str
= ecommunity_ecom2str(
3467 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3468 vty_out(vty
, " route-target import %s\n",
3470 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3474 if (is_export_rt_configured(vpn
)) {
3475 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3477 ecom_str
= ecommunity_ecom2str(
3478 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3479 vty_out(vty
, " route-target export %s\n",
3481 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3485 if (vpn
->advertise_gw_macip
)
3486 vty_out(vty
, " advertise-default-gw\n");
3488 if (vpn
->advertise_svi_macip
)
3489 vty_out(vty
, " advertise-svi-ip\n");
3491 if (vpn
->advertise_subnet
)
3492 vty_out(vty
, " advertise-subnet\n");
3494 vty_out(vty
, " exit-vni\n");
3498 #include "bgpd/bgp_evpn_vty_clippy.c"
3500 DEFPY(bgp_evpn_flood_control
,
3501 bgp_evpn_flood_control_cmd
,
3502 "[no$no] flooding <disable$disable|head-end-replication$her>",
3504 "Specify handling for BUM packets\n"
3505 "Do not flood any BUM packets\n"
3506 "Flood BUM packets using head-end replication\n")
3508 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3509 enum vxlan_flood_control flood_ctrl
;
3515 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3517 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3521 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3524 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3525 bgp_evpn_flood_control_change(bgp
);
3530 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3531 bgp_evpn_advertise_default_gw_vni_cmd
,
3532 "advertise-default-gw",
3533 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3535 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3536 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3541 evpn_set_advertise_default_gw(bgp
, vpn
);
3546 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3547 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3548 "no advertise-default-gw",
3550 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3552 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3553 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3558 evpn_unset_advertise_default_gw(bgp
, vpn
);
3564 DEFUN (bgp_evpn_advertise_default_gw
,
3565 bgp_evpn_advertise_default_gw_cmd
,
3566 "advertise-default-gw",
3567 "Advertise All default g/w mac-ip routes in EVPN\n")
3569 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3574 if (!EVPN_ENABLED(bgp
)) {
3576 "This command is only supported under the EVPN VRF\n");
3580 evpn_set_advertise_default_gw(bgp
, NULL
);
3585 DEFUN (no_bgp_evpn_advertise_default_gw
,
3586 no_bgp_evpn_advertise_default_gw_cmd
,
3587 "no advertise-default-gw",
3589 "Withdraw All default g/w mac-ip routes from EVPN\n")
3591 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3596 evpn_unset_advertise_default_gw(bgp
, NULL
);
3601 DEFUN (bgp_evpn_advertise_all_vni
,
3602 bgp_evpn_advertise_all_vni_cmd
,
3603 "advertise-all-vni",
3604 "Advertise All local VNIs\n")
3606 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3607 struct bgp
*bgp_evpn
= NULL
;
3612 bgp_evpn
= bgp_get_evpn();
3613 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3614 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3615 bgp_evpn
->name_pretty
);
3616 return CMD_WARNING_CONFIG_FAILED
;
3619 evpn_set_advertise_all_vni(bgp
);
3623 DEFUN (no_bgp_evpn_advertise_all_vni
,
3624 no_bgp_evpn_advertise_all_vni_cmd
,
3625 "no advertise-all-vni",
3627 "Advertise All local VNIs\n")
3629 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3633 evpn_unset_advertise_all_vni(bgp
);
3637 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3638 bgp_evpn_advertise_autort_rfc8365_cmd
,
3639 "autort rfc8365-compatible",
3640 "Auto-derivation of RT\n"
3641 "Auto-derivation of RT using RFC8365\n")
3643 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3647 evpn_set_advertise_autort_rfc8365(bgp
);
3651 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3652 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3653 "no autort rfc8365-compatible",
3655 "Auto-derivation of RT\n"
3656 "Auto-derivation of RT using RFC8365\n")
3658 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3662 evpn_unset_advertise_autort_rfc8365(bgp
);
3666 DEFUN (bgp_evpn_default_originate
,
3667 bgp_evpn_default_originate_cmd
,
3668 "default-originate <ipv4 | ipv6>",
3669 "originate a default route\n"
3670 "ipv4 address family\n"
3671 "ipv6 address family\n")
3675 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3679 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3680 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3684 DEFUN (no_bgp_evpn_default_originate
,
3685 no_bgp_evpn_default_originate_cmd
,
3686 "no default-originate <ipv4 | ipv6>",
3688 "withdraw a default route\n"
3689 "ipv4 address family\n"
3690 "ipv6 address family\n")
3694 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3698 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3699 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3703 DEFPY (dup_addr_detection
,
3704 dup_addr_detection_cmd
,
3705 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3706 "Duplicate address detection\n"
3707 "Max allowed moves before address detected as duplicate\n"
3708 "Num of max allowed moves (2-1000) default 5\n"
3709 "Duplicate address detection time\n"
3710 "Time in seconds (2-1800) default 180\n")
3712 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3717 if (!EVPN_ENABLED(bgp_vrf
)) {
3719 "This command is only supported under the EVPN VRF\n");
3723 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3726 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3728 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3730 bgp_zebra_dup_addr_detection(bgp_vrf
);
3735 DEFPY (dup_addr_detection_auto_recovery
,
3736 dup_addr_detection_auto_recovery_cmd
,
3737 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3738 "Duplicate address detection\n"
3739 "Duplicate address detection freeze\n"
3740 "Duplicate address detection permanent freeze\n"
3741 "Duplicate address detection freeze time (30-3600)\n")
3743 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3744 uint32_t freeze_time
= freeze_time_val
;
3749 if (!EVPN_ENABLED(bgp_vrf
)) {
3751 "This command is only supported under the EVPN VRF\n");
3755 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3756 bgp_vrf
->evpn_info
->dad_freeze
= true;
3757 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3759 bgp_zebra_dup_addr_detection(bgp_vrf
);
3764 DEFPY (no_dup_addr_detection
,
3765 no_dup_addr_detection_cmd
,
3766 "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>]",
3768 "Duplicate address detection\n"
3769 "Max allowed moves before address detected as duplicate\n"
3770 "Num of max allowed moves (2-1000) default 5\n"
3771 "Duplicate address detection time\n"
3772 "Time in seconds (2-1800) default 180\n"
3773 "Duplicate address detection freeze\n"
3774 "Duplicate address detection permanent freeze\n"
3775 "Duplicate address detection freeze time (30-3600)\n")
3777 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3778 uint32_t max_moves
= (uint32_t)max_moves_val
;
3779 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3784 if (!EVPN_ENABLED(bgp_vrf
)) {
3786 "This command is only supported under the EVPN VRF\n");
3791 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3793 /* Reset all parameters to default. */
3794 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3795 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3796 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3797 bgp_vrf
->evpn_info
->dad_freeze
= false;
3798 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3801 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3803 "%% Value does not match with config\n");
3806 bgp_vrf
->evpn_info
->dad_max_moves
=
3807 EVPN_DAD_DEFAULT_MAX_MOVES
;
3811 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3813 "%% Value does not match with config\n");
3816 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3820 if (bgp_vrf
->evpn_info
->dad_freeze_time
3823 "%% Value does not match with config\n");
3826 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3827 bgp_vrf
->evpn_info
->dad_freeze
= false;
3830 if (permanent_val
) {
3831 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3833 "%% Value does not match with config\n");
3836 bgp_vrf
->evpn_info
->dad_freeze
= false;
3840 bgp_zebra_dup_addr_detection(bgp_vrf
);
3845 DEFPY(bgp_evpn_advertise_svi_ip
,
3846 bgp_evpn_advertise_svi_ip_cmd
,
3847 "[no$no] advertise-svi-ip",
3849 "Advertise svi mac-ip routes in EVPN\n")
3851 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3857 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3859 if (!EVPN_ENABLED(bgp
)) {
3861 "This command is only supported under EVPN VRF\n");
3864 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3870 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3871 bgp_evpn_advertise_svi_ip_vni_cmd
,
3872 "[no$no] advertise-svi-ip",
3874 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3876 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3877 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3883 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3885 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3890 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3891 bgp_evpn_advertise_vni_subnet_cmd
,
3893 "Advertise the subnet corresponding to VNI\n")
3895 struct bgp
*bgp_vrf
= NULL
;
3896 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3897 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3902 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3906 evpn_set_advertise_subnet(bgp
, vpn
);
3910 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3911 no_bgp_evpn_advertise_vni_subnet_cmd
,
3912 "no advertise-subnet",
3914 "Advertise All local VNIs\n")
3916 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3917 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3922 evpn_unset_advertise_subnet(bgp
, vpn
);
3926 DEFUN (bgp_evpn_advertise_type5
,
3927 bgp_evpn_advertise_type5_cmd
,
3928 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3929 "Advertise prefix routes\n"
3932 "advertise gateway IP overlay index\n"
3933 "route-map for filtering specific routes\n"
3934 "Name of the route map\n")
3936 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3943 int rmap_changed
= 0;
3944 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3946 bool adv_flag_changed
= false;
3948 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3949 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3950 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3952 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3954 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3956 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3957 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3960 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3964 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3966 "%% Only ipv4 or ipv6 address families are supported\n");
3970 if (safi
!= SAFI_UNICAST
) {
3972 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3976 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3977 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3978 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3982 if (afi
== AFI_IP
) {
3983 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3984 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3985 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3986 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3989 * this is the case for first time ever configuration
3990 * adv ipv4 unicast is enabled for the first time.
3991 * So no need to reset any flag
3993 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3995 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3996 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3997 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3999 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4000 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4001 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4003 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4004 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
4007 * This is modify case from gateway-ip
4008 * to no overlay index
4010 adv_flag_changed
= true;
4011 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4012 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4013 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4014 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4015 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4017 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4018 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4021 * This is modify case from no overlay index
4024 adv_flag_changed
= true;
4025 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4027 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4028 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4032 * Command is issued with the same option
4033 * (no overlay index or gateway-ip) which was
4034 * already configured. So nothing to do.
4035 * However, route-map may have been modified.
4036 * check if route-map has been modified.
4037 * If not, return an error
4043 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4044 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
4045 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4046 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4049 * this is the case for first time ever configuration
4050 * adv ipv6 unicast is enabled for the first time.
4051 * So no need to reset any flag
4053 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
4055 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4056 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4057 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
4059 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4060 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4061 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
4063 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4064 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
4067 * This is modify case from gateway-ip
4068 * to no overlay index
4070 adv_flag_changed
= true;
4071 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4072 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4073 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4074 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4075 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
4077 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4078 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4081 * This is modify case from no overlay index
4084 adv_flag_changed
= true;
4085 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4086 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4087 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4088 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4092 * Command is issued with the same option
4093 * (no overlay index or gateway-ip) which was
4094 * already configured. So nothing to do.
4095 * However, route-map may have been modified.
4096 * check if route-map has been modified.
4097 * If not, return an error
4104 if ((rmap_changed
) || (adv_flag_changed
)) {
4106 /* If either of these are changed, then FRR needs to
4107 * withdraw already advertised type5 routes.
4109 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4111 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4112 XFREE(MTYPE_ROUTE_MAP_NAME
,
4113 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4114 route_map_counter_decrement(
4115 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4116 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4117 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4122 /* set the route-map for advertise command */
4123 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4124 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4125 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4126 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4127 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4128 route_map_counter_increment(
4129 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4132 /* advertise type-5 routes */
4133 if (advertise_type5_routes(bgp_vrf
, afi
))
4134 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4138 DEFUN (no_bgp_evpn_advertise_type5
,
4139 no_bgp_evpn_advertise_type5_cmd
,
4140 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
4142 "Advertise prefix routes\n"
4145 "route-map for filtering specific routes\n"
4146 "Name of the route map\n")
4148 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4157 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4158 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4160 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4162 "%% Only ipv4 or ipv6 address families are supported\n");
4166 if (safi
!= SAFI_UNICAST
) {
4168 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4172 if (afi
== AFI_IP
) {
4174 /* if we are not advertising ipv4 prefix as type-5
4177 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4178 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4179 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4180 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4181 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4182 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4183 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4184 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4185 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4189 /* if we are not advertising ipv6 prefix as type-5
4192 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4193 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4194 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4195 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4196 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4197 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4198 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4199 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4200 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4204 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4205 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4206 XFREE(MTYPE_ROUTE_MAP_NAME
,
4207 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4208 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4209 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4215 DEFPY (bgp_evpn_use_es_l3nhg
,
4216 bgp_evpn_use_es_l3nhg_cmd
,
4217 "[no$no] use-es-l3nhg",
4219 "use L3 nexthop group for host routes with ES destination\n")
4221 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4225 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4226 bgp_evpn_ead_evi_rx_disable_cmd
,
4227 "[no$no] disable-ead-evi-rx",
4229 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4231 bool ead_evi_rx
= no
? true :false;
4233 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4234 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4235 bgp_evpn_switch_ead_evi_rx();
4240 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4241 bgp_evpn_ead_evi_tx_disable_cmd
,
4242 "[no$no] disable-ead-evi-tx",
4244 "Don't advertise EAD-EVI for local ESs\n")
4246 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4250 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4251 bgp_evpn_enable_resolve_overlay_index_cmd
,
4252 "[no$no] enable-resolve-overlay-index",
4254 "Enable Recursive Resolution of type-5 route overlay index\n")
4256 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4258 if (bgp
!= bgp_get_evpn()) {
4259 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4263 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4267 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4268 bgp_evpn_advertise_pip_ip_mac_cmd
,
4269 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4271 "evpn system primary IP\n"
4274 MAC_STR MAC_STR MAC_STR
)
4276 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4277 struct bgp
*bgp_evpn
= NULL
;
4279 if (EVPN_ENABLED(bgp_vrf
)) {
4281 "This command is supported under L3VNI BGP EVPN VRF\n");
4282 return CMD_WARNING_CONFIG_FAILED
;
4284 bgp_evpn
= bgp_get_evpn();
4287 /* pip is already enabled */
4288 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4291 bgp_vrf
->evpn_info
->advertise_pip
= true;
4292 if (ip
.s_addr
!= INADDR_ANY
) {
4293 /* Already configured with same IP */
4294 if (IPV4_ADDR_SAME(&ip
,
4295 &bgp_vrf
->evpn_info
->pip_ip_static
))
4298 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4299 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4301 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4303 /* default instance router-id assignemt */
4305 bgp_vrf
->evpn_info
->pip_ip
=
4306 bgp_evpn
->router_id
;
4309 if (!is_zero_mac(&mac
->eth_addr
)) {
4310 /* Already configured with same MAC */
4311 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4312 &mac
->eth_addr
, ETH_ALEN
) == 0)
4315 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4316 &mac
->eth_addr
, ETH_ALEN
);
4317 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4318 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4321 /* Copy zebra sys mac */
4322 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4323 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4324 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4329 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4331 /* Disable PIP feature */
4332 bgp_vrf
->evpn_info
->advertise_pip
= false;
4333 /* copy anycast mac */
4334 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4335 &bgp_vrf
->rmac
, ETH_ALEN
);
4337 /* remove MAC-IP option retain PIP knob. */
4338 if ((ip
.s_addr
!= INADDR_ANY
) &&
4339 !IPV4_ADDR_SAME(&ip
,
4340 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4342 "%% BGP EVPN PIP IP does not match\n");
4343 return CMD_WARNING_CONFIG_FAILED
;
4346 if (!is_zero_mac(&mac
->eth_addr
) &&
4347 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4348 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4350 "%% BGP EVPN PIP MAC does not match\n");
4351 return CMD_WARNING_CONFIG_FAILED
;
4353 /* pip_rmac can carry vrr_rmac reset only if it matches
4354 * with static value.
4356 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4357 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4359 /* Copy zebra sys mac */
4361 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4362 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4363 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4366 /* copy anycast mac */
4367 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4368 &bgp_vrf
->rmac
, ETH_ALEN
);
4372 /* reset user configured sys MAC */
4373 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4374 /* reset user configured sys IP */
4375 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4376 /* Assign default PIP IP (bgp instance router-id) */
4378 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4380 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4383 if (is_evpn_enabled()) {
4384 struct listnode
*node
= NULL
;
4385 struct bgpevpn
*vpn
= NULL
;
4388 * At this point if bgp_evpn is NULL and evpn is enabled
4389 * something stupid has gone wrong
4393 update_advertise_vrf_routes(bgp_vrf
);
4395 /* Update (svi) type-2 routes */
4396 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4397 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4399 update_routes_for_vni(bgp_evpn
, vpn
);
4407 * Display VNI information - for all or a specific VNI
4409 DEFUN(show_bgp_l2vpn_evpn_vni
,
4410 show_bgp_l2vpn_evpn_vni_cmd
,
4411 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4420 struct bgp
*bgp_evpn
;
4424 json_object
*json
= NULL
;
4425 uint32_t num_l2vnis
= 0;
4426 uint32_t num_l3vnis
= 0;
4427 uint32_t num_vnis
= 0;
4428 struct listnode
*node
= NULL
;
4429 struct bgp
*bgp_temp
= NULL
;
4431 uj
= use_json(argc
, argv
);
4433 bgp_evpn
= bgp_get_evpn();
4437 if (!argv_find(argv
, argc
, "evpn", &idx
))
4441 json
= json_object_new_object();
4443 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4445 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4447 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4448 if (bgp_temp
->l3vni
)
4451 num_vnis
= num_l2vnis
+ num_l3vnis
;
4453 json_object_string_add(json
, "advertiseGatewayMacip",
4454 bgp_evpn
->advertise_gw_macip
4457 json_object_string_add(json
, "advertiseSviMacIp",
4458 bgp_evpn
->evpn_info
->advertise_svi_macip
4459 ? "Enabled" : "Disabled");
4460 json_object_string_add(json
, "advertiseAllVnis",
4461 is_evpn_enabled() ? "Enabled"
4463 json_object_string_add(
4465 bgp_evpn
->vxlan_flood_ctrl
==
4466 VXLAN_FLOOD_HEAD_END_REPL
4467 ? "Head-end replication"
4469 json_object_string_add(
4470 json
, "vxlanFlooding",
4471 bgp_evpn
->vxlan_flood_ctrl
==
4472 VXLAN_FLOOD_HEAD_END_REPL
4475 json_object_int_add(json
, "numVnis", num_vnis
);
4476 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4477 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4479 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4480 bgp_evpn
->advertise_gw_macip
? "Enabled"
4482 vty_out(vty
, "Advertise SVI Macip: %s\n",
4483 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4485 vty_out(vty
, "Advertise All VNI flag: %s\n",
4486 is_evpn_enabled() ? "Enabled" : "Disabled");
4487 vty_out(vty
, "BUM flooding: %s\n",
4488 bgp_evpn
->vxlan_flood_ctrl
==
4489 VXLAN_FLOOD_HEAD_END_REPL
4490 ? "Head-end replication"
4492 vty_out(vty
, "VXLAN flooding: %s\n",
4493 bgp_evpn
->vxlan_flood_ctrl
==
4494 VXLAN_FLOOD_HEAD_END_REPL
4497 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4498 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4500 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4504 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4507 /* Display specific VNI */
4508 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4509 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4513 vty_json(vty
, json
);
4518 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4519 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4520 "show bgp l2vpn evpn vni remote-ip-hash",
4528 struct bgp
*bgp_evpn
;
4531 bgp_evpn
= bgp_get_evpn();
4535 if (!argv_find(argv
, argc
, "evpn", &idx
))
4538 hash_iterate(bgp_evpn
->vnihash
,
4539 (void (*)(struct hash_bucket
*,
4540 void *))bgp_evpn_show_remote_ip_hash
,
4546 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4547 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4548 "show bgp l2vpn evpn vni-svi-hash",
4553 "Show vni-svi-hash\n")
4555 struct bgp
*bgp_evpn
;
4558 bgp_evpn
= bgp_get_evpn();
4562 if (!argv_find(argv
, argc
, "evpn", &idx
))
4565 hash_iterate(bgp_evpn
->vni_svi_hash
,
4566 (void (*)(struct hash_bucket
*,
4567 void *))bgp_evpn_show_vni_svi_hash
,
4573 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4574 show_bgp_l2vpn_evpn_es_evi_cmd
,
4575 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4581 "VxLAN Network Identifier\n"
4584 "Detailed information\n")
4587 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4589 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4594 DEFPY(show_bgp_l2vpn_evpn_es
,
4595 show_bgp_l2vpn_evpn_es_cmd
,
4596 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4601 "Ethernet Segment\n"
4603 "Detailed information\n"
4609 if (!str_to_esi(esi_str
, &esi
)) {
4610 vty_out(vty
, "%% Malformed ESI\n");
4613 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4616 bgp_evpn_es_show(vty
, uj
, !!detail
);
4622 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4623 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4624 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4625 "Ethernet Segment\n"
4631 if (!str_to_esi(esi_str
, &esi
)) {
4632 vty_out(vty
, "%% Malformed ESI\n");
4635 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4638 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4644 DEFPY(show_bgp_l2vpn_evpn_nh
,
4645 show_bgp_l2vpn_evpn_nh_cmd
,
4646 "show bgp l2vpn evpn next-hops [json$uj]",
4654 bgp_evpn_nh_show(vty
, uj
);
4660 * Display EVPN neighbor summary.
4662 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4663 "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]",
4666 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4667 "Summary of BGP neighbor status\n"
4668 "Show only sessions in Established state\n"
4669 "Show only sessions not in Established state\n"
4670 "Show only the specified neighbor session\n"
4671 "Neighbor to display information about\n"
4672 "Neighbor to display information about\n"
4673 "Neighbor on BGP configured interface\n"
4674 "Show only the specified remote AS sessions\n"
4676 "Internal (iBGP) AS sessions\n"
4677 "External (eBGP) AS sessions\n"
4678 "Shorten the information on BGP instances\n"
4679 "Increase table width for longer output\n" JSON_STR
)
4684 char *neighbor
= NULL
;
4685 as_t as
= 0; /* 0 means AS filter not set */
4686 int as_type
= AS_UNSPECIFIED
;
4687 uint16_t show_flags
= 0;
4689 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4690 vrf
= argv
[++idx_vrf
]->arg
;
4692 if (argv_find(argv
, argc
, "failed", &idx
))
4693 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4695 if (argv_find(argv
, argc
, "established", &idx
))
4696 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4699 if (argv_find(argv
, argc
, "neighbor", &idx
))
4700 neighbor
= argv
[idx
+ 1]->arg
;
4702 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4703 if (argv
[idx
+ 1]->arg
[0] == 'i')
4704 as_type
= AS_INTERNAL
;
4705 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4706 as_type
= AS_EXTERNAL
;
4708 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4711 if (argv_find(argv
, argc
, "terse", &idx
))
4712 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4714 if (argv_find(argv
, argc
, "wide", &idx
))
4715 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4717 if (use_json(argc
, argv
))
4718 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4720 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4721 as_type
, as
, show_flags
);
4724 static int bgp_evpn_cli_parse_type_cmp(int *type
, const char *type_str
)
4726 if ((strncmp(type_str
, "ma", 2) == 0) || (strmatch(type_str
, "2")))
4727 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4728 else if ((strncmp(type_str
, "mu", 2) == 0) || (strmatch(type_str
, "3")))
4729 *type
= BGP_EVPN_IMET_ROUTE
;
4730 else if ((strncmp(type_str
, "es", 2) == 0) || (strmatch(type_str
, "4")))
4731 *type
= BGP_EVPN_ES_ROUTE
;
4732 else if ((strncmp(type_str
, "ea", 2) == 0) || (strmatch(type_str
, "1")))
4733 *type
= BGP_EVPN_AD_ROUTE
;
4734 else if ((strncmp(type_str
, "p", 1) == 0) || (strmatch(type_str
, "5")))
4735 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4742 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4746 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4747 /* Specific type is requested */
4748 if (bgp_evpn_cli_parse_type_cmp(type
,
4749 argv
[type_idx
+ 1]->arg
) != 0)
4757 * Display global EVPN routing table.
4759 DEFUN(show_bgp_l2vpn_evpn_route
,
4760 show_bgp_l2vpn_evpn_route_cmd
,
4761 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4767 "Display Detailed Information\n"
4769 EVPN_TYPE_ALL_LIST_HELP_STR
4776 json_object
*json
= NULL
;
4778 uj
= use_json(argc
, argv
);
4780 bgp
= bgp_get_evpn();
4785 json
= json_object_new_object();
4787 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4790 if (argv_find(argv
, argc
, "detail", &detail
))
4793 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4796 vty_json(vty
, json
);
4801 * Display global EVPN routing table for specific RD.
4803 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4804 show_bgp_l2vpn_evpn_route_rd_cmd
,
4805 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4811 EVPN_RT_DIST_HELP_STR
4812 EVPN_ASN_IP_HELP_STR
4813 "All VPN Route Distinguishers\n"
4815 EVPN_TYPE_ALL_LIST_HELP_STR
4820 struct prefix_rd prd
;
4823 json_object
*json
= NULL
;
4824 int idx_ext_community
= 0;
4827 bgp
= bgp_get_evpn();
4831 /* check if we need json output */
4832 uj
= use_json(argc
, argv
);
4834 json
= json_object_new_object();
4836 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4838 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4839 &idx_ext_community
)) {
4840 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4843 "%% Malformed Route Distinguisher\n");
4849 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4853 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4855 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4858 vty_json(vty
, json
);
4864 * Display global EVPN routing table for specific RD and MACIP.
4866 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4867 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4868 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4874 EVPN_RT_DIST_HELP_STR
4875 EVPN_ASN_IP_HELP_STR
4876 "All VPN Route Distinguishers\n"
4878 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4880 "IP address (IPv4 or IPv6)\n"
4885 struct prefix_rd prd
;
4888 int idx_ext_community
= 0;
4892 json_object
*json
= NULL
;
4895 memset(&mac
, 0, sizeof(struct ethaddr
));
4896 memset(&ip
, 0, sizeof(struct ipaddr
));
4898 bgp
= bgp_get_evpn();
4902 /* check if we need json output */
4903 uj
= use_json(argc
, argv
);
4905 json
= json_object_new_object();
4908 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4909 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4910 &idx_ext_community
)) {
4911 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4914 "%% Malformed Route Distinguisher\n");
4921 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4922 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4923 vty_out(vty
, "%% Malformed MAC address\n");
4928 /* get the ip if specified */
4929 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4930 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4931 vty_out(vty
, "%% Malformed IP address\n");
4937 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4939 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4942 vty_json(vty
, json
);
4947 /* Display per ESI routing table */
4948 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4949 show_bgp_l2vpn_evpn_route_esi_cmd
,
4950 "show bgp l2vpn evpn route esi ESI [json]",
4956 "Ethernet Segment Identifier\n"
4962 struct bgp
*bgp
= NULL
;
4963 json_object
*json
= NULL
;
4965 memset(&esi
, 0, sizeof(esi
));
4966 bgp
= bgp_get_evpn();
4970 uj
= use_json(argc
, argv
);
4972 json
= json_object_new_object();
4974 /* get the ESI - ESI-ID is at argv[6] */
4975 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4976 vty_out(vty
, "%% Malformed ESI\n");
4980 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4983 vty_json(vty
, json
);
4990 * Display per-VNI EVPN routing table.
4992 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4993 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4999 "VXLAN Network Identifier\n"
5002 EVPN_TYPE_1_HELP_STR
5003 EVPN_TYPE_1_HELP_STR
5004 EVPN_TYPE_2_HELP_STR
5005 EVPN_TYPE_2_HELP_STR
5006 EVPN_TYPE_3_HELP_STR
5007 EVPN_TYPE_3_HELP_STR
5009 "Remote VTEP IP address\n"
5014 struct in_addr vtep_ip
;
5019 json_object
*json
= NULL
;
5021 bgp
= bgp_get_evpn();
5025 /* check if we need json output */
5026 uj
= use_json(argc
, argv
);
5028 json
= json_object_new_object();
5030 if (!argv_find(argv
, argc
, "evpn", &idx
))
5035 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5037 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
5040 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
5041 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
5042 vty_out(vty
, "%% Malformed VTEP IP address\n");
5047 evpn_show_routes_vni(vty
, bgp
, vni
, type
, false, vtep_ip
, json
);
5050 vty_json(vty
, json
);
5056 * Display per-VNI EVPN routing table for specific MACIP.
5058 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
5059 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
5060 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
5066 "VXLAN Network Identifier\n"
5069 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5071 "IP address (IPv4 or IPv6)\n"
5080 json_object
*json
= NULL
;
5082 bgp
= bgp_get_evpn();
5086 /* check if we need json output */
5087 uj
= use_json(argc
, argv
);
5089 json
= json_object_new_object();
5091 if (!argv_find(argv
, argc
, "evpn", &idx
))
5095 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5098 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5099 vty_out(vty
, "%% Malformed MAC address\n");
5104 memset(&ip
, 0, sizeof(ip
));
5105 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5107 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5108 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5109 vty_out(vty
, "%% Malformed IP address\n");
5114 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5117 vty_json(vty
, json
);
5123 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5125 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5126 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5127 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5133 "VXLAN Network Identifier\n"
5135 EVPN_TYPE_3_HELP_STR
5136 "Originating Router IP address\n"
5142 struct in_addr orig_ip
;
5145 json_object
*json
= NULL
;
5147 bgp
= bgp_get_evpn();
5151 /* check if we need json output */
5152 uj
= use_json(argc
, argv
);
5154 json
= json_object_new_object();
5156 if (!argv_find(argv
, argc
, "evpn", &idx
))
5160 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5163 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5165 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5169 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5172 vty_json(vty
, json
);
5178 * Display per-VNI EVPN routing table - for all VNIs.
5180 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5181 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5182 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5188 "VXLAN Network Identifier\n"
5190 "Print Detailed Output\n"
5192 "Remote VTEP IP address\n"
5196 struct in_addr vtep_ip
;
5199 json_object
*json
= NULL
;
5200 /* Detail Adjust. Adjust indexes according to detail option */
5203 bgp
= bgp_get_evpn();
5207 /* check if we need json output */
5208 uj
= use_json(argc
, argv
);
5210 json
= json_object_new_object();
5212 if (!argv_find(argv
, argc
, "evpn", &idx
))
5215 if (argv_find(argv
, argc
, "detail", &da
))
5218 /* vtep-ip position depends on detail option */
5220 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5222 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5223 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5224 vty_out(vty
, "%% Malformed VTEP IP address\n");
5229 evpn_show_routes_vni_all(vty
, bgp
, 0, false, vtep_ip
, json
, da
);
5232 vty_json(vty
, json
);
5233 json_object_free(json
);
5240 * Display per-VNI EVPN ALL routing tables - for all VNIs.
5242 DEFPY(show_bgp_vni_all
,
5243 show_bgp_vni_all_cmd
,
5244 "show bgp vni all [vtep A.B.C.D$addr] [detail$detail] [json$uj]",
5255 json_object
*json
= NULL
;
5257 bgp
= bgp_get_evpn();
5261 /* check if we need json output */
5263 json
= json_object_new_object();
5265 evpn_show_routes_vni_all_type_all(vty
, bgp
, addr
, json
, !!detail
);
5268 vty_json(vty
, json
);
5274 * Display per-VNI EVPN EAD routing table - for all VNIs.
5276 DEFPY(show_bgp_vni_all_ead
,
5277 show_bgp_vni_all_ead_cmd
,
5278 "show bgp vni all type <1|ead> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5284 EVPN_TYPE_1_HELP_STR
5285 EVPN_TYPE_1_HELP_STR
5292 json_object
*json
= NULL
;
5294 bgp
= bgp_get_evpn();
5298 /* check if we need json output */
5300 json
= json_object_new_object();
5302 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_AD_ROUTE
, false, addr
, json
,
5306 vty_json(vty
, json
);
5312 * Display per-VNI EVPN MAC routing table - for all VNIs.
5314 DEFPY(show_bgp_vni_all_macip_mac
,
5315 show_bgp_vni_all_macip_mac_cmd
,
5316 "show bgp vni all type <2|macip> mac [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5322 EVPN_TYPE_2_HELP_STR
5323 EVPN_TYPE_2_HELP_STR
5331 json_object
*json
= NULL
;
5333 bgp
= bgp_get_evpn();
5337 /* check if we need json output */
5339 json
= json_object_new_object();
5341 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5345 vty_json(vty
, json
);
5351 * Display per-VNI EVPN IP routing table - for all VNIs.
5353 DEFPY(show_bgp_vni_all_macip_ip
,
5354 show_bgp_vni_all_macip_ip_cmd
,
5355 "show bgp vni all type <2|macip> ip [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5361 EVPN_TYPE_2_HELP_STR
5362 EVPN_TYPE_2_HELP_STR
5370 json_object
*json
= NULL
;
5372 bgp
= bgp_get_evpn();
5376 /* check if we need json output */
5378 json
= json_object_new_object();
5380 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5384 vty_json(vty
, json
);
5390 * Display per-VNI EVPN Multicast routing table - for all VNIs.
5392 DEFPY(show_bgp_vni_all_imet
,
5393 show_bgp_vni_all_imet_cmd
,
5394 "show bgp vni all type <3|multicast> [vtep A.B.C.D$addr] [<detail$detail|json$uj>]",
5400 EVPN_TYPE_3_HELP_STR
5401 EVPN_TYPE_3_HELP_STR
5408 json_object
*json
= NULL
;
5410 bgp
= bgp_get_evpn();
5414 /* check if we need json output */
5416 json
= json_object_new_object();
5418 evpn_show_routes_vni_all(vty
, bgp
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5422 vty_json(vty
, json
);
5428 * Display per-VNI EVPN ALL routing tables - for select VNI
5432 "show bgp vni "CMD_VNI_RANGE
"$vni [vtep A.B.C.D$addr] [json$uj]",
5442 json_object
*json
= NULL
;
5443 json_object
*json_mac
= NULL
;
5445 bgp
= bgp_get_evpn();
5449 /* check if we need json output */
5451 json
= json_object_new_object();
5452 json_mac
= json_object_new_object();
5455 evpn_show_routes_vni(vty
, bgp
, vni
, 0, false, addr
, json
);
5458 vty_out(vty
, "\n\nMAC Table:\n\n");
5460 evpn_show_routes_vni(vty
, bgp
, vni
, 0, true, addr
, json_mac
);
5463 json_object_object_add(json
, "macTable", json_mac
);
5464 vty_json(vty
, json
);
5471 * Display per-VNI EVPN EAD routing table - for select VNI
5473 DEFPY(show_bgp_vni_ead
,
5474 show_bgp_vni_ead_cmd
,
5475 "show bgp vni "CMD_VNI_RANGE
"$vni type <1|ead> [vtep A.B.C.D$addr] [json$uj]",
5481 EVPN_TYPE_1_HELP_STR
5482 EVPN_TYPE_1_HELP_STR
5488 json_object
*json
= NULL
;
5490 bgp
= bgp_get_evpn();
5494 /* check if we need json output */
5496 json
= json_object_new_object();
5498 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_AD_ROUTE
, false, addr
,
5502 vty_json(vty
, json
);
5508 * Display per-VNI EVPN MAC-IP MAC routing table - for select VNI
5510 DEFPY(show_bgp_vni_macip_mac
,
5511 show_bgp_vni_macip_mac_cmd
,
5512 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac [vtep A.B.C.D$addr] [json$uj]",
5518 EVPN_TYPE_2_HELP_STR
5519 EVPN_TYPE_2_HELP_STR
5526 json_object
*json
= NULL
;
5528 bgp
= bgp_get_evpn();
5532 /* check if we need json output */
5534 json
= json_object_new_object();
5536 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, true, addr
,
5540 vty_json(vty
, json
);
5546 * Display per-VNI EVPN MAC-IP IP routing table - for select VNI
5548 DEFPY(show_bgp_vni_macip_ip
,
5549 show_bgp_vni_macip_ip_cmd
,
5550 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> ip [vtep A.B.C.D$addr] [json$uj]",
5556 EVPN_TYPE_2_HELP_STR
5557 EVPN_TYPE_2_HELP_STR
5564 json_object
*json
= NULL
;
5566 bgp
= bgp_get_evpn();
5570 /* check if we need json output */
5572 json
= json_object_new_object();
5574 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_MAC_IP_ROUTE
, false, addr
,
5578 vty_json(vty
, json
);
5584 * Display per-VNI EVPN Multicast routing table - for select VNI
5586 DEFPY(show_bgp_vni_imet
,
5587 show_bgp_vni_imet_cmd
,
5588 "show bgp vni "CMD_VNI_RANGE
"$vni type <3|multicast> [vtep A.B.C.D$addr] [json$uj]",
5594 EVPN_TYPE_3_HELP_STR
5595 EVPN_TYPE_3_HELP_STR
5601 json_object
*json
= NULL
;
5603 bgp
= bgp_get_evpn();
5607 /* check if we need json output */
5609 json
= json_object_new_object();
5611 evpn_show_routes_vni(vty
, bgp
, vni
, BGP_EVPN_IMET_ROUTE
, false, addr
,
5615 vty_json(vty
, json
);
5621 * Display per-VNI EVPN MACIP MAC routing table - for select VNI & MAC
5623 DEFPY(show_bgp_vni_macip_mac_addr
,
5624 show_bgp_vni_macip_mac_addr_cmd
,
5625 "show bgp vni "CMD_VNI_RANGE
"$vni type <2|macip> mac X:X:X:X:X:X [json$uj]",
5631 EVPN_TYPE_2_HELP_STR
5632 EVPN_TYPE_2_HELP_STR
5638 json_object
*json
= NULL
;
5640 bgp
= bgp_get_evpn();
5644 /* check if we need json output */
5646 json
= json_object_new_object();
5648 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
->eth_addr
, NULL
, json
);
5651 vty_json(vty
, json
);
5657 * Display per-VNI EVPN MACIP IP routing table - for select VNI & IP
5659 DEFPY(show_bgp_vni_macip_ip_addr
, show_bgp_vni_macip_ip_addr_cmd
,
5660 "show bgp vni " CMD_VNI_RANGE
5661 "$vni type <2|macip> ip <A.B.C.D|X:X::X:X> [json$uj]",
5662 SHOW_STR BGP_STR VNI_HELP_STR VNI_NUM_HELP_STR EVPN_TYPE_HELP_STR
5663 EVPN_TYPE_2_HELP_STR EVPN_TYPE_2_HELP_STR
5664 "IP Table\n" IP_ADDR_STR IP6_ADDR_STR JSON_STR
)
5667 json_object
*json
= NULL
;
5668 struct ipaddr ip_addr
= {.ipa_type
= IPADDR_NONE
};
5670 bgp
= bgp_get_evpn();
5674 /* check if we need json output */
5676 json
= json_object_new_object();
5678 if (sockunion_family(ip
) == AF_INET
) {
5679 ip_addr
.ipa_type
= IPADDR_V4
;
5680 ip_addr
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
5682 ip_addr
.ipa_type
= IPADDR_V6
;
5683 memcpy(&ip_addr
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
5684 sizeof(struct in6_addr
));
5686 evpn_show_route_vni_macip(vty
, bgp
, vni
, NULL
, &ip_addr
, json
);
5689 vty_json(vty
, json
);
5695 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5696 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5697 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5698 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5699 "EVPN route information\n"
5700 "MAC IP routes in the EVI tables linked to the ES\n"
5702 "Detailed information\n" JSON_STR
)
5706 json_object
*json
= NULL
;
5709 if (!str_to_esi(esi_str
, &esi
)) {
5710 vty_out(vty
, "%% Malformed ESI\n");
5719 json
= json_object_new_object();
5720 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5722 vty_json(vty
, json
);
5728 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5729 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5730 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5731 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5732 "EVPN route information\n"
5733 "MAC IP routes in the global table linked to the ES\n"
5735 "Detailed information\n" JSON_STR
)
5739 json_object
*json
= NULL
;
5742 if (!str_to_esi(esi_str
, &esi
)) {
5743 vty_out(vty
, "%% Malformed ESI\n");
5752 json
= json_object_new_object();
5753 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5755 vty_json(vty
, json
);
5761 * Display EVPN import route-target hash table
5763 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5764 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5765 "show bgp l2vpn evpn vrf-import-rt [json]",
5770 "Show vrf import route target\n"
5774 struct bgp
*bgp_evpn
= NULL
;
5775 json_object
*json
= NULL
;
5777 bgp_evpn
= bgp_get_evpn();
5781 uj
= use_json(argc
, argv
);
5783 json
= json_object_new_object();
5785 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5788 vty_json(vty
, json
);
5794 * Display EVPN import route-target hash table
5796 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5797 show_bgp_l2vpn_evpn_import_rt_cmd
,
5798 "show bgp l2vpn evpn import-rt [json]",
5803 "Show import route target\n"
5808 json_object
*json
= NULL
;
5810 bgp
= bgp_get_evpn();
5814 uj
= use_json(argc
, argv
);
5816 json
= json_object_new_object();
5818 evpn_show_import_rts(vty
, bgp
, json
);
5821 vty_json(vty
, json
);
5826 DEFPY_HIDDEN(test_es_add
,
5828 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5831 "Ethernet-segment\n"
5832 "Ethernet-Segment Identifier\n"
5840 struct in_addr vtep_ip
;
5843 bgp
= bgp_get_evpn();
5845 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5849 if (!str_to_esi(esi_str
, &esi
)) {
5850 vty_out(vty
, "%% Malformed ESI\n");
5855 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5857 vty_out(vty
, "%% Failed to delete ES\n");
5861 if (state_str
&& !strcmp(state_str
, "up"))
5865 vtep_ip
= bgp
->router_id
;
5867 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5868 EVPN_MH_DF_PREF_MIN
, false);
5870 vty_out(vty
, "%% Failed to add ES\n");
5877 DEFPY_HIDDEN(test_es_vni_add
,
5878 test_es_vni_add_cmd
,
5879 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5882 "Ethernet-segment\n"
5883 "Ethernet-Segment Identifier\n"
5892 bgp
= bgp_get_evpn();
5894 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5898 if (!str_to_esi(esi_str
, &esi
)) {
5899 vty_out(vty
, "%% Malformed ESI\n");
5904 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5906 vty_out(vty
, "%% Failed to deref ES VNI\n");
5910 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5912 vty_out(vty
, "%% Failed to ref ES VNI\n");
5919 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5920 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5924 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5925 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5926 "Summary of BGP neighbor status\n" JSON_STR
)
5928 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5929 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5930 SHOW_STR BGP_STR EVPN_HELP_STR
5932 "Display Detailed Information\n"
5934 EVPN_TYPE_2_HELP_STR
5935 EVPN_TYPE_2_HELP_STR
5936 EVPN_TYPE_3_HELP_STR
5937 EVPN_TYPE_3_HELP_STR
)
5940 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5941 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5942 SHOW_STR BGP_STR EVPN_HELP_STR
5944 EVPN_RT_DIST_HELP_STR
5945 EVPN_ASN_IP_HELP_STR
5947 EVPN_TYPE_2_HELP_STR
5948 EVPN_TYPE_2_HELP_STR
5949 EVPN_TYPE_3_HELP_STR
5950 EVPN_TYPE_3_HELP_STR
)
5953 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5954 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5955 SHOW_STR BGP_STR EVPN_HELP_STR
5957 EVPN_RT_DIST_HELP_STR
5958 EVPN_ASN_IP_HELP_STR
5960 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5962 "IP address (IPv4 or IPv6)\n")
5965 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5966 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5967 SHOW_STR BGP_STR EVPN_HELP_STR
5969 "VXLAN Network Identifier\n"
5972 EVPN_TYPE_2_HELP_STR
5973 EVPN_TYPE_2_HELP_STR
5974 EVPN_TYPE_3_HELP_STR
5975 EVPN_TYPE_3_HELP_STR
5977 "Remote VTEP IP address\n")
5979 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5980 show_bgp_evpn_route_vni_macip_cmd
,
5981 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5982 SHOW_STR BGP_STR EVPN_HELP_STR
5984 "VXLAN Network Identifier\n"
5987 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5989 "IP address (IPv4 or IPv6)\n")
5991 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5992 show_bgp_evpn_route_vni_multicast_cmd
,
5993 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5994 SHOW_STR BGP_STR EVPN_HELP_STR
5996 "VXLAN Network Identifier\n"
5998 EVPN_TYPE_3_HELP_STR
5999 "Originating Router IP address\n")
6001 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
6002 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
6003 SHOW_STR BGP_STR EVPN_HELP_STR
6005 "VXLAN Network Identifier\n"
6007 "Print Detailed Output\n"
6009 "Remote VTEP IP address\n")
6011 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
6012 "show bgp evpn import-rt",
6013 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
6015 DEFUN_NOSH (bgp_evpn_vni
,
6017 "vni " CMD_VNI_RANGE
,
6018 "VXLAN Network Identifier\n"
6022 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6023 struct bgpevpn
*vpn
;
6028 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
6030 /* Create VNI, or mark as configured. */
6031 vpn
= evpn_create_update_vni(bgp
, vni
);
6033 vty_out(vty
, "%% Failed to create VNI \n");
6037 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
6041 DEFUN (no_bgp_evpn_vni
,
6042 no_bgp_evpn_vni_cmd
,
6043 "no vni " CMD_VNI_RANGE
,
6045 "VXLAN Network Identifier\n"
6049 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6050 struct bgpevpn
*vpn
;
6055 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
6057 /* Check if we should disallow. */
6058 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
6060 vty_out(vty
, "%% Specified VNI does not exist\n");
6063 if (!is_vni_configured(vpn
)) {
6064 vty_out(vty
, "%% Specified VNI is not configured\n");
6068 evpn_delete_vni(bgp
, vpn
);
6072 DEFUN_NOSH (exit_vni
,
6075 "Exit from VNI mode\n")
6077 if (vty
->node
== BGP_EVPN_VNI_NODE
)
6078 vty
->node
= BGP_EVPN_NODE
;
6082 DEFUN (bgp_evpn_vrf_rd
,
6083 bgp_evpn_vrf_rd_cmd
,
6084 "rd ASN:NN_OR_IP-ADDRESS:NN",
6085 EVPN_RT_DIST_HELP_STR
6086 EVPN_ASN_IP_HELP_STR
)
6089 struct prefix_rd prd
;
6090 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6095 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6097 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6101 /* If same as existing value, there is nothing more to do. */
6102 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
6105 /* Configure or update the RD. */
6106 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
6110 DEFUN (no_bgp_evpn_vrf_rd
,
6111 no_bgp_evpn_vrf_rd_cmd
,
6112 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6114 EVPN_RT_DIST_HELP_STR
6115 EVPN_ASN_IP_HELP_STR
)
6118 struct prefix_rd prd
;
6119 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6124 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6126 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6130 /* Check if we should disallow. */
6131 if (!is_vrf_rd_configured(bgp_vrf
)) {
6132 vty_out(vty
, "%% RD is not configured for this VRF\n");
6136 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
6138 "%% RD specified does not match configuration for this VRF\n");
6142 evpn_unconfigure_vrf_rd(bgp_vrf
);
6146 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
6147 no_bgp_evpn_vrf_rd_without_val_cmd
,
6150 EVPN_RT_DIST_HELP_STR
)
6152 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
6157 /* Check if we should disallow. */
6158 if (!is_vrf_rd_configured(bgp_vrf
)) {
6159 vty_out(vty
, "%% RD is not configured for this VRF\n");
6163 evpn_unconfigure_vrf_rd(bgp_vrf
);
6167 DEFUN (bgp_evpn_vni_rd
,
6168 bgp_evpn_vni_rd_cmd
,
6169 "rd ASN:NN_OR_IP-ADDRESS:NN",
6170 EVPN_RT_DIST_HELP_STR
6171 EVPN_ASN_IP_HELP_STR
)
6173 struct prefix_rd prd
;
6174 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6175 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6181 if (!EVPN_ENABLED(bgp
)) {
6183 "This command is only supported under EVPN VRF\n");
6187 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
6189 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6193 /* If same as existing value, there is nothing more to do. */
6194 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
6197 /* Configure or update the RD. */
6198 evpn_configure_rd(bgp
, vpn
, &prd
);
6202 DEFUN (no_bgp_evpn_vni_rd
,
6203 no_bgp_evpn_vni_rd_cmd
,
6204 "no rd ASN:NN_OR_IP-ADDRESS:NN",
6206 EVPN_RT_DIST_HELP_STR
6207 EVPN_ASN_IP_HELP_STR
)
6209 struct prefix_rd prd
;
6210 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6211 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6217 if (!EVPN_ENABLED(bgp
)) {
6219 "This command is only supported under EVPN VRF\n");
6223 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
6225 vty_out(vty
, "%% Malformed Route Distinguisher\n");
6229 /* Check if we should disallow. */
6230 if (!is_rd_configured(vpn
)) {
6231 vty_out(vty
, "%% RD is not configured for this VNI\n");
6235 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
6237 "%% RD specified does not match configuration for this VNI\n");
6241 evpn_unconfigure_rd(bgp
, vpn
);
6245 DEFUN (no_bgp_evpn_vni_rd_without_val
,
6246 no_bgp_evpn_vni_rd_without_val_cmd
,
6249 EVPN_RT_DIST_HELP_STR
)
6251 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6252 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6257 if (!EVPN_ENABLED(bgp
)) {
6259 "This command is only supported under EVPN VRF\n");
6263 /* Check if we should disallow. */
6264 if (!is_rd_configured(vpn
)) {
6265 vty_out(vty
, "%% RD is not configured for this VNI\n");
6269 evpn_unconfigure_rd(bgp
, vpn
);
6274 * Loop over all extended-communities in the route-target list rtl and
6275 * return 1 if we find ecomtarget
6277 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
6278 struct ecommunity
*ecomtarget
)
6280 struct listnode
*node
;
6281 struct ecommunity
*ecom
;
6283 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
6284 if (ecommunity_match(ecom
, ecomtarget
))
6292 * L3 RT version of above.
6294 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
6295 struct ecommunity
*ecomtarget
)
6297 struct listnode
*node
;
6298 struct vrf_route_target
*l3rt
;
6300 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
6301 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
6308 /* display L3VNI related info for a VRF instance */
6309 DEFUN (show_bgp_vrf_l3vni_info
,
6310 show_bgp_vrf_l3vni_info_cmd
,
6311 "show bgp vrf VRFNAME vni [json]",
6319 char buf
[ETHER_ADDR_STRLEN
];
6321 const char *name
= NULL
;
6322 struct bgp
*bgp
= NULL
;
6323 struct listnode
*node
= NULL
;
6324 struct bgpevpn
*vpn
= NULL
;
6325 struct vrf_route_target
*l3rt
;
6326 json_object
*json
= NULL
;
6327 json_object
*json_vnis
= NULL
;
6328 json_object
*json_export_rts
= NULL
;
6329 json_object
*json_import_rts
= NULL
;
6330 bool uj
= use_json(argc
, argv
);
6333 json
= json_object_new_object();
6334 json_vnis
= json_object_new_array();
6335 json_export_rts
= json_object_new_array();
6336 json_import_rts
= json_object_new_array();
6339 name
= argv
[idx_vrf
]->arg
;
6340 bgp
= bgp_lookup_by_name(name
);
6341 if (strmatch(name
, VRF_DEFAULT_NAME
))
6342 bgp
= bgp_get_default();
6346 vty_out(vty
, "BGP instance for VRF %s not found\n",
6349 json_object_string_add(json
, "warning",
6350 "BGP instance not found");
6351 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
6352 json_object_free(json
);
6358 vty_out(vty
, "BGP VRF: %s\n", name
);
6359 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
6360 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
6361 vty_out(vty
, " Rmac: %s\n",
6362 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6363 vty_out(vty
, " VNI Filter: %s\n",
6364 CHECK_FLAG(bgp
->vrf_flags
,
6365 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6366 ? "prefix-routes-only"
6368 vty_out(vty
, " L2-VNI List:\n");
6370 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6371 vty_out(vty
, "%u ", vpn
->vni
);
6373 vty_out(vty
, " Export-RTs:\n");
6375 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6376 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6378 vty_out(vty
, " Import-RTs:\n");
6380 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6381 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
6383 vty_out(vty
, " RD: %pRD\n", &bgp
->vrf_prd
);
6385 json_object_string_add(json
, "vrf", name
);
6386 json_object_string_addf(json
, "local-ip", "%pI4",
6387 &bgp
->originator_ip
);
6388 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
6389 json_object_string_add(
6391 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
6392 json_object_string_add(
6394 CHECK_FLAG(bgp
->vrf_flags
,
6395 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
6396 ? "prefix-routes-only"
6398 /* list of l2vnis */
6399 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
6400 json_object_array_add(json_vnis
,
6401 json_object_new_int(vpn
->vni
));
6402 json_object_object_add(json
, "l2vnis", json_vnis
);
6405 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
6406 json_object_array_add(
6408 json_object_new_string(
6409 ecommunity_str(l3rt
->ecom
)));
6410 json_object_object_add(json
, "export-rts", json_export_rts
);
6413 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
6414 json_object_array_add(
6416 json_object_new_string(
6417 ecommunity_str(l3rt
->ecom
)));
6418 json_object_object_add(json
, "import-rts", json_import_rts
);
6419 json_object_string_addf(json
, "rd", "%pRD", &bgp
->vrf_prd
);
6423 vty_json(vty
, json
);
6427 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
6430 /* Do nothing if we already have this route-target */
6432 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6434 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
6439 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6441 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
6449 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
6451 /* Verify we already have this route-target */
6453 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
6457 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
6459 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
6463 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
6469 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
6470 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
6473 int ret
= CMD_SUCCESS
;
6474 bool is_wildcard
= false;
6475 struct ecommunity
*ecom
= NULL
;
6477 for (int i
= rt_idx
; i
< argc
; i
++) {
6478 is_wildcard
= false;
6481 * Special handling for wildcard '*' here.
6483 * Let's just convert it to 0 here so we dont have to modify
6484 * the ecommunity parser.
6486 if ((argv
[i
]->arg
)[0] == '*') {
6487 (argv
[i
]->arg
)[0] = '0';
6491 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
6494 /* Put it back as was */
6496 (argv
[i
]->arg
)[0] = '*';
6499 vty_out(vty
, "%% Malformed Route Target list\n");
6504 ecommunity_str(ecom
);
6507 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
6509 "%% RT specified already configured for this VRF: %s\n",
6511 ecommunity_free(&ecom
);
6516 if (del_rt(bgp
, ecom
, is_import
) != 0) {
6518 "%% RT specified does not match configuration for this VRF: %s\n",
6523 ecommunity_free(&ecom
);
6530 /* import/export rt for l3vni-vrf */
6531 DEFUN (bgp_evpn_vrf_rt
,
6532 bgp_evpn_vrf_rt_cmd
,
6533 "route-target <both|import|export> RTLIST...",
6535 "import and export\n"
6538 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
6540 int ret
= CMD_SUCCESS
;
6541 int tmp_ret
= CMD_SUCCESS
;
6543 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6546 return CMD_WARNING_CONFIG_FAILED
;
6548 if (!strcmp(argv
[1]->arg
, "import"))
6549 rt_type
= RT_TYPE_IMPORT
;
6550 else if (!strcmp(argv
[1]->arg
, "export"))
6551 rt_type
= RT_TYPE_EXPORT
;
6552 else if (!strcmp(argv
[1]->arg
, "both"))
6553 rt_type
= RT_TYPE_BOTH
;
6555 vty_out(vty
, "%% Invalid Route Target type\n");
6556 return CMD_WARNING_CONFIG_FAILED
;
6559 if (strmatch(argv
[2]->arg
, "auto")) {
6560 vty_out(vty
, "%% `auto` cannot be configured via list\n");
6561 return CMD_WARNING_CONFIG_FAILED
;
6564 if (rt_type
!= RT_TYPE_IMPORT
) {
6565 for (int i
= 2; i
< argc
; i
++) {
6566 if ((argv
[i
]->arg
)[0] == '*') {
6568 "%% Wildcard '*' only applicable for import\n");
6569 return CMD_WARNING_CONFIG_FAILED
;
6574 /* Add/update the import route-target */
6575 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6576 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
6578 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6581 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6582 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
6584 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6590 DEFPY (bgp_evpn_vrf_rt_auto
,
6591 bgp_evpn_vrf_rt_auto_cmd
,
6592 "route-target <both|import|export>$type auto",
6594 "import and export\n"
6597 "Automatically derive route target\n")
6599 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6603 return CMD_WARNING_CONFIG_FAILED
;
6605 if (strmatch(type
, "import"))
6606 rt_type
= RT_TYPE_IMPORT
;
6607 else if (strmatch(type
, "export"))
6608 rt_type
= RT_TYPE_EXPORT
;
6609 else if (strmatch(type
, "both"))
6610 rt_type
= RT_TYPE_BOTH
;
6612 vty_out(vty
, "%% Invalid Route Target type\n");
6613 return CMD_WARNING_CONFIG_FAILED
;
6616 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6617 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6619 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6620 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6625 DEFUN (no_bgp_evpn_vrf_rt
,
6626 no_bgp_evpn_vrf_rt_cmd
,
6627 "no route-target <both|import|export> RTLIST...",
6630 "import and export\n"
6633 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6635 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6636 int ret
= CMD_SUCCESS
;
6637 int tmp_ret
= CMD_SUCCESS
;
6641 return CMD_WARNING_CONFIG_FAILED
;
6643 if (!strcmp(argv
[2]->arg
, "import"))
6644 rt_type
= RT_TYPE_IMPORT
;
6645 else if (!strcmp(argv
[2]->arg
, "export"))
6646 rt_type
= RT_TYPE_EXPORT
;
6647 else if (!strcmp(argv
[2]->arg
, "both"))
6648 rt_type
= RT_TYPE_BOTH
;
6650 vty_out(vty
, "%% Invalid Route Target type\n");
6651 return CMD_WARNING_CONFIG_FAILED
;
6654 if (!strcmp(argv
[3]->arg
, "auto")) {
6655 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6656 return CMD_WARNING_CONFIG_FAILED
;
6659 if (rt_type
== RT_TYPE_IMPORT
) {
6660 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6662 "%% Import RT is not configured for this VRF\n");
6663 return CMD_WARNING_CONFIG_FAILED
;
6665 } else if (rt_type
== RT_TYPE_EXPORT
) {
6666 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6668 "%% Export RT is not configured for this VRF\n");
6669 return CMD_WARNING_CONFIG_FAILED
;
6671 } else if (rt_type
== RT_TYPE_BOTH
) {
6672 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6673 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6675 "%% Import/Export RT is not configured for this VRF\n");
6676 return CMD_WARNING_CONFIG_FAILED
;
6680 if (rt_type
!= RT_TYPE_IMPORT
) {
6681 for (int i
= 3; i
< argc
; i
++) {
6682 if ((argv
[i
]->arg
)[0] == '*') {
6684 "%% Wildcard '*' only applicable for import\n");
6685 return CMD_WARNING_CONFIG_FAILED
;
6690 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6691 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6693 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6696 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6697 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6699 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6705 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6706 no_bgp_evpn_vrf_rt_auto_cmd
,
6707 "no route-target <both|import|export>$type auto",
6710 "import and export\n"
6713 "Automatically derive route target\n")
6715 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6719 return CMD_WARNING_CONFIG_FAILED
;
6721 if (strmatch(type
, "import"))
6722 rt_type
= RT_TYPE_IMPORT
;
6723 else if (strmatch(type
, "export"))
6724 rt_type
= RT_TYPE_EXPORT
;
6725 else if (strmatch(type
, "both"))
6726 rt_type
= RT_TYPE_BOTH
;
6728 vty_out(vty
, "%% Invalid Route Target type\n");
6729 return CMD_WARNING_CONFIG_FAILED
;
6732 if (rt_type
== RT_TYPE_IMPORT
) {
6733 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6735 "%% Import AUTO RT is not configured for this VRF\n");
6736 return CMD_WARNING_CONFIG_FAILED
;
6738 } else if (rt_type
== RT_TYPE_EXPORT
) {
6739 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6741 "%% Export AUTO RT is not configured for this VRF\n");
6742 return CMD_WARNING_CONFIG_FAILED
;
6744 } else if (rt_type
== RT_TYPE_BOTH
) {
6745 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6746 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6748 "%% Import/Export AUTO RT is not configured for this VRF\n");
6749 return CMD_WARNING_CONFIG_FAILED
;
6753 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6754 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6756 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6757 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6762 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6763 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6765 "EAD ES fragment config\n"
6766 "EVIs per-fragment\n"
6769 bgp_mh_info
->evi_per_es_frag
=
6770 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6775 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6776 "ead-es-route-target export RT",
6777 "EAD ES Route Target\n"
6779 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6781 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6782 struct ecommunity
*ecomadd
= NULL
;
6787 if (!EVPN_ENABLED(bgp
)) {
6788 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6792 /* Add/update the export route-target */
6793 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6795 vty_out(vty
, "%% Malformed Route Target list\n");
6798 ecommunity_str(ecomadd
);
6800 /* Do nothing if we already have this export route-target */
6801 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6803 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6808 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6809 "no ead-es-route-target export RT",
6811 "EAD ES Route Target\n"
6812 "export\n" EVPN_ASN_IP_HELP_STR
)
6814 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6815 struct ecommunity
*ecomdel
= NULL
;
6820 if (!EVPN_ENABLED(bgp
)) {
6821 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6825 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6827 vty_out(vty
, "%% Malformed Route Target list\n");
6830 ecommunity_str(ecomdel
);
6832 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6834 ecommunity_free(&ecomdel
);
6836 "%% RT specified does not match EAD-ES RT configuration\n");
6839 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6844 DEFUN (bgp_evpn_vni_rt
,
6845 bgp_evpn_vni_rt_cmd
,
6846 "route-target <both|import|export> RT",
6848 "import and export\n"
6851 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6853 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6854 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6856 struct ecommunity
*ecomadd
= NULL
;
6861 if (!EVPN_ENABLED(bgp
)) {
6863 "This command is only supported under EVPN VRF\n");
6867 if (!strcmp(argv
[1]->text
, "import"))
6868 rt_type
= RT_TYPE_IMPORT
;
6869 else if (!strcmp(argv
[1]->text
, "export"))
6870 rt_type
= RT_TYPE_EXPORT
;
6871 else if (!strcmp(argv
[1]->text
, "both"))
6872 rt_type
= RT_TYPE_BOTH
;
6874 vty_out(vty
, "%% Invalid Route Target type\n");
6878 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6880 vty_out(vty
, "%% Malformed Route Target list\n");
6883 ecommunity_str(ecomadd
);
6885 /* Add/update the import route-target */
6886 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6887 /* Do nothing if we already have this import route-target */
6888 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6889 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6892 /* Add/update the export route-target */
6893 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6894 /* Do nothing if we already have this export route-target */
6895 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6896 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6902 DEFUN (no_bgp_evpn_vni_rt
,
6903 no_bgp_evpn_vni_rt_cmd
,
6904 "no route-target <both|import|export> RT",
6907 "import and export\n"
6910 EVPN_ASN_IP_HELP_STR
)
6912 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6913 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6914 int rt_type
, found_ecomdel
;
6915 struct ecommunity
*ecomdel
= NULL
;
6920 if (!EVPN_ENABLED(bgp
)) {
6922 "This command is only supported under EVPN VRF\n");
6926 if (!strcmp(argv
[2]->text
, "import"))
6927 rt_type
= RT_TYPE_IMPORT
;
6928 else if (!strcmp(argv
[2]->text
, "export"))
6929 rt_type
= RT_TYPE_EXPORT
;
6930 else if (!strcmp(argv
[2]->text
, "both"))
6931 rt_type
= RT_TYPE_BOTH
;
6933 vty_out(vty
, "%% Invalid Route Target type\n");
6937 /* The user did "no route-target import", check to see if there are any
6938 * import route-targets configured. */
6939 if (rt_type
== RT_TYPE_IMPORT
) {
6940 if (!is_import_rt_configured(vpn
)) {
6942 "%% Import RT is not configured for this VNI\n");
6945 } else if (rt_type
== RT_TYPE_EXPORT
) {
6946 if (!is_export_rt_configured(vpn
)) {
6948 "%% Export RT is not configured for this VNI\n");
6951 } else if (rt_type
== RT_TYPE_BOTH
) {
6952 if (!is_import_rt_configured(vpn
)
6953 && !is_export_rt_configured(vpn
)) {
6955 "%% Import/Export RT is not configured for this VNI\n");
6960 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6962 vty_out(vty
, "%% Malformed Route Target list\n");
6965 ecommunity_str(ecomdel
);
6967 if (rt_type
== RT_TYPE_IMPORT
) {
6968 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6969 ecommunity_free(&ecomdel
);
6971 "%% RT specified does not match configuration for this VNI\n");
6974 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6975 } else if (rt_type
== RT_TYPE_EXPORT
) {
6976 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6977 ecommunity_free(&ecomdel
);
6979 "%% RT specified does not match configuration for this VNI\n");
6982 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6983 } else if (rt_type
== RT_TYPE_BOTH
) {
6986 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6987 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6991 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6992 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6996 if (!found_ecomdel
) {
6997 ecommunity_free(&ecomdel
);
6999 "%% RT specified does not match configuration for this VNI\n");
7007 DEFUN (no_bgp_evpn_vni_rt_without_val
,
7008 no_bgp_evpn_vni_rt_without_val_cmd
,
7009 "no route-target <import|export>",
7015 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
7016 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
7022 if (!EVPN_ENABLED(bgp
)) {
7024 "This command is only supported under EVPN VRF\n");
7028 if (!strcmp(argv
[2]->text
, "import")) {
7029 rt_type
= RT_TYPE_IMPORT
;
7030 } else if (!strcmp(argv
[2]->text
, "export")) {
7031 rt_type
= RT_TYPE_EXPORT
;
7033 vty_out(vty
, "%% Invalid Route Target type\n");
7037 /* Check if we should disallow. */
7038 if (rt_type
== RT_TYPE_IMPORT
) {
7039 if (!is_import_rt_configured(vpn
)) {
7041 "%% Import RT is not configured for this VNI\n");
7045 if (!is_export_rt_configured(vpn
)) {
7047 "%% Export RT is not configured for this VNI\n");
7052 /* Unconfigure the RT. */
7053 if (rt_type
== RT_TYPE_IMPORT
)
7054 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
7056 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
7060 static int vni_cmp(const void **a
, const void **b
)
7062 const struct bgpevpn
*first
= *a
;
7063 const struct bgpevpn
*secnd
= *b
;
7065 return secnd
->vni
- first
->vni
;
7069 * Output EVPN configuration information.
7071 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
7074 char buf2
[INET6_ADDRSTRLEN
];
7076 if (bgp
->advertise_all_vni
)
7077 vty_out(vty
, " advertise-all-vni\n");
7079 if (hashcount(bgp
->vnihash
)) {
7080 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
7081 struct listnode
*ln
;
7082 struct bgpevpn
*data
;
7084 list_sort(vnilist
, vni_cmp
);
7085 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
7086 write_vni_config(vty
, data
);
7088 list_delete(&vnilist
);
7091 if (bgp
->advertise_autort_rfc8365
)
7092 vty_out(vty
, " autort rfc8365-compatible\n");
7094 if (bgp
->advertise_gw_macip
)
7095 vty_out(vty
, " advertise-default-gw\n");
7097 if (bgp
->evpn_info
->advertise_svi_macip
)
7098 vty_out(vty
, " advertise-svi-ip\n");
7100 if (bgp
->resolve_overlay_index
)
7101 vty_out(vty
, " enable-resolve-overlay-index\n");
7103 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
7104 vty_out(vty
, " ead-es-frag evi-limit %u\n",
7105 bgp_mh_info
->evi_per_es_frag
);
7107 if (bgp_mh_info
->host_routes_use_l3nhg
!=
7108 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
7109 if (bgp_mh_info
->host_routes_use_l3nhg
)
7110 vty_out(vty
, " use-es-l3nhg\n");
7112 vty_out(vty
, " no use-es-l3nhg\n");
7115 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
7116 if (bgp_mh_info
->ead_evi_rx
)
7117 vty_out(vty
, " no disable-ead-evi-rx\n");
7119 vty_out(vty
, " disable-ead-evi-rx\n");
7122 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
7123 if (bgp_mh_info
->ead_evi_tx
)
7124 vty_out(vty
, " no disable-ead-evi-tx\n");
7126 vty_out(vty
, " disable-ead-evi-tx\n");
7129 if (!bgp
->evpn_info
->dup_addr_detect
)
7130 vty_out(vty
, " no dup-addr-detection\n");
7132 if (bgp
->evpn_info
->dad_max_moves
!=
7133 EVPN_DAD_DEFAULT_MAX_MOVES
||
7134 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
7135 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
7136 bgp
->evpn_info
->dad_max_moves
,
7137 bgp
->evpn_info
->dad_time
);
7139 if (bgp
->evpn_info
->dad_freeze
) {
7140 if (bgp
->evpn_info
->dad_freeze_time
)
7142 " dup-addr-detection freeze %u\n",
7143 bgp
->evpn_info
->dad_freeze_time
);
7146 " dup-addr-detection freeze permanent\n");
7149 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
7150 vty_out(vty
, " flooding disable\n");
7152 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7153 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
7154 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7155 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
7156 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7159 " advertise ipv4 unicast\n");
7160 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7161 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
7162 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
7164 " advertise ipv4 unicast gateway-ip route-map %s\n",
7165 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
7167 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
7170 /* EAD ES export route-target */
7171 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
7172 struct ecommunity
*ecom
;
7174 struct listnode
*node
;
7176 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
7179 ecom_str
= ecommunity_ecom2str(
7180 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7181 vty_out(vty
, " ead-es-route-target export %s\n",
7183 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7187 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7188 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
7189 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7191 " advertise ipv6 unicast route-map %s\n",
7192 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7195 " advertise ipv6 unicast\n");
7196 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7197 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
7198 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
7200 " advertise ipv6 unicast gateway-ip route-map %s\n",
7201 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
7203 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
7206 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7207 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
7208 vty_out(vty
, " default-originate ipv4\n");
7210 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
7211 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
7212 vty_out(vty
, " default-originate ipv6\n");
7214 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
7215 if (!bgp
->evpn_info
->advertise_pip
)
7216 vty_out(vty
, " no advertise-pip\n");
7217 if (bgp
->evpn_info
->advertise_pip
) {
7218 if (bgp
->evpn_info
->pip_ip_static
.s_addr
7220 vty_out(vty
, " advertise-pip ip %s",
7222 &bgp
->evpn_info
->pip_ip_static
,
7223 buf2
, INET_ADDRSTRLEN
));
7225 bgp
->evpn_info
->pip_rmac_static
))) {
7226 char buf
[ETHER_ADDR_STRLEN
];
7228 vty_out(vty
, " mac %s",
7238 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
7239 vty_out(vty
, " rd %pRD\n", &bgp
->vrf_prd
);
7241 /* import route-target */
7242 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
7244 struct listnode
*node
, *nnode
;
7245 struct vrf_route_target
*l3rt
;
7247 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
7250 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7253 ecom_str
= ecommunity_ecom2str(
7254 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7256 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
7257 char *vni_str
= NULL
;
7259 vni_str
= strchr(ecom_str
, ':');
7261 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7265 /* Move pointer to vni */
7268 vty_out(vty
, " route-target import *:%s\n",
7272 vty_out(vty
, " route-target import %s\n",
7275 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7279 /* import route-target auto */
7280 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
7281 vty_out(vty
, " route-target import auto\n");
7283 /* export route-target */
7284 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
7286 struct listnode
*node
, *nnode
;
7287 struct vrf_route_target
*l3rt
;
7289 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
7292 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
7295 ecom_str
= ecommunity_ecom2str(
7296 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
7297 vty_out(vty
, " route-target export %s\n", ecom_str
);
7298 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
7302 /* export route-target auto */
7303 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
7304 vty_out(vty
, " route-target export auto\n");
7307 void bgp_ethernetvpn_init(void)
7309 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
7310 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
7311 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
7312 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
7313 install_element(VIEW_NODE
,
7314 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
7315 install_element(VIEW_NODE
,
7316 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
7319 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
7322 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
7323 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
7324 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
7325 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
7326 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
7327 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
7328 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
7329 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
7330 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
7331 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
7332 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
7333 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
7334 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
7335 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
7336 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
7337 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
7338 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
7339 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
7340 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
7341 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
7342 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
7343 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
7344 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
7345 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
7346 install_element(BGP_EVPN_NODE
,
7347 &bgp_evpn_enable_resolve_overlay_index_cmd
);
7350 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
7351 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
7353 /* "show bgp l2vpn evpn" commands. */
7354 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
7355 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
7356 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
7357 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
7358 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
7359 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
7360 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
7361 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
7362 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
7363 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
7364 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
7365 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
7366 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
7367 install_element(VIEW_NODE
,
7368 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
7369 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
7370 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
7371 install_element(VIEW_NODE
,
7372 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
7373 install_element(VIEW_NODE
,
7374 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
7375 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
7376 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
7378 /* "show bgp vni" commands. */
7379 install_element(VIEW_NODE
, &show_bgp_vni_all_cmd
);
7380 install_element(VIEW_NODE
, &show_bgp_vni_all_ead_cmd
);
7381 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_mac_cmd
);
7382 install_element(VIEW_NODE
, &show_bgp_vni_all_macip_ip_cmd
);
7383 install_element(VIEW_NODE
, &show_bgp_vni_all_imet_cmd
);
7384 install_element(VIEW_NODE
, &show_bgp_vni_cmd
);
7385 install_element(VIEW_NODE
, &show_bgp_vni_ead_cmd
);
7386 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_cmd
);
7387 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_cmd
);
7388 install_element(VIEW_NODE
, &show_bgp_vni_imet_cmd
);
7389 install_element(VIEW_NODE
, &show_bgp_vni_macip_mac_addr_cmd
);
7390 install_element(VIEW_NODE
, &show_bgp_vni_macip_ip_addr_cmd
);
7392 /* "show bgp evpn" commands. */
7393 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
7394 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
7395 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
7396 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
7397 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
7398 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
7399 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
7400 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
7401 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
7402 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
7403 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
7404 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
7406 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
7407 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
7408 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
7409 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
7410 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
7411 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
7412 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
7413 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
7414 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
7415 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
7416 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
7417 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
7418 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
7419 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
7420 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
7421 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
7422 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
7423 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
7424 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
7425 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
7426 install_element(BGP_EVPN_VNI_NODE
,
7427 &bgp_evpn_advertise_default_gw_vni_cmd
);
7428 install_element(BGP_EVPN_VNI_NODE
,
7429 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
7430 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
7431 install_element(BGP_EVPN_VNI_NODE
,
7432 &no_bgp_evpn_advertise_vni_subnet_cmd
);