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]:[Frag-id]\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
];
381 json_import_rtl
= json_export_rtl
= 0;
384 json_import_rtl
= json_object_new_array();
385 json_export_rtl
= json_object_new_array();
386 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
387 json_object_string_add(json
, "type", "L3");
388 json_object_string_add(json
, "inKernel", "True");
389 json_object_string_add(
391 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
392 json_object_string_addf(json
, "originatorIp", "%pI4",
393 &bgp_vrf
->originator_ip
);
394 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
395 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
396 json_object_string_add(json
, "advertisePip",
397 bgp_vrf
->evpn_info
->advertise_pip
?
398 "Enabled" : "Disabled");
399 json_object_string_addf(json
, "sysIP", "%pI4",
400 &bgp_vrf
->evpn_info
->pip_ip
);
401 json_object_string_add(json
, "sysMac",
402 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
403 buf2
, sizeof(buf2
)));
404 json_object_string_add(json
, "rmac",
405 prefix_mac2str(&bgp_vrf
->rmac
,
406 buf2
, sizeof(buf2
)));
408 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
409 vty_out(vty
, " (known to the kernel)");
412 vty_out(vty
, " Type: %s\n", "L3");
413 vty_out(vty
, " Tenant VRF: %s\n",
414 vrf_id_to_name(bgp_vrf
->vrf_id
));
415 vty_out(vty
, " RD: %s\n",
416 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
417 vty_out(vty
, " Originator IP: %pI4\n",
418 &bgp_vrf
->originator_ip
);
419 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
420 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
421 vty_out(vty
, " Advertise-pip: %s\n",
422 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
423 vty_out(vty
, " System-IP: %s\n",
424 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
425 buf1
, INET_ADDRSTRLEN
));
426 vty_out(vty
, " System-MAC: %s\n",
427 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
428 buf2
, sizeof(buf2
)));
429 vty_out(vty
, " Router-MAC: %s\n",
430 prefix_mac2str(&bgp_vrf
->rmac
,
431 buf2
, sizeof(buf2
)));
435 vty_out(vty
, " Import Route Target:\n");
437 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
438 ecom_str
= ecommunity_ecom2str(ecom
,
439 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
442 json_object_array_add(json_import_rtl
,
443 json_object_new_string(ecom_str
));
445 vty_out(vty
, " %s\n", ecom_str
);
447 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
451 json_object_object_add(json
, "importRts", json_import_rtl
);
453 vty_out(vty
, " Export Route Target:\n");
455 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
456 ecom_str
= ecommunity_ecom2str(ecom
,
457 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
460 json_object_array_add(json_export_rtl
,
461 json_object_new_string(ecom_str
));
463 vty_out(vty
, " %s\n", ecom_str
);
465 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
469 json_object_object_add(json
, "exportRts", json_export_rtl
);
472 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
474 char buf1
[RD_ADDRSTRLEN
];
476 struct listnode
*node
, *nnode
;
477 struct ecommunity
*ecom
;
478 json_object
*json_import_rtl
= NULL
;
479 json_object
*json_export_rtl
= NULL
;
480 struct bgp
*bgp_evpn
;
482 bgp_evpn
= bgp_get_evpn();
485 json_import_rtl
= json_object_new_array();
486 json_export_rtl
= json_object_new_array();
487 json_object_int_add(json
, "vni", vpn
->vni
);
488 json_object_string_add(json
, "type", "L2");
489 json_object_string_add(json
, "inKernel",
490 is_vni_live(vpn
) ? "True" : "False");
491 json_object_string_add(
493 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
494 json_object_string_addf(json
, "originatorIp", "%pI4",
495 &vpn
->originator_ip
);
496 json_object_string_addf(json
, "mcastGroup", "%pI4",
498 /* per vni knob is enabled -- Enabled
499 * Global knob is enabled -- Active
500 * default -- Disabled
502 if (!vpn
->advertise_gw_macip
&&
503 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
504 json_object_string_add(json
, "advertiseGatewayMacip",
506 else if (vpn
->advertise_gw_macip
)
507 json_object_string_add(json
, "advertiseGatewayMacip",
510 json_object_string_add(json
, "advertiseGatewayMacip",
512 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
513 bgp_evpn
->evpn_info
->advertise_svi_macip
)
514 json_object_string_add(json
, "advertiseSviMacIp",
516 else if (vpn
->advertise_svi_macip
)
517 json_object_string_add(json
, "advertiseSviMacIp",
520 json_object_string_add(json
, "advertiseSviMacIp",
522 json_object_string_add(
523 json
, "sviInterface",
524 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
526 vty_out(vty
, "VNI: %d", vpn
->vni
);
527 if (is_vni_live(vpn
))
528 vty_out(vty
, " (known to the kernel)");
531 vty_out(vty
, " Type: %s\n", "L2");
532 vty_out(vty
, " Tenant-Vrf: %s\n",
533 vrf_id_to_name(vpn
->tenant_vrf_id
));
534 vty_out(vty
, " RD: %s\n",
535 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
536 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
537 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
538 if (!vpn
->advertise_gw_macip
&&
539 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
540 vty_out(vty
, " Advertise-gw-macip : %s\n",
542 else if (vpn
->advertise_gw_macip
)
543 vty_out(vty
, " Advertise-gw-macip : %s\n",
546 vty_out(vty
, " Advertise-gw-macip : %s\n",
548 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
549 bgp_evpn
->evpn_info
->advertise_svi_macip
)
550 vty_out(vty
, " Advertise-svi-macip : %s\n",
552 else if (vpn
->advertise_svi_macip
)
553 vty_out(vty
, " Advertise-svi-macip : %s\n",
556 vty_out(vty
, " Advertise-svi-macip : %s\n",
558 vty_out(vty
, " SVI interface : %s\n",
559 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
563 vty_out(vty
, " Import Route Target:\n");
565 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
566 ecom_str
= ecommunity_ecom2str(ecom
,
567 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
570 json_object_array_add(json_import_rtl
,
571 json_object_new_string(ecom_str
));
573 vty_out(vty
, " %s\n", ecom_str
);
575 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
579 json_object_object_add(json
, "importRts", json_import_rtl
);
581 vty_out(vty
, " Export Route Target:\n");
583 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
584 ecom_str
= ecommunity_ecom2str(ecom
,
585 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
588 json_object_array_add(json_export_rtl
,
589 json_object_new_string(ecom_str
));
591 vty_out(vty
, " %s\n", ecom_str
);
593 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
597 json_object_object_add(json
, "exportRts", json_export_rtl
);
600 static void show_esi_routes(struct bgp
*bgp
,
601 struct bgp_evpn_es
*es
,
606 struct bgp_dest
*dest
;
607 struct bgp_path_info
*pi
;
608 uint32_t prefix_cnt
, path_cnt
;
611 prefix_cnt
= path_cnt
= 0;
613 tbl_ver
= es
->route_table
->version
;
614 for (dest
= bgp_table_top(es
->route_table
); dest
;
615 dest
= bgp_route_next(dest
)) {
616 int add_prefix_to_json
= 0;
617 char prefix_str
[BUFSIZ
];
618 json_object
*json_paths
= NULL
;
619 json_object
*json_prefix
= NULL
;
620 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
622 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
626 json_prefix
= json_object_new_object();
628 pi
= bgp_dest_get_bgp_path_info(dest
);
630 /* Overall header/legend displayed once. */
632 bgp_evpn_show_route_header(vty
, bgp
,
641 json_paths
= json_object_new_array();
643 /* For EVPN, the prefix is displayed for each path (to fit in
644 * with code that already exists).
646 for (; pi
; pi
= pi
->next
) {
647 json_object
*json_path
= NULL
;
650 json_path
= json_object_new_array();
652 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
656 json_object_array_add(json_paths
, json_path
);
659 add_prefix_to_json
= 1;
663 if (add_prefix_to_json
) {
664 json_object_string_add(json_prefix
, "prefix",
666 json_object_int_add(json_prefix
, "prefixLen",
668 json_object_object_add(json_prefix
, "paths",
670 json_object_object_add(json
, prefix_str
,
673 json_object_free(json_paths
);
674 json_object_free(json_prefix
);
682 json_object_int_add(json
, "numPrefix", prefix_cnt
);
683 json_object_int_add(json
, "numPaths", path_cnt
);
686 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
688 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
689 prefix_cnt
, path_cnt
);
693 /* Display all MAC-IP VNI routes linked to an ES */
694 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
695 json_object
*json
, int detail
,
699 struct bgp_path_info
*pi
;
700 int header
= detail
? 0 : 1;
702 struct listnode
*node
;
703 struct bgp_evpn_es
*es
;
704 struct bgp_path_es_info
*es_info
;
705 struct bgp
*bgp
= bgp_get_evpn();
706 json_object
*json_paths
= NULL
;
714 json_paths
= json_object_new_array();
716 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
717 struct list
*es_list
;
719 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
723 es_list
= es
->macip_global_path_list
;
725 es_list
= es
->macip_evi_path_list
;
727 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
728 json_object
*json_path
= NULL
;
733 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
736 /* Overall header/legend displayed once. */
738 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
745 json_path
= json_object_new_array();
748 route_vty_out_detail(
749 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
750 RPKI_NOT_BEING_USED
, json_path
);
752 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
756 json_object_array_add(json_paths
, json_path
);
761 json_object_object_add(json
, "paths", json_paths
);
762 json_object_int_add(json
, "numPaths", path_cnt
);
765 vty_out(vty
, "There are no MAC-IP ES paths");
767 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
772 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
773 json_object
*json
, int detail
)
775 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
778 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
779 json_object
*json
, int detail
)
781 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
784 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
785 struct vty
*vty
, struct in_addr vtep_ip
,
786 json_object
*json
, int detail
)
788 struct bgp_dest
*dest
;
789 struct bgp_path_info
*pi
;
790 struct bgp_table
*table
;
791 int header
= detail
? 0 : 1;
793 uint32_t prefix_cnt
, path_cnt
;
795 prefix_cnt
= path_cnt
= 0;
797 table
= vpn
->route_table
;
798 tbl_ver
= table
->version
;
799 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
800 const struct prefix_evpn
*evp
=
801 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
802 int add_prefix_to_json
= 0;
803 char prefix_str
[BUFSIZ
];
804 json_object
*json_paths
= NULL
;
805 json_object
*json_prefix
= NULL
;
806 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
808 prefix2str((struct prefix_evpn
*)bgp_dest_get_prefix(dest
),
809 prefix_str
, sizeof(prefix_str
));
811 if (type
&& evp
->prefix
.route_type
!= type
)
815 json_prefix
= json_object_new_object();
817 pi
= bgp_dest_get_bgp_path_info(dest
);
819 /* Overall header/legend displayed once. */
821 bgp_evpn_show_route_header(vty
, bgp
,
830 json_paths
= json_object_new_array();
832 /* For EVPN, the prefix is displayed for each path (to fit in
833 * with code that already exists).
835 for (; pi
; pi
= pi
->next
) {
836 json_object
*json_path
= NULL
;
838 if (vtep_ip
.s_addr
!= INADDR_ANY
839 && !IPV4_ADDR_SAME(&(vtep_ip
),
840 &(pi
->attr
->nexthop
)))
844 json_path
= json_object_new_array();
847 route_vty_out_detail(vty
, bgp
, dest
, pi
,
848 AFI_L2VPN
, SAFI_EVPN
,
852 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
856 json_object_array_add(json_paths
, json_path
);
859 add_prefix_to_json
= 1;
863 if (add_prefix_to_json
) {
864 json_object_string_add(json_prefix
, "prefix",
866 json_object_int_add(json_prefix
, "prefixLen",
868 json_object_object_add(json_prefix
, "paths",
870 json_object_object_add(json
, prefix_str
,
873 json_object_free(json_paths
);
874 json_object_free(json_prefix
);
882 json_object_int_add(json
, "numPrefix", prefix_cnt
);
883 json_object_int_add(json
, "numPaths", path_cnt
);
886 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
887 type
? "(of requested type) " : "");
889 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
890 prefix_cnt
, path_cnt
,
891 type
? " (of requested type)" : "");
896 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
898 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
899 struct vni_walk_ctx
*wctx
= arg
;
900 struct vty
*vty
= wctx
->vty
;
901 json_object
*json
= wctx
->json
;
902 json_object
*json_vni
= NULL
;
903 char vni_str
[VNI_STR_LEN
];
905 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
907 json_vni
= json_object_new_object();
908 json_object_int_add(json_vni
, "vni", vpn
->vni
);
910 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
913 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
917 json_object_object_add(json
, vni_str
, json_vni
);
920 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
923 json_object
*json_vni
= NULL
;
924 json_object
*json_import_rtl
= NULL
;
925 json_object
*json_export_rtl
= NULL
;
927 char buf2
[INET6_ADDRSTRLEN
];
930 struct listnode
*node
, *nnode
;
931 struct ecommunity
*ecom
;
937 json_vni
= json_object_new_object();
938 json_import_rtl
= json_object_new_array();
939 json_export_rtl
= json_object_new_array();
942 /* if an l3vni is present in bgp it is live */
944 snprintf(buf1
, sizeof(buf1
), "*");
947 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
948 json_object_string_add(json_vni
, "type", "L3");
949 json_object_string_add(json_vni
, "inKernel", "True");
950 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
951 &bgp
->originator_ip
);
952 json_object_string_add(
954 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
955 json_object_string_add(json_vni
, "advertiseGatewayMacip",
957 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
958 json_object_string_add(
959 json_vni
, "advertisePip",
960 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
961 json_object_string_addf(json_vni
, "sysIP", "%pI4",
962 &bgp
->evpn_info
->pip_ip
);
963 json_object_string_add(json_vni
, "sysMAC",
964 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
965 buf2
, sizeof(buf2
)));
966 json_object_string_add(
968 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
970 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
971 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
974 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
975 ecom_str
= ecommunity_ecom2str(ecom
,
976 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
979 json_object_array_add(json_import_rtl
,
980 json_object_new_string(ecom_str
));
982 if (listcount(bgp
->vrf_import_rtl
) > 1)
983 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
986 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
988 vty_out(vty
, " %-25s", rt_buf
);
991 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
993 /* If there are multiple import RTs we break here and show only
1000 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1002 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
1003 ecom_str
= ecommunity_ecom2str(ecom
,
1004 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1007 json_object_array_add(json_export_rtl
,
1008 json_object_new_string(ecom_str
));
1010 if (listcount(bgp
->vrf_export_rtl
) > 1)
1011 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1014 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1016 vty_out(vty
, " %-25s", rt_buf
);
1019 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1021 /* If there are multiple export RTs we break here and show only
1028 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1031 char vni_str
[VNI_STR_LEN
];
1033 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1034 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1035 json_object_object_add(json
, vni_str
, json_vni
);
1041 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1045 json_object
*json_vni
= NULL
;
1046 json_object
*json_import_rtl
= NULL
;
1047 json_object
*json_export_rtl
= NULL
;
1048 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1050 char buf2
[RD_ADDRSTRLEN
];
1053 struct listnode
*node
, *nnode
;
1054 struct ecommunity
*ecom
;
1055 struct bgp
*bgp_evpn
;
1060 bgp_evpn
= bgp_get_evpn();
1063 json_vni
= json_object_new_object();
1064 json_import_rtl
= json_object_new_array();
1065 json_export_rtl
= json_object_new_array();
1069 if (is_vni_live(vpn
))
1070 snprintf(buf1
, sizeof(buf1
), "*");
1073 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1074 json_object_string_add(json_vni
, "type", "L2");
1075 json_object_string_add(json_vni
, "inKernel",
1076 is_vni_live(vpn
) ? "True" : "False");
1077 json_object_string_add(
1079 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1080 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1081 &vpn
->originator_ip
);
1082 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1084 /* per vni knob is enabled -- Enabled
1085 * Global knob is enabled -- Active
1086 * default -- Disabled
1088 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1089 && bgp_evpn
->advertise_gw_macip
)
1090 json_object_string_add(
1091 json_vni
, "advertiseGatewayMacip", "Active");
1092 else if (vpn
->advertise_gw_macip
)
1093 json_object_string_add(
1094 json_vni
, "advertiseGatewayMacip", "Enabled");
1096 json_object_string_add(
1097 json_vni
, "advertiseGatewayMacip", "Disabled");
1098 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1099 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1100 json_object_string_add(json_vni
, "advertiseSviMacIp",
1102 else if (vpn
->advertise_svi_macip
)
1103 json_object_string_add(json_vni
, "advertiseSviMacIp",
1106 json_object_string_add(json_vni
, "advertiseSviMacIp",
1109 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1110 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1113 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1114 ecom_str
= ecommunity_ecom2str(ecom
,
1115 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1118 json_object_array_add(json_import_rtl
,
1119 json_object_new_string(ecom_str
));
1121 if (listcount(vpn
->import_rtl
) > 1)
1122 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1125 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1127 vty_out(vty
, " %-25s", rt_buf
);
1130 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1132 /* If there are multiple import RTs we break here and show only
1139 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1141 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1142 ecom_str
= ecommunity_ecom2str(ecom
,
1143 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1146 json_object_array_add(json_export_rtl
,
1147 json_object_new_string(ecom_str
));
1149 if (listcount(vpn
->export_rtl
) > 1)
1150 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1153 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1155 vty_out(vty
, " %-25s", rt_buf
);
1158 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1160 /* If there are multiple export RTs we break here and show only
1167 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1170 char vni_str
[VNI_STR_LEN
];
1172 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1173 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1174 json_object_object_add(json
, vni_str
, json_vni
);
1180 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1181 enum bgp_show_type type
, void *output_arg
,
1182 int option
, bool use_json
)
1184 afi_t afi
= AFI_L2VPN
;
1186 struct bgp_table
*table
;
1187 struct bgp_dest
*dest
;
1188 struct bgp_dest
*rm
;
1189 struct bgp_path_info
*pi
;
1192 char rd_str
[RD_ADDRSTRLEN
];
1196 unsigned long output_count
= 0;
1197 unsigned long total_count
= 0;
1198 json_object
*json
= NULL
;
1199 json_object
*json_array
= NULL
;
1200 json_object
*json_prefix_info
= NULL
;
1202 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1204 bgp
= bgp_get_evpn();
1207 vty_out(vty
, "No BGP process is configured\n");
1209 vty_out(vty
, "{}\n");
1214 json
= json_object_new_object();
1216 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1217 dest
= bgp_route_next(dest
)) {
1219 json_object
*json_nroute
= NULL
;
1220 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1222 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1225 table
= bgp_dest_get_bgp_table_info(dest
);
1230 tbl_ver
= table
->version
;
1232 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1233 pi
= bgp_dest_get_bgp_path_info(rm
);
1238 for (; pi
; pi
= pi
->next
) {
1239 struct community
*picomm
= NULL
;
1241 picomm
= bgp_attr_get_community(pi
->attr
);
1244 if (type
== bgp_show_type_neighbor
) {
1245 struct peer
*peer
= output_arg
;
1247 if (peer_cmp(peer
, pi
->peer
) != 0)
1250 if (type
== bgp_show_type_lcommunity_exact
) {
1251 struct lcommunity
*lcom
= output_arg
;
1253 if (!bgp_attr_get_lcommunity(
1256 bgp_attr_get_lcommunity(
1261 if (type
== bgp_show_type_lcommunity
) {
1262 struct lcommunity
*lcom
= output_arg
;
1264 if (!bgp_attr_get_lcommunity(
1267 bgp_attr_get_lcommunity(
1272 if (type
== bgp_show_type_community
) {
1273 struct community
*com
= output_arg
;
1276 !community_match(picomm
, com
))
1279 if (type
== bgp_show_type_community_exact
) {
1280 struct community
*com
= output_arg
;
1283 !community_cmp(picomm
, com
))
1288 json_object_int_add(
1289 json
, "bgpTableVersion",
1291 json_object_string_addf(
1296 json_object_int_add(
1299 bgp
->default_local_pref
);
1300 json_object_int_add(
1304 if (option
== SHOW_DISPLAY_TAGS
)
1309 == SHOW_DISPLAY_OVERLAY
)
1313 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1321 json_object_new_object();
1322 bgp_evpn_show_route_rd_header(
1323 vty
, dest
, json_nroute
, rd_str
,
1327 if (use_json
&& !json_array
)
1328 json_array
= json_object_new_array();
1330 if (option
== SHOW_DISPLAY_TAGS
)
1332 vty
, bgp_dest_get_prefix(rm
),
1333 pi
, no_display
, SAFI_EVPN
,
1335 else if (option
== SHOW_DISPLAY_OVERLAY
)
1336 route_vty_out_overlay(
1337 vty
, bgp_dest_get_prefix(rm
),
1338 pi
, no_display
, json_array
);
1341 bgp_dest_get_prefix(rm
),
1342 pi
, no_display
, SAFI_EVPN
,
1350 if (use_json
&& json_array
) {
1351 const struct prefix
*p
=
1352 bgp_dest_get_prefix(rm
);
1354 json_prefix_info
= json_object_new_object();
1356 prefix2str((struct prefix_evpn
*)p
, buf
,
1359 json_object_string_addf(
1360 json_prefix_info
, "prefix", "%pFX",
1361 (struct prefix_evpn
*)p
);
1363 json_object_int_add(json_prefix_info
,
1364 "prefixLen", p
->prefixlen
);
1366 json_object_object_add(json_prefix_info
,
1367 "paths", json_array
);
1368 json_object_object_add(json_nroute
, buf
,
1374 if (use_json
&& json_nroute
)
1375 json_object_object_add(json
, rd_str
, json_nroute
);
1379 json_object_int_add(json
, "numPrefix", output_count
);
1380 json_object_int_add(json
, "totalPrefix", total_count
);
1381 vty_json(vty
, json
);
1383 if (output_count
== 0)
1384 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1388 "\nDisplayed %ld out of %ld total prefixes\n",
1389 output_count
, total_count
);
1394 DEFUN(show_ip_bgp_l2vpn_evpn
,
1395 show_ip_bgp_l2vpn_evpn_cmd
,
1396 "show [ip] bgp l2vpn evpn [json]",
1397 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1399 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1400 SHOW_DISPLAY_STANDARD
,
1401 use_json(argc
, argv
));
1404 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1405 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1406 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1412 "Display information for a route distinguisher\n"
1413 "VPN Route Distinguisher\n"
1414 "All VPN Route Distinguishers\n"
1417 int idx_ext_community
= 0;
1419 struct prefix_rd prd
;
1422 if (argv_find(argv
, argc
, "all", &rd_all
))
1423 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1424 NULL
, SHOW_DISPLAY_STANDARD
,
1425 use_json(argc
, argv
));
1427 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1428 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1430 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1433 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1434 SHOW_DISPLAY_STANDARD
,
1435 use_json(argc
, argv
));
1438 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1439 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1440 "show [ip] bgp l2vpn evpn all tags",
1446 "Display information about all EVPN NLRIs\n"
1447 "Display BGP tags for prefixes\n")
1449 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1450 SHOW_DISPLAY_TAGS
, 0);
1453 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1454 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1455 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1461 "Display information for a route distinguisher\n"
1462 "VPN Route Distinguisher\n"
1463 "All VPN Route Distinguishers\n"
1464 "Display BGP tags for prefixes\n")
1466 int idx_ext_community
= 0;
1468 struct prefix_rd prd
;
1471 if (argv_find(argv
, argc
, "all", &rd_all
))
1472 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1473 NULL
, SHOW_DISPLAY_TAGS
, 0);
1475 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1476 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1478 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1481 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1482 SHOW_DISPLAY_TAGS
, 0);
1485 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1486 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1487 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1493 "Detailed information on TCP and BGP neighbor connections\n"
1494 "IPv4 Neighbor to display information about\n"
1495 "IPv6 Neighbor to display information about\n"
1496 "Neighbor on BGP configured interface\n"
1497 "Display routes learned from neighbor\n" JSON_STR
)
1501 char *peerstr
= NULL
;
1502 bool uj
= use_json(argc
, argv
);
1503 afi_t afi
= AFI_L2VPN
;
1504 safi_t safi
= SAFI_EVPN
;
1505 struct bgp
*bgp
= NULL
;
1507 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1510 vty_out(vty
, "No index\n");
1514 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1515 argv_find(argv
, argc
, "neighbors", &idx
);
1516 peerstr
= argv
[++idx
]->arg
;
1518 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1521 json_object
*json_no
= NULL
;
1522 json_no
= json_object_new_object();
1523 json_object_string_add(json_no
, "warning",
1524 "Malformed address");
1525 vty_out(vty
, "%s\n",
1526 json_object_to_json_string(json_no
));
1527 json_object_free(json_no
);
1529 vty_out(vty
, "Malformed address: %s\n",
1533 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1535 json_object
*json_no
= NULL
;
1536 json_no
= json_object_new_object();
1537 json_object_string_add(
1539 "No such neighbor or address family");
1540 vty_out(vty
, "%s\n",
1541 json_object_to_json_string(json_no
));
1542 json_object_free(json_no
);
1544 vty_out(vty
, "%% No such neighbor or address family\n");
1548 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1549 SHOW_DISPLAY_STANDARD
, uj
);
1552 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1553 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1554 "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]",
1560 "Display information for a route distinguisher\n"
1561 "VPN Route Distinguisher\n"
1562 "All VPN Route Distinguishers\n"
1563 "Detailed information on TCP and BGP neighbor connections\n"
1564 "IPv4 Neighbor to display information about\n"
1565 "IPv6 Neighbor to display information about\n"
1566 "Neighbor on BGP configured interface\n"
1567 "Display routes learned from neighbor\n" JSON_STR
)
1569 int idx_ext_community
= 0;
1573 char *peerstr
= NULL
;
1574 struct prefix_rd prd
= {};
1575 bool uj
= use_json(argc
, argv
);
1576 afi_t afi
= AFI_L2VPN
;
1577 safi_t safi
= SAFI_EVPN
;
1578 struct bgp
*bgp
= NULL
;
1581 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1584 vty_out(vty
, "No index\n");
1588 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1589 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1590 &idx_ext_community
);
1591 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1594 json_object
*json_no
= NULL
;
1595 json_no
= json_object_new_object();
1596 json_object_string_add(
1598 "Malformed Route Distinguisher");
1599 vty_out(vty
, "%s\n",
1600 json_object_to_json_string(json_no
));
1601 json_object_free(json_no
);
1604 "%% Malformed Route Distinguisher\n");
1609 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1610 argv_find(argv
, argc
, "neighbors", &idx
);
1611 peerstr
= argv
[++idx
]->arg
;
1613 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1616 json_object
*json_no
= NULL
;
1617 json_no
= json_object_new_object();
1618 json_object_string_add(json_no
, "warning",
1619 "Malformed address");
1620 vty_out(vty
, "%s\n",
1621 json_object_to_json_string(json_no
));
1622 json_object_free(json_no
);
1624 vty_out(vty
, "Malformed address: %s\n",
1628 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1630 json_object
*json_no
= NULL
;
1631 json_no
= json_object_new_object();
1632 json_object_string_add(
1634 "No such neighbor or address family");
1635 vty_out(vty
, "%s\n",
1636 json_object_to_json_string(json_no
));
1637 json_object_free(json_no
);
1639 vty_out(vty
, "%% No such neighbor or address family\n");
1645 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1646 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1648 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1649 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1652 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1653 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1654 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1660 "Detailed information on TCP and BGP neighbor connections\n"
1661 "IPv4 Neighbor to display information about\n"
1662 "IPv6 Neighbor to display information about\n"
1663 "Neighbor on BGP configured interface\n"
1664 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1668 bool uj
= use_json(argc
, argv
);
1669 struct bgp
*bgp
= NULL
;
1670 afi_t afi
= AFI_L2VPN
;
1671 safi_t safi
= SAFI_EVPN
;
1672 char *peerstr
= NULL
;
1677 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1680 vty_out(vty
, "No index\n");
1684 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1685 argv_find(argv
, argc
, "neighbors", &idx
);
1686 peerstr
= argv
[++idx
]->arg
;
1688 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1691 json_object
*json_no
= NULL
;
1692 json_no
= json_object_new_object();
1693 json_object_string_add(json_no
, "warning",
1694 "Malformed address");
1695 vty_out(vty
, "%s\n",
1696 json_object_to_json_string(json_no
));
1697 json_object_free(json_no
);
1699 vty_out(vty
, "Malformed address: %s\n",
1703 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1705 json_object
*json_no
= NULL
;
1706 json_no
= json_object_new_object();
1707 json_object_string_add(
1709 "No such neighbor or address family");
1710 vty_out(vty
, "%s\n",
1711 json_object_to_json_string(json_no
));
1712 json_object_free(json_no
);
1714 vty_out(vty
, "%% No such neighbor or address family\n");
1718 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1721 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1722 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1723 "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]",
1729 "Display information for a route distinguisher\n"
1730 "VPN Route Distinguisher\n"
1731 "All VPN Route Distinguishers\n"
1732 "Detailed information on TCP and BGP neighbor connections\n"
1733 "IPv4 Neighbor to display information about\n"
1734 "IPv6 Neighbor to display information about\n"
1735 "Neighbor on BGP configured interface\n"
1736 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1738 int idx_ext_community
= 0;
1742 struct prefix_rd prd
;
1743 struct bgp
*bgp
= NULL
;
1744 bool uj
= use_json(argc
, argv
);
1745 char *peerstr
= NULL
;
1746 afi_t afi
= AFI_L2VPN
;
1747 safi_t safi
= SAFI_EVPN
;
1756 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1759 vty_out(vty
, "No index\n");
1763 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1764 argv_find(argv
, argc
, "neighbors", &idx
);
1765 peerstr
= argv
[++idx
]->arg
;
1767 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1770 json_object
*json_no
= NULL
;
1771 json_no
= json_object_new_object();
1772 json_object_string_add(json_no
, "warning",
1773 "Malformed address");
1774 vty_out(vty
, "%s\n",
1775 json_object_to_json_string(json_no
));
1776 json_object_free(json_no
);
1778 vty_out(vty
, "Malformed address: %s\n",
1782 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1784 json_object
*json_no
= NULL
;
1785 json_no
= json_object_new_object();
1786 json_object_string_add(
1788 "No such neighbor or address family");
1789 vty_out(vty
, "%s\n",
1790 json_object_to_json_string(json_no
));
1791 json_object_free(json_no
);
1793 vty_out(vty
, "%% No such neighbor or address family\n");
1797 if (argv_find(argv
, argc
, "all", &rd_all
))
1798 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1801 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1802 &idx_ext_community
);
1803 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1806 json_object
*json_no
= NULL
;
1807 json_no
= json_object_new_object();
1808 json_object_string_add(
1810 "Malformed Route Distinguisher");
1811 vty_out(vty
, "%s\n",
1812 json_object_to_json_string(json_no
));
1813 json_object_free(json_no
);
1816 "%% Malformed Route Distinguisher\n");
1821 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1824 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1825 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1826 "show [ip] bgp l2vpn evpn all overlay [json]",
1832 "Display information about all EVPN NLRIs\n"
1833 "Display BGP Overlay Information for prefixes\n"
1836 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1837 SHOW_DISPLAY_OVERLAY
,
1838 use_json(argc
, argv
));
1841 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1842 show_ip_bgp_evpn_rd_overlay_cmd
,
1843 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1849 "Display information for a route distinguisher\n"
1850 "VPN Route Distinguisher\n"
1851 "All VPN Route Distinguishers\n"
1852 "Display BGP Overlay Information for prefixes\n")
1854 int idx_ext_community
= 0;
1856 struct prefix_rd prd
;
1859 if (argv_find(argv
, argc
, "all", &rd_all
))
1860 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1861 NULL
, SHOW_DISPLAY_OVERLAY
,
1862 use_json(argc
, argv
));
1864 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1865 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1867 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1870 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1871 SHOW_DISPLAY_OVERLAY
,
1872 use_json(argc
, argv
));
1875 DEFUN(show_bgp_l2vpn_evpn_com
,
1876 show_bgp_l2vpn_evpn_com_cmd
,
1877 "show bgp l2vpn evpn \
1878 <community AA:NN|large-community AA:BB:CC> \
1879 [exact-match] [json]",
1884 "Display routes matching the community\n"
1885 "Community number where AA and NN are (0-65535)\n"
1886 "Display routes matching the large-community\n"
1887 "List of large-community numbers\n"
1888 "Exact match of the communities\n"
1893 const char *clist_number_or_name
;
1894 int show_type
= bgp_show_type_normal
;
1895 struct community
*com
;
1896 struct lcommunity
*lcom
;
1898 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1899 clist_number_or_name
= argv
[++idx
]->arg
;
1900 show_type
= bgp_show_type_lcommunity
;
1902 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1903 show_type
= bgp_show_type_lcommunity_exact
;
1905 lcom
= lcommunity_str2com(clist_number_or_name
);
1907 vty_out(vty
, "%% Large-community malformed\n");
1911 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1912 SHOW_DISPLAY_STANDARD
,
1913 use_json(argc
, argv
));
1915 lcommunity_free(&lcom
);
1916 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1917 clist_number_or_name
= argv
[++idx
]->arg
;
1918 show_type
= bgp_show_type_community
;
1920 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1921 show_type
= bgp_show_type_community_exact
;
1923 com
= community_str2com(clist_number_or_name
);
1926 vty_out(vty
, "%% Community malformed: %s\n",
1927 clist_number_or_name
);
1931 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1932 SHOW_DISPLAY_STANDARD
,
1933 use_json(argc
, argv
));
1934 community_free(&com
);
1940 /* For testing purpose, static route of EVPN RT-5. */
1941 DEFUN(evpnrt5_network
,
1942 evpnrt5_network_cmd
,
1943 "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map RMAP_NAME]",
1944 "Specify a network to announce via BGP\n"
1947 "Specify Route Distinguisher\n"
1948 "VPN Route Distinguisher\n"
1950 "Ethernet Tag Value\n"
1953 "Ethernet Segment Identifier\n"
1954 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1956 "Gateway IP ( A.B.C.D )\n"
1957 "Gateway IPv6 ( X:X::X:X )\n"
1958 "Router Mac Ext Comm\n"
1959 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1960 "Route-map to modify the attributes\n"
1961 "Name of the route map\n")
1963 int idx_ipv4_prefixlen
= 1;
1964 int idx_route_distinguisher
= 3;
1969 int idx_routermac
= 13;
1971 return bgp_static_set_safi(
1972 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1973 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1974 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1975 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1976 argv
[idx_routermac
]->arg
);
1979 /* For testing purpose, static route of EVPN RT-5. */
1980 DEFUN(no_evpnrt5_network
,
1981 no_evpnrt5_network_cmd
,
1982 "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>",
1984 "Specify a network to announce via BGP\n"
1987 "Specify Route Distinguisher\n"
1988 "VPN Route Distinguisher\n"
1990 "Ethernet Tag Value\n"
1993 "Ethernet Segment Identifier\n"
1994 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1995 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1997 int idx_ipv4_prefixlen
= 2;
1998 int idx_ext_community
= 4;
2003 return bgp_static_unset_safi(
2004 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2005 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2006 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2007 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2010 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2012 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2015 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2017 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2021 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2022 * check that this is a change.
2024 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2025 struct ecommunity
*ecomadd
)
2027 /* If the VNI is "live", we need to uninstall routes using the current
2028 * import RT(s) first before we update the import RT, and subsequently
2031 if (is_vni_live(vpn
))
2032 bgp_evpn_uninstall_routes(bgp
, vpn
);
2034 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2035 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2037 /* If the auto route-target is in use we must remove it */
2038 evpn_import_rt_delete_auto(bgp
, vpn
);
2040 /* Add new RT and rebuild the RT to VNI mapping */
2041 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2043 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2044 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2046 /* Install routes that match new import RT */
2047 if (is_vni_live(vpn
))
2048 bgp_evpn_install_routes(bgp
, vpn
);
2052 * Unconfigure Import RT(s) for a VNI (vty handler).
2054 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2055 struct ecommunity
*ecomdel
)
2057 struct listnode
*node
, *nnode
, *node_to_del
;
2058 struct ecommunity
*ecom
;
2060 /* Along the lines of "configure" except we have to reset to the
2063 if (is_vni_live(vpn
))
2064 bgp_evpn_uninstall_routes(bgp
, vpn
);
2066 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2067 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2069 /* Delete all import RTs */
2070 if (ecomdel
== NULL
) {
2071 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2072 ecommunity_free(&ecom
);
2073 list_delete_node(vpn
->import_rtl
, node
);
2077 /* Delete a specific import RT */
2081 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2082 if (ecommunity_match(ecom
, ecomdel
)) {
2083 ecommunity_free(&ecom
);
2090 list_delete_node(vpn
->import_rtl
, node_to_del
);
2093 assert(vpn
->import_rtl
);
2094 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2095 if (list_isempty(vpn
->import_rtl
)) {
2096 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2097 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2099 /* Rebuild the RT to VNI mapping */
2101 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2103 /* Install routes that match new import RT */
2104 if (is_vni_live(vpn
))
2105 bgp_evpn_install_routes(bgp
, vpn
);
2109 * Configure the Export RT for a VNI (vty handler). Caller expected to
2110 * check that this is a change. Note that only a single export RT is
2111 * allowed for a VNI and any change to configuration is implemented as
2112 * a "replace" (similar to other configuration).
2114 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2115 struct ecommunity
*ecomadd
)
2117 /* If the auto route-target is in use we must remove it */
2118 evpn_export_rt_delete_auto(bgp
, vpn
);
2120 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2121 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2123 if (is_vni_live(vpn
))
2124 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2128 * Unconfigure the Export RT for a VNI (vty handler)
2130 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2131 struct ecommunity
*ecomdel
)
2133 struct listnode
*node
, *nnode
, *node_to_del
;
2134 struct ecommunity
*ecom
;
2136 /* Delete all export RTs */
2137 if (ecomdel
== NULL
) {
2138 /* Reset to default and process all routes. */
2139 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2140 ecommunity_free(&ecom
);
2141 list_delete_node(vpn
->export_rtl
, node
);
2145 /* Delete a specific export RT */
2149 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2150 if (ecommunity_match(ecom
, ecomdel
)) {
2151 ecommunity_free(&ecom
);
2158 list_delete_node(vpn
->export_rtl
, node_to_del
);
2161 assert(vpn
->export_rtl
);
2162 if (list_isempty(vpn
->export_rtl
)) {
2163 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2164 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2167 if (is_vni_live(vpn
))
2168 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2172 * Configure RD for VRF
2174 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2176 /* If we have already advertise type-5 routes with a diffrent RD, we
2177 * have to delete and withdraw them firs
2179 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2182 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2183 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2185 /* We have a new RD for VRF.
2186 * Advertise all type-5 routes again with the new RD
2188 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2192 * Unconfigure RD for VRF
2194 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2196 /* If we have already advertise type-5 routes with a diffrent RD, we
2197 * have to delete and withdraw them firs
2199 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2201 /* fall back to default RD */
2202 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2203 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2205 /* We have a new RD for VRF.
2206 * Advertise all type-5 routes again with the new RD
2208 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2212 * Configure RD for a VNI (vty handler)
2214 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2215 struct prefix_rd
*rd
)
2217 /* If the VNI is "live", we need to delete and withdraw this VNI's
2218 * local routes with the prior RD first. Then, after updating RD,
2219 * need to re-advertise.
2221 if (is_vni_live(vpn
))
2222 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2225 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2226 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2228 if (is_vni_live(vpn
))
2229 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2233 * Unconfigure RD for a VNI (vty handler)
2235 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2237 /* If the VNI is "live", we need to delete and withdraw this VNI's
2238 * local routes with the prior RD first. Then, after resetting RD
2239 * to automatic value, need to re-advertise.
2241 if (is_vni_live(vpn
))
2242 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2244 /* reset RD to default */
2245 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2247 if (is_vni_live(vpn
))
2248 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2252 * Create VNI, if not already present (VTY handler). Mark as configured.
2254 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2256 struct bgpevpn
*vpn
;
2257 struct in_addr mcast_grp
= {INADDR_ANY
};
2259 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2261 /* Check if this L2VNI is already configured as L3VNI */
2262 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2265 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2270 /* tenant vrf will be updated when we get local_vni_add from
2273 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2276 /* Mark as configured. */
2277 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2282 * Delete VNI. If VNI does not exist in the system (i.e., just
2283 * configuration), all that is needed is to free it. Otherwise,
2284 * any parameters configured for the VNI need to be reset (with
2285 * appropriate action) and the VNI marked as unconfigured; the
2286 * VNI will continue to exist, purely as a "learnt" entity.
2288 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2290 if (!is_vni_live(vpn
)) {
2291 bgp_evpn_free(bgp
, vpn
);
2295 /* We need to take the unconfigure action for each parameter of this VNI
2296 * that is configured. Some optimization is possible, but not worth the
2297 * additional code for an operation that should be pretty rare.
2299 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2301 /* First, deal with the export side - RD and export RT changes. */
2302 if (is_rd_configured(vpn
))
2303 evpn_unconfigure_rd(bgp
, vpn
);
2304 if (is_export_rt_configured(vpn
))
2305 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2307 /* Next, deal with the import side. */
2308 if (is_import_rt_configured(vpn
))
2309 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2313 * Display import RT mapping to VRFs (vty handler)
2314 * bgp_evpn: evpn bgp instance
2316 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2324 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2325 (void (*)(struct hash_bucket
*,
2326 void *))show_vrf_import_rt_entry
,
2331 * Display import RT mapping to VNIs (vty handler)
2333 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2342 bgp
->import_rt_hash
,
2343 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2348 * Display EVPN routes for all VNIs - vty handler.
2350 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2351 struct in_addr vtep_ip
, json_object
*json
,
2355 struct vni_walk_ctx wctx
;
2357 num_vnis
= hashcount(bgp
->vnihash
);
2360 memset(&wctx
, 0, sizeof(wctx
));
2363 wctx
.vtep_ip
= vtep_ip
;
2365 wctx
.detail
= detail
;
2366 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2367 void *))show_vni_routes_hash
,
2372 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2374 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2375 vni_t vni
, struct in_addr orig_ip
,
2378 struct bgpevpn
*vpn
;
2379 struct prefix_evpn p
;
2380 struct bgp_dest
*dest
;
2381 struct bgp_path_info
*pi
;
2382 uint32_t path_cnt
= 0;
2385 json_object
*json_paths
= NULL
;
2391 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2393 vty_out(vty
, "VNI not found\n");
2397 /* See if route exists. */
2398 build_evpn_type3_prefix(&p
, orig_ip
);
2399 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2400 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2402 vty_out(vty
, "%% Network not in table\n");
2405 bgp_dest_unlock_node(dest
);
2411 json_paths
= json_object_new_array();
2413 /* Prefix and num paths displayed once per prefix. */
2414 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2416 /* Display each path for this prefix. */
2417 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2418 json_object
*json_path
= NULL
;
2421 json_path
= json_object_new_array();
2423 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2424 RPKI_NOT_BEING_USED
, json_path
);
2427 json_object_array_add(json_paths
, json_path
);
2434 json_object_object_add(json
, "paths", json_paths
);
2436 json_object_int_add(json
, "numPaths", path_cnt
);
2438 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2442 bgp_dest_unlock_node(dest
);
2446 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2447 * By definition, only matching type-2 route will be displayed.
2449 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2450 vni_t vni
, struct ethaddr
*mac
,
2451 struct ipaddr
*ip
, json_object
*json
)
2453 struct bgpevpn
*vpn
;
2454 struct prefix_evpn p
;
2455 struct bgp_dest
*dest
;
2456 struct bgp_path_info
*pi
;
2457 uint32_t path_cnt
= 0;
2460 json_object
*json_paths
= NULL
;
2466 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2469 vty_out(vty
, "VNI not found\n");
2473 /* See if route exists. Look for both non-sticky and sticky. */
2474 build_evpn_type2_prefix(&p
, mac
, ip
);
2475 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2476 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2478 vty_out(vty
, "%% Network not in table\n");
2481 bgp_dest_unlock_node(dest
);
2487 json_paths
= json_object_new_array();
2489 /* Prefix and num paths displayed once per prefix. */
2490 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2492 /* Display each path for this prefix. */
2493 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2494 json_object
*json_path
= NULL
;
2497 json_path
= json_object_new_array();
2499 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2500 RPKI_NOT_BEING_USED
, json_path
);
2503 json_object_array_add(json_paths
, json_path
);
2510 json_object_object_add(json
, "paths", json_paths
);
2512 json_object_int_add(json
, "numPaths", path_cnt
);
2514 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2518 bgp_dest_unlock_node(dest
);
2521 /* Disaplay EVPN routes for a ESI - VTY handler */
2522 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2523 esi_t
*esi
, json_object
*json
)
2525 struct bgp_evpn_es
*es
= NULL
;
2528 es
= bgp_evpn_es_find(esi
);
2531 vty_out(vty
, "ESI not found\n");
2535 show_esi_routes(bgp
, es
, vty
, json
);
2539 * Display EVPN routes for a VNI - vty handler.
2540 * If 'type' is non-zero, only routes matching that type are shown.
2541 * If the vtep_ip is non zero, only routes behind that vtep are shown
2543 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2544 int type
, struct in_addr vtep_ip
,
2547 struct bgpevpn
*vpn
;
2550 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2553 vty_out(vty
, "VNI not found\n");
2557 /* Walk this VNI's route table and display appropriate routes. */
2558 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2562 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2563 * IP (vty handler). By definition, only matching type-2 route will be
2566 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2567 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2568 struct ipaddr
*ip
, json_object
*json
)
2570 struct prefix_evpn p
;
2571 struct bgp_dest
*dest
;
2572 struct bgp_path_info
*pi
;
2575 uint32_t path_cnt
= 0;
2576 json_object
*json_paths
= NULL
;
2577 char prefix_str
[BUFSIZ
];
2582 /* See if route exists. Look for both non-sticky and sticky. */
2583 build_evpn_type2_prefix(&p
, mac
, ip
);
2584 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2585 (struct prefix
*)&p
, prd
);
2586 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2588 vty_out(vty
, "%% Network not in table\n");
2591 bgp_dest_unlock_node(dest
);
2596 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2598 /* Prefix and num paths displayed once per prefix. */
2599 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2602 json_paths
= json_object_new_array();
2604 /* Display each path for this prefix. */
2605 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2606 json_object
*json_path
= NULL
;
2609 json_path
= json_object_new_array();
2611 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2612 RPKI_NOT_BEING_USED
, json_path
);
2615 json_object_array_add(json_paths
, json_path
);
2620 if (json
&& path_cnt
) {
2622 json_object_object_add(json
, prefix_str
, json_paths
);
2623 json_object_int_add(json
, "numPaths", path_cnt
);
2625 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2629 bgp_dest_unlock_node(dest
);
2633 * Display BGP EVPN routing table -- for specific RD (vty handler)
2634 * If 'type' is non-zero, only routes matching that type are shown.
2636 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2637 struct prefix_rd
*prd
, int type
,
2640 struct bgp_dest
*rd_dest
;
2641 struct bgp_table
*table
;
2642 struct bgp_dest
*dest
;
2643 struct bgp_path_info
*pi
;
2647 uint32_t prefix_cnt
, path_cnt
;
2648 char rd_str
[RD_ADDRSTRLEN
];
2649 json_object
*json_rd
= NULL
;
2650 int add_rd_to_json
= 0;
2654 prefix_cnt
= path_cnt
= 0;
2656 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2658 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2662 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2663 if (table
== NULL
) {
2664 bgp_dest_unlock_node(rd_dest
);
2669 json_rd
= json_object_new_object();
2670 json_object_string_add(json_rd
, "rd", rd_str
);
2673 bgp_dest_unlock_node(rd_dest
);
2675 /* Display all prefixes with this RD. */
2676 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2677 const struct prefix_evpn
*evp
=
2678 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2679 json_object
*json_prefix
= NULL
;
2680 json_object
*json_paths
= NULL
;
2681 char prefix_str
[BUFSIZ
];
2682 int add_prefix_to_json
= 0;
2684 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2685 sizeof(prefix_str
));
2687 if (type
&& evp
->prefix
.route_type
!= type
)
2691 json_prefix
= json_object_new_object();
2693 pi
= bgp_dest_get_bgp_path_info(dest
);
2695 /* RD header and legend - once overall. */
2696 if (rd_header
&& !json
) {
2698 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2700 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2702 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2704 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2706 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2710 /* Prefix and num paths displayed once per prefix. */
2711 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2718 json_paths
= json_object_new_array();
2720 /* Display each path for this prefix. */
2721 for (; pi
; pi
= pi
->next
) {
2722 json_object
*json_path
= NULL
;
2725 json_path
= json_object_new_array();
2727 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2728 RPKI_NOT_BEING_USED
, json_path
);
2731 json_object_array_add(json_paths
, json_path
);
2734 add_prefix_to_json
= 1;
2739 if (add_prefix_to_json
) {
2740 json_object_object_add(json_prefix
, "paths",
2742 json_object_object_add(json_rd
, prefix_str
,
2745 json_object_free(json_paths
);
2746 json_object_free(json_prefix
);
2755 json_object_object_add(json
, rd_str
, json_rd
);
2757 json_object_free(json_rd
);
2761 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2762 json_object_int_add(json
, "numPaths", path_cnt
);
2764 if (prefix_cnt
== 0)
2765 vty_out(vty
, "No prefixes exist with this RD%s\n",
2766 type
? " (of requested type)" : "");
2769 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2770 prefix_cnt
, path_cnt
,
2771 type
? " (of requested type)" : "");
2776 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2777 * (vty handler). Only matching type-2 routes will be displayed.
2779 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2780 struct ethaddr
*mac
, struct ipaddr
*ip
,
2783 struct bgp_dest
*rd_dest
;
2784 struct bgp_table
*table
;
2785 struct bgp_dest
*dest
;
2786 struct bgp_path_info
*pi
;
2787 afi_t afi
= AFI_L2VPN
;
2788 safi_t safi
= SAFI_EVPN
;
2789 uint32_t prefix_cnt
, path_cnt
;
2790 prefix_cnt
= path_cnt
= 0;
2792 /* EVPN routing table is a 2-level table with the first level being
2793 * the RD. We need to look in every RD we know about.
2795 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2796 rd_dest
= bgp_route_next(rd_dest
)) {
2797 json_object
*json_paths
= NULL
; /* paths array for prefix */
2798 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2799 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2800 char rd_str
[RD_ADDRSTRLEN
];
2801 char prefix_str
[BUFSIZ
];
2802 int add_rd_to_json
= 0;
2803 struct prefix_evpn ep
;
2804 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2806 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2810 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2813 /* Construct an RT-2 from the user-supplied mac(ip),
2814 * then search the l2vpn evpn table for it.
2816 build_evpn_type2_prefix(&ep
, mac
, ip
);
2817 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2818 (struct prefix
*)&ep
,
2819 (struct prefix_rd
*)rd_destp
);
2824 json_rd
= json_object_new_object();
2826 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2828 prefix2str(p
, prefix_str
, sizeof(prefix_str
));
2830 pi
= bgp_dest_get_bgp_path_info(dest
);
2832 /* RD header - per RD. */
2833 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2834 rd_str
, RD_ADDRSTRLEN
);
2839 json_prefix
= json_object_new_object();
2840 json_paths
= json_object_new_array();
2841 json_object_string_add(json_prefix
, "prefix",
2843 json_object_int_add(json_prefix
, "prefixLen",
2846 /* Prefix and num paths displayed once per prefix. */
2847 route_vty_out_detail_header(
2848 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2849 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2851 /* For EVPN, the prefix is displayed for each path (to
2852 * fit in with code that already exists).
2854 for (; pi
; pi
= pi
->next
) {
2855 json_object
*json_path
= NULL
;
2861 json_path
= json_object_new_array();
2863 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2864 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2868 json_object_array_add(json_paths
, json_path
);
2874 json_object_object_add(json_prefix
, "paths",
2876 json_object_object_add(json_rd
, prefix_str
,
2879 json_object_object_add(json
, rd_str
, json_rd
);
2881 json_object_free(json_rd
);
2886 bgp_dest_unlock_node(dest
);
2890 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2891 json_object_int_add(json
, "numPaths", path_cnt
);
2893 if (prefix_cnt
== 0) {
2894 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2896 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2897 prefix_cnt
, path_cnt
);
2903 * Display BGP EVPN routing table - all routes (vty handler).
2904 * If 'type' is non-zero, only routes matching that type are shown.
2906 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2907 json_object
*json
, int detail
)
2909 struct bgp_dest
*rd_dest
;
2910 struct bgp_table
*table
;
2911 struct bgp_dest
*dest
;
2912 struct bgp_path_info
*pi
;
2913 int header
= detail
? 0 : 1;
2917 uint32_t prefix_cnt
, path_cnt
;
2921 prefix_cnt
= path_cnt
= 0;
2923 /* EVPN routing table is a 2-level table with the first level being
2926 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2927 rd_dest
= bgp_route_next(rd_dest
)) {
2928 char rd_str
[RD_ADDRSTRLEN
];
2929 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2930 int add_rd_to_json
= 0;
2932 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2934 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2938 tbl_ver
= table
->version
;
2939 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2943 json_rd
= json_object_new_object();
2947 /* Display all prefixes for an RD */
2948 for (dest
= bgp_table_top(table
); dest
;
2949 dest
= bgp_route_next(dest
)) {
2950 json_object
*json_prefix
=
2951 NULL
; /* contains prefix under a RD */
2952 json_object
*json_paths
=
2953 NULL
; /* array of paths under a prefix*/
2954 const struct prefix_evpn
*evp
=
2955 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2957 char prefix_str
[BUFSIZ
];
2958 int add_prefix_to_json
= 0;
2959 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2961 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2962 sizeof(prefix_str
));
2964 if (type
&& evp
->prefix
.route_type
!= type
)
2967 pi
= bgp_dest_get_bgp_path_info(dest
);
2969 /* Overall header/legend displayed once. */
2971 bgp_evpn_show_route_header(vty
, bgp
,
2976 "%19s Extended Community\n"
2981 /* RD header - per RD. */
2983 bgp_evpn_show_route_rd_header(
2984 vty
, rd_dest
, json_rd
, rd_str
,
2993 json_prefix
= json_object_new_object();
2994 json_paths
= json_object_new_array();
2995 json_object_string_add(json_prefix
, "prefix",
2997 json_object_int_add(json_prefix
, "prefixLen",
3001 /* Prefix and num paths displayed once per prefix. */
3003 route_vty_out_detail_header(
3005 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3006 SAFI_EVPN
, json_prefix
);
3008 /* For EVPN, the prefix is displayed for each path (to
3010 * with code that already exists).
3012 for (; pi
; pi
= pi
->next
) {
3013 json_object
*json_path
= NULL
;
3016 add_prefix_to_json
= 1;
3020 json_path
= json_object_new_array();
3023 route_vty_out_detail(
3024 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
3025 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3028 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3032 json_object_array_add(json_paths
,
3037 if (add_prefix_to_json
) {
3038 json_object_object_add(json_prefix
,
3041 json_object_object_add(json_rd
,
3045 json_object_free(json_prefix
);
3046 json_object_free(json_paths
);
3055 json_object_object_add(json
, rd_str
, json_rd
);
3057 json_object_free(json_rd
);
3064 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3065 json_object_int_add(json
, "numPaths", path_cnt
);
3067 if (prefix_cnt
== 0) {
3068 vty_out(vty
, "No EVPN prefixes %sexist\n",
3069 type
? "(of requested type) " : "");
3071 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3072 prefix_cnt
, path_cnt
,
3073 type
? " (of requested type)" : "");
3079 * Display specified VNI (vty handler)
3081 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3085 struct bgpevpn
*vpn
;
3087 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3090 display_vni(vty
, vpn
, json
);
3092 struct bgp
*bgp_temp
;
3093 struct listnode
*node
= NULL
;
3095 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3096 if (bgp_temp
->l3vni
== vni
) {
3098 display_l3vni(vty
, bgp_temp
, json
);
3105 vty_out(vty
, "{}\n");
3107 vty_out(vty
, "VNI not found\n");
3114 * Display a VNI (upon user query).
3116 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3120 struct bgp
*bgp_temp
= NULL
;
3121 struct listnode
*node
;
3125 vty_out(vty
, "Flags: * - Kernel\n");
3126 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3127 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3130 /* print all L2 VNIS */
3133 hash_iterate(bgp
->vnihash
,
3134 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3137 /* print all L3 VNIs */
3138 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3139 show_l3vni_entry(vty
, bgp_temp
, json
);
3143 * evpn - enable advertisement of svi MAC-IP
3145 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3149 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3151 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3154 bgp
->evpn_info
->advertise_svi_macip
= set
;
3155 bgp_zebra_advertise_svi_macip(bgp
,
3156 bgp
->evpn_info
->advertise_svi_macip
, 0);
3158 if (set
&& vpn
->advertise_svi_macip
)
3160 else if (!set
&& !vpn
->advertise_svi_macip
)
3163 vpn
->advertise_svi_macip
= set
;
3164 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3170 * evpn - enable advertisement of default g/w
3172 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3175 if (bgp
->advertise_gw_macip
)
3178 bgp
->advertise_gw_macip
= 1;
3179 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3181 if (vpn
->advertise_gw_macip
)
3184 vpn
->advertise_gw_macip
= 1;
3185 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3192 * evpn - disable advertisement of default g/w
3194 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3195 struct bgpevpn
*vpn
)
3198 if (!bgp
->advertise_gw_macip
)
3201 bgp
->advertise_gw_macip
= 0;
3202 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3204 if (!vpn
->advertise_gw_macip
)
3207 vpn
->advertise_gw_macip
= 0;
3208 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3215 * evpn - enable advertisement of default g/w
3217 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3218 afi_t afi
, bool add
)
3220 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3223 /* bail if we are already advertising default route */
3224 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3228 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3229 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3230 else if (afi
== AFI_IP6
)
3231 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3232 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3234 /* bail out if we havent advertised the default route */
3235 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3238 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3239 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3240 else if (afi
== AFI_IP6
)
3241 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3242 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3245 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3249 * evpn - enable advertisement of default g/w
3251 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3252 struct bgpevpn
*vpn
)
3254 if (vpn
->advertise_subnet
)
3257 vpn
->advertise_subnet
= 1;
3258 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3262 * evpn - disable advertisement of default g/w
3264 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3266 if (!vpn
->advertise_subnet
)
3269 vpn
->advertise_subnet
= 0;
3270 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3274 * EVPN (VNI advertisement) enabled. Register with zebra.
3276 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3278 bgp
->advertise_all_vni
= 1;
3280 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3284 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3285 * cache, EVPN routes (delete and withdraw from peers).
3287 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3289 bgp
->advertise_all_vni
= 0;
3290 bgp_set_evpn(bgp_get_default());
3291 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3292 bgp_evpn_cleanup_on_disable(bgp
);
3295 /* Set resolve overlay index flag */
3296 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3298 if (set
== bgp
->resolve_overlay_index
)
3302 bgp
->resolve_overlay_index
= true;
3303 hash_iterate(bgp
->vnihash
,
3304 (void (*)(struct hash_bucket
*, void *))
3305 bgp_evpn_handle_resolve_overlay_index_set
,
3310 (void (*)(struct hash_bucket
*, void *))
3311 bgp_evpn_handle_resolve_overlay_index_unset
,
3313 bgp
->resolve_overlay_index
= false;
3318 * EVPN - use RFC8365 to auto-derive RT
3320 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3322 bgp
->advertise_autort_rfc8365
= 1;
3323 bgp_evpn_handle_autort_change(bgp
);
3327 * EVPN - don't use RFC8365 to auto-derive RT
3329 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3331 bgp
->advertise_autort_rfc8365
= 0;
3332 bgp_evpn_handle_autort_change(bgp
);
3335 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3337 char buf1
[RD_ADDRSTRLEN
];
3339 struct listnode
*node
, *nnode
;
3340 struct ecommunity
*ecom
;
3342 if (is_vni_configured(vpn
)) {
3343 vty_out(vty
, " vni %d\n", vpn
->vni
);
3344 if (is_rd_configured(vpn
))
3345 vty_out(vty
, " rd %s\n",
3346 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3348 if (is_import_rt_configured(vpn
)) {
3349 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3351 ecom_str
= ecommunity_ecom2str(
3352 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3353 vty_out(vty
, " route-target import %s\n",
3355 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3359 if (is_export_rt_configured(vpn
)) {
3360 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3362 ecom_str
= ecommunity_ecom2str(
3363 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3364 vty_out(vty
, " route-target export %s\n",
3366 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3370 if (vpn
->advertise_gw_macip
)
3371 vty_out(vty
, " advertise-default-gw\n");
3373 if (vpn
->advertise_svi_macip
)
3374 vty_out(vty
, " advertise-svi-ip\n");
3376 if (vpn
->advertise_subnet
)
3377 vty_out(vty
, " advertise-subnet\n");
3379 vty_out(vty
, " exit-vni\n");
3383 #ifndef VTYSH_EXTRACT_PL
3384 #include "bgpd/bgp_evpn_vty_clippy.c"
3387 DEFPY(bgp_evpn_flood_control
,
3388 bgp_evpn_flood_control_cmd
,
3389 "[no$no] flooding <disable$disable|head-end-replication$her>",
3391 "Specify handling for BUM packets\n"
3392 "Do not flood any BUM packets\n"
3393 "Flood BUM packets using head-end replication\n")
3395 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3396 enum vxlan_flood_control flood_ctrl
;
3402 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3404 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3408 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3411 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3412 bgp_evpn_flood_control_change(bgp
);
3417 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3418 bgp_evpn_advertise_default_gw_vni_cmd
,
3419 "advertise-default-gw",
3420 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3422 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3423 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3428 evpn_set_advertise_default_gw(bgp
, vpn
);
3433 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3434 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3435 "no advertise-default-gw",
3437 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3439 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3440 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3445 evpn_unset_advertise_default_gw(bgp
, vpn
);
3451 DEFUN (bgp_evpn_advertise_default_gw
,
3452 bgp_evpn_advertise_default_gw_cmd
,
3453 "advertise-default-gw",
3454 "Advertise All default g/w mac-ip routes in EVPN\n")
3456 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3461 if (!EVPN_ENABLED(bgp
)) {
3463 "This command is only supported under the EVPN VRF\n");
3467 evpn_set_advertise_default_gw(bgp
, NULL
);
3472 DEFUN (no_bgp_evpn_advertise_default_gw
,
3473 no_bgp_evpn_advertise_default_gw_cmd
,
3474 "no advertise-default-gw",
3476 "Withdraw All default g/w mac-ip routes from EVPN\n")
3478 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3483 evpn_unset_advertise_default_gw(bgp
, NULL
);
3488 DEFUN (bgp_evpn_advertise_all_vni
,
3489 bgp_evpn_advertise_all_vni_cmd
,
3490 "advertise-all-vni",
3491 "Advertise All local VNIs\n")
3493 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3494 struct bgp
*bgp_evpn
= NULL
;
3499 bgp_evpn
= bgp_get_evpn();
3500 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3501 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3502 bgp_evpn
->name_pretty
);
3503 return CMD_WARNING_CONFIG_FAILED
;
3506 evpn_set_advertise_all_vni(bgp
);
3510 DEFUN (no_bgp_evpn_advertise_all_vni
,
3511 no_bgp_evpn_advertise_all_vni_cmd
,
3512 "no advertise-all-vni",
3514 "Advertise All local VNIs\n")
3516 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3520 evpn_unset_advertise_all_vni(bgp
);
3524 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3525 bgp_evpn_advertise_autort_rfc8365_cmd
,
3526 "autort rfc8365-compatible",
3527 "Auto-derivation of RT\n"
3528 "Auto-derivation of RT using RFC8365\n")
3530 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3534 evpn_set_advertise_autort_rfc8365(bgp
);
3538 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3539 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3540 "no autort rfc8365-compatible",
3542 "Auto-derivation of RT\n"
3543 "Auto-derivation of RT using RFC8365\n")
3545 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3549 evpn_unset_advertise_autort_rfc8365(bgp
);
3553 DEFUN (bgp_evpn_default_originate
,
3554 bgp_evpn_default_originate_cmd
,
3555 "default-originate <ipv4 | ipv6>",
3556 "originate a default route\n"
3557 "ipv4 address family\n"
3558 "ipv6 address family\n")
3562 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3566 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3567 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3571 DEFUN (no_bgp_evpn_default_originate
,
3572 no_bgp_evpn_default_originate_cmd
,
3573 "no default-originate <ipv4 | ipv6>",
3575 "withdraw a default route\n"
3576 "ipv4 address family\n"
3577 "ipv6 address family\n")
3581 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3585 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3586 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3590 DEFPY (dup_addr_detection
,
3591 dup_addr_detection_cmd
,
3592 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3593 "Duplicate address detection\n"
3594 "Max allowed moves before address detected as duplicate\n"
3595 "Num of max allowed moves (2-1000) default 5\n"
3596 "Duplicate address detection time\n"
3597 "Time in seconds (2-1800) default 180\n")
3599 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3604 if (!EVPN_ENABLED(bgp_vrf
)) {
3606 "This command is only supported under the EVPN VRF\n");
3610 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3613 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3615 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3617 bgp_zebra_dup_addr_detection(bgp_vrf
);
3622 DEFPY (dup_addr_detection_auto_recovery
,
3623 dup_addr_detection_auto_recovery_cmd
,
3624 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3625 "Duplicate address detection\n"
3626 "Duplicate address detection freeze\n"
3627 "Duplicate address detection permanent freeze\n"
3628 "Duplicate address detection freeze time (30-3600)\n")
3630 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3631 uint32_t freeze_time
= freeze_time_val
;
3636 if (!EVPN_ENABLED(bgp_vrf
)) {
3638 "This command is only supported under the EVPN VRF\n");
3642 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3643 bgp_vrf
->evpn_info
->dad_freeze
= true;
3644 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3646 bgp_zebra_dup_addr_detection(bgp_vrf
);
3651 DEFPY (no_dup_addr_detection
,
3652 no_dup_addr_detection_cmd
,
3653 "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>]",
3655 "Duplicate address detection\n"
3656 "Max allowed moves before address detected as duplicate\n"
3657 "Num of max allowed moves (2-1000) default 5\n"
3658 "Duplicate address detection time\n"
3659 "Time in seconds (2-1800) default 180\n"
3660 "Duplicate address detection freeze\n"
3661 "Duplicate address detection permanent freeze\n"
3662 "Duplicate address detection freeze time (30-3600)\n")
3664 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3665 uint32_t max_moves
= (uint32_t)max_moves_val
;
3666 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3671 if (!EVPN_ENABLED(bgp_vrf
)) {
3673 "This command is only supported under the EVPN VRF\n");
3678 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3680 /* Reset all parameters to default. */
3681 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3682 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3683 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3684 bgp_vrf
->evpn_info
->dad_freeze
= false;
3685 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3688 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3690 "%% Value does not match with config\n");
3693 bgp_vrf
->evpn_info
->dad_max_moves
=
3694 EVPN_DAD_DEFAULT_MAX_MOVES
;
3698 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3700 "%% Value does not match with config\n");
3703 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3707 if (bgp_vrf
->evpn_info
->dad_freeze_time
3710 "%% Value does not match with config\n");
3713 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3714 bgp_vrf
->evpn_info
->dad_freeze
= false;
3717 if (permanent_val
) {
3718 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3720 "%% Value does not match with config\n");
3723 bgp_vrf
->evpn_info
->dad_freeze
= false;
3727 bgp_zebra_dup_addr_detection(bgp_vrf
);
3732 DEFPY(bgp_evpn_advertise_svi_ip
,
3733 bgp_evpn_advertise_svi_ip_cmd
,
3734 "[no$no] advertise-svi-ip",
3736 "Advertise svi mac-ip routes in EVPN\n")
3738 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3744 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3746 if (!EVPN_ENABLED(bgp
)) {
3748 "This command is only supported under EVPN VRF\n");
3751 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3757 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3758 bgp_evpn_advertise_svi_ip_vni_cmd
,
3759 "[no$no] advertise-svi-ip",
3761 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3763 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3764 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3770 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3772 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3777 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3778 bgp_evpn_advertise_vni_subnet_cmd
,
3780 "Advertise the subnet corresponding to VNI\n")
3782 struct bgp
*bgp_vrf
= NULL
;
3783 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3784 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3789 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3793 evpn_set_advertise_subnet(bgp
, vpn
);
3797 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3798 no_bgp_evpn_advertise_vni_subnet_cmd
,
3799 "no advertise-subnet",
3801 "Advertise All local VNIs\n")
3803 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3804 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3809 evpn_unset_advertise_subnet(bgp
, vpn
);
3813 DEFUN (bgp_evpn_advertise_type5
,
3814 bgp_evpn_advertise_type5_cmd
,
3815 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3816 "Advertise prefix routes\n"
3819 "advertise gateway IP overlay index\n"
3820 "route-map for filtering specific routes\n"
3821 "Name of the route map\n")
3823 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3830 int rmap_changed
= 0;
3831 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3833 bool adv_flag_changed
= false;
3835 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3836 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3837 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3839 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3841 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3843 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3844 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3847 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3851 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3853 "%% Only ipv4 or ipv6 address families are supported\n");
3857 if (safi
!= SAFI_UNICAST
) {
3859 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3863 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3864 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3865 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3869 if (afi
== AFI_IP
) {
3870 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3871 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3872 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3873 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3876 * this is the case for first time ever configuration
3877 * adv ipv4 unicast is enabled for the first time.
3878 * So no need to reset any flag
3880 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3882 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3883 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3884 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3886 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3887 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3888 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3890 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3891 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3894 * This is modify case from gateway-ip
3895 * to no overlay index
3897 adv_flag_changed
= true;
3898 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3899 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3900 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3901 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3902 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3904 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3905 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3908 * This is modify case from no overlay index
3911 adv_flag_changed
= true;
3912 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3913 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3914 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3915 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3919 * Command is issued with the same option
3920 * (no overlay index or gateway-ip) which was
3921 * already configured. So nothing to do.
3922 * However, route-map may have been modified.
3923 * check if route-map has been modified.
3924 * If not, return an error
3930 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3931 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3932 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3933 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3936 * this is the case for first time ever configuration
3937 * adv ipv6 unicast is enabled for the first time.
3938 * So no need to reset any flag
3940 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3942 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3943 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3944 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3946 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3947 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3948 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3950 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3951 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3954 * This is modify case from gateway-ip
3955 * to no overlay index
3957 adv_flag_changed
= true;
3958 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3959 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3960 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3961 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3962 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3964 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3965 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3968 * This is modify case from no overlay index
3971 adv_flag_changed
= true;
3972 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3973 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3974 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3975 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3979 * Command is issued with the same option
3980 * (no overlay index or gateway-ip) which was
3981 * already configured. So nothing to do.
3982 * However, route-map may have been modified.
3983 * check if route-map has been modified.
3984 * If not, return an error
3991 if ((rmap_changed
) || (adv_flag_changed
)) {
3993 /* If either of these are changed, then FRR needs to
3994 * withdraw already advertised type5 routes.
3996 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3998 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3999 XFREE(MTYPE_ROUTE_MAP_NAME
,
4000 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4001 route_map_counter_decrement(
4002 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4003 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4004 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4009 /* set the route-map for advertise command */
4010 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4011 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4012 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4013 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4014 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4015 route_map_counter_increment(
4016 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4019 /* advertise type-5 routes */
4020 if (advertise_type5_routes(bgp_vrf
, afi
))
4021 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4025 DEFUN (no_bgp_evpn_advertise_type5
,
4026 no_bgp_evpn_advertise_type5_cmd
,
4027 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4029 "Advertise prefix routes\n"
4033 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4039 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4040 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4042 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4044 "%% Only ipv4 or ipv6 address families are supported\n");
4048 if (safi
!= SAFI_UNICAST
) {
4050 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4054 if (afi
== AFI_IP
) {
4056 /* if we are not advertising ipv4 prefix as type-5
4059 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4060 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4061 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4062 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4063 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4064 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4065 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4066 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4067 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4071 /* if we are not advertising ipv6 prefix as type-5
4074 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4075 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4076 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4077 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4078 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4079 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4080 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4081 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4086 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4087 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4088 XFREE(MTYPE_ROUTE_MAP_NAME
,
4089 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4090 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4091 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4097 DEFPY (bgp_evpn_use_es_l3nhg
,
4098 bgp_evpn_use_es_l3nhg_cmd
,
4099 "[no$no] use-es-l3nhg",
4101 "use L3 nexthop group for host routes with ES destination\n")
4103 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4107 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4108 bgp_evpn_ead_evi_rx_disable_cmd
,
4109 "[no$no] disable-ead-evi-rx",
4111 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4113 bool ead_evi_rx
= no
? true :false;
4115 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4116 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4117 bgp_evpn_switch_ead_evi_rx();
4122 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4123 bgp_evpn_ead_evi_tx_disable_cmd
,
4124 "[no$no] disable-ead-evi-tx",
4126 "Don't advertise EAD-EVI for local ESs\n")
4128 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4132 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4133 bgp_evpn_enable_resolve_overlay_index_cmd
,
4134 "[no$no] enable-resolve-overlay-index",
4136 "Enable Recursive Resolution of type-5 route overlay index\n")
4138 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4140 if (bgp
!= bgp_get_evpn()) {
4141 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4145 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4149 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4150 bgp_evpn_advertise_pip_ip_mac_cmd
,
4151 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4153 "evpn system primary IP\n"
4156 MAC_STR MAC_STR MAC_STR
)
4158 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4159 struct bgp
*bgp_evpn
= NULL
;
4161 if (EVPN_ENABLED(bgp_vrf
)) {
4163 "This command is supported under L3VNI BGP EVPN VRF\n");
4164 return CMD_WARNING_CONFIG_FAILED
;
4166 bgp_evpn
= bgp_get_evpn();
4169 /* pip is already enabled */
4170 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4173 bgp_vrf
->evpn_info
->advertise_pip
= true;
4174 if (ip
.s_addr
!= INADDR_ANY
) {
4175 /* Already configured with same IP */
4176 if (IPV4_ADDR_SAME(&ip
,
4177 &bgp_vrf
->evpn_info
->pip_ip_static
))
4180 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4181 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4183 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4185 /* default instance router-id assignemt */
4187 bgp_vrf
->evpn_info
->pip_ip
=
4188 bgp_evpn
->router_id
;
4191 if (!is_zero_mac(&mac
->eth_addr
)) {
4192 /* Already configured with same MAC */
4193 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4194 &mac
->eth_addr
, ETH_ALEN
) == 0)
4197 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4198 &mac
->eth_addr
, ETH_ALEN
);
4199 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4200 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4203 /* Copy zebra sys mac */
4204 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4205 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4206 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4211 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4213 /* Disable PIP feature */
4214 bgp_vrf
->evpn_info
->advertise_pip
= false;
4215 /* copy anycast mac */
4216 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4217 &bgp_vrf
->rmac
, ETH_ALEN
);
4219 /* remove MAC-IP option retain PIP knob. */
4220 if ((ip
.s_addr
!= INADDR_ANY
) &&
4221 !IPV4_ADDR_SAME(&ip
,
4222 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4224 "%% BGP EVPN PIP IP does not match\n");
4225 return CMD_WARNING_CONFIG_FAILED
;
4228 if (!is_zero_mac(&mac
->eth_addr
) &&
4229 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4230 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4232 "%% BGP EVPN PIP MAC does not match\n");
4233 return CMD_WARNING_CONFIG_FAILED
;
4235 /* pip_rmac can carry vrr_rmac reset only if it matches
4236 * with static value.
4238 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4239 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4241 /* Copy zebra sys mac */
4243 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4244 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4245 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4248 /* copy anycast mac */
4249 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4250 &bgp_vrf
->rmac
, ETH_ALEN
);
4254 /* reset user configured sys MAC */
4255 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4256 /* reset user configured sys IP */
4257 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4258 /* Assign default PIP IP (bgp instance router-id) */
4260 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4262 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4265 if (is_evpn_enabled()) {
4266 struct listnode
*node
= NULL
;
4267 struct bgpevpn
*vpn
= NULL
;
4270 * At this point if bgp_evpn is NULL and evpn is enabled
4271 * something stupid has gone wrong
4275 update_advertise_vrf_routes(bgp_vrf
);
4277 /* Update (svi) type-2 routes */
4278 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4279 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4281 update_routes_for_vni(bgp_evpn
, vpn
);
4289 * Display VNI information - for all or a specific VNI
4291 DEFUN(show_bgp_l2vpn_evpn_vni
,
4292 show_bgp_l2vpn_evpn_vni_cmd
,
4293 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4302 struct bgp
*bgp_evpn
;
4306 json_object
*json
= NULL
;
4307 uint32_t num_l2vnis
= 0;
4308 uint32_t num_l3vnis
= 0;
4309 uint32_t num_vnis
= 0;
4310 struct listnode
*node
= NULL
;
4311 struct bgp
*bgp_temp
= NULL
;
4313 uj
= use_json(argc
, argv
);
4315 bgp_evpn
= bgp_get_evpn();
4319 if (!argv_find(argv
, argc
, "evpn", &idx
))
4323 json
= json_object_new_object();
4325 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4327 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4329 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4330 if (bgp_temp
->l3vni
)
4333 num_vnis
= num_l2vnis
+ num_l3vnis
;
4335 json_object_string_add(json
, "advertiseGatewayMacip",
4336 bgp_evpn
->advertise_gw_macip
4339 json_object_string_add(json
, "advertiseSviMacIp",
4340 bgp_evpn
->evpn_info
->advertise_svi_macip
4341 ? "Enabled" : "Disabled");
4342 json_object_string_add(json
, "advertiseAllVnis",
4343 is_evpn_enabled() ? "Enabled"
4345 json_object_string_add(
4347 bgp_evpn
->vxlan_flood_ctrl
4348 == VXLAN_FLOOD_HEAD_END_REPL
4349 ? "Head-end replication"
4351 json_object_int_add(json
, "numVnis", num_vnis
);
4352 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4353 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4355 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4356 bgp_evpn
->advertise_gw_macip
? "Enabled"
4358 vty_out(vty
, "Advertise SVI Macip: %s\n",
4359 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4361 vty_out(vty
, "Advertise All VNI flag: %s\n",
4362 is_evpn_enabled() ? "Enabled" : "Disabled");
4363 vty_out(vty
, "BUM flooding: %s\n",
4364 bgp_evpn
->vxlan_flood_ctrl
4365 == VXLAN_FLOOD_HEAD_END_REPL
4366 ? "Head-end replication"
4368 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4369 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4371 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4375 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4378 /* Display specific VNI */
4379 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4380 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4384 vty_json(vty
, json
);
4389 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4390 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4391 "show bgp l2vpn evpn vni remote-ip-hash",
4399 struct bgp
*bgp_evpn
;
4402 bgp_evpn
= bgp_get_evpn();
4406 if (!argv_find(argv
, argc
, "evpn", &idx
))
4409 hash_iterate(bgp_evpn
->vnihash
,
4410 (void (*)(struct hash_bucket
*,
4411 void *))bgp_evpn_show_remote_ip_hash
,
4417 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4418 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4419 "show bgp l2vpn evpn vni-svi-hash",
4424 "Show vni-svi-hash\n")
4426 struct bgp
*bgp_evpn
;
4429 bgp_evpn
= bgp_get_evpn();
4433 if (!argv_find(argv
, argc
, "evpn", &idx
))
4436 hash_iterate(bgp_evpn
->vni_svi_hash
,
4437 (void (*)(struct hash_bucket
*,
4438 void *))bgp_evpn_show_vni_svi_hash
,
4444 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4445 show_bgp_l2vpn_evpn_es_evi_cmd
,
4446 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4452 "VxLAN Network Identifier\n"
4455 "Detailed information\n")
4458 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4460 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4465 DEFPY(show_bgp_l2vpn_evpn_es
,
4466 show_bgp_l2vpn_evpn_es_cmd
,
4467 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4472 "Ethernet Segment\n"
4474 "Detailed information\n"
4480 if (!str_to_esi(esi_str
, &esi
)) {
4481 vty_out(vty
, "%% Malformed ESI\n");
4484 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4487 bgp_evpn_es_show(vty
, uj
, !!detail
);
4493 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4494 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4495 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4496 "Ethernet Segment\n"
4502 if (!str_to_esi(esi_str
, &esi
)) {
4503 vty_out(vty
, "%% Malformed ESI\n");
4506 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4509 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4515 DEFPY(show_bgp_l2vpn_evpn_nh
,
4516 show_bgp_l2vpn_evpn_nh_cmd
,
4517 "show bgp l2vpn evpn next-hops [json$uj]",
4525 bgp_evpn_nh_show(vty
, uj
);
4531 * Display EVPN neighbor summary.
4533 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4534 "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]",
4537 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4538 "Summary of BGP neighbor status\n"
4539 "Show only sessions in Established state\n"
4540 "Show only sessions not in Established state\n"
4541 "Show only the specified neighbor session\n"
4542 "Neighbor to display information about\n"
4543 "Neighbor to display information about\n"
4544 "Neighbor on BGP configured interface\n"
4545 "Show only the specified remote AS sessions\n"
4547 "Internal (iBGP) AS sessions\n"
4548 "External (eBGP) AS sessions\n"
4549 "Shorten the information on BGP instances\n"
4550 "Increase table width for longer output\n" JSON_STR
)
4555 char *neighbor
= NULL
;
4556 as_t as
= 0; /* 0 means AS filter not set */
4557 int as_type
= AS_UNSPECIFIED
;
4558 uint16_t show_flags
= 0;
4560 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4561 vrf
= argv
[++idx_vrf
]->arg
;
4563 if (argv_find(argv
, argc
, "failed", &idx
))
4564 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4566 if (argv_find(argv
, argc
, "established", &idx
))
4567 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4570 if (argv_find(argv
, argc
, "neighbor", &idx
))
4571 neighbor
= argv
[idx
+ 1]->arg
;
4573 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4574 if (argv
[idx
+ 1]->arg
[0] == 'i')
4575 as_type
= AS_INTERNAL
;
4576 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4577 as_type
= AS_EXTERNAL
;
4579 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4582 if (argv_find(argv
, argc
, "terse", &idx
))
4583 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4585 if (argv_find(argv
, argc
, "wide", &idx
))
4586 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4588 if (use_json(argc
, argv
))
4589 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4591 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4592 as_type
, as
, show_flags
);
4595 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4599 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4600 /* Specific type is requested */
4601 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4602 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4603 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4604 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4605 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4606 *type
= BGP_EVPN_IMET_ROUTE
;
4607 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4608 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4609 *type
= BGP_EVPN_ES_ROUTE
;
4610 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4611 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4612 *type
= BGP_EVPN_AD_ROUTE
;
4613 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4614 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4615 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4624 * Display global EVPN routing table.
4626 DEFUN(show_bgp_l2vpn_evpn_route
,
4627 show_bgp_l2vpn_evpn_route_cmd
,
4628 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4634 "Display Detailed Information\n"
4636 EVPN_TYPE_ALL_LIST_HELP_STR
4643 json_object
*json
= NULL
;
4645 uj
= use_json(argc
, argv
);
4647 bgp
= bgp_get_evpn();
4652 json
= json_object_new_object();
4654 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4657 if (argv_find(argv
, argc
, "detail", &detail
))
4660 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4663 vty_json(vty
, json
);
4668 * Display global EVPN routing table for specific RD.
4670 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4671 show_bgp_l2vpn_evpn_route_rd_cmd
,
4672 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4678 EVPN_RT_DIST_HELP_STR
4679 EVPN_ASN_IP_HELP_STR
4680 "All VPN Route Distinguishers\n"
4682 EVPN_TYPE_ALL_LIST_HELP_STR
4687 struct prefix_rd prd
;
4690 json_object
*json
= NULL
;
4691 int idx_ext_community
= 0;
4694 bgp
= bgp_get_evpn();
4698 /* check if we need json output */
4699 uj
= use_json(argc
, argv
);
4701 json
= json_object_new_object();
4703 if (argv_find(argv
, argc
, "all", &rd_all
)) {
4705 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4706 &idx_ext_community
)) {
4707 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4710 "%% Malformed Route Distinguisher\n");
4716 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4720 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4722 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4725 vty_json(vty
, json
);
4731 * Display global EVPN routing table for specific RD and MACIP.
4733 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4734 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4735 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4741 EVPN_RT_DIST_HELP_STR
4742 EVPN_ASN_IP_HELP_STR
4743 "All VPN Route Distinguishers\n"
4745 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4747 "IP address (IPv4 or IPv6)\n"
4752 struct prefix_rd prd
;
4755 int idx_ext_community
= 0;
4759 json_object
*json
= NULL
;
4762 memset(&mac
, 0, sizeof(struct ethaddr
));
4763 memset(&ip
, 0, sizeof(struct ipaddr
));
4765 bgp
= bgp_get_evpn();
4769 /* check if we need json output */
4770 uj
= use_json(argc
, argv
);
4772 json
= json_object_new_object();
4775 if (argv_find(argv
, argc
, "all", &rd_all
)) {
4776 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4777 &idx_ext_community
)) {
4778 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4781 "%% Malformed Route Distinguisher\n");
4788 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4789 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4790 vty_out(vty
, "%% Malformed MAC address\n");
4795 /* get the ip if specified */
4796 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4797 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4798 vty_out(vty
, "%% Malformed IP address\n");
4804 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4806 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4809 vty_json(vty
, json
);
4814 /* Display per ESI routing table */
4815 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4816 show_bgp_l2vpn_evpn_route_esi_cmd
,
4817 "show bgp l2vpn evpn route esi ESI [json]",
4823 "Ethernet Segment Identifier\n"
4829 struct bgp
*bgp
= NULL
;
4830 json_object
*json
= NULL
;
4832 memset(&esi
, 0, sizeof(esi
));
4833 bgp
= bgp_get_evpn();
4837 uj
= use_json(argc
, argv
);
4839 json
= json_object_new_object();
4841 /* get the ESI - ESI-ID is at argv[6] */
4842 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4843 vty_out(vty
, "%% Malformed ESI\n");
4847 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4850 vty_json(vty
, json
);
4857 * Display per-VNI EVPN routing table.
4859 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4860 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4866 "VXLAN Network Identifier\n"
4869 EVPN_TYPE_1_HELP_STR
4870 EVPN_TYPE_1_HELP_STR
4871 EVPN_TYPE_2_HELP_STR
4872 EVPN_TYPE_2_HELP_STR
4873 EVPN_TYPE_3_HELP_STR
4874 EVPN_TYPE_3_HELP_STR
4876 "Remote VTEP IP address\n"
4881 struct in_addr vtep_ip
;
4886 json_object
*json
= NULL
;
4888 bgp
= bgp_get_evpn();
4892 /* check if we need json output */
4893 uj
= use_json(argc
, argv
);
4895 json
= json_object_new_object();
4897 if (!argv_find(argv
, argc
, "evpn", &idx
))
4902 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4904 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4907 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4908 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4909 vty_out(vty
, "%% Malformed VTEP IP address\n");
4914 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4917 vty_json(vty
, json
);
4923 * Display per-VNI EVPN routing table for specific MACIP.
4925 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4926 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4927 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4933 "VXLAN Network Identifier\n"
4936 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4938 "IP address (IPv4 or IPv6)\n"
4947 json_object
*json
= NULL
;
4949 bgp
= bgp_get_evpn();
4953 /* check if we need json output */
4954 uj
= use_json(argc
, argv
);
4956 json
= json_object_new_object();
4958 if (!argv_find(argv
, argc
, "evpn", &idx
))
4962 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4965 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4966 vty_out(vty
, "%% Malformed MAC address\n");
4971 memset(&ip
, 0, sizeof(ip
));
4972 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4974 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4975 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4976 vty_out(vty
, "%% Malformed IP address\n");
4981 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4984 vty_json(vty
, json
);
4990 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4992 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4993 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4994 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5000 "VXLAN Network Identifier\n"
5002 EVPN_TYPE_3_HELP_STR
5003 "Originating Router IP address\n"
5009 struct in_addr orig_ip
;
5012 json_object
*json
= NULL
;
5014 bgp
= bgp_get_evpn();
5018 /* check if we need json output */
5019 uj
= use_json(argc
, argv
);
5021 json
= json_object_new_object();
5023 if (!argv_find(argv
, argc
, "evpn", &idx
))
5027 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5030 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5032 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5036 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5039 vty_json(vty
, json
);
5045 * Display per-VNI EVPN routing table - for all VNIs.
5047 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5048 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5049 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5055 "VXLAN Network Identifier\n"
5057 "Print Detailed Output\n"
5059 "Remote VTEP IP address\n"
5063 struct in_addr vtep_ip
;
5066 json_object
*json
= NULL
;
5067 /* Detail Adjust. Adjust indexes according to detail option */
5070 bgp
= bgp_get_evpn();
5074 /* check if we need json output */
5075 uj
= use_json(argc
, argv
);
5077 json
= json_object_new_object();
5079 if (!argv_find(argv
, argc
, "evpn", &idx
))
5082 if (argv_find(argv
, argc
, "detail", &da
))
5085 /* vtep-ip position depends on detail option */
5087 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5089 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5090 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5091 vty_out(vty
, "%% Malformed VTEP IP address\n");
5096 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5099 vty_json(vty
, json
);
5105 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5106 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5107 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5108 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5109 "EVPN route information\n"
5110 "MAC IP routes in the EVI tables linked to the ES\n"
5112 "Detailed information\n" JSON_STR
)
5116 json_object
*json
= NULL
;
5119 if (!str_to_esi(esi_str
, &esi
)) {
5120 vty_out(vty
, "%% Malformed ESI\n");
5129 json
= json_object_new_object();
5130 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5132 vty_json(vty
, json
);
5138 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5139 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5140 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5141 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5142 "EVPN route information\n"
5143 "MAC IP routes in the global table linked to the ES\n"
5145 "Detailed information\n" JSON_STR
)
5149 json_object
*json
= NULL
;
5152 if (!str_to_esi(esi_str
, &esi
)) {
5153 vty_out(vty
, "%% Malformed ESI\n");
5162 json
= json_object_new_object();
5163 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5165 vty_json(vty
, json
);
5171 * Display EVPN import route-target hash table
5173 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5174 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5175 "show bgp l2vpn evpn vrf-import-rt [json]",
5180 "Show vrf import route target\n"
5184 struct bgp
*bgp_evpn
= NULL
;
5185 json_object
*json
= NULL
;
5187 bgp_evpn
= bgp_get_evpn();
5191 uj
= use_json(argc
, argv
);
5193 json
= json_object_new_object();
5195 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5198 vty_json(vty
, json
);
5204 * Display EVPN import route-target hash table
5206 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5207 show_bgp_l2vpn_evpn_import_rt_cmd
,
5208 "show bgp l2vpn evpn import-rt [json]",
5213 "Show import route target\n"
5218 json_object
*json
= NULL
;
5220 bgp
= bgp_get_evpn();
5224 uj
= use_json(argc
, argv
);
5226 json
= json_object_new_object();
5228 evpn_show_import_rts(vty
, bgp
, json
);
5231 vty_json(vty
, json
);
5236 DEFPY_HIDDEN(test_es_add
,
5238 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5241 "Ethernet-segment\n"
5242 "Ethernet-Segment Identifier\n"
5250 struct in_addr vtep_ip
;
5253 bgp
= bgp_get_evpn();
5255 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5259 if (!str_to_esi(esi_str
, &esi
)) {
5260 vty_out(vty
, "%% Malformed ESI\n");
5265 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5267 vty_out(vty
, "%% Failed to delete ES\n");
5271 if (state_str
&& !strcmp(state_str
, "up"))
5275 vtep_ip
= bgp
->router_id
;
5277 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5278 EVPN_MH_DF_PREF_MIN
, false);
5280 vty_out(vty
, "%% Failed to add ES\n");
5287 DEFPY_HIDDEN(test_es_vni_add
,
5288 test_es_vni_add_cmd
,
5289 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5292 "Ethernet-segment\n"
5293 "Ethernet-Segment Identifier\n"
5302 bgp
= bgp_get_evpn();
5304 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5308 if (!str_to_esi(esi_str
, &esi
)) {
5309 vty_out(vty
, "%% Malformed ESI\n");
5314 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5316 vty_out(vty
, "%% Failed to deref ES VNI\n");
5320 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5322 vty_out(vty
, "%% Failed to ref ES VNI\n");
5329 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5330 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5334 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5335 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5336 "Summary of BGP neighbor status\n" JSON_STR
)
5338 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5339 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5340 SHOW_STR BGP_STR EVPN_HELP_STR
5342 "Display Detailed Information\n"
5344 EVPN_TYPE_2_HELP_STR
5345 EVPN_TYPE_2_HELP_STR
5346 EVPN_TYPE_3_HELP_STR
5347 EVPN_TYPE_3_HELP_STR
)
5350 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5351 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5352 SHOW_STR BGP_STR EVPN_HELP_STR
5354 EVPN_RT_DIST_HELP_STR
5355 EVPN_ASN_IP_HELP_STR
5357 EVPN_TYPE_2_HELP_STR
5358 EVPN_TYPE_2_HELP_STR
5359 EVPN_TYPE_3_HELP_STR
5360 EVPN_TYPE_3_HELP_STR
)
5363 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5364 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5365 SHOW_STR BGP_STR EVPN_HELP_STR
5367 EVPN_RT_DIST_HELP_STR
5368 EVPN_ASN_IP_HELP_STR
5370 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5372 "IP address (IPv4 or IPv6)\n")
5375 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5376 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5377 SHOW_STR BGP_STR EVPN_HELP_STR
5379 "VXLAN Network Identifier\n"
5382 EVPN_TYPE_2_HELP_STR
5383 EVPN_TYPE_2_HELP_STR
5384 EVPN_TYPE_3_HELP_STR
5385 EVPN_TYPE_3_HELP_STR
5387 "Remote VTEP IP address\n")
5389 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5390 show_bgp_evpn_route_vni_macip_cmd
,
5391 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5392 SHOW_STR BGP_STR EVPN_HELP_STR
5394 "VXLAN Network Identifier\n"
5397 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5399 "IP address (IPv4 or IPv6)\n")
5401 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5402 show_bgp_evpn_route_vni_multicast_cmd
,
5403 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5404 SHOW_STR BGP_STR EVPN_HELP_STR
5406 "VXLAN Network Identifier\n"
5408 EVPN_TYPE_3_HELP_STR
5409 "Originating Router IP address\n")
5411 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5412 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5413 SHOW_STR BGP_STR EVPN_HELP_STR
5415 "VXLAN Network Identifier\n"
5417 "Print Detailed Output\n"
5419 "Remote VTEP IP address\n")
5421 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5422 "show bgp evpn import-rt",
5423 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5425 DEFUN_NOSH (bgp_evpn_vni
,
5427 "vni " CMD_VNI_RANGE
,
5428 "VXLAN Network Identifier\n"
5432 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5433 struct bgpevpn
*vpn
;
5438 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5440 /* Create VNI, or mark as configured. */
5441 vpn
= evpn_create_update_vni(bgp
, vni
);
5443 vty_out(vty
, "%% Failed to create VNI \n");
5447 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5451 DEFUN (no_bgp_evpn_vni
,
5452 no_bgp_evpn_vni_cmd
,
5453 "no vni " CMD_VNI_RANGE
,
5455 "VXLAN Network Identifier\n"
5459 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5460 struct bgpevpn
*vpn
;
5465 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5467 /* Check if we should disallow. */
5468 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5470 vty_out(vty
, "%% Specified VNI does not exist\n");
5473 if (!is_vni_configured(vpn
)) {
5474 vty_out(vty
, "%% Specified VNI is not configured\n");
5478 evpn_delete_vni(bgp
, vpn
);
5482 DEFUN_NOSH (exit_vni
,
5485 "Exit from VNI mode\n")
5487 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5488 vty
->node
= BGP_EVPN_NODE
;
5492 DEFUN (bgp_evpn_vrf_rd
,
5493 bgp_evpn_vrf_rd_cmd
,
5494 "rd ASN:NN_OR_IP-ADDRESS:NN",
5495 EVPN_RT_DIST_HELP_STR
5496 EVPN_ASN_IP_HELP_STR
)
5499 struct prefix_rd prd
;
5500 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5505 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5507 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5511 /* If same as existing value, there is nothing more to do. */
5512 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5515 /* Configure or update the RD. */
5516 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5520 DEFUN (no_bgp_evpn_vrf_rd
,
5521 no_bgp_evpn_vrf_rd_cmd
,
5522 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5524 EVPN_RT_DIST_HELP_STR
5525 EVPN_ASN_IP_HELP_STR
)
5528 struct prefix_rd prd
;
5529 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5534 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5536 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5540 /* Check if we should disallow. */
5541 if (!is_vrf_rd_configured(bgp_vrf
)) {
5542 vty_out(vty
, "%% RD is not configured for this VRF\n");
5546 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5548 "%% RD specified does not match configuration for this VRF\n");
5552 evpn_unconfigure_vrf_rd(bgp_vrf
);
5556 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5557 no_bgp_evpn_vrf_rd_without_val_cmd
,
5560 EVPN_RT_DIST_HELP_STR
)
5562 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5567 /* Check if we should disallow. */
5568 if (!is_vrf_rd_configured(bgp_vrf
)) {
5569 vty_out(vty
, "%% RD is not configured for this VRF\n");
5573 evpn_unconfigure_vrf_rd(bgp_vrf
);
5577 DEFUN (bgp_evpn_vni_rd
,
5578 bgp_evpn_vni_rd_cmd
,
5579 "rd ASN:NN_OR_IP-ADDRESS:NN",
5580 EVPN_RT_DIST_HELP_STR
5581 EVPN_ASN_IP_HELP_STR
)
5583 struct prefix_rd prd
;
5584 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5585 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5591 if (!EVPN_ENABLED(bgp
)) {
5593 "This command is only supported under EVPN VRF\n");
5597 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5599 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5603 /* If same as existing value, there is nothing more to do. */
5604 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5607 /* Configure or update the RD. */
5608 evpn_configure_rd(bgp
, vpn
, &prd
);
5612 DEFUN (no_bgp_evpn_vni_rd
,
5613 no_bgp_evpn_vni_rd_cmd
,
5614 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5616 EVPN_RT_DIST_HELP_STR
5617 EVPN_ASN_IP_HELP_STR
)
5619 struct prefix_rd prd
;
5620 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5621 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5627 if (!EVPN_ENABLED(bgp
)) {
5629 "This command is only supported under EVPN VRF\n");
5633 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5635 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5639 /* Check if we should disallow. */
5640 if (!is_rd_configured(vpn
)) {
5641 vty_out(vty
, "%% RD is not configured for this VNI\n");
5645 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5647 "%% RD specified does not match configuration for this VNI\n");
5651 evpn_unconfigure_rd(bgp
, vpn
);
5655 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5656 no_bgp_evpn_vni_rd_without_val_cmd
,
5659 EVPN_RT_DIST_HELP_STR
)
5661 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5662 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5667 if (!EVPN_ENABLED(bgp
)) {
5669 "This command is only supported under EVPN VRF\n");
5673 /* Check if we should disallow. */
5674 if (!is_rd_configured(vpn
)) {
5675 vty_out(vty
, "%% RD is not configured for this VNI\n");
5679 evpn_unconfigure_rd(bgp
, vpn
);
5684 * Loop over all extended-communities in the route-target list rtl and
5685 * return 1 if we find ecomtarget
5687 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5688 struct ecommunity
*ecomtarget
)
5690 struct listnode
*node
, *nnode
;
5691 struct ecommunity
*ecom
;
5693 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5694 if (ecommunity_match(ecom
, ecomtarget
))
5701 /* display L3VNI related info for a VRF instance */
5702 DEFUN (show_bgp_vrf_l3vni_info
,
5703 show_bgp_vrf_l3vni_info_cmd
,
5704 "show bgp vrf VRFNAME vni [json]",
5712 char buf
[ETHER_ADDR_STRLEN
];
5713 char buf1
[INET6_ADDRSTRLEN
];
5715 const char *name
= NULL
;
5716 struct bgp
*bgp
= NULL
;
5717 struct listnode
*node
= NULL
;
5718 struct bgpevpn
*vpn
= NULL
;
5719 struct ecommunity
*ecom
= NULL
;
5720 json_object
*json
= NULL
;
5721 json_object
*json_vnis
= NULL
;
5722 json_object
*json_export_rts
= NULL
;
5723 json_object
*json_import_rts
= NULL
;
5724 bool uj
= use_json(argc
, argv
);
5727 json
= json_object_new_object();
5728 json_vnis
= json_object_new_array();
5729 json_export_rts
= json_object_new_array();
5730 json_import_rts
= json_object_new_array();
5733 name
= argv
[idx_vrf
]->arg
;
5734 bgp
= bgp_lookup_by_name(name
);
5735 if (strmatch(name
, VRF_DEFAULT_NAME
))
5736 bgp
= bgp_get_default();
5740 vty_out(vty
, "BGP instance for VRF %s not found\n",
5743 json_object_string_add(json
, "warning",
5744 "BGP instance not found");
5745 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5746 json_object_free(json
);
5752 vty_out(vty
, "BGP VRF: %s\n", name
);
5753 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5754 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5755 vty_out(vty
, " Rmac: %s\n",
5756 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5757 vty_out(vty
, " VNI Filter: %s\n",
5758 CHECK_FLAG(bgp
->vrf_flags
,
5759 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5760 ? "prefix-routes-only"
5762 vty_out(vty
, " L2-VNI List:\n");
5764 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5765 vty_out(vty
, "%u ", vpn
->vni
);
5767 vty_out(vty
, " Export-RTs:\n");
5769 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5770 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5772 vty_out(vty
, " Import-RTs:\n");
5774 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5775 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5777 vty_out(vty
, " RD: %s\n",
5778 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5780 json_object_string_add(json
, "vrf", name
);
5781 json_object_string_addf(json
, "local-ip", "%pI4",
5782 &bgp
->originator_ip
);
5783 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5784 json_object_string_add(
5786 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5787 json_object_string_add(
5789 CHECK_FLAG(bgp
->vrf_flags
,
5790 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5791 ? "prefix-routes-only"
5793 /* list of l2vnis */
5794 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5795 json_object_array_add(json_vnis
,
5796 json_object_new_int(vpn
->vni
));
5797 json_object_object_add(json
, "l2vnis", json_vnis
);
5800 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5801 json_object_array_add(
5803 json_object_new_string(ecommunity_str(ecom
)));
5804 json_object_object_add(json
, "export-rts", json_export_rts
);
5807 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5808 json_object_array_add(
5810 json_object_new_string(ecommunity_str(ecom
)));
5811 json_object_object_add(json
, "import-rts", json_import_rts
);
5812 json_object_string_add(
5814 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5818 vty_json(vty
, json
);
5822 /* import/export rt for l3vni-vrf */
5823 DEFUN (bgp_evpn_vrf_rt
,
5824 bgp_evpn_vrf_rt_cmd
,
5825 "route-target <both|import|export> RT",
5827 "import and export\n"
5830 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5833 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5834 struct ecommunity
*ecomadd
= NULL
;
5839 if (!strcmp(argv
[1]->arg
, "import"))
5840 rt_type
= RT_TYPE_IMPORT
;
5841 else if (!strcmp(argv
[1]->arg
, "export"))
5842 rt_type
= RT_TYPE_EXPORT
;
5843 else if (!strcmp(argv
[1]->arg
, "both"))
5844 rt_type
= RT_TYPE_BOTH
;
5846 vty_out(vty
, "%% Invalid Route Target type\n");
5850 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5852 vty_out(vty
, "%% Malformed Route Target list\n");
5855 ecommunity_str(ecomadd
);
5857 /* Add/update the import route-target */
5858 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5859 /* Do nothing if we already have this import route-target */
5860 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5861 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5864 /* Add/update the export route-target */
5865 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5866 /* Do nothing if we already have this export route-target */
5867 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5868 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5874 DEFUN (no_bgp_evpn_vrf_rt
,
5875 no_bgp_evpn_vrf_rt_cmd
,
5876 "no route-target <both|import|export> RT",
5879 "import and export\n"
5882 EVPN_ASN_IP_HELP_STR
)
5884 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5885 int rt_type
, found_ecomdel
;
5886 struct ecommunity
*ecomdel
= NULL
;
5891 if (!strcmp(argv
[2]->arg
, "import"))
5892 rt_type
= RT_TYPE_IMPORT
;
5893 else if (!strcmp(argv
[2]->arg
, "export"))
5894 rt_type
= RT_TYPE_EXPORT
;
5895 else if (!strcmp(argv
[2]->arg
, "both"))
5896 rt_type
= RT_TYPE_BOTH
;
5898 vty_out(vty
, "%% Invalid Route Target type\n");
5902 if (rt_type
== RT_TYPE_IMPORT
) {
5903 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5905 "%% Import RT is not configured for this VRF\n");
5908 } else if (rt_type
== RT_TYPE_EXPORT
) {
5909 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5911 "%% Export RT is not configured for this VRF\n");
5914 } else if (rt_type
== RT_TYPE_BOTH
) {
5915 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5916 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5918 "%% Import/Export RT is not configured for this VRF\n");
5923 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5925 vty_out(vty
, "%% Malformed Route Target list\n");
5928 ecommunity_str(ecomdel
);
5930 if (rt_type
== RT_TYPE_IMPORT
) {
5931 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5933 ecommunity_free(&ecomdel
);
5935 "%% RT specified does not match configuration for this VRF\n");
5938 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5939 } else if (rt_type
== RT_TYPE_EXPORT
) {
5940 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5942 ecommunity_free(&ecomdel
);
5944 "%% RT specified does not match configuration for this VRF\n");
5947 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5948 } else if (rt_type
== RT_TYPE_BOTH
) {
5951 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5953 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5957 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5959 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5963 if (!found_ecomdel
) {
5964 ecommunity_free(&ecomdel
);
5966 "%% RT specified does not match configuration for this VRF\n");
5971 ecommunity_free(&ecomdel
);
5975 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
5976 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
5978 "EAD ES fragment config\n"
5979 "EVIs per-fragment\n"
5982 bgp_mh_info
->evi_per_es_frag
=
5983 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
5988 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
5989 "ead-es-route-target export RT",
5990 "EAD ES Route Target\n"
5992 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5994 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5995 struct ecommunity
*ecomadd
= NULL
;
6000 if (!EVPN_ENABLED(bgp
)) {
6001 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6005 /* Add/update the export route-target */
6006 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6008 vty_out(vty
, "%% Malformed Route Target list\n");
6011 ecommunity_str(ecomadd
);
6013 /* Do nothing if we already have this export route-target */
6014 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6016 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6021 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6022 "no ead-es-route-target export RT",
6024 "EAD ES Route Target\n"
6025 "export\n" EVPN_ASN_IP_HELP_STR
)
6027 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6028 struct ecommunity
*ecomdel
= NULL
;
6033 if (!EVPN_ENABLED(bgp
)) {
6034 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6038 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6040 vty_out(vty
, "%% Malformed Route Target list\n");
6043 ecommunity_str(ecomdel
);
6045 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6048 "%% RT specified does not match EAD-ES RT configuration\n");
6051 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
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 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6092 vty_out(vty
, "%% Malformed Route Target list\n");
6095 ecommunity_str(ecomadd
);
6097 /* Add/update the import route-target */
6098 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6099 /* Do nothing if we already have this import route-target */
6100 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6101 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6104 /* Add/update the export route-target */
6105 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6106 /* Do nothing if we already have this export route-target */
6107 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6108 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6114 DEFUN (no_bgp_evpn_vni_rt
,
6115 no_bgp_evpn_vni_rt_cmd
,
6116 "no route-target <both|import|export> RT",
6119 "import and export\n"
6122 EVPN_ASN_IP_HELP_STR
)
6124 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6125 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6126 int rt_type
, found_ecomdel
;
6127 struct ecommunity
*ecomdel
= NULL
;
6132 if (!EVPN_ENABLED(bgp
)) {
6134 "This command is only supported under EVPN VRF\n");
6138 if (!strcmp(argv
[2]->text
, "import"))
6139 rt_type
= RT_TYPE_IMPORT
;
6140 else if (!strcmp(argv
[2]->text
, "export"))
6141 rt_type
= RT_TYPE_EXPORT
;
6142 else if (!strcmp(argv
[2]->text
, "both"))
6143 rt_type
= RT_TYPE_BOTH
;
6145 vty_out(vty
, "%% Invalid Route Target type\n");
6149 /* The user did "no route-target import", check to see if there are any
6150 * import route-targets configured. */
6151 if (rt_type
== RT_TYPE_IMPORT
) {
6152 if (!is_import_rt_configured(vpn
)) {
6154 "%% Import RT is not configured for this VNI\n");
6157 } else if (rt_type
== RT_TYPE_EXPORT
) {
6158 if (!is_export_rt_configured(vpn
)) {
6160 "%% Export RT is not configured for this VNI\n");
6163 } else if (rt_type
== RT_TYPE_BOTH
) {
6164 if (!is_import_rt_configured(vpn
)
6165 && !is_export_rt_configured(vpn
)) {
6167 "%% Import/Export RT is not configured for this VNI\n");
6172 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6174 vty_out(vty
, "%% Malformed Route Target list\n");
6177 ecommunity_str(ecomdel
);
6179 if (rt_type
== RT_TYPE_IMPORT
) {
6180 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6182 "%% RT specified does not match configuration for this VNI\n");
6185 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6186 } else if (rt_type
== RT_TYPE_EXPORT
) {
6187 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6189 "%% RT specified does not match configuration for this VNI\n");
6192 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6193 } else if (rt_type
== RT_TYPE_BOTH
) {
6196 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6197 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6201 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6202 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6206 if (!found_ecomdel
) {
6208 "%% RT specified does not match configuration for this VNI\n");
6216 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6217 no_bgp_evpn_vni_rt_without_val_cmd
,
6218 "no route-target <import|export>",
6224 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6225 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6231 if (!EVPN_ENABLED(bgp
)) {
6233 "This command is only supported under EVPN VRF\n");
6237 if (!strcmp(argv
[2]->text
, "import")) {
6238 rt_type
= RT_TYPE_IMPORT
;
6239 } else if (!strcmp(argv
[2]->text
, "export")) {
6240 rt_type
= RT_TYPE_EXPORT
;
6242 vty_out(vty
, "%% Invalid Route Target type\n");
6246 /* Check if we should disallow. */
6247 if (rt_type
== RT_TYPE_IMPORT
) {
6248 if (!is_import_rt_configured(vpn
)) {
6250 "%% Import RT is not configured for this VNI\n");
6254 if (!is_export_rt_configured(vpn
)) {
6256 "%% Export RT is not configured for this VNI\n");
6261 /* Unconfigure the RT. */
6262 if (rt_type
== RT_TYPE_IMPORT
)
6263 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6265 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6269 static int vni_cmp(const void **a
, const void **b
)
6271 const struct bgpevpn
*first
= *a
;
6272 const struct bgpevpn
*secnd
= *b
;
6274 return secnd
->vni
- first
->vni
;
6278 * Output EVPN configuration information.
6280 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6283 char buf1
[RD_ADDRSTRLEN
];
6284 char buf2
[INET6_ADDRSTRLEN
];
6286 if (bgp
->advertise_all_vni
)
6287 vty_out(vty
, " advertise-all-vni\n");
6289 if (hashcount(bgp
->vnihash
)) {
6290 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6291 struct listnode
*ln
;
6292 struct bgpevpn
*data
;
6294 list_sort(vnilist
, vni_cmp
);
6295 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6296 write_vni_config(vty
, data
);
6298 list_delete(&vnilist
);
6301 if (bgp
->advertise_autort_rfc8365
)
6302 vty_out(vty
, " autort rfc8365-compatible\n");
6304 if (bgp
->advertise_gw_macip
)
6305 vty_out(vty
, " advertise-default-gw\n");
6307 if (bgp
->evpn_info
->advertise_svi_macip
)
6308 vty_out(vty
, " advertise-svi-ip\n");
6310 if (bgp
->resolve_overlay_index
)
6311 vty_out(vty
, " enable-resolve-overlay-index\n");
6313 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
6314 vty_out(vty
, " ead-es-frag evi-limit %u\n",
6315 bgp_mh_info
->evi_per_es_frag
);
6317 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6318 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6319 if (bgp_mh_info
->host_routes_use_l3nhg
)
6320 vty_out(vty
, " use-es-l3nhg\n");
6322 vty_out(vty
, " no use-es-l3nhg\n");
6325 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6326 if (bgp_mh_info
->ead_evi_rx
)
6327 vty_out(vty
, " no disable-ead-evi-rx\n");
6329 vty_out(vty
, " disable-ead-evi-rx\n");
6332 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6333 if (bgp_mh_info
->ead_evi_tx
)
6334 vty_out(vty
, " no disable-ead-evi-tx\n");
6336 vty_out(vty
, " disable-ead-evi-tx\n");
6339 if (!bgp
->evpn_info
->dup_addr_detect
)
6340 vty_out(vty
, " no dup-addr-detection\n");
6342 if (bgp
->evpn_info
->dad_max_moves
!=
6343 EVPN_DAD_DEFAULT_MAX_MOVES
||
6344 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6345 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6346 bgp
->evpn_info
->dad_max_moves
,
6347 bgp
->evpn_info
->dad_time
);
6349 if (bgp
->evpn_info
->dad_freeze
) {
6350 if (bgp
->evpn_info
->dad_freeze_time
)
6352 " dup-addr-detection freeze %u\n",
6353 bgp
->evpn_info
->dad_freeze_time
);
6356 " dup-addr-detection freeze permanent\n");
6359 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6360 vty_out(vty
, " flooding disable\n");
6362 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6363 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6364 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6365 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6366 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6369 " advertise ipv4 unicast\n");
6370 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6371 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6372 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6374 " advertise ipv4 unicast gateway-ip route-map %s\n",
6375 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6377 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6380 /* EAD ES export route-target */
6381 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
6382 struct ecommunity
*ecom
;
6384 struct listnode
*node
;
6386 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
6389 ecom_str
= ecommunity_ecom2str(
6390 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6391 vty_out(vty
, " ead-es-route-target export %s\n",
6393 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6397 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6398 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6399 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6401 " advertise ipv6 unicast route-map %s\n",
6402 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6405 " advertise ipv6 unicast\n");
6406 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6407 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6408 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6410 " advertise ipv6 unicast gateway-ip route-map %s\n",
6411 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6413 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6416 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6417 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6418 vty_out(vty
, " default-originate ipv4\n");
6420 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6421 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6422 vty_out(vty
, " default-originate ipv6\n");
6424 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6425 if (!bgp
->evpn_info
->advertise_pip
)
6426 vty_out(vty
, " no advertise-pip\n");
6427 if (bgp
->evpn_info
->advertise_pip
) {
6428 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6430 vty_out(vty
, " advertise-pip ip %s",
6432 &bgp
->evpn_info
->pip_ip_static
,
6433 buf2
, INET_ADDRSTRLEN
));
6435 bgp
->evpn_info
->pip_rmac_static
))) {
6436 char buf
[ETHER_ADDR_STRLEN
];
6438 vty_out(vty
, " mac %s",
6448 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6449 vty_out(vty
, " rd %s\n",
6450 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6452 /* import route-target */
6453 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6455 struct listnode
*node
, *nnode
;
6456 struct ecommunity
*ecom
;
6458 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6460 ecom_str
= ecommunity_ecom2str(
6461 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6462 vty_out(vty
, " route-target import %s\n", ecom_str
);
6463 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6467 /* export route-target */
6468 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6470 struct listnode
*node
, *nnode
;
6471 struct ecommunity
*ecom
;
6473 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6475 ecom_str
= ecommunity_ecom2str(
6476 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6477 vty_out(vty
, " route-target export %s\n", ecom_str
);
6478 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6483 void bgp_ethernetvpn_init(void)
6485 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6486 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6487 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6488 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6489 install_element(VIEW_NODE
,
6490 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6491 install_element(VIEW_NODE
,
6492 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6495 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6498 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6499 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6500 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6501 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6502 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6503 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6504 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6505 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6506 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6507 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6508 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6509 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6510 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6511 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6512 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6513 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6514 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6515 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6516 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6517 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6518 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6519 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6520 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6521 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6522 install_element(BGP_EVPN_NODE
,
6523 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6526 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6527 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6529 /* "show bgp l2vpn evpn" commands. */
6530 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6531 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6532 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6533 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6534 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6535 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6536 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6537 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6538 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6539 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6540 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6541 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6542 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6543 install_element(VIEW_NODE
,
6544 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6545 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6546 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6547 install_element(VIEW_NODE
,
6548 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6549 install_element(VIEW_NODE
,
6550 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6551 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6552 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6554 /* "show bgp evpn" commands. */
6555 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6556 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6557 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6558 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6559 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6560 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6561 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6562 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6563 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6564 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6565 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6566 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6568 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6569 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6570 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6571 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6572 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6573 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6574 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6575 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6576 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6577 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6578 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6579 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6580 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6581 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6582 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
6583 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
6584 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
6585 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6586 install_element(BGP_EVPN_VNI_NODE
,
6587 &bgp_evpn_advertise_default_gw_vni_cmd
);
6588 install_element(BGP_EVPN_VNI_NODE
,
6589 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6590 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6591 install_element(BGP_EVPN_VNI_NODE
,
6592 &no_bgp_evpn_advertise_vni_subnet_cmd
);