1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
62 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
63 enum overlay_index_type
*oly
)
65 *oly
= OVERLAY_INDEX_TYPE_NONE
;
66 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
67 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
71 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
75 uint8_t type
, sub_type
;
76 struct ecommunity_as eas
;
77 struct ecommunity_ip eip
;
78 struct listnode
*node
, *nnode
;
79 struct bgp
*tmp_bgp_vrf
= NULL
;
80 json_object
*json_rt
= NULL
;
81 json_object
*json_vrfs
= NULL
;
82 char rt_buf
[RT_ADDRSTRLEN
];
85 json_rt
= json_object_new_object();
86 json_vrfs
= json_object_new_array();
89 pnt
= (uint8_t *)&irt
->rt
.val
;
92 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
95 memset(&eas
, 0, sizeof(eas
));
97 case ECOMMUNITY_ENCODE_AS
:
98 eas
.as
= (*pnt
++ << 8);
100 ptr_get_be32(pnt
, &eas
.val
);
102 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
105 json_object_string_add(json_rt
, "rt", rt_buf
);
107 vty_out(vty
, "Route-target: %s", rt_buf
);
111 case ECOMMUNITY_ENCODE_IP
:
112 memcpy(&eip
.ip
, pnt
, 4);
114 eip
.val
= (*pnt
++ << 8);
117 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
126 case ECOMMUNITY_ENCODE_AS4
:
127 pnt
= ptr_get_be32(pnt
, &eas
.val
);
128 eas
.val
= (*pnt
++ << 8);
131 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
134 json_object_string_add(json_rt
, "rt", rt_buf
);
136 vty_out(vty
, "Route-target: %s", rt_buf
);
146 "\nList of VRFs importing routes with this route-target:\n");
149 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
151 json_object_array_add(
153 json_object_new_string(
154 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
156 vty_out(vty
, " %s\n",
157 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
161 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
162 json_object_object_add(json
, rt_buf
, json_rt
);
166 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
168 json_object
*json
= NULL
;
169 struct vty
*vty
= NULL
;
170 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
172 vty
= (struct vty
*)args
[0];
173 json
= (struct json_object
*)args
[1];
175 display_vrf_import_rt(vty
, irt
, json
);
178 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
182 uint8_t type
, sub_type
;
183 struct ecommunity_as eas
;
184 struct ecommunity_ip eip
;
185 struct listnode
*node
, *nnode
;
186 struct bgpevpn
*tmp_vpn
;
187 json_object
*json_rt
= NULL
;
188 json_object
*json_vnis
= NULL
;
189 char rt_buf
[RT_ADDRSTRLEN
];
192 json_rt
= json_object_new_object();
193 json_vnis
= json_object_new_array();
196 /* TODO: This needs to go into a function */
198 pnt
= (uint8_t *)&irt
->rt
.val
;
201 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
204 memset(&eas
, 0, sizeof(eas
));
206 case ECOMMUNITY_ENCODE_AS
:
207 eas
.as
= (*pnt
++ << 8);
209 ptr_get_be32(pnt
, &eas
.val
);
211 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
214 json_object_string_add(json_rt
, "rt", rt_buf
);
216 vty_out(vty
, "Route-target: %s", rt_buf
);
220 case ECOMMUNITY_ENCODE_IP
:
221 memcpy(&eip
.ip
, pnt
, 4);
223 eip
.val
= (*pnt
++ << 8);
226 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
229 json_object_string_add(json_rt
, "rt", rt_buf
);
231 vty_out(vty
, "Route-target: %s", rt_buf
);
235 case ECOMMUNITY_ENCODE_AS4
:
236 pnt
= ptr_get_be32(pnt
, &eas
.val
);
237 eas
.val
= (*pnt
++ << 8);
240 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
243 json_object_string_add(json_rt
, "rt", rt_buf
);
245 vty_out(vty
, "Route-target: %s", rt_buf
);
255 "\nList of VNIs importing routes with this route-target:\n");
258 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
260 json_object_array_add(
261 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
263 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
267 json_object_object_add(json_rt
, "vnis", json_vnis
);
268 json_object_object_add(json
, rt_buf
, json_rt
);
272 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
274 json_object
*json
= NULL
;
275 struct vty
*vty
= NULL
;
276 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
281 display_import_rt(vty
, irt
, json
);
286 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
287 struct bgp_dest
*rd_dest
,
288 json_object
*json
, char *rd_str
,
295 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
299 /* Decode RD type. */
300 type
= decode_rd_type(pnt
);
303 vty_out(vty
, "Route Distinguisher: ");
307 decode_rd_as(pnt
+ 2, &rd_as
);
308 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
310 json_object_string_add(json
, "rd", rd_str
);
312 vty_out(vty
, "%s\n", rd_str
);
316 decode_rd_as4(pnt
+ 2, &rd_as
);
317 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
325 decode_rd_ip(pnt
+ 2, &rd_ip
);
326 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
328 json_object_string_add(json
, "rd", rd_str
);
330 vty_out(vty
, "%s\n", rd_str
);
335 snprintf(rd_str
, len
, "Unknown");
336 json_object_string_add(json
, "rd", rd_str
);
338 snprintf(rd_str
, len
, "Unknown RD type");
339 vty_out(vty
, "%s\n", rd_str
);
345 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
346 uint64_t tbl_ver
, json_object
*json
)
349 " Network Next Hop Metric LocPrf Weight Path\n";
355 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
356 tbl_ver
, &bgp
->router_id
);
358 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
359 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
361 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
363 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
364 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
365 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
366 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
367 vty_out(vty
, "%s", ri_header
);
370 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
373 char buf1
[INET6_ADDRSTRLEN
];
375 struct listnode
*node
, *nnode
;
376 struct ecommunity
*ecom
;
377 json_object
*json_import_rtl
= NULL
;
378 json_object
*json_export_rtl
= NULL
;
379 char buf2
[ETHER_ADDR_STRLEN
];
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
) {
1240 if (type
== bgp_show_type_neighbor
) {
1241 struct peer
*peer
= output_arg
;
1243 if (peer_cmp(peer
, pi
->peer
) != 0)
1246 if (type
== bgp_show_type_lcommunity_exact
) {
1247 struct lcommunity
*lcom
= output_arg
;
1249 if (!pi
->attr
->lcommunity
||
1251 pi
->attr
->lcommunity
, lcom
))
1254 if (type
== bgp_show_type_lcommunity
) {
1255 struct lcommunity
*lcom
= output_arg
;
1257 if (!pi
->attr
->lcommunity
||
1259 pi
->attr
->lcommunity
, lcom
))
1262 if (type
== bgp_show_type_community
) {
1263 struct community
*com
= output_arg
;
1265 if (!pi
->attr
->community
||
1267 pi
->attr
->community
, com
))
1270 if (type
== bgp_show_type_community_exact
) {
1271 struct community
*com
= output_arg
;
1273 if (!pi
->attr
->community
||
1275 pi
->attr
->community
, com
))
1280 json_object_int_add(
1281 json
, "bgpTableVersion",
1283 json_object_string_addf(
1288 json_object_int_add(
1291 bgp
->default_local_pref
);
1292 json_object_int_add(
1296 if (option
== SHOW_DISPLAY_TAGS
)
1301 == SHOW_DISPLAY_OVERLAY
)
1305 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1313 json_object_new_object();
1314 bgp_evpn_show_route_rd_header(
1315 vty
, dest
, json_nroute
, rd_str
,
1319 if (use_json
&& !json_array
)
1320 json_array
= json_object_new_array();
1322 if (option
== SHOW_DISPLAY_TAGS
)
1324 vty
, bgp_dest_get_prefix(rm
),
1325 pi
, no_display
, SAFI_EVPN
,
1327 else if (option
== SHOW_DISPLAY_OVERLAY
)
1328 route_vty_out_overlay(
1329 vty
, bgp_dest_get_prefix(rm
),
1330 pi
, no_display
, json_array
);
1333 bgp_dest_get_prefix(rm
),
1334 pi
, no_display
, SAFI_EVPN
,
1342 if (use_json
&& json_array
) {
1343 const struct prefix
*p
=
1344 bgp_dest_get_prefix(rm
);
1346 json_prefix_info
= json_object_new_object();
1348 json_object_string_add(
1349 json_prefix_info
, "prefix",
1350 prefix2str((struct prefix_evpn
*)p
, buf
,
1353 json_object_int_add(json_prefix_info
,
1354 "prefixLen", p
->prefixlen
);
1356 json_object_object_add(json_prefix_info
,
1357 "paths", json_array
);
1358 json_object_object_add(json_nroute
, buf
,
1364 if (use_json
&& json_nroute
)
1365 json_object_object_add(json
, rd_str
, json_nroute
);
1369 json_object_int_add(json
, "numPrefix", output_count
);
1370 json_object_int_add(json
, "totalPrefix", total_count
);
1371 vty_json(vty
, json
);
1373 if (output_count
== 0)
1374 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1378 "\nDisplayed %ld out of %ld total prefixes\n",
1379 output_count
, total_count
);
1384 DEFUN(show_ip_bgp_l2vpn_evpn
,
1385 show_ip_bgp_l2vpn_evpn_cmd
,
1386 "show [ip] bgp l2vpn evpn [json]",
1387 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1389 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1390 SHOW_DISPLAY_STANDARD
,
1391 use_json(argc
, argv
));
1394 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1395 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1396 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1402 "Display information for a route distinguisher\n"
1403 "VPN Route Distinguisher\n"
1404 "All VPN Route Distinguishers\n"
1407 int idx_ext_community
= 0;
1409 struct prefix_rd prd
;
1412 argv_find(argv
, argc
, "all", &rd_all
);
1414 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1415 NULL
, SHOW_DISPLAY_STANDARD
,
1416 use_json(argc
, argv
));
1418 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1419 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1421 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1424 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1425 SHOW_DISPLAY_STANDARD
,
1426 use_json(argc
, argv
));
1429 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1430 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1431 "show [ip] bgp l2vpn evpn all tags",
1437 "Display information about all EVPN NLRIs\n"
1438 "Display BGP tags for prefixes\n")
1440 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1441 SHOW_DISPLAY_TAGS
, 0);
1444 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1445 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1446 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1452 "Display information for a route distinguisher\n"
1453 "VPN Route Distinguisher\n"
1454 "All VPN Route Distinguishers\n"
1455 "Display BGP tags for prefixes\n")
1457 int idx_ext_community
= 0;
1459 struct prefix_rd prd
;
1462 argv_find(argv
, argc
, "all", &rd_all
);
1464 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1465 NULL
, SHOW_DISPLAY_TAGS
, 0);
1467 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1468 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1470 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1473 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1474 SHOW_DISPLAY_TAGS
, 0);
1477 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1478 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1479 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1485 "Detailed information on TCP and BGP neighbor connections\n"
1486 "IPv4 Neighbor to display information about\n"
1487 "IPv6 Neighbor to display information about\n"
1488 "Neighbor on BGP configured interface\n"
1489 "Display routes learned from neighbor\n" JSON_STR
)
1493 char *peerstr
= NULL
;
1494 bool uj
= use_json(argc
, argv
);
1495 afi_t afi
= AFI_L2VPN
;
1496 safi_t safi
= SAFI_EVPN
;
1497 struct bgp
*bgp
= NULL
;
1499 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1502 vty_out(vty
, "No index\n");
1506 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1507 argv_find(argv
, argc
, "neighbors", &idx
);
1508 peerstr
= argv
[++idx
]->arg
;
1510 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1513 json_object
*json_no
= NULL
;
1514 json_no
= json_object_new_object();
1515 json_object_string_add(json_no
, "warning",
1516 "Malformed address");
1517 vty_out(vty
, "%s\n",
1518 json_object_to_json_string(json_no
));
1519 json_object_free(json_no
);
1521 vty_out(vty
, "Malformed address: %s\n",
1525 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1527 json_object
*json_no
= NULL
;
1528 json_no
= json_object_new_object();
1529 json_object_string_add(
1531 "No such neighbor or address family");
1532 vty_out(vty
, "%s\n",
1533 json_object_to_json_string(json_no
));
1534 json_object_free(json_no
);
1536 vty_out(vty
, "%% No such neighbor or address family\n");
1540 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1541 SHOW_DISPLAY_STANDARD
, uj
);
1544 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1545 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1546 "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]",
1552 "Display information for a route distinguisher\n"
1553 "VPN Route Distinguisher\n"
1554 "All VPN Route Distinguishers\n"
1555 "Detailed information on TCP and BGP neighbor connections\n"
1556 "IPv4 Neighbor to display information about\n"
1557 "IPv6 Neighbor to display information about\n"
1558 "Neighbor on BGP configured interface\n"
1559 "Display routes learned from neighbor\n" JSON_STR
)
1561 int idx_ext_community
= 0;
1565 char *peerstr
= NULL
;
1566 struct prefix_rd prd
;
1567 bool uj
= use_json(argc
, argv
);
1568 afi_t afi
= AFI_L2VPN
;
1569 safi_t safi
= SAFI_EVPN
;
1570 struct bgp
*bgp
= NULL
;
1573 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1576 vty_out(vty
, "No index\n");
1580 argv_find(argv
, argc
, "all", &rd_all
);
1582 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1583 &idx_ext_community
);
1584 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1587 json_object
*json_no
= NULL
;
1588 json_no
= json_object_new_object();
1589 json_object_string_add(
1591 "Malformed Route Distinguisher");
1592 vty_out(vty
, "%s\n",
1593 json_object_to_json_string(json_no
));
1594 json_object_free(json_no
);
1597 "%% Malformed Route Distinguisher\n");
1602 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1603 argv_find(argv
, argc
, "neighbors", &idx
);
1604 peerstr
= argv
[++idx
]->arg
;
1606 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1609 json_object
*json_no
= NULL
;
1610 json_no
= json_object_new_object();
1611 json_object_string_add(json_no
, "warning",
1612 "Malformed address");
1613 vty_out(vty
, "%s\n",
1614 json_object_to_json_string(json_no
));
1615 json_object_free(json_no
);
1617 vty_out(vty
, "Malformed address: %s\n",
1621 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1623 json_object
*json_no
= NULL
;
1624 json_no
= json_object_new_object();
1625 json_object_string_add(
1627 "No such neighbor or address family");
1628 vty_out(vty
, "%s\n",
1629 json_object_to_json_string(json_no
));
1630 json_object_free(json_no
);
1632 vty_out(vty
, "%% No such neighbor or address family\n");
1638 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1639 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1641 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1642 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1645 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1646 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1647 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1653 "Detailed information on TCP and BGP neighbor connections\n"
1654 "IPv4 Neighbor to display information about\n"
1655 "IPv6 Neighbor to display information about\n"
1656 "Neighbor on BGP configured interface\n"
1657 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1661 bool uj
= use_json(argc
, argv
);
1662 struct bgp
*bgp
= NULL
;
1663 afi_t afi
= AFI_L2VPN
;
1664 safi_t safi
= SAFI_EVPN
;
1665 char *peerstr
= NULL
;
1670 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1673 vty_out(vty
, "No index\n");
1677 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1678 argv_find(argv
, argc
, "neighbors", &idx
);
1679 peerstr
= argv
[++idx
]->arg
;
1681 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1684 json_object
*json_no
= NULL
;
1685 json_no
= json_object_new_object();
1686 json_object_string_add(json_no
, "warning",
1687 "Malformed address");
1688 vty_out(vty
, "%s\n",
1689 json_object_to_json_string(json_no
));
1690 json_object_free(json_no
);
1692 vty_out(vty
, "Malformed address: %s\n",
1696 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1698 json_object
*json_no
= NULL
;
1699 json_no
= json_object_new_object();
1700 json_object_string_add(
1702 "No such neighbor or address family");
1703 vty_out(vty
, "%s\n",
1704 json_object_to_json_string(json_no
));
1705 json_object_free(json_no
);
1707 vty_out(vty
, "%% No such neighbor or address family\n");
1711 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1714 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1715 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1716 "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]",
1722 "Display information for a route distinguisher\n"
1723 "VPN Route Distinguisher\n"
1724 "All VPN Route Distinguishers\n"
1725 "Detailed information on TCP and BGP neighbor connections\n"
1726 "IPv4 Neighbor to display information about\n"
1727 "IPv6 Neighbor to display information about\n"
1728 "Neighbor on BGP configured interface\n"
1729 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1731 int idx_ext_community
= 0;
1735 struct prefix_rd prd
;
1736 struct bgp
*bgp
= NULL
;
1737 bool uj
= use_json(argc
, argv
);
1738 char *peerstr
= NULL
;
1739 afi_t afi
= AFI_L2VPN
;
1740 safi_t safi
= SAFI_EVPN
;
1749 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1752 vty_out(vty
, "No index\n");
1756 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1757 argv_find(argv
, argc
, "neighbors", &idx
);
1758 peerstr
= argv
[++idx
]->arg
;
1760 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1763 json_object
*json_no
= NULL
;
1764 json_no
= json_object_new_object();
1765 json_object_string_add(json_no
, "warning",
1766 "Malformed address");
1767 vty_out(vty
, "%s\n",
1768 json_object_to_json_string(json_no
));
1769 json_object_free(json_no
);
1771 vty_out(vty
, "Malformed address: %s\n",
1775 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1777 json_object
*json_no
= NULL
;
1778 json_no
= json_object_new_object();
1779 json_object_string_add(
1781 "No such neighbor or address family");
1782 vty_out(vty
, "%s\n",
1783 json_object_to_json_string(json_no
));
1784 json_object_free(json_no
);
1786 vty_out(vty
, "%% No such neighbor or address family\n");
1790 argv_find(argv
, argc
, "all", &rd_all
);
1792 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1795 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1796 &idx_ext_community
);
1797 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1800 json_object
*json_no
= NULL
;
1801 json_no
= json_object_new_object();
1802 json_object_string_add(
1804 "Malformed Route Distinguisher");
1805 vty_out(vty
, "%s\n",
1806 json_object_to_json_string(json_no
));
1807 json_object_free(json_no
);
1810 "%% Malformed Route Distinguisher\n");
1815 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1818 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1819 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1820 "show [ip] bgp l2vpn evpn all overlay [json]",
1826 "Display information about all EVPN NLRIs\n"
1827 "Display BGP Overlay Information for prefixes\n"
1830 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1831 SHOW_DISPLAY_OVERLAY
,
1832 use_json(argc
, argv
));
1835 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1836 show_ip_bgp_evpn_rd_overlay_cmd
,
1837 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1843 "Display information for a route distinguisher\n"
1844 "VPN Route Distinguisher\n"
1845 "All VPN Route Distinguishers\n"
1846 "Display BGP Overlay Information for prefixes\n")
1848 int idx_ext_community
= 0;
1850 struct prefix_rd prd
;
1853 argv_find(argv
, argc
, "all", &rd_all
);
1855 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1856 NULL
, SHOW_DISPLAY_OVERLAY
,
1857 use_json(argc
, argv
));
1859 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1860 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1862 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1865 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1866 SHOW_DISPLAY_OVERLAY
,
1867 use_json(argc
, argv
));
1870 DEFUN(show_bgp_l2vpn_evpn_com
,
1871 show_bgp_l2vpn_evpn_com_cmd
,
1872 "show bgp l2vpn evpn \
1873 <community AA:NN|large-community AA:BB:CC> \
1874 [exact-match] [json]",
1879 "Display routes matching the community\n"
1880 "Community number where AA and NN are (0-65535)\n"
1881 "Display routes matching the large-community\n"
1882 "List of large-community numbers\n"
1883 "Exact match of the communities\n"
1888 const char *clist_number_or_name
;
1889 int show_type
= bgp_show_type_normal
;
1890 struct community
*com
;
1891 struct lcommunity
*lcom
;
1893 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1894 clist_number_or_name
= argv
[++idx
]->arg
;
1895 show_type
= bgp_show_type_lcommunity
;
1897 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1898 show_type
= bgp_show_type_lcommunity_exact
;
1900 lcom
= lcommunity_str2com(clist_number_or_name
);
1902 vty_out(vty
, "%% Large-community malformed\n");
1906 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1907 SHOW_DISPLAY_STANDARD
,
1908 use_json(argc
, argv
));
1910 lcommunity_free(&lcom
);
1911 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1912 clist_number_or_name
= argv
[++idx
]->arg
;
1913 show_type
= bgp_show_type_community
;
1915 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1916 show_type
= bgp_show_type_community_exact
;
1918 com
= community_str2com(clist_number_or_name
);
1921 vty_out(vty
, "%% Community malformed: %s\n",
1922 clist_number_or_name
);
1926 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1927 SHOW_DISPLAY_STANDARD
,
1928 use_json(argc
, argv
));
1929 community_free(&com
);
1935 /* For testing purpose, static route of EVPN RT-5. */
1936 DEFUN(evpnrt5_network
,
1937 evpnrt5_network_cmd
,
1938 "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
1939 "Specify a network to announce via BGP\n"
1942 "Specify Route Distinguisher\n"
1943 "VPN Route Distinguisher\n"
1945 "Ethernet Tag Value\n"
1948 "Ethernet Segment Identifier\n"
1949 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1951 "Gateway IP ( A.B.C.D )\n"
1952 "Gateway IPv6 ( X:X::X:X )\n"
1953 "Router Mac Ext Comm\n"
1954 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1955 "Route-map to modify the attributes\n"
1956 "Name of the route map\n")
1958 int idx_ipv4_prefixlen
= 1;
1959 int idx_route_distinguisher
= 3;
1964 int idx_routermac
= 13;
1966 return bgp_static_set_safi(
1967 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1968 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1969 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1970 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1971 argv
[idx_routermac
]->arg
);
1974 /* For testing purpose, static route of EVPN RT-5. */
1975 DEFUN(no_evpnrt5_network
,
1976 no_evpnrt5_network_cmd
,
1977 "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>",
1979 "Specify a network to announce via BGP\n"
1982 "Specify Route Distinguisher\n"
1983 "VPN Route Distinguisher\n"
1985 "Ethernet Tag Value\n"
1988 "Ethernet Segment Identifier\n"
1989 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1990 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1992 int idx_ipv4_prefixlen
= 2;
1993 int idx_ext_community
= 4;
1998 return bgp_static_unset_safi(
1999 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2000 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2001 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2002 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2005 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2007 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2010 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2012 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2016 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2017 * check that this is a change.
2019 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2020 struct ecommunity
*ecomadd
)
2022 /* If the VNI is "live", we need to uninstall routes using the current
2023 * import RT(s) first before we update the import RT, and subsequently
2026 if (is_vni_live(vpn
))
2027 bgp_evpn_uninstall_routes(bgp
, vpn
);
2029 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2030 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2032 /* If the auto route-target is in use we must remove it */
2033 evpn_import_rt_delete_auto(bgp
, vpn
);
2035 /* Add new RT and rebuild the RT to VNI mapping */
2036 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2038 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2039 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2041 /* Install routes that match new import RT */
2042 if (is_vni_live(vpn
))
2043 bgp_evpn_install_routes(bgp
, vpn
);
2047 * Unconfigure Import RT(s) for a VNI (vty handler).
2049 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2050 struct ecommunity
*ecomdel
)
2052 struct listnode
*node
, *nnode
, *node_to_del
;
2053 struct ecommunity
*ecom
;
2055 /* Along the lines of "configure" except we have to reset to the
2058 if (is_vni_live(vpn
))
2059 bgp_evpn_uninstall_routes(bgp
, vpn
);
2061 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2062 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2064 /* Delete all import RTs */
2065 if (ecomdel
== NULL
) {
2066 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2067 ecommunity_free(&ecom
);
2068 list_delete_node(vpn
->import_rtl
, node
);
2072 /* Delete a specific import RT */
2076 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2077 if (ecommunity_match(ecom
, ecomdel
)) {
2078 ecommunity_free(&ecom
);
2085 list_delete_node(vpn
->import_rtl
, node_to_del
);
2088 assert(vpn
->import_rtl
);
2089 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2090 if (list_isempty(vpn
->import_rtl
)) {
2091 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2092 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2094 /* Rebuild the RT to VNI mapping */
2096 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2098 /* Install routes that match new import RT */
2099 if (is_vni_live(vpn
))
2100 bgp_evpn_install_routes(bgp
, vpn
);
2104 * Configure the Export RT for a VNI (vty handler). Caller expected to
2105 * check that this is a change. Note that only a single export RT is
2106 * allowed for a VNI and any change to configuration is implemented as
2107 * a "replace" (similar to other configuration).
2109 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2110 struct ecommunity
*ecomadd
)
2112 /* If the auto route-target is in use we must remove it */
2113 evpn_export_rt_delete_auto(bgp
, vpn
);
2115 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2116 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2118 if (is_vni_live(vpn
))
2119 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2123 * Unconfigure the Export RT for a VNI (vty handler)
2125 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2126 struct ecommunity
*ecomdel
)
2128 struct listnode
*node
, *nnode
, *node_to_del
;
2129 struct ecommunity
*ecom
;
2131 /* Delete all export RTs */
2132 if (ecomdel
== NULL
) {
2133 /* Reset to default and process all routes. */
2134 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2135 ecommunity_free(&ecom
);
2136 list_delete_node(vpn
->export_rtl
, node
);
2140 /* Delete a specific export RT */
2144 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2145 if (ecommunity_match(ecom
, ecomdel
)) {
2146 ecommunity_free(&ecom
);
2153 list_delete_node(vpn
->export_rtl
, node_to_del
);
2156 assert(vpn
->export_rtl
);
2157 if (list_isempty(vpn
->export_rtl
)) {
2158 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2159 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2162 if (is_vni_live(vpn
))
2163 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2167 * Configure RD for VRF
2169 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2171 /* If we have already advertise type-5 routes with a diffrent RD, we
2172 * have to delete and withdraw them firs
2174 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2177 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2178 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2180 /* We have a new RD for VRF.
2181 * Advertise all type-5 routes again with the new RD
2183 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2187 * Unconfigure RD for VRF
2189 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2191 /* If we have already advertise type-5 routes with a diffrent RD, we
2192 * have to delete and withdraw them firs
2194 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2196 /* fall back to default RD */
2197 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2198 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2200 /* We have a new RD for VRF.
2201 * Advertise all type-5 routes again with the new RD
2203 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2207 * Configure RD for a VNI (vty handler)
2209 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2210 struct prefix_rd
*rd
)
2212 /* If the VNI is "live", we need to delete and withdraw this VNI's
2213 * local routes with the prior RD first. Then, after updating RD,
2214 * need to re-advertise.
2216 if (is_vni_live(vpn
))
2217 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2220 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2221 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2223 if (is_vni_live(vpn
))
2224 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2228 * Unconfigure RD for a VNI (vty handler)
2230 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2232 /* If the VNI is "live", we need to delete and withdraw this VNI's
2233 * local routes with the prior RD first. Then, after resetting RD
2234 * to automatic value, need to re-advertise.
2236 if (is_vni_live(vpn
))
2237 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2239 /* reset RD to default */
2240 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2242 if (is_vni_live(vpn
))
2243 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2247 * Create VNI, if not already present (VTY handler). Mark as configured.
2249 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2251 struct bgpevpn
*vpn
;
2252 struct in_addr mcast_grp
= {INADDR_ANY
};
2257 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2259 /* Check if this L2VNI is already configured as L3VNI */
2260 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2263 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2268 /* tenant vrf will be updated when we get local_vni_add from
2271 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2275 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2281 /* Mark as configured. */
2282 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2287 * Delete VNI. If VNI does not exist in the system (i.e., just
2288 * configuration), all that is needed is to free it. Otherwise,
2289 * any parameters configured for the VNI need to be reset (with
2290 * appropriate action) and the VNI marked as unconfigured; the
2291 * VNI will continue to exist, purely as a "learnt" entity.
2293 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2295 assert(bgp
->vnihash
);
2297 if (!is_vni_live(vpn
)) {
2298 bgp_evpn_free(bgp
, vpn
);
2302 /* We need to take the unconfigure action for each parameter of this VNI
2303 * that is configured. Some optimization is possible, but not worth the
2304 * additional code for an operation that should be pretty rare.
2306 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2308 /* First, deal with the export side - RD and export RT changes. */
2309 if (is_rd_configured(vpn
))
2310 evpn_unconfigure_rd(bgp
, vpn
);
2311 if (is_export_rt_configured(vpn
))
2312 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2314 /* Next, deal with the import side. */
2315 if (is_import_rt_configured(vpn
))
2316 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2320 * Display import RT mapping to VRFs (vty handler)
2321 * bgp_evpn: evpn bgp instance
2323 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2331 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2332 (void (*)(struct hash_bucket
*,
2333 void *))show_vrf_import_rt_entry
,
2338 * Display import RT mapping to VNIs (vty handler)
2340 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2349 bgp
->import_rt_hash
,
2350 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2355 * Display EVPN routes for all VNIs - vty handler.
2357 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2358 struct in_addr vtep_ip
, json_object
*json
,
2362 struct vni_walk_ctx wctx
;
2364 num_vnis
= hashcount(bgp
->vnihash
);
2367 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2370 wctx
.vtep_ip
= vtep_ip
;
2372 wctx
.detail
= detail
;
2373 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2374 void *))show_vni_routes_hash
,
2379 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2381 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2382 vni_t vni
, struct in_addr orig_ip
,
2385 struct bgpevpn
*vpn
;
2386 struct prefix_evpn p
;
2387 struct bgp_dest
*dest
;
2388 struct bgp_path_info
*pi
;
2389 uint32_t path_cnt
= 0;
2392 json_object
*json_paths
= NULL
;
2398 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2400 vty_out(vty
, "VNI not found\n");
2404 /* See if route exists. */
2405 build_evpn_type3_prefix(&p
, orig_ip
);
2406 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2407 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2409 vty_out(vty
, "%% Network not in table\n");
2412 bgp_dest_unlock_node(dest
);
2418 json_paths
= json_object_new_array();
2420 /* Prefix and num paths displayed once per prefix. */
2421 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2423 /* Display each path for this prefix. */
2424 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2425 json_object
*json_path
= NULL
;
2428 json_path
= json_object_new_array();
2430 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2431 RPKI_NOT_BEING_USED
, json_path
);
2434 json_object_array_add(json_paths
, json_path
);
2441 json_object_object_add(json
, "paths", json_paths
);
2443 json_object_int_add(json
, "numPaths", path_cnt
);
2445 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2449 bgp_dest_unlock_node(dest
);
2453 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2454 * By definition, only matching type-2 route will be displayed.
2456 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2457 vni_t vni
, struct ethaddr
*mac
,
2458 struct ipaddr
*ip
, json_object
*json
)
2460 struct bgpevpn
*vpn
;
2461 struct prefix_evpn p
;
2462 struct bgp_dest
*dest
;
2463 struct bgp_path_info
*pi
;
2464 uint32_t path_cnt
= 0;
2467 json_object
*json_paths
= NULL
;
2473 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2476 vty_out(vty
, "VNI not found\n");
2480 /* See if route exists. Look for both non-sticky and sticky. */
2481 build_evpn_type2_prefix(&p
, mac
, ip
);
2482 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2483 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2485 vty_out(vty
, "%% Network not in table\n");
2488 bgp_dest_unlock_node(dest
);
2494 json_paths
= json_object_new_array();
2496 /* Prefix and num paths displayed once per prefix. */
2497 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2499 /* Display each path for this prefix. */
2500 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2501 json_object
*json_path
= NULL
;
2504 json_path
= json_object_new_array();
2506 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2507 RPKI_NOT_BEING_USED
, json_path
);
2510 json_object_array_add(json_paths
, json_path
);
2517 json_object_object_add(json
, "paths", json_paths
);
2519 json_object_int_add(json
, "numPaths", path_cnt
);
2521 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2525 bgp_dest_unlock_node(dest
);
2528 /* Disaplay EVPN routes for a ESI - VTY handler */
2529 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2530 esi_t
*esi
, json_object
*json
)
2532 struct bgp_evpn_es
*es
= NULL
;
2535 es
= bgp_evpn_es_find(esi
);
2538 vty_out(vty
, "ESI not found\n");
2542 show_esi_routes(bgp
, es
, vty
, json
);
2546 * Display EVPN routes for a VNI - vty handler.
2547 * If 'type' is non-zero, only routes matching that type are shown.
2548 * If the vtep_ip is non zero, only routes behind that vtep are shown
2550 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2551 int type
, struct in_addr vtep_ip
,
2554 struct bgpevpn
*vpn
;
2557 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2560 vty_out(vty
, "VNI not found\n");
2564 /* Walk this VNI's route table and display appropriate routes. */
2565 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2569 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2570 * IP (vty handler). By definition, only matching type-2 route will be
2573 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2574 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2575 struct ipaddr
*ip
, json_object
*json
)
2577 struct prefix_evpn p
;
2578 struct bgp_dest
*dest
;
2579 struct bgp_path_info
*pi
;
2582 uint32_t path_cnt
= 0;
2583 json_object
*json_paths
= NULL
;
2584 char prefix_str
[BUFSIZ
];
2589 /* See if route exists. Look for both non-sticky and sticky. */
2590 build_evpn_type2_prefix(&p
, mac
, ip
);
2591 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2592 (struct prefix
*)&p
, prd
);
2593 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2595 vty_out(vty
, "%% Network not in table\n");
2598 bgp_dest_unlock_node(dest
);
2603 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2605 /* Prefix and num paths displayed once per prefix. */
2606 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2609 json_paths
= json_object_new_array();
2611 /* Display each path for this prefix. */
2612 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2613 json_object
*json_path
= NULL
;
2616 json_path
= json_object_new_array();
2618 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2619 RPKI_NOT_BEING_USED
, json_path
);
2622 json_object_array_add(json_paths
, json_path
);
2627 if (json
&& path_cnt
) {
2629 json_object_object_add(json
, prefix_str
, json_paths
);
2630 json_object_int_add(json
, "numPaths", path_cnt
);
2632 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2636 bgp_dest_unlock_node(dest
);
2640 * Display BGP EVPN routing table -- for specific RD (vty handler)
2641 * If 'type' is non-zero, only routes matching that type are shown.
2643 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2644 struct prefix_rd
*prd
, int type
,
2647 struct bgp_dest
*rd_dest
;
2648 struct bgp_table
*table
;
2649 struct bgp_dest
*dest
;
2650 struct bgp_path_info
*pi
;
2654 uint32_t prefix_cnt
, path_cnt
;
2655 char rd_str
[RD_ADDRSTRLEN
];
2656 json_object
*json_rd
= NULL
;
2657 int add_rd_to_json
= 0;
2661 prefix_cnt
= path_cnt
= 0;
2663 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2665 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2669 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2670 if (table
== NULL
) {
2671 bgp_dest_unlock_node(rd_dest
);
2676 json_rd
= json_object_new_object();
2677 json_object_string_add(json_rd
, "rd", rd_str
);
2680 bgp_dest_unlock_node(rd_dest
);
2682 /* Display all prefixes with this RD. */
2683 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2684 const struct prefix_evpn
*evp
=
2685 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2686 json_object
*json_prefix
= NULL
;
2687 json_object
*json_paths
= NULL
;
2688 char prefix_str
[BUFSIZ
];
2689 int add_prefix_to_json
= 0;
2691 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2692 sizeof(prefix_str
));
2694 if (type
&& evp
->prefix
.route_type
!= type
)
2698 json_prefix
= json_object_new_object();
2700 pi
= bgp_dest_get_bgp_path_info(dest
);
2702 /* RD header and legend - once overall. */
2703 if (rd_header
&& !json
) {
2705 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
2707 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2709 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2711 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2713 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2717 /* Prefix and num paths displayed once per prefix. */
2718 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2725 json_paths
= json_object_new_array();
2727 /* Display each path for this prefix. */
2728 for (; pi
; pi
= pi
->next
) {
2729 json_object
*json_path
= NULL
;
2732 json_path
= json_object_new_array();
2734 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2735 RPKI_NOT_BEING_USED
, json_path
);
2738 json_object_array_add(json_paths
, json_path
);
2741 add_prefix_to_json
= 1;
2746 if (add_prefix_to_json
) {
2747 json_object_object_add(json_prefix
, "paths",
2749 json_object_object_add(json_rd
, prefix_str
,
2752 json_object_free(json_paths
);
2753 json_object_free(json_prefix
);
2762 json_object_object_add(json
, rd_str
, json_rd
);
2764 json_object_free(json_rd
);
2768 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2769 json_object_int_add(json
, "numPaths", path_cnt
);
2771 if (prefix_cnt
== 0)
2772 vty_out(vty
, "No prefixes exist with this RD%s\n",
2773 type
? " (of requested type)" : "");
2776 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2777 prefix_cnt
, path_cnt
,
2778 type
? " (of requested type)" : "");
2783 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2784 * (vty handler). Only matching type-2 routes will be displayed.
2786 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2787 struct ethaddr
*mac
, struct ipaddr
*ip
,
2790 struct bgp_dest
*rd_dest
;
2791 struct bgp_table
*table
;
2792 struct bgp_dest
*dest
;
2793 struct bgp_path_info
*pi
;
2794 afi_t afi
= AFI_L2VPN
;
2795 safi_t safi
= SAFI_EVPN
;
2796 uint32_t prefix_cnt
, path_cnt
;
2797 prefix_cnt
= path_cnt
= 0;
2799 /* EVPN routing table is a 2-level table with the first level being
2800 * the RD. We need to look in every RD we know about.
2802 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2803 rd_dest
= bgp_route_next(rd_dest
)) {
2804 json_object
*json_paths
= NULL
; /* paths array for prefix */
2805 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2806 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2807 char rd_str
[RD_ADDRSTRLEN
];
2808 char prefix_str
[BUFSIZ
];
2809 int add_rd_to_json
= 0;
2810 struct prefix_evpn ep
;
2811 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2813 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2817 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2820 /* Construct an RT-2 from the user-supplied mac(ip),
2821 * then search the l2vpn evpn table for it.
2823 build_evpn_type2_prefix(&ep
, mac
, ip
);
2824 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2825 (struct prefix
*)&ep
,
2826 (struct prefix_rd
*)rd_destp
);
2831 json_rd
= json_object_new_object();
2833 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2835 prefix2str(p
, prefix_str
, sizeof(prefix_str
));
2837 pi
= bgp_dest_get_bgp_path_info(dest
);
2839 /* RD header - per RD. */
2840 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2841 rd_str
, RD_ADDRSTRLEN
);
2846 json_prefix
= json_object_new_object();
2847 json_paths
= json_object_new_array();
2848 json_object_string_add(json_prefix
, "prefix",
2850 json_object_int_add(json_prefix
, "prefixLen",
2853 /* Prefix and num paths displayed once per prefix. */
2854 route_vty_out_detail_header(
2855 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2856 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2858 /* For EVPN, the prefix is displayed for each path (to
2859 * fit in with code that already exists).
2861 for (; pi
; pi
= pi
->next
) {
2862 json_object
*json_path
= NULL
;
2868 json_path
= json_object_new_array();
2870 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2871 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2875 json_object_array_add(json_paths
, json_path
);
2881 json_object_object_add(json_prefix
, "paths",
2883 json_object_object_add(json_rd
, prefix_str
,
2886 json_object_object_add(json
, rd_str
, json_rd
);
2888 json_object_free(json_rd
);
2893 bgp_dest_unlock_node(dest
);
2897 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2898 json_object_int_add(json
, "numPaths", path_cnt
);
2900 if (prefix_cnt
== 0) {
2901 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2903 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2904 prefix_cnt
, path_cnt
);
2910 * Display BGP EVPN routing table - all routes (vty handler).
2911 * If 'type' is non-zero, only routes matching that type are shown.
2913 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2914 json_object
*json
, int detail
)
2916 struct bgp_dest
*rd_dest
;
2917 struct bgp_table
*table
;
2918 struct bgp_dest
*dest
;
2919 struct bgp_path_info
*pi
;
2920 int header
= detail
? 0 : 1;
2924 uint32_t prefix_cnt
, path_cnt
;
2928 prefix_cnt
= path_cnt
= 0;
2930 /* EVPN routing table is a 2-level table with the first level being
2933 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2934 rd_dest
= bgp_route_next(rd_dest
)) {
2935 char rd_str
[RD_ADDRSTRLEN
];
2936 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2937 int add_rd_to_json
= 0;
2939 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2941 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2945 tbl_ver
= table
->version
;
2946 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2950 json_rd
= json_object_new_object();
2954 /* Display all prefixes for an RD */
2955 for (dest
= bgp_table_top(table
); dest
;
2956 dest
= bgp_route_next(dest
)) {
2957 json_object
*json_prefix
=
2958 NULL
; /* contains prefix under a RD */
2959 json_object
*json_paths
=
2960 NULL
; /* array of paths under a prefix*/
2961 const struct prefix_evpn
*evp
=
2962 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2964 char prefix_str
[BUFSIZ
];
2965 int add_prefix_to_json
= 0;
2966 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2968 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2969 sizeof(prefix_str
));
2971 if (type
&& evp
->prefix
.route_type
!= type
)
2974 pi
= bgp_dest_get_bgp_path_info(dest
);
2976 /* Overall header/legend displayed once. */
2978 bgp_evpn_show_route_header(vty
, bgp
,
2983 "%19s Extended Community\n"
2988 /* RD header - per RD. */
2990 bgp_evpn_show_route_rd_header(
2991 vty
, rd_dest
, json_rd
, rd_str
,
3000 json_prefix
= json_object_new_object();
3001 json_paths
= json_object_new_array();
3002 json_object_string_add(json_prefix
, "prefix",
3004 json_object_int_add(json_prefix
, "prefixLen",
3008 /* Prefix and num paths displayed once per prefix. */
3010 route_vty_out_detail_header(
3012 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3013 SAFI_EVPN
, json_prefix
);
3015 /* For EVPN, the prefix is displayed for each path (to
3017 * with code that already exists).
3019 for (; pi
; pi
= pi
->next
) {
3020 json_object
*json_path
= NULL
;
3023 add_prefix_to_json
= 1;
3027 json_path
= json_object_new_array();
3030 route_vty_out_detail(
3031 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
3032 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3035 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3039 json_object_array_add(json_paths
,
3044 if (add_prefix_to_json
) {
3045 json_object_object_add(json_prefix
,
3048 json_object_object_add(json_rd
,
3052 json_object_free(json_prefix
);
3053 json_object_free(json_paths
);
3062 json_object_object_add(json
, rd_str
, json_rd
);
3064 json_object_free(json_rd
);
3071 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3072 json_object_int_add(json
, "numPaths", path_cnt
);
3074 if (prefix_cnt
== 0) {
3075 vty_out(vty
, "No EVPN prefixes %sexist\n",
3076 type
? "(of requested type) " : "");
3078 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3079 prefix_cnt
, path_cnt
,
3080 type
? " (of requested type)" : "");
3086 * Display specified VNI (vty handler)
3088 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3092 struct bgpevpn
*vpn
;
3094 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3097 display_vni(vty
, vpn
, json
);
3099 struct bgp
*bgp_temp
;
3100 struct listnode
*node
= NULL
;
3102 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3103 if (bgp_temp
->l3vni
== vni
) {
3105 display_l3vni(vty
, bgp_temp
, json
);
3112 vty_out(vty
, "{}\n");
3114 vty_out(vty
, "VNI not found\n");
3121 * Display a VNI (upon user query).
3123 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3127 struct bgp
*bgp_temp
= NULL
;
3128 struct listnode
*node
;
3132 vty_out(vty
, "Flags: * - Kernel\n");
3133 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3134 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3137 /* print all L2 VNIS */
3140 hash_iterate(bgp
->vnihash
,
3141 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3144 /* print all L3 VNIs */
3145 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3146 show_l3vni_entry(vty
, bgp_temp
, json
);
3150 * evpn - enable advertisement of svi MAC-IP
3152 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3156 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3158 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3161 bgp
->evpn_info
->advertise_svi_macip
= set
;
3162 bgp_zebra_advertise_svi_macip(bgp
,
3163 bgp
->evpn_info
->advertise_svi_macip
, 0);
3165 if (set
&& vpn
->advertise_svi_macip
)
3167 else if (!set
&& !vpn
->advertise_svi_macip
)
3170 vpn
->advertise_svi_macip
= set
;
3171 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3177 * evpn - enable advertisement of default g/w
3179 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3182 if (bgp
->advertise_gw_macip
)
3185 bgp
->advertise_gw_macip
= 1;
3186 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3188 if (vpn
->advertise_gw_macip
)
3191 vpn
->advertise_gw_macip
= 1;
3192 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3199 * evpn - disable advertisement of default g/w
3201 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3202 struct bgpevpn
*vpn
)
3205 if (!bgp
->advertise_gw_macip
)
3208 bgp
->advertise_gw_macip
= 0;
3209 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3211 if (!vpn
->advertise_gw_macip
)
3214 vpn
->advertise_gw_macip
= 0;
3215 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3222 * evpn - enable advertisement of default g/w
3224 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3225 afi_t afi
, bool add
)
3227 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3230 /* bail if we are already advertising default route */
3231 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3235 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3236 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3237 else if (afi
== AFI_IP6
)
3238 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3239 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3241 /* bail out if we havent advertised the default route */
3242 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3245 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3246 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3247 else if (afi
== AFI_IP6
)
3248 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3249 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3252 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3256 * evpn - enable advertisement of default g/w
3258 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3259 struct bgpevpn
*vpn
)
3261 if (vpn
->advertise_subnet
)
3264 vpn
->advertise_subnet
= 1;
3265 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3269 * evpn - disable advertisement of default g/w
3271 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3273 if (!vpn
->advertise_subnet
)
3276 vpn
->advertise_subnet
= 0;
3277 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3281 * EVPN (VNI advertisement) enabled. Register with zebra.
3283 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3285 bgp
->advertise_all_vni
= 1;
3287 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3291 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3292 * cache, EVPN routes (delete and withdraw from peers).
3294 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3296 bgp
->advertise_all_vni
= 0;
3297 bgp_set_evpn(bgp_get_default());
3298 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3299 bgp_evpn_cleanup_on_disable(bgp
);
3302 /* Set resolve overlay index flag */
3303 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3305 if (set
== bgp
->resolve_overlay_index
)
3309 bgp
->resolve_overlay_index
= true;
3310 hash_iterate(bgp
->vnihash
,
3311 (void (*)(struct hash_bucket
*, void *))
3312 bgp_evpn_handle_resolve_overlay_index_set
,
3317 (void (*)(struct hash_bucket
*, void *))
3318 bgp_evpn_handle_resolve_overlay_index_unset
,
3320 bgp
->resolve_overlay_index
= false;
3325 * EVPN - use RFC8365 to auto-derive RT
3327 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3329 bgp
->advertise_autort_rfc8365
= 1;
3330 bgp_evpn_handle_autort_change(bgp
);
3334 * EVPN - don't use RFC8365 to auto-derive RT
3336 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3338 bgp
->advertise_autort_rfc8365
= 0;
3339 bgp_evpn_handle_autort_change(bgp
);
3342 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3344 char buf1
[RD_ADDRSTRLEN
];
3346 struct listnode
*node
, *nnode
;
3347 struct ecommunity
*ecom
;
3349 if (is_vni_configured(vpn
)) {
3350 vty_out(vty
, " vni %d\n", vpn
->vni
);
3351 if (is_rd_configured(vpn
))
3352 vty_out(vty
, " rd %s\n",
3353 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3355 if (is_import_rt_configured(vpn
)) {
3356 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3358 ecom_str
= ecommunity_ecom2str(
3359 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3360 vty_out(vty
, " route-target import %s\n",
3362 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3366 if (is_export_rt_configured(vpn
)) {
3367 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3369 ecom_str
= ecommunity_ecom2str(
3370 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3371 vty_out(vty
, " route-target export %s\n",
3373 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3377 if (vpn
->advertise_gw_macip
)
3378 vty_out(vty
, " advertise-default-gw\n");
3380 if (vpn
->advertise_svi_macip
)
3381 vty_out(vty
, " advertise-svi-ip\n");
3383 if (vpn
->advertise_subnet
)
3384 vty_out(vty
, " advertise-subnet\n");
3386 vty_out(vty
, " exit-vni\n");
3390 #ifndef VTYSH_EXTRACT_PL
3391 #include "bgpd/bgp_evpn_vty_clippy.c"
3394 DEFPY(bgp_evpn_flood_control
,
3395 bgp_evpn_flood_control_cmd
,
3396 "[no$no] flooding <disable$disable|head-end-replication$her>",
3398 "Specify handling for BUM packets\n"
3399 "Do not flood any BUM packets\n"
3400 "Flood BUM packets using head-end replication\n")
3402 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3403 enum vxlan_flood_control flood_ctrl
;
3409 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3411 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3415 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3418 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3419 bgp_evpn_flood_control_change(bgp
);
3424 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3425 bgp_evpn_advertise_default_gw_vni_cmd
,
3426 "advertise-default-gw",
3427 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3429 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3430 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3435 evpn_set_advertise_default_gw(bgp
, vpn
);
3440 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3441 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3442 "no advertise-default-gw",
3444 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3446 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3447 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3452 evpn_unset_advertise_default_gw(bgp
, vpn
);
3458 DEFUN (bgp_evpn_advertise_default_gw
,
3459 bgp_evpn_advertise_default_gw_cmd
,
3460 "advertise-default-gw",
3461 "Advertise All default g/w mac-ip routes in EVPN\n")
3463 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3468 if (!EVPN_ENABLED(bgp
)) {
3470 "This command is only supported under the EVPN VRF\n");
3474 evpn_set_advertise_default_gw(bgp
, NULL
);
3479 DEFUN (no_bgp_evpn_advertise_default_gw
,
3480 no_bgp_evpn_advertise_default_gw_cmd
,
3481 "no advertise-default-gw",
3483 "Withdraw All default g/w mac-ip routes from EVPN\n")
3485 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3490 evpn_unset_advertise_default_gw(bgp
, NULL
);
3495 DEFUN (bgp_evpn_advertise_all_vni
,
3496 bgp_evpn_advertise_all_vni_cmd
,
3497 "advertise-all-vni",
3498 "Advertise All local VNIs\n")
3500 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3501 struct bgp
*bgp_evpn
= NULL
;
3506 bgp_evpn
= bgp_get_evpn();
3507 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3508 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3510 return CMD_WARNING_CONFIG_FAILED
;
3513 evpn_set_advertise_all_vni(bgp
);
3517 DEFUN (no_bgp_evpn_advertise_all_vni
,
3518 no_bgp_evpn_advertise_all_vni_cmd
,
3519 "no advertise-all-vni",
3521 "Advertise All local VNIs\n")
3523 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3527 evpn_unset_advertise_all_vni(bgp
);
3531 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3532 bgp_evpn_advertise_autort_rfc8365_cmd
,
3533 "autort rfc8365-compatible",
3534 "Auto-derivation of RT\n"
3535 "Auto-derivation of RT using RFC8365\n")
3537 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3541 evpn_set_advertise_autort_rfc8365(bgp
);
3545 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3546 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3547 "no autort rfc8365-compatible",
3549 "Auto-derivation of RT\n"
3550 "Auto-derivation of RT using RFC8365\n")
3552 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3556 evpn_unset_advertise_autort_rfc8365(bgp
);
3560 DEFUN (bgp_evpn_default_originate
,
3561 bgp_evpn_default_originate_cmd
,
3562 "default-originate <ipv4 | ipv6>",
3563 "originate a default route\n"
3564 "ipv4 address family\n"
3565 "ipv6 address family\n")
3569 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3573 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3574 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3578 DEFUN (no_bgp_evpn_default_originate
,
3579 no_bgp_evpn_default_originate_cmd
,
3580 "no default-originate <ipv4 | ipv6>",
3582 "withdraw a default route\n"
3583 "ipv4 address family\n"
3584 "ipv6 address family\n")
3588 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3592 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3593 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3597 DEFPY (dup_addr_detection
,
3598 dup_addr_detection_cmd
,
3599 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3600 "Duplicate address detection\n"
3601 "Max allowed moves before address detected as duplicate\n"
3602 "Num of max allowed moves (2-1000) default 5\n"
3603 "Duplicate address detection time\n"
3604 "Time in seconds (2-1800) default 180\n")
3606 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3611 if (!EVPN_ENABLED(bgp_vrf
)) {
3613 "This command is only supported under the EVPN VRF\n");
3617 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3620 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3622 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3624 bgp_zebra_dup_addr_detection(bgp_vrf
);
3629 DEFPY (dup_addr_detection_auto_recovery
,
3630 dup_addr_detection_auto_recovery_cmd
,
3631 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3632 "Duplicate address detection\n"
3633 "Duplicate address detection freeze\n"
3634 "Duplicate address detection permanent freeze\n"
3635 "Duplicate address detection freeze time (30-3600)\n")
3637 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3638 uint32_t freeze_time
= freeze_time_val
;
3643 if (!EVPN_ENABLED(bgp_vrf
)) {
3645 "This command is only supported under the EVPN VRF\n");
3649 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3650 bgp_vrf
->evpn_info
->dad_freeze
= true;
3651 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3653 bgp_zebra_dup_addr_detection(bgp_vrf
);
3658 DEFPY (no_dup_addr_detection
,
3659 no_dup_addr_detection_cmd
,
3660 "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>]",
3662 "Duplicate address detection\n"
3663 "Max allowed moves before address detected as duplicate\n"
3664 "Num of max allowed moves (2-1000) default 5\n"
3665 "Duplicate address detection time\n"
3666 "Time in seconds (2-1800) default 180\n"
3667 "Duplicate address detection freeze\n"
3668 "Duplicate address detection permanent freeze\n"
3669 "Duplicate address detection freeze time (30-3600)\n")
3671 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3672 uint32_t max_moves
= (uint32_t)max_moves_val
;
3673 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3678 if (!EVPN_ENABLED(bgp_vrf
)) {
3680 "This command is only supported under the EVPN VRF\n");
3685 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3687 /* Reset all parameters to default. */
3688 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3689 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3690 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3691 bgp_vrf
->evpn_info
->dad_freeze
= false;
3692 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3695 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3697 "%% Value does not match with config\n");
3700 bgp_vrf
->evpn_info
->dad_max_moves
=
3701 EVPN_DAD_DEFAULT_MAX_MOVES
;
3705 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3707 "%% Value does not match with config\n");
3710 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3714 if (bgp_vrf
->evpn_info
->dad_freeze_time
3717 "%% Value does not match with config\n");
3720 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3721 bgp_vrf
->evpn_info
->dad_freeze
= false;
3724 if (permanent_val
) {
3725 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3727 "%% Value does not match with config\n");
3730 bgp_vrf
->evpn_info
->dad_freeze
= false;
3734 bgp_zebra_dup_addr_detection(bgp_vrf
);
3739 DEFPY(bgp_evpn_advertise_svi_ip
,
3740 bgp_evpn_advertise_svi_ip_cmd
,
3741 "[no$no] advertise-svi-ip",
3743 "Advertise svi mac-ip routes in EVPN\n")
3745 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3751 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3753 if (!EVPN_ENABLED(bgp
)) {
3755 "This command is only supported under EVPN VRF\n");
3758 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3764 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3765 bgp_evpn_advertise_svi_ip_vni_cmd
,
3766 "[no$no] advertise-svi-ip",
3768 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3770 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3771 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3777 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3779 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3784 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3785 bgp_evpn_advertise_vni_subnet_cmd
,
3787 "Advertise the subnet corresponding to VNI\n")
3789 struct bgp
*bgp_vrf
= NULL
;
3790 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3791 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3796 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3800 evpn_set_advertise_subnet(bgp
, vpn
);
3804 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3805 no_bgp_evpn_advertise_vni_subnet_cmd
,
3806 "no advertise-subnet",
3808 "Advertise All local VNIs\n")
3810 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3811 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3816 evpn_unset_advertise_subnet(bgp
, vpn
);
3820 DEFUN (bgp_evpn_advertise_type5
,
3821 bgp_evpn_advertise_type5_cmd
,
3822 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map WORD]",
3823 "Advertise prefix routes\n"
3826 "advertise gateway IP overlay index\n"
3827 "route-map for filtering specific routes\n"
3828 "Name of the route map\n")
3830 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3837 int rmap_changed
= 0;
3838 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3840 bool adv_flag_changed
= false;
3842 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3843 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3844 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3846 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3848 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3850 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3851 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3854 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3858 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3860 "%%only ipv4 or ipv6 address families are supported");
3864 if (safi
!= SAFI_UNICAST
) {
3866 "%%only ipv4 unicast or ipv6 unicast are supported");
3870 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3871 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3872 vty_out(vty
, "%%Unknown overlay-index type specified");
3876 if (afi
== AFI_IP
) {
3877 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3878 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3879 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3880 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3883 * this is the case for first time ever configuration
3884 * adv ipv4 unicast is enabled for the first time.
3885 * So no need to reset any flag
3887 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3889 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3890 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3891 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3893 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3894 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3895 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3897 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3898 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3901 * This is modify case from gateway-ip
3902 * to no overlay index
3904 adv_flag_changed
= true;
3905 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3906 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3907 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3908 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3909 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3911 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3912 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3915 * This is modify case from no overlay index
3918 adv_flag_changed
= true;
3919 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3920 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3921 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3922 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3926 * Command is issued with the same option
3927 * (no overlay index or gateway-ip) which was
3928 * already configured. So nothing to do.
3929 * However, route-map may have been modified.
3930 * check if route-map has been modified.
3931 * If not, return an error
3937 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3938 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3939 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3940 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3943 * this is the case for first time ever configuration
3944 * adv ipv6 unicast is enabled for the first time.
3945 * So no need to reset any flag
3947 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3949 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3950 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3951 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3953 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3954 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3955 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3957 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3958 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3961 * This is modify case from gateway-ip
3962 * to no overlay index
3964 adv_flag_changed
= true;
3965 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3966 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3967 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3968 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3969 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3971 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3972 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3975 * This is modify case from no overlay index
3978 adv_flag_changed
= true;
3979 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3980 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3981 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3982 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3986 * Command is issued with the same option
3987 * (no overlay index or gateway-ip) which was
3988 * already configured. So nothing to do.
3989 * However, route-map may have been modified.
3990 * check if route-map has been modified.
3991 * If not, return an error
3998 if ((rmap_changed
) || (adv_flag_changed
)) {
4000 /* If either of these are changed, then FRR needs to
4001 * withdraw already advertised type5 routes.
4003 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4005 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4006 XFREE(MTYPE_ROUTE_MAP_NAME
,
4007 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4008 route_map_counter_decrement(
4009 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4010 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4011 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4016 /* set the route-map for advertise command */
4017 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4018 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4019 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4020 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4021 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4022 route_map_counter_increment(
4023 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4026 /* advertise type-5 routes */
4027 if (advertise_type5_routes(bgp_vrf
, afi
))
4028 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4032 DEFUN (no_bgp_evpn_advertise_type5
,
4033 no_bgp_evpn_advertise_type5_cmd
,
4034 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4036 "Advertise prefix routes\n"
4040 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4046 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4047 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4049 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4051 "%%only ipv4 or ipv6 address families are supported");
4055 if (safi
!= SAFI_UNICAST
) {
4057 "%%only ipv4 unicast or ipv6 unicast are supported");
4061 if (afi
== AFI_IP
) {
4063 /* if we are not advertising ipv4 prefix as type-5
4066 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4067 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4068 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4069 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4070 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4071 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4072 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4073 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4074 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4078 /* if we are not advertising ipv6 prefix as type-5
4081 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4082 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4083 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4084 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4085 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4086 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4087 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4088 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4089 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4093 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4094 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4095 XFREE(MTYPE_ROUTE_MAP_NAME
,
4096 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4097 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4098 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4104 DEFPY (bgp_evpn_use_es_l3nhg
,
4105 bgp_evpn_use_es_l3nhg_cmd
,
4106 "[no$no] use-es-l3nhg",
4108 "use L3 nexthop group for host routes with ES destination\n")
4110 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4114 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4115 bgp_evpn_ead_evi_rx_disable_cmd
,
4116 "[no$no] disable-ead-evi-rx",
4118 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4120 bool ead_evi_rx
= no
? true :false;
4122 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4123 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4124 bgp_evpn_switch_ead_evi_rx();
4129 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4130 bgp_evpn_ead_evi_tx_disable_cmd
,
4131 "[no$no] disable-ead-evi-tx",
4133 "Don't advertise EAD-EVI for local ESs\n")
4135 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4139 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4140 bgp_evpn_enable_resolve_overlay_index_cmd
,
4141 "[no$no] enable-resolve-overlay-index",
4143 "Enable Recursive Resolution of type-5 route overlay index\n")
4145 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4147 if (bgp
!= bgp_get_evpn()) {
4148 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4152 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4156 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4157 bgp_evpn_advertise_pip_ip_mac_cmd
,
4158 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4160 "evpn system primary IP\n"
4163 MAC_STR MAC_STR MAC_STR
)
4165 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4166 struct bgp
*bgp_evpn
= NULL
;
4168 if (EVPN_ENABLED(bgp_vrf
)) {
4170 "This command is supported under L3VNI BGP EVPN VRF\n");
4171 return CMD_WARNING_CONFIG_FAILED
;
4173 bgp_evpn
= bgp_get_evpn();
4176 /* pip is already enabled */
4177 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4180 bgp_vrf
->evpn_info
->advertise_pip
= true;
4181 if (ip
.s_addr
!= INADDR_ANY
) {
4182 /* Already configured with same IP */
4183 if (IPV4_ADDR_SAME(&ip
,
4184 &bgp_vrf
->evpn_info
->pip_ip_static
))
4187 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4188 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4190 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4192 /* default instance router-id assignemt */
4194 bgp_vrf
->evpn_info
->pip_ip
=
4195 bgp_evpn
->router_id
;
4198 if (!is_zero_mac(&mac
->eth_addr
)) {
4199 /* Already configured with same MAC */
4200 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4201 &mac
->eth_addr
, ETH_ALEN
) == 0)
4204 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4205 &mac
->eth_addr
, ETH_ALEN
);
4206 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4207 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4210 /* Copy zebra sys mac */
4211 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4212 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4213 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4218 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4220 /* Disable PIP feature */
4221 bgp_vrf
->evpn_info
->advertise_pip
= false;
4222 /* copy anycast mac */
4223 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4224 &bgp_vrf
->rmac
, ETH_ALEN
);
4226 /* remove MAC-IP option retain PIP knob. */
4227 if ((ip
.s_addr
!= INADDR_ANY
) &&
4228 !IPV4_ADDR_SAME(&ip
,
4229 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4231 "%% BGP EVPN PIP IP does not match\n");
4232 return CMD_WARNING_CONFIG_FAILED
;
4235 if (!is_zero_mac(&mac
->eth_addr
) &&
4236 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4237 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4239 "%% BGP EVPN PIP MAC does not match\n");
4240 return CMD_WARNING_CONFIG_FAILED
;
4242 /* pip_rmac can carry vrr_rmac reset only if it matches
4243 * with static value.
4245 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4246 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4248 /* Copy zebra sys mac */
4250 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4251 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4252 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4255 /* copy anycast mac */
4256 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4257 &bgp_vrf
->rmac
, ETH_ALEN
);
4261 /* reset user configured sys MAC */
4262 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4263 /* reset user configured sys IP */
4264 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4265 /* Assign default PIP IP (bgp instance router-id) */
4267 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4269 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4272 if (is_evpn_enabled()) {
4273 struct listnode
*node
= NULL
;
4274 struct bgpevpn
*vpn
= NULL
;
4277 * At this point if bgp_evpn is NULL and evpn is enabled
4278 * something stupid has gone wrong
4282 update_advertise_vrf_routes(bgp_vrf
);
4284 /* Update (svi) type-2 routes */
4285 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4286 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4288 update_routes_for_vni(bgp_evpn
, vpn
);
4296 * Display VNI information - for all or a specific VNI
4298 DEFUN(show_bgp_l2vpn_evpn_vni
,
4299 show_bgp_l2vpn_evpn_vni_cmd
,
4300 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4309 struct bgp
*bgp_evpn
;
4313 json_object
*json
= NULL
;
4314 uint32_t num_l2vnis
= 0;
4315 uint32_t num_l3vnis
= 0;
4316 uint32_t num_vnis
= 0;
4317 struct listnode
*node
= NULL
;
4318 struct bgp
*bgp_temp
= NULL
;
4320 uj
= use_json(argc
, argv
);
4322 bgp_evpn
= bgp_get_evpn();
4326 if (!argv_find(argv
, argc
, "evpn", &idx
))
4330 json
= json_object_new_object();
4332 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4334 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4336 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4337 if (bgp_temp
->l3vni
)
4340 num_vnis
= num_l2vnis
+ num_l3vnis
;
4342 json_object_string_add(json
, "advertiseGatewayMacip",
4343 bgp_evpn
->advertise_gw_macip
4346 json_object_string_add(json
, "advertiseSviMacIp",
4347 bgp_evpn
->evpn_info
->advertise_svi_macip
4348 ? "Enabled" : "Disabled");
4349 json_object_string_add(json
, "advertiseAllVnis",
4350 is_evpn_enabled() ? "Enabled"
4352 json_object_string_add(
4354 bgp_evpn
->vxlan_flood_ctrl
4355 == VXLAN_FLOOD_HEAD_END_REPL
4356 ? "Head-end replication"
4358 json_object_int_add(json
, "numVnis", num_vnis
);
4359 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4360 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4362 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4363 bgp_evpn
->advertise_gw_macip
? "Enabled"
4365 vty_out(vty
, "Advertise SVI Macip: %s\n",
4366 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4368 vty_out(vty
, "Advertise All VNI flag: %s\n",
4369 is_evpn_enabled() ? "Enabled" : "Disabled");
4370 vty_out(vty
, "BUM flooding: %s\n",
4371 bgp_evpn
->vxlan_flood_ctrl
4372 == VXLAN_FLOOD_HEAD_END_REPL
4373 ? "Head-end replication"
4375 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4376 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4378 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4382 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4385 /* Display specific VNI */
4386 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4387 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4391 vty_json(vty
, json
);
4397 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4398 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4399 "show bgp l2vpn evpn vni remote-ip-hash",
4407 struct bgp
*bgp_evpn
;
4410 bgp_evpn
= bgp_get_evpn();
4414 if (!argv_find(argv
, argc
, "evpn", &idx
))
4417 hash_iterate(bgp_evpn
->vnihash
,
4418 (void (*)(struct hash_bucket
*,
4419 void *))bgp_evpn_show_remote_ip_hash
,
4425 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4426 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4427 "show bgp l2vpn evpn vni-svi-hash",
4432 "Show vni-svi-hash\n")
4434 struct bgp
*bgp_evpn
;
4437 bgp_evpn
= bgp_get_evpn();
4441 if (!argv_find(argv
, argc
, "evpn", &idx
))
4444 hash_iterate(bgp_evpn
->vni_svi_hash
,
4445 (void (*)(struct hash_bucket
*,
4446 void *))bgp_evpn_show_vni_svi_hash
,
4452 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4453 show_bgp_l2vpn_evpn_es_evi_cmd
,
4454 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4460 "VxLAN Network Identifier\n"
4463 "Detailed information\n")
4466 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4468 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4473 DEFPY(show_bgp_l2vpn_evpn_es
,
4474 show_bgp_l2vpn_evpn_es_cmd
,
4475 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4480 "Ethernet Segment\n"
4482 "Detailed information\n"
4488 if (!str_to_esi(esi_str
, &esi
)) {
4489 vty_out(vty
, "%%Malformed ESI\n");
4492 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4495 bgp_evpn_es_show(vty
, uj
, !!detail
);
4501 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4502 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4503 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4504 "Ethernet Segment\n"
4510 if (!str_to_esi(esi_str
, &esi
)) {
4511 vty_out(vty
, "%%Malformed ESI\n");
4514 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4517 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4523 DEFPY(show_bgp_l2vpn_evpn_nh
,
4524 show_bgp_l2vpn_evpn_nh_cmd
,
4525 "show bgp l2vpn evpn next-hops [json$uj]",
4533 bgp_evpn_nh_show(vty
, uj
);
4539 * Display EVPN neighbor summary.
4541 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4542 "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]",
4545 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4546 "Summary of BGP neighbor status\n"
4547 "Show only sessions in Established state\n"
4548 "Show only sessions not in Established state\n"
4549 "Show only the specified neighbor session\n"
4550 "Neighbor to display information about\n"
4551 "Neighbor to display information about\n"
4552 "Neighbor on BGP configured interface\n"
4553 "Show only the specified remote AS sessions\n"
4555 "Internal (iBGP) AS sessions\n"
4556 "External (eBGP) AS sessions\n"
4557 "Shorten the information on BGP instances\n"
4558 "Increase table width for longer output\n" JSON_STR
)
4563 char *neighbor
= NULL
;
4564 as_t as
= 0; /* 0 means AS filter not set */
4565 int as_type
= AS_UNSPECIFIED
;
4566 uint16_t show_flags
= 0;
4568 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4569 vrf
= argv
[++idx_vrf
]->arg
;
4571 if (argv_find(argv
, argc
, "failed", &idx
))
4572 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4574 if (argv_find(argv
, argc
, "established", &idx
))
4575 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4578 if (argv_find(argv
, argc
, "neighbor", &idx
))
4579 neighbor
= argv
[idx
+ 1]->arg
;
4581 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4582 if (argv
[idx
+ 1]->arg
[0] == 'i')
4583 as_type
= AS_INTERNAL
;
4584 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4585 as_type
= AS_EXTERNAL
;
4587 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4590 if (argv_find(argv
, argc
, "terse", &idx
))
4591 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4593 if (argv_find(argv
, argc
, "wide", &idx
))
4594 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4596 if (use_json(argc
, argv
))
4597 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4599 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4600 as_type
, as
, show_flags
);
4603 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4607 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4608 /* Specific type is requested */
4609 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4610 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4611 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4612 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4613 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4614 *type
= BGP_EVPN_IMET_ROUTE
;
4615 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4616 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4617 *type
= BGP_EVPN_ES_ROUTE
;
4618 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4619 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4620 *type
= BGP_EVPN_AD_ROUTE
;
4621 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4622 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4623 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4632 * Display global EVPN routing table.
4634 DEFUN(show_bgp_l2vpn_evpn_route
,
4635 show_bgp_l2vpn_evpn_route_cmd
,
4636 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4642 "Display Detailed Information\n"
4644 EVPN_TYPE_ALL_LIST_HELP_STR
4651 json_object
*json
= NULL
;
4653 uj
= use_json(argc
, argv
);
4655 bgp
= bgp_get_evpn();
4660 json
= json_object_new_object();
4662 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4665 if (argv_find(argv
, argc
, "detail", &detail
))
4668 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4671 vty_json(vty
, json
);
4677 * Display global EVPN routing table for specific RD.
4679 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4680 show_bgp_l2vpn_evpn_route_rd_cmd
,
4681 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4687 EVPN_RT_DIST_HELP_STR
4688 EVPN_ASN_IP_HELP_STR
4689 "All VPN Route Distinguishers\n"
4691 EVPN_TYPE_ALL_LIST_HELP_STR
4696 struct prefix_rd prd
;
4699 json_object
*json
= NULL
;
4700 int idx_ext_community
= 0;
4703 bgp
= bgp_get_evpn();
4707 /* check if we need json output */
4708 uj
= use_json(argc
, argv
);
4710 json
= json_object_new_object();
4712 argv_find(argv
, argc
, "all", &rd_all
);
4715 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4716 &idx_ext_community
);
4717 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4719 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4724 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4728 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4730 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4733 vty_json(vty
, json
);
4740 * Display global EVPN routing table for specific RD and MACIP.
4742 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4743 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4744 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4750 EVPN_RT_DIST_HELP_STR
4751 EVPN_ASN_IP_HELP_STR
4752 "All VPN Route Distinguishers\n"
4754 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4756 "IP address (IPv4 or IPv6)\n"
4761 struct prefix_rd prd
;
4764 int idx_ext_community
= 0;
4768 json_object
*json
= NULL
;
4771 memset(&mac
, 0, sizeof(struct ethaddr
));
4772 memset(&ip
, 0, sizeof(struct ipaddr
));
4774 bgp
= bgp_get_evpn();
4778 /* check if we need json output */
4779 uj
= use_json(argc
, argv
);
4781 json
= json_object_new_object();
4784 argv_find(argv
, argc
, "all", &rd_all
);
4786 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4787 &idx_ext_community
);
4788 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4790 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4796 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4797 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4798 vty_out(vty
, "%% Malformed MAC address\n");
4803 /* get the ip if specified */
4804 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4805 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4806 vty_out(vty
, "%% Malformed IP address\n");
4812 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4814 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4817 vty_json(vty
, json
);
4823 /* Display per ESI routing table */
4824 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4825 show_bgp_l2vpn_evpn_route_esi_cmd
,
4826 "show bgp l2vpn evpn route esi ESI [json]",
4832 "Ethernet Segment Identifier\n"
4838 struct bgp
*bgp
= NULL
;
4839 json_object
*json
= NULL
;
4841 memset(&esi
, 0, sizeof(esi
));
4842 bgp
= bgp_get_evpn();
4846 uj
= use_json(argc
, argv
);
4848 json
= json_object_new_object();
4850 /* get the ESI - ESI-ID is at argv[6] */
4851 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4852 vty_out(vty
, "%% Malformed ESI\n");
4856 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4859 vty_json(vty
, json
);
4867 * Display per-VNI EVPN routing table.
4869 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4870 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4876 "VXLAN Network Identifier\n"
4879 EVPN_TYPE_1_HELP_STR
4880 EVPN_TYPE_1_HELP_STR
4881 EVPN_TYPE_2_HELP_STR
4882 EVPN_TYPE_2_HELP_STR
4883 EVPN_TYPE_3_HELP_STR
4884 EVPN_TYPE_3_HELP_STR
4886 "Remote VTEP IP address\n"
4891 struct in_addr vtep_ip
;
4896 json_object
*json
= NULL
;
4898 bgp
= bgp_get_evpn();
4902 /* check if we need json output */
4903 uj
= use_json(argc
, argv
);
4905 json
= json_object_new_object();
4907 if (!argv_find(argv
, argc
, "evpn", &idx
))
4912 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4914 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4917 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4918 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4919 vty_out(vty
, "%% Malformed VTEP IP address\n");
4924 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4927 vty_json(vty
, json
);
4934 * Display per-VNI EVPN routing table for specific MACIP.
4936 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4937 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4938 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4944 "VXLAN Network Identifier\n"
4947 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4949 "IP address (IPv4 or IPv6)\n"
4958 json_object
*json
= NULL
;
4960 bgp
= bgp_get_evpn();
4964 /* check if we need json output */
4965 uj
= use_json(argc
, argv
);
4967 json
= json_object_new_object();
4969 if (!argv_find(argv
, argc
, "evpn", &idx
))
4973 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4976 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4977 vty_out(vty
, "%% Malformed MAC address\n");
4982 memset(&ip
, 0, sizeof(ip
));
4983 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4985 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4986 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4987 vty_out(vty
, "%% Malformed IP address\n");
4992 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4995 vty_json(vty
, json
);
5002 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5004 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5005 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5006 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5012 "VXLAN Network Identifier\n"
5014 EVPN_TYPE_3_HELP_STR
5015 "Originating Router IP address\n"
5021 struct in_addr orig_ip
;
5024 json_object
*json
= NULL
;
5026 bgp
= bgp_get_evpn();
5030 /* check if we need json output */
5031 uj
= use_json(argc
, argv
);
5033 json
= json_object_new_object();
5035 if (!argv_find(argv
, argc
, "evpn", &idx
))
5039 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5042 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5044 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5048 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5051 vty_json(vty
, json
);
5058 * Display per-VNI EVPN routing table - for all VNIs.
5060 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5061 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5062 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5068 "VXLAN Network Identifier\n"
5070 "Print Detailed Output\n"
5072 "Remote VTEP IP address\n"
5076 struct in_addr vtep_ip
;
5079 json_object
*json
= NULL
;
5080 /* Detail Adjust. Adjust indexes according to detail option */
5083 bgp
= bgp_get_evpn();
5087 /* check if we need json output */
5088 uj
= use_json(argc
, argv
);
5090 json
= json_object_new_object();
5092 if (!argv_find(argv
, argc
, "evpn", &idx
))
5095 if (argv_find(argv
, argc
, "detail", &da
))
5098 /* vtep-ip position depends on detail option */
5100 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5102 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5103 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5104 vty_out(vty
, "%% Malformed VTEP IP address\n");
5109 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5112 vty_json(vty
, json
);
5119 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5120 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5121 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5122 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5123 "EVPN route information\n"
5124 "MAC IP routes in the EVI tables linked to the ES\n"
5126 "Detailed information\n" JSON_STR
)
5130 json_object
*json
= NULL
;
5133 if (!str_to_esi(esi_str
, &esi
)) {
5134 vty_out(vty
, "%%Malformed ESI\n");
5143 json
= json_object_new_object();
5144 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5146 vty_json(vty
, json
);
5153 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5154 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5155 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5156 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5157 "EVPN route information\n"
5158 "MAC IP routes in the global table linked to the ES\n"
5160 "Detailed information\n" JSON_STR
)
5164 json_object
*json
= NULL
;
5167 if (!str_to_esi(esi_str
, &esi
)) {
5168 vty_out(vty
, "%%Malformed ESI\n");
5177 json
= json_object_new_object();
5178 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5180 vty_json(vty
, json
);
5187 * Display EVPN import route-target hash table
5189 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5190 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5191 "show bgp l2vpn evpn vrf-import-rt [json]",
5196 "Show vrf import route target\n"
5200 struct bgp
*bgp_evpn
= NULL
;
5201 json_object
*json
= NULL
;
5203 bgp_evpn
= bgp_get_evpn();
5207 uj
= use_json(argc
, argv
);
5209 json
= json_object_new_object();
5211 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5214 vty_json(vty
, json
);
5221 * Display EVPN import route-target hash table
5223 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5224 show_bgp_l2vpn_evpn_import_rt_cmd
,
5225 "show bgp l2vpn evpn import-rt [json]",
5230 "Show import route target\n"
5235 json_object
*json
= NULL
;
5237 bgp
= bgp_get_evpn();
5241 uj
= use_json(argc
, argv
);
5243 json
= json_object_new_object();
5245 evpn_show_import_rts(vty
, bgp
, json
);
5248 vty_json(vty
, json
);
5254 DEFPY_HIDDEN(test_es_add
,
5256 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5259 "Ethernet-segment\n"
5260 "Ethernet-Segment Identifier\n"
5268 struct in_addr vtep_ip
;
5271 bgp
= bgp_get_evpn();
5273 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5277 if (!str_to_esi(esi_str
, &esi
)) {
5278 vty_out(vty
, "%%Malformed ESI\n");
5283 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5285 vty_out(vty
, "%%Failed to delete ES\n");
5289 if (state_str
&& !strcmp(state_str
, "up"))
5293 vtep_ip
= bgp
->router_id
;
5295 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5296 EVPN_MH_DF_PREF_MIN
, false);
5298 vty_out(vty
, "%%Failed to add ES\n");
5305 DEFPY_HIDDEN(test_es_vni_add
,
5306 test_es_vni_add_cmd
,
5307 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5310 "Ethernet-segment\n"
5311 "Ethernet-Segment Identifier\n"
5320 bgp
= bgp_get_evpn();
5322 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5326 if (!str_to_esi(esi_str
, &esi
)) {
5327 vty_out(vty
, "%%Malformed ESI\n");
5332 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5334 vty_out(vty
, "%%Failed to deref ES VNI\n");
5338 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5340 vty_out(vty
, "%%Failed to ref ES VNI\n");
5347 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5348 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5352 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5353 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5354 "Summary of BGP neighbor status\n" JSON_STR
)
5356 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5357 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5358 SHOW_STR BGP_STR EVPN_HELP_STR
5360 "Display Detailed Information\n"
5362 EVPN_TYPE_2_HELP_STR
5363 EVPN_TYPE_2_HELP_STR
5364 EVPN_TYPE_3_HELP_STR
5365 EVPN_TYPE_3_HELP_STR
)
5368 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5369 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5370 SHOW_STR BGP_STR EVPN_HELP_STR
5372 EVPN_RT_DIST_HELP_STR
5373 EVPN_ASN_IP_HELP_STR
5375 EVPN_TYPE_2_HELP_STR
5376 EVPN_TYPE_2_HELP_STR
5377 EVPN_TYPE_3_HELP_STR
5378 EVPN_TYPE_3_HELP_STR
)
5381 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5382 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5383 SHOW_STR BGP_STR EVPN_HELP_STR
5385 EVPN_RT_DIST_HELP_STR
5386 EVPN_ASN_IP_HELP_STR
5388 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5390 "IP address (IPv4 or IPv6)\n")
5393 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5394 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5395 SHOW_STR BGP_STR EVPN_HELP_STR
5397 "VXLAN Network Identifier\n"
5400 EVPN_TYPE_2_HELP_STR
5401 EVPN_TYPE_2_HELP_STR
5402 EVPN_TYPE_3_HELP_STR
5403 EVPN_TYPE_3_HELP_STR
5405 "Remote VTEP IP address\n")
5407 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5408 show_bgp_evpn_route_vni_macip_cmd
,
5409 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5410 SHOW_STR BGP_STR EVPN_HELP_STR
5412 "VXLAN Network Identifier\n"
5415 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5417 "IP address (IPv4 or IPv6)\n")
5419 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5420 show_bgp_evpn_route_vni_multicast_cmd
,
5421 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5422 SHOW_STR BGP_STR EVPN_HELP_STR
5424 "VXLAN Network Identifier\n"
5426 EVPN_TYPE_3_HELP_STR
5427 "Originating Router IP address\n")
5429 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5430 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5431 SHOW_STR BGP_STR EVPN_HELP_STR
5433 "VXLAN Network Identifier\n"
5435 "Print Detailed Output\n"
5437 "Remote VTEP IP address\n")
5439 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5440 "show bgp evpn import-rt",
5441 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5443 DEFUN_NOSH (bgp_evpn_vni
,
5445 "vni " CMD_VNI_RANGE
,
5446 "VXLAN Network Identifier\n"
5450 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5451 struct bgpevpn
*vpn
;
5456 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5458 /* Create VNI, or mark as configured. */
5459 vpn
= evpn_create_update_vni(bgp
, vni
);
5461 vty_out(vty
, "%% Failed to create VNI \n");
5465 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5469 DEFUN (no_bgp_evpn_vni
,
5470 no_bgp_evpn_vni_cmd
,
5471 "no vni " CMD_VNI_RANGE
,
5473 "VXLAN Network Identifier\n"
5477 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5478 struct bgpevpn
*vpn
;
5483 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5485 /* Check if we should disallow. */
5486 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5488 vty_out(vty
, "%% Specified VNI does not exist\n");
5491 if (!is_vni_configured(vpn
)) {
5492 vty_out(vty
, "%% Specified VNI is not configured\n");
5496 evpn_delete_vni(bgp
, vpn
);
5500 DEFUN_NOSH (exit_vni
,
5503 "Exit from VNI mode\n")
5505 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5506 vty
->node
= BGP_EVPN_NODE
;
5510 DEFUN (bgp_evpn_vrf_rd
,
5511 bgp_evpn_vrf_rd_cmd
,
5512 "rd ASN:NN_OR_IP-ADDRESS:NN",
5513 EVPN_RT_DIST_HELP_STR
5514 EVPN_ASN_IP_HELP_STR
)
5517 struct prefix_rd prd
;
5518 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5523 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5525 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5529 /* If same as existing value, there is nothing more to do. */
5530 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5533 /* Configure or update the RD. */
5534 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5538 DEFUN (no_bgp_evpn_vrf_rd
,
5539 no_bgp_evpn_vrf_rd_cmd
,
5540 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5542 EVPN_RT_DIST_HELP_STR
5543 EVPN_ASN_IP_HELP_STR
)
5546 struct prefix_rd prd
;
5547 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5552 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5554 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5558 /* Check if we should disallow. */
5559 if (!is_vrf_rd_configured(bgp_vrf
)) {
5560 vty_out(vty
, "%% RD is not configured for this VRF\n");
5564 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5566 "%% RD specified does not match configuration for this VRF\n");
5570 evpn_unconfigure_vrf_rd(bgp_vrf
);
5574 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5575 no_bgp_evpn_vrf_rd_without_val_cmd
,
5578 EVPN_RT_DIST_HELP_STR
)
5580 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5585 /* Check if we should disallow. */
5586 if (!is_vrf_rd_configured(bgp_vrf
)) {
5587 vty_out(vty
, "%% RD is not configured for this VRF\n");
5591 evpn_unconfigure_vrf_rd(bgp_vrf
);
5595 DEFUN (bgp_evpn_vni_rd
,
5596 bgp_evpn_vni_rd_cmd
,
5597 "rd ASN:NN_OR_IP-ADDRESS:NN",
5598 EVPN_RT_DIST_HELP_STR
5599 EVPN_ASN_IP_HELP_STR
)
5601 struct prefix_rd prd
;
5602 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5603 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5609 if (!EVPN_ENABLED(bgp
)) {
5611 "This command is only supported under EVPN VRF\n");
5615 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5617 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5621 /* If same as existing value, there is nothing more to do. */
5622 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5625 /* Configure or update the RD. */
5626 evpn_configure_rd(bgp
, vpn
, &prd
);
5630 DEFUN (no_bgp_evpn_vni_rd
,
5631 no_bgp_evpn_vni_rd_cmd
,
5632 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5634 EVPN_RT_DIST_HELP_STR
5635 EVPN_ASN_IP_HELP_STR
)
5637 struct prefix_rd prd
;
5638 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5639 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5645 if (!EVPN_ENABLED(bgp
)) {
5647 "This command is only supported under EVPN VRF\n");
5651 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5653 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5657 /* Check if we should disallow. */
5658 if (!is_rd_configured(vpn
)) {
5659 vty_out(vty
, "%% RD is not configured for this VNI\n");
5663 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5665 "%% RD specified does not match configuration for this VNI\n");
5669 evpn_unconfigure_rd(bgp
, vpn
);
5673 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5674 no_bgp_evpn_vni_rd_without_val_cmd
,
5677 EVPN_RT_DIST_HELP_STR
)
5679 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5680 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5685 if (!EVPN_ENABLED(bgp
)) {
5687 "This command is only supported under EVPN VRF\n");
5691 /* Check if we should disallow. */
5692 if (!is_rd_configured(vpn
)) {
5693 vty_out(vty
, "%% RD is not configured for this VNI\n");
5697 evpn_unconfigure_rd(bgp
, vpn
);
5702 * Loop over all extended-communities in the route-target list rtl and
5703 * return 1 if we find ecomtarget
5705 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5706 struct ecommunity
*ecomtarget
)
5708 struct listnode
*node
, *nnode
;
5709 struct ecommunity
*ecom
;
5711 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5712 if (ecommunity_match(ecom
, ecomtarget
))
5719 /* display L3VNI related info for a VRF instance */
5720 DEFUN (show_bgp_vrf_l3vni_info
,
5721 show_bgp_vrf_l3vni_info_cmd
,
5722 "show bgp vrf VRFNAME vni [json]",
5730 char buf
[ETHER_ADDR_STRLEN
];
5731 char buf1
[INET6_ADDRSTRLEN
];
5733 const char *name
= NULL
;
5734 struct bgp
*bgp
= NULL
;
5735 struct listnode
*node
= NULL
;
5736 struct bgpevpn
*vpn
= NULL
;
5737 struct ecommunity
*ecom
= NULL
;
5738 json_object
*json
= NULL
;
5739 json_object
*json_vnis
= NULL
;
5740 json_object
*json_export_rts
= NULL
;
5741 json_object
*json_import_rts
= NULL
;
5742 bool uj
= use_json(argc
, argv
);
5745 json
= json_object_new_object();
5746 json_vnis
= json_object_new_array();
5747 json_export_rts
= json_object_new_array();
5748 json_import_rts
= json_object_new_array();
5751 name
= argv
[idx_vrf
]->arg
;
5752 bgp
= bgp_lookup_by_name(name
);
5755 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5757 json_object_string_add(json
, "warning",
5758 "BGP instance not found");
5759 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5760 json_object_free(json
);
5766 vty_out(vty
, "BGP VRF: %s\n", name
);
5767 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5768 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5769 vty_out(vty
, " Rmac: %s\n",
5770 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5771 vty_out(vty
, " VNI Filter: %s\n",
5772 CHECK_FLAG(bgp
->vrf_flags
,
5773 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5774 ? "prefix-routes-only"
5776 vty_out(vty
, " L2-VNI List:\n");
5778 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5779 vty_out(vty
, "%u ", vpn
->vni
);
5781 vty_out(vty
, " Export-RTs:\n");
5783 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5784 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5786 vty_out(vty
, " Import-RTs:\n");
5788 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5789 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5791 vty_out(vty
, " RD: %s\n",
5792 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5794 json_object_string_add(json
, "vrf", name
);
5795 json_object_string_addf(json
, "local-ip", "%pI4",
5796 &bgp
->originator_ip
);
5797 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5798 json_object_string_add(
5800 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5801 json_object_string_add(
5803 CHECK_FLAG(bgp
->vrf_flags
,
5804 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5805 ? "prefix-routes-only"
5807 /* list of l2vnis */
5808 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5809 json_object_array_add(json_vnis
,
5810 json_object_new_int(vpn
->vni
));
5811 json_object_object_add(json
, "l2vnis", json_vnis
);
5814 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5815 json_object_array_add(
5817 json_object_new_string(ecommunity_str(ecom
)));
5818 json_object_object_add(json
, "export-rts", json_export_rts
);
5821 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5822 json_object_array_add(
5824 json_object_new_string(ecommunity_str(ecom
)));
5825 json_object_object_add(json
, "import-rts", json_import_rts
);
5826 json_object_string_add(
5828 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5832 vty_json(vty
, json
);
5837 /* import/export rt for l3vni-vrf */
5838 DEFUN (bgp_evpn_vrf_rt
,
5839 bgp_evpn_vrf_rt_cmd
,
5840 "route-target <both|import|export> RT",
5842 "import and export\n"
5845 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5848 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5849 struct ecommunity
*ecomadd
= NULL
;
5854 if (!strcmp(argv
[1]->arg
, "import"))
5855 rt_type
= RT_TYPE_IMPORT
;
5856 else if (!strcmp(argv
[1]->arg
, "export"))
5857 rt_type
= RT_TYPE_EXPORT
;
5858 else if (!strcmp(argv
[1]->arg
, "both"))
5859 rt_type
= RT_TYPE_BOTH
;
5861 vty_out(vty
, "%% Invalid Route Target type\n");
5865 /* Add/update the import route-target */
5866 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5867 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5868 ECOMMUNITY_ROUTE_TARGET
, 0);
5870 vty_out(vty
, "%% Malformed Route Target list\n");
5873 ecommunity_str(ecomadd
);
5875 /* Do nothing if we already have this import route-target */
5876 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5877 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5880 /* Add/update the export route-target */
5881 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5882 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5883 ECOMMUNITY_ROUTE_TARGET
, 0);
5885 vty_out(vty
, "%% Malformed Route Target list\n");
5888 ecommunity_str(ecomadd
);
5890 /* Do nothing if we already have this export route-target */
5891 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5892 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5898 DEFUN (no_bgp_evpn_vrf_rt
,
5899 no_bgp_evpn_vrf_rt_cmd
,
5900 "no route-target <both|import|export> RT",
5903 "import and export\n"
5906 EVPN_ASN_IP_HELP_STR
)
5908 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5909 int rt_type
, found_ecomdel
;
5910 struct ecommunity
*ecomdel
= NULL
;
5915 if (!strcmp(argv
[2]->arg
, "import"))
5916 rt_type
= RT_TYPE_IMPORT
;
5917 else if (!strcmp(argv
[2]->arg
, "export"))
5918 rt_type
= RT_TYPE_EXPORT
;
5919 else if (!strcmp(argv
[2]->arg
, "both"))
5920 rt_type
= RT_TYPE_BOTH
;
5922 vty_out(vty
, "%% Invalid Route Target type\n");
5926 if (rt_type
== RT_TYPE_IMPORT
) {
5927 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5929 "%% Import RT is not configured for this VRF\n");
5932 } else if (rt_type
== RT_TYPE_EXPORT
) {
5933 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5935 "%% Export RT is not configured for this VRF\n");
5938 } else if (rt_type
== RT_TYPE_BOTH
) {
5939 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5940 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5942 "%% Import/Export RT is not configured for this VRF\n");
5947 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5949 vty_out(vty
, "%% Malformed Route Target list\n");
5952 ecommunity_str(ecomdel
);
5954 if (rt_type
== RT_TYPE_IMPORT
) {
5955 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5957 ecommunity_free(&ecomdel
);
5959 "%% RT specified does not match configuration for this VRF\n");
5962 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5963 } else if (rt_type
== RT_TYPE_EXPORT
) {
5964 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5966 ecommunity_free(&ecomdel
);
5968 "%% RT specified does not match configuration for this VRF\n");
5971 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5972 } else if (rt_type
== RT_TYPE_BOTH
) {
5975 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5977 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5981 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5983 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5987 if (!found_ecomdel
) {
5988 ecommunity_free(&ecomdel
);
5990 "%% RT specified does not match configuration for this VRF\n");
5995 ecommunity_free(&ecomdel
);
5999 DEFUN (bgp_evpn_vni_rt
,
6000 bgp_evpn_vni_rt_cmd
,
6001 "route-target <both|import|export> RT",
6003 "import and export\n"
6006 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6008 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6009 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6011 struct ecommunity
*ecomadd
= NULL
;
6016 if (!EVPN_ENABLED(bgp
)) {
6018 "This command is only supported under EVPN VRF\n");
6022 if (!strcmp(argv
[1]->text
, "import"))
6023 rt_type
= RT_TYPE_IMPORT
;
6024 else if (!strcmp(argv
[1]->text
, "export"))
6025 rt_type
= RT_TYPE_EXPORT
;
6026 else if (!strcmp(argv
[1]->text
, "both"))
6027 rt_type
= RT_TYPE_BOTH
;
6029 vty_out(vty
, "%% Invalid Route Target type\n");
6033 /* Add/update the import route-target */
6034 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6035 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6036 ECOMMUNITY_ROUTE_TARGET
, 0);
6038 vty_out(vty
, "%% Malformed Route Target list\n");
6041 ecommunity_str(ecomadd
);
6043 /* Do nothing if we already have this import route-target */
6044 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6045 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6048 /* Add/update the export route-target */
6049 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6050 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6051 ECOMMUNITY_ROUTE_TARGET
, 0);
6053 vty_out(vty
, "%% Malformed Route Target list\n");
6056 ecommunity_str(ecomadd
);
6058 /* Do nothing if we already have this export route-target */
6059 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6060 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6066 DEFUN (no_bgp_evpn_vni_rt
,
6067 no_bgp_evpn_vni_rt_cmd
,
6068 "no route-target <both|import|export> RT",
6071 "import and export\n"
6074 EVPN_ASN_IP_HELP_STR
)
6076 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6077 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6078 int rt_type
, found_ecomdel
;
6079 struct ecommunity
*ecomdel
= NULL
;
6084 if (!EVPN_ENABLED(bgp
)) {
6086 "This command is only supported under EVPN VRF\n");
6090 if (!strcmp(argv
[2]->text
, "import"))
6091 rt_type
= RT_TYPE_IMPORT
;
6092 else if (!strcmp(argv
[2]->text
, "export"))
6093 rt_type
= RT_TYPE_EXPORT
;
6094 else if (!strcmp(argv
[2]->text
, "both"))
6095 rt_type
= RT_TYPE_BOTH
;
6097 vty_out(vty
, "%% Invalid Route Target type\n");
6101 /* The user did "no route-target import", check to see if there are any
6102 * import route-targets configured. */
6103 if (rt_type
== RT_TYPE_IMPORT
) {
6104 if (!is_import_rt_configured(vpn
)) {
6106 "%% Import RT is not configured for this VNI\n");
6109 } else if (rt_type
== RT_TYPE_EXPORT
) {
6110 if (!is_export_rt_configured(vpn
)) {
6112 "%% Export RT is not configured for this VNI\n");
6115 } else if (rt_type
== RT_TYPE_BOTH
) {
6116 if (!is_import_rt_configured(vpn
)
6117 && !is_export_rt_configured(vpn
)) {
6119 "%% Import/Export RT is not configured for this VNI\n");
6124 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6126 vty_out(vty
, "%% Malformed Route Target list\n");
6129 ecommunity_str(ecomdel
);
6131 if (rt_type
== RT_TYPE_IMPORT
) {
6132 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6134 "%% RT specified does not match configuration for this VNI\n");
6137 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6138 } else if (rt_type
== RT_TYPE_EXPORT
) {
6139 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6141 "%% RT specified does not match configuration for this VNI\n");
6144 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6145 } else if (rt_type
== RT_TYPE_BOTH
) {
6148 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6149 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6153 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6154 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6158 if (!found_ecomdel
) {
6160 "%% RT specified does not match configuration for this VNI\n");
6168 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6169 no_bgp_evpn_vni_rt_without_val_cmd
,
6170 "no route-target <import|export>",
6176 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6177 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6183 if (!EVPN_ENABLED(bgp
)) {
6185 "This command is only supported under EVPN VRF\n");
6189 if (!strcmp(argv
[2]->text
, "import")) {
6190 rt_type
= RT_TYPE_IMPORT
;
6191 } else if (!strcmp(argv
[2]->text
, "export")) {
6192 rt_type
= RT_TYPE_EXPORT
;
6194 vty_out(vty
, "%% Invalid Route Target type\n");
6198 /* Check if we should disallow. */
6199 if (rt_type
== RT_TYPE_IMPORT
) {
6200 if (!is_import_rt_configured(vpn
)) {
6202 "%% Import RT is not configured for this VNI\n");
6206 if (!is_export_rt_configured(vpn
)) {
6208 "%% Export RT is not configured for this VNI\n");
6213 /* Unconfigure the RT. */
6214 if (rt_type
== RT_TYPE_IMPORT
)
6215 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6217 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6221 static int vni_cmp(const void **a
, const void **b
)
6223 const struct bgpevpn
*first
= *a
;
6224 const struct bgpevpn
*secnd
= *b
;
6226 return secnd
->vni
- first
->vni
;
6230 * Output EVPN configuration information.
6232 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6235 char buf1
[RD_ADDRSTRLEN
];
6236 char buf2
[INET6_ADDRSTRLEN
];
6238 if (bgp
->advertise_all_vni
)
6239 vty_out(vty
, " advertise-all-vni\n");
6242 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6243 struct listnode
*ln
;
6244 struct bgpevpn
*data
;
6246 list_sort(vnilist
, vni_cmp
);
6247 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6248 write_vni_config(vty
, data
);
6250 list_delete(&vnilist
);
6253 if (bgp
->advertise_autort_rfc8365
)
6254 vty_out(vty
, " autort rfc8365-compatible\n");
6256 if (bgp
->advertise_gw_macip
)
6257 vty_out(vty
, " advertise-default-gw\n");
6259 if (bgp
->evpn_info
->advertise_svi_macip
)
6260 vty_out(vty
, " advertise-svi-ip\n");
6262 if (bgp
->resolve_overlay_index
)
6263 vty_out(vty
, " enable-resolve-overlay-index\n");
6265 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6266 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6267 if (bgp_mh_info
->host_routes_use_l3nhg
)
6268 vty_out(vty
, " use-es-l3nhg\n");
6270 vty_out(vty
, " no use-es-l3nhg\n");
6273 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6274 if (bgp_mh_info
->ead_evi_rx
)
6275 vty_out(vty
, " no disable-ead-evi-rx\n");
6277 vty_out(vty
, " disable-ead-evi-rx\n");
6280 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6281 if (bgp_mh_info
->ead_evi_tx
)
6282 vty_out(vty
, " no disable-ead-evi-tx\n");
6284 vty_out(vty
, " disable-ead-evi-tx\n");
6287 if (!bgp
->evpn_info
->dup_addr_detect
)
6288 vty_out(vty
, " no dup-addr-detection\n");
6290 if (bgp
->evpn_info
->dad_max_moves
!=
6291 EVPN_DAD_DEFAULT_MAX_MOVES
||
6292 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6293 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6294 bgp
->evpn_info
->dad_max_moves
,
6295 bgp
->evpn_info
->dad_time
);
6297 if (bgp
->evpn_info
->dad_freeze
) {
6298 if (bgp
->evpn_info
->dad_freeze_time
)
6300 " dup-addr-detection freeze %u\n",
6301 bgp
->evpn_info
->dad_freeze_time
);
6304 " dup-addr-detection freeze permanent\n");
6307 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6308 vty_out(vty
, " flooding disable\n");
6310 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6311 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6312 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6313 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6314 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6317 " advertise ipv4 unicast\n");
6318 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6319 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6320 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6322 " advertise ipv4 unicast gateway-ip route-map %s\n",
6323 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6325 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6328 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6329 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6330 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6332 " advertise ipv6 unicast route-map %s\n",
6333 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6336 " advertise ipv6 unicast\n");
6337 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6338 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6339 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6341 " advertise ipv6 unicast gateway-ip route-map %s\n",
6342 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6344 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6347 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6348 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6349 vty_out(vty
, " default-originate ipv4\n");
6351 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6352 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6353 vty_out(vty
, " default-originate ipv6\n");
6355 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6356 if (!bgp
->evpn_info
->advertise_pip
)
6357 vty_out(vty
, " no advertise-pip\n");
6358 if (bgp
->evpn_info
->advertise_pip
) {
6359 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6361 vty_out(vty
, " advertise-pip ip %s",
6363 &bgp
->evpn_info
->pip_ip_static
,
6364 buf2
, INET_ADDRSTRLEN
));
6366 bgp
->evpn_info
->pip_rmac_static
))) {
6367 char buf
[ETHER_ADDR_STRLEN
];
6369 vty_out(vty
, " mac %s",
6379 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6380 vty_out(vty
, " rd %s\n",
6381 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6383 /* import route-target */
6384 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6386 struct listnode
*node
, *nnode
;
6387 struct ecommunity
*ecom
;
6389 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6391 ecom_str
= ecommunity_ecom2str(
6392 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6393 vty_out(vty
, " route-target import %s\n", ecom_str
);
6394 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6398 /* export route-target */
6399 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6401 struct listnode
*node
, *nnode
;
6402 struct ecommunity
*ecom
;
6404 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6406 ecom_str
= ecommunity_ecom2str(
6407 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6408 vty_out(vty
, " route-target export %s\n", ecom_str
);
6409 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6414 void bgp_ethernetvpn_init(void)
6416 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6417 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6418 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6419 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6420 install_element(VIEW_NODE
,
6421 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6422 install_element(VIEW_NODE
,
6423 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6426 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6429 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6430 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6431 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6432 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6433 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6434 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6435 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6436 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6437 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6438 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6439 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6440 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6441 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6442 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6443 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6444 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6445 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6446 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6447 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6448 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6449 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6450 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6451 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6452 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6453 install_element(BGP_EVPN_NODE
,
6454 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6457 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6458 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6460 /* "show bgp l2vpn evpn" commands. */
6461 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6462 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6463 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6464 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6465 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6466 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6467 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6468 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6469 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6470 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6471 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6472 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6473 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6474 install_element(VIEW_NODE
,
6475 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6476 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6477 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6478 install_element(VIEW_NODE
,
6479 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6480 install_element(VIEW_NODE
,
6481 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6482 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6483 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6485 /* "show bgp evpn" commands. */
6486 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6487 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6488 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6489 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6490 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6491 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6492 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6493 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6494 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6495 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6496 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6497 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6499 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6500 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6501 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6502 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6503 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6504 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6505 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6506 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6507 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6508 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6509 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6510 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6511 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6512 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6513 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6514 install_element(BGP_EVPN_VNI_NODE
,
6515 &bgp_evpn_advertise_default_gw_vni_cmd
);
6516 install_element(BGP_EVPN_VNI_NODE
,
6517 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6518 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6519 install_element(BGP_EVPN_VNI_NODE
,
6520 &no_bgp_evpn_advertise_vni_subnet_cmd
);