1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
62 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
63 enum overlay_index_type
*oly
)
65 *oly
= OVERLAY_INDEX_TYPE_NONE
;
66 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
67 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
71 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
75 uint8_t type
, sub_type
;
76 struct ecommunity_as eas
;
77 struct ecommunity_ip eip
;
78 struct listnode
*node
, *nnode
;
79 struct bgp
*tmp_bgp_vrf
= NULL
;
80 json_object
*json_rt
= NULL
;
81 json_object
*json_vrfs
= NULL
;
82 char rt_buf
[RT_ADDRSTRLEN
];
85 json_rt
= json_object_new_object();
86 json_vrfs
= json_object_new_array();
89 pnt
= (uint8_t *)&irt
->rt
.val
;
92 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
95 memset(&eas
, 0, sizeof(eas
));
97 case ECOMMUNITY_ENCODE_AS
:
98 eas
.as
= (*pnt
++ << 8);
100 ptr_get_be32(pnt
, &eas
.val
);
102 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
105 json_object_string_add(json_rt
, "rt", rt_buf
);
107 vty_out(vty
, "Route-target: %s", rt_buf
);
111 case ECOMMUNITY_ENCODE_IP
:
112 memcpy(&eip
.ip
, pnt
, 4);
114 eip
.val
= (*pnt
++ << 8);
117 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
126 case ECOMMUNITY_ENCODE_AS4
:
127 pnt
= ptr_get_be32(pnt
, &eas
.val
);
128 eas
.val
= (*pnt
++ << 8);
131 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
134 json_object_string_add(json_rt
, "rt", rt_buf
);
136 vty_out(vty
, "Route-target: %s", rt_buf
);
146 "\nList of VRFs importing routes with this route-target:\n");
149 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
151 json_object_array_add(
153 json_object_new_string(
154 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
156 vty_out(vty
, " %s\n",
157 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
161 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
162 json_object_object_add(json
, rt_buf
, json_rt
);
166 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
168 json_object
*json
= NULL
;
169 struct vty
*vty
= NULL
;
170 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
172 vty
= (struct vty
*)args
[0];
173 json
= (struct json_object
*)args
[1];
175 display_vrf_import_rt(vty
, irt
, json
);
178 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
182 uint8_t type
, sub_type
;
183 struct ecommunity_as eas
;
184 struct ecommunity_ip eip
;
185 struct listnode
*node
, *nnode
;
186 struct bgpevpn
*tmp_vpn
;
187 json_object
*json_rt
= NULL
;
188 json_object
*json_vnis
= NULL
;
189 char rt_buf
[RT_ADDRSTRLEN
];
192 json_rt
= json_object_new_object();
193 json_vnis
= json_object_new_array();
196 /* TODO: This needs to go into a function */
198 pnt
= (uint8_t *)&irt
->rt
.val
;
201 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
204 memset(&eas
, 0, sizeof(eas
));
206 case ECOMMUNITY_ENCODE_AS
:
207 eas
.as
= (*pnt
++ << 8);
209 ptr_get_be32(pnt
, &eas
.val
);
211 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
214 json_object_string_add(json_rt
, "rt", rt_buf
);
216 vty_out(vty
, "Route-target: %s", rt_buf
);
220 case ECOMMUNITY_ENCODE_IP
:
221 memcpy(&eip
.ip
, pnt
, 4);
223 eip
.val
= (*pnt
++ << 8);
226 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
229 json_object_string_add(json_rt
, "rt", rt_buf
);
231 vty_out(vty
, "Route-target: %s", rt_buf
);
235 case ECOMMUNITY_ENCODE_AS4
:
236 pnt
= ptr_get_be32(pnt
, &eas
.val
);
237 eas
.val
= (*pnt
++ << 8);
240 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
243 json_object_string_add(json_rt
, "rt", rt_buf
);
245 vty_out(vty
, "Route-target: %s", rt_buf
);
255 "\nList of VNIs importing routes with this route-target:\n");
258 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
260 json_object_array_add(
261 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
263 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
267 json_object_object_add(json_rt
, "vnis", json_vnis
);
268 json_object_object_add(json
, rt_buf
, json_rt
);
272 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
274 json_object
*json
= NULL
;
275 struct vty
*vty
= NULL
;
276 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
281 display_import_rt(vty
, irt
, json
);
286 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
287 struct bgp_dest
*rd_dest
,
288 json_object
*json
, char *rd_str
,
295 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
299 /* Decode RD type. */
300 type
= decode_rd_type(pnt
);
303 vty_out(vty
, "Route Distinguisher: ");
307 decode_rd_as(pnt
+ 2, &rd_as
);
308 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
310 json_object_string_add(json
, "rd", rd_str
);
312 vty_out(vty
, "%s\n", rd_str
);
316 decode_rd_as4(pnt
+ 2, &rd_as
);
317 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
325 decode_rd_ip(pnt
+ 2, &rd_ip
);
326 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
328 json_object_string_add(json
, "rd", rd_str
);
330 vty_out(vty
, "%s\n", rd_str
);
335 snprintf(rd_str
, len
, "Unknown");
336 json_object_string_add(json
, "rd", rd_str
);
338 snprintf(rd_str
, len
, "Unknown RD type");
339 vty_out(vty
, "%s\n", rd_str
);
345 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
346 uint64_t tbl_ver
, json_object
*json
)
349 " Network Next Hop Metric LocPrf Weight Path\n";
355 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
356 tbl_ver
, &bgp
->router_id
);
358 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
359 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
361 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]\n");
363 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
364 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
365 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
366 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
367 vty_out(vty
, "%s", ri_header
);
370 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
373 char buf1
[INET6_ADDRSTRLEN
];
375 struct listnode
*node
, *nnode
;
376 struct ecommunity
*ecom
;
377 json_object
*json_import_rtl
= NULL
;
378 json_object
*json_export_rtl
= NULL
;
379 char buf2
[ETHER_ADDR_STRLEN
];
381 json_import_rtl
= json_export_rtl
= 0;
384 json_import_rtl
= json_object_new_array();
385 json_export_rtl
= json_object_new_array();
386 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
387 json_object_string_add(json
, "type", "L3");
388 json_object_string_add(json
, "inKernel", "True");
389 json_object_string_add(
391 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
392 json_object_string_addf(json
, "originatorIp", "%pI4",
393 &bgp_vrf
->originator_ip
);
394 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
395 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
396 json_object_string_add(json
, "advertisePip",
397 bgp_vrf
->evpn_info
->advertise_pip
?
398 "Enabled" : "Disabled");
399 json_object_string_addf(json
, "sysIP", "%pI4",
400 &bgp_vrf
->evpn_info
->pip_ip
);
401 json_object_string_add(json
, "sysMac",
402 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
403 buf2
, sizeof(buf2
)));
404 json_object_string_add(json
, "rmac",
405 prefix_mac2str(&bgp_vrf
->rmac
,
406 buf2
, sizeof(buf2
)));
408 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
409 vty_out(vty
, " (known to the kernel)");
412 vty_out(vty
, " Type: %s\n", "L3");
413 vty_out(vty
, " Tenant VRF: %s\n",
414 vrf_id_to_name(bgp_vrf
->vrf_id
));
415 vty_out(vty
, " RD: %s\n",
416 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
417 vty_out(vty
, " Originator IP: %pI4\n",
418 &bgp_vrf
->originator_ip
);
419 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
420 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
421 vty_out(vty
, " Advertise-pip: %s\n",
422 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
423 vty_out(vty
, " System-IP: %s\n",
424 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
425 buf1
, INET_ADDRSTRLEN
));
426 vty_out(vty
, " System-MAC: %s\n",
427 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
428 buf2
, sizeof(buf2
)));
429 vty_out(vty
, " Router-MAC: %s\n",
430 prefix_mac2str(&bgp_vrf
->rmac
,
431 buf2
, sizeof(buf2
)));
435 vty_out(vty
, " Import Route Target:\n");
437 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
438 ecom_str
= ecommunity_ecom2str(ecom
,
439 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
442 json_object_array_add(json_import_rtl
,
443 json_object_new_string(ecom_str
));
445 vty_out(vty
, " %s\n", ecom_str
);
447 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
451 json_object_object_add(json
, "importRts", json_import_rtl
);
453 vty_out(vty
, " Export Route Target:\n");
455 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
456 ecom_str
= ecommunity_ecom2str(ecom
,
457 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
460 json_object_array_add(json_export_rtl
,
461 json_object_new_string(ecom_str
));
463 vty_out(vty
, " %s\n", ecom_str
);
465 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
469 json_object_object_add(json
, "exportRts", json_export_rtl
);
472 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
474 char buf1
[RD_ADDRSTRLEN
];
476 struct listnode
*node
, *nnode
;
477 struct ecommunity
*ecom
;
478 json_object
*json_import_rtl
= NULL
;
479 json_object
*json_export_rtl
= NULL
;
480 struct bgp
*bgp_evpn
;
482 bgp_evpn
= bgp_get_evpn();
485 json_import_rtl
= json_object_new_array();
486 json_export_rtl
= json_object_new_array();
487 json_object_int_add(json
, "vni", vpn
->vni
);
488 json_object_string_add(json
, "type", "L2");
489 json_object_string_add(json
, "inKernel",
490 is_vni_live(vpn
) ? "True" : "False");
491 json_object_string_add(
493 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
494 json_object_string_addf(json
, "originatorIp", "%pI4",
495 &vpn
->originator_ip
);
496 json_object_string_addf(json
, "mcastGroup", "%pI4",
498 /* per vni knob is enabled -- Enabled
499 * Global knob is enabled -- Active
500 * default -- Disabled
502 if (!vpn
->advertise_gw_macip
&&
503 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
504 json_object_string_add(json
, "advertiseGatewayMacip",
506 else if (vpn
->advertise_gw_macip
)
507 json_object_string_add(json
, "advertiseGatewayMacip",
510 json_object_string_add(json
, "advertiseGatewayMacip",
512 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
513 bgp_evpn
->evpn_info
->advertise_svi_macip
)
514 json_object_string_add(json
, "advertiseSviMacIp",
516 else if (vpn
->advertise_svi_macip
)
517 json_object_string_add(json
, "advertiseSviMacIp",
520 json_object_string_add(json
, "advertiseSviMacIp",
522 json_object_string_add(
523 json
, "sviInterface",
524 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
526 vty_out(vty
, "VNI: %d", vpn
->vni
);
527 if (is_vni_live(vpn
))
528 vty_out(vty
, " (known to the kernel)");
531 vty_out(vty
, " Type: %s\n", "L2");
532 vty_out(vty
, " Tenant-Vrf: %s\n",
533 vrf_id_to_name(vpn
->tenant_vrf_id
));
534 vty_out(vty
, " RD: %s\n",
535 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
536 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
537 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
538 if (!vpn
->advertise_gw_macip
&&
539 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
540 vty_out(vty
, " Advertise-gw-macip : %s\n",
542 else if (vpn
->advertise_gw_macip
)
543 vty_out(vty
, " Advertise-gw-macip : %s\n",
546 vty_out(vty
, " Advertise-gw-macip : %s\n",
548 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
549 bgp_evpn
->evpn_info
->advertise_svi_macip
)
550 vty_out(vty
, " Advertise-svi-macip : %s\n",
552 else if (vpn
->advertise_svi_macip
)
553 vty_out(vty
, " Advertise-svi-macip : %s\n",
556 vty_out(vty
, " Advertise-svi-macip : %s\n",
558 vty_out(vty
, " SVI interface : %s\n",
559 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
563 vty_out(vty
, " Import Route Target:\n");
565 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
566 ecom_str
= ecommunity_ecom2str(ecom
,
567 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
570 json_object_array_add(json_import_rtl
,
571 json_object_new_string(ecom_str
));
573 vty_out(vty
, " %s\n", ecom_str
);
575 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
579 json_object_object_add(json
, "importRts", json_import_rtl
);
581 vty_out(vty
, " Export Route Target:\n");
583 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
584 ecom_str
= ecommunity_ecom2str(ecom
,
585 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
588 json_object_array_add(json_export_rtl
,
589 json_object_new_string(ecom_str
));
591 vty_out(vty
, " %s\n", ecom_str
);
593 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
597 json_object_object_add(json
, "exportRts", json_export_rtl
);
600 static void show_esi_routes(struct bgp
*bgp
,
601 struct bgp_evpn_es
*es
,
606 struct bgp_dest
*dest
;
607 struct bgp_path_info
*pi
;
608 uint32_t prefix_cnt
, path_cnt
;
611 prefix_cnt
= path_cnt
= 0;
613 tbl_ver
= es
->route_table
->version
;
614 for (dest
= bgp_table_top(es
->route_table
); dest
;
615 dest
= bgp_route_next(dest
)) {
616 int add_prefix_to_json
= 0;
617 char prefix_str
[BUFSIZ
];
618 json_object
*json_paths
= NULL
;
619 json_object
*json_prefix
= NULL
;
620 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
622 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
626 json_prefix
= json_object_new_object();
628 pi
= bgp_dest_get_bgp_path_info(dest
);
630 /* Overall header/legend displayed once. */
632 bgp_evpn_show_route_header(vty
, bgp
,
641 json_paths
= json_object_new_array();
643 /* For EVPN, the prefix is displayed for each path (to fit in
644 * with code that already exists).
646 for (; pi
; pi
= pi
->next
) {
647 json_object
*json_path
= NULL
;
650 json_path
= json_object_new_array();
652 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
656 json_object_array_add(json_paths
, json_path
);
659 add_prefix_to_json
= 1;
663 if (add_prefix_to_json
) {
664 json_object_string_add(json_prefix
, "prefix",
666 json_object_int_add(json_prefix
, "prefixLen",
668 json_object_object_add(json_prefix
, "paths",
670 json_object_object_add(json
, prefix_str
,
673 json_object_free(json_paths
);
674 json_object_free(json_prefix
);
682 json_object_int_add(json
, "numPrefix", prefix_cnt
);
683 json_object_int_add(json
, "numPaths", path_cnt
);
686 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
688 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
689 prefix_cnt
, path_cnt
);
693 /* Display all MAC-IP VNI routes linked to an ES */
694 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
695 json_object
*json
, int detail
,
699 struct bgp_path_info
*pi
;
700 int header
= detail
? 0 : 1;
702 struct listnode
*node
;
703 struct bgp_evpn_es
*es
;
704 struct bgp_path_es_info
*es_info
;
705 struct bgp
*bgp
= bgp_get_evpn();
706 json_object
*json_paths
= NULL
;
714 json_paths
= json_object_new_array();
716 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
717 struct list
*es_list
;
719 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
723 es_list
= es
->macip_global_path_list
;
725 es_list
= es
->macip_evi_path_list
;
727 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
728 json_object
*json_path
= NULL
;
733 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
736 /* Overall header/legend displayed once. */
738 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
745 json_path
= json_object_new_array();
748 route_vty_out_detail(
749 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
750 RPKI_NOT_BEING_USED
, json_path
);
752 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
756 json_object_array_add(json_paths
, json_path
);
761 json_object_object_add(json
, "paths", json_paths
);
762 json_object_int_add(json
, "numPaths", path_cnt
);
765 vty_out(vty
, "There are no MAC-IP ES paths");
767 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
772 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
773 json_object
*json
, int detail
)
775 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
778 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
779 json_object
*json
, int detail
)
781 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
784 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
785 struct vty
*vty
, struct in_addr vtep_ip
,
786 json_object
*json
, int detail
)
788 struct bgp_dest
*dest
;
789 struct bgp_path_info
*pi
;
790 struct bgp_table
*table
;
791 int header
= detail
? 0 : 1;
793 uint32_t prefix_cnt
, path_cnt
;
795 prefix_cnt
= path_cnt
= 0;
797 table
= vpn
->route_table
;
798 tbl_ver
= table
->version
;
799 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
800 const struct prefix_evpn
*evp
=
801 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
802 int add_prefix_to_json
= 0;
803 char prefix_str
[BUFSIZ
];
804 json_object
*json_paths
= NULL
;
805 json_object
*json_prefix
= NULL
;
806 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
808 prefix2str((struct prefix_evpn
*)bgp_dest_get_prefix(dest
),
809 prefix_str
, sizeof(prefix_str
));
811 if (type
&& evp
->prefix
.route_type
!= type
)
815 json_prefix
= json_object_new_object();
817 pi
= bgp_dest_get_bgp_path_info(dest
);
819 /* Overall header/legend displayed once. */
821 bgp_evpn_show_route_header(vty
, bgp
,
830 json_paths
= json_object_new_array();
832 /* For EVPN, the prefix is displayed for each path (to fit in
833 * with code that already exists).
835 for (; pi
; pi
= pi
->next
) {
836 json_object
*json_path
= NULL
;
838 if (vtep_ip
.s_addr
!= INADDR_ANY
839 && !IPV4_ADDR_SAME(&(vtep_ip
),
840 &(pi
->attr
->nexthop
)))
844 json_path
= json_object_new_array();
847 route_vty_out_detail(vty
, bgp
, dest
, pi
,
848 AFI_L2VPN
, SAFI_EVPN
,
852 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
856 json_object_array_add(json_paths
, json_path
);
859 add_prefix_to_json
= 1;
863 if (add_prefix_to_json
) {
864 json_object_string_add(json_prefix
, "prefix",
866 json_object_int_add(json_prefix
, "prefixLen",
868 json_object_object_add(json_prefix
, "paths",
870 json_object_object_add(json
, prefix_str
,
873 json_object_free(json_paths
);
874 json_object_free(json_prefix
);
882 json_object_int_add(json
, "numPrefix", prefix_cnt
);
883 json_object_int_add(json
, "numPaths", path_cnt
);
886 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
887 type
? "(of requested type) " : "");
889 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
890 prefix_cnt
, path_cnt
,
891 type
? " (of requested type)" : "");
896 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
898 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
899 struct vni_walk_ctx
*wctx
= arg
;
900 struct vty
*vty
= wctx
->vty
;
901 json_object
*json
= wctx
->json
;
902 json_object
*json_vni
= NULL
;
903 char vni_str
[VNI_STR_LEN
];
905 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
907 json_vni
= json_object_new_object();
908 json_object_int_add(json_vni
, "vni", vpn
->vni
);
910 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
913 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
917 json_object_object_add(json
, vni_str
, json_vni
);
920 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
923 json_object
*json_vni
= NULL
;
924 json_object
*json_import_rtl
= NULL
;
925 json_object
*json_export_rtl
= NULL
;
927 char buf2
[INET6_ADDRSTRLEN
];
930 struct listnode
*node
, *nnode
;
931 struct ecommunity
*ecom
;
937 json_vni
= json_object_new_object();
938 json_import_rtl
= json_object_new_array();
939 json_export_rtl
= json_object_new_array();
942 /* if an l3vni is present in bgp it is live */
944 snprintf(buf1
, sizeof(buf1
), "*");
947 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
948 json_object_string_add(json_vni
, "type", "L3");
949 json_object_string_add(json_vni
, "inKernel", "True");
950 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
951 &bgp
->originator_ip
);
952 json_object_string_add(
954 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
955 json_object_string_add(json_vni
, "advertiseGatewayMacip",
957 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
958 json_object_string_add(
959 json_vni
, "advertisePip",
960 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
961 json_object_string_addf(json_vni
, "sysIP", "%pI4",
962 &bgp
->evpn_info
->pip_ip
);
963 json_object_string_add(json_vni
, "sysMAC",
964 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
965 buf2
, sizeof(buf2
)));
966 json_object_string_add(
968 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
970 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
971 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
974 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
975 ecom_str
= ecommunity_ecom2str(ecom
,
976 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
979 json_object_array_add(json_import_rtl
,
980 json_object_new_string(ecom_str
));
982 if (listcount(bgp
->vrf_import_rtl
) > 1)
983 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
986 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
988 vty_out(vty
, " %-25s", rt_buf
);
991 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
993 /* If there are multiple import RTs we break here and show only
1000 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1002 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
1003 ecom_str
= ecommunity_ecom2str(ecom
,
1004 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1007 json_object_array_add(json_export_rtl
,
1008 json_object_new_string(ecom_str
));
1010 if (listcount(bgp
->vrf_export_rtl
) > 1)
1011 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1014 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1016 vty_out(vty
, " %-25s", rt_buf
);
1019 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1021 /* If there are multiple export RTs we break here and show only
1028 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1031 char vni_str
[VNI_STR_LEN
];
1033 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1034 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1035 json_object_object_add(json
, vni_str
, json_vni
);
1041 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1045 json_object
*json_vni
= NULL
;
1046 json_object
*json_import_rtl
= NULL
;
1047 json_object
*json_export_rtl
= NULL
;
1048 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1050 char buf2
[RD_ADDRSTRLEN
];
1053 struct listnode
*node
, *nnode
;
1054 struct ecommunity
*ecom
;
1055 struct bgp
*bgp_evpn
;
1060 bgp_evpn
= bgp_get_evpn();
1063 json_vni
= json_object_new_object();
1064 json_import_rtl
= json_object_new_array();
1065 json_export_rtl
= json_object_new_array();
1069 if (is_vni_live(vpn
))
1070 snprintf(buf1
, sizeof(buf1
), "*");
1073 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1074 json_object_string_add(json_vni
, "type", "L2");
1075 json_object_string_add(json_vni
, "inKernel",
1076 is_vni_live(vpn
) ? "True" : "False");
1077 json_object_string_add(
1079 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1080 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1081 &vpn
->originator_ip
);
1082 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1084 /* per vni knob is enabled -- Enabled
1085 * Global knob is enabled -- Active
1086 * default -- Disabled
1088 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1089 && bgp_evpn
->advertise_gw_macip
)
1090 json_object_string_add(
1091 json_vni
, "advertiseGatewayMacip", "Active");
1092 else if (vpn
->advertise_gw_macip
)
1093 json_object_string_add(
1094 json_vni
, "advertiseGatewayMacip", "Enabled");
1096 json_object_string_add(
1097 json_vni
, "advertiseGatewayMacip", "Disabled");
1098 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1099 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1100 json_object_string_add(json_vni
, "advertiseSviMacIp",
1102 else if (vpn
->advertise_svi_macip
)
1103 json_object_string_add(json_vni
, "advertiseSviMacIp",
1106 json_object_string_add(json_vni
, "advertiseSviMacIp",
1109 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1110 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1113 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1114 ecom_str
= ecommunity_ecom2str(ecom
,
1115 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1118 json_object_array_add(json_import_rtl
,
1119 json_object_new_string(ecom_str
));
1121 if (listcount(vpn
->import_rtl
) > 1)
1122 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1125 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1127 vty_out(vty
, " %-25s", rt_buf
);
1130 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1132 /* If there are multiple import RTs we break here and show only
1139 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1141 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1142 ecom_str
= ecommunity_ecom2str(ecom
,
1143 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1146 json_object_array_add(json_export_rtl
,
1147 json_object_new_string(ecom_str
));
1149 if (listcount(vpn
->export_rtl
) > 1)
1150 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1153 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1155 vty_out(vty
, " %-25s", rt_buf
);
1158 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1160 /* If there are multiple export RTs we break here and show only
1167 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1170 char vni_str
[VNI_STR_LEN
];
1172 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1173 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1174 json_object_object_add(json
, vni_str
, json_vni
);
1180 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1181 enum bgp_show_type type
, void *output_arg
,
1182 int option
, bool use_json
)
1184 afi_t afi
= AFI_L2VPN
;
1186 struct bgp_table
*table
;
1187 struct bgp_dest
*dest
;
1188 struct bgp_dest
*rm
;
1189 struct bgp_path_info
*pi
;
1192 char rd_str
[RD_ADDRSTRLEN
];
1196 unsigned long output_count
= 0;
1197 unsigned long total_count
= 0;
1198 json_object
*json
= NULL
;
1199 json_object
*json_array
= NULL
;
1200 json_object
*json_prefix_info
= NULL
;
1202 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1204 bgp
= bgp_get_evpn();
1207 vty_out(vty
, "No BGP process is configured\n");
1209 vty_out(vty
, "{}\n");
1214 json
= json_object_new_object();
1216 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1217 dest
= bgp_route_next(dest
)) {
1219 json_object
*json_nroute
= NULL
;
1220 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1222 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1225 table
= bgp_dest_get_bgp_table_info(dest
);
1230 tbl_ver
= table
->version
;
1232 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1233 pi
= bgp_dest_get_bgp_path_info(rm
);
1238 for (; pi
; pi
= pi
->next
) {
1240 if (type
== bgp_show_type_neighbor
) {
1241 struct peer
*peer
= output_arg
;
1243 if (peer_cmp(peer
, pi
->peer
) != 0)
1246 if (type
== bgp_show_type_lcommunity_exact
) {
1247 struct lcommunity
*lcom
= output_arg
;
1249 if (!pi
->attr
->lcommunity
||
1251 pi
->attr
->lcommunity
, lcom
))
1254 if (type
== bgp_show_type_lcommunity
) {
1255 struct lcommunity
*lcom
= output_arg
;
1257 if (!pi
->attr
->lcommunity
||
1259 pi
->attr
->lcommunity
, lcom
))
1262 if (type
== bgp_show_type_community
) {
1263 struct community
*com
= output_arg
;
1265 if (!pi
->attr
->community
||
1267 pi
->attr
->community
, com
))
1270 if (type
== bgp_show_type_community_exact
) {
1271 struct community
*com
= output_arg
;
1273 if (!pi
->attr
->community
||
1275 pi
->attr
->community
, com
))
1280 json_object_int_add(
1281 json
, "bgpTableVersion",
1283 json_object_string_addf(
1288 json_object_int_add(
1291 bgp
->default_local_pref
);
1292 json_object_int_add(
1296 if (option
== SHOW_DISPLAY_TAGS
)
1301 == SHOW_DISPLAY_OVERLAY
)
1305 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1313 json_object_new_object();
1314 bgp_evpn_show_route_rd_header(
1315 vty
, dest
, json_nroute
, rd_str
,
1319 if (use_json
&& !json_array
)
1320 json_array
= json_object_new_array();
1322 if (option
== SHOW_DISPLAY_TAGS
)
1324 vty
, bgp_dest_get_prefix(rm
),
1325 pi
, no_display
, SAFI_EVPN
,
1327 else if (option
== SHOW_DISPLAY_OVERLAY
)
1328 route_vty_out_overlay(
1329 vty
, bgp_dest_get_prefix(rm
),
1330 pi
, no_display
, json_array
);
1333 bgp_dest_get_prefix(rm
),
1334 pi
, no_display
, SAFI_EVPN
,
1342 if (use_json
&& json_array
) {
1343 const struct prefix
*p
=
1344 bgp_dest_get_prefix(rm
);
1346 json_prefix_info
= json_object_new_object();
1348 json_object_string_add(
1349 json_prefix_info
, "prefix",
1350 prefix2str((struct prefix_evpn
*)p
, buf
,
1353 json_object_int_add(json_prefix_info
,
1354 "prefixLen", p
->prefixlen
);
1356 json_object_object_add(json_prefix_info
,
1357 "paths", json_array
);
1358 json_object_object_add(json_nroute
, buf
,
1364 if (use_json
&& json_nroute
)
1365 json_object_object_add(json
, rd_str
, json_nroute
);
1369 json_object_int_add(json
, "numPrefix", output_count
);
1370 json_object_int_add(json
, "totalPrefix", total_count
);
1371 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1372 json
, JSON_C_TO_STRING_PRETTY
));
1373 json_object_free(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_out(vty
, "%s\n",
4394 json_object_to_json_string_ext(
4396 JSON_C_TO_STRING_PRETTY
4397 | JSON_C_TO_STRING_NOSLASHESCAPE
));
4398 json_object_free(json
);
4404 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4405 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4406 "show bgp l2vpn evpn vni remote-ip-hash",
4414 struct bgp
*bgp_evpn
;
4417 bgp_evpn
= bgp_get_evpn();
4421 if (!argv_find(argv
, argc
, "evpn", &idx
))
4424 hash_iterate(bgp_evpn
->vnihash
,
4425 (void (*)(struct hash_bucket
*,
4426 void *))bgp_evpn_show_remote_ip_hash
,
4432 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4433 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4434 "show bgp l2vpn evpn vni-svi-hash",
4439 "Show vni-svi-hash\n")
4441 struct bgp
*bgp_evpn
;
4444 bgp_evpn
= bgp_get_evpn();
4448 if (!argv_find(argv
, argc
, "evpn", &idx
))
4451 hash_iterate(bgp_evpn
->vni_svi_hash
,
4452 (void (*)(struct hash_bucket
*,
4453 void *))bgp_evpn_show_vni_svi_hash
,
4459 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4460 show_bgp_l2vpn_evpn_es_evi_cmd
,
4461 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4467 "VxLAN Network Identifier\n"
4470 "Detailed information\n")
4473 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4475 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4480 DEFPY(show_bgp_l2vpn_evpn_es
,
4481 show_bgp_l2vpn_evpn_es_cmd
,
4482 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4487 "Ethernet Segment\n"
4489 "Detailed information\n"
4495 if (!str_to_esi(esi_str
, &esi
)) {
4496 vty_out(vty
, "%%Malformed ESI\n");
4499 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4502 bgp_evpn_es_show(vty
, uj
, !!detail
);
4508 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4509 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4510 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4511 "Ethernet Segment\n"
4517 if (!str_to_esi(esi_str
, &esi
)) {
4518 vty_out(vty
, "%%Malformed ESI\n");
4521 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4524 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4530 DEFPY(show_bgp_l2vpn_evpn_nh
,
4531 show_bgp_l2vpn_evpn_nh_cmd
,
4532 "show bgp l2vpn evpn next-hops [json$uj]",
4540 bgp_evpn_nh_show(vty
, uj
);
4546 * Display EVPN neighbor summary.
4548 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4549 "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]",
4552 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4553 "Summary of BGP neighbor status\n"
4554 "Show only sessions in Established state\n"
4555 "Show only sessions not in Established state\n"
4556 "Show only the specified neighbor session\n"
4557 "Neighbor to display information about\n"
4558 "Neighbor to display information about\n"
4559 "Neighbor on BGP configured interface\n"
4560 "Show only the specified remote AS sessions\n"
4562 "Internal (iBGP) AS sessions\n"
4563 "External (eBGP) AS sessions\n"
4564 "Shorten the information on BGP instances\n"
4565 "Increase table width for longer output\n" JSON_STR
)
4570 char *neighbor
= NULL
;
4571 as_t as
= 0; /* 0 means AS filter not set */
4572 int as_type
= AS_UNSPECIFIED
;
4573 uint16_t show_flags
= 0;
4575 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4576 vrf
= argv
[++idx_vrf
]->arg
;
4578 if (argv_find(argv
, argc
, "failed", &idx
))
4579 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4581 if (argv_find(argv
, argc
, "established", &idx
))
4582 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4585 if (argv_find(argv
, argc
, "neighbor", &idx
))
4586 neighbor
= argv
[idx
+ 1]->arg
;
4588 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4589 if (argv
[idx
+ 1]->arg
[0] == 'i')
4590 as_type
= AS_INTERNAL
;
4591 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4592 as_type
= AS_EXTERNAL
;
4594 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4597 if (argv_find(argv
, argc
, "terse", &idx
))
4598 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4600 if (argv_find(argv
, argc
, "wide", &idx
))
4601 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4603 if (use_json(argc
, argv
))
4604 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4606 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4607 as_type
, as
, show_flags
);
4610 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4614 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4615 /* Specific type is requested */
4616 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4617 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4618 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4619 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4620 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4621 *type
= BGP_EVPN_IMET_ROUTE
;
4622 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4623 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4624 *type
= BGP_EVPN_ES_ROUTE
;
4625 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4626 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4627 *type
= BGP_EVPN_AD_ROUTE
;
4628 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4629 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4630 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4639 * Display global EVPN routing table.
4641 DEFUN(show_bgp_l2vpn_evpn_route
,
4642 show_bgp_l2vpn_evpn_route_cmd
,
4643 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4649 "Display Detailed Information\n"
4651 EVPN_TYPE_ALL_LIST_HELP_STR
4658 json_object
*json
= NULL
;
4660 uj
= use_json(argc
, argv
);
4662 bgp
= bgp_get_evpn();
4667 json
= json_object_new_object();
4669 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4672 if (argv_find(argv
, argc
, "detail", &detail
))
4675 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4678 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4679 json
, JSON_C_TO_STRING_PRETTY
));
4680 json_object_free(json
);
4686 * Display global EVPN routing table for specific RD.
4688 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4689 show_bgp_l2vpn_evpn_route_rd_cmd
,
4690 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4696 EVPN_RT_DIST_HELP_STR
4697 EVPN_ASN_IP_HELP_STR
4698 "All VPN Route Distinguishers\n"
4700 EVPN_TYPE_ALL_LIST_HELP_STR
4705 struct prefix_rd prd
;
4708 json_object
*json
= NULL
;
4709 int idx_ext_community
= 0;
4712 bgp
= bgp_get_evpn();
4716 /* check if we need json output */
4717 uj
= use_json(argc
, argv
);
4719 json
= json_object_new_object();
4721 argv_find(argv
, argc
, "all", &rd_all
);
4724 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4725 &idx_ext_community
);
4726 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4728 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4733 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4737 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4739 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4742 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4743 json
, JSON_C_TO_STRING_PRETTY
));
4744 json_object_free(json
);
4751 * Display global EVPN routing table for specific RD and MACIP.
4753 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4754 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4755 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4761 EVPN_RT_DIST_HELP_STR
4762 EVPN_ASN_IP_HELP_STR
4763 "All VPN Route Distinguishers\n"
4765 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4767 "IP address (IPv4 or IPv6)\n"
4772 struct prefix_rd prd
;
4775 int idx_ext_community
= 0;
4779 json_object
*json
= NULL
;
4782 memset(&mac
, 0, sizeof(struct ethaddr
));
4783 memset(&ip
, 0, sizeof(struct ipaddr
));
4785 bgp
= bgp_get_evpn();
4789 /* check if we need json output */
4790 uj
= use_json(argc
, argv
);
4792 json
= json_object_new_object();
4795 argv_find(argv
, argc
, "all", &rd_all
);
4797 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4798 &idx_ext_community
);
4799 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4801 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4807 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4808 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4809 vty_out(vty
, "%% Malformed MAC address\n");
4814 /* get the ip if specified */
4815 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4816 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4817 vty_out(vty
, "%% Malformed IP address\n");
4823 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4825 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4828 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4829 json
, JSON_C_TO_STRING_PRETTY
));
4830 json_object_free(json
);
4836 /* Display per ESI routing table */
4837 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4838 show_bgp_l2vpn_evpn_route_esi_cmd
,
4839 "show bgp l2vpn evpn route esi ESI [json]",
4845 "Ethernet Segment Identifier\n"
4851 struct bgp
*bgp
= NULL
;
4852 json_object
*json
= NULL
;
4854 memset(&esi
, 0, sizeof(esi
));
4855 bgp
= bgp_get_evpn();
4859 uj
= use_json(argc
, argv
);
4861 json
= json_object_new_object();
4863 /* get the ESI - ESI-ID is at argv[6] */
4864 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4865 vty_out(vty
, "%% Malformed ESI\n");
4869 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4872 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4873 json
, JSON_C_TO_STRING_PRETTY
));
4874 json_object_free(json
);
4882 * Display per-VNI EVPN routing table.
4884 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4885 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4891 "VXLAN Network Identifier\n"
4894 EVPN_TYPE_1_HELP_STR
4895 EVPN_TYPE_1_HELP_STR
4896 EVPN_TYPE_2_HELP_STR
4897 EVPN_TYPE_2_HELP_STR
4898 EVPN_TYPE_3_HELP_STR
4899 EVPN_TYPE_3_HELP_STR
4901 "Remote VTEP IP address\n"
4906 struct in_addr vtep_ip
;
4911 json_object
*json
= NULL
;
4913 bgp
= bgp_get_evpn();
4917 /* check if we need json output */
4918 uj
= use_json(argc
, argv
);
4920 json
= json_object_new_object();
4922 if (!argv_find(argv
, argc
, "evpn", &idx
))
4927 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4929 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4932 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4933 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4934 vty_out(vty
, "%% Malformed VTEP IP address\n");
4939 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4942 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4943 json
, JSON_C_TO_STRING_PRETTY
));
4944 json_object_free(json
);
4951 * Display per-VNI EVPN routing table for specific MACIP.
4953 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4954 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4955 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4961 "VXLAN Network Identifier\n"
4964 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4966 "IP address (IPv4 or IPv6)\n"
4975 json_object
*json
= NULL
;
4977 bgp
= bgp_get_evpn();
4981 /* check if we need json output */
4982 uj
= use_json(argc
, argv
);
4984 json
= json_object_new_object();
4986 if (!argv_find(argv
, argc
, "evpn", &idx
))
4990 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4993 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4994 vty_out(vty
, "%% Malformed MAC address\n");
4999 memset(&ip
, 0, sizeof(ip
));
5000 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5002 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5003 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5004 vty_out(vty
, "%% Malformed IP address\n");
5009 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5012 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5013 json
, JSON_C_TO_STRING_PRETTY
));
5014 json_object_free(json
);
5021 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5023 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5024 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5025 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5031 "VXLAN Network Identifier\n"
5033 EVPN_TYPE_3_HELP_STR
5034 "Originating Router IP address\n"
5040 struct in_addr orig_ip
;
5043 json_object
*json
= NULL
;
5045 bgp
= bgp_get_evpn();
5049 /* check if we need json output */
5050 uj
= use_json(argc
, argv
);
5052 json
= json_object_new_object();
5054 if (!argv_find(argv
, argc
, "evpn", &idx
))
5058 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5061 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5063 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5067 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5070 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5071 json
, JSON_C_TO_STRING_PRETTY
));
5072 json_object_free(json
);
5079 * Display per-VNI EVPN routing table - for all VNIs.
5081 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5082 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5083 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5089 "VXLAN Network Identifier\n"
5091 "Print Detailed Output\n"
5093 "Remote VTEP IP address\n"
5097 struct in_addr vtep_ip
;
5100 json_object
*json
= NULL
;
5101 /* Detail Adjust. Adjust indexes according to detail option */
5104 bgp
= bgp_get_evpn();
5108 /* check if we need json output */
5109 uj
= use_json(argc
, argv
);
5111 json
= json_object_new_object();
5113 if (!argv_find(argv
, argc
, "evpn", &idx
))
5116 if (argv_find(argv
, argc
, "detail", &da
))
5119 /* vtep-ip position depends on detail option */
5121 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5123 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5124 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5125 vty_out(vty
, "%% Malformed VTEP IP address\n");
5130 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5133 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5134 json
, JSON_C_TO_STRING_PRETTY
));
5135 json_object_free(json
);
5142 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5143 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5144 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5145 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5146 "EVPN route information\n"
5147 "MAC IP routes in the EVI tables linked to the ES\n"
5149 "Detailed information\n" JSON_STR
)
5153 json_object
*json
= NULL
;
5156 if (!str_to_esi(esi_str
, &esi
)) {
5157 vty_out(vty
, "%%Malformed ESI\n");
5166 json
= json_object_new_object();
5167 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5169 vty_out(vty
, "%s\n",
5170 json_object_to_json_string_ext(
5171 json
, JSON_C_TO_STRING_PRETTY
));
5172 json_object_free(json
);
5179 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5180 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5181 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5182 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5183 "EVPN route information\n"
5184 "MAC IP routes in the global table linked to the ES\n"
5186 "Detailed information\n" JSON_STR
)
5190 json_object
*json
= NULL
;
5193 if (!str_to_esi(esi_str
, &esi
)) {
5194 vty_out(vty
, "%%Malformed ESI\n");
5203 json
= json_object_new_object();
5204 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5206 vty_out(vty
, "%s\n",
5207 json_object_to_json_string_ext(
5208 json
, JSON_C_TO_STRING_PRETTY
));
5209 json_object_free(json
);
5216 * Display EVPN import route-target hash table
5218 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5219 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5220 "show bgp l2vpn evpn vrf-import-rt [json]",
5225 "Show vrf import route target\n"
5229 struct bgp
*bgp_evpn
= NULL
;
5230 json_object
*json
= NULL
;
5232 bgp_evpn
= bgp_get_evpn();
5236 uj
= use_json(argc
, argv
);
5238 json
= json_object_new_object();
5240 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5243 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5244 json
, JSON_C_TO_STRING_PRETTY
));
5245 json_object_free(json
);
5252 * Display EVPN import route-target hash table
5254 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5255 show_bgp_l2vpn_evpn_import_rt_cmd
,
5256 "show bgp l2vpn evpn import-rt [json]",
5261 "Show import route target\n"
5266 json_object
*json
= NULL
;
5268 bgp
= bgp_get_evpn();
5272 uj
= use_json(argc
, argv
);
5274 json
= json_object_new_object();
5276 evpn_show_import_rts(vty
, bgp
, json
);
5279 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5280 json
, JSON_C_TO_STRING_PRETTY
));
5281 json_object_free(json
);
5287 DEFPY_HIDDEN(test_es_add
,
5289 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5292 "Ethernet-segment\n"
5293 "Ethernet-Segment Identifier\n"
5301 struct in_addr vtep_ip
;
5304 bgp
= bgp_get_evpn();
5306 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5310 if (!str_to_esi(esi_str
, &esi
)) {
5311 vty_out(vty
, "%%Malformed ESI\n");
5316 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5318 vty_out(vty
, "%%Failed to delete ES\n");
5322 if (state_str
&& !strcmp(state_str
, "up"))
5326 vtep_ip
= bgp
->router_id
;
5328 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5329 EVPN_MH_DF_PREF_MIN
, false);
5331 vty_out(vty
, "%%Failed to add ES\n");
5338 DEFPY_HIDDEN(test_es_vni_add
,
5339 test_es_vni_add_cmd
,
5340 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5343 "Ethernet-segment\n"
5344 "Ethernet-Segment Identifier\n"
5353 bgp
= bgp_get_evpn();
5355 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5359 if (!str_to_esi(esi_str
, &esi
)) {
5360 vty_out(vty
, "%%Malformed ESI\n");
5365 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5367 vty_out(vty
, "%%Failed to deref ES VNI\n");
5371 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5373 vty_out(vty
, "%%Failed to ref ES VNI\n");
5380 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5381 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5385 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5386 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5387 "Summary of BGP neighbor status\n" JSON_STR
)
5389 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5390 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5391 SHOW_STR BGP_STR EVPN_HELP_STR
5393 "Display Detailed Information\n"
5395 EVPN_TYPE_2_HELP_STR
5396 EVPN_TYPE_2_HELP_STR
5397 EVPN_TYPE_3_HELP_STR
5398 EVPN_TYPE_3_HELP_STR
)
5401 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5402 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5403 SHOW_STR BGP_STR EVPN_HELP_STR
5405 EVPN_RT_DIST_HELP_STR
5406 EVPN_ASN_IP_HELP_STR
5408 EVPN_TYPE_2_HELP_STR
5409 EVPN_TYPE_2_HELP_STR
5410 EVPN_TYPE_3_HELP_STR
5411 EVPN_TYPE_3_HELP_STR
)
5414 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5415 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5416 SHOW_STR BGP_STR EVPN_HELP_STR
5418 EVPN_RT_DIST_HELP_STR
5419 EVPN_ASN_IP_HELP_STR
5421 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5423 "IP address (IPv4 or IPv6)\n")
5426 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5427 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5428 SHOW_STR BGP_STR EVPN_HELP_STR
5430 "VXLAN Network Identifier\n"
5433 EVPN_TYPE_2_HELP_STR
5434 EVPN_TYPE_2_HELP_STR
5435 EVPN_TYPE_3_HELP_STR
5436 EVPN_TYPE_3_HELP_STR
5438 "Remote VTEP IP address\n")
5440 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5441 show_bgp_evpn_route_vni_macip_cmd
,
5442 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5443 SHOW_STR BGP_STR EVPN_HELP_STR
5445 "VXLAN Network Identifier\n"
5448 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5450 "IP address (IPv4 or IPv6)\n")
5452 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5453 show_bgp_evpn_route_vni_multicast_cmd
,
5454 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5455 SHOW_STR BGP_STR EVPN_HELP_STR
5457 "VXLAN Network Identifier\n"
5459 EVPN_TYPE_3_HELP_STR
5460 "Originating Router IP address\n")
5462 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5463 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5464 SHOW_STR BGP_STR EVPN_HELP_STR
5466 "VXLAN Network Identifier\n"
5468 "Print Detailed Output\n"
5470 "Remote VTEP IP address\n")
5472 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5473 "show bgp evpn import-rt",
5474 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5476 DEFUN_NOSH (bgp_evpn_vni
,
5478 "vni " CMD_VNI_RANGE
,
5479 "VXLAN Network Identifier\n"
5483 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5484 struct bgpevpn
*vpn
;
5489 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5491 /* Create VNI, or mark as configured. */
5492 vpn
= evpn_create_update_vni(bgp
, vni
);
5494 vty_out(vty
, "%% Failed to create VNI \n");
5498 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5502 DEFUN (no_bgp_evpn_vni
,
5503 no_bgp_evpn_vni_cmd
,
5504 "no vni " CMD_VNI_RANGE
,
5506 "VXLAN Network Identifier\n"
5510 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5511 struct bgpevpn
*vpn
;
5516 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5518 /* Check if we should disallow. */
5519 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5521 vty_out(vty
, "%% Specified VNI does not exist\n");
5524 if (!is_vni_configured(vpn
)) {
5525 vty_out(vty
, "%% Specified VNI is not configured\n");
5529 evpn_delete_vni(bgp
, vpn
);
5533 DEFUN_NOSH (exit_vni
,
5536 "Exit from VNI mode\n")
5538 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5539 vty
->node
= BGP_EVPN_NODE
;
5543 DEFUN (bgp_evpn_vrf_rd
,
5544 bgp_evpn_vrf_rd_cmd
,
5545 "rd ASN:NN_OR_IP-ADDRESS:NN",
5546 EVPN_RT_DIST_HELP_STR
5547 EVPN_ASN_IP_HELP_STR
)
5550 struct prefix_rd prd
;
5551 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5556 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5558 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5562 /* If same as existing value, there is nothing more to do. */
5563 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5566 /* Configure or update the RD. */
5567 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5571 DEFUN (no_bgp_evpn_vrf_rd
,
5572 no_bgp_evpn_vrf_rd_cmd
,
5573 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5575 EVPN_RT_DIST_HELP_STR
5576 EVPN_ASN_IP_HELP_STR
)
5579 struct prefix_rd prd
;
5580 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5585 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5587 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5591 /* Check if we should disallow. */
5592 if (!is_vrf_rd_configured(bgp_vrf
)) {
5593 vty_out(vty
, "%% RD is not configured for this VRF\n");
5597 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5599 "%% RD specified does not match configuration for this VRF\n");
5603 evpn_unconfigure_vrf_rd(bgp_vrf
);
5607 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5608 no_bgp_evpn_vrf_rd_without_val_cmd
,
5611 EVPN_RT_DIST_HELP_STR
)
5613 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5618 /* Check if we should disallow. */
5619 if (!is_vrf_rd_configured(bgp_vrf
)) {
5620 vty_out(vty
, "%% RD is not configured for this VRF\n");
5624 evpn_unconfigure_vrf_rd(bgp_vrf
);
5628 DEFUN (bgp_evpn_vni_rd
,
5629 bgp_evpn_vni_rd_cmd
,
5630 "rd ASN:NN_OR_IP-ADDRESS:NN",
5631 EVPN_RT_DIST_HELP_STR
5632 EVPN_ASN_IP_HELP_STR
)
5634 struct prefix_rd prd
;
5635 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5636 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5642 if (!EVPN_ENABLED(bgp
)) {
5644 "This command is only supported under EVPN VRF\n");
5648 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5650 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5654 /* If same as existing value, there is nothing more to do. */
5655 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5658 /* Configure or update the RD. */
5659 evpn_configure_rd(bgp
, vpn
, &prd
);
5663 DEFUN (no_bgp_evpn_vni_rd
,
5664 no_bgp_evpn_vni_rd_cmd
,
5665 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5667 EVPN_RT_DIST_HELP_STR
5668 EVPN_ASN_IP_HELP_STR
)
5670 struct prefix_rd prd
;
5671 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5672 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5678 if (!EVPN_ENABLED(bgp
)) {
5680 "This command is only supported under EVPN VRF\n");
5684 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5686 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5690 /* Check if we should disallow. */
5691 if (!is_rd_configured(vpn
)) {
5692 vty_out(vty
, "%% RD is not configured for this VNI\n");
5696 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5698 "%% RD specified does not match configuration for this VNI\n");
5702 evpn_unconfigure_rd(bgp
, vpn
);
5706 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5707 no_bgp_evpn_vni_rd_without_val_cmd
,
5710 EVPN_RT_DIST_HELP_STR
)
5712 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5713 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5718 if (!EVPN_ENABLED(bgp
)) {
5720 "This command is only supported under EVPN VRF\n");
5724 /* Check if we should disallow. */
5725 if (!is_rd_configured(vpn
)) {
5726 vty_out(vty
, "%% RD is not configured for this VNI\n");
5730 evpn_unconfigure_rd(bgp
, vpn
);
5735 * Loop over all extended-communities in the route-target list rtl and
5736 * return 1 if we find ecomtarget
5738 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5739 struct ecommunity
*ecomtarget
)
5741 struct listnode
*node
, *nnode
;
5742 struct ecommunity
*ecom
;
5744 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5745 if (ecommunity_match(ecom
, ecomtarget
))
5752 /* display L3VNI related info for a VRF instance */
5753 DEFUN (show_bgp_vrf_l3vni_info
,
5754 show_bgp_vrf_l3vni_info_cmd
,
5755 "show bgp vrf VRFNAME vni [json]",
5763 char buf
[ETHER_ADDR_STRLEN
];
5764 char buf1
[INET6_ADDRSTRLEN
];
5766 const char *name
= NULL
;
5767 struct bgp
*bgp
= NULL
;
5768 struct listnode
*node
= NULL
;
5769 struct bgpevpn
*vpn
= NULL
;
5770 struct ecommunity
*ecom
= NULL
;
5771 json_object
*json
= NULL
;
5772 json_object
*json_vnis
= NULL
;
5773 json_object
*json_export_rts
= NULL
;
5774 json_object
*json_import_rts
= NULL
;
5775 bool uj
= use_json(argc
, argv
);
5778 json
= json_object_new_object();
5779 json_vnis
= json_object_new_array();
5780 json_export_rts
= json_object_new_array();
5781 json_import_rts
= json_object_new_array();
5784 name
= argv
[idx_vrf
]->arg
;
5785 bgp
= bgp_lookup_by_name(name
);
5788 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5790 json_object_string_add(json
, "warning",
5791 "BGP instance not found");
5792 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5793 json_object_free(json
);
5799 vty_out(vty
, "BGP VRF: %s\n", name
);
5800 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5801 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5802 vty_out(vty
, " Rmac: %s\n",
5803 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5804 vty_out(vty
, " VNI Filter: %s\n",
5805 CHECK_FLAG(bgp
->vrf_flags
,
5806 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5807 ? "prefix-routes-only"
5809 vty_out(vty
, " L2-VNI List:\n");
5811 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5812 vty_out(vty
, "%u ", vpn
->vni
);
5814 vty_out(vty
, " Export-RTs:\n");
5816 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5817 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5819 vty_out(vty
, " Import-RTs:\n");
5821 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5822 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5824 vty_out(vty
, " RD: %s\n",
5825 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5827 json_object_string_add(json
, "vrf", name
);
5828 json_object_string_addf(json
, "local-ip", "%pI4",
5829 &bgp
->originator_ip
);
5830 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5831 json_object_string_add(
5833 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5834 json_object_string_add(
5836 CHECK_FLAG(bgp
->vrf_flags
,
5837 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5838 ? "prefix-routes-only"
5840 /* list of l2vnis */
5841 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5842 json_object_array_add(json_vnis
,
5843 json_object_new_int(vpn
->vni
));
5844 json_object_object_add(json
, "l2vnis", json_vnis
);
5847 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5848 json_object_array_add(
5850 json_object_new_string(ecommunity_str(ecom
)));
5851 json_object_object_add(json
, "export-rts", json_export_rts
);
5854 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5855 json_object_array_add(
5857 json_object_new_string(ecommunity_str(ecom
)));
5858 json_object_object_add(json
, "import-rts", json_import_rts
);
5859 json_object_string_add(
5861 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5865 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5866 json
, JSON_C_TO_STRING_PRETTY
));
5867 json_object_free(json
);
5872 /* import/export rt for l3vni-vrf */
5873 DEFUN (bgp_evpn_vrf_rt
,
5874 bgp_evpn_vrf_rt_cmd
,
5875 "route-target <both|import|export> RT",
5877 "import and export\n"
5880 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5883 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5884 struct ecommunity
*ecomadd
= NULL
;
5889 if (!strcmp(argv
[1]->arg
, "import"))
5890 rt_type
= RT_TYPE_IMPORT
;
5891 else if (!strcmp(argv
[1]->arg
, "export"))
5892 rt_type
= RT_TYPE_EXPORT
;
5893 else if (!strcmp(argv
[1]->arg
, "both"))
5894 rt_type
= RT_TYPE_BOTH
;
5896 vty_out(vty
, "%% Invalid Route Target type\n");
5900 /* Add/update the import route-target */
5901 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5902 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5903 ECOMMUNITY_ROUTE_TARGET
, 0);
5905 vty_out(vty
, "%% Malformed Route Target list\n");
5908 ecommunity_str(ecomadd
);
5910 /* Do nothing if we already have this import route-target */
5911 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5912 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5915 /* Add/update the export route-target */
5916 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5917 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5918 ECOMMUNITY_ROUTE_TARGET
, 0);
5920 vty_out(vty
, "%% Malformed Route Target list\n");
5923 ecommunity_str(ecomadd
);
5925 /* Do nothing if we already have this export route-target */
5926 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5927 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5933 DEFUN (no_bgp_evpn_vrf_rt
,
5934 no_bgp_evpn_vrf_rt_cmd
,
5935 "no route-target <both|import|export> RT",
5938 "import and export\n"
5941 EVPN_ASN_IP_HELP_STR
)
5943 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5944 int rt_type
, found_ecomdel
;
5945 struct ecommunity
*ecomdel
= NULL
;
5950 if (!strcmp(argv
[2]->arg
, "import"))
5951 rt_type
= RT_TYPE_IMPORT
;
5952 else if (!strcmp(argv
[2]->arg
, "export"))
5953 rt_type
= RT_TYPE_EXPORT
;
5954 else if (!strcmp(argv
[2]->arg
, "both"))
5955 rt_type
= RT_TYPE_BOTH
;
5957 vty_out(vty
, "%% Invalid Route Target type\n");
5961 if (rt_type
== RT_TYPE_IMPORT
) {
5962 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5964 "%% Import RT is not configured for this VRF\n");
5967 } else if (rt_type
== RT_TYPE_EXPORT
) {
5968 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5970 "%% Export RT is not configured for this VRF\n");
5973 } else if (rt_type
== RT_TYPE_BOTH
) {
5974 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5975 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5977 "%% Import/Export RT is not configured for this VRF\n");
5982 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5984 vty_out(vty
, "%% Malformed Route Target list\n");
5987 ecommunity_str(ecomdel
);
5989 if (rt_type
== RT_TYPE_IMPORT
) {
5990 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5992 ecommunity_free(&ecomdel
);
5994 "%% RT specified does not match configuration for this VRF\n");
5997 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5998 } else if (rt_type
== RT_TYPE_EXPORT
) {
5999 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6001 ecommunity_free(&ecomdel
);
6003 "%% RT specified does not match configuration for this VRF\n");
6006 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6007 } else if (rt_type
== RT_TYPE_BOTH
) {
6010 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
6012 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
6016 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6018 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6022 if (!found_ecomdel
) {
6023 ecommunity_free(&ecomdel
);
6025 "%% RT specified does not match configuration for this VRF\n");
6030 ecommunity_free(&ecomdel
);
6034 DEFUN (bgp_evpn_vni_rt
,
6035 bgp_evpn_vni_rt_cmd
,
6036 "route-target <both|import|export> RT",
6038 "import and export\n"
6041 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6043 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6044 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6046 struct ecommunity
*ecomadd
= NULL
;
6051 if (!EVPN_ENABLED(bgp
)) {
6053 "This command is only supported under EVPN VRF\n");
6057 if (!strcmp(argv
[1]->text
, "import"))
6058 rt_type
= RT_TYPE_IMPORT
;
6059 else if (!strcmp(argv
[1]->text
, "export"))
6060 rt_type
= RT_TYPE_EXPORT
;
6061 else if (!strcmp(argv
[1]->text
, "both"))
6062 rt_type
= RT_TYPE_BOTH
;
6064 vty_out(vty
, "%% Invalid Route Target type\n");
6068 /* Add/update the import route-target */
6069 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6070 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6071 ECOMMUNITY_ROUTE_TARGET
, 0);
6073 vty_out(vty
, "%% Malformed Route Target list\n");
6076 ecommunity_str(ecomadd
);
6078 /* Do nothing if we already have this import route-target */
6079 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6080 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6083 /* Add/update the export route-target */
6084 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6085 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6086 ECOMMUNITY_ROUTE_TARGET
, 0);
6088 vty_out(vty
, "%% Malformed Route Target list\n");
6091 ecommunity_str(ecomadd
);
6093 /* Do nothing if we already have this export route-target */
6094 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6095 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6101 DEFUN (no_bgp_evpn_vni_rt
,
6102 no_bgp_evpn_vni_rt_cmd
,
6103 "no route-target <both|import|export> RT",
6106 "import and export\n"
6109 EVPN_ASN_IP_HELP_STR
)
6111 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6112 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6113 int rt_type
, found_ecomdel
;
6114 struct ecommunity
*ecomdel
= NULL
;
6119 if (!EVPN_ENABLED(bgp
)) {
6121 "This command is only supported under EVPN VRF\n");
6125 if (!strcmp(argv
[2]->text
, "import"))
6126 rt_type
= RT_TYPE_IMPORT
;
6127 else if (!strcmp(argv
[2]->text
, "export"))
6128 rt_type
= RT_TYPE_EXPORT
;
6129 else if (!strcmp(argv
[2]->text
, "both"))
6130 rt_type
= RT_TYPE_BOTH
;
6132 vty_out(vty
, "%% Invalid Route Target type\n");
6136 /* The user did "no route-target import", check to see if there are any
6137 * import route-targets configured. */
6138 if (rt_type
== RT_TYPE_IMPORT
) {
6139 if (!is_import_rt_configured(vpn
)) {
6141 "%% Import RT is not configured for this VNI\n");
6144 } else if (rt_type
== RT_TYPE_EXPORT
) {
6145 if (!is_export_rt_configured(vpn
)) {
6147 "%% Export RT is not configured for this VNI\n");
6150 } else if (rt_type
== RT_TYPE_BOTH
) {
6151 if (!is_import_rt_configured(vpn
)
6152 && !is_export_rt_configured(vpn
)) {
6154 "%% Import/Export RT is not configured for this VNI\n");
6159 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6161 vty_out(vty
, "%% Malformed Route Target list\n");
6164 ecommunity_str(ecomdel
);
6166 if (rt_type
== RT_TYPE_IMPORT
) {
6167 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6169 "%% RT specified does not match configuration for this VNI\n");
6172 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6173 } else if (rt_type
== RT_TYPE_EXPORT
) {
6174 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6176 "%% RT specified does not match configuration for this VNI\n");
6179 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6180 } else if (rt_type
== RT_TYPE_BOTH
) {
6183 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6184 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6188 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6189 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6193 if (!found_ecomdel
) {
6195 "%% RT specified does not match configuration for this VNI\n");
6203 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6204 no_bgp_evpn_vni_rt_without_val_cmd
,
6205 "no route-target <import|export>",
6211 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6212 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6218 if (!EVPN_ENABLED(bgp
)) {
6220 "This command is only supported under EVPN VRF\n");
6224 if (!strcmp(argv
[2]->text
, "import")) {
6225 rt_type
= RT_TYPE_IMPORT
;
6226 } else if (!strcmp(argv
[2]->text
, "export")) {
6227 rt_type
= RT_TYPE_EXPORT
;
6229 vty_out(vty
, "%% Invalid Route Target type\n");
6233 /* Check if we should disallow. */
6234 if (rt_type
== RT_TYPE_IMPORT
) {
6235 if (!is_import_rt_configured(vpn
)) {
6237 "%% Import RT is not configured for this VNI\n");
6241 if (!is_export_rt_configured(vpn
)) {
6243 "%% Export RT is not configured for this VNI\n");
6248 /* Unconfigure the RT. */
6249 if (rt_type
== RT_TYPE_IMPORT
)
6250 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6252 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6256 static int vni_cmp(const void **a
, const void **b
)
6258 const struct bgpevpn
*first
= *a
;
6259 const struct bgpevpn
*secnd
= *b
;
6261 return secnd
->vni
- first
->vni
;
6265 * Output EVPN configuration information.
6267 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6270 char buf1
[RD_ADDRSTRLEN
];
6271 char buf2
[INET6_ADDRSTRLEN
];
6273 if (bgp
->advertise_all_vni
)
6274 vty_out(vty
, " advertise-all-vni\n");
6277 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6278 struct listnode
*ln
;
6279 struct bgpevpn
*data
;
6281 list_sort(vnilist
, vni_cmp
);
6282 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6283 write_vni_config(vty
, data
);
6285 list_delete(&vnilist
);
6288 if (bgp
->advertise_autort_rfc8365
)
6289 vty_out(vty
, " autort rfc8365-compatible\n");
6291 if (bgp
->advertise_gw_macip
)
6292 vty_out(vty
, " advertise-default-gw\n");
6294 if (bgp
->evpn_info
->advertise_svi_macip
)
6295 vty_out(vty
, " advertise-svi-ip\n");
6297 if (bgp
->resolve_overlay_index
)
6298 vty_out(vty
, " enable-resolve-overlay-index\n");
6300 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6301 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6302 if (bgp_mh_info
->host_routes_use_l3nhg
)
6303 vty_out(vty
, " use-es-l3nhg\n");
6305 vty_out(vty
, " no use-es-l3nhg\n");
6308 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6309 if (bgp_mh_info
->ead_evi_rx
)
6310 vty_out(vty
, " no disable-ead-evi-rx\n");
6312 vty_out(vty
, " disable-ead-evi-rx\n");
6315 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6316 if (bgp_mh_info
->ead_evi_tx
)
6317 vty_out(vty
, " no disable-ead-evi-tx\n");
6319 vty_out(vty
, " disable-ead-evi-tx\n");
6322 if (!bgp
->evpn_info
->dup_addr_detect
)
6323 vty_out(vty
, " no dup-addr-detection\n");
6325 if (bgp
->evpn_info
->dad_max_moves
!=
6326 EVPN_DAD_DEFAULT_MAX_MOVES
||
6327 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6328 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6329 bgp
->evpn_info
->dad_max_moves
,
6330 bgp
->evpn_info
->dad_time
);
6332 if (bgp
->evpn_info
->dad_freeze
) {
6333 if (bgp
->evpn_info
->dad_freeze_time
)
6335 " dup-addr-detection freeze %u\n",
6336 bgp
->evpn_info
->dad_freeze_time
);
6339 " dup-addr-detection freeze permanent\n");
6342 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6343 vty_out(vty
, " flooding disable\n");
6345 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6346 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6347 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6348 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6349 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6352 " advertise ipv4 unicast\n");
6353 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6354 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6355 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6357 " advertise ipv4 unicast gateway-ip route-map %s\n",
6358 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6360 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6363 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6364 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6365 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6367 " advertise ipv6 unicast route-map %s\n",
6368 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6371 " advertise ipv6 unicast\n");
6372 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6373 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6374 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6376 " advertise ipv6 unicast gateway-ip route-map %s\n",
6377 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6379 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6382 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6383 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6384 vty_out(vty
, " default-originate ipv4\n");
6386 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6387 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6388 vty_out(vty
, " default-originate ipv6\n");
6390 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6391 if (!bgp
->evpn_info
->advertise_pip
)
6392 vty_out(vty
, " no advertise-pip\n");
6393 if (bgp
->evpn_info
->advertise_pip
) {
6394 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6396 vty_out(vty
, " advertise-pip ip %s",
6398 &bgp
->evpn_info
->pip_ip_static
,
6399 buf2
, INET_ADDRSTRLEN
));
6401 bgp
->evpn_info
->pip_rmac_static
))) {
6402 char buf
[ETHER_ADDR_STRLEN
];
6404 vty_out(vty
, " mac %s",
6414 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6415 vty_out(vty
, " rd %s\n",
6416 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6418 /* import route-target */
6419 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6421 struct listnode
*node
, *nnode
;
6422 struct ecommunity
*ecom
;
6424 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6426 ecom_str
= ecommunity_ecom2str(
6427 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6428 vty_out(vty
, " route-target import %s\n", ecom_str
);
6429 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6433 /* export route-target */
6434 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6436 struct listnode
*node
, *nnode
;
6437 struct ecommunity
*ecom
;
6439 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6441 ecom_str
= ecommunity_ecom2str(
6442 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6443 vty_out(vty
, " route-target export %s\n", ecom_str
);
6444 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6449 void bgp_ethernetvpn_init(void)
6451 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6452 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6453 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6454 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6455 install_element(VIEW_NODE
,
6456 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6457 install_element(VIEW_NODE
,
6458 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6461 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6464 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6465 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6466 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6467 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6468 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6469 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6470 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6471 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6472 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6473 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6474 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6475 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6476 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6477 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6478 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6479 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6480 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6481 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6482 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6483 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6484 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6485 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6486 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6487 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6488 install_element(BGP_EVPN_NODE
,
6489 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6492 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6493 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6495 /* "show bgp l2vpn evpn" commands. */
6496 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6497 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6498 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6499 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6500 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6501 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6502 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6503 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6504 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6505 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6506 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6507 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6508 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6509 install_element(VIEW_NODE
,
6510 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6511 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6512 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6513 install_element(VIEW_NODE
,
6514 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6515 install_element(VIEW_NODE
,
6516 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6517 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6518 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6520 /* "show bgp evpn" commands. */
6521 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6522 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6523 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6524 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6525 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6526 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6527 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6528 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6529 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6530 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6531 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6532 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6534 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6535 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6536 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6537 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6538 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6539 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6540 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6541 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6542 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6543 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6544 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6545 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6546 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6547 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6548 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6549 install_element(BGP_EVPN_VNI_NODE
,
6550 &bgp_evpn_advertise_default_gw_vni_cmd
);
6551 install_element(BGP_EVPN_VNI_NODE
,
6552 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6553 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6554 install_element(BGP_EVPN_VNI_NODE
,
6555 &no_bgp_evpn_advertise_vni_subnet_cmd
);