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
;
62 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
63 enum overlay_index_type
*oly
)
65 *oly
= OVERLAY_INDEX_TYPE_NONE
;
66 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
67 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
71 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
75 uint8_t type
, sub_type
;
76 struct ecommunity_as eas
;
77 struct ecommunity_ip eip
;
78 struct listnode
*node
, *nnode
;
79 struct bgp
*tmp_bgp_vrf
= NULL
;
80 json_object
*json_rt
= NULL
;
81 json_object
*json_vrfs
= NULL
;
82 char rt_buf
[RT_ADDRSTRLEN
];
85 json_rt
= json_object_new_object();
86 json_vrfs
= json_object_new_array();
89 pnt
= (uint8_t *)&irt
->rt
.val
;
92 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
95 memset(&eas
, 0, sizeof(eas
));
97 case ECOMMUNITY_ENCODE_AS
:
98 eas
.as
= (*pnt
++ << 8);
100 ptr_get_be32(pnt
, &eas
.val
);
102 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
105 json_object_string_add(json_rt
, "rt", rt_buf
);
107 vty_out(vty
, "Route-target: %s", rt_buf
);
111 case ECOMMUNITY_ENCODE_IP
:
112 memcpy(&eip
.ip
, pnt
, 4);
114 eip
.val
= (*pnt
++ << 8);
117 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
126 case ECOMMUNITY_ENCODE_AS4
:
127 pnt
= ptr_get_be32(pnt
, &eas
.val
);
128 eas
.val
= (*pnt
++ << 8);
131 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
134 json_object_string_add(json_rt
, "rt", rt_buf
);
136 vty_out(vty
, "Route-target: %s", rt_buf
);
146 "\nList of VRFs importing routes with this route-target:\n");
149 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
151 json_object_array_add(
153 json_object_new_string(
154 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
156 vty_out(vty
, " %s\n",
157 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
161 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
162 json_object_object_add(json
, rt_buf
, json_rt
);
166 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
168 json_object
*json
= NULL
;
169 struct vty
*vty
= NULL
;
170 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
172 vty
= (struct vty
*)args
[0];
173 json
= (struct json_object
*)args
[1];
175 display_vrf_import_rt(vty
, irt
, json
);
178 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
182 uint8_t type
, sub_type
;
183 struct ecommunity_as eas
;
184 struct ecommunity_ip eip
;
185 struct listnode
*node
, *nnode
;
186 struct bgpevpn
*tmp_vpn
;
187 json_object
*json_rt
= NULL
;
188 json_object
*json_vnis
= NULL
;
189 char rt_buf
[RT_ADDRSTRLEN
];
192 json_rt
= json_object_new_object();
193 json_vnis
= json_object_new_array();
196 /* TODO: This needs to go into a function */
198 pnt
= (uint8_t *)&irt
->rt
.val
;
201 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
204 memset(&eas
, 0, sizeof(eas
));
206 case ECOMMUNITY_ENCODE_AS
:
207 eas
.as
= (*pnt
++ << 8);
209 ptr_get_be32(pnt
, &eas
.val
);
211 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
214 json_object_string_add(json_rt
, "rt", rt_buf
);
216 vty_out(vty
, "Route-target: %s", rt_buf
);
220 case ECOMMUNITY_ENCODE_IP
:
221 memcpy(&eip
.ip
, pnt
, 4);
223 eip
.val
= (*pnt
++ << 8);
226 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
229 json_object_string_add(json_rt
, "rt", rt_buf
);
231 vty_out(vty
, "Route-target: %s", rt_buf
);
235 case ECOMMUNITY_ENCODE_AS4
:
236 pnt
= ptr_get_be32(pnt
, &eas
.val
);
237 eas
.val
= (*pnt
++ << 8);
240 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
243 json_object_string_add(json_rt
, "rt", rt_buf
);
245 vty_out(vty
, "Route-target: %s", rt_buf
);
255 "\nList of VNIs importing routes with this route-target:\n");
258 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
260 json_object_array_add(
261 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
263 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
267 json_object_object_add(json_rt
, "vnis", json_vnis
);
268 json_object_object_add(json
, rt_buf
, json_rt
);
272 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
274 json_object
*json
= NULL
;
275 struct vty
*vty
= NULL
;
276 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
281 display_import_rt(vty
, irt
, json
);
286 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
287 struct bgp_dest
*rd_dest
,
288 json_object
*json
, char *rd_str
,
295 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
299 /* Decode RD type. */
300 type
= decode_rd_type(pnt
);
303 vty_out(vty
, "Route Distinguisher: ");
307 decode_rd_as(pnt
+ 2, &rd_as
);
308 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
310 json_object_string_add(json
, "rd", rd_str
);
312 vty_out(vty
, "%s\n", rd_str
);
316 decode_rd_as4(pnt
+ 2, &rd_as
);
317 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
325 decode_rd_ip(pnt
+ 2, &rd_ip
);
326 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
328 json_object_string_add(json
, "rd", rd_str
);
330 vty_out(vty
, "%s\n", rd_str
);
335 snprintf(rd_str
, len
, "Unknown");
336 json_object_string_add(json
, "rd", rd_str
);
338 snprintf(rd_str
, len
, "Unknown RD type");
339 vty_out(vty
, "%s\n", rd_str
);
345 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
346 uint64_t tbl_ver
, json_object
*json
)
349 " Network Next Hop Metric LocPrf Weight Path\n";
355 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
356 tbl_ver
, &bgp
->router_id
);
358 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
359 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
361 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
363 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
364 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
365 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
366 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
367 vty_out(vty
, "%s", ri_header
);
370 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
373 char buf1
[INET6_ADDRSTRLEN
];
375 struct listnode
*node
, *nnode
;
376 struct ecommunity
*ecom
;
377 json_object
*json_import_rtl
= NULL
;
378 json_object
*json_export_rtl
= NULL
;
379 char buf2
[ETHER_ADDR_STRLEN
];
380 char originator_ip
[BUFSIZ
] = {0};
382 json_import_rtl
= json_export_rtl
= 0;
385 json_import_rtl
= json_object_new_array();
386 json_export_rtl
= json_object_new_array();
387 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
388 json_object_string_add(json
, "type", "L3");
389 json_object_string_add(json
, "inKernel", "True");
390 json_object_string_add(
392 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
393 json_object_string_add(
394 json
, "originatorIp",
395 inet_ntop(AF_INET
, &bgp_vrf
->originator_ip
,
396 originator_ip
, sizeof(originator_ip
)));
397 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
398 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
399 json_object_string_add(json
, "advertisePip",
400 bgp_vrf
->evpn_info
->advertise_pip
?
401 "Enabled" : "Disabled");
402 json_object_string_add(json
, "sysIP",
404 &bgp_vrf
->evpn_info
->pip_ip
,
405 buf1
, INET_ADDRSTRLEN
));
406 json_object_string_add(json
, "sysMac",
407 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
408 buf2
, sizeof(buf2
)));
409 json_object_string_add(json
, "rmac",
410 prefix_mac2str(&bgp_vrf
->rmac
,
411 buf2
, sizeof(buf2
)));
413 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
414 vty_out(vty
, " (known to the kernel)");
417 vty_out(vty
, " Type: %s\n", "L3");
418 vty_out(vty
, " Tenant VRF: %s\n",
419 vrf_id_to_name(bgp_vrf
->vrf_id
));
420 vty_out(vty
, " RD: %s\n",
421 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
422 vty_out(vty
, " Originator IP: %pI4\n",
423 &bgp_vrf
->originator_ip
);
424 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
425 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
426 vty_out(vty
, " Advertise-pip: %s\n",
427 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
428 vty_out(vty
, " System-IP: %s\n",
429 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
430 buf1
, INET_ADDRSTRLEN
));
431 vty_out(vty
, " System-MAC: %s\n",
432 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
433 buf2
, sizeof(buf2
)));
434 vty_out(vty
, " Router-MAC: %s\n",
435 prefix_mac2str(&bgp_vrf
->rmac
,
436 buf2
, sizeof(buf2
)));
440 vty_out(vty
, " Import Route Target:\n");
442 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
443 ecom_str
= ecommunity_ecom2str(ecom
,
444 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
447 json_object_array_add(json_import_rtl
,
448 json_object_new_string(ecom_str
));
450 vty_out(vty
, " %s\n", ecom_str
);
452 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
456 json_object_object_add(json
, "importRts", json_import_rtl
);
458 vty_out(vty
, " Export Route Target:\n");
460 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
461 ecom_str
= ecommunity_ecom2str(ecom
,
462 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
465 json_object_array_add(json_export_rtl
,
466 json_object_new_string(ecom_str
));
468 vty_out(vty
, " %s\n", ecom_str
);
470 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
474 json_object_object_add(json
, "exportRts", json_export_rtl
);
477 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
479 char buf1
[RD_ADDRSTRLEN
];
481 struct listnode
*node
, *nnode
;
482 struct ecommunity
*ecom
;
483 json_object
*json_import_rtl
= NULL
;
484 json_object
*json_export_rtl
= NULL
;
485 struct bgp
*bgp_evpn
;
486 char buf
[BUFSIZ
] = {0};
488 bgp_evpn
= bgp_get_evpn();
491 json_import_rtl
= json_object_new_array();
492 json_export_rtl
= json_object_new_array();
493 json_object_int_add(json
, "vni", vpn
->vni
);
494 json_object_string_add(json
, "type", "L2");
495 json_object_string_add(json
, "inKernel",
496 is_vni_live(vpn
) ? "True" : "False");
497 json_object_string_add(
499 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
500 json_object_string_add(json
, "originatorIp",
501 inet_ntop(AF_INET
, &vpn
->originator_ip
,
503 json_object_string_add(
505 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf
, sizeof(buf
)));
506 /* per vni knob is enabled -- Enabled
507 * Global knob is enabled -- Active
508 * default -- Disabled
510 if (!vpn
->advertise_gw_macip
&&
511 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
512 json_object_string_add(json
, "advertiseGatewayMacip",
514 else if (vpn
->advertise_gw_macip
)
515 json_object_string_add(json
, "advertiseGatewayMacip",
518 json_object_string_add(json
, "advertiseGatewayMacip",
520 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
521 bgp_evpn
->evpn_info
->advertise_svi_macip
)
522 json_object_string_add(json
, "advertiseSviMacIp",
524 else if (vpn
->advertise_svi_macip
)
525 json_object_string_add(json
, "advertiseSviMacIp",
528 json_object_string_add(json
, "advertiseSviMacIp",
530 json_object_string_add(
531 json
, "sviInterface",
532 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
534 vty_out(vty
, "VNI: %d", vpn
->vni
);
535 if (is_vni_live(vpn
))
536 vty_out(vty
, " (known to the kernel)");
539 vty_out(vty
, " Type: %s\n", "L2");
540 vty_out(vty
, " Tenant-Vrf: %s\n",
541 vrf_id_to_name(vpn
->tenant_vrf_id
));
542 vty_out(vty
, " RD: %s\n",
543 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
544 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
545 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
546 if (!vpn
->advertise_gw_macip
&&
547 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
548 vty_out(vty
, " Advertise-gw-macip : %s\n",
550 else if (vpn
->advertise_gw_macip
)
551 vty_out(vty
, " Advertise-gw-macip : %s\n",
554 vty_out(vty
, " Advertise-gw-macip : %s\n",
556 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
557 bgp_evpn
->evpn_info
->advertise_svi_macip
)
558 vty_out(vty
, " Advertise-svi-macip : %s\n",
560 else if (vpn
->advertise_svi_macip
)
561 vty_out(vty
, " Advertise-svi-macip : %s\n",
564 vty_out(vty
, " Advertise-svi-macip : %s\n",
566 vty_out(vty
, " SVI interface : %s\n",
567 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
571 vty_out(vty
, " Import Route Target:\n");
573 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
574 ecom_str
= ecommunity_ecom2str(ecom
,
575 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
578 json_object_array_add(json_import_rtl
,
579 json_object_new_string(ecom_str
));
581 vty_out(vty
, " %s\n", ecom_str
);
583 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
587 json_object_object_add(json
, "importRts", json_import_rtl
);
589 vty_out(vty
, " Export Route Target:\n");
591 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
592 ecom_str
= ecommunity_ecom2str(ecom
,
593 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
596 json_object_array_add(json_export_rtl
,
597 json_object_new_string(ecom_str
));
599 vty_out(vty
, " %s\n", ecom_str
);
601 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
605 json_object_object_add(json
, "exportRts", json_export_rtl
);
608 static void show_esi_routes(struct bgp
*bgp
,
609 struct bgp_evpn_es
*es
,
614 struct bgp_dest
*dest
;
615 struct bgp_path_info
*pi
;
616 uint32_t prefix_cnt
, path_cnt
;
619 prefix_cnt
= path_cnt
= 0;
621 tbl_ver
= es
->route_table
->version
;
622 for (dest
= bgp_table_top(es
->route_table
); dest
;
623 dest
= bgp_route_next(dest
)) {
624 int add_prefix_to_json
= 0;
625 char prefix_str
[BUFSIZ
];
626 json_object
*json_paths
= NULL
;
627 json_object
*json_prefix
= NULL
;
628 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
630 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
634 json_prefix
= json_object_new_object();
636 pi
= bgp_dest_get_bgp_path_info(dest
);
638 /* Overall header/legend displayed once. */
640 bgp_evpn_show_route_header(vty
, bgp
,
649 json_paths
= json_object_new_array();
651 /* For EVPN, the prefix is displayed for each path (to fit in
652 * with code that already exists).
654 for (; pi
; pi
= pi
->next
) {
655 json_object
*json_path
= NULL
;
658 json_path
= json_object_new_array();
660 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
664 json_object_array_add(json_paths
, json_path
);
667 add_prefix_to_json
= 1;
671 if (add_prefix_to_json
) {
672 json_object_string_add(json_prefix
, "prefix",
674 json_object_int_add(json_prefix
, "prefixLen",
676 json_object_object_add(json_prefix
, "paths",
678 json_object_object_add(json
, prefix_str
,
681 json_object_free(json_paths
);
682 json_object_free(json_prefix
);
690 json_object_int_add(json
, "numPrefix", prefix_cnt
);
691 json_object_int_add(json
, "numPaths", path_cnt
);
694 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
696 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
697 prefix_cnt
, path_cnt
);
701 /* Display all MAC-IP VNI routes linked to an ES */
702 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
703 json_object
*json
, int detail
,
707 struct bgp_path_info
*pi
;
708 int header
= detail
? 0 : 1;
710 struct listnode
*node
;
711 struct bgp_evpn_es
*es
;
712 struct bgp_path_es_info
*es_info
;
713 struct bgp
*bgp
= bgp_get_evpn();
714 json_object
*json_paths
= NULL
;
722 json_paths
= json_object_new_array();
724 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
725 struct list
*es_list
;
727 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
731 es_list
= es
->macip_global_path_list
;
733 es_list
= es
->macip_evi_path_list
;
735 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
736 json_object
*json_path
= NULL
;
741 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
744 /* Overall header/legend displayed once. */
746 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
753 json_path
= json_object_new_array();
756 route_vty_out_detail(
757 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
758 RPKI_NOT_BEING_USED
, json_path
);
760 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
764 json_object_array_add(json_paths
, json_path
);
769 json_object_object_add(json
, "paths", json_paths
);
770 json_object_int_add(json
, "numPaths", path_cnt
);
773 vty_out(vty
, "There are no MAC-IP ES paths");
775 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
780 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
781 json_object
*json
, int detail
)
783 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
786 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
787 json_object
*json
, int detail
)
789 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
792 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
793 struct vty
*vty
, struct in_addr vtep_ip
,
794 json_object
*json
, int detail
)
796 struct bgp_dest
*dest
;
797 struct bgp_path_info
*pi
;
798 struct bgp_table
*table
;
799 int header
= detail
? 0 : 1;
801 uint32_t prefix_cnt
, path_cnt
;
803 prefix_cnt
= path_cnt
= 0;
805 table
= vpn
->route_table
;
806 tbl_ver
= table
->version
;
807 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
808 const struct prefix_evpn
*evp
=
809 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
810 int add_prefix_to_json
= 0;
811 char prefix_str
[BUFSIZ
];
812 json_object
*json_paths
= NULL
;
813 json_object
*json_prefix
= NULL
;
814 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
816 prefix2str((struct prefix_evpn
*)bgp_dest_get_prefix(dest
),
817 prefix_str
, sizeof(prefix_str
));
819 if (type
&& evp
->prefix
.route_type
!= type
)
823 json_prefix
= json_object_new_object();
825 pi
= bgp_dest_get_bgp_path_info(dest
);
827 /* Overall header/legend displayed once. */
829 bgp_evpn_show_route_header(vty
, bgp
,
838 json_paths
= json_object_new_array();
840 /* For EVPN, the prefix is displayed for each path (to fit in
841 * with code that already exists).
843 for (; pi
; pi
= pi
->next
) {
844 json_object
*json_path
= NULL
;
846 if (vtep_ip
.s_addr
!= INADDR_ANY
847 && !IPV4_ADDR_SAME(&(vtep_ip
),
848 &(pi
->attr
->nexthop
)))
852 json_path
= json_object_new_array();
855 route_vty_out_detail(vty
, bgp
, dest
, pi
,
856 AFI_L2VPN
, SAFI_EVPN
,
860 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
864 json_object_array_add(json_paths
, json_path
);
867 add_prefix_to_json
= 1;
871 if (add_prefix_to_json
) {
872 json_object_string_add(json_prefix
, "prefix",
874 json_object_int_add(json_prefix
, "prefixLen",
876 json_object_object_add(json_prefix
, "paths",
878 json_object_object_add(json
, prefix_str
,
881 json_object_free(json_paths
);
882 json_object_free(json_prefix
);
890 json_object_int_add(json
, "numPrefix", prefix_cnt
);
891 json_object_int_add(json
, "numPaths", path_cnt
);
894 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
895 type
? "(of requested type) " : "");
897 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
898 prefix_cnt
, path_cnt
,
899 type
? " (of requested type)" : "");
904 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
906 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
907 struct vni_walk_ctx
*wctx
= arg
;
908 struct vty
*vty
= wctx
->vty
;
909 json_object
*json
= wctx
->json
;
910 json_object
*json_vni
= NULL
;
911 char vni_str
[VNI_STR_LEN
];
913 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
915 json_vni
= json_object_new_object();
916 json_object_int_add(json_vni
, "vni", vpn
->vni
);
918 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
921 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
925 json_object_object_add(json
, vni_str
, json_vni
);
928 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
931 json_object
*json_vni
= NULL
;
932 json_object
*json_import_rtl
= NULL
;
933 json_object
*json_export_rtl
= NULL
;
935 char buf2
[INET6_ADDRSTRLEN
];
936 char buf3
[BUFSIZ
] = {0};
939 struct listnode
*node
, *nnode
;
940 struct ecommunity
*ecom
;
946 json_vni
= json_object_new_object();
947 json_import_rtl
= json_object_new_array();
948 json_export_rtl
= json_object_new_array();
951 /* if an l3vni is present in bgp it is live */
953 snprintf(buf1
, sizeof(buf1
), "*");
956 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
957 json_object_string_add(json_vni
, "type", "L3");
958 json_object_string_add(json_vni
, "inKernel", "True");
959 json_object_string_add(json_vni
, "originatorIp",
960 inet_ntop(AF_INET
, &bgp
->originator_ip
,
961 buf3
, sizeof(buf3
)));
962 json_object_string_add(
964 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
965 json_object_string_add(json_vni
, "advertiseGatewayMacip",
967 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
968 json_object_string_add(
969 json_vni
, "advertisePip",
970 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
971 json_object_string_add(json_vni
, "sysIP",
973 &bgp
->evpn_info
->pip_ip
, buf3
,
975 json_object_string_add(json_vni
, "sysMAC",
976 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
977 buf2
, sizeof(buf2
)));
978 json_object_string_add(
980 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
982 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
983 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
986 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
987 ecom_str
= ecommunity_ecom2str(ecom
,
988 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
991 json_object_array_add(json_import_rtl
,
992 json_object_new_string(ecom_str
));
994 if (listcount(bgp
->vrf_import_rtl
) > 1)
995 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
998 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1000 vty_out(vty
, " %-25s", rt_buf
);
1003 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1005 /* If there are multiple import RTs we break here and show only
1012 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1014 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
1015 ecom_str
= ecommunity_ecom2str(ecom
,
1016 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1019 json_object_array_add(json_export_rtl
,
1020 json_object_new_string(ecom_str
));
1022 if (listcount(bgp
->vrf_export_rtl
) > 1)
1023 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1026 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1028 vty_out(vty
, " %-25s", rt_buf
);
1031 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1033 /* If there are multiple export RTs we break here and show only
1040 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1043 char vni_str
[VNI_STR_LEN
];
1045 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1046 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1047 json_object_object_add(json
, vni_str
, json_vni
);
1053 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1057 json_object
*json_vni
= NULL
;
1058 json_object
*json_import_rtl
= NULL
;
1059 json_object
*json_export_rtl
= NULL
;
1060 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1062 char buf2
[RD_ADDRSTRLEN
];
1063 char buf3
[BUFSIZ
] = {0};
1066 struct listnode
*node
, *nnode
;
1067 struct ecommunity
*ecom
;
1068 struct bgp
*bgp_evpn
;
1073 bgp_evpn
= bgp_get_evpn();
1076 json_vni
= json_object_new_object();
1077 json_import_rtl
= json_object_new_array();
1078 json_export_rtl
= json_object_new_array();
1082 if (is_vni_live(vpn
))
1083 snprintf(buf1
, sizeof(buf1
), "*");
1086 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1087 json_object_string_add(json_vni
, "type", "L2");
1088 json_object_string_add(json_vni
, "inKernel",
1089 is_vni_live(vpn
) ? "True" : "False");
1090 json_object_string_add(
1092 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1093 json_object_string_add(json_vni
, "originatorIp",
1094 inet_ntop(AF_INET
, &vpn
->originator_ip
,
1095 buf3
, sizeof(buf3
)));
1096 json_object_string_add(json_vni
, "mcastGroup",
1097 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf3
,
1099 /* per vni knob is enabled -- Enabled
1100 * Global knob is enabled -- Active
1101 * default -- Disabled
1103 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1104 && bgp_evpn
->advertise_gw_macip
)
1105 json_object_string_add(
1106 json_vni
, "advertiseGatewayMacip", "Active");
1107 else if (vpn
->advertise_gw_macip
)
1108 json_object_string_add(
1109 json_vni
, "advertiseGatewayMacip", "Enabled");
1111 json_object_string_add(
1112 json_vni
, "advertiseGatewayMacip", "Disabled");
1113 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1114 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1115 json_object_string_add(json_vni
, "advertiseSviMacIp",
1117 else if (vpn
->advertise_svi_macip
)
1118 json_object_string_add(json_vni
, "advertiseSviMacIp",
1121 json_object_string_add(json_vni
, "advertiseSviMacIp",
1124 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1125 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1128 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1129 ecom_str
= ecommunity_ecom2str(ecom
,
1130 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1133 json_object_array_add(json_import_rtl
,
1134 json_object_new_string(ecom_str
));
1136 if (listcount(vpn
->import_rtl
) > 1)
1137 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1140 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1142 vty_out(vty
, " %-25s", rt_buf
);
1145 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1147 /* If there are multiple import RTs we break here and show only
1154 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1156 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1157 ecom_str
= ecommunity_ecom2str(ecom
,
1158 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1161 json_object_array_add(json_export_rtl
,
1162 json_object_new_string(ecom_str
));
1164 if (listcount(vpn
->export_rtl
) > 1)
1165 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1168 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1170 vty_out(vty
, " %-25s", rt_buf
);
1173 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1175 /* If there are multiple export RTs we break here and show only
1182 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1185 char vni_str
[VNI_STR_LEN
];
1187 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1188 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1189 json_object_object_add(json
, vni_str
, json_vni
);
1195 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1196 enum bgp_show_type type
, void *output_arg
,
1197 int option
, bool use_json
)
1199 afi_t afi
= AFI_L2VPN
;
1201 struct bgp_table
*table
;
1202 struct bgp_dest
*dest
;
1203 struct bgp_dest
*rm
;
1204 struct bgp_path_info
*pi
;
1207 char rd_str
[RD_ADDRSTRLEN
];
1210 char router_id
[BUFSIZ
] = {0};
1212 unsigned long output_count
= 0;
1213 unsigned long total_count
= 0;
1214 json_object
*json
= NULL
;
1215 json_object
*json_array
= NULL
;
1216 json_object
*json_prefix_info
= NULL
;
1218 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1220 bgp
= bgp_get_evpn();
1223 vty_out(vty
, "No BGP process is configured\n");
1225 vty_out(vty
, "{}\n");
1230 json
= json_object_new_object();
1232 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1233 dest
= bgp_route_next(dest
)) {
1235 json_object
*json_nroute
= NULL
;
1236 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1238 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1241 table
= bgp_dest_get_bgp_table_info(dest
);
1246 tbl_ver
= table
->version
;
1248 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1249 pi
= bgp_dest_get_bgp_path_info(rm
);
1254 for (; pi
; pi
= pi
->next
) {
1256 if (type
== bgp_show_type_neighbor
) {
1257 struct peer
*peer
= output_arg
;
1259 if (peer_cmp(peer
, pi
->peer
) != 0)
1262 if (type
== bgp_show_type_lcommunity_exact
) {
1263 struct lcommunity
*lcom
= output_arg
;
1265 if (!pi
->attr
->lcommunity
||
1267 pi
->attr
->lcommunity
, lcom
))
1270 if (type
== bgp_show_type_lcommunity
) {
1271 struct lcommunity
*lcom
= output_arg
;
1273 if (!pi
->attr
->lcommunity
||
1275 pi
->attr
->lcommunity
, lcom
))
1278 if (type
== bgp_show_type_community
) {
1279 struct community
*com
= output_arg
;
1281 if (!pi
->attr
->community
||
1283 pi
->attr
->community
, com
))
1286 if (type
== bgp_show_type_community_exact
) {
1287 struct community
*com
= output_arg
;
1289 if (!pi
->attr
->community
||
1291 pi
->attr
->community
, com
))
1296 json_object_int_add(
1297 json
, "bgpTableVersion",
1299 json_object_string_add(
1306 sizeof(router_id
)));
1307 json_object_int_add(
1310 bgp
->default_local_pref
);
1311 json_object_int_add(
1315 if (option
== SHOW_DISPLAY_TAGS
)
1320 == SHOW_DISPLAY_OVERLAY
)
1324 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1332 json_object_new_object();
1333 bgp_evpn_show_route_rd_header(
1334 vty
, dest
, json_nroute
, rd_str
,
1338 if (use_json
&& !json_array
)
1339 json_array
= json_object_new_array();
1341 if (option
== SHOW_DISPLAY_TAGS
)
1343 vty
, bgp_dest_get_prefix(rm
),
1344 pi
, no_display
, SAFI_EVPN
,
1346 else if (option
== SHOW_DISPLAY_OVERLAY
)
1347 route_vty_out_overlay(
1348 vty
, bgp_dest_get_prefix(rm
),
1349 pi
, no_display
, json_array
);
1352 bgp_dest_get_prefix(rm
),
1353 pi
, no_display
, SAFI_EVPN
,
1361 if (use_json
&& json_array
) {
1362 const struct prefix
*p
=
1363 bgp_dest_get_prefix(rm
);
1365 json_prefix_info
= json_object_new_object();
1367 json_object_string_add(
1368 json_prefix_info
, "prefix",
1369 prefix2str((struct prefix_evpn
*)p
, buf
,
1372 json_object_int_add(json_prefix_info
,
1373 "prefixLen", p
->prefixlen
);
1375 json_object_object_add(json_prefix_info
,
1376 "paths", json_array
);
1377 json_object_object_add(json_nroute
, buf
,
1383 if (use_json
&& json_nroute
)
1384 json_object_object_add(json
, rd_str
, json_nroute
);
1388 json_object_int_add(json
, "numPrefix", output_count
);
1389 json_object_int_add(json
, "totalPrefix", total_count
);
1390 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1391 json
, JSON_C_TO_STRING_PRETTY
));
1392 json_object_free(json
);
1394 if (output_count
== 0)
1395 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1399 "\nDisplayed %ld out of %ld total prefixes\n",
1400 output_count
, total_count
);
1405 DEFUN(show_ip_bgp_l2vpn_evpn
,
1406 show_ip_bgp_l2vpn_evpn_cmd
,
1407 "show [ip] bgp l2vpn evpn [json]",
1408 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1410 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1411 SHOW_DISPLAY_STANDARD
,
1412 use_json(argc
, argv
));
1415 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1416 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1417 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1423 "Display information for a route distinguisher\n"
1424 "VPN Route Distinguisher\n"
1425 "All VPN Route Distinguishers\n"
1428 int idx_ext_community
= 0;
1430 struct prefix_rd prd
;
1433 argv_find(argv
, argc
, "all", &rd_all
);
1435 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1436 NULL
, SHOW_DISPLAY_STANDARD
,
1437 use_json(argc
, argv
));
1439 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1440 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1442 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1445 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1446 SHOW_DISPLAY_STANDARD
,
1447 use_json(argc
, argv
));
1450 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1451 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1452 "show [ip] bgp l2vpn evpn all tags",
1458 "Display information about all EVPN NLRIs\n"
1459 "Display BGP tags for prefixes\n")
1461 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1462 SHOW_DISPLAY_TAGS
, 0);
1465 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1466 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1467 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1473 "Display information for a route distinguisher\n"
1474 "VPN Route Distinguisher\n"
1475 "All VPN Route Distinguishers\n"
1476 "Display BGP tags for prefixes\n")
1478 int idx_ext_community
= 0;
1480 struct prefix_rd prd
;
1483 argv_find(argv
, argc
, "all", &rd_all
);
1485 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1486 NULL
, SHOW_DISPLAY_TAGS
, 0);
1488 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1489 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1491 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1494 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1495 SHOW_DISPLAY_TAGS
, 0);
1498 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1499 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1500 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1506 "Detailed information on TCP and BGP neighbor connections\n"
1507 "IPv4 Neighbor to display information about\n"
1508 "IPv6 Neighbor to display information about\n"
1509 "Neighbor on BGP configured interface\n"
1510 "Display routes learned from neighbor\n" JSON_STR
)
1514 char *peerstr
= NULL
;
1515 bool uj
= use_json(argc
, argv
);
1516 afi_t afi
= AFI_L2VPN
;
1517 safi_t safi
= SAFI_EVPN
;
1518 struct bgp
*bgp
= NULL
;
1520 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1523 vty_out(vty
, "No index\n");
1527 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1528 argv_find(argv
, argc
, "neighbors", &idx
);
1529 peerstr
= argv
[++idx
]->arg
;
1531 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1534 json_object
*json_no
= NULL
;
1535 json_no
= json_object_new_object();
1536 json_object_string_add(json_no
, "warning",
1537 "Malformed address");
1538 vty_out(vty
, "%s\n",
1539 json_object_to_json_string(json_no
));
1540 json_object_free(json_no
);
1542 vty_out(vty
, "Malformed address: %s\n",
1546 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1548 json_object
*json_no
= NULL
;
1549 json_no
= json_object_new_object();
1550 json_object_string_add(
1552 "No such neighbor or address family");
1553 vty_out(vty
, "%s\n",
1554 json_object_to_json_string(json_no
));
1555 json_object_free(json_no
);
1557 vty_out(vty
, "%% No such neighbor or address family\n");
1561 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1562 SHOW_DISPLAY_STANDARD
, uj
);
1565 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1566 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1567 "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]",
1573 "Display information for a route distinguisher\n"
1574 "VPN Route Distinguisher\n"
1575 "All VPN Route Distinguishers\n"
1576 "Detailed information on TCP and BGP neighbor connections\n"
1577 "IPv4 Neighbor to display information about\n"
1578 "IPv6 Neighbor to display information about\n"
1579 "Neighbor on BGP configured interface\n"
1580 "Display routes learned from neighbor\n" JSON_STR
)
1582 int idx_ext_community
= 0;
1586 char *peerstr
= NULL
;
1587 struct prefix_rd prd
;
1588 bool uj
= use_json(argc
, argv
);
1589 afi_t afi
= AFI_L2VPN
;
1590 safi_t safi
= SAFI_EVPN
;
1591 struct bgp
*bgp
= NULL
;
1594 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1597 vty_out(vty
, "No index\n");
1601 argv_find(argv
, argc
, "all", &rd_all
);
1603 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1604 &idx_ext_community
);
1605 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1608 json_object
*json_no
= NULL
;
1609 json_no
= json_object_new_object();
1610 json_object_string_add(
1612 "Malformed Route Distinguisher");
1613 vty_out(vty
, "%s\n",
1614 json_object_to_json_string(json_no
));
1615 json_object_free(json_no
);
1618 "%% Malformed Route Distinguisher\n");
1623 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1624 argv_find(argv
, argc
, "neighbors", &idx
);
1625 peerstr
= argv
[++idx
]->arg
;
1627 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1630 json_object
*json_no
= NULL
;
1631 json_no
= json_object_new_object();
1632 json_object_string_add(json_no
, "warning",
1633 "Malformed address");
1634 vty_out(vty
, "%s\n",
1635 json_object_to_json_string(json_no
));
1636 json_object_free(json_no
);
1638 vty_out(vty
, "Malformed address: %s\n",
1642 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1644 json_object
*json_no
= NULL
;
1645 json_no
= json_object_new_object();
1646 json_object_string_add(
1648 "No such neighbor or address family");
1649 vty_out(vty
, "%s\n",
1650 json_object_to_json_string(json_no
));
1651 json_object_free(json_no
);
1653 vty_out(vty
, "%% No such neighbor or address family\n");
1659 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1660 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1662 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1663 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1666 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1667 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1668 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1674 "Detailed information on TCP and BGP neighbor connections\n"
1675 "IPv4 Neighbor to display information about\n"
1676 "IPv6 Neighbor to display information about\n"
1677 "Neighbor on BGP configured interface\n"
1678 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1682 bool uj
= use_json(argc
, argv
);
1683 struct bgp
*bgp
= NULL
;
1684 afi_t afi
= AFI_L2VPN
;
1685 safi_t safi
= SAFI_EVPN
;
1686 char *peerstr
= NULL
;
1691 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1694 vty_out(vty
, "No index\n");
1698 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1699 argv_find(argv
, argc
, "neighbors", &idx
);
1700 peerstr
= argv
[++idx
]->arg
;
1702 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1705 json_object
*json_no
= NULL
;
1706 json_no
= json_object_new_object();
1707 json_object_string_add(json_no
, "warning",
1708 "Malformed address");
1709 vty_out(vty
, "%s\n",
1710 json_object_to_json_string(json_no
));
1711 json_object_free(json_no
);
1713 vty_out(vty
, "Malformed address: %s\n",
1717 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1719 json_object
*json_no
= NULL
;
1720 json_no
= json_object_new_object();
1721 json_object_string_add(
1723 "No such neighbor or address family");
1724 vty_out(vty
, "%s\n",
1725 json_object_to_json_string(json_no
));
1726 json_object_free(json_no
);
1728 vty_out(vty
, "%% No such neighbor or address family\n");
1732 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1735 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1736 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1737 "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]",
1743 "Display information for a route distinguisher\n"
1744 "VPN Route Distinguisher\n"
1745 "All VPN Route Distinguishers\n"
1746 "Detailed information on TCP and BGP neighbor connections\n"
1747 "IPv4 Neighbor to display information about\n"
1748 "IPv6 Neighbor to display information about\n"
1749 "Neighbor on BGP configured interface\n"
1750 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1752 int idx_ext_community
= 0;
1756 struct prefix_rd prd
;
1757 struct bgp
*bgp
= NULL
;
1758 bool uj
= use_json(argc
, argv
);
1759 char *peerstr
= NULL
;
1760 afi_t afi
= AFI_L2VPN
;
1761 safi_t safi
= SAFI_EVPN
;
1770 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1773 vty_out(vty
, "No index\n");
1777 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1778 argv_find(argv
, argc
, "neighbors", &idx
);
1779 peerstr
= argv
[++idx
]->arg
;
1781 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1784 json_object
*json_no
= NULL
;
1785 json_no
= json_object_new_object();
1786 json_object_string_add(json_no
, "warning",
1787 "Malformed address");
1788 vty_out(vty
, "%s\n",
1789 json_object_to_json_string(json_no
));
1790 json_object_free(json_no
);
1792 vty_out(vty
, "Malformed address: %s\n",
1796 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1798 json_object
*json_no
= NULL
;
1799 json_no
= json_object_new_object();
1800 json_object_string_add(
1802 "No such neighbor or address family");
1803 vty_out(vty
, "%s\n",
1804 json_object_to_json_string(json_no
));
1805 json_object_free(json_no
);
1807 vty_out(vty
, "%% No such neighbor or address family\n");
1811 argv_find(argv
, argc
, "all", &rd_all
);
1813 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1816 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1817 &idx_ext_community
);
1818 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1821 json_object
*json_no
= NULL
;
1822 json_no
= json_object_new_object();
1823 json_object_string_add(
1825 "Malformed Route Distinguisher");
1826 vty_out(vty
, "%s\n",
1827 json_object_to_json_string(json_no
));
1828 json_object_free(json_no
);
1831 "%% Malformed Route Distinguisher\n");
1836 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1839 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1840 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1841 "show [ip] bgp l2vpn evpn all overlay [json]",
1847 "Display information about all EVPN NLRIs\n"
1848 "Display BGP Overlay Information for prefixes\n"
1851 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1852 SHOW_DISPLAY_OVERLAY
,
1853 use_json(argc
, argv
));
1856 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1857 show_ip_bgp_evpn_rd_overlay_cmd
,
1858 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1864 "Display information for a route distinguisher\n"
1865 "VPN Route Distinguisher\n"
1866 "All VPN Route Distinguishers\n"
1867 "Display BGP Overlay Information for prefixes\n")
1869 int idx_ext_community
= 0;
1871 struct prefix_rd prd
;
1874 argv_find(argv
, argc
, "all", &rd_all
);
1876 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1877 NULL
, SHOW_DISPLAY_OVERLAY
,
1878 use_json(argc
, argv
));
1880 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1881 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1883 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1886 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1887 SHOW_DISPLAY_OVERLAY
,
1888 use_json(argc
, argv
));
1891 DEFUN(show_bgp_l2vpn_evpn_com
,
1892 show_bgp_l2vpn_evpn_com_cmd
,
1893 "show bgp l2vpn evpn \
1894 <community AA:NN|large-community AA:BB:CC> \
1895 [exact-match] [json]",
1900 "Display routes matching the community\n"
1901 "Community number where AA and NN are (0-65535)\n"
1902 "Display routes matching the large-community\n"
1903 "List of large-community numbers\n"
1904 "Exact match of the communities\n"
1909 const char *clist_number_or_name
;
1910 int show_type
= bgp_show_type_normal
;
1911 struct community
*com
;
1912 struct lcommunity
*lcom
;
1914 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1915 clist_number_or_name
= argv
[++idx
]->arg
;
1916 show_type
= bgp_show_type_lcommunity
;
1918 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1919 show_type
= bgp_show_type_lcommunity_exact
;
1921 lcom
= lcommunity_str2com(clist_number_or_name
);
1923 vty_out(vty
, "%% Large-community malformed\n");
1927 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1928 SHOW_DISPLAY_STANDARD
,
1929 use_json(argc
, argv
));
1931 lcommunity_free(&lcom
);
1932 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1933 clist_number_or_name
= argv
[++idx
]->arg
;
1934 show_type
= bgp_show_type_community
;
1936 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1937 show_type
= bgp_show_type_community_exact
;
1939 com
= community_str2com(clist_number_or_name
);
1942 vty_out(vty
, "%% Community malformed: %s\n",
1943 clist_number_or_name
);
1947 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1948 SHOW_DISPLAY_STANDARD
,
1949 use_json(argc
, argv
));
1950 community_free(&com
);
1956 /* For testing purpose, static route of EVPN RT-5. */
1957 DEFUN(evpnrt5_network
,
1958 evpnrt5_network_cmd
,
1959 "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 WORD]",
1960 "Specify a network to announce via BGP\n"
1963 "Specify Route Distinguisher\n"
1964 "VPN Route Distinguisher\n"
1966 "Ethernet Tag Value\n"
1969 "Ethernet Segment Identifier\n"
1970 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1972 "Gateway IP ( A.B.C.D )\n"
1973 "Gateway IPv6 ( X:X::X:X )\n"
1974 "Router Mac Ext Comm\n"
1975 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1976 "Route-map to modify the attributes\n"
1977 "Name of the route map\n")
1979 int idx_ipv4_prefixlen
= 1;
1980 int idx_route_distinguisher
= 3;
1985 int idx_routermac
= 13;
1987 return bgp_static_set_safi(
1988 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1989 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1990 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1991 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1992 argv
[idx_routermac
]->arg
);
1995 /* For testing purpose, static route of EVPN RT-5. */
1996 DEFUN(no_evpnrt5_network
,
1997 no_evpnrt5_network_cmd
,
1998 "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>",
2000 "Specify a network to announce via BGP\n"
2003 "Specify Route Distinguisher\n"
2004 "VPN Route Distinguisher\n"
2006 "Ethernet Tag Value\n"
2009 "Ethernet Segment Identifier\n"
2010 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2011 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2013 int idx_ipv4_prefixlen
= 2;
2014 int idx_ext_community
= 4;
2019 return bgp_static_unset_safi(
2020 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2021 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2022 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2023 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2026 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2028 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2031 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2033 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2037 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2038 * check that this is a change.
2040 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2041 struct ecommunity
*ecomadd
)
2043 /* If the VNI is "live", we need to uninstall routes using the current
2044 * import RT(s) first before we update the import RT, and subsequently
2047 if (is_vni_live(vpn
))
2048 bgp_evpn_uninstall_routes(bgp
, vpn
);
2050 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2051 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2053 /* If the auto route-target is in use we must remove it */
2054 evpn_import_rt_delete_auto(bgp
, vpn
);
2056 /* Add new RT and rebuild the RT to VNI mapping */
2057 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2059 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2060 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2062 /* Install routes that match new import RT */
2063 if (is_vni_live(vpn
))
2064 bgp_evpn_install_routes(bgp
, vpn
);
2068 * Unconfigure Import RT(s) for a VNI (vty handler).
2070 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2071 struct ecommunity
*ecomdel
)
2073 struct listnode
*node
, *nnode
, *node_to_del
;
2074 struct ecommunity
*ecom
;
2076 /* Along the lines of "configure" except we have to reset to the
2079 if (is_vni_live(vpn
))
2080 bgp_evpn_uninstall_routes(bgp
, vpn
);
2082 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2083 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2085 /* Delete all import RTs */
2086 if (ecomdel
== NULL
) {
2087 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2088 ecommunity_free(&ecom
);
2089 list_delete_node(vpn
->import_rtl
, node
);
2093 /* Delete a specific import RT */
2097 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2098 if (ecommunity_match(ecom
, ecomdel
)) {
2099 ecommunity_free(&ecom
);
2106 list_delete_node(vpn
->import_rtl
, node_to_del
);
2109 assert(vpn
->import_rtl
);
2110 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2111 if (list_isempty(vpn
->import_rtl
)) {
2112 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2113 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2115 /* Rebuild the RT to VNI mapping */
2117 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2119 /* Install routes that match new import RT */
2120 if (is_vni_live(vpn
))
2121 bgp_evpn_install_routes(bgp
, vpn
);
2125 * Configure the Export RT for a VNI (vty handler). Caller expected to
2126 * check that this is a change. Note that only a single export RT is
2127 * allowed for a VNI and any change to configuration is implemented as
2128 * a "replace" (similar to other configuration).
2130 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2131 struct ecommunity
*ecomadd
)
2133 /* If the auto route-target is in use we must remove it */
2134 evpn_export_rt_delete_auto(bgp
, vpn
);
2136 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2137 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2139 if (is_vni_live(vpn
))
2140 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2144 * Unconfigure the Export RT for a VNI (vty handler)
2146 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2147 struct ecommunity
*ecomdel
)
2149 struct listnode
*node
, *nnode
, *node_to_del
;
2150 struct ecommunity
*ecom
;
2152 /* Delete all export RTs */
2153 if (ecomdel
== NULL
) {
2154 /* Reset to default and process all routes. */
2155 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2156 ecommunity_free(&ecom
);
2157 list_delete_node(vpn
->export_rtl
, node
);
2161 /* Delete a specific export RT */
2165 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2166 if (ecommunity_match(ecom
, ecomdel
)) {
2167 ecommunity_free(&ecom
);
2174 list_delete_node(vpn
->export_rtl
, node_to_del
);
2177 assert(vpn
->export_rtl
);
2178 if (list_isempty(vpn
->export_rtl
)) {
2179 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2180 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2183 if (is_vni_live(vpn
))
2184 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2188 * Configure RD for VRF
2190 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2192 /* If we have already advertise type-5 routes with a diffrent RD, we
2193 * have to delete and withdraw them firs
2195 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2198 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2199 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2201 /* We have a new RD for VRF.
2202 * Advertise all type-5 routes again with the new RD
2204 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2208 * Unconfigure RD for VRF
2210 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2212 /* If we have already advertise type-5 routes with a diffrent RD, we
2213 * have to delete and withdraw them firs
2215 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2217 /* fall back to default RD */
2218 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2219 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2221 /* We have a new RD for VRF.
2222 * Advertise all type-5 routes again with the new RD
2224 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2228 * Configure RD for a VNI (vty handler)
2230 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2231 struct prefix_rd
*rd
)
2233 /* If the VNI is "live", we need to delete and withdraw this VNI's
2234 * local routes with the prior RD first. Then, after updating RD,
2235 * need to re-advertise.
2237 if (is_vni_live(vpn
))
2238 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2241 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2242 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2244 if (is_vni_live(vpn
))
2245 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2249 * Unconfigure RD for a VNI (vty handler)
2251 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2253 /* If the VNI is "live", we need to delete and withdraw this VNI's
2254 * local routes with the prior RD first. Then, after resetting RD
2255 * to automatic value, need to re-advertise.
2257 if (is_vni_live(vpn
))
2258 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2260 /* reset RD to default */
2261 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2263 if (is_vni_live(vpn
))
2264 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2268 * Create VNI, if not already present (VTY handler). Mark as configured.
2270 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2272 struct bgpevpn
*vpn
;
2273 struct in_addr mcast_grp
= {INADDR_ANY
};
2278 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2280 /* Check if this L2VNI is already configured as L3VNI */
2281 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2284 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2289 /* tenant vrf will be updated when we get local_vni_add from
2292 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2296 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2302 /* Mark as configured. */
2303 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2308 * Delete VNI. If VNI does not exist in the system (i.e., just
2309 * configuration), all that is needed is to free it. Otherwise,
2310 * any parameters configured for the VNI need to be reset (with
2311 * appropriate action) and the VNI marked as unconfigured; the
2312 * VNI will continue to exist, purely as a "learnt" entity.
2314 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2316 assert(bgp
->vnihash
);
2318 if (!is_vni_live(vpn
)) {
2319 bgp_evpn_free(bgp
, vpn
);
2323 /* We need to take the unconfigure action for each parameter of this VNI
2324 * that is configured. Some optimization is possible, but not worth the
2325 * additional code for an operation that should be pretty rare.
2327 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2329 /* First, deal with the export side - RD and export RT changes. */
2330 if (is_rd_configured(vpn
))
2331 evpn_unconfigure_rd(bgp
, vpn
);
2332 if (is_export_rt_configured(vpn
))
2333 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2335 /* Next, deal with the import side. */
2336 if (is_import_rt_configured(vpn
))
2337 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2341 * Display import RT mapping to VRFs (vty handler)
2342 * bgp_evpn: evpn bgp instance
2344 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2352 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2353 (void (*)(struct hash_bucket
*,
2354 void *))show_vrf_import_rt_entry
,
2359 * Display import RT mapping to VNIs (vty handler)
2361 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2370 bgp
->import_rt_hash
,
2371 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2376 * Display EVPN routes for all VNIs - vty handler.
2378 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2379 struct in_addr vtep_ip
, json_object
*json
,
2383 struct vni_walk_ctx wctx
;
2385 num_vnis
= hashcount(bgp
->vnihash
);
2388 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2391 wctx
.vtep_ip
= vtep_ip
;
2393 wctx
.detail
= detail
;
2394 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2395 void *))show_vni_routes_hash
,
2400 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2402 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2403 vni_t vni
, struct in_addr orig_ip
,
2406 struct bgpevpn
*vpn
;
2407 struct prefix_evpn p
;
2408 struct bgp_dest
*dest
;
2409 struct bgp_path_info
*pi
;
2410 uint32_t path_cnt
= 0;
2413 json_object
*json_paths
= NULL
;
2419 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2421 vty_out(vty
, "VNI not found\n");
2425 /* See if route exists. */
2426 build_evpn_type3_prefix(&p
, orig_ip
);
2427 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2428 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2430 vty_out(vty
, "%% Network not in table\n");
2433 bgp_dest_unlock_node(dest
);
2439 json_paths
= json_object_new_array();
2441 /* Prefix and num paths displayed once per prefix. */
2442 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2444 /* Display each path for this prefix. */
2445 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2446 json_object
*json_path
= NULL
;
2449 json_path
= json_object_new_array();
2451 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2452 RPKI_NOT_BEING_USED
, json_path
);
2455 json_object_array_add(json_paths
, json_path
);
2462 json_object_object_add(json
, "paths", json_paths
);
2464 json_object_int_add(json
, "numPaths", path_cnt
);
2466 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2470 bgp_dest_unlock_node(dest
);
2474 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2475 * By definition, only matching type-2 route will be displayed.
2477 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2478 vni_t vni
, struct ethaddr
*mac
,
2479 struct ipaddr
*ip
, json_object
*json
)
2481 struct bgpevpn
*vpn
;
2482 struct prefix_evpn p
;
2483 struct bgp_dest
*dest
;
2484 struct bgp_path_info
*pi
;
2485 uint32_t path_cnt
= 0;
2488 json_object
*json_paths
= NULL
;
2494 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2497 vty_out(vty
, "VNI not found\n");
2501 /* See if route exists. Look for both non-sticky and sticky. */
2502 build_evpn_type2_prefix(&p
, mac
, ip
);
2503 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2504 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2506 vty_out(vty
, "%% Network not in table\n");
2509 bgp_dest_unlock_node(dest
);
2515 json_paths
= json_object_new_array();
2517 /* Prefix and num paths displayed once per prefix. */
2518 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2520 /* Display each path for this prefix. */
2521 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2522 json_object
*json_path
= NULL
;
2525 json_path
= json_object_new_array();
2527 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2528 RPKI_NOT_BEING_USED
, json_path
);
2531 json_object_array_add(json_paths
, json_path
);
2538 json_object_object_add(json
, "paths", json_paths
);
2540 json_object_int_add(json
, "numPaths", path_cnt
);
2542 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2546 bgp_dest_unlock_node(dest
);
2549 /* Disaplay EVPN routes for a ESI - VTY handler */
2550 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2551 esi_t
*esi
, json_object
*json
)
2553 struct bgp_evpn_es
*es
= NULL
;
2556 es
= bgp_evpn_es_find(esi
);
2559 vty_out(vty
, "ESI not found\n");
2563 show_esi_routes(bgp
, es
, vty
, json
);
2567 * Display EVPN routes for a VNI - vty handler.
2568 * If 'type' is non-zero, only routes matching that type are shown.
2569 * If the vtep_ip is non zero, only routes behind that vtep are shown
2571 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2572 int type
, struct in_addr vtep_ip
,
2575 struct bgpevpn
*vpn
;
2578 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2581 vty_out(vty
, "VNI not found\n");
2585 /* Walk this VNI's route table and display appropriate routes. */
2586 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2590 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2591 * IP (vty handler). By definition, only matching type-2 route will be
2594 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2595 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2596 struct ipaddr
*ip
, json_object
*json
)
2598 struct prefix_evpn p
;
2599 struct bgp_dest
*dest
;
2600 struct bgp_path_info
*pi
;
2603 uint32_t path_cnt
= 0;
2604 json_object
*json_paths
= NULL
;
2605 char prefix_str
[BUFSIZ
];
2610 /* See if route exists. Look for both non-sticky and sticky. */
2611 build_evpn_type2_prefix(&p
, mac
, ip
);
2612 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2613 (struct prefix
*)&p
, prd
);
2614 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2616 vty_out(vty
, "%% Network not in table\n");
2619 bgp_dest_unlock_node(dest
);
2624 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2626 /* Prefix and num paths displayed once per prefix. */
2627 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2630 json_paths
= json_object_new_array();
2632 /* Display each path for this prefix. */
2633 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2634 json_object
*json_path
= NULL
;
2637 json_path
= json_object_new_array();
2639 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2640 RPKI_NOT_BEING_USED
, json_path
);
2643 json_object_array_add(json_paths
, json_path
);
2648 if (json
&& path_cnt
) {
2650 json_object_object_add(json
, prefix_str
, json_paths
);
2651 json_object_int_add(json
, "numPaths", path_cnt
);
2653 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2657 bgp_dest_unlock_node(dest
);
2661 * Display BGP EVPN routing table -- for specific RD (vty handler)
2662 * If 'type' is non-zero, only routes matching that type are shown.
2664 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2665 struct prefix_rd
*prd
, int type
,
2668 struct bgp_dest
*rd_dest
;
2669 struct bgp_table
*table
;
2670 struct bgp_dest
*dest
;
2671 struct bgp_path_info
*pi
;
2675 uint32_t prefix_cnt
, path_cnt
;
2676 char rd_str
[RD_ADDRSTRLEN
];
2677 json_object
*json_rd
= NULL
;
2678 int add_rd_to_json
= 0;
2682 prefix_cnt
= path_cnt
= 0;
2684 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2686 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2690 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2691 if (table
== NULL
) {
2692 bgp_dest_unlock_node(rd_dest
);
2697 json_rd
= json_object_new_object();
2698 json_object_string_add(json_rd
, "rd", rd_str
);
2701 bgp_dest_unlock_node(rd_dest
);
2703 /* Display all prefixes with this RD. */
2704 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2705 const struct prefix_evpn
*evp
=
2706 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2707 json_object
*json_prefix
= NULL
;
2708 json_object
*json_paths
= NULL
;
2709 char prefix_str
[BUFSIZ
];
2710 int add_prefix_to_json
= 0;
2712 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2713 sizeof(prefix_str
));
2715 if (type
&& evp
->prefix
.route_type
!= type
)
2719 json_prefix
= json_object_new_object();
2721 pi
= bgp_dest_get_bgp_path_info(dest
);
2723 /* RD header and legend - once overall. */
2724 if (rd_header
&& !json
) {
2726 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
2728 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2730 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2732 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2734 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2738 /* Prefix and num paths displayed once per prefix. */
2739 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2746 json_paths
= json_object_new_array();
2748 /* Display each path for this prefix. */
2749 for (; pi
; pi
= pi
->next
) {
2750 json_object
*json_path
= NULL
;
2753 json_path
= json_object_new_array();
2755 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2756 RPKI_NOT_BEING_USED
, json_path
);
2759 json_object_array_add(json_paths
, json_path
);
2762 add_prefix_to_json
= 1;
2767 if (add_prefix_to_json
) {
2768 json_object_object_add(json_prefix
, "paths",
2770 json_object_object_add(json_rd
, prefix_str
,
2773 json_object_free(json_paths
);
2774 json_object_free(json_prefix
);
2783 json_object_object_add(json
, rd_str
, json_rd
);
2785 json_object_free(json_rd
);
2789 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2790 json_object_int_add(json
, "numPaths", path_cnt
);
2792 if (prefix_cnt
== 0)
2793 vty_out(vty
, "No prefixes exist with this RD%s\n",
2794 type
? " (of requested type)" : "");
2797 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2798 prefix_cnt
, path_cnt
,
2799 type
? " (of requested type)" : "");
2804 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2805 * (vty handler). Only matching type-2 routes will be displayed.
2807 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2808 struct ethaddr
*mac
, struct ipaddr
*ip
,
2811 struct bgp_dest
*rd_dest
;
2812 struct bgp_table
*table
;
2813 struct bgp_dest
*dest
;
2814 struct bgp_path_info
*pi
;
2815 afi_t afi
= AFI_L2VPN
;
2816 safi_t safi
= SAFI_EVPN
;
2817 uint32_t prefix_cnt
, path_cnt
;
2818 prefix_cnt
= path_cnt
= 0;
2820 /* EVPN routing table is a 2-level table with the first level being
2821 * the RD. We need to look in every RD we know about.
2823 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2824 rd_dest
= bgp_route_next(rd_dest
)) {
2825 json_object
*json_paths
= NULL
; /* paths array for prefix */
2826 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2827 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2828 char rd_str
[RD_ADDRSTRLEN
];
2829 char prefix_str
[BUFSIZ
];
2830 int add_rd_to_json
= 0;
2831 struct prefix_evpn ep
;
2832 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2834 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2838 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2841 /* Construct an RT-2 from the user-supplied mac(ip),
2842 * then search the l2vpn evpn table for it.
2844 build_evpn_type2_prefix(&ep
, mac
, ip
);
2845 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2846 (struct prefix
*)&ep
,
2847 (struct prefix_rd
*)rd_destp
);
2852 json_rd
= json_object_new_object();
2854 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2856 prefix2str(p
, prefix_str
, sizeof(prefix_str
));
2858 pi
= bgp_dest_get_bgp_path_info(dest
);
2860 /* RD header - per RD. */
2861 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2862 rd_str
, RD_ADDRSTRLEN
);
2867 json_prefix
= json_object_new_object();
2868 json_paths
= json_object_new_array();
2869 json_object_string_add(json_prefix
, "prefix",
2871 json_object_int_add(json_prefix
, "prefixLen",
2874 /* Prefix and num paths displayed once per prefix. */
2875 route_vty_out_detail_header(
2876 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2877 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2879 /* For EVPN, the prefix is displayed for each path (to
2880 * fit in with code that already exists).
2882 for (; pi
; pi
= pi
->next
) {
2883 json_object
*json_path
= NULL
;
2889 json_path
= json_object_new_array();
2891 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2892 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2896 json_object_array_add(json_paths
, json_path
);
2902 json_object_object_add(json_prefix
, "paths",
2904 json_object_object_add(json_rd
, prefix_str
,
2907 json_object_object_add(json
, rd_str
, json_rd
);
2909 json_object_free(json_rd
);
2914 bgp_dest_unlock_node(dest
);
2918 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2919 json_object_int_add(json
, "numPaths", path_cnt
);
2921 if (prefix_cnt
== 0) {
2922 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2924 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2925 prefix_cnt
, path_cnt
);
2931 * Display BGP EVPN routing table - all routes (vty handler).
2932 * If 'type' is non-zero, only routes matching that type are shown.
2934 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2935 json_object
*json
, int detail
)
2937 struct bgp_dest
*rd_dest
;
2938 struct bgp_table
*table
;
2939 struct bgp_dest
*dest
;
2940 struct bgp_path_info
*pi
;
2941 int header
= detail
? 0 : 1;
2945 uint32_t prefix_cnt
, path_cnt
;
2949 prefix_cnt
= path_cnt
= 0;
2951 /* EVPN routing table is a 2-level table with the first level being
2954 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2955 rd_dest
= bgp_route_next(rd_dest
)) {
2956 char rd_str
[RD_ADDRSTRLEN
];
2957 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2958 int add_rd_to_json
= 0;
2960 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2962 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2966 tbl_ver
= table
->version
;
2967 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2971 json_rd
= json_object_new_object();
2975 /* Display all prefixes for an RD */
2976 for (dest
= bgp_table_top(table
); dest
;
2977 dest
= bgp_route_next(dest
)) {
2978 json_object
*json_prefix
=
2979 NULL
; /* contains prefix under a RD */
2980 json_object
*json_paths
=
2981 NULL
; /* array of paths under a prefix*/
2982 const struct prefix_evpn
*evp
=
2983 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2985 char prefix_str
[BUFSIZ
];
2986 int add_prefix_to_json
= 0;
2987 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2989 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2990 sizeof(prefix_str
));
2992 if (type
&& evp
->prefix
.route_type
!= type
)
2995 pi
= bgp_dest_get_bgp_path_info(dest
);
2997 /* Overall header/legend displayed once. */
2999 bgp_evpn_show_route_header(vty
, bgp
,
3004 "%19s Extended Community\n"
3009 /* RD header - per RD. */
3011 bgp_evpn_show_route_rd_header(
3012 vty
, rd_dest
, json_rd
, rd_str
,
3021 json_prefix
= json_object_new_object();
3022 json_paths
= json_object_new_array();
3023 json_object_string_add(json_prefix
, "prefix",
3025 json_object_int_add(json_prefix
, "prefixLen",
3029 /* Prefix and num paths displayed once per prefix. */
3031 route_vty_out_detail_header(
3033 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3034 SAFI_EVPN
, json_prefix
);
3036 /* For EVPN, the prefix is displayed for each path (to
3038 * with code that already exists).
3040 for (; pi
; pi
= pi
->next
) {
3041 json_object
*json_path
= NULL
;
3044 add_prefix_to_json
= 1;
3048 json_path
= json_object_new_array();
3051 route_vty_out_detail(
3052 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
3053 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3056 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3060 json_object_array_add(json_paths
,
3065 if (add_prefix_to_json
) {
3066 json_object_object_add(json_prefix
,
3069 json_object_object_add(json_rd
,
3073 json_object_free(json_prefix
);
3074 json_object_free(json_paths
);
3083 json_object_object_add(json
, rd_str
, json_rd
);
3085 json_object_free(json_rd
);
3092 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3093 json_object_int_add(json
, "numPaths", path_cnt
);
3095 if (prefix_cnt
== 0) {
3096 vty_out(vty
, "No EVPN prefixes %sexist\n",
3097 type
? "(of requested type) " : "");
3099 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3100 prefix_cnt
, path_cnt
,
3101 type
? " (of requested type)" : "");
3107 * Display specified VNI (vty handler)
3109 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3113 struct bgpevpn
*vpn
;
3115 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3118 display_vni(vty
, vpn
, json
);
3120 struct bgp
*bgp_temp
;
3121 struct listnode
*node
= NULL
;
3123 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3124 if (bgp_temp
->l3vni
== vni
) {
3126 display_l3vni(vty
, bgp_temp
, json
);
3133 vty_out(vty
, "{}\n");
3135 vty_out(vty
, "VNI not found\n");
3142 * Display a VNI (upon user query).
3144 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3148 struct bgp
*bgp_temp
= NULL
;
3149 struct listnode
*node
;
3153 vty_out(vty
, "Flags: * - Kernel\n");
3154 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3155 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3158 /* print all L2 VNIS */
3161 hash_iterate(bgp
->vnihash
,
3162 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3165 /* print all L3 VNIs */
3166 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3167 show_l3vni_entry(vty
, bgp_temp
, json
);
3171 * evpn - enable advertisement of svi MAC-IP
3173 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3177 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3179 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3182 bgp
->evpn_info
->advertise_svi_macip
= set
;
3183 bgp_zebra_advertise_svi_macip(bgp
,
3184 bgp
->evpn_info
->advertise_svi_macip
, 0);
3186 if (set
&& vpn
->advertise_svi_macip
)
3188 else if (!set
&& !vpn
->advertise_svi_macip
)
3191 vpn
->advertise_svi_macip
= set
;
3192 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3198 * evpn - enable advertisement of default g/w
3200 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3203 if (bgp
->advertise_gw_macip
)
3206 bgp
->advertise_gw_macip
= 1;
3207 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3209 if (vpn
->advertise_gw_macip
)
3212 vpn
->advertise_gw_macip
= 1;
3213 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3220 * evpn - disable advertisement of default g/w
3222 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3223 struct bgpevpn
*vpn
)
3226 if (!bgp
->advertise_gw_macip
)
3229 bgp
->advertise_gw_macip
= 0;
3230 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3232 if (!vpn
->advertise_gw_macip
)
3235 vpn
->advertise_gw_macip
= 0;
3236 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3243 * evpn - enable advertisement of default g/w
3245 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3246 afi_t afi
, bool add
)
3248 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3251 /* bail if we are already advertising default route */
3252 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3256 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3257 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3258 else if (afi
== AFI_IP6
)
3259 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3260 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3262 /* bail out if we havent advertised the default route */
3263 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3266 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3267 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3268 else if (afi
== AFI_IP6
)
3269 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3270 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3273 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3277 * evpn - enable advertisement of default g/w
3279 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3280 struct bgpevpn
*vpn
)
3282 if (vpn
->advertise_subnet
)
3285 vpn
->advertise_subnet
= 1;
3286 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3290 * evpn - disable advertisement of default g/w
3292 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3294 if (!vpn
->advertise_subnet
)
3297 vpn
->advertise_subnet
= 0;
3298 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3302 * EVPN (VNI advertisement) enabled. Register with zebra.
3304 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3306 bgp
->advertise_all_vni
= 1;
3308 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3312 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3313 * cache, EVPN routes (delete and withdraw from peers).
3315 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3317 bgp
->advertise_all_vni
= 0;
3318 bgp_set_evpn(bgp_get_default());
3319 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3320 bgp_evpn_cleanup_on_disable(bgp
);
3323 /* Set resolve overlay index flag */
3324 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3326 if (set
== bgp
->resolve_overlay_index
)
3330 bgp
->resolve_overlay_index
= true;
3331 hash_iterate(bgp
->vnihash
,
3332 (void (*)(struct hash_bucket
*, void *))
3333 bgp_evpn_handle_resolve_overlay_index_set
,
3338 (void (*)(struct hash_bucket
*, void *))
3339 bgp_evpn_handle_resolve_overlay_index_unset
,
3341 bgp
->resolve_overlay_index
= false;
3346 * EVPN - use RFC8365 to auto-derive RT
3348 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3350 bgp
->advertise_autort_rfc8365
= 1;
3351 bgp_evpn_handle_autort_change(bgp
);
3355 * EVPN - don't use RFC8365 to auto-derive RT
3357 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3359 bgp
->advertise_autort_rfc8365
= 0;
3360 bgp_evpn_handle_autort_change(bgp
);
3363 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3365 char buf1
[RD_ADDRSTRLEN
];
3367 struct listnode
*node
, *nnode
;
3368 struct ecommunity
*ecom
;
3370 if (is_vni_configured(vpn
)) {
3371 vty_out(vty
, " vni %d\n", vpn
->vni
);
3372 if (is_rd_configured(vpn
))
3373 vty_out(vty
, " rd %s\n",
3374 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3376 if (is_import_rt_configured(vpn
)) {
3377 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3379 ecom_str
= ecommunity_ecom2str(
3380 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3381 vty_out(vty
, " route-target import %s\n",
3383 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3387 if (is_export_rt_configured(vpn
)) {
3388 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3390 ecom_str
= ecommunity_ecom2str(
3391 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3392 vty_out(vty
, " route-target export %s\n",
3394 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3398 if (vpn
->advertise_gw_macip
)
3399 vty_out(vty
, " advertise-default-gw\n");
3401 if (vpn
->advertise_svi_macip
)
3402 vty_out(vty
, " advertise-svi-ip\n");
3404 if (vpn
->advertise_subnet
)
3405 vty_out(vty
, " advertise-subnet\n");
3407 vty_out(vty
, " exit-vni\n");
3411 #ifndef VTYSH_EXTRACT_PL
3412 #include "bgpd/bgp_evpn_vty_clippy.c"
3415 DEFPY(bgp_evpn_flood_control
,
3416 bgp_evpn_flood_control_cmd
,
3417 "[no$no] flooding <disable$disable|head-end-replication$her>",
3419 "Specify handling for BUM packets\n"
3420 "Do not flood any BUM packets\n"
3421 "Flood BUM packets using head-end replication\n")
3423 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3424 enum vxlan_flood_control flood_ctrl
;
3430 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3432 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3436 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3439 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3440 bgp_evpn_flood_control_change(bgp
);
3445 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3446 bgp_evpn_advertise_default_gw_vni_cmd
,
3447 "advertise-default-gw",
3448 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3450 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3451 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3456 evpn_set_advertise_default_gw(bgp
, vpn
);
3461 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3462 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3463 "no advertise-default-gw",
3465 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3467 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3468 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3473 evpn_unset_advertise_default_gw(bgp
, vpn
);
3479 DEFUN (bgp_evpn_advertise_default_gw
,
3480 bgp_evpn_advertise_default_gw_cmd
,
3481 "advertise-default-gw",
3482 "Advertise All default g/w mac-ip routes in EVPN\n")
3484 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3489 if (!EVPN_ENABLED(bgp
)) {
3491 "This command is only supported under the EVPN VRF\n");
3495 evpn_set_advertise_default_gw(bgp
, NULL
);
3500 DEFUN (no_bgp_evpn_advertise_default_gw
,
3501 no_bgp_evpn_advertise_default_gw_cmd
,
3502 "no advertise-default-gw",
3504 "Withdraw All default g/w mac-ip routes from EVPN\n")
3506 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3511 evpn_unset_advertise_default_gw(bgp
, NULL
);
3516 DEFUN (bgp_evpn_advertise_all_vni
,
3517 bgp_evpn_advertise_all_vni_cmd
,
3518 "advertise-all-vni",
3519 "Advertise All local VNIs\n")
3521 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3522 struct bgp
*bgp_evpn
= NULL
;
3527 bgp_evpn
= bgp_get_evpn();
3528 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3529 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3531 return CMD_WARNING_CONFIG_FAILED
;
3534 evpn_set_advertise_all_vni(bgp
);
3538 DEFUN (no_bgp_evpn_advertise_all_vni
,
3539 no_bgp_evpn_advertise_all_vni_cmd
,
3540 "no advertise-all-vni",
3542 "Advertise All local VNIs\n")
3544 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3548 evpn_unset_advertise_all_vni(bgp
);
3552 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3553 bgp_evpn_advertise_autort_rfc8365_cmd
,
3554 "autort rfc8365-compatible",
3555 "Auto-derivation of RT\n"
3556 "Auto-derivation of RT using RFC8365\n")
3558 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3562 evpn_set_advertise_autort_rfc8365(bgp
);
3566 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3567 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3568 "no autort rfc8365-compatible",
3570 "Auto-derivation of RT\n"
3571 "Auto-derivation of RT using RFC8365\n")
3573 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3577 evpn_unset_advertise_autort_rfc8365(bgp
);
3581 DEFUN (bgp_evpn_default_originate
,
3582 bgp_evpn_default_originate_cmd
,
3583 "default-originate <ipv4 | ipv6>",
3584 "originate a default route\n"
3585 "ipv4 address family\n"
3586 "ipv6 address family\n")
3590 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3594 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3595 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3599 DEFUN (no_bgp_evpn_default_originate
,
3600 no_bgp_evpn_default_originate_cmd
,
3601 "no default-originate <ipv4 | ipv6>",
3603 "withdraw a default route\n"
3604 "ipv4 address family\n"
3605 "ipv6 address family\n")
3609 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3613 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3614 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3618 DEFPY (dup_addr_detection
,
3619 dup_addr_detection_cmd
,
3620 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3621 "Duplicate address detection\n"
3622 "Max allowed moves before address detected as duplicate\n"
3623 "Num of max allowed moves (2-1000) default 5\n"
3624 "Duplicate address detection time\n"
3625 "Time in seconds (2-1800) default 180\n")
3627 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3632 if (!EVPN_ENABLED(bgp_vrf
)) {
3634 "This command is only supported under the EVPN VRF\n");
3638 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3641 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3643 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3645 bgp_zebra_dup_addr_detection(bgp_vrf
);
3650 DEFPY (dup_addr_detection_auto_recovery
,
3651 dup_addr_detection_auto_recovery_cmd
,
3652 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3653 "Duplicate address detection\n"
3654 "Duplicate address detection freeze\n"
3655 "Duplicate address detection permanent freeze\n"
3656 "Duplicate address detection freeze time (30-3600)\n")
3658 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3659 uint32_t freeze_time
= freeze_time_val
;
3664 if (!EVPN_ENABLED(bgp_vrf
)) {
3666 "This command is only supported under the EVPN VRF\n");
3670 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3671 bgp_vrf
->evpn_info
->dad_freeze
= true;
3672 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3674 bgp_zebra_dup_addr_detection(bgp_vrf
);
3679 DEFPY (no_dup_addr_detection
,
3680 no_dup_addr_detection_cmd
,
3681 "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>]",
3683 "Duplicate address detection\n"
3684 "Max allowed moves before address detected as duplicate\n"
3685 "Num of max allowed moves (2-1000) default 5\n"
3686 "Duplicate address detection time\n"
3687 "Time in seconds (2-1800) default 180\n"
3688 "Duplicate address detection freeze\n"
3689 "Duplicate address detection permanent freeze\n"
3690 "Duplicate address detection freeze time (30-3600)\n")
3692 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3693 uint32_t max_moves
= (uint32_t)max_moves_val
;
3694 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3699 if (!EVPN_ENABLED(bgp_vrf
)) {
3701 "This command is only supported under the EVPN VRF\n");
3706 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3708 /* Reset all parameters to default. */
3709 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3710 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3711 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3712 bgp_vrf
->evpn_info
->dad_freeze
= false;
3713 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3716 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3718 "%% Value does not match with config\n");
3721 bgp_vrf
->evpn_info
->dad_max_moves
=
3722 EVPN_DAD_DEFAULT_MAX_MOVES
;
3726 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3728 "%% Value does not match with config\n");
3731 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3735 if (bgp_vrf
->evpn_info
->dad_freeze_time
3738 "%% Value does not match with config\n");
3741 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3742 bgp_vrf
->evpn_info
->dad_freeze
= false;
3745 if (permanent_val
) {
3746 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3748 "%% Value does not match with config\n");
3751 bgp_vrf
->evpn_info
->dad_freeze
= false;
3755 bgp_zebra_dup_addr_detection(bgp_vrf
);
3760 DEFPY(bgp_evpn_advertise_svi_ip
,
3761 bgp_evpn_advertise_svi_ip_cmd
,
3762 "[no$no] advertise-svi-ip",
3764 "Advertise svi mac-ip routes in EVPN\n")
3766 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3772 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3774 if (!EVPN_ENABLED(bgp
)) {
3776 "This command is only supported under EVPN VRF\n");
3779 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3785 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3786 bgp_evpn_advertise_svi_ip_vni_cmd
,
3787 "[no$no] advertise-svi-ip",
3789 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3791 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3792 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3798 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3800 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3805 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3806 bgp_evpn_advertise_vni_subnet_cmd
,
3808 "Advertise the subnet corresponding to VNI\n")
3810 struct bgp
*bgp_vrf
= NULL
;
3811 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3812 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3817 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3821 evpn_set_advertise_subnet(bgp
, vpn
);
3825 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3826 no_bgp_evpn_advertise_vni_subnet_cmd
,
3827 "no advertise-subnet",
3829 "Advertise All local VNIs\n")
3831 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3832 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3837 evpn_unset_advertise_subnet(bgp
, vpn
);
3841 DEFUN (bgp_evpn_advertise_type5
,
3842 bgp_evpn_advertise_type5_cmd
,
3843 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map WORD]",
3844 "Advertise prefix routes\n"
3847 "advertise gateway IP overlay index\n"
3848 "route-map for filtering specific routes\n"
3849 "Name of the route map\n")
3851 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3858 int rmap_changed
= 0;
3859 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3861 bool adv_flag_changed
= false;
3863 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3864 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3865 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3867 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3869 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3871 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3872 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3875 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3879 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3881 "%%only ipv4 or ipv6 address families are supported");
3885 if (safi
!= SAFI_UNICAST
) {
3887 "%%only ipv4 unicast or ipv6 unicast are supported");
3891 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3892 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3893 vty_out(vty
, "%%Unknown overlay-index type specified");
3897 if (afi
== AFI_IP
) {
3898 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3899 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3900 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3901 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3904 * this is the case for first time ever configuration
3905 * adv ipv4 unicast is enabled for the first time.
3906 * So no need to reset any flag
3908 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3910 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3911 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3912 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3914 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3915 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3916 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3918 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3919 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3922 * This is modify case from gateway-ip
3923 * to no overlay index
3925 adv_flag_changed
= true;
3926 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3927 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3928 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3929 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3930 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3932 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3933 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3936 * This is modify case from no overlay index
3939 adv_flag_changed
= true;
3940 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3941 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3942 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3943 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3947 * Command is issued with the same option
3948 * (no overlay index or gateway-ip) which was
3949 * already configured. So nothing to do.
3950 * However, route-map may have been modified.
3951 * check if route-map has been modified.
3952 * If not, return an error
3958 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3959 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3960 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3961 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3964 * this is the case for first time ever configuration
3965 * adv ipv6 unicast is enabled for the first time.
3966 * So no need to reset any flag
3968 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3970 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3971 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3972 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3974 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3975 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3976 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3978 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3979 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3982 * This is modify case from gateway-ip
3983 * to no overlay index
3985 adv_flag_changed
= true;
3986 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3987 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3988 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3989 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3990 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3992 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3993 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3996 * This is modify case from no overlay index
3999 adv_flag_changed
= true;
4000 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4001 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4002 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4003 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4007 * Command is issued with the same option
4008 * (no overlay index or gateway-ip) which was
4009 * already configured. So nothing to do.
4010 * However, route-map may have been modified.
4011 * check if route-map has been modified.
4012 * If not, return an error
4019 if ((rmap_changed
) || (adv_flag_changed
)) {
4021 /* If either of these are changed, then FRR needs to
4022 * withdraw already advertised type5 routes.
4024 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4026 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4027 XFREE(MTYPE_ROUTE_MAP_NAME
,
4028 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4029 route_map_counter_decrement(
4030 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4031 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4032 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4037 /* set the route-map for advertise command */
4038 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4039 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4040 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4041 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4042 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4043 route_map_counter_increment(
4044 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4047 /* advertise type-5 routes */
4048 if (advertise_type5_routes(bgp_vrf
, afi
))
4049 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4053 DEFUN (no_bgp_evpn_advertise_type5
,
4054 no_bgp_evpn_advertise_type5_cmd
,
4055 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4057 "Advertise prefix routes\n"
4061 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4067 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4068 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4070 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4072 "%%only ipv4 or ipv6 address families are supported");
4076 if (safi
!= SAFI_UNICAST
) {
4078 "%%only ipv4 unicast or ipv6 unicast are supported");
4082 if (afi
== AFI_IP
) {
4084 /* if we are not advertising ipv4 prefix as type-5
4087 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4088 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4089 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4090 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4091 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4092 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4093 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4094 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4095 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4099 /* if we are not advertising ipv6 prefix as type-5
4102 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4103 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4104 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4105 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4106 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4107 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4108 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4109 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4110 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4114 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4115 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4116 XFREE(MTYPE_ROUTE_MAP_NAME
,
4117 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4118 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4119 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4125 DEFPY (bgp_evpn_use_es_l3nhg
,
4126 bgp_evpn_use_es_l3nhg_cmd
,
4127 "[no$no] use-es-l3nhg",
4129 "use L3 nexthop group for host routes with ES destination\n")
4131 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4135 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4136 bgp_evpn_ead_evi_rx_disable_cmd
,
4137 "[no$no] disable-ead-evi-rx",
4139 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4141 bool ead_evi_rx
= no
? true :false;
4143 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4144 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4145 bgp_evpn_switch_ead_evi_rx();
4150 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4151 bgp_evpn_ead_evi_tx_disable_cmd
,
4152 "[no$no] disable-ead-evi-tx",
4154 "Don't advertise EAD-EVI for local ESs\n")
4156 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4160 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4161 bgp_evpn_enable_resolve_overlay_index_cmd
,
4162 "[no$no] enable-resolve-overlay-index",
4164 "Enable Recursive Resolution of type-5 route overlay index\n")
4166 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4168 if (bgp
!= bgp_get_evpn()) {
4169 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4173 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4177 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4178 bgp_evpn_advertise_pip_ip_mac_cmd
,
4179 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4181 "evpn system primary IP\n"
4184 MAC_STR MAC_STR MAC_STR
)
4186 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4187 struct bgp
*bgp_evpn
= NULL
;
4189 if (EVPN_ENABLED(bgp_vrf
)) {
4191 "This command is supported under L3VNI BGP EVPN VRF\n");
4192 return CMD_WARNING_CONFIG_FAILED
;
4194 bgp_evpn
= bgp_get_evpn();
4197 /* pip is already enabled */
4198 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4201 bgp_vrf
->evpn_info
->advertise_pip
= true;
4202 if (ip
.s_addr
!= INADDR_ANY
) {
4203 /* Already configured with same IP */
4204 if (IPV4_ADDR_SAME(&ip
,
4205 &bgp_vrf
->evpn_info
->pip_ip_static
))
4208 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4209 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4211 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4213 /* default instance router-id assignemt */
4215 bgp_vrf
->evpn_info
->pip_ip
=
4216 bgp_evpn
->router_id
;
4219 if (!is_zero_mac(&mac
->eth_addr
)) {
4220 /* Already configured with same MAC */
4221 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4222 &mac
->eth_addr
, ETH_ALEN
) == 0)
4225 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4226 &mac
->eth_addr
, ETH_ALEN
);
4227 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4228 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4231 /* Copy zebra sys mac */
4232 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4233 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4234 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4239 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4241 /* Disable PIP feature */
4242 bgp_vrf
->evpn_info
->advertise_pip
= false;
4243 /* copy anycast mac */
4244 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4245 &bgp_vrf
->rmac
, ETH_ALEN
);
4247 /* remove MAC-IP option retain PIP knob. */
4248 if ((ip
.s_addr
!= INADDR_ANY
) &&
4249 !IPV4_ADDR_SAME(&ip
,
4250 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4252 "%% BGP EVPN PIP IP does not match\n");
4253 return CMD_WARNING_CONFIG_FAILED
;
4256 if (!is_zero_mac(&mac
->eth_addr
) &&
4257 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4258 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4260 "%% BGP EVPN PIP MAC does not match\n");
4261 return CMD_WARNING_CONFIG_FAILED
;
4263 /* pip_rmac can carry vrr_rmac reset only if it matches
4264 * with static value.
4266 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4267 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4269 /* Copy zebra sys mac */
4271 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4272 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4273 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4276 /* copy anycast mac */
4277 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4278 &bgp_vrf
->rmac
, ETH_ALEN
);
4282 /* reset user configured sys MAC */
4283 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4284 /* reset user configured sys IP */
4285 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4286 /* Assign default PIP IP (bgp instance router-id) */
4288 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4290 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4293 if (is_evpn_enabled()) {
4294 struct listnode
*node
= NULL
;
4295 struct bgpevpn
*vpn
= NULL
;
4298 * At this point if bgp_evpn is NULL and evpn is enabled
4299 * something stupid has gone wrong
4303 update_advertise_vrf_routes(bgp_vrf
);
4305 /* Update (svi) type-2 routes */
4306 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4307 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4309 update_routes_for_vni(bgp_evpn
, vpn
);
4317 * Display VNI information - for all or a specific VNI
4319 DEFUN(show_bgp_l2vpn_evpn_vni
,
4320 show_bgp_l2vpn_evpn_vni_cmd
,
4321 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4330 struct bgp
*bgp_evpn
;
4334 json_object
*json
= NULL
;
4335 uint32_t num_l2vnis
= 0;
4336 uint32_t num_l3vnis
= 0;
4337 uint32_t num_vnis
= 0;
4338 struct listnode
*node
= NULL
;
4339 struct bgp
*bgp_temp
= NULL
;
4341 uj
= use_json(argc
, argv
);
4343 bgp_evpn
= bgp_get_evpn();
4347 if (!argv_find(argv
, argc
, "evpn", &idx
))
4351 json
= json_object_new_object();
4353 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4355 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4357 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4358 if (bgp_temp
->l3vni
)
4361 num_vnis
= num_l2vnis
+ num_l3vnis
;
4363 json_object_string_add(json
, "advertiseGatewayMacip",
4364 bgp_evpn
->advertise_gw_macip
4367 json_object_string_add(json
, "advertiseSviMacIp",
4368 bgp_evpn
->evpn_info
->advertise_svi_macip
4369 ? "Enabled" : "Disabled");
4370 json_object_string_add(json
, "advertiseAllVnis",
4371 is_evpn_enabled() ? "Enabled"
4373 json_object_string_add(
4375 bgp_evpn
->vxlan_flood_ctrl
4376 == VXLAN_FLOOD_HEAD_END_REPL
4377 ? "Head-end replication"
4379 json_object_int_add(json
, "numVnis", num_vnis
);
4380 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4381 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4383 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4384 bgp_evpn
->advertise_gw_macip
? "Enabled"
4386 vty_out(vty
, "Advertise SVI Macip: %s\n",
4387 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4389 vty_out(vty
, "Advertise All VNI flag: %s\n",
4390 is_evpn_enabled() ? "Enabled" : "Disabled");
4391 vty_out(vty
, "BUM flooding: %s\n",
4392 bgp_evpn
->vxlan_flood_ctrl
4393 == VXLAN_FLOOD_HEAD_END_REPL
4394 ? "Head-end replication"
4396 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4397 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4399 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4403 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4406 /* Display specific VNI */
4407 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4408 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4412 vty_out(vty
, "%s\n",
4413 json_object_to_json_string_ext(
4415 JSON_C_TO_STRING_PRETTY
4416 | JSON_C_TO_STRING_NOSLASHESCAPE
));
4417 json_object_free(json
);
4423 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4424 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4425 "show bgp l2vpn evpn vni remote-ip-hash",
4433 struct bgp
*bgp_evpn
;
4436 bgp_evpn
= bgp_get_evpn();
4440 if (!argv_find(argv
, argc
, "evpn", &idx
))
4443 hash_iterate(bgp_evpn
->vnihash
,
4444 (void (*)(struct hash_bucket
*,
4445 void *))bgp_evpn_show_remote_ip_hash
,
4451 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4452 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4453 "show bgp l2vpn evpn vni-svi-hash",
4458 "Show vni-svi-hash\n")
4460 struct bgp
*bgp_evpn
;
4463 bgp_evpn
= bgp_get_evpn();
4467 if (!argv_find(argv
, argc
, "evpn", &idx
))
4470 hash_iterate(bgp_evpn
->vni_svi_hash
,
4471 (void (*)(struct hash_bucket
*,
4472 void *))bgp_evpn_show_vni_svi_hash
,
4478 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4479 show_bgp_l2vpn_evpn_es_evi_cmd
,
4480 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4486 "VxLAN Network Identifier\n"
4489 "Detailed information\n")
4492 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4494 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4499 DEFPY(show_bgp_l2vpn_evpn_es
,
4500 show_bgp_l2vpn_evpn_es_cmd
,
4501 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4506 "Ethernet Segment\n"
4508 "Detailed information\n"
4514 if (!str_to_esi(esi_str
, &esi
)) {
4515 vty_out(vty
, "%%Malformed ESI\n");
4518 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4521 bgp_evpn_es_show(vty
, uj
, !!detail
);
4527 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4528 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4529 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4530 "Ethernet Segment\n"
4536 if (!str_to_esi(esi_str
, &esi
)) {
4537 vty_out(vty
, "%%Malformed ESI\n");
4540 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4543 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4549 DEFPY(show_bgp_l2vpn_evpn_nh
,
4550 show_bgp_l2vpn_evpn_nh_cmd
,
4551 "show bgp l2vpn evpn next-hops [json$uj]",
4559 bgp_evpn_nh_show(vty
, uj
);
4565 * Display EVPN neighbor summary.
4567 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4568 "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]",
4571 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4572 "Summary of BGP neighbor status\n"
4573 "Show only sessions in Established state\n"
4574 "Show only sessions not in Established state\n"
4575 "Show only the specified neighbor session\n"
4576 "Neighbor to display information about\n"
4577 "Neighbor to display information about\n"
4578 "Neighbor on BGP configured interface\n"
4579 "Show only the specified remote AS sessions\n"
4581 "Internal (iBGP) AS sessions\n"
4582 "External (eBGP) AS sessions\n"
4583 "Shorten the information on BGP instances\n"
4584 "Increase table width for longer output\n" JSON_STR
)
4589 char *neighbor
= NULL
;
4590 as_t as
= 0; /* 0 means AS filter not set */
4591 int as_type
= AS_UNSPECIFIED
;
4592 uint16_t show_flags
= 0;
4594 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4595 vrf
= argv
[++idx_vrf
]->arg
;
4597 if (argv_find(argv
, argc
, "failed", &idx
))
4598 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4600 if (argv_find(argv
, argc
, "established", &idx
))
4601 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4604 if (argv_find(argv
, argc
, "neighbor", &idx
))
4605 neighbor
= argv
[idx
+ 1]->arg
;
4607 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4608 if (argv
[idx
+ 1]->arg
[0] == 'i')
4609 as_type
= AS_INTERNAL
;
4610 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4611 as_type
= AS_EXTERNAL
;
4613 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4616 if (argv_find(argv
, argc
, "terse", &idx
))
4617 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4619 if (argv_find(argv
, argc
, "wide", &idx
))
4620 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4622 if (use_json(argc
, argv
))
4623 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4625 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4626 as_type
, as
, show_flags
);
4629 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4633 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4634 /* Specific type is requested */
4635 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4636 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4637 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4638 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4639 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4640 *type
= BGP_EVPN_IMET_ROUTE
;
4641 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4642 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4643 *type
= BGP_EVPN_ES_ROUTE
;
4644 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4645 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4646 *type
= BGP_EVPN_AD_ROUTE
;
4647 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4648 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4649 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4658 * Display global EVPN routing table.
4660 DEFUN(show_bgp_l2vpn_evpn_route
,
4661 show_bgp_l2vpn_evpn_route_cmd
,
4662 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4668 "Display Detailed Information\n"
4670 EVPN_TYPE_ALL_LIST_HELP_STR
4677 json_object
*json
= NULL
;
4679 uj
= use_json(argc
, argv
);
4681 bgp
= bgp_get_evpn();
4686 json
= json_object_new_object();
4688 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4691 if (argv_find(argv
, argc
, "detail", &detail
))
4694 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4697 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4698 json
, JSON_C_TO_STRING_PRETTY
));
4699 json_object_free(json
);
4705 * Display global EVPN routing table for specific RD.
4707 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4708 show_bgp_l2vpn_evpn_route_rd_cmd
,
4709 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4715 EVPN_RT_DIST_HELP_STR
4716 EVPN_ASN_IP_HELP_STR
4717 "All VPN Route Distinguishers\n"
4719 EVPN_TYPE_ALL_LIST_HELP_STR
4724 struct prefix_rd prd
;
4727 json_object
*json
= NULL
;
4728 int idx_ext_community
= 0;
4731 bgp
= bgp_get_evpn();
4735 /* check if we need json output */
4736 uj
= use_json(argc
, argv
);
4738 json
= json_object_new_object();
4740 argv_find(argv
, argc
, "all", &rd_all
);
4743 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4744 &idx_ext_community
);
4745 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4747 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4752 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4756 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4758 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4761 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4762 json
, JSON_C_TO_STRING_PRETTY
));
4763 json_object_free(json
);
4770 * Display global EVPN routing table for specific RD and MACIP.
4772 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4773 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4774 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4780 EVPN_RT_DIST_HELP_STR
4781 EVPN_ASN_IP_HELP_STR
4782 "All VPN Route Distinguishers\n"
4784 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4786 "IP address (IPv4 or IPv6)\n"
4791 struct prefix_rd prd
;
4794 int idx_ext_community
= 0;
4798 json_object
*json
= NULL
;
4801 memset(&mac
, 0, sizeof(struct ethaddr
));
4802 memset(&ip
, 0, sizeof(struct ipaddr
));
4804 bgp
= bgp_get_evpn();
4808 /* check if we need json output */
4809 uj
= use_json(argc
, argv
);
4811 json
= json_object_new_object();
4814 argv_find(argv
, argc
, "all", &rd_all
);
4816 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4817 &idx_ext_community
);
4818 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4820 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4826 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4827 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4828 vty_out(vty
, "%% Malformed MAC address\n");
4833 /* get the ip if specified */
4834 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4835 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4836 vty_out(vty
, "%% Malformed IP address\n");
4842 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4844 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4847 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4848 json
, JSON_C_TO_STRING_PRETTY
));
4849 json_object_free(json
);
4855 /* Display per ESI routing table */
4856 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4857 show_bgp_l2vpn_evpn_route_esi_cmd
,
4858 "show bgp l2vpn evpn route esi ESI [json]",
4864 "Ethernet Segment Identifier\n"
4870 struct bgp
*bgp
= NULL
;
4871 json_object
*json
= NULL
;
4873 memset(&esi
, 0, sizeof(esi
));
4874 bgp
= bgp_get_evpn();
4878 uj
= use_json(argc
, argv
);
4880 json
= json_object_new_object();
4882 /* get the ESI - ESI-ID is at argv[6] */
4883 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4884 vty_out(vty
, "%% Malformed ESI\n");
4888 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4891 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4892 json
, JSON_C_TO_STRING_PRETTY
));
4893 json_object_free(json
);
4901 * Display per-VNI EVPN routing table.
4903 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4904 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4910 "VXLAN Network Identifier\n"
4913 EVPN_TYPE_1_HELP_STR
4914 EVPN_TYPE_1_HELP_STR
4915 EVPN_TYPE_2_HELP_STR
4916 EVPN_TYPE_2_HELP_STR
4917 EVPN_TYPE_3_HELP_STR
4918 EVPN_TYPE_3_HELP_STR
4920 "Remote VTEP IP address\n"
4925 struct in_addr vtep_ip
;
4930 json_object
*json
= NULL
;
4932 bgp
= bgp_get_evpn();
4936 /* check if we need json output */
4937 uj
= use_json(argc
, argv
);
4939 json
= json_object_new_object();
4941 if (!argv_find(argv
, argc
, "evpn", &idx
))
4946 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4948 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4951 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4952 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4953 vty_out(vty
, "%% Malformed VTEP IP address\n");
4958 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4961 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4962 json
, JSON_C_TO_STRING_PRETTY
));
4963 json_object_free(json
);
4970 * Display per-VNI EVPN routing table for specific MACIP.
4972 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4973 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4974 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4980 "VXLAN Network Identifier\n"
4983 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4985 "IP address (IPv4 or IPv6)\n"
4994 json_object
*json
= NULL
;
4996 bgp
= bgp_get_evpn();
5000 /* check if we need json output */
5001 uj
= use_json(argc
, argv
);
5003 json
= json_object_new_object();
5005 if (!argv_find(argv
, argc
, "evpn", &idx
))
5009 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5012 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5013 vty_out(vty
, "%% Malformed MAC address\n");
5018 memset(&ip
, 0, sizeof(ip
));
5019 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5021 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5022 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5023 vty_out(vty
, "%% Malformed IP address\n");
5028 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5031 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5032 json
, JSON_C_TO_STRING_PRETTY
));
5033 json_object_free(json
);
5040 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5042 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5043 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5044 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5050 "VXLAN Network Identifier\n"
5052 EVPN_TYPE_3_HELP_STR
5053 "Originating Router IP address\n"
5059 struct in_addr orig_ip
;
5062 json_object
*json
= NULL
;
5064 bgp
= bgp_get_evpn();
5068 /* check if we need json output */
5069 uj
= use_json(argc
, argv
);
5071 json
= json_object_new_object();
5073 if (!argv_find(argv
, argc
, "evpn", &idx
))
5077 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5080 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5082 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5086 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5089 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5090 json
, JSON_C_TO_STRING_PRETTY
));
5091 json_object_free(json
);
5098 * Display per-VNI EVPN routing table - for all VNIs.
5100 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5101 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5102 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5108 "VXLAN Network Identifier\n"
5110 "Print Detailed Output\n"
5112 "Remote VTEP IP address\n"
5116 struct in_addr vtep_ip
;
5119 json_object
*json
= NULL
;
5120 /* Detail Adjust. Adjust indexes according to detail option */
5123 bgp
= bgp_get_evpn();
5127 /* check if we need json output */
5128 uj
= use_json(argc
, argv
);
5130 json
= json_object_new_object();
5132 if (!argv_find(argv
, argc
, "evpn", &idx
))
5135 if (argv_find(argv
, argc
, "detail", &da
))
5138 /* vtep-ip position depends on detail option */
5140 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5142 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5143 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5144 vty_out(vty
, "%% Malformed VTEP IP address\n");
5149 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5152 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5153 json
, JSON_C_TO_STRING_PRETTY
));
5154 json_object_free(json
);
5161 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5162 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5163 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5164 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5165 "EVPN route information\n"
5166 "MAC IP routes in the EVI tables linked to the ES\n"
5168 "Detailed information\n" JSON_STR
)
5172 json_object
*json
= NULL
;
5175 if (!str_to_esi(esi_str
, &esi
)) {
5176 vty_out(vty
, "%%Malformed ESI\n");
5185 json
= json_object_new_object();
5186 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5188 vty_out(vty
, "%s\n",
5189 json_object_to_json_string_ext(
5190 json
, JSON_C_TO_STRING_PRETTY
));
5191 json_object_free(json
);
5198 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5199 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5200 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5201 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5202 "EVPN route information\n"
5203 "MAC IP routes in the global table linked to the ES\n"
5205 "Detailed information\n" JSON_STR
)
5209 json_object
*json
= NULL
;
5212 if (!str_to_esi(esi_str
, &esi
)) {
5213 vty_out(vty
, "%%Malformed ESI\n");
5222 json
= json_object_new_object();
5223 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5225 vty_out(vty
, "%s\n",
5226 json_object_to_json_string_ext(
5227 json
, JSON_C_TO_STRING_PRETTY
));
5228 json_object_free(json
);
5235 * Display EVPN import route-target hash table
5237 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5238 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5239 "show bgp l2vpn evpn vrf-import-rt [json]",
5244 "Show vrf import route target\n"
5248 struct bgp
*bgp_evpn
= NULL
;
5249 json_object
*json
= NULL
;
5251 bgp_evpn
= bgp_get_evpn();
5255 uj
= use_json(argc
, argv
);
5257 json
= json_object_new_object();
5259 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5262 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5263 json
, JSON_C_TO_STRING_PRETTY
));
5264 json_object_free(json
);
5271 * Display EVPN import route-target hash table
5273 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5274 show_bgp_l2vpn_evpn_import_rt_cmd
,
5275 "show bgp l2vpn evpn import-rt [json]",
5280 "Show import route target\n"
5285 json_object
*json
= NULL
;
5287 bgp
= bgp_get_evpn();
5291 uj
= use_json(argc
, argv
);
5293 json
= json_object_new_object();
5295 evpn_show_import_rts(vty
, bgp
, json
);
5298 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5299 json
, JSON_C_TO_STRING_PRETTY
));
5300 json_object_free(json
);
5306 DEFPY_HIDDEN(test_es_add
,
5308 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5311 "Ethernet-segment\n"
5312 "Ethernet-Segment Identifier\n"
5320 struct in_addr vtep_ip
;
5323 bgp
= bgp_get_evpn();
5325 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5329 if (!str_to_esi(esi_str
, &esi
)) {
5330 vty_out(vty
, "%%Malformed ESI\n");
5335 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5337 vty_out(vty
, "%%Failed to delete ES\n");
5341 if (state_str
&& !strcmp(state_str
, "up"))
5345 vtep_ip
= bgp
->router_id
;
5347 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5348 EVPN_MH_DF_PREF_MIN
, false);
5350 vty_out(vty
, "%%Failed to add ES\n");
5357 DEFPY_HIDDEN(test_es_vni_add
,
5358 test_es_vni_add_cmd
,
5359 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5362 "Ethernet-segment\n"
5363 "Ethernet-Segment Identifier\n"
5372 bgp
= bgp_get_evpn();
5374 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5378 if (!str_to_esi(esi_str
, &esi
)) {
5379 vty_out(vty
, "%%Malformed ESI\n");
5384 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5386 vty_out(vty
, "%%Failed to deref ES VNI\n");
5390 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5392 vty_out(vty
, "%%Failed to ref ES VNI\n");
5399 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5400 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5404 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5405 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5406 "Summary of BGP neighbor status\n" JSON_STR
)
5408 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5409 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5410 SHOW_STR BGP_STR EVPN_HELP_STR
5412 "Display Detailed Information\n"
5414 EVPN_TYPE_2_HELP_STR
5415 EVPN_TYPE_2_HELP_STR
5416 EVPN_TYPE_3_HELP_STR
5417 EVPN_TYPE_3_HELP_STR
)
5420 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5421 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5422 SHOW_STR BGP_STR EVPN_HELP_STR
5424 EVPN_RT_DIST_HELP_STR
5425 EVPN_ASN_IP_HELP_STR
5427 EVPN_TYPE_2_HELP_STR
5428 EVPN_TYPE_2_HELP_STR
5429 EVPN_TYPE_3_HELP_STR
5430 EVPN_TYPE_3_HELP_STR
)
5433 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5434 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5435 SHOW_STR BGP_STR EVPN_HELP_STR
5437 EVPN_RT_DIST_HELP_STR
5438 EVPN_ASN_IP_HELP_STR
5440 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5442 "IP address (IPv4 or IPv6)\n")
5445 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5446 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5447 SHOW_STR BGP_STR EVPN_HELP_STR
5449 "VXLAN Network Identifier\n"
5452 EVPN_TYPE_2_HELP_STR
5453 EVPN_TYPE_2_HELP_STR
5454 EVPN_TYPE_3_HELP_STR
5455 EVPN_TYPE_3_HELP_STR
5457 "Remote VTEP IP address\n")
5459 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5460 show_bgp_evpn_route_vni_macip_cmd
,
5461 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5462 SHOW_STR BGP_STR EVPN_HELP_STR
5464 "VXLAN Network Identifier\n"
5467 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5469 "IP address (IPv4 or IPv6)\n")
5471 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5472 show_bgp_evpn_route_vni_multicast_cmd
,
5473 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5474 SHOW_STR BGP_STR EVPN_HELP_STR
5476 "VXLAN Network Identifier\n"
5478 EVPN_TYPE_3_HELP_STR
5479 "Originating Router IP address\n")
5481 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5482 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5483 SHOW_STR BGP_STR EVPN_HELP_STR
5485 "VXLAN Network Identifier\n"
5487 "Print Detailed Output\n"
5489 "Remote VTEP IP address\n")
5491 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5492 "show bgp evpn import-rt",
5493 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5495 DEFUN_NOSH (bgp_evpn_vni
,
5497 "vni " CMD_VNI_RANGE
,
5498 "VXLAN Network Identifier\n"
5502 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5503 struct bgpevpn
*vpn
;
5508 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5510 /* Create VNI, or mark as configured. */
5511 vpn
= evpn_create_update_vni(bgp
, vni
);
5513 vty_out(vty
, "%% Failed to create VNI \n");
5517 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5521 DEFUN (no_bgp_evpn_vni
,
5522 no_bgp_evpn_vni_cmd
,
5523 "no vni " CMD_VNI_RANGE
,
5525 "VXLAN Network Identifier\n"
5529 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5530 struct bgpevpn
*vpn
;
5535 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5537 /* Check if we should disallow. */
5538 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5540 vty_out(vty
, "%% Specified VNI does not exist\n");
5543 if (!is_vni_configured(vpn
)) {
5544 vty_out(vty
, "%% Specified VNI is not configured\n");
5548 evpn_delete_vni(bgp
, vpn
);
5552 DEFUN_NOSH (exit_vni
,
5555 "Exit from VNI mode\n")
5557 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5558 vty
->node
= BGP_EVPN_NODE
;
5562 DEFUN (bgp_evpn_vrf_rd
,
5563 bgp_evpn_vrf_rd_cmd
,
5564 "rd ASN:NN_OR_IP-ADDRESS:NN",
5565 EVPN_RT_DIST_HELP_STR
5566 EVPN_ASN_IP_HELP_STR
)
5569 struct prefix_rd prd
;
5570 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5575 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5577 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5581 /* If same as existing value, there is nothing more to do. */
5582 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5585 /* Configure or update the RD. */
5586 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5590 DEFUN (no_bgp_evpn_vrf_rd
,
5591 no_bgp_evpn_vrf_rd_cmd
,
5592 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5594 EVPN_RT_DIST_HELP_STR
5595 EVPN_ASN_IP_HELP_STR
)
5598 struct prefix_rd prd
;
5599 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5604 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5606 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5610 /* Check if we should disallow. */
5611 if (!is_vrf_rd_configured(bgp_vrf
)) {
5612 vty_out(vty
, "%% RD is not configured for this VRF\n");
5616 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5618 "%% RD specified does not match configuration for this VRF\n");
5622 evpn_unconfigure_vrf_rd(bgp_vrf
);
5626 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5627 no_bgp_evpn_vrf_rd_without_val_cmd
,
5630 EVPN_RT_DIST_HELP_STR
)
5632 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5637 /* Check if we should disallow. */
5638 if (!is_vrf_rd_configured(bgp_vrf
)) {
5639 vty_out(vty
, "%% RD is not configured for this VRF\n");
5643 evpn_unconfigure_vrf_rd(bgp_vrf
);
5647 DEFUN (bgp_evpn_vni_rd
,
5648 bgp_evpn_vni_rd_cmd
,
5649 "rd ASN:NN_OR_IP-ADDRESS:NN",
5650 EVPN_RT_DIST_HELP_STR
5651 EVPN_ASN_IP_HELP_STR
)
5653 struct prefix_rd prd
;
5654 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5655 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5661 if (!EVPN_ENABLED(bgp
)) {
5663 "This command is only supported under EVPN VRF\n");
5667 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5669 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5673 /* If same as existing value, there is nothing more to do. */
5674 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5677 /* Configure or update the RD. */
5678 evpn_configure_rd(bgp
, vpn
, &prd
);
5682 DEFUN (no_bgp_evpn_vni_rd
,
5683 no_bgp_evpn_vni_rd_cmd
,
5684 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5686 EVPN_RT_DIST_HELP_STR
5687 EVPN_ASN_IP_HELP_STR
)
5689 struct prefix_rd prd
;
5690 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5691 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5697 if (!EVPN_ENABLED(bgp
)) {
5699 "This command is only supported under EVPN VRF\n");
5703 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5705 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5709 /* Check if we should disallow. */
5710 if (!is_rd_configured(vpn
)) {
5711 vty_out(vty
, "%% RD is not configured for this VNI\n");
5715 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5717 "%% RD specified does not match configuration for this VNI\n");
5721 evpn_unconfigure_rd(bgp
, vpn
);
5725 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5726 no_bgp_evpn_vni_rd_without_val_cmd
,
5729 EVPN_RT_DIST_HELP_STR
)
5731 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5732 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5737 if (!EVPN_ENABLED(bgp
)) {
5739 "This command is only supported under EVPN VRF\n");
5743 /* Check if we should disallow. */
5744 if (!is_rd_configured(vpn
)) {
5745 vty_out(vty
, "%% RD is not configured for this VNI\n");
5749 evpn_unconfigure_rd(bgp
, vpn
);
5754 * Loop over all extended-communities in the route-target list rtl and
5755 * return 1 if we find ecomtarget
5757 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5758 struct ecommunity
*ecomtarget
)
5760 struct listnode
*node
, *nnode
;
5761 struct ecommunity
*ecom
;
5763 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5764 if (ecommunity_match(ecom
, ecomtarget
))
5771 /* display L3VNI related info for a VRF instance */
5772 DEFUN (show_bgp_vrf_l3vni_info
,
5773 show_bgp_vrf_l3vni_info_cmd
,
5774 "show bgp vrf VRFNAME vni [json]",
5782 char buf
[ETHER_ADDR_STRLEN
];
5783 char buf1
[INET6_ADDRSTRLEN
];
5784 char originator_ip
[BUFSIZ
] = {0};
5786 const char *name
= NULL
;
5787 struct bgp
*bgp
= NULL
;
5788 struct listnode
*node
= NULL
;
5789 struct bgpevpn
*vpn
= NULL
;
5790 struct ecommunity
*ecom
= NULL
;
5791 json_object
*json
= NULL
;
5792 json_object
*json_vnis
= NULL
;
5793 json_object
*json_export_rts
= NULL
;
5794 json_object
*json_import_rts
= NULL
;
5795 bool uj
= use_json(argc
, argv
);
5798 json
= json_object_new_object();
5799 json_vnis
= json_object_new_array();
5800 json_export_rts
= json_object_new_array();
5801 json_import_rts
= json_object_new_array();
5804 name
= argv
[idx_vrf
]->arg
;
5805 bgp
= bgp_lookup_by_name(name
);
5808 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5810 json_object_string_add(json
, "warning",
5811 "BGP instance not found");
5812 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5813 json_object_free(json
);
5819 vty_out(vty
, "BGP VRF: %s\n", name
);
5820 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5821 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5822 vty_out(vty
, " Rmac: %s\n",
5823 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5824 vty_out(vty
, " VNI Filter: %s\n",
5825 CHECK_FLAG(bgp
->vrf_flags
,
5826 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5827 ? "prefix-routes-only"
5829 vty_out(vty
, " L2-VNI List:\n");
5831 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5832 vty_out(vty
, "%u ", vpn
->vni
);
5834 vty_out(vty
, " Export-RTs:\n");
5836 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5837 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5839 vty_out(vty
, " Import-RTs:\n");
5841 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5842 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5844 vty_out(vty
, " RD: %s\n",
5845 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5847 json_object_string_add(json
, "vrf", name
);
5848 json_object_string_add(json
, "local-ip",
5849 inet_ntop(AF_INET
, &bgp
->originator_ip
,
5851 sizeof(originator_ip
)));
5852 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5853 json_object_string_add(
5855 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5856 json_object_string_add(
5858 CHECK_FLAG(bgp
->vrf_flags
,
5859 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5860 ? "prefix-routes-only"
5862 /* list of l2vnis */
5863 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5864 json_object_array_add(json_vnis
,
5865 json_object_new_int(vpn
->vni
));
5866 json_object_object_add(json
, "l2vnis", json_vnis
);
5869 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5870 json_object_array_add(
5872 json_object_new_string(ecommunity_str(ecom
)));
5873 json_object_object_add(json
, "export-rts", json_export_rts
);
5876 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5877 json_object_array_add(
5879 json_object_new_string(ecommunity_str(ecom
)));
5880 json_object_object_add(json
, "import-rts", json_import_rts
);
5881 json_object_string_add(
5883 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5887 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5888 json
, JSON_C_TO_STRING_PRETTY
));
5889 json_object_free(json
);
5894 /* import/export rt for l3vni-vrf */
5895 DEFUN (bgp_evpn_vrf_rt
,
5896 bgp_evpn_vrf_rt_cmd
,
5897 "route-target <both|import|export> RT",
5899 "import and export\n"
5902 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5905 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5906 struct ecommunity
*ecomadd
= NULL
;
5911 if (!strcmp(argv
[1]->arg
, "import"))
5912 rt_type
= RT_TYPE_IMPORT
;
5913 else if (!strcmp(argv
[1]->arg
, "export"))
5914 rt_type
= RT_TYPE_EXPORT
;
5915 else if (!strcmp(argv
[1]->arg
, "both"))
5916 rt_type
= RT_TYPE_BOTH
;
5918 vty_out(vty
, "%% Invalid Route Target type\n");
5922 /* Add/update the import route-target */
5923 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5924 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5925 ECOMMUNITY_ROUTE_TARGET
, 0);
5927 vty_out(vty
, "%% Malformed Route Target list\n");
5930 ecommunity_str(ecomadd
);
5932 /* Do nothing if we already have this import route-target */
5933 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5934 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5937 /* Add/update the export route-target */
5938 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5939 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5940 ECOMMUNITY_ROUTE_TARGET
, 0);
5942 vty_out(vty
, "%% Malformed Route Target list\n");
5945 ecommunity_str(ecomadd
);
5947 /* Do nothing if we already have this export route-target */
5948 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5949 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5955 DEFUN (no_bgp_evpn_vrf_rt
,
5956 no_bgp_evpn_vrf_rt_cmd
,
5957 "no route-target <both|import|export> RT",
5960 "import and export\n"
5963 EVPN_ASN_IP_HELP_STR
)
5965 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5966 int rt_type
, found_ecomdel
;
5967 struct ecommunity
*ecomdel
= NULL
;
5972 if (!strcmp(argv
[2]->arg
, "import"))
5973 rt_type
= RT_TYPE_IMPORT
;
5974 else if (!strcmp(argv
[2]->arg
, "export"))
5975 rt_type
= RT_TYPE_EXPORT
;
5976 else if (!strcmp(argv
[2]->arg
, "both"))
5977 rt_type
= RT_TYPE_BOTH
;
5979 vty_out(vty
, "%% Invalid Route Target type\n");
5983 if (rt_type
== RT_TYPE_IMPORT
) {
5984 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5986 "%% Import RT is not configured for this VRF\n");
5989 } else if (rt_type
== RT_TYPE_EXPORT
) {
5990 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5992 "%% Export RT is not configured for this VRF\n");
5995 } else if (rt_type
== RT_TYPE_BOTH
) {
5996 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5997 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5999 "%% Import/Export RT is not configured for this VRF\n");
6004 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6006 vty_out(vty
, "%% Malformed Route Target list\n");
6009 ecommunity_str(ecomdel
);
6011 if (rt_type
== RT_TYPE_IMPORT
) {
6012 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
6014 ecommunity_free(&ecomdel
);
6016 "%% RT specified does not match configuration for this VRF\n");
6019 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
6020 } else if (rt_type
== RT_TYPE_EXPORT
) {
6021 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6023 ecommunity_free(&ecomdel
);
6025 "%% RT specified does not match configuration for this VRF\n");
6028 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6029 } else if (rt_type
== RT_TYPE_BOTH
) {
6032 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
6034 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
6038 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6040 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6044 if (!found_ecomdel
) {
6045 ecommunity_free(&ecomdel
);
6047 "%% RT specified does not match configuration for this VRF\n");
6052 ecommunity_free(&ecomdel
);
6056 DEFUN (bgp_evpn_vni_rt
,
6057 bgp_evpn_vni_rt_cmd
,
6058 "route-target <both|import|export> RT",
6060 "import and export\n"
6063 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6065 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6066 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6068 struct ecommunity
*ecomadd
= NULL
;
6073 if (!EVPN_ENABLED(bgp
)) {
6075 "This command is only supported under EVPN VRF\n");
6079 if (!strcmp(argv
[1]->text
, "import"))
6080 rt_type
= RT_TYPE_IMPORT
;
6081 else if (!strcmp(argv
[1]->text
, "export"))
6082 rt_type
= RT_TYPE_EXPORT
;
6083 else if (!strcmp(argv
[1]->text
, "both"))
6084 rt_type
= RT_TYPE_BOTH
;
6086 vty_out(vty
, "%% Invalid Route Target type\n");
6090 /* Add/update the import route-target */
6091 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6092 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6093 ECOMMUNITY_ROUTE_TARGET
, 0);
6095 vty_out(vty
, "%% Malformed Route Target list\n");
6098 ecommunity_str(ecomadd
);
6100 /* Do nothing if we already have this import route-target */
6101 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6102 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6105 /* Add/update the export route-target */
6106 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6107 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6108 ECOMMUNITY_ROUTE_TARGET
, 0);
6110 vty_out(vty
, "%% Malformed Route Target list\n");
6113 ecommunity_str(ecomadd
);
6115 /* Do nothing if we already have this export route-target */
6116 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6117 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6123 DEFUN (no_bgp_evpn_vni_rt
,
6124 no_bgp_evpn_vni_rt_cmd
,
6125 "no route-target <both|import|export> RT",
6128 "import and export\n"
6131 EVPN_ASN_IP_HELP_STR
)
6133 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6134 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6135 int rt_type
, found_ecomdel
;
6136 struct ecommunity
*ecomdel
= NULL
;
6141 if (!EVPN_ENABLED(bgp
)) {
6143 "This command is only supported under EVPN VRF\n");
6147 if (!strcmp(argv
[2]->text
, "import"))
6148 rt_type
= RT_TYPE_IMPORT
;
6149 else if (!strcmp(argv
[2]->text
, "export"))
6150 rt_type
= RT_TYPE_EXPORT
;
6151 else if (!strcmp(argv
[2]->text
, "both"))
6152 rt_type
= RT_TYPE_BOTH
;
6154 vty_out(vty
, "%% Invalid Route Target type\n");
6158 /* The user did "no route-target import", check to see if there are any
6159 * import route-targets configured. */
6160 if (rt_type
== RT_TYPE_IMPORT
) {
6161 if (!is_import_rt_configured(vpn
)) {
6163 "%% Import RT is not configured for this VNI\n");
6166 } else if (rt_type
== RT_TYPE_EXPORT
) {
6167 if (!is_export_rt_configured(vpn
)) {
6169 "%% Export RT is not configured for this VNI\n");
6172 } else if (rt_type
== RT_TYPE_BOTH
) {
6173 if (!is_import_rt_configured(vpn
)
6174 && !is_export_rt_configured(vpn
)) {
6176 "%% Import/Export RT is not configured for this VNI\n");
6181 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6183 vty_out(vty
, "%% Malformed Route Target list\n");
6186 ecommunity_str(ecomdel
);
6188 if (rt_type
== RT_TYPE_IMPORT
) {
6189 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6191 "%% RT specified does not match configuration for this VNI\n");
6194 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6195 } else if (rt_type
== RT_TYPE_EXPORT
) {
6196 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6198 "%% RT specified does not match configuration for this VNI\n");
6201 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6202 } else if (rt_type
== RT_TYPE_BOTH
) {
6205 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6206 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6210 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6211 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6215 if (!found_ecomdel
) {
6217 "%% RT specified does not match configuration for this VNI\n");
6225 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6226 no_bgp_evpn_vni_rt_without_val_cmd
,
6227 "no route-target <import|export>",
6233 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6234 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6240 if (!EVPN_ENABLED(bgp
)) {
6242 "This command is only supported under EVPN VRF\n");
6246 if (!strcmp(argv
[2]->text
, "import")) {
6247 rt_type
= RT_TYPE_IMPORT
;
6248 } else if (!strcmp(argv
[2]->text
, "export")) {
6249 rt_type
= RT_TYPE_EXPORT
;
6251 vty_out(vty
, "%% Invalid Route Target type\n");
6255 /* Check if we should disallow. */
6256 if (rt_type
== RT_TYPE_IMPORT
) {
6257 if (!is_import_rt_configured(vpn
)) {
6259 "%% Import RT is not configured for this VNI\n");
6263 if (!is_export_rt_configured(vpn
)) {
6265 "%% Export RT is not configured for this VNI\n");
6270 /* Unconfigure the RT. */
6271 if (rt_type
== RT_TYPE_IMPORT
)
6272 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6274 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6278 static int vni_cmp(const void **a
, const void **b
)
6280 const struct bgpevpn
*first
= *a
;
6281 const struct bgpevpn
*secnd
= *b
;
6283 return secnd
->vni
- first
->vni
;
6287 * Output EVPN configuration information.
6289 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6292 char buf1
[RD_ADDRSTRLEN
];
6293 char buf2
[INET6_ADDRSTRLEN
];
6295 if (bgp
->advertise_all_vni
)
6296 vty_out(vty
, " advertise-all-vni\n");
6299 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6300 struct listnode
*ln
;
6301 struct bgpevpn
*data
;
6303 list_sort(vnilist
, vni_cmp
);
6304 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6305 write_vni_config(vty
, data
);
6307 list_delete(&vnilist
);
6310 if (bgp
->advertise_autort_rfc8365
)
6311 vty_out(vty
, " autort rfc8365-compatible\n");
6313 if (bgp
->advertise_gw_macip
)
6314 vty_out(vty
, " advertise-default-gw\n");
6316 if (bgp
->evpn_info
->advertise_svi_macip
)
6317 vty_out(vty
, " advertise-svi-ip\n");
6319 if (bgp
->resolve_overlay_index
)
6320 vty_out(vty
, " enable-resolve-overlay-index\n");
6322 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6323 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6324 if (bgp_mh_info
->host_routes_use_l3nhg
)
6325 vty_out(vty
, " use-es-l3nhg\n");
6327 vty_out(vty
, " no use-es-l3nhg\n");
6330 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6331 if (bgp_mh_info
->ead_evi_rx
)
6332 vty_out(vty
, " no disable-ead-evi-rx\n");
6334 vty_out(vty
, " disable-ead-evi-rx\n");
6337 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6338 if (bgp_mh_info
->ead_evi_tx
)
6339 vty_out(vty
, " no disable-ead-evi-tx\n");
6341 vty_out(vty
, " disable-ead-evi-tx\n");
6344 if (!bgp
->evpn_info
->dup_addr_detect
)
6345 vty_out(vty
, " no dup-addr-detection\n");
6347 if (bgp
->evpn_info
->dad_max_moves
!=
6348 EVPN_DAD_DEFAULT_MAX_MOVES
||
6349 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6350 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6351 bgp
->evpn_info
->dad_max_moves
,
6352 bgp
->evpn_info
->dad_time
);
6354 if (bgp
->evpn_info
->dad_freeze
) {
6355 if (bgp
->evpn_info
->dad_freeze_time
)
6357 " dup-addr-detection freeze %u\n",
6358 bgp
->evpn_info
->dad_freeze_time
);
6361 " dup-addr-detection freeze permanent\n");
6364 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6365 vty_out(vty
, " flooding disable\n");
6367 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6368 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6369 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6370 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6371 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6374 " advertise ipv4 unicast\n");
6375 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6376 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6377 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6379 " advertise ipv4 unicast gateway-ip route-map %s\n",
6380 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6382 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6385 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6386 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6387 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6389 " advertise ipv6 unicast route-map %s\n",
6390 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6393 " advertise ipv6 unicast\n");
6394 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6395 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6396 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6398 " advertise ipv6 unicast gateway-ip route-map %s\n",
6399 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6401 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6404 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6405 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6406 vty_out(vty
, " default-originate ipv4\n");
6408 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6409 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6410 vty_out(vty
, " default-originate ipv6\n");
6412 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6413 if (!bgp
->evpn_info
->advertise_pip
)
6414 vty_out(vty
, " no advertise-pip\n");
6415 if (bgp
->evpn_info
->advertise_pip
) {
6416 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6418 vty_out(vty
, " advertise-pip ip %s",
6420 &bgp
->evpn_info
->pip_ip_static
,
6421 buf2
, INET_ADDRSTRLEN
));
6423 bgp
->evpn_info
->pip_rmac_static
))) {
6424 char buf
[ETHER_ADDR_STRLEN
];
6426 vty_out(vty
, " mac %s",
6436 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6437 vty_out(vty
, " rd %s\n",
6438 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6440 /* import route-target */
6441 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6443 struct listnode
*node
, *nnode
;
6444 struct ecommunity
*ecom
;
6446 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6448 ecom_str
= ecommunity_ecom2str(
6449 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6450 vty_out(vty
, " route-target import %s\n", ecom_str
);
6451 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6455 /* export route-target */
6456 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6458 struct listnode
*node
, *nnode
;
6459 struct ecommunity
*ecom
;
6461 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6463 ecom_str
= ecommunity_ecom2str(
6464 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6465 vty_out(vty
, " route-target export %s\n", ecom_str
);
6466 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6471 void bgp_ethernetvpn_init(void)
6473 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6474 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6475 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6476 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6477 install_element(VIEW_NODE
,
6478 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6479 install_element(VIEW_NODE
,
6480 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6483 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6486 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6487 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6488 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6489 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6490 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6491 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6492 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6493 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6494 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6495 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6496 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6497 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6498 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6499 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6500 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6501 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6502 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6503 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6504 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6505 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6506 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6507 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6508 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6509 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6510 install_element(BGP_EVPN_NODE
,
6511 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6514 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6515 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6517 /* "show bgp l2vpn evpn" commands. */
6518 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6519 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6520 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6521 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6522 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6523 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6524 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6525 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6526 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6527 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6528 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6529 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6530 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6531 install_element(VIEW_NODE
,
6532 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6533 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6534 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6535 install_element(VIEW_NODE
,
6536 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6537 install_element(VIEW_NODE
,
6538 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6539 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6540 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6542 /* "show bgp evpn" commands. */
6543 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6544 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6545 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6546 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6547 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6548 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6549 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6550 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6551 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6552 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6553 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6554 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6556 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6557 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6558 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6559 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6560 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6561 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6562 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6563 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6564 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6565 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6566 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6567 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6568 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6569 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6570 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6571 install_element(BGP_EVPN_VNI_NODE
,
6572 &bgp_evpn_advertise_default_gw_vni_cmd
);
6573 install_element(BGP_EVPN_VNI_NODE
,
6574 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6575 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6576 install_element(BGP_EVPN_VNI_NODE
,
6577 &no_bgp_evpn_advertise_vni_subnet_cmd
);