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 prefix2str((struct prefix_evpn
*)p
, buf
,
1351 json_object_string_addf(
1352 json_prefix_info
, "prefix", "%pFX",
1353 (struct prefix_evpn
*)p
);
1355 json_object_int_add(json_prefix_info
,
1356 "prefixLen", p
->prefixlen
);
1358 json_object_object_add(json_prefix_info
,
1359 "paths", json_array
);
1360 json_object_object_add(json_nroute
, buf
,
1366 if (use_json
&& json_nroute
)
1367 json_object_object_add(json
, rd_str
, json_nroute
);
1371 json_object_int_add(json
, "numPrefix", output_count
);
1372 json_object_int_add(json
, "totalPrefix", total_count
);
1373 vty_json(vty
, json
);
1375 if (output_count
== 0)
1376 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1380 "\nDisplayed %ld out of %ld total prefixes\n",
1381 output_count
, total_count
);
1386 DEFUN(show_ip_bgp_l2vpn_evpn
,
1387 show_ip_bgp_l2vpn_evpn_cmd
,
1388 "show [ip] bgp l2vpn evpn [json]",
1389 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1391 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1392 SHOW_DISPLAY_STANDARD
,
1393 use_json(argc
, argv
));
1396 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1397 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1398 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1404 "Display information for a route distinguisher\n"
1405 "VPN Route Distinguisher\n"
1406 "All VPN Route Distinguishers\n"
1409 int idx_ext_community
= 0;
1411 struct prefix_rd prd
;
1414 argv_find(argv
, argc
, "all", &rd_all
);
1416 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1417 NULL
, SHOW_DISPLAY_STANDARD
,
1418 use_json(argc
, argv
));
1420 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1421 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1423 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1426 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1427 SHOW_DISPLAY_STANDARD
,
1428 use_json(argc
, argv
));
1431 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1432 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1433 "show [ip] bgp l2vpn evpn all tags",
1439 "Display information about all EVPN NLRIs\n"
1440 "Display BGP tags for prefixes\n")
1442 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1443 SHOW_DISPLAY_TAGS
, 0);
1446 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1447 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1448 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1454 "Display information for a route distinguisher\n"
1455 "VPN Route Distinguisher\n"
1456 "All VPN Route Distinguishers\n"
1457 "Display BGP tags for prefixes\n")
1459 int idx_ext_community
= 0;
1461 struct prefix_rd prd
;
1464 argv_find(argv
, argc
, "all", &rd_all
);
1466 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1467 NULL
, SHOW_DISPLAY_TAGS
, 0);
1469 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1470 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1472 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1475 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1476 SHOW_DISPLAY_TAGS
, 0);
1479 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1480 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1481 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1487 "Detailed information on TCP and BGP neighbor connections\n"
1488 "IPv4 Neighbor to display information about\n"
1489 "IPv6 Neighbor to display information about\n"
1490 "Neighbor on BGP configured interface\n"
1491 "Display routes learned from neighbor\n" JSON_STR
)
1495 char *peerstr
= NULL
;
1496 bool uj
= use_json(argc
, argv
);
1497 afi_t afi
= AFI_L2VPN
;
1498 safi_t safi
= SAFI_EVPN
;
1499 struct bgp
*bgp
= NULL
;
1501 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1504 vty_out(vty
, "No index\n");
1508 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1509 argv_find(argv
, argc
, "neighbors", &idx
);
1510 peerstr
= argv
[++idx
]->arg
;
1512 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1515 json_object
*json_no
= NULL
;
1516 json_no
= json_object_new_object();
1517 json_object_string_add(json_no
, "warning",
1518 "Malformed address");
1519 vty_out(vty
, "%s\n",
1520 json_object_to_json_string(json_no
));
1521 json_object_free(json_no
);
1523 vty_out(vty
, "Malformed address: %s\n",
1527 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1529 json_object
*json_no
= NULL
;
1530 json_no
= json_object_new_object();
1531 json_object_string_add(
1533 "No such neighbor or address family");
1534 vty_out(vty
, "%s\n",
1535 json_object_to_json_string(json_no
));
1536 json_object_free(json_no
);
1538 vty_out(vty
, "%% No such neighbor or address family\n");
1542 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1543 SHOW_DISPLAY_STANDARD
, uj
);
1546 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1547 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1548 "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]",
1554 "Display information for a route distinguisher\n"
1555 "VPN Route Distinguisher\n"
1556 "All VPN Route Distinguishers\n"
1557 "Detailed information on TCP and BGP neighbor connections\n"
1558 "IPv4 Neighbor to display information about\n"
1559 "IPv6 Neighbor to display information about\n"
1560 "Neighbor on BGP configured interface\n"
1561 "Display routes learned from neighbor\n" JSON_STR
)
1563 int idx_ext_community
= 0;
1567 char *peerstr
= NULL
;
1568 struct prefix_rd prd
;
1569 bool uj
= use_json(argc
, argv
);
1570 afi_t afi
= AFI_L2VPN
;
1571 safi_t safi
= SAFI_EVPN
;
1572 struct bgp
*bgp
= NULL
;
1575 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1578 vty_out(vty
, "No index\n");
1582 argv_find(argv
, argc
, "all", &rd_all
);
1584 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1585 &idx_ext_community
);
1586 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1589 json_object
*json_no
= NULL
;
1590 json_no
= json_object_new_object();
1591 json_object_string_add(
1593 "Malformed Route Distinguisher");
1594 vty_out(vty
, "%s\n",
1595 json_object_to_json_string(json_no
));
1596 json_object_free(json_no
);
1599 "%% Malformed Route Distinguisher\n");
1604 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1605 argv_find(argv
, argc
, "neighbors", &idx
);
1606 peerstr
= argv
[++idx
]->arg
;
1608 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1611 json_object
*json_no
= NULL
;
1612 json_no
= json_object_new_object();
1613 json_object_string_add(json_no
, "warning",
1614 "Malformed address");
1615 vty_out(vty
, "%s\n",
1616 json_object_to_json_string(json_no
));
1617 json_object_free(json_no
);
1619 vty_out(vty
, "Malformed address: %s\n",
1623 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1625 json_object
*json_no
= NULL
;
1626 json_no
= json_object_new_object();
1627 json_object_string_add(
1629 "No such neighbor or address family");
1630 vty_out(vty
, "%s\n",
1631 json_object_to_json_string(json_no
));
1632 json_object_free(json_no
);
1634 vty_out(vty
, "%% No such neighbor or address family\n");
1640 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1641 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1643 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1644 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1647 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1648 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1649 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1655 "Detailed information on TCP and BGP neighbor connections\n"
1656 "IPv4 Neighbor to display information about\n"
1657 "IPv6 Neighbor to display information about\n"
1658 "Neighbor on BGP configured interface\n"
1659 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1663 bool uj
= use_json(argc
, argv
);
1664 struct bgp
*bgp
= NULL
;
1665 afi_t afi
= AFI_L2VPN
;
1666 safi_t safi
= SAFI_EVPN
;
1667 char *peerstr
= NULL
;
1672 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1675 vty_out(vty
, "No index\n");
1679 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1680 argv_find(argv
, argc
, "neighbors", &idx
);
1681 peerstr
= argv
[++idx
]->arg
;
1683 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1686 json_object
*json_no
= NULL
;
1687 json_no
= json_object_new_object();
1688 json_object_string_add(json_no
, "warning",
1689 "Malformed address");
1690 vty_out(vty
, "%s\n",
1691 json_object_to_json_string(json_no
));
1692 json_object_free(json_no
);
1694 vty_out(vty
, "Malformed address: %s\n",
1698 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1700 json_object
*json_no
= NULL
;
1701 json_no
= json_object_new_object();
1702 json_object_string_add(
1704 "No such neighbor or address family");
1705 vty_out(vty
, "%s\n",
1706 json_object_to_json_string(json_no
));
1707 json_object_free(json_no
);
1709 vty_out(vty
, "%% No such neighbor or address family\n");
1713 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1716 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1717 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1718 "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]",
1724 "Display information for a route distinguisher\n"
1725 "VPN Route Distinguisher\n"
1726 "All VPN Route Distinguishers\n"
1727 "Detailed information on TCP and BGP neighbor connections\n"
1728 "IPv4 Neighbor to display information about\n"
1729 "IPv6 Neighbor to display information about\n"
1730 "Neighbor on BGP configured interface\n"
1731 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1733 int idx_ext_community
= 0;
1737 struct prefix_rd prd
;
1738 struct bgp
*bgp
= NULL
;
1739 bool uj
= use_json(argc
, argv
);
1740 char *peerstr
= NULL
;
1741 afi_t afi
= AFI_L2VPN
;
1742 safi_t safi
= SAFI_EVPN
;
1751 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1754 vty_out(vty
, "No index\n");
1758 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1759 argv_find(argv
, argc
, "neighbors", &idx
);
1760 peerstr
= argv
[++idx
]->arg
;
1762 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1765 json_object
*json_no
= NULL
;
1766 json_no
= json_object_new_object();
1767 json_object_string_add(json_no
, "warning",
1768 "Malformed address");
1769 vty_out(vty
, "%s\n",
1770 json_object_to_json_string(json_no
));
1771 json_object_free(json_no
);
1773 vty_out(vty
, "Malformed address: %s\n",
1777 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1779 json_object
*json_no
= NULL
;
1780 json_no
= json_object_new_object();
1781 json_object_string_add(
1783 "No such neighbor or address family");
1784 vty_out(vty
, "%s\n",
1785 json_object_to_json_string(json_no
));
1786 json_object_free(json_no
);
1788 vty_out(vty
, "%% No such neighbor or address family\n");
1792 argv_find(argv
, argc
, "all", &rd_all
);
1794 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1797 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1798 &idx_ext_community
);
1799 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1802 json_object
*json_no
= NULL
;
1803 json_no
= json_object_new_object();
1804 json_object_string_add(
1806 "Malformed Route Distinguisher");
1807 vty_out(vty
, "%s\n",
1808 json_object_to_json_string(json_no
));
1809 json_object_free(json_no
);
1812 "%% Malformed Route Distinguisher\n");
1817 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1820 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1821 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1822 "show [ip] bgp l2vpn evpn all overlay [json]",
1828 "Display information about all EVPN NLRIs\n"
1829 "Display BGP Overlay Information for prefixes\n"
1832 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1833 SHOW_DISPLAY_OVERLAY
,
1834 use_json(argc
, argv
));
1837 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1838 show_ip_bgp_evpn_rd_overlay_cmd
,
1839 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1845 "Display information for a route distinguisher\n"
1846 "VPN Route Distinguisher\n"
1847 "All VPN Route Distinguishers\n"
1848 "Display BGP Overlay Information for prefixes\n")
1850 int idx_ext_community
= 0;
1852 struct prefix_rd prd
;
1855 argv_find(argv
, argc
, "all", &rd_all
);
1857 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1858 NULL
, SHOW_DISPLAY_OVERLAY
,
1859 use_json(argc
, argv
));
1861 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1862 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1864 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1867 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1868 SHOW_DISPLAY_OVERLAY
,
1869 use_json(argc
, argv
));
1872 DEFUN(show_bgp_l2vpn_evpn_com
,
1873 show_bgp_l2vpn_evpn_com_cmd
,
1874 "show bgp l2vpn evpn \
1875 <community AA:NN|large-community AA:BB:CC> \
1876 [exact-match] [json]",
1881 "Display routes matching the community\n"
1882 "Community number where AA and NN are (0-65535)\n"
1883 "Display routes matching the large-community\n"
1884 "List of large-community numbers\n"
1885 "Exact match of the communities\n"
1890 const char *clist_number_or_name
;
1891 int show_type
= bgp_show_type_normal
;
1892 struct community
*com
;
1893 struct lcommunity
*lcom
;
1895 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1896 clist_number_or_name
= argv
[++idx
]->arg
;
1897 show_type
= bgp_show_type_lcommunity
;
1899 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1900 show_type
= bgp_show_type_lcommunity_exact
;
1902 lcom
= lcommunity_str2com(clist_number_or_name
);
1904 vty_out(vty
, "%% Large-community malformed\n");
1908 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1909 SHOW_DISPLAY_STANDARD
,
1910 use_json(argc
, argv
));
1912 lcommunity_free(&lcom
);
1913 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1914 clist_number_or_name
= argv
[++idx
]->arg
;
1915 show_type
= bgp_show_type_community
;
1917 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1918 show_type
= bgp_show_type_community_exact
;
1920 com
= community_str2com(clist_number_or_name
);
1923 vty_out(vty
, "%% Community malformed: %s\n",
1924 clist_number_or_name
);
1928 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1929 SHOW_DISPLAY_STANDARD
,
1930 use_json(argc
, argv
));
1931 community_free(&com
);
1937 /* For testing purpose, static route of EVPN RT-5. */
1938 DEFUN(evpnrt5_network
,
1939 evpnrt5_network_cmd
,
1940 "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]",
1941 "Specify a network to announce via BGP\n"
1944 "Specify Route Distinguisher\n"
1945 "VPN Route Distinguisher\n"
1947 "Ethernet Tag Value\n"
1950 "Ethernet Segment Identifier\n"
1951 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1953 "Gateway IP ( A.B.C.D )\n"
1954 "Gateway IPv6 ( X:X::X:X )\n"
1955 "Router Mac Ext Comm\n"
1956 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1957 "Route-map to modify the attributes\n"
1958 "Name of the route map\n")
1960 int idx_ipv4_prefixlen
= 1;
1961 int idx_route_distinguisher
= 3;
1966 int idx_routermac
= 13;
1968 return bgp_static_set_safi(
1969 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1970 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1971 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1972 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1973 argv
[idx_routermac
]->arg
);
1976 /* For testing purpose, static route of EVPN RT-5. */
1977 DEFUN(no_evpnrt5_network
,
1978 no_evpnrt5_network_cmd
,
1979 "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>",
1981 "Specify a network to announce via BGP\n"
1984 "Specify Route Distinguisher\n"
1985 "VPN Route Distinguisher\n"
1987 "Ethernet Tag Value\n"
1990 "Ethernet Segment Identifier\n"
1991 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1992 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1994 int idx_ipv4_prefixlen
= 2;
1995 int idx_ext_community
= 4;
2000 return bgp_static_unset_safi(
2001 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2002 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2003 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2004 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2007 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2009 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2012 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2014 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2018 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2019 * check that this is a change.
2021 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2022 struct ecommunity
*ecomadd
)
2024 /* If the VNI is "live", we need to uninstall routes using the current
2025 * import RT(s) first before we update the import RT, and subsequently
2028 if (is_vni_live(vpn
))
2029 bgp_evpn_uninstall_routes(bgp
, vpn
);
2031 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2032 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2034 /* If the auto route-target is in use we must remove it */
2035 evpn_import_rt_delete_auto(bgp
, vpn
);
2037 /* Add new RT and rebuild the RT to VNI mapping */
2038 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2040 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2041 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2043 /* Install routes that match new import RT */
2044 if (is_vni_live(vpn
))
2045 bgp_evpn_install_routes(bgp
, vpn
);
2049 * Unconfigure Import RT(s) for a VNI (vty handler).
2051 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2052 struct ecommunity
*ecomdel
)
2054 struct listnode
*node
, *nnode
, *node_to_del
;
2055 struct ecommunity
*ecom
;
2057 /* Along the lines of "configure" except we have to reset to the
2060 if (is_vni_live(vpn
))
2061 bgp_evpn_uninstall_routes(bgp
, vpn
);
2063 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2064 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2066 /* Delete all import RTs */
2067 if (ecomdel
== NULL
) {
2068 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2069 ecommunity_free(&ecom
);
2070 list_delete_node(vpn
->import_rtl
, node
);
2074 /* Delete a specific import RT */
2078 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2079 if (ecommunity_match(ecom
, ecomdel
)) {
2080 ecommunity_free(&ecom
);
2087 list_delete_node(vpn
->import_rtl
, node_to_del
);
2090 assert(vpn
->import_rtl
);
2091 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2092 if (list_isempty(vpn
->import_rtl
)) {
2093 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2094 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2096 /* Rebuild the RT to VNI mapping */
2098 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2100 /* Install routes that match new import RT */
2101 if (is_vni_live(vpn
))
2102 bgp_evpn_install_routes(bgp
, vpn
);
2106 * Configure the Export RT for a VNI (vty handler). Caller expected to
2107 * check that this is a change. Note that only a single export RT is
2108 * allowed for a VNI and any change to configuration is implemented as
2109 * a "replace" (similar to other configuration).
2111 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2112 struct ecommunity
*ecomadd
)
2114 /* If the auto route-target is in use we must remove it */
2115 evpn_export_rt_delete_auto(bgp
, vpn
);
2117 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2118 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2120 if (is_vni_live(vpn
))
2121 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2125 * Unconfigure the Export RT for a VNI (vty handler)
2127 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2128 struct ecommunity
*ecomdel
)
2130 struct listnode
*node
, *nnode
, *node_to_del
;
2131 struct ecommunity
*ecom
;
2133 /* Delete all export RTs */
2134 if (ecomdel
== NULL
) {
2135 /* Reset to default and process all routes. */
2136 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2137 ecommunity_free(&ecom
);
2138 list_delete_node(vpn
->export_rtl
, node
);
2142 /* Delete a specific export RT */
2146 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2147 if (ecommunity_match(ecom
, ecomdel
)) {
2148 ecommunity_free(&ecom
);
2155 list_delete_node(vpn
->export_rtl
, node_to_del
);
2158 assert(vpn
->export_rtl
);
2159 if (list_isempty(vpn
->export_rtl
)) {
2160 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2161 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2164 if (is_vni_live(vpn
))
2165 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2169 * Configure RD for VRF
2171 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2173 /* If we have already advertise type-5 routes with a diffrent RD, we
2174 * have to delete and withdraw them firs
2176 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2179 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2180 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2182 /* We have a new RD for VRF.
2183 * Advertise all type-5 routes again with the new RD
2185 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2189 * Unconfigure RD for VRF
2191 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2193 /* If we have already advertise type-5 routes with a diffrent RD, we
2194 * have to delete and withdraw them firs
2196 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2198 /* fall back to default RD */
2199 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2200 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2202 /* We have a new RD for VRF.
2203 * Advertise all type-5 routes again with the new RD
2205 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2209 * Configure RD for a VNI (vty handler)
2211 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2212 struct prefix_rd
*rd
)
2214 /* If the VNI is "live", we need to delete and withdraw this VNI's
2215 * local routes with the prior RD first. Then, after updating RD,
2216 * need to re-advertise.
2218 if (is_vni_live(vpn
))
2219 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2222 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2223 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2225 if (is_vni_live(vpn
))
2226 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2230 * Unconfigure RD for a VNI (vty handler)
2232 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2234 /* If the VNI is "live", we need to delete and withdraw this VNI's
2235 * local routes with the prior RD first. Then, after resetting RD
2236 * to automatic value, need to re-advertise.
2238 if (is_vni_live(vpn
))
2239 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2241 /* reset RD to default */
2242 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2244 if (is_vni_live(vpn
))
2245 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2249 * Create VNI, if not already present (VTY handler). Mark as configured.
2251 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2253 struct bgpevpn
*vpn
;
2254 struct in_addr mcast_grp
= {INADDR_ANY
};
2259 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2261 /* Check if this L2VNI is already configured as L3VNI */
2262 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2265 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2270 /* tenant vrf will be updated when we get local_vni_add from
2273 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2277 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2283 /* Mark as configured. */
2284 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2289 * Delete VNI. If VNI does not exist in the system (i.e., just
2290 * configuration), all that is needed is to free it. Otherwise,
2291 * any parameters configured for the VNI need to be reset (with
2292 * appropriate action) and the VNI marked as unconfigured; the
2293 * VNI will continue to exist, purely as a "learnt" entity.
2295 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2297 assert(bgp
->vnihash
);
2299 if (!is_vni_live(vpn
)) {
2300 bgp_evpn_free(bgp
, vpn
);
2304 /* We need to take the unconfigure action for each parameter of this VNI
2305 * that is configured. Some optimization is possible, but not worth the
2306 * additional code for an operation that should be pretty rare.
2308 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2310 /* First, deal with the export side - RD and export RT changes. */
2311 if (is_rd_configured(vpn
))
2312 evpn_unconfigure_rd(bgp
, vpn
);
2313 if (is_export_rt_configured(vpn
))
2314 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2316 /* Next, deal with the import side. */
2317 if (is_import_rt_configured(vpn
))
2318 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2322 * Display import RT mapping to VRFs (vty handler)
2323 * bgp_evpn: evpn bgp instance
2325 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2333 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2334 (void (*)(struct hash_bucket
*,
2335 void *))show_vrf_import_rt_entry
,
2340 * Display import RT mapping to VNIs (vty handler)
2342 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2351 bgp
->import_rt_hash
,
2352 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2357 * Display EVPN routes for all VNIs - vty handler.
2359 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2360 struct in_addr vtep_ip
, json_object
*json
,
2364 struct vni_walk_ctx wctx
;
2366 num_vnis
= hashcount(bgp
->vnihash
);
2369 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2372 wctx
.vtep_ip
= vtep_ip
;
2374 wctx
.detail
= detail
;
2375 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2376 void *))show_vni_routes_hash
,
2381 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2383 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2384 vni_t vni
, struct in_addr orig_ip
,
2387 struct bgpevpn
*vpn
;
2388 struct prefix_evpn p
;
2389 struct bgp_dest
*dest
;
2390 struct bgp_path_info
*pi
;
2391 uint32_t path_cnt
= 0;
2394 json_object
*json_paths
= NULL
;
2400 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2402 vty_out(vty
, "VNI not found\n");
2406 /* See if route exists. */
2407 build_evpn_type3_prefix(&p
, orig_ip
);
2408 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2409 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2411 vty_out(vty
, "%% Network not in table\n");
2414 bgp_dest_unlock_node(dest
);
2420 json_paths
= json_object_new_array();
2422 /* Prefix and num paths displayed once per prefix. */
2423 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2425 /* Display each path for this prefix. */
2426 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2427 json_object
*json_path
= NULL
;
2430 json_path
= json_object_new_array();
2432 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2433 RPKI_NOT_BEING_USED
, json_path
);
2436 json_object_array_add(json_paths
, json_path
);
2443 json_object_object_add(json
, "paths", json_paths
);
2445 json_object_int_add(json
, "numPaths", path_cnt
);
2447 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2451 bgp_dest_unlock_node(dest
);
2455 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2456 * By definition, only matching type-2 route will be displayed.
2458 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2459 vni_t vni
, struct ethaddr
*mac
,
2460 struct ipaddr
*ip
, json_object
*json
)
2462 struct bgpevpn
*vpn
;
2463 struct prefix_evpn p
;
2464 struct bgp_dest
*dest
;
2465 struct bgp_path_info
*pi
;
2466 uint32_t path_cnt
= 0;
2469 json_object
*json_paths
= NULL
;
2475 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2478 vty_out(vty
, "VNI not found\n");
2482 /* See if route exists. Look for both non-sticky and sticky. */
2483 build_evpn_type2_prefix(&p
, mac
, ip
);
2484 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2485 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2487 vty_out(vty
, "%% Network not in table\n");
2490 bgp_dest_unlock_node(dest
);
2496 json_paths
= json_object_new_array();
2498 /* Prefix and num paths displayed once per prefix. */
2499 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2501 /* Display each path for this prefix. */
2502 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2503 json_object
*json_path
= NULL
;
2506 json_path
= json_object_new_array();
2508 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2509 RPKI_NOT_BEING_USED
, json_path
);
2512 json_object_array_add(json_paths
, json_path
);
2519 json_object_object_add(json
, "paths", json_paths
);
2521 json_object_int_add(json
, "numPaths", path_cnt
);
2523 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2527 bgp_dest_unlock_node(dest
);
2530 /* Disaplay EVPN routes for a ESI - VTY handler */
2531 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2532 esi_t
*esi
, json_object
*json
)
2534 struct bgp_evpn_es
*es
= NULL
;
2537 es
= bgp_evpn_es_find(esi
);
2540 vty_out(vty
, "ESI not found\n");
2544 show_esi_routes(bgp
, es
, vty
, json
);
2548 * Display EVPN routes for a VNI - vty handler.
2549 * If 'type' is non-zero, only routes matching that type are shown.
2550 * If the vtep_ip is non zero, only routes behind that vtep are shown
2552 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2553 int type
, struct in_addr vtep_ip
,
2556 struct bgpevpn
*vpn
;
2559 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2562 vty_out(vty
, "VNI not found\n");
2566 /* Walk this VNI's route table and display appropriate routes. */
2567 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2571 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2572 * IP (vty handler). By definition, only matching type-2 route will be
2575 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2576 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2577 struct ipaddr
*ip
, json_object
*json
)
2579 struct prefix_evpn p
;
2580 struct bgp_dest
*dest
;
2581 struct bgp_path_info
*pi
;
2584 uint32_t path_cnt
= 0;
2585 json_object
*json_paths
= NULL
;
2586 char prefix_str
[BUFSIZ
];
2591 /* See if route exists. Look for both non-sticky and sticky. */
2592 build_evpn_type2_prefix(&p
, mac
, ip
);
2593 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2594 (struct prefix
*)&p
, prd
);
2595 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2597 vty_out(vty
, "%% Network not in table\n");
2600 bgp_dest_unlock_node(dest
);
2605 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2607 /* Prefix and num paths displayed once per prefix. */
2608 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2611 json_paths
= json_object_new_array();
2613 /* Display each path for this prefix. */
2614 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2615 json_object
*json_path
= NULL
;
2618 json_path
= json_object_new_array();
2620 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2621 RPKI_NOT_BEING_USED
, json_path
);
2624 json_object_array_add(json_paths
, json_path
);
2629 if (json
&& path_cnt
) {
2631 json_object_object_add(json
, prefix_str
, json_paths
);
2632 json_object_int_add(json
, "numPaths", path_cnt
);
2634 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2638 bgp_dest_unlock_node(dest
);
2642 * Display BGP EVPN routing table -- for specific RD (vty handler)
2643 * If 'type' is non-zero, only routes matching that type are shown.
2645 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2646 struct prefix_rd
*prd
, int type
,
2649 struct bgp_dest
*rd_dest
;
2650 struct bgp_table
*table
;
2651 struct bgp_dest
*dest
;
2652 struct bgp_path_info
*pi
;
2656 uint32_t prefix_cnt
, path_cnt
;
2657 char rd_str
[RD_ADDRSTRLEN
];
2658 json_object
*json_rd
= NULL
;
2659 int add_rd_to_json
= 0;
2663 prefix_cnt
= path_cnt
= 0;
2665 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2667 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2671 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2672 if (table
== NULL
) {
2673 bgp_dest_unlock_node(rd_dest
);
2678 json_rd
= json_object_new_object();
2679 json_object_string_add(json_rd
, "rd", rd_str
);
2682 bgp_dest_unlock_node(rd_dest
);
2684 /* Display all prefixes with this RD. */
2685 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2686 const struct prefix_evpn
*evp
=
2687 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2688 json_object
*json_prefix
= NULL
;
2689 json_object
*json_paths
= NULL
;
2690 char prefix_str
[BUFSIZ
];
2691 int add_prefix_to_json
= 0;
2693 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2694 sizeof(prefix_str
));
2696 if (type
&& evp
->prefix
.route_type
!= type
)
2700 json_prefix
= json_object_new_object();
2702 pi
= bgp_dest_get_bgp_path_info(dest
);
2704 /* RD header and legend - once overall. */
2705 if (rd_header
&& !json
) {
2707 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
2709 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2711 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2713 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2715 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2719 /* Prefix and num paths displayed once per prefix. */
2720 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2727 json_paths
= json_object_new_array();
2729 /* Display each path for this prefix. */
2730 for (; pi
; pi
= pi
->next
) {
2731 json_object
*json_path
= NULL
;
2734 json_path
= json_object_new_array();
2736 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2737 RPKI_NOT_BEING_USED
, json_path
);
2740 json_object_array_add(json_paths
, json_path
);
2743 add_prefix_to_json
= 1;
2748 if (add_prefix_to_json
) {
2749 json_object_object_add(json_prefix
, "paths",
2751 json_object_object_add(json_rd
, prefix_str
,
2754 json_object_free(json_paths
);
2755 json_object_free(json_prefix
);
2764 json_object_object_add(json
, rd_str
, json_rd
);
2766 json_object_free(json_rd
);
2770 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2771 json_object_int_add(json
, "numPaths", path_cnt
);
2773 if (prefix_cnt
== 0)
2774 vty_out(vty
, "No prefixes exist with this RD%s\n",
2775 type
? " (of requested type)" : "");
2778 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2779 prefix_cnt
, path_cnt
,
2780 type
? " (of requested type)" : "");
2785 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2786 * (vty handler). Only matching type-2 routes will be displayed.
2788 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2789 struct ethaddr
*mac
, struct ipaddr
*ip
,
2792 struct bgp_dest
*rd_dest
;
2793 struct bgp_table
*table
;
2794 struct bgp_dest
*dest
;
2795 struct bgp_path_info
*pi
;
2796 afi_t afi
= AFI_L2VPN
;
2797 safi_t safi
= SAFI_EVPN
;
2798 uint32_t prefix_cnt
, path_cnt
;
2799 prefix_cnt
= path_cnt
= 0;
2801 /* EVPN routing table is a 2-level table with the first level being
2802 * the RD. We need to look in every RD we know about.
2804 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2805 rd_dest
= bgp_route_next(rd_dest
)) {
2806 json_object
*json_paths
= NULL
; /* paths array for prefix */
2807 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2808 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2809 char rd_str
[RD_ADDRSTRLEN
];
2810 char prefix_str
[BUFSIZ
];
2811 int add_rd_to_json
= 0;
2812 struct prefix_evpn ep
;
2813 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2815 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2819 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2822 /* Construct an RT-2 from the user-supplied mac(ip),
2823 * then search the l2vpn evpn table for it.
2825 build_evpn_type2_prefix(&ep
, mac
, ip
);
2826 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2827 (struct prefix
*)&ep
,
2828 (struct prefix_rd
*)rd_destp
);
2833 json_rd
= json_object_new_object();
2835 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2837 prefix2str(p
, prefix_str
, sizeof(prefix_str
));
2839 pi
= bgp_dest_get_bgp_path_info(dest
);
2841 /* RD header - per RD. */
2842 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2843 rd_str
, RD_ADDRSTRLEN
);
2848 json_prefix
= json_object_new_object();
2849 json_paths
= json_object_new_array();
2850 json_object_string_add(json_prefix
, "prefix",
2852 json_object_int_add(json_prefix
, "prefixLen",
2855 /* Prefix and num paths displayed once per prefix. */
2856 route_vty_out_detail_header(
2857 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2858 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2860 /* For EVPN, the prefix is displayed for each path (to
2861 * fit in with code that already exists).
2863 for (; pi
; pi
= pi
->next
) {
2864 json_object
*json_path
= NULL
;
2870 json_path
= json_object_new_array();
2872 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2873 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2877 json_object_array_add(json_paths
, json_path
);
2883 json_object_object_add(json_prefix
, "paths",
2885 json_object_object_add(json_rd
, prefix_str
,
2888 json_object_object_add(json
, rd_str
, json_rd
);
2890 json_object_free(json_rd
);
2895 bgp_dest_unlock_node(dest
);
2899 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2900 json_object_int_add(json
, "numPaths", path_cnt
);
2902 if (prefix_cnt
== 0) {
2903 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2905 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2906 prefix_cnt
, path_cnt
);
2912 * Display BGP EVPN routing table - all routes (vty handler).
2913 * If 'type' is non-zero, only routes matching that type are shown.
2915 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2916 json_object
*json
, int detail
)
2918 struct bgp_dest
*rd_dest
;
2919 struct bgp_table
*table
;
2920 struct bgp_dest
*dest
;
2921 struct bgp_path_info
*pi
;
2922 int header
= detail
? 0 : 1;
2926 uint32_t prefix_cnt
, path_cnt
;
2930 prefix_cnt
= path_cnt
= 0;
2932 /* EVPN routing table is a 2-level table with the first level being
2935 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2936 rd_dest
= bgp_route_next(rd_dest
)) {
2937 char rd_str
[RD_ADDRSTRLEN
];
2938 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2939 int add_rd_to_json
= 0;
2941 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2943 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2947 tbl_ver
= table
->version
;
2948 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2952 json_rd
= json_object_new_object();
2956 /* Display all prefixes for an RD */
2957 for (dest
= bgp_table_top(table
); dest
;
2958 dest
= bgp_route_next(dest
)) {
2959 json_object
*json_prefix
=
2960 NULL
; /* contains prefix under a RD */
2961 json_object
*json_paths
=
2962 NULL
; /* array of paths under a prefix*/
2963 const struct prefix_evpn
*evp
=
2964 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2966 char prefix_str
[BUFSIZ
];
2967 int add_prefix_to_json
= 0;
2968 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2970 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2971 sizeof(prefix_str
));
2973 if (type
&& evp
->prefix
.route_type
!= type
)
2976 pi
= bgp_dest_get_bgp_path_info(dest
);
2978 /* Overall header/legend displayed once. */
2980 bgp_evpn_show_route_header(vty
, bgp
,
2985 "%19s Extended Community\n"
2990 /* RD header - per RD. */
2992 bgp_evpn_show_route_rd_header(
2993 vty
, rd_dest
, json_rd
, rd_str
,
3002 json_prefix
= json_object_new_object();
3003 json_paths
= json_object_new_array();
3004 json_object_string_add(json_prefix
, "prefix",
3006 json_object_int_add(json_prefix
, "prefixLen",
3010 /* Prefix and num paths displayed once per prefix. */
3012 route_vty_out_detail_header(
3014 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3015 SAFI_EVPN
, json_prefix
);
3017 /* For EVPN, the prefix is displayed for each path (to
3019 * with code that already exists).
3021 for (; pi
; pi
= pi
->next
) {
3022 json_object
*json_path
= NULL
;
3025 add_prefix_to_json
= 1;
3029 json_path
= json_object_new_array();
3032 route_vty_out_detail(
3033 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
3034 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3037 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3041 json_object_array_add(json_paths
,
3046 if (add_prefix_to_json
) {
3047 json_object_object_add(json_prefix
,
3050 json_object_object_add(json_rd
,
3054 json_object_free(json_prefix
);
3055 json_object_free(json_paths
);
3064 json_object_object_add(json
, rd_str
, json_rd
);
3066 json_object_free(json_rd
);
3073 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3074 json_object_int_add(json
, "numPaths", path_cnt
);
3076 if (prefix_cnt
== 0) {
3077 vty_out(vty
, "No EVPN prefixes %sexist\n",
3078 type
? "(of requested type) " : "");
3080 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3081 prefix_cnt
, path_cnt
,
3082 type
? " (of requested type)" : "");
3088 * Display specified VNI (vty handler)
3090 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3094 struct bgpevpn
*vpn
;
3096 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3099 display_vni(vty
, vpn
, json
);
3101 struct bgp
*bgp_temp
;
3102 struct listnode
*node
= NULL
;
3104 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3105 if (bgp_temp
->l3vni
== vni
) {
3107 display_l3vni(vty
, bgp_temp
, json
);
3114 vty_out(vty
, "{}\n");
3116 vty_out(vty
, "VNI not found\n");
3123 * Display a VNI (upon user query).
3125 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3129 struct bgp
*bgp_temp
= NULL
;
3130 struct listnode
*node
;
3134 vty_out(vty
, "Flags: * - Kernel\n");
3135 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3136 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3139 /* print all L2 VNIS */
3142 hash_iterate(bgp
->vnihash
,
3143 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3146 /* print all L3 VNIs */
3147 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3148 show_l3vni_entry(vty
, bgp_temp
, json
);
3152 * evpn - enable advertisement of svi MAC-IP
3154 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3158 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3160 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3163 bgp
->evpn_info
->advertise_svi_macip
= set
;
3164 bgp_zebra_advertise_svi_macip(bgp
,
3165 bgp
->evpn_info
->advertise_svi_macip
, 0);
3167 if (set
&& vpn
->advertise_svi_macip
)
3169 else if (!set
&& !vpn
->advertise_svi_macip
)
3172 vpn
->advertise_svi_macip
= set
;
3173 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3179 * evpn - enable advertisement of default g/w
3181 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3184 if (bgp
->advertise_gw_macip
)
3187 bgp
->advertise_gw_macip
= 1;
3188 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3190 if (vpn
->advertise_gw_macip
)
3193 vpn
->advertise_gw_macip
= 1;
3194 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3201 * evpn - disable advertisement of default g/w
3203 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3204 struct bgpevpn
*vpn
)
3207 if (!bgp
->advertise_gw_macip
)
3210 bgp
->advertise_gw_macip
= 0;
3211 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3213 if (!vpn
->advertise_gw_macip
)
3216 vpn
->advertise_gw_macip
= 0;
3217 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3224 * evpn - enable advertisement of default g/w
3226 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3227 afi_t afi
, bool add
)
3229 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3232 /* bail if we are already advertising default route */
3233 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3237 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3238 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3239 else if (afi
== AFI_IP6
)
3240 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3241 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3243 /* bail out if we havent advertised the default route */
3244 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3247 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3248 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3249 else if (afi
== AFI_IP6
)
3250 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3251 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3254 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3258 * evpn - enable advertisement of default g/w
3260 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3261 struct bgpevpn
*vpn
)
3263 if (vpn
->advertise_subnet
)
3266 vpn
->advertise_subnet
= 1;
3267 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3271 * evpn - disable advertisement of default g/w
3273 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3275 if (!vpn
->advertise_subnet
)
3278 vpn
->advertise_subnet
= 0;
3279 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3283 * EVPN (VNI advertisement) enabled. Register with zebra.
3285 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3287 bgp
->advertise_all_vni
= 1;
3289 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3293 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3294 * cache, EVPN routes (delete and withdraw from peers).
3296 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3298 bgp
->advertise_all_vni
= 0;
3299 bgp_set_evpn(bgp_get_default());
3300 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3301 bgp_evpn_cleanup_on_disable(bgp
);
3304 /* Set resolve overlay index flag */
3305 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3307 if (set
== bgp
->resolve_overlay_index
)
3311 bgp
->resolve_overlay_index
= true;
3312 hash_iterate(bgp
->vnihash
,
3313 (void (*)(struct hash_bucket
*, void *))
3314 bgp_evpn_handle_resolve_overlay_index_set
,
3319 (void (*)(struct hash_bucket
*, void *))
3320 bgp_evpn_handle_resolve_overlay_index_unset
,
3322 bgp
->resolve_overlay_index
= false;
3327 * EVPN - use RFC8365 to auto-derive RT
3329 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3331 bgp
->advertise_autort_rfc8365
= 1;
3332 bgp_evpn_handle_autort_change(bgp
);
3336 * EVPN - don't use RFC8365 to auto-derive RT
3338 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3340 bgp
->advertise_autort_rfc8365
= 0;
3341 bgp_evpn_handle_autort_change(bgp
);
3344 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3346 char buf1
[RD_ADDRSTRLEN
];
3348 struct listnode
*node
, *nnode
;
3349 struct ecommunity
*ecom
;
3351 if (is_vni_configured(vpn
)) {
3352 vty_out(vty
, " vni %d\n", vpn
->vni
);
3353 if (is_rd_configured(vpn
))
3354 vty_out(vty
, " rd %s\n",
3355 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3357 if (is_import_rt_configured(vpn
)) {
3358 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3360 ecom_str
= ecommunity_ecom2str(
3361 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3362 vty_out(vty
, " route-target import %s\n",
3364 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3368 if (is_export_rt_configured(vpn
)) {
3369 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3371 ecom_str
= ecommunity_ecom2str(
3372 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3373 vty_out(vty
, " route-target export %s\n",
3375 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3379 if (vpn
->advertise_gw_macip
)
3380 vty_out(vty
, " advertise-default-gw\n");
3382 if (vpn
->advertise_svi_macip
)
3383 vty_out(vty
, " advertise-svi-ip\n");
3385 if (vpn
->advertise_subnet
)
3386 vty_out(vty
, " advertise-subnet\n");
3388 vty_out(vty
, " exit-vni\n");
3392 #ifndef VTYSH_EXTRACT_PL
3393 #include "bgpd/bgp_evpn_vty_clippy.c"
3396 DEFPY(bgp_evpn_flood_control
,
3397 bgp_evpn_flood_control_cmd
,
3398 "[no$no] flooding <disable$disable|head-end-replication$her>",
3400 "Specify handling for BUM packets\n"
3401 "Do not flood any BUM packets\n"
3402 "Flood BUM packets using head-end replication\n")
3404 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3405 enum vxlan_flood_control flood_ctrl
;
3411 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3413 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3417 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3420 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3421 bgp_evpn_flood_control_change(bgp
);
3426 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3427 bgp_evpn_advertise_default_gw_vni_cmd
,
3428 "advertise-default-gw",
3429 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3431 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3432 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3437 evpn_set_advertise_default_gw(bgp
, vpn
);
3442 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3443 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3444 "no advertise-default-gw",
3446 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3448 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3449 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3454 evpn_unset_advertise_default_gw(bgp
, vpn
);
3460 DEFUN (bgp_evpn_advertise_default_gw
,
3461 bgp_evpn_advertise_default_gw_cmd
,
3462 "advertise-default-gw",
3463 "Advertise All default g/w mac-ip routes in EVPN\n")
3465 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3470 if (!EVPN_ENABLED(bgp
)) {
3472 "This command is only supported under the EVPN VRF\n");
3476 evpn_set_advertise_default_gw(bgp
, NULL
);
3481 DEFUN (no_bgp_evpn_advertise_default_gw
,
3482 no_bgp_evpn_advertise_default_gw_cmd
,
3483 "no advertise-default-gw",
3485 "Withdraw All default g/w mac-ip routes from EVPN\n")
3487 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3492 evpn_unset_advertise_default_gw(bgp
, NULL
);
3497 DEFUN (bgp_evpn_advertise_all_vni
,
3498 bgp_evpn_advertise_all_vni_cmd
,
3499 "advertise-all-vni",
3500 "Advertise All local VNIs\n")
3502 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3503 struct bgp
*bgp_evpn
= NULL
;
3508 bgp_evpn
= bgp_get_evpn();
3509 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3510 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3512 return CMD_WARNING_CONFIG_FAILED
;
3515 evpn_set_advertise_all_vni(bgp
);
3519 DEFUN (no_bgp_evpn_advertise_all_vni
,
3520 no_bgp_evpn_advertise_all_vni_cmd
,
3521 "no advertise-all-vni",
3523 "Advertise All local VNIs\n")
3525 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3529 evpn_unset_advertise_all_vni(bgp
);
3533 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3534 bgp_evpn_advertise_autort_rfc8365_cmd
,
3535 "autort rfc8365-compatible",
3536 "Auto-derivation of RT\n"
3537 "Auto-derivation of RT using RFC8365\n")
3539 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3543 evpn_set_advertise_autort_rfc8365(bgp
);
3547 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3548 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3549 "no autort rfc8365-compatible",
3551 "Auto-derivation of RT\n"
3552 "Auto-derivation of RT using RFC8365\n")
3554 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3558 evpn_unset_advertise_autort_rfc8365(bgp
);
3562 DEFUN (bgp_evpn_default_originate
,
3563 bgp_evpn_default_originate_cmd
,
3564 "default-originate <ipv4 | ipv6>",
3565 "originate a default route\n"
3566 "ipv4 address family\n"
3567 "ipv6 address family\n")
3571 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3575 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3576 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3580 DEFUN (no_bgp_evpn_default_originate
,
3581 no_bgp_evpn_default_originate_cmd
,
3582 "no default-originate <ipv4 | ipv6>",
3584 "withdraw a default route\n"
3585 "ipv4 address family\n"
3586 "ipv6 address family\n")
3590 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3594 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3595 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3599 DEFPY (dup_addr_detection
,
3600 dup_addr_detection_cmd
,
3601 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3602 "Duplicate address detection\n"
3603 "Max allowed moves before address detected as duplicate\n"
3604 "Num of max allowed moves (2-1000) default 5\n"
3605 "Duplicate address detection time\n"
3606 "Time in seconds (2-1800) default 180\n")
3608 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3613 if (!EVPN_ENABLED(bgp_vrf
)) {
3615 "This command is only supported under the EVPN VRF\n");
3619 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3622 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3624 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3626 bgp_zebra_dup_addr_detection(bgp_vrf
);
3631 DEFPY (dup_addr_detection_auto_recovery
,
3632 dup_addr_detection_auto_recovery_cmd
,
3633 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3634 "Duplicate address detection\n"
3635 "Duplicate address detection freeze\n"
3636 "Duplicate address detection permanent freeze\n"
3637 "Duplicate address detection freeze time (30-3600)\n")
3639 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3640 uint32_t freeze_time
= freeze_time_val
;
3645 if (!EVPN_ENABLED(bgp_vrf
)) {
3647 "This command is only supported under the EVPN VRF\n");
3651 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3652 bgp_vrf
->evpn_info
->dad_freeze
= true;
3653 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3655 bgp_zebra_dup_addr_detection(bgp_vrf
);
3660 DEFPY (no_dup_addr_detection
,
3661 no_dup_addr_detection_cmd
,
3662 "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>]",
3664 "Duplicate address detection\n"
3665 "Max allowed moves before address detected as duplicate\n"
3666 "Num of max allowed moves (2-1000) default 5\n"
3667 "Duplicate address detection time\n"
3668 "Time in seconds (2-1800) default 180\n"
3669 "Duplicate address detection freeze\n"
3670 "Duplicate address detection permanent freeze\n"
3671 "Duplicate address detection freeze time (30-3600)\n")
3673 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3674 uint32_t max_moves
= (uint32_t)max_moves_val
;
3675 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3680 if (!EVPN_ENABLED(bgp_vrf
)) {
3682 "This command is only supported under the EVPN VRF\n");
3687 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3689 /* Reset all parameters to default. */
3690 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3691 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3692 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3693 bgp_vrf
->evpn_info
->dad_freeze
= false;
3694 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3697 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3699 "%% Value does not match with config\n");
3702 bgp_vrf
->evpn_info
->dad_max_moves
=
3703 EVPN_DAD_DEFAULT_MAX_MOVES
;
3707 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3709 "%% Value does not match with config\n");
3712 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3716 if (bgp_vrf
->evpn_info
->dad_freeze_time
3719 "%% Value does not match with config\n");
3722 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3723 bgp_vrf
->evpn_info
->dad_freeze
= false;
3726 if (permanent_val
) {
3727 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3729 "%% Value does not match with config\n");
3732 bgp_vrf
->evpn_info
->dad_freeze
= false;
3736 bgp_zebra_dup_addr_detection(bgp_vrf
);
3741 DEFPY(bgp_evpn_advertise_svi_ip
,
3742 bgp_evpn_advertise_svi_ip_cmd
,
3743 "[no$no] advertise-svi-ip",
3745 "Advertise svi mac-ip routes in EVPN\n")
3747 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3753 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3755 if (!EVPN_ENABLED(bgp
)) {
3757 "This command is only supported under EVPN VRF\n");
3760 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3766 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3767 bgp_evpn_advertise_svi_ip_vni_cmd
,
3768 "[no$no] advertise-svi-ip",
3770 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3772 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3773 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3779 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3781 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3786 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3787 bgp_evpn_advertise_vni_subnet_cmd
,
3789 "Advertise the subnet corresponding to VNI\n")
3791 struct bgp
*bgp_vrf
= NULL
;
3792 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3793 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3798 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3802 evpn_set_advertise_subnet(bgp
, vpn
);
3806 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3807 no_bgp_evpn_advertise_vni_subnet_cmd
,
3808 "no advertise-subnet",
3810 "Advertise All local VNIs\n")
3812 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3813 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3818 evpn_unset_advertise_subnet(bgp
, vpn
);
3822 DEFUN (bgp_evpn_advertise_type5
,
3823 bgp_evpn_advertise_type5_cmd
,
3824 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map WORD]",
3825 "Advertise prefix routes\n"
3828 "advertise gateway IP overlay index\n"
3829 "route-map for filtering specific routes\n"
3830 "Name of the route map\n")
3832 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3839 int rmap_changed
= 0;
3840 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3842 bool adv_flag_changed
= false;
3844 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3845 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3846 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3848 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3850 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3852 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3853 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3856 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3860 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3862 "%%only ipv4 or ipv6 address families are supported");
3866 if (safi
!= SAFI_UNICAST
) {
3868 "%%only ipv4 unicast or ipv6 unicast are supported");
3872 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3873 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3874 vty_out(vty
, "%%Unknown overlay-index type specified");
3878 if (afi
== AFI_IP
) {
3879 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3880 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3881 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3882 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3885 * this is the case for first time ever configuration
3886 * adv ipv4 unicast is enabled for the first time.
3887 * So no need to reset any flag
3889 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3891 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3892 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3893 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3895 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3896 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3897 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3899 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3900 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3903 * This is modify case from gateway-ip
3904 * to no overlay index
3906 adv_flag_changed
= true;
3907 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3908 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3909 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3910 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3911 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3913 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3914 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3917 * This is modify case from no overlay index
3920 adv_flag_changed
= true;
3921 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3922 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3923 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3924 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3928 * Command is issued with the same option
3929 * (no overlay index or gateway-ip) which was
3930 * already configured. So nothing to do.
3931 * However, route-map may have been modified.
3932 * check if route-map has been modified.
3933 * If not, return an error
3939 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3940 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3941 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3942 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3945 * this is the case for first time ever configuration
3946 * adv ipv6 unicast is enabled for the first time.
3947 * So no need to reset any flag
3949 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3951 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3952 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3953 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3955 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3956 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3957 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3959 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3960 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3963 * This is modify case from gateway-ip
3964 * to no overlay index
3966 adv_flag_changed
= true;
3967 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3968 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3969 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3970 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3971 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3973 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3974 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3977 * This is modify case from no overlay index
3980 adv_flag_changed
= true;
3981 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3982 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3983 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3984 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3988 * Command is issued with the same option
3989 * (no overlay index or gateway-ip) which was
3990 * already configured. So nothing to do.
3991 * However, route-map may have been modified.
3992 * check if route-map has been modified.
3993 * If not, return an error
4000 if ((rmap_changed
) || (adv_flag_changed
)) {
4002 /* If either of these are changed, then FRR needs to
4003 * withdraw already advertised type5 routes.
4005 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4007 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4008 XFREE(MTYPE_ROUTE_MAP_NAME
,
4009 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4010 route_map_counter_decrement(
4011 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4012 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4013 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4018 /* set the route-map for advertise command */
4019 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4020 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4021 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4022 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4023 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4024 route_map_counter_increment(
4025 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4028 /* advertise type-5 routes */
4029 if (advertise_type5_routes(bgp_vrf
, afi
))
4030 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4034 DEFUN (no_bgp_evpn_advertise_type5
,
4035 no_bgp_evpn_advertise_type5_cmd
,
4036 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4038 "Advertise prefix routes\n"
4042 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4048 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4049 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4051 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4053 "%%only ipv4 or ipv6 address families are supported");
4057 if (safi
!= SAFI_UNICAST
) {
4059 "%%only ipv4 unicast or ipv6 unicast are supported");
4063 if (afi
== AFI_IP
) {
4065 /* if we are not advertising ipv4 prefix as type-5
4068 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4069 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4070 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4071 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4072 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4073 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4074 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4075 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4076 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4080 /* if we are not advertising ipv6 prefix as type-5
4083 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4084 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4085 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4086 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4087 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4088 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4089 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4090 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4091 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4095 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4096 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4097 XFREE(MTYPE_ROUTE_MAP_NAME
,
4098 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4099 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4100 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4106 DEFPY (bgp_evpn_use_es_l3nhg
,
4107 bgp_evpn_use_es_l3nhg_cmd
,
4108 "[no$no] use-es-l3nhg",
4110 "use L3 nexthop group for host routes with ES destination\n")
4112 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4116 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4117 bgp_evpn_ead_evi_rx_disable_cmd
,
4118 "[no$no] disable-ead-evi-rx",
4120 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4122 bool ead_evi_rx
= no
? true :false;
4124 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4125 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4126 bgp_evpn_switch_ead_evi_rx();
4131 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4132 bgp_evpn_ead_evi_tx_disable_cmd
,
4133 "[no$no] disable-ead-evi-tx",
4135 "Don't advertise EAD-EVI for local ESs\n")
4137 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4141 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4142 bgp_evpn_enable_resolve_overlay_index_cmd
,
4143 "[no$no] enable-resolve-overlay-index",
4145 "Enable Recursive Resolution of type-5 route overlay index\n")
4147 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4149 if (bgp
!= bgp_get_evpn()) {
4150 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4154 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4158 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4159 bgp_evpn_advertise_pip_ip_mac_cmd
,
4160 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4162 "evpn system primary IP\n"
4165 MAC_STR MAC_STR MAC_STR
)
4167 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4168 struct bgp
*bgp_evpn
= NULL
;
4170 if (EVPN_ENABLED(bgp_vrf
)) {
4172 "This command is supported under L3VNI BGP EVPN VRF\n");
4173 return CMD_WARNING_CONFIG_FAILED
;
4175 bgp_evpn
= bgp_get_evpn();
4178 /* pip is already enabled */
4179 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4182 bgp_vrf
->evpn_info
->advertise_pip
= true;
4183 if (ip
.s_addr
!= INADDR_ANY
) {
4184 /* Already configured with same IP */
4185 if (IPV4_ADDR_SAME(&ip
,
4186 &bgp_vrf
->evpn_info
->pip_ip_static
))
4189 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4190 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4192 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4194 /* default instance router-id assignemt */
4196 bgp_vrf
->evpn_info
->pip_ip
=
4197 bgp_evpn
->router_id
;
4200 if (!is_zero_mac(&mac
->eth_addr
)) {
4201 /* Already configured with same MAC */
4202 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4203 &mac
->eth_addr
, ETH_ALEN
) == 0)
4206 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4207 &mac
->eth_addr
, ETH_ALEN
);
4208 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4209 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4212 /* Copy zebra sys mac */
4213 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4214 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4215 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4220 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4222 /* Disable PIP feature */
4223 bgp_vrf
->evpn_info
->advertise_pip
= false;
4224 /* copy anycast mac */
4225 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4226 &bgp_vrf
->rmac
, ETH_ALEN
);
4228 /* remove MAC-IP option retain PIP knob. */
4229 if ((ip
.s_addr
!= INADDR_ANY
) &&
4230 !IPV4_ADDR_SAME(&ip
,
4231 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4233 "%% BGP EVPN PIP IP does not match\n");
4234 return CMD_WARNING_CONFIG_FAILED
;
4237 if (!is_zero_mac(&mac
->eth_addr
) &&
4238 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4239 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4241 "%% BGP EVPN PIP MAC does not match\n");
4242 return CMD_WARNING_CONFIG_FAILED
;
4244 /* pip_rmac can carry vrr_rmac reset only if it matches
4245 * with static value.
4247 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4248 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4250 /* Copy zebra sys mac */
4252 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4253 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4254 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4257 /* copy anycast mac */
4258 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4259 &bgp_vrf
->rmac
, ETH_ALEN
);
4263 /* reset user configured sys MAC */
4264 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4265 /* reset user configured sys IP */
4266 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4267 /* Assign default PIP IP (bgp instance router-id) */
4269 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4271 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4274 if (is_evpn_enabled()) {
4275 struct listnode
*node
= NULL
;
4276 struct bgpevpn
*vpn
= NULL
;
4279 * At this point if bgp_evpn is NULL and evpn is enabled
4280 * something stupid has gone wrong
4284 update_advertise_vrf_routes(bgp_vrf
);
4286 /* Update (svi) type-2 routes */
4287 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4288 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4290 update_routes_for_vni(bgp_evpn
, vpn
);
4298 * Display VNI information - for all or a specific VNI
4300 DEFUN(show_bgp_l2vpn_evpn_vni
,
4301 show_bgp_l2vpn_evpn_vni_cmd
,
4302 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4311 struct bgp
*bgp_evpn
;
4315 json_object
*json
= NULL
;
4316 uint32_t num_l2vnis
= 0;
4317 uint32_t num_l3vnis
= 0;
4318 uint32_t num_vnis
= 0;
4319 struct listnode
*node
= NULL
;
4320 struct bgp
*bgp_temp
= NULL
;
4322 uj
= use_json(argc
, argv
);
4324 bgp_evpn
= bgp_get_evpn();
4328 if (!argv_find(argv
, argc
, "evpn", &idx
))
4332 json
= json_object_new_object();
4334 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4336 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4338 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4339 if (bgp_temp
->l3vni
)
4342 num_vnis
= num_l2vnis
+ num_l3vnis
;
4344 json_object_string_add(json
, "advertiseGatewayMacip",
4345 bgp_evpn
->advertise_gw_macip
4348 json_object_string_add(json
, "advertiseSviMacIp",
4349 bgp_evpn
->evpn_info
->advertise_svi_macip
4350 ? "Enabled" : "Disabled");
4351 json_object_string_add(json
, "advertiseAllVnis",
4352 is_evpn_enabled() ? "Enabled"
4354 json_object_string_add(
4356 bgp_evpn
->vxlan_flood_ctrl
4357 == VXLAN_FLOOD_HEAD_END_REPL
4358 ? "Head-end replication"
4360 json_object_int_add(json
, "numVnis", num_vnis
);
4361 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4362 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4364 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4365 bgp_evpn
->advertise_gw_macip
? "Enabled"
4367 vty_out(vty
, "Advertise SVI Macip: %s\n",
4368 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4370 vty_out(vty
, "Advertise All VNI flag: %s\n",
4371 is_evpn_enabled() ? "Enabled" : "Disabled");
4372 vty_out(vty
, "BUM flooding: %s\n",
4373 bgp_evpn
->vxlan_flood_ctrl
4374 == VXLAN_FLOOD_HEAD_END_REPL
4375 ? "Head-end replication"
4377 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4378 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4380 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4384 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4387 /* Display specific VNI */
4388 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4389 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4393 vty_json(vty
, json
);
4398 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4399 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4400 "show bgp l2vpn evpn vni remote-ip-hash",
4408 struct bgp
*bgp_evpn
;
4411 bgp_evpn
= bgp_get_evpn();
4415 if (!argv_find(argv
, argc
, "evpn", &idx
))
4418 hash_iterate(bgp_evpn
->vnihash
,
4419 (void (*)(struct hash_bucket
*,
4420 void *))bgp_evpn_show_remote_ip_hash
,
4426 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4427 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4428 "show bgp l2vpn evpn vni-svi-hash",
4433 "Show vni-svi-hash\n")
4435 struct bgp
*bgp_evpn
;
4438 bgp_evpn
= bgp_get_evpn();
4442 if (!argv_find(argv
, argc
, "evpn", &idx
))
4445 hash_iterate(bgp_evpn
->vni_svi_hash
,
4446 (void (*)(struct hash_bucket
*,
4447 void *))bgp_evpn_show_vni_svi_hash
,
4453 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4454 show_bgp_l2vpn_evpn_es_evi_cmd
,
4455 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4461 "VxLAN Network Identifier\n"
4464 "Detailed information\n")
4467 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4469 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4474 DEFPY(show_bgp_l2vpn_evpn_es
,
4475 show_bgp_l2vpn_evpn_es_cmd
,
4476 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4481 "Ethernet Segment\n"
4483 "Detailed information\n"
4489 if (!str_to_esi(esi_str
, &esi
)) {
4490 vty_out(vty
, "%%Malformed ESI\n");
4493 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4496 bgp_evpn_es_show(vty
, uj
, !!detail
);
4502 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4503 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4504 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4505 "Ethernet Segment\n"
4511 if (!str_to_esi(esi_str
, &esi
)) {
4512 vty_out(vty
, "%%Malformed ESI\n");
4515 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4518 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4524 DEFPY(show_bgp_l2vpn_evpn_nh
,
4525 show_bgp_l2vpn_evpn_nh_cmd
,
4526 "show bgp l2vpn evpn next-hops [json$uj]",
4534 bgp_evpn_nh_show(vty
, uj
);
4540 * Display EVPN neighbor summary.
4542 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4543 "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]",
4546 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4547 "Summary of BGP neighbor status\n"
4548 "Show only sessions in Established state\n"
4549 "Show only sessions not in Established state\n"
4550 "Show only the specified neighbor session\n"
4551 "Neighbor to display information about\n"
4552 "Neighbor to display information about\n"
4553 "Neighbor on BGP configured interface\n"
4554 "Show only the specified remote AS sessions\n"
4556 "Internal (iBGP) AS sessions\n"
4557 "External (eBGP) AS sessions\n"
4558 "Shorten the information on BGP instances\n"
4559 "Increase table width for longer output\n" JSON_STR
)
4564 char *neighbor
= NULL
;
4565 as_t as
= 0; /* 0 means AS filter not set */
4566 int as_type
= AS_UNSPECIFIED
;
4567 uint16_t show_flags
= 0;
4569 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4570 vrf
= argv
[++idx_vrf
]->arg
;
4572 if (argv_find(argv
, argc
, "failed", &idx
))
4573 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4575 if (argv_find(argv
, argc
, "established", &idx
))
4576 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4579 if (argv_find(argv
, argc
, "neighbor", &idx
))
4580 neighbor
= argv
[idx
+ 1]->arg
;
4582 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4583 if (argv
[idx
+ 1]->arg
[0] == 'i')
4584 as_type
= AS_INTERNAL
;
4585 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4586 as_type
= AS_EXTERNAL
;
4588 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4591 if (argv_find(argv
, argc
, "terse", &idx
))
4592 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4594 if (argv_find(argv
, argc
, "wide", &idx
))
4595 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4597 if (use_json(argc
, argv
))
4598 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4600 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4601 as_type
, as
, show_flags
);
4604 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4608 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4609 /* Specific type is requested */
4610 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4611 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4612 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4613 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4614 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4615 *type
= BGP_EVPN_IMET_ROUTE
;
4616 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4617 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4618 *type
= BGP_EVPN_ES_ROUTE
;
4619 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4620 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4621 *type
= BGP_EVPN_AD_ROUTE
;
4622 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4623 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4624 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4633 * Display global EVPN routing table.
4635 DEFUN(show_bgp_l2vpn_evpn_route
,
4636 show_bgp_l2vpn_evpn_route_cmd
,
4637 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4643 "Display Detailed Information\n"
4645 EVPN_TYPE_ALL_LIST_HELP_STR
4652 json_object
*json
= NULL
;
4654 uj
= use_json(argc
, argv
);
4656 bgp
= bgp_get_evpn();
4661 json
= json_object_new_object();
4663 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4666 if (argv_find(argv
, argc
, "detail", &detail
))
4669 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4672 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
);
4739 * Display global EVPN routing table for specific RD and MACIP.
4741 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4742 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4743 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4749 EVPN_RT_DIST_HELP_STR
4750 EVPN_ASN_IP_HELP_STR
4751 "All VPN Route Distinguishers\n"
4753 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4755 "IP address (IPv4 or IPv6)\n"
4760 struct prefix_rd prd
;
4763 int idx_ext_community
= 0;
4767 json_object
*json
= NULL
;
4770 memset(&mac
, 0, sizeof(struct ethaddr
));
4771 memset(&ip
, 0, sizeof(struct ipaddr
));
4773 bgp
= bgp_get_evpn();
4777 /* check if we need json output */
4778 uj
= use_json(argc
, argv
);
4780 json
= json_object_new_object();
4783 argv_find(argv
, argc
, "all", &rd_all
);
4785 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4786 &idx_ext_community
);
4787 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4789 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4795 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4796 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4797 vty_out(vty
, "%% Malformed MAC address\n");
4802 /* get the ip if specified */
4803 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4804 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4805 vty_out(vty
, "%% Malformed IP address\n");
4811 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4813 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4816 vty_json(vty
, json
);
4821 /* Display per ESI routing table */
4822 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4823 show_bgp_l2vpn_evpn_route_esi_cmd
,
4824 "show bgp l2vpn evpn route esi ESI [json]",
4830 "Ethernet Segment Identifier\n"
4836 struct bgp
*bgp
= NULL
;
4837 json_object
*json
= NULL
;
4839 memset(&esi
, 0, sizeof(esi
));
4840 bgp
= bgp_get_evpn();
4844 uj
= use_json(argc
, argv
);
4846 json
= json_object_new_object();
4848 /* get the ESI - ESI-ID is at argv[6] */
4849 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4850 vty_out(vty
, "%% Malformed ESI\n");
4854 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4857 vty_json(vty
, json
);
4864 * Display per-VNI EVPN routing table.
4866 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4867 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4873 "VXLAN Network Identifier\n"
4876 EVPN_TYPE_1_HELP_STR
4877 EVPN_TYPE_1_HELP_STR
4878 EVPN_TYPE_2_HELP_STR
4879 EVPN_TYPE_2_HELP_STR
4880 EVPN_TYPE_3_HELP_STR
4881 EVPN_TYPE_3_HELP_STR
4883 "Remote VTEP IP address\n"
4888 struct in_addr vtep_ip
;
4893 json_object
*json
= NULL
;
4895 bgp
= bgp_get_evpn();
4899 /* check if we need json output */
4900 uj
= use_json(argc
, argv
);
4902 json
= json_object_new_object();
4904 if (!argv_find(argv
, argc
, "evpn", &idx
))
4909 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4911 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4914 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4915 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4916 vty_out(vty
, "%% Malformed VTEP IP address\n");
4921 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4924 vty_json(vty
, json
);
4930 * Display per-VNI EVPN routing table for specific MACIP.
4932 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4933 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4934 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4940 "VXLAN Network Identifier\n"
4943 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4945 "IP address (IPv4 or IPv6)\n"
4954 json_object
*json
= NULL
;
4956 bgp
= bgp_get_evpn();
4960 /* check if we need json output */
4961 uj
= use_json(argc
, argv
);
4963 json
= json_object_new_object();
4965 if (!argv_find(argv
, argc
, "evpn", &idx
))
4969 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4972 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4973 vty_out(vty
, "%% Malformed MAC address\n");
4978 memset(&ip
, 0, sizeof(ip
));
4979 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4981 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4982 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4983 vty_out(vty
, "%% Malformed IP address\n");
4988 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4991 vty_json(vty
, json
);
4997 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4999 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5000 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5001 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5007 "VXLAN Network Identifier\n"
5009 EVPN_TYPE_3_HELP_STR
5010 "Originating Router IP address\n"
5016 struct in_addr orig_ip
;
5019 json_object
*json
= NULL
;
5021 bgp
= bgp_get_evpn();
5025 /* check if we need json output */
5026 uj
= use_json(argc
, argv
);
5028 json
= json_object_new_object();
5030 if (!argv_find(argv
, argc
, "evpn", &idx
))
5034 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5037 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5039 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5043 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5046 vty_json(vty
, json
);
5052 * Display per-VNI EVPN routing table - for all VNIs.
5054 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5055 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5056 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5062 "VXLAN Network Identifier\n"
5064 "Print Detailed Output\n"
5066 "Remote VTEP IP address\n"
5070 struct in_addr vtep_ip
;
5073 json_object
*json
= NULL
;
5074 /* Detail Adjust. Adjust indexes according to detail option */
5077 bgp
= bgp_get_evpn();
5081 /* check if we need json output */
5082 uj
= use_json(argc
, argv
);
5084 json
= json_object_new_object();
5086 if (!argv_find(argv
, argc
, "evpn", &idx
))
5089 if (argv_find(argv
, argc
, "detail", &da
))
5092 /* vtep-ip position depends on detail option */
5094 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5096 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5097 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5098 vty_out(vty
, "%% Malformed VTEP IP address\n");
5103 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5106 vty_json(vty
, json
);
5112 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5113 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5114 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5115 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5116 "EVPN route information\n"
5117 "MAC IP routes in the EVI tables linked to the ES\n"
5119 "Detailed information\n" JSON_STR
)
5123 json_object
*json
= NULL
;
5126 if (!str_to_esi(esi_str
, &esi
)) {
5127 vty_out(vty
, "%%Malformed ESI\n");
5136 json
= json_object_new_object();
5137 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5139 vty_json(vty
, json
);
5145 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5146 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5147 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5148 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5149 "EVPN route information\n"
5150 "MAC IP routes in the global table linked to the ES\n"
5152 "Detailed information\n" JSON_STR
)
5156 json_object
*json
= NULL
;
5159 if (!str_to_esi(esi_str
, &esi
)) {
5160 vty_out(vty
, "%%Malformed ESI\n");
5169 json
= json_object_new_object();
5170 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5172 vty_json(vty
, json
);
5178 * Display EVPN import route-target hash table
5180 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5181 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5182 "show bgp l2vpn evpn vrf-import-rt [json]",
5187 "Show vrf import route target\n"
5191 struct bgp
*bgp_evpn
= NULL
;
5192 json_object
*json
= NULL
;
5194 bgp_evpn
= bgp_get_evpn();
5198 uj
= use_json(argc
, argv
);
5200 json
= json_object_new_object();
5202 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5205 vty_json(vty
, json
);
5211 * Display EVPN import route-target hash table
5213 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5214 show_bgp_l2vpn_evpn_import_rt_cmd
,
5215 "show bgp l2vpn evpn import-rt [json]",
5220 "Show import route target\n"
5225 json_object
*json
= NULL
;
5227 bgp
= bgp_get_evpn();
5231 uj
= use_json(argc
, argv
);
5233 json
= json_object_new_object();
5235 evpn_show_import_rts(vty
, bgp
, json
);
5238 vty_json(vty
, json
);
5243 DEFPY_HIDDEN(test_es_add
,
5245 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5248 "Ethernet-segment\n"
5249 "Ethernet-Segment Identifier\n"
5257 struct in_addr vtep_ip
;
5260 bgp
= bgp_get_evpn();
5262 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5266 if (!str_to_esi(esi_str
, &esi
)) {
5267 vty_out(vty
, "%%Malformed ESI\n");
5272 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5274 vty_out(vty
, "%%Failed to delete ES\n");
5278 if (state_str
&& !strcmp(state_str
, "up"))
5282 vtep_ip
= bgp
->router_id
;
5284 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5285 EVPN_MH_DF_PREF_MIN
, false);
5287 vty_out(vty
, "%%Failed to add ES\n");
5294 DEFPY_HIDDEN(test_es_vni_add
,
5295 test_es_vni_add_cmd
,
5296 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5299 "Ethernet-segment\n"
5300 "Ethernet-Segment Identifier\n"
5309 bgp
= bgp_get_evpn();
5311 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5315 if (!str_to_esi(esi_str
, &esi
)) {
5316 vty_out(vty
, "%%Malformed ESI\n");
5321 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5323 vty_out(vty
, "%%Failed to deref ES VNI\n");
5327 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5329 vty_out(vty
, "%%Failed to ref ES VNI\n");
5336 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5337 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5341 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5342 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5343 "Summary of BGP neighbor status\n" JSON_STR
)
5345 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5346 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5347 SHOW_STR BGP_STR EVPN_HELP_STR
5349 "Display Detailed Information\n"
5351 EVPN_TYPE_2_HELP_STR
5352 EVPN_TYPE_2_HELP_STR
5353 EVPN_TYPE_3_HELP_STR
5354 EVPN_TYPE_3_HELP_STR
)
5357 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5358 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5359 SHOW_STR BGP_STR EVPN_HELP_STR
5361 EVPN_RT_DIST_HELP_STR
5362 EVPN_ASN_IP_HELP_STR
5364 EVPN_TYPE_2_HELP_STR
5365 EVPN_TYPE_2_HELP_STR
5366 EVPN_TYPE_3_HELP_STR
5367 EVPN_TYPE_3_HELP_STR
)
5370 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5371 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5372 SHOW_STR BGP_STR EVPN_HELP_STR
5374 EVPN_RT_DIST_HELP_STR
5375 EVPN_ASN_IP_HELP_STR
5377 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5379 "IP address (IPv4 or IPv6)\n")
5382 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5383 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5384 SHOW_STR BGP_STR EVPN_HELP_STR
5386 "VXLAN Network Identifier\n"
5389 EVPN_TYPE_2_HELP_STR
5390 EVPN_TYPE_2_HELP_STR
5391 EVPN_TYPE_3_HELP_STR
5392 EVPN_TYPE_3_HELP_STR
5394 "Remote VTEP IP address\n")
5396 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5397 show_bgp_evpn_route_vni_macip_cmd
,
5398 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5399 SHOW_STR BGP_STR EVPN_HELP_STR
5401 "VXLAN Network Identifier\n"
5404 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5406 "IP address (IPv4 or IPv6)\n")
5408 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5409 show_bgp_evpn_route_vni_multicast_cmd
,
5410 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5411 SHOW_STR BGP_STR EVPN_HELP_STR
5413 "VXLAN Network Identifier\n"
5415 EVPN_TYPE_3_HELP_STR
5416 "Originating Router IP address\n")
5418 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5419 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5420 SHOW_STR BGP_STR EVPN_HELP_STR
5422 "VXLAN Network Identifier\n"
5424 "Print Detailed Output\n"
5426 "Remote VTEP IP address\n")
5428 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5429 "show bgp evpn import-rt",
5430 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5432 DEFUN_NOSH (bgp_evpn_vni
,
5434 "vni " CMD_VNI_RANGE
,
5435 "VXLAN Network Identifier\n"
5439 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5440 struct bgpevpn
*vpn
;
5445 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5447 /* Create VNI, or mark as configured. */
5448 vpn
= evpn_create_update_vni(bgp
, vni
);
5450 vty_out(vty
, "%% Failed to create VNI \n");
5454 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5458 DEFUN (no_bgp_evpn_vni
,
5459 no_bgp_evpn_vni_cmd
,
5460 "no vni " CMD_VNI_RANGE
,
5462 "VXLAN Network Identifier\n"
5466 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5467 struct bgpevpn
*vpn
;
5472 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5474 /* Check if we should disallow. */
5475 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5477 vty_out(vty
, "%% Specified VNI does not exist\n");
5480 if (!is_vni_configured(vpn
)) {
5481 vty_out(vty
, "%% Specified VNI is not configured\n");
5485 evpn_delete_vni(bgp
, vpn
);
5489 DEFUN_NOSH (exit_vni
,
5492 "Exit from VNI mode\n")
5494 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5495 vty
->node
= BGP_EVPN_NODE
;
5499 DEFUN (bgp_evpn_vrf_rd
,
5500 bgp_evpn_vrf_rd_cmd
,
5501 "rd ASN:NN_OR_IP-ADDRESS:NN",
5502 EVPN_RT_DIST_HELP_STR
5503 EVPN_ASN_IP_HELP_STR
)
5506 struct prefix_rd prd
;
5507 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5512 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5514 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5518 /* If same as existing value, there is nothing more to do. */
5519 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5522 /* Configure or update the RD. */
5523 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5527 DEFUN (no_bgp_evpn_vrf_rd
,
5528 no_bgp_evpn_vrf_rd_cmd
,
5529 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5531 EVPN_RT_DIST_HELP_STR
5532 EVPN_ASN_IP_HELP_STR
)
5535 struct prefix_rd prd
;
5536 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5541 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5543 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5547 /* Check if we should disallow. */
5548 if (!is_vrf_rd_configured(bgp_vrf
)) {
5549 vty_out(vty
, "%% RD is not configured for this VRF\n");
5553 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5555 "%% RD specified does not match configuration for this VRF\n");
5559 evpn_unconfigure_vrf_rd(bgp_vrf
);
5563 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5564 no_bgp_evpn_vrf_rd_without_val_cmd
,
5567 EVPN_RT_DIST_HELP_STR
)
5569 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5574 /* Check if we should disallow. */
5575 if (!is_vrf_rd_configured(bgp_vrf
)) {
5576 vty_out(vty
, "%% RD is not configured for this VRF\n");
5580 evpn_unconfigure_vrf_rd(bgp_vrf
);
5584 DEFUN (bgp_evpn_vni_rd
,
5585 bgp_evpn_vni_rd_cmd
,
5586 "rd ASN:NN_OR_IP-ADDRESS:NN",
5587 EVPN_RT_DIST_HELP_STR
5588 EVPN_ASN_IP_HELP_STR
)
5590 struct prefix_rd prd
;
5591 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5592 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5598 if (!EVPN_ENABLED(bgp
)) {
5600 "This command is only supported under EVPN VRF\n");
5604 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5606 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5610 /* If same as existing value, there is nothing more to do. */
5611 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5614 /* Configure or update the RD. */
5615 evpn_configure_rd(bgp
, vpn
, &prd
);
5619 DEFUN (no_bgp_evpn_vni_rd
,
5620 no_bgp_evpn_vni_rd_cmd
,
5621 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5623 EVPN_RT_DIST_HELP_STR
5624 EVPN_ASN_IP_HELP_STR
)
5626 struct prefix_rd prd
;
5627 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5628 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5634 if (!EVPN_ENABLED(bgp
)) {
5636 "This command is only supported under EVPN VRF\n");
5640 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5642 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5646 /* Check if we should disallow. */
5647 if (!is_rd_configured(vpn
)) {
5648 vty_out(vty
, "%% RD is not configured for this VNI\n");
5652 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5654 "%% RD specified does not match configuration for this VNI\n");
5658 evpn_unconfigure_rd(bgp
, vpn
);
5662 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5663 no_bgp_evpn_vni_rd_without_val_cmd
,
5666 EVPN_RT_DIST_HELP_STR
)
5668 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5669 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5674 if (!EVPN_ENABLED(bgp
)) {
5676 "This command is only supported under EVPN VRF\n");
5680 /* Check if we should disallow. */
5681 if (!is_rd_configured(vpn
)) {
5682 vty_out(vty
, "%% RD is not configured for this VNI\n");
5686 evpn_unconfigure_rd(bgp
, vpn
);
5691 * Loop over all extended-communities in the route-target list rtl and
5692 * return 1 if we find ecomtarget
5694 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5695 struct ecommunity
*ecomtarget
)
5697 struct listnode
*node
, *nnode
;
5698 struct ecommunity
*ecom
;
5700 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5701 if (ecommunity_match(ecom
, ecomtarget
))
5708 /* display L3VNI related info for a VRF instance */
5709 DEFUN (show_bgp_vrf_l3vni_info
,
5710 show_bgp_vrf_l3vni_info_cmd
,
5711 "show bgp vrf VRFNAME vni [json]",
5719 char buf
[ETHER_ADDR_STRLEN
];
5720 char buf1
[INET6_ADDRSTRLEN
];
5722 const char *name
= NULL
;
5723 struct bgp
*bgp
= NULL
;
5724 struct listnode
*node
= NULL
;
5725 struct bgpevpn
*vpn
= NULL
;
5726 struct ecommunity
*ecom
= NULL
;
5727 json_object
*json
= NULL
;
5728 json_object
*json_vnis
= NULL
;
5729 json_object
*json_export_rts
= NULL
;
5730 json_object
*json_import_rts
= NULL
;
5731 bool uj
= use_json(argc
, argv
);
5734 json
= json_object_new_object();
5735 json_vnis
= json_object_new_array();
5736 json_export_rts
= json_object_new_array();
5737 json_import_rts
= json_object_new_array();
5740 name
= argv
[idx_vrf
]->arg
;
5741 bgp
= bgp_lookup_by_name(name
);
5744 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5746 json_object_string_add(json
, "warning",
5747 "BGP instance not found");
5748 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5749 json_object_free(json
);
5755 vty_out(vty
, "BGP VRF: %s\n", name
);
5756 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5757 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5758 vty_out(vty
, " Rmac: %s\n",
5759 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5760 vty_out(vty
, " VNI Filter: %s\n",
5761 CHECK_FLAG(bgp
->vrf_flags
,
5762 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5763 ? "prefix-routes-only"
5765 vty_out(vty
, " L2-VNI List:\n");
5767 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5768 vty_out(vty
, "%u ", vpn
->vni
);
5770 vty_out(vty
, " Export-RTs:\n");
5772 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5773 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5775 vty_out(vty
, " Import-RTs:\n");
5777 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5778 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5780 vty_out(vty
, " RD: %s\n",
5781 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5783 json_object_string_add(json
, "vrf", name
);
5784 json_object_string_addf(json
, "local-ip", "%pI4",
5785 &bgp
->originator_ip
);
5786 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5787 json_object_string_add(
5789 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5790 json_object_string_add(
5792 CHECK_FLAG(bgp
->vrf_flags
,
5793 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5794 ? "prefix-routes-only"
5796 /* list of l2vnis */
5797 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5798 json_object_array_add(json_vnis
,
5799 json_object_new_int(vpn
->vni
));
5800 json_object_object_add(json
, "l2vnis", json_vnis
);
5803 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5804 json_object_array_add(
5806 json_object_new_string(ecommunity_str(ecom
)));
5807 json_object_object_add(json
, "export-rts", json_export_rts
);
5810 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5811 json_object_array_add(
5813 json_object_new_string(ecommunity_str(ecom
)));
5814 json_object_object_add(json
, "import-rts", json_import_rts
);
5815 json_object_string_add(
5817 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5821 vty_json(vty
, json
);
5825 /* import/export rt for l3vni-vrf */
5826 DEFUN (bgp_evpn_vrf_rt
,
5827 bgp_evpn_vrf_rt_cmd
,
5828 "route-target <both|import|export> RT",
5830 "import and export\n"
5833 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5836 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5837 struct ecommunity
*ecomadd
= NULL
;
5842 if (!strcmp(argv
[1]->arg
, "import"))
5843 rt_type
= RT_TYPE_IMPORT
;
5844 else if (!strcmp(argv
[1]->arg
, "export"))
5845 rt_type
= RT_TYPE_EXPORT
;
5846 else if (!strcmp(argv
[1]->arg
, "both"))
5847 rt_type
= RT_TYPE_BOTH
;
5849 vty_out(vty
, "%% Invalid Route Target type\n");
5853 /* Add/update the import route-target */
5854 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5855 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5856 ECOMMUNITY_ROUTE_TARGET
, 0);
5858 vty_out(vty
, "%% Malformed Route Target list\n");
5861 ecommunity_str(ecomadd
);
5863 /* Do nothing if we already have this import route-target */
5864 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5865 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5868 /* Add/update the export route-target */
5869 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5870 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5871 ECOMMUNITY_ROUTE_TARGET
, 0);
5873 vty_out(vty
, "%% Malformed Route Target list\n");
5876 ecommunity_str(ecomadd
);
5878 /* Do nothing if we already have this export route-target */
5879 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5880 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5886 DEFUN (no_bgp_evpn_vrf_rt
,
5887 no_bgp_evpn_vrf_rt_cmd
,
5888 "no route-target <both|import|export> RT",
5891 "import and export\n"
5894 EVPN_ASN_IP_HELP_STR
)
5896 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5897 int rt_type
, found_ecomdel
;
5898 struct ecommunity
*ecomdel
= NULL
;
5903 if (!strcmp(argv
[2]->arg
, "import"))
5904 rt_type
= RT_TYPE_IMPORT
;
5905 else if (!strcmp(argv
[2]->arg
, "export"))
5906 rt_type
= RT_TYPE_EXPORT
;
5907 else if (!strcmp(argv
[2]->arg
, "both"))
5908 rt_type
= RT_TYPE_BOTH
;
5910 vty_out(vty
, "%% Invalid Route Target type\n");
5914 if (rt_type
== RT_TYPE_IMPORT
) {
5915 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5917 "%% Import RT is not configured for this VRF\n");
5920 } else if (rt_type
== RT_TYPE_EXPORT
) {
5921 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5923 "%% Export RT is not configured for this VRF\n");
5926 } else if (rt_type
== RT_TYPE_BOTH
) {
5927 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5928 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5930 "%% Import/Export RT is not configured for this VRF\n");
5935 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5937 vty_out(vty
, "%% Malformed Route Target list\n");
5940 ecommunity_str(ecomdel
);
5942 if (rt_type
== RT_TYPE_IMPORT
) {
5943 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5945 ecommunity_free(&ecomdel
);
5947 "%% RT specified does not match configuration for this VRF\n");
5950 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5951 } else if (rt_type
== RT_TYPE_EXPORT
) {
5952 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5954 ecommunity_free(&ecomdel
);
5956 "%% RT specified does not match configuration for this VRF\n");
5959 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5960 } else if (rt_type
== RT_TYPE_BOTH
) {
5963 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5965 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5969 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5971 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5975 if (!found_ecomdel
) {
5976 ecommunity_free(&ecomdel
);
5978 "%% RT specified does not match configuration for this VRF\n");
5983 ecommunity_free(&ecomdel
);
5987 DEFUN (bgp_evpn_vni_rt
,
5988 bgp_evpn_vni_rt_cmd
,
5989 "route-target <both|import|export> RT",
5991 "import and export\n"
5994 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5996 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5997 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5999 struct ecommunity
*ecomadd
= NULL
;
6004 if (!EVPN_ENABLED(bgp
)) {
6006 "This command is only supported under EVPN VRF\n");
6010 if (!strcmp(argv
[1]->text
, "import"))
6011 rt_type
= RT_TYPE_IMPORT
;
6012 else if (!strcmp(argv
[1]->text
, "export"))
6013 rt_type
= RT_TYPE_EXPORT
;
6014 else if (!strcmp(argv
[1]->text
, "both"))
6015 rt_type
= RT_TYPE_BOTH
;
6017 vty_out(vty
, "%% Invalid Route Target type\n");
6021 /* Add/update the import route-target */
6022 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6023 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6024 ECOMMUNITY_ROUTE_TARGET
, 0);
6026 vty_out(vty
, "%% Malformed Route Target list\n");
6029 ecommunity_str(ecomadd
);
6031 /* Do nothing if we already have this import route-target */
6032 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6033 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6036 /* Add/update the export route-target */
6037 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6038 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6039 ECOMMUNITY_ROUTE_TARGET
, 0);
6041 vty_out(vty
, "%% Malformed Route Target list\n");
6044 ecommunity_str(ecomadd
);
6046 /* Do nothing if we already have this export route-target */
6047 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6048 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6054 DEFUN (no_bgp_evpn_vni_rt
,
6055 no_bgp_evpn_vni_rt_cmd
,
6056 "no route-target <both|import|export> RT",
6059 "import and export\n"
6062 EVPN_ASN_IP_HELP_STR
)
6064 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6065 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6066 int rt_type
, found_ecomdel
;
6067 struct ecommunity
*ecomdel
= NULL
;
6072 if (!EVPN_ENABLED(bgp
)) {
6074 "This command is only supported under EVPN VRF\n");
6078 if (!strcmp(argv
[2]->text
, "import"))
6079 rt_type
= RT_TYPE_IMPORT
;
6080 else if (!strcmp(argv
[2]->text
, "export"))
6081 rt_type
= RT_TYPE_EXPORT
;
6082 else if (!strcmp(argv
[2]->text
, "both"))
6083 rt_type
= RT_TYPE_BOTH
;
6085 vty_out(vty
, "%% Invalid Route Target type\n");
6089 /* The user did "no route-target import", check to see if there are any
6090 * import route-targets configured. */
6091 if (rt_type
== RT_TYPE_IMPORT
) {
6092 if (!is_import_rt_configured(vpn
)) {
6094 "%% Import RT is not configured for this VNI\n");
6097 } else if (rt_type
== RT_TYPE_EXPORT
) {
6098 if (!is_export_rt_configured(vpn
)) {
6100 "%% Export RT is not configured for this VNI\n");
6103 } else if (rt_type
== RT_TYPE_BOTH
) {
6104 if (!is_import_rt_configured(vpn
)
6105 && !is_export_rt_configured(vpn
)) {
6107 "%% Import/Export RT is not configured for this VNI\n");
6112 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6114 vty_out(vty
, "%% Malformed Route Target list\n");
6117 ecommunity_str(ecomdel
);
6119 if (rt_type
== RT_TYPE_IMPORT
) {
6120 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6122 "%% RT specified does not match configuration for this VNI\n");
6125 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6126 } else if (rt_type
== RT_TYPE_EXPORT
) {
6127 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6129 "%% RT specified does not match configuration for this VNI\n");
6132 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6133 } else if (rt_type
== RT_TYPE_BOTH
) {
6136 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6137 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6141 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6142 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6146 if (!found_ecomdel
) {
6148 "%% RT specified does not match configuration for this VNI\n");
6156 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6157 no_bgp_evpn_vni_rt_without_val_cmd
,
6158 "no route-target <import|export>",
6164 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6165 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6171 if (!EVPN_ENABLED(bgp
)) {
6173 "This command is only supported under EVPN VRF\n");
6177 if (!strcmp(argv
[2]->text
, "import")) {
6178 rt_type
= RT_TYPE_IMPORT
;
6179 } else if (!strcmp(argv
[2]->text
, "export")) {
6180 rt_type
= RT_TYPE_EXPORT
;
6182 vty_out(vty
, "%% Invalid Route Target type\n");
6186 /* Check if we should disallow. */
6187 if (rt_type
== RT_TYPE_IMPORT
) {
6188 if (!is_import_rt_configured(vpn
)) {
6190 "%% Import RT is not configured for this VNI\n");
6194 if (!is_export_rt_configured(vpn
)) {
6196 "%% Export RT is not configured for this VNI\n");
6201 /* Unconfigure the RT. */
6202 if (rt_type
== RT_TYPE_IMPORT
)
6203 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6205 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6209 static int vni_cmp(const void **a
, const void **b
)
6211 const struct bgpevpn
*first
= *a
;
6212 const struct bgpevpn
*secnd
= *b
;
6214 return secnd
->vni
- first
->vni
;
6218 * Output EVPN configuration information.
6220 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6223 char buf1
[RD_ADDRSTRLEN
];
6224 char buf2
[INET6_ADDRSTRLEN
];
6226 if (bgp
->advertise_all_vni
)
6227 vty_out(vty
, " advertise-all-vni\n");
6230 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6231 struct listnode
*ln
;
6232 struct bgpevpn
*data
;
6234 list_sort(vnilist
, vni_cmp
);
6235 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6236 write_vni_config(vty
, data
);
6238 list_delete(&vnilist
);
6241 if (bgp
->advertise_autort_rfc8365
)
6242 vty_out(vty
, " autort rfc8365-compatible\n");
6244 if (bgp
->advertise_gw_macip
)
6245 vty_out(vty
, " advertise-default-gw\n");
6247 if (bgp
->evpn_info
->advertise_svi_macip
)
6248 vty_out(vty
, " advertise-svi-ip\n");
6250 if (bgp
->resolve_overlay_index
)
6251 vty_out(vty
, " enable-resolve-overlay-index\n");
6253 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6254 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6255 if (bgp_mh_info
->host_routes_use_l3nhg
)
6256 vty_out(vty
, " use-es-l3nhg\n");
6258 vty_out(vty
, " no use-es-l3nhg\n");
6261 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6262 if (bgp_mh_info
->ead_evi_rx
)
6263 vty_out(vty
, " no disable-ead-evi-rx\n");
6265 vty_out(vty
, " disable-ead-evi-rx\n");
6268 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6269 if (bgp_mh_info
->ead_evi_tx
)
6270 vty_out(vty
, " no disable-ead-evi-tx\n");
6272 vty_out(vty
, " disable-ead-evi-tx\n");
6275 if (!bgp
->evpn_info
->dup_addr_detect
)
6276 vty_out(vty
, " no dup-addr-detection\n");
6278 if (bgp
->evpn_info
->dad_max_moves
!=
6279 EVPN_DAD_DEFAULT_MAX_MOVES
||
6280 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6281 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6282 bgp
->evpn_info
->dad_max_moves
,
6283 bgp
->evpn_info
->dad_time
);
6285 if (bgp
->evpn_info
->dad_freeze
) {
6286 if (bgp
->evpn_info
->dad_freeze_time
)
6288 " dup-addr-detection freeze %u\n",
6289 bgp
->evpn_info
->dad_freeze_time
);
6292 " dup-addr-detection freeze permanent\n");
6295 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6296 vty_out(vty
, " flooding disable\n");
6298 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6299 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6300 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6301 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6302 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6305 " advertise ipv4 unicast\n");
6306 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6307 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6308 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6310 " advertise ipv4 unicast gateway-ip route-map %s\n",
6311 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6313 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6316 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6317 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6318 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6320 " advertise ipv6 unicast route-map %s\n",
6321 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6324 " advertise ipv6 unicast\n");
6325 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6326 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6327 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6329 " advertise ipv6 unicast gateway-ip route-map %s\n",
6330 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6332 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6335 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6336 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6337 vty_out(vty
, " default-originate ipv4\n");
6339 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6340 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6341 vty_out(vty
, " default-originate ipv6\n");
6343 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6344 if (!bgp
->evpn_info
->advertise_pip
)
6345 vty_out(vty
, " no advertise-pip\n");
6346 if (bgp
->evpn_info
->advertise_pip
) {
6347 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6349 vty_out(vty
, " advertise-pip ip %s",
6351 &bgp
->evpn_info
->pip_ip_static
,
6352 buf2
, INET_ADDRSTRLEN
));
6354 bgp
->evpn_info
->pip_rmac_static
))) {
6355 char buf
[ETHER_ADDR_STRLEN
];
6357 vty_out(vty
, " mac %s",
6367 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6368 vty_out(vty
, " rd %s\n",
6369 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6371 /* import route-target */
6372 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6374 struct listnode
*node
, *nnode
;
6375 struct ecommunity
*ecom
;
6377 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6379 ecom_str
= ecommunity_ecom2str(
6380 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6381 vty_out(vty
, " route-target import %s\n", ecom_str
);
6382 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6386 /* export route-target */
6387 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6389 struct listnode
*node
, *nnode
;
6390 struct ecommunity
*ecom
;
6392 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6394 ecom_str
= ecommunity_ecom2str(
6395 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6396 vty_out(vty
, " route-target export %s\n", ecom_str
);
6397 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6402 void bgp_ethernetvpn_init(void)
6404 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6405 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6406 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6407 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6408 install_element(VIEW_NODE
,
6409 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6410 install_element(VIEW_NODE
,
6411 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6414 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6417 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6418 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6419 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6420 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6421 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6422 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6423 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6424 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6425 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6426 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6427 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6428 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6429 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6430 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6431 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6432 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6433 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6434 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6435 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6436 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6437 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6438 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6439 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6440 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6441 install_element(BGP_EVPN_NODE
,
6442 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6445 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6446 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6448 /* "show bgp l2vpn evpn" commands. */
6449 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6450 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6451 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6452 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6453 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6454 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6455 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6456 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6457 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6458 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6459 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6460 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6461 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6462 install_element(VIEW_NODE
,
6463 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6464 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6465 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6466 install_element(VIEW_NODE
,
6467 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6468 install_element(VIEW_NODE
,
6469 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6470 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6471 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6473 /* "show bgp evpn" commands. */
6474 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6475 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6476 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6477 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6478 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6479 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6480 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6481 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6482 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6483 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6484 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6485 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6487 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6488 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6489 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6490 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6491 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6492 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6493 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6494 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6495 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6496 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6497 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6498 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6499 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6500 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6501 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6502 install_element(BGP_EVPN_VNI_NODE
,
6503 &bgp_evpn_advertise_default_gw_vni_cmd
);
6504 install_element(BGP_EVPN_VNI_NODE
,
6505 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6506 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6507 install_element(BGP_EVPN_VNI_NODE
,
6508 &no_bgp_evpn_advertise_vni_subnet_cmd
);