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]:[ESI]:[EthTag]:[IPlen]:[VTEP-IP]\n");
363 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
364 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
365 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
366 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
367 vty_out(vty
, "%s", ri_header
);
370 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
373 char buf1
[INET6_ADDRSTRLEN
];
375 struct listnode
*node
, *nnode
;
376 struct ecommunity
*ecom
;
377 json_object
*json_import_rtl
= NULL
;
378 json_object
*json_export_rtl
= NULL
;
379 char buf2
[ETHER_ADDR_STRLEN
];
380 char originator_ip
[BUFSIZ
] = {0};
382 json_import_rtl
= json_export_rtl
= 0;
385 json_import_rtl
= json_object_new_array();
386 json_export_rtl
= json_object_new_array();
387 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
388 json_object_string_add(json
, "type", "L3");
389 json_object_string_add(json
, "inKernel", "True");
390 json_object_string_add(
392 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
393 json_object_string_add(
394 json
, "originatorIp",
395 inet_ntop(AF_INET
, &bgp_vrf
->originator_ip
,
396 originator_ip
, sizeof(originator_ip
)));
397 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
398 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
399 json_object_to_json_string_ext(json
,
400 JSON_C_TO_STRING_NOSLASHESCAPE
);
401 json_object_string_add(json
, "advertisePip",
402 bgp_vrf
->evpn_info
->advertise_pip
?
403 "Enabled" : "Disabled");
404 json_object_string_add(json
, "sysIP",
406 &bgp_vrf
->evpn_info
->pip_ip
,
407 buf1
, INET_ADDRSTRLEN
));
408 json_object_string_add(json
, "sysMac",
409 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
410 buf2
, sizeof(buf2
)));
411 json_object_string_add(json
, "rmac",
412 prefix_mac2str(&bgp_vrf
->rmac
,
413 buf2
, sizeof(buf2
)));
415 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
416 vty_out(vty
, " (known to the kernel)");
419 vty_out(vty
, " Type: %s\n", "L3");
420 vty_out(vty
, " Tenant VRF: %s\n",
421 vrf_id_to_name(bgp_vrf
->vrf_id
));
422 vty_out(vty
, " RD: %s\n",
423 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
424 vty_out(vty
, " Originator IP: %pI4\n",
425 &bgp_vrf
->originator_ip
);
426 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
427 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
428 vty_out(vty
, " Advertise-pip: %s\n",
429 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
430 vty_out(vty
, " System-IP: %s\n",
431 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
432 buf1
, INET_ADDRSTRLEN
));
433 vty_out(vty
, " System-MAC: %s\n",
434 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
435 buf2
, sizeof(buf2
)));
436 vty_out(vty
, " Router-MAC: %s\n",
437 prefix_mac2str(&bgp_vrf
->rmac
,
438 buf2
, sizeof(buf2
)));
442 vty_out(vty
, " Import Route Target:\n");
444 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
445 ecom_str
= ecommunity_ecom2str(ecom
,
446 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
449 json_object_array_add(json_import_rtl
,
450 json_object_new_string(ecom_str
));
452 vty_out(vty
, " %s\n", ecom_str
);
454 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
458 json_object_object_add(json
, "importRts", json_import_rtl
);
460 vty_out(vty
, " Export Route Target:\n");
462 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
463 ecom_str
= ecommunity_ecom2str(ecom
,
464 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
467 json_object_array_add(json_export_rtl
,
468 json_object_new_string(ecom_str
));
470 vty_out(vty
, " %s\n", ecom_str
);
472 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
476 json_object_object_add(json
, "exportRts", json_export_rtl
);
479 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
481 char buf1
[RD_ADDRSTRLEN
];
483 struct listnode
*node
, *nnode
;
484 struct ecommunity
*ecom
;
485 json_object
*json_import_rtl
= NULL
;
486 json_object
*json_export_rtl
= NULL
;
487 struct bgp
*bgp_evpn
;
488 char buf
[BUFSIZ
] = {0};
490 bgp_evpn
= bgp_get_evpn();
493 json_import_rtl
= json_object_new_array();
494 json_export_rtl
= json_object_new_array();
495 json_object_int_add(json
, "vni", vpn
->vni
);
496 json_object_string_add(json
, "type", "L2");
497 json_object_string_add(json
, "inKernel",
498 is_vni_live(vpn
) ? "True" : "False");
499 json_object_string_add(
501 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
502 json_object_string_add(json
, "originatorIp",
503 inet_ntop(AF_INET
, &vpn
->originator_ip
,
505 json_object_string_add(
507 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf
, sizeof(buf
)));
508 /* per vni knob is enabled -- Enabled
509 * Global knob is enabled -- Active
510 * default -- Disabled
512 if (!vpn
->advertise_gw_macip
&&
513 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
514 json_object_string_add(json
, "advertiseGatewayMacip",
516 else if (vpn
->advertise_gw_macip
)
517 json_object_string_add(json
, "advertiseGatewayMacip",
520 json_object_string_add(json
, "advertiseGatewayMacip",
522 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
523 bgp_evpn
->evpn_info
->advertise_svi_macip
)
524 json_object_string_add(json
, "advertiseSviMacIp",
526 else if (vpn
->advertise_svi_macip
)
527 json_object_string_add(json
, "advertiseSviMacIp",
530 json_object_string_add(json
, "advertiseSviMacIp",
532 json_object_string_add(
533 json
, "sviInterface",
534 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
536 vty_out(vty
, "VNI: %d", vpn
->vni
);
537 if (is_vni_live(vpn
))
538 vty_out(vty
, " (known to the kernel)");
541 vty_out(vty
, " Type: %s\n", "L2");
542 vty_out(vty
, " Tenant-Vrf: %s\n",
543 vrf_id_to_name(vpn
->tenant_vrf_id
));
544 vty_out(vty
, " RD: %s\n",
545 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
546 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
547 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
548 if (!vpn
->advertise_gw_macip
&&
549 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
550 vty_out(vty
, " Advertise-gw-macip : %s\n",
552 else if (vpn
->advertise_gw_macip
)
553 vty_out(vty
, " Advertise-gw-macip : %s\n",
556 vty_out(vty
, " Advertise-gw-macip : %s\n",
558 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
559 bgp_evpn
->evpn_info
->advertise_svi_macip
)
560 vty_out(vty
, " Advertise-svi-macip : %s\n",
562 else if (vpn
->advertise_svi_macip
)
563 vty_out(vty
, " Advertise-svi-macip : %s\n",
566 vty_out(vty
, " Advertise-svi-macip : %s\n",
568 vty_out(vty
, " SVI interface : %s\n",
569 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
573 vty_out(vty
, " Import Route Target:\n");
575 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
576 ecom_str
= ecommunity_ecom2str(ecom
,
577 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
580 json_object_array_add(json_import_rtl
,
581 json_object_new_string(ecom_str
));
583 vty_out(vty
, " %s\n", ecom_str
);
585 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
589 json_object_object_add(json
, "importRts", json_import_rtl
);
591 vty_out(vty
, " Export Route Target:\n");
593 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
594 ecom_str
= ecommunity_ecom2str(ecom
,
595 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
598 json_object_array_add(json_export_rtl
,
599 json_object_new_string(ecom_str
));
601 vty_out(vty
, " %s\n", ecom_str
);
603 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
607 json_object_object_add(json
, "exportRts", json_export_rtl
);
610 static void show_esi_routes(struct bgp
*bgp
,
611 struct bgp_evpn_es
*es
,
616 struct bgp_dest
*dest
;
617 struct bgp_path_info
*pi
;
618 uint32_t prefix_cnt
, path_cnt
;
621 prefix_cnt
= path_cnt
= 0;
623 tbl_ver
= es
->route_table
->version
;
624 for (dest
= bgp_table_top(es
->route_table
); dest
;
625 dest
= bgp_route_next(dest
)) {
626 int add_prefix_to_json
= 0;
627 char prefix_str
[BUFSIZ
];
628 json_object
*json_paths
= NULL
;
629 json_object
*json_prefix
= NULL
;
630 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
632 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
636 json_prefix
= json_object_new_object();
638 pi
= bgp_dest_get_bgp_path_info(dest
);
640 /* Overall header/legend displayed once. */
642 bgp_evpn_show_route_header(vty
, bgp
,
651 json_paths
= json_object_new_array();
653 /* For EVPN, the prefix is displayed for each path (to fit in
654 * with code that already exists).
656 for (; pi
; pi
= pi
->next
) {
657 json_object
*json_path
= NULL
;
660 json_path
= json_object_new_array();
662 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
666 json_object_array_add(json_paths
, json_path
);
669 add_prefix_to_json
= 1;
673 if (add_prefix_to_json
) {
674 json_object_string_add(json_prefix
, "prefix",
676 json_object_int_add(json_prefix
, "prefixLen",
678 json_object_object_add(json_prefix
, "paths",
680 json_object_object_add(json
, prefix_str
,
683 json_object_free(json_paths
);
684 json_object_free(json_prefix
);
692 json_object_int_add(json
, "numPrefix", prefix_cnt
);
693 json_object_int_add(json
, "numPaths", path_cnt
);
696 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
698 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
699 prefix_cnt
, path_cnt
);
703 /* Display all MAC-IP VNI routes linked to an ES */
704 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
705 json_object
*json
, int detail
,
709 struct bgp_path_info
*pi
;
710 int header
= detail
? 0 : 1;
712 struct listnode
*node
;
713 struct bgp_evpn_es
*es
;
714 struct bgp_path_es_info
*es_info
;
715 struct bgp
*bgp
= bgp_get_evpn();
716 json_object
*json_paths
= NULL
;
724 json_paths
= json_object_new_array();
726 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
727 struct list
*es_list
;
729 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
733 es_list
= es
->macip_global_path_list
;
735 es_list
= es
->macip_evi_path_list
;
737 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
738 json_object
*json_path
= NULL
;
743 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
746 /* Overall header/legend displayed once. */
748 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
755 json_path
= json_object_new_array();
758 route_vty_out_detail(
759 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
760 RPKI_NOT_BEING_USED
, json_path
);
762 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
766 json_object_array_add(json_paths
, json_path
);
771 json_object_object_add(json
, "paths", json_paths
);
772 json_object_int_add(json
, "numPaths", path_cnt
);
775 vty_out(vty
, "There are no MAC-IP ES paths");
777 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
782 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
783 json_object
*json
, int detail
)
785 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
788 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
789 json_object
*json
, int detail
)
791 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
794 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
795 struct vty
*vty
, struct in_addr vtep_ip
,
796 json_object
*json
, int detail
)
798 struct bgp_dest
*dest
;
799 struct bgp_path_info
*pi
;
800 struct bgp_table
*table
;
801 int header
= detail
? 0 : 1;
803 uint32_t prefix_cnt
, path_cnt
;
805 prefix_cnt
= path_cnt
= 0;
807 table
= vpn
->route_table
;
808 tbl_ver
= table
->version
;
809 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
810 const struct prefix_evpn
*evp
=
811 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
812 int add_prefix_to_json
= 0;
813 char prefix_str
[BUFSIZ
];
814 json_object
*json_paths
= NULL
;
815 json_object
*json_prefix
= NULL
;
816 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
818 prefix2str((struct prefix_evpn
*)bgp_dest_get_prefix(dest
),
819 prefix_str
, sizeof(prefix_str
));
821 if (type
&& evp
->prefix
.route_type
!= type
)
825 json_prefix
= json_object_new_object();
827 pi
= bgp_dest_get_bgp_path_info(dest
);
829 /* Overall header/legend displayed once. */
831 bgp_evpn_show_route_header(vty
, bgp
,
840 json_paths
= json_object_new_array();
842 /* For EVPN, the prefix is displayed for each path (to fit in
843 * with code that already exists).
845 for (; pi
; pi
= pi
->next
) {
846 json_object
*json_path
= NULL
;
848 if (vtep_ip
.s_addr
!= INADDR_ANY
849 && !IPV4_ADDR_SAME(&(vtep_ip
),
850 &(pi
->attr
->nexthop
)))
854 json_path
= json_object_new_array();
857 route_vty_out_detail(vty
, bgp
, dest
, pi
,
858 AFI_L2VPN
, SAFI_EVPN
,
862 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
866 json_object_array_add(json_paths
, json_path
);
869 add_prefix_to_json
= 1;
873 if (add_prefix_to_json
) {
874 json_object_string_add(json_prefix
, "prefix",
876 json_object_int_add(json_prefix
, "prefixLen",
878 json_object_object_add(json_prefix
, "paths",
880 json_object_object_add(json
, prefix_str
,
883 json_object_free(json_paths
);
884 json_object_free(json_prefix
);
892 json_object_int_add(json
, "numPrefix", prefix_cnt
);
893 json_object_int_add(json
, "numPaths", path_cnt
);
896 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
897 type
? "(of requested type) " : "");
899 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
900 prefix_cnt
, path_cnt
,
901 type
? " (of requested type)" : "");
906 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
908 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
909 struct vni_walk_ctx
*wctx
= arg
;
910 struct vty
*vty
= wctx
->vty
;
911 json_object
*json
= wctx
->json
;
912 json_object
*json_vni
= NULL
;
913 char vni_str
[VNI_STR_LEN
];
915 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
917 json_vni
= json_object_new_object();
918 json_object_int_add(json_vni
, "vni", vpn
->vni
);
920 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
923 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
927 json_object_object_add(json
, vni_str
, json_vni
);
930 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
933 json_object
*json_vni
= NULL
;
934 json_object
*json_import_rtl
= NULL
;
935 json_object
*json_export_rtl
= NULL
;
937 char buf2
[INET6_ADDRSTRLEN
];
938 char buf3
[BUFSIZ
] = {0};
941 struct listnode
*node
, *nnode
;
942 struct ecommunity
*ecom
;
948 json_vni
= json_object_new_object();
949 json_import_rtl
= json_object_new_array();
950 json_export_rtl
= json_object_new_array();
953 /* if an l3vni is present in bgp it is live */
955 snprintf(buf1
, sizeof(buf1
), "*");
958 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
959 json_object_string_add(json_vni
, "type", "L3");
960 json_object_string_add(json_vni
, "inKernel", "True");
961 json_object_string_add(json_vni
, "originatorIp",
962 inet_ntop(AF_INET
, &bgp
->originator_ip
,
963 buf3
, sizeof(buf3
)));
964 json_object_string_add(
966 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
967 json_object_string_add(json_vni
, "advertiseGatewayMacip",
969 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
970 json_object_to_json_string_ext(json_vni
,
971 JSON_C_TO_STRING_NOSLASHESCAPE
);
972 json_object_string_add(
973 json_vni
, "advertisePip",
974 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
975 json_object_string_add(json_vni
, "sysIP",
977 &bgp
->evpn_info
->pip_ip
, buf3
,
979 json_object_string_add(json_vni
, "sysMAC",
980 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
981 buf2
, sizeof(buf2
)));
982 json_object_string_add(
984 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
986 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
987 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
990 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
991 ecom_str
= ecommunity_ecom2str(ecom
,
992 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
995 json_object_array_add(json_import_rtl
,
996 json_object_new_string(ecom_str
));
998 if (listcount(bgp
->vrf_import_rtl
) > 1)
999 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1002 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1004 vty_out(vty
, " %-25s", rt_buf
);
1007 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1009 /* If there are multiple import RTs we break here and show only
1016 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1018 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
1019 ecom_str
= ecommunity_ecom2str(ecom
,
1020 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1023 json_object_array_add(json_export_rtl
,
1024 json_object_new_string(ecom_str
));
1026 if (listcount(bgp
->vrf_export_rtl
) > 1)
1027 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1030 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1032 vty_out(vty
, " %-25s", rt_buf
);
1035 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1037 /* If there are multiple export RTs we break here and show only
1044 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1047 char vni_str
[VNI_STR_LEN
];
1049 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1050 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1051 json_object_object_add(json
, vni_str
, json_vni
);
1057 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1061 json_object
*json_vni
= NULL
;
1062 json_object
*json_import_rtl
= NULL
;
1063 json_object
*json_export_rtl
= NULL
;
1064 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1066 char buf2
[RD_ADDRSTRLEN
];
1067 char buf3
[BUFSIZ
] = {0};
1070 struct listnode
*node
, *nnode
;
1071 struct ecommunity
*ecom
;
1072 struct bgp
*bgp_evpn
;
1077 bgp_evpn
= bgp_get_evpn();
1080 json_vni
= json_object_new_object();
1081 json_import_rtl
= json_object_new_array();
1082 json_export_rtl
= json_object_new_array();
1086 if (is_vni_live(vpn
))
1087 snprintf(buf1
, sizeof(buf1
), "*");
1090 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1091 json_object_string_add(json_vni
, "type", "L2");
1092 json_object_string_add(json_vni
, "inKernel",
1093 is_vni_live(vpn
) ? "True" : "False");
1094 json_object_string_add(
1096 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1097 json_object_string_add(json_vni
, "originatorIp",
1098 inet_ntop(AF_INET
, &vpn
->originator_ip
,
1099 buf3
, sizeof(buf3
)));
1100 json_object_string_add(json_vni
, "mcastGroup",
1101 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf3
,
1103 /* per vni knob is enabled -- Enabled
1104 * Global knob is enabled -- Active
1105 * default -- Disabled
1107 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1108 && bgp_evpn
->advertise_gw_macip
)
1109 json_object_string_add(
1110 json_vni
, "advertiseGatewayMacip", "Active");
1111 else if (vpn
->advertise_gw_macip
)
1112 json_object_string_add(
1113 json_vni
, "advertiseGatewayMacip", "Enabled");
1115 json_object_string_add(
1116 json_vni
, "advertiseGatewayMacip", "Disabled");
1117 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1118 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1119 json_object_string_add(json_vni
, "advertiseSviMacIp",
1121 else if (vpn
->advertise_svi_macip
)
1122 json_object_string_add(json_vni
, "advertiseSviMacIp",
1125 json_object_string_add(json_vni
, "advertiseSviMacIp",
1128 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1129 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1132 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1133 ecom_str
= ecommunity_ecom2str(ecom
,
1134 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1137 json_object_array_add(json_import_rtl
,
1138 json_object_new_string(ecom_str
));
1140 if (listcount(vpn
->import_rtl
) > 1)
1141 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1144 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1146 vty_out(vty
, " %-25s", rt_buf
);
1149 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1151 /* If there are multiple import RTs we break here and show only
1158 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1160 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1161 ecom_str
= ecommunity_ecom2str(ecom
,
1162 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1165 json_object_array_add(json_export_rtl
,
1166 json_object_new_string(ecom_str
));
1168 if (listcount(vpn
->export_rtl
) > 1)
1169 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1172 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1174 vty_out(vty
, " %-25s", rt_buf
);
1177 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1179 /* If there are multiple export RTs we break here and show only
1186 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1189 char vni_str
[VNI_STR_LEN
];
1191 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1192 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1193 json_object_object_add(json
, vni_str
, json_vni
);
1199 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1200 enum bgp_show_type type
, void *output_arg
,
1201 int option
, bool use_json
)
1203 afi_t afi
= AFI_L2VPN
;
1205 struct bgp_table
*table
;
1206 struct bgp_dest
*dest
;
1207 struct bgp_dest
*rm
;
1208 struct bgp_path_info
*pi
;
1211 char rd_str
[RD_ADDRSTRLEN
];
1214 char router_id
[BUFSIZ
] = {0};
1216 unsigned long output_count
= 0;
1217 unsigned long total_count
= 0;
1218 json_object
*json
= NULL
;
1219 json_object
*json_array
= NULL
;
1220 json_object
*json_prefix_info
= NULL
;
1222 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1224 bgp
= bgp_get_evpn();
1227 vty_out(vty
, "No BGP process is configured\n");
1229 vty_out(vty
, "{}\n");
1234 json
= json_object_new_object();
1236 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1237 dest
= bgp_route_next(dest
)) {
1239 json_object
*json_nroute
= NULL
;
1240 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1242 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1245 table
= bgp_dest_get_bgp_table_info(dest
);
1250 tbl_ver
= table
->version
;
1252 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1253 pi
= bgp_dest_get_bgp_path_info(rm
);
1258 for (; pi
; pi
= pi
->next
) {
1260 if (type
== bgp_show_type_neighbor
) {
1261 struct peer
*peer
= output_arg
;
1263 if (peer_cmp(peer
, pi
->peer
) != 0)
1266 if (type
== bgp_show_type_lcommunity_exact
) {
1267 struct lcommunity
*lcom
= output_arg
;
1269 if (!pi
->attr
->lcommunity
||
1271 pi
->attr
->lcommunity
, lcom
))
1274 if (type
== bgp_show_type_lcommunity
) {
1275 struct lcommunity
*lcom
= output_arg
;
1277 if (!pi
->attr
->lcommunity
||
1279 pi
->attr
->lcommunity
, lcom
))
1282 if (type
== bgp_show_type_community
) {
1283 struct community
*com
= output_arg
;
1285 if (!pi
->attr
->community
||
1287 pi
->attr
->community
, com
))
1290 if (type
== bgp_show_type_community_exact
) {
1291 struct community
*com
= output_arg
;
1293 if (!pi
->attr
->community
||
1295 pi
->attr
->community
, com
))
1300 json_object_int_add(
1301 json
, "bgpTableVersion",
1303 json_object_string_add(
1310 sizeof(router_id
)));
1311 json_object_int_add(
1314 bgp
->default_local_pref
);
1315 json_object_int_add(
1319 if (option
== SHOW_DISPLAY_TAGS
)
1324 == SHOW_DISPLAY_OVERLAY
)
1328 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1336 json_object_new_object();
1337 bgp_evpn_show_route_rd_header(
1338 vty
, dest
, json_nroute
, rd_str
,
1342 if (use_json
&& !json_array
)
1343 json_array
= json_object_new_array();
1345 if (option
== SHOW_DISPLAY_TAGS
)
1347 vty
, bgp_dest_get_prefix(rm
),
1348 pi
, no_display
, SAFI_EVPN
,
1350 else if (option
== SHOW_DISPLAY_OVERLAY
)
1351 route_vty_out_overlay(
1352 vty
, bgp_dest_get_prefix(rm
),
1353 pi
, no_display
, json_array
);
1356 bgp_dest_get_prefix(rm
),
1357 pi
, no_display
, SAFI_EVPN
,
1365 if (use_json
&& json_array
) {
1366 const struct prefix
*p
=
1367 bgp_dest_get_prefix(rm
);
1369 json_prefix_info
= json_object_new_object();
1371 json_object_string_add(
1372 json_prefix_info
, "prefix",
1373 prefix2str((struct prefix_evpn
*)p
, buf
,
1376 json_object_int_add(json_prefix_info
,
1377 "prefixLen", p
->prefixlen
);
1379 json_object_object_add(json_prefix_info
,
1380 "paths", json_array
);
1381 json_object_object_add(json_nroute
, buf
,
1387 if (use_json
&& json_nroute
)
1388 json_object_object_add(json
, rd_str
, json_nroute
);
1392 json_object_int_add(json
, "numPrefix", output_count
);
1393 json_object_int_add(json
, "totalPrefix", total_count
);
1394 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1395 json
, JSON_C_TO_STRING_PRETTY
));
1396 json_object_free(json
);
1398 if (output_count
== 0)
1399 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1403 "\nDisplayed %ld out of %ld total prefixes\n",
1404 output_count
, total_count
);
1409 DEFUN(show_ip_bgp_l2vpn_evpn
,
1410 show_ip_bgp_l2vpn_evpn_cmd
,
1411 "show [ip] bgp l2vpn evpn [json]",
1412 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1414 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1415 SHOW_DISPLAY_STANDARD
,
1416 use_json(argc
, argv
));
1419 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1420 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1421 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1427 "Display information for a route distinguisher\n"
1428 "VPN Route Distinguisher\n"
1429 "All VPN Route Distinguishers\n"
1432 int idx_ext_community
= 0;
1434 struct prefix_rd prd
;
1437 argv_find(argv
, argc
, "all", &rd_all
);
1439 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1440 NULL
, SHOW_DISPLAY_STANDARD
,
1441 use_json(argc
, argv
));
1443 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1444 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1446 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1449 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1450 SHOW_DISPLAY_STANDARD
,
1451 use_json(argc
, argv
));
1454 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1455 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1456 "show [ip] bgp l2vpn evpn all tags",
1462 "Display information about all EVPN NLRIs\n"
1463 "Display BGP tags for prefixes\n")
1465 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1466 SHOW_DISPLAY_TAGS
, 0);
1469 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1470 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1471 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1477 "Display information for a route distinguisher\n"
1478 "VPN Route Distinguisher\n"
1479 "All VPN Route Distinguishers\n"
1480 "Display BGP tags for prefixes\n")
1482 int idx_ext_community
= 0;
1484 struct prefix_rd prd
;
1487 argv_find(argv
, argc
, "all", &rd_all
);
1489 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1490 NULL
, SHOW_DISPLAY_TAGS
, 0);
1492 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1493 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1495 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1498 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1499 SHOW_DISPLAY_TAGS
, 0);
1502 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1503 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1504 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1510 "Detailed information on TCP and BGP neighbor connections\n"
1511 "IPv4 Neighbor to display information about\n"
1512 "IPv6 Neighbor to display information about\n"
1513 "Neighbor on BGP configured interface\n"
1514 "Display routes learned from neighbor\n" JSON_STR
)
1518 char *peerstr
= NULL
;
1519 bool uj
= use_json(argc
, argv
);
1520 afi_t afi
= AFI_L2VPN
;
1521 safi_t safi
= SAFI_EVPN
;
1522 struct bgp
*bgp
= NULL
;
1524 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1527 vty_out(vty
, "No index\n");
1531 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1532 argv_find(argv
, argc
, "neighbors", &idx
);
1533 peerstr
= argv
[++idx
]->arg
;
1535 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1538 json_object
*json_no
= NULL
;
1539 json_no
= json_object_new_object();
1540 json_object_string_add(json_no
, "warning",
1541 "Malformed address");
1542 vty_out(vty
, "%s\n",
1543 json_object_to_json_string(json_no
));
1544 json_object_free(json_no
);
1546 vty_out(vty
, "Malformed address: %s\n",
1550 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1552 json_object
*json_no
= NULL
;
1553 json_no
= json_object_new_object();
1554 json_object_string_add(
1556 "No such neighbor or address family");
1557 vty_out(vty
, "%s\n",
1558 json_object_to_json_string(json_no
));
1559 json_object_free(json_no
);
1561 vty_out(vty
, "%% No such neighbor or address family\n");
1565 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1566 SHOW_DISPLAY_STANDARD
, uj
);
1569 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1570 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1571 "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]",
1577 "Display information for a route distinguisher\n"
1578 "VPN Route Distinguisher\n"
1579 "All VPN Route Distinguishers\n"
1580 "Detailed information on TCP and BGP neighbor connections\n"
1581 "IPv4 Neighbor to display information about\n"
1582 "IPv6 Neighbor to display information about\n"
1583 "Neighbor on BGP configured interface\n"
1584 "Display routes learned from neighbor\n" JSON_STR
)
1586 int idx_ext_community
= 0;
1590 char *peerstr
= NULL
;
1591 struct prefix_rd prd
;
1592 bool uj
= use_json(argc
, argv
);
1593 afi_t afi
= AFI_L2VPN
;
1594 safi_t safi
= SAFI_EVPN
;
1595 struct bgp
*bgp
= NULL
;
1598 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1601 vty_out(vty
, "No index\n");
1605 argv_find(argv
, argc
, "all", &rd_all
);
1607 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1608 &idx_ext_community
);
1609 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1612 json_object
*json_no
= NULL
;
1613 json_no
= json_object_new_object();
1614 json_object_string_add(
1616 "Malformed Route Distinguisher");
1617 vty_out(vty
, "%s\n",
1618 json_object_to_json_string(json_no
));
1619 json_object_free(json_no
);
1622 "%% Malformed Route Distinguisher\n");
1627 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1628 argv_find(argv
, argc
, "neighbors", &idx
);
1629 peerstr
= argv
[++idx
]->arg
;
1631 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1634 json_object
*json_no
= NULL
;
1635 json_no
= json_object_new_object();
1636 json_object_string_add(json_no
, "warning",
1637 "Malformed address");
1638 vty_out(vty
, "%s\n",
1639 json_object_to_json_string(json_no
));
1640 json_object_free(json_no
);
1642 vty_out(vty
, "Malformed address: %s\n",
1646 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1648 json_object
*json_no
= NULL
;
1649 json_no
= json_object_new_object();
1650 json_object_string_add(
1652 "No such neighbor or address family");
1653 vty_out(vty
, "%s\n",
1654 json_object_to_json_string(json_no
));
1655 json_object_free(json_no
);
1657 vty_out(vty
, "%% No such neighbor or address family\n");
1663 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1664 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1666 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1667 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1670 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1671 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1672 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1678 "Detailed information on TCP and BGP neighbor connections\n"
1679 "IPv4 Neighbor to display information about\n"
1680 "IPv6 Neighbor to display information about\n"
1681 "Neighbor on BGP configured interface\n"
1682 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1686 bool uj
= use_json(argc
, argv
);
1687 struct bgp
*bgp
= NULL
;
1688 afi_t afi
= AFI_L2VPN
;
1689 safi_t safi
= SAFI_EVPN
;
1690 char *peerstr
= NULL
;
1695 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1698 vty_out(vty
, "No index\n");
1702 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1703 argv_find(argv
, argc
, "neighbors", &idx
);
1704 peerstr
= argv
[++idx
]->arg
;
1706 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1709 json_object
*json_no
= NULL
;
1710 json_no
= json_object_new_object();
1711 json_object_string_add(json_no
, "warning",
1712 "Malformed address");
1713 vty_out(vty
, "%s\n",
1714 json_object_to_json_string(json_no
));
1715 json_object_free(json_no
);
1717 vty_out(vty
, "Malformed address: %s\n",
1721 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1723 json_object
*json_no
= NULL
;
1724 json_no
= json_object_new_object();
1725 json_object_string_add(
1727 "No such neighbor or address family");
1728 vty_out(vty
, "%s\n",
1729 json_object_to_json_string(json_no
));
1730 json_object_free(json_no
);
1732 vty_out(vty
, "%% No such neighbor or address family\n");
1736 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1739 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1740 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1741 "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]",
1747 "Display information for a route distinguisher\n"
1748 "VPN Route Distinguisher\n"
1749 "All VPN Route Distinguishers\n"
1750 "Detailed information on TCP and BGP neighbor connections\n"
1751 "IPv4 Neighbor to display information about\n"
1752 "IPv6 Neighbor to display information about\n"
1753 "Neighbor on BGP configured interface\n"
1754 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1756 int idx_ext_community
= 0;
1760 struct prefix_rd prd
;
1761 struct bgp
*bgp
= NULL
;
1762 bool uj
= use_json(argc
, argv
);
1763 char *peerstr
= NULL
;
1764 afi_t afi
= AFI_L2VPN
;
1765 safi_t safi
= SAFI_EVPN
;
1774 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1777 vty_out(vty
, "No index\n");
1781 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1782 argv_find(argv
, argc
, "neighbors", &idx
);
1783 peerstr
= argv
[++idx
]->arg
;
1785 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1788 json_object
*json_no
= NULL
;
1789 json_no
= json_object_new_object();
1790 json_object_string_add(json_no
, "warning",
1791 "Malformed address");
1792 vty_out(vty
, "%s\n",
1793 json_object_to_json_string(json_no
));
1794 json_object_free(json_no
);
1796 vty_out(vty
, "Malformed address: %s\n",
1800 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1802 json_object
*json_no
= NULL
;
1803 json_no
= json_object_new_object();
1804 json_object_string_add(
1806 "No such neighbor or address family");
1807 vty_out(vty
, "%s\n",
1808 json_object_to_json_string(json_no
));
1809 json_object_free(json_no
);
1811 vty_out(vty
, "%% No such neighbor or address family\n");
1815 argv_find(argv
, argc
, "all", &rd_all
);
1817 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1820 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1821 &idx_ext_community
);
1822 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1825 json_object
*json_no
= NULL
;
1826 json_no
= json_object_new_object();
1827 json_object_string_add(
1829 "Malformed Route Distinguisher");
1830 vty_out(vty
, "%s\n",
1831 json_object_to_json_string(json_no
));
1832 json_object_free(json_no
);
1835 "%% Malformed Route Distinguisher\n");
1840 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1843 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1844 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1845 "show [ip] bgp l2vpn evpn all overlay [json]",
1851 "Display information about all EVPN NLRIs\n"
1852 "Display BGP Overlay Information for prefixes\n"
1855 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1856 SHOW_DISPLAY_OVERLAY
,
1857 use_json(argc
, argv
));
1860 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1861 show_ip_bgp_evpn_rd_overlay_cmd
,
1862 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1868 "Display information for a route distinguisher\n"
1869 "VPN Route Distinguisher\n"
1870 "All VPN Route Distinguishers\n"
1871 "Display BGP Overlay Information for prefixes\n")
1873 int idx_ext_community
= 0;
1875 struct prefix_rd prd
;
1878 argv_find(argv
, argc
, "all", &rd_all
);
1880 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1881 NULL
, SHOW_DISPLAY_OVERLAY
,
1882 use_json(argc
, argv
));
1884 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1885 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1887 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1890 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1891 SHOW_DISPLAY_OVERLAY
,
1892 use_json(argc
, argv
));
1895 DEFUN(show_bgp_l2vpn_evpn_com
,
1896 show_bgp_l2vpn_evpn_com_cmd
,
1897 "show bgp l2vpn evpn \
1898 <community AA:NN|large-community AA:BB:CC> \
1899 [exact-match] [json]",
1904 "Display routes matching the community\n"
1905 "Community number where AA and NN are (0-65535)\n"
1906 "Display routes matching the large-community\n"
1907 "List of large-community numbers\n"
1908 "Exact match of the communities\n"
1913 const char *clist_number_or_name
;
1914 int show_type
= bgp_show_type_normal
;
1915 struct community
*com
;
1916 struct lcommunity
*lcom
;
1918 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1919 clist_number_or_name
= argv
[++idx
]->arg
;
1920 show_type
= bgp_show_type_lcommunity
;
1922 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1923 show_type
= bgp_show_type_lcommunity_exact
;
1925 lcom
= lcommunity_str2com(clist_number_or_name
);
1927 vty_out(vty
, "%% Large-community malformed\n");
1931 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1932 SHOW_DISPLAY_STANDARD
,
1933 use_json(argc
, argv
));
1935 lcommunity_free(&lcom
);
1936 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1937 clist_number_or_name
= argv
[++idx
]->arg
;
1938 show_type
= bgp_show_type_community
;
1940 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1941 show_type
= bgp_show_type_community_exact
;
1943 com
= community_str2com(clist_number_or_name
);
1946 vty_out(vty
, "%% Community malformed: %s\n",
1947 clist_number_or_name
);
1951 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1952 SHOW_DISPLAY_STANDARD
,
1953 use_json(argc
, argv
));
1954 community_free(&com
);
1960 /* For testing purpose, static route of EVPN RT-5. */
1961 DEFUN(evpnrt5_network
,
1962 evpnrt5_network_cmd
,
1963 "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]",
1964 "Specify a network to announce via BGP\n"
1967 "Specify Route Distinguisher\n"
1968 "VPN Route Distinguisher\n"
1970 "Ethernet Tag Value\n"
1973 "Ethernet Segment Identifier\n"
1974 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1976 "Gateway IP ( A.B.C.D )\n"
1977 "Gateway IPv6 ( X:X::X:X )\n"
1978 "Router Mac Ext Comm\n"
1979 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1980 "Route-map to modify the attributes\n"
1981 "Name of the route map\n")
1983 int idx_ipv4_prefixlen
= 1;
1984 int idx_route_distinguisher
= 3;
1989 int idx_routermac
= 13;
1991 return bgp_static_set_safi(
1992 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1993 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1994 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1995 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1996 argv
[idx_routermac
]->arg
);
1999 /* For testing purpose, static route of EVPN RT-5. */
2000 DEFUN(no_evpnrt5_network
,
2001 no_evpnrt5_network_cmd
,
2002 "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>",
2004 "Specify a network to announce via BGP\n"
2007 "Specify Route Distinguisher\n"
2008 "VPN Route Distinguisher\n"
2010 "Ethernet Tag Value\n"
2013 "Ethernet Segment Identifier\n"
2014 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
2015 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
2017 int idx_ipv4_prefixlen
= 2;
2018 int idx_ext_community
= 4;
2023 return bgp_static_unset_safi(
2024 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
2025 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
2026 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
2027 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
2030 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2032 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2035 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2037 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2041 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2042 * check that this is a change.
2044 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2045 struct ecommunity
*ecomadd
)
2047 /* If the VNI is "live", we need to uninstall routes using the current
2048 * import RT(s) first before we update the import RT, and subsequently
2051 if (is_vni_live(vpn
))
2052 bgp_evpn_uninstall_routes(bgp
, vpn
);
2054 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2055 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2057 /* If the auto route-target is in use we must remove it */
2058 evpn_import_rt_delete_auto(bgp
, vpn
);
2060 /* Add new RT and rebuild the RT to VNI mapping */
2061 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2063 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2064 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2066 /* Install routes that match new import RT */
2067 if (is_vni_live(vpn
))
2068 bgp_evpn_install_routes(bgp
, vpn
);
2072 * Unconfigure Import RT(s) for a VNI (vty handler).
2074 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2075 struct ecommunity
*ecomdel
)
2077 struct listnode
*node
, *nnode
, *node_to_del
;
2078 struct ecommunity
*ecom
;
2080 /* Along the lines of "configure" except we have to reset to the
2083 if (is_vni_live(vpn
))
2084 bgp_evpn_uninstall_routes(bgp
, vpn
);
2086 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2087 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2089 /* Delete all import RTs */
2090 if (ecomdel
== NULL
) {
2091 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2092 ecommunity_free(&ecom
);
2093 list_delete_node(vpn
->import_rtl
, node
);
2097 /* Delete a specific import RT */
2101 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2102 if (ecommunity_match(ecom
, ecomdel
)) {
2103 ecommunity_free(&ecom
);
2110 list_delete_node(vpn
->import_rtl
, node_to_del
);
2113 assert(vpn
->import_rtl
);
2114 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2115 if (list_isempty(vpn
->import_rtl
)) {
2116 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2117 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2119 /* Rebuild the RT to VNI mapping */
2121 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2123 /* Install routes that match new import RT */
2124 if (is_vni_live(vpn
))
2125 bgp_evpn_install_routes(bgp
, vpn
);
2129 * Configure the Export RT for a VNI (vty handler). Caller expected to
2130 * check that this is a change. Note that only a single export RT is
2131 * allowed for a VNI and any change to configuration is implemented as
2132 * a "replace" (similar to other configuration).
2134 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2135 struct ecommunity
*ecomadd
)
2137 /* If the auto route-target is in use we must remove it */
2138 evpn_export_rt_delete_auto(bgp
, vpn
);
2140 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2141 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2143 if (is_vni_live(vpn
))
2144 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2148 * Unconfigure the Export RT for a VNI (vty handler)
2150 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2151 struct ecommunity
*ecomdel
)
2153 struct listnode
*node
, *nnode
, *node_to_del
;
2154 struct ecommunity
*ecom
;
2156 /* Delete all export RTs */
2157 if (ecomdel
== NULL
) {
2158 /* Reset to default and process all routes. */
2159 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2160 ecommunity_free(&ecom
);
2161 list_delete_node(vpn
->export_rtl
, node
);
2165 /* Delete a specific export RT */
2169 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2170 if (ecommunity_match(ecom
, ecomdel
)) {
2171 ecommunity_free(&ecom
);
2178 list_delete_node(vpn
->export_rtl
, node_to_del
);
2181 assert(vpn
->export_rtl
);
2182 if (list_isempty(vpn
->export_rtl
)) {
2183 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2184 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2187 if (is_vni_live(vpn
))
2188 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2192 * Configure RD for VRF
2194 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2196 /* If we have already advertise type-5 routes with a diffrent RD, we
2197 * have to delete and withdraw them firs
2199 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2202 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2203 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2205 /* We have a new RD for VRF.
2206 * Advertise all type-5 routes again with the new RD
2208 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2212 * Unconfigure RD for VRF
2214 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2216 /* If we have already advertise type-5 routes with a diffrent RD, we
2217 * have to delete and withdraw them firs
2219 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2221 /* fall back to default RD */
2222 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2223 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2225 /* We have a new RD for VRF.
2226 * Advertise all type-5 routes again with the new RD
2228 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2232 * Configure RD for a VNI (vty handler)
2234 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2235 struct prefix_rd
*rd
)
2237 /* If the VNI is "live", we need to delete and withdraw this VNI's
2238 * local routes with the prior RD first. Then, after updating RD,
2239 * need to re-advertise.
2241 if (is_vni_live(vpn
))
2242 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2245 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2246 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2248 if (is_vni_live(vpn
))
2249 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2253 * Unconfigure RD for a VNI (vty handler)
2255 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2257 /* If the VNI is "live", we need to delete and withdraw this VNI's
2258 * local routes with the prior RD first. Then, after resetting RD
2259 * to automatic value, need to re-advertise.
2261 if (is_vni_live(vpn
))
2262 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2264 /* reset RD to default */
2265 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2267 if (is_vni_live(vpn
))
2268 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2272 * Create VNI, if not already present (VTY handler). Mark as configured.
2274 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2276 struct bgpevpn
*vpn
;
2277 struct in_addr mcast_grp
= {INADDR_ANY
};
2282 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2284 /* Check if this L2VNI is already configured as L3VNI */
2285 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2288 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2293 /* tenant vrf will be updated when we get local_vni_add from
2296 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2300 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2306 /* Mark as configured. */
2307 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2312 * Delete VNI. If VNI does not exist in the system (i.e., just
2313 * configuration), all that is needed is to free it. Otherwise,
2314 * any parameters configured for the VNI need to be reset (with
2315 * appropriate action) and the VNI marked as unconfigured; the
2316 * VNI will continue to exist, purely as a "learnt" entity.
2318 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2320 assert(bgp
->vnihash
);
2322 if (!is_vni_live(vpn
)) {
2323 bgp_evpn_free(bgp
, vpn
);
2327 /* We need to take the unconfigure action for each parameter of this VNI
2328 * that is configured. Some optimization is possible, but not worth the
2329 * additional code for an operation that should be pretty rare.
2331 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2333 /* First, deal with the export side - RD and export RT changes. */
2334 if (is_rd_configured(vpn
))
2335 evpn_unconfigure_rd(bgp
, vpn
);
2336 if (is_export_rt_configured(vpn
))
2337 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2339 /* Next, deal with the import side. */
2340 if (is_import_rt_configured(vpn
))
2341 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2345 * Display import RT mapping to VRFs (vty handler)
2346 * bgp_evpn: evpn bgp instance
2348 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2356 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2357 (void (*)(struct hash_bucket
*,
2358 void *))show_vrf_import_rt_entry
,
2363 * Display import RT mapping to VNIs (vty handler)
2365 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2374 bgp
->import_rt_hash
,
2375 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2380 * Display EVPN routes for all VNIs - vty handler.
2382 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2383 struct in_addr vtep_ip
, json_object
*json
,
2387 struct vni_walk_ctx wctx
;
2389 num_vnis
= hashcount(bgp
->vnihash
);
2392 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2395 wctx
.vtep_ip
= vtep_ip
;
2397 wctx
.detail
= detail
;
2398 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2399 void *))show_vni_routes_hash
,
2404 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2406 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2407 vni_t vni
, struct in_addr orig_ip
,
2410 struct bgpevpn
*vpn
;
2411 struct prefix_evpn p
;
2412 struct bgp_dest
*dest
;
2413 struct bgp_path_info
*pi
;
2414 uint32_t path_cnt
= 0;
2417 json_object
*json_paths
= NULL
;
2423 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2425 vty_out(vty
, "VNI not found\n");
2429 /* See if route exists. */
2430 build_evpn_type3_prefix(&p
, orig_ip
);
2431 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2432 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2434 vty_out(vty
, "%% Network not in table\n");
2437 bgp_dest_unlock_node(dest
);
2443 json_paths
= json_object_new_array();
2445 /* Prefix and num paths displayed once per prefix. */
2446 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2448 /* Display each path for this prefix. */
2449 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2450 json_object
*json_path
= NULL
;
2453 json_path
= json_object_new_array();
2455 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2456 RPKI_NOT_BEING_USED
, json_path
);
2459 json_object_array_add(json_paths
, json_path
);
2466 json_object_object_add(json
, "paths", json_paths
);
2468 json_object_int_add(json
, "numPaths", path_cnt
);
2470 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2474 bgp_dest_unlock_node(dest
);
2478 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2479 * By definition, only matching type-2 route will be displayed.
2481 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2482 vni_t vni
, struct ethaddr
*mac
,
2483 struct ipaddr
*ip
, json_object
*json
)
2485 struct bgpevpn
*vpn
;
2486 struct prefix_evpn p
;
2487 struct bgp_dest
*dest
;
2488 struct bgp_path_info
*pi
;
2489 uint32_t path_cnt
= 0;
2492 json_object
*json_paths
= NULL
;
2498 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2501 vty_out(vty
, "VNI not found\n");
2505 /* See if route exists. Look for both non-sticky and sticky. */
2506 build_evpn_type2_prefix(&p
, mac
, ip
);
2507 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2508 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2510 vty_out(vty
, "%% Network not in table\n");
2513 bgp_dest_unlock_node(dest
);
2519 json_paths
= json_object_new_array();
2521 /* Prefix and num paths displayed once per prefix. */
2522 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2524 /* Display each path for this prefix. */
2525 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2526 json_object
*json_path
= NULL
;
2529 json_path
= json_object_new_array();
2531 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2532 RPKI_NOT_BEING_USED
, json_path
);
2535 json_object_array_add(json_paths
, json_path
);
2542 json_object_object_add(json
, "paths", json_paths
);
2544 json_object_int_add(json
, "numPaths", path_cnt
);
2546 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2550 bgp_dest_unlock_node(dest
);
2553 /* Disaplay EVPN routes for a ESI - VTY handler */
2554 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2555 esi_t
*esi
, json_object
*json
)
2557 struct bgp_evpn_es
*es
= NULL
;
2560 es
= bgp_evpn_es_find(esi
);
2563 vty_out(vty
, "ESI not found\n");
2567 show_esi_routes(bgp
, es
, vty
, json
);
2571 * Display EVPN routes for a VNI - vty handler.
2572 * If 'type' is non-zero, only routes matching that type are shown.
2573 * If the vtep_ip is non zero, only routes behind that vtep are shown
2575 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2576 int type
, struct in_addr vtep_ip
,
2579 struct bgpevpn
*vpn
;
2582 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2585 vty_out(vty
, "VNI not found\n");
2589 /* Walk this VNI's route table and display appropriate routes. */
2590 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2594 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2595 * IP (vty handler). By definition, only matching type-2 route will be
2598 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2599 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2600 struct ipaddr
*ip
, json_object
*json
)
2602 struct prefix_evpn p
;
2603 struct bgp_dest
*dest
;
2604 struct bgp_path_info
*pi
;
2607 uint32_t path_cnt
= 0;
2608 json_object
*json_paths
= NULL
;
2609 char prefix_str
[BUFSIZ
];
2614 /* See if route exists. Look for both non-sticky and sticky. */
2615 build_evpn_type2_prefix(&p
, mac
, ip
);
2616 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2617 (struct prefix
*)&p
, prd
);
2618 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2620 vty_out(vty
, "%% Network not in table\n");
2623 bgp_dest_unlock_node(dest
);
2628 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2630 /* Prefix and num paths displayed once per prefix. */
2631 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2634 json_paths
= json_object_new_array();
2636 /* Display each path for this prefix. */
2637 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2638 json_object
*json_path
= NULL
;
2641 json_path
= json_object_new_array();
2643 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2644 RPKI_NOT_BEING_USED
, json_path
);
2647 json_object_array_add(json_paths
, json_path
);
2652 if (json
&& path_cnt
) {
2654 json_object_object_add(json
, prefix_str
, json_paths
);
2655 json_object_int_add(json
, "numPaths", path_cnt
);
2657 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2661 bgp_dest_unlock_node(dest
);
2665 * Display BGP EVPN routing table -- for specific RD (vty handler)
2666 * If 'type' is non-zero, only routes matching that type are shown.
2668 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2669 struct prefix_rd
*prd
, int type
,
2672 struct bgp_dest
*rd_dest
;
2673 struct bgp_table
*table
;
2674 struct bgp_dest
*dest
;
2675 struct bgp_path_info
*pi
;
2679 uint32_t prefix_cnt
, path_cnt
;
2680 char rd_str
[RD_ADDRSTRLEN
];
2681 json_object
*json_rd
= NULL
;
2682 int add_rd_to_json
= 0;
2686 prefix_cnt
= path_cnt
= 0;
2688 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2690 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2694 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2695 if (table
== NULL
) {
2696 bgp_dest_unlock_node(rd_dest
);
2701 json_rd
= json_object_new_object();
2702 json_object_string_add(json_rd
, "rd", rd_str
);
2705 bgp_dest_unlock_node(rd_dest
);
2707 /* Display all prefixes with this RD. */
2708 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2709 const struct prefix_evpn
*evp
=
2710 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2711 json_object
*json_prefix
= NULL
;
2712 json_object
*json_paths
= NULL
;
2713 char prefix_str
[BUFSIZ
];
2714 int add_prefix_to_json
= 0;
2716 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2717 sizeof(prefix_str
));
2719 if (type
&& evp
->prefix
.route_type
!= type
)
2723 json_prefix
= json_object_new_object();
2725 pi
= bgp_dest_get_bgp_path_info(dest
);
2727 /* RD header and legend - once overall. */
2728 if (rd_header
&& !json
) {
2730 "EVPN type-1 prefix: [1]:[ESI]:[EthTag]:[IPlen]:[VTEP-IP]\n");
2732 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2734 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2736 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2738 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2742 /* Prefix and num paths displayed once per prefix. */
2743 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2750 json_paths
= json_object_new_array();
2752 /* Display each path for this prefix. */
2753 for (; pi
; pi
= pi
->next
) {
2754 json_object
*json_path
= NULL
;
2757 json_path
= json_object_new_array();
2759 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2760 RPKI_NOT_BEING_USED
, json_path
);
2763 json_object_array_add(json_paths
, json_path
);
2766 add_prefix_to_json
= 1;
2771 if (add_prefix_to_json
) {
2772 json_object_object_add(json_prefix
, "paths",
2774 json_object_object_add(json_rd
, prefix_str
,
2777 json_object_free(json_paths
);
2778 json_object_free(json_prefix
);
2787 json_object_object_add(json
, rd_str
, json_rd
);
2789 json_object_free(json_rd
);
2793 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2794 json_object_int_add(json
, "numPaths", path_cnt
);
2796 if (prefix_cnt
== 0)
2797 vty_out(vty
, "No prefixes exist with this RD%s\n",
2798 type
? " (of requested type)" : "");
2801 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2802 prefix_cnt
, path_cnt
,
2803 type
? " (of requested type)" : "");
2808 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2809 * (vty handler). Only matching type-2 routes will be displayed.
2811 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2812 struct ethaddr
*mac
, struct ipaddr
*ip
,
2815 struct bgp_dest
*rd_dest
;
2816 struct bgp_table
*table
;
2817 struct bgp_dest
*dest
;
2818 struct bgp_path_info
*pi
;
2819 afi_t afi
= AFI_L2VPN
;
2820 safi_t safi
= SAFI_EVPN
;
2821 uint32_t prefix_cnt
, path_cnt
;
2822 prefix_cnt
= path_cnt
= 0;
2824 /* EVPN routing table is a 2-level table with the first level being
2825 * the RD. We need to look in every RD we know about.
2827 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2828 rd_dest
= bgp_route_next(rd_dest
)) {
2829 json_object
*json_paths
= NULL
; /* paths array for prefix */
2830 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2831 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2832 char rd_str
[RD_ADDRSTRLEN
];
2833 char prefix_str
[BUFSIZ
];
2834 int add_rd_to_json
= 0;
2835 struct prefix_evpn ep
;
2836 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2838 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2842 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2845 /* Construct an RT-2 from the user-supplied mac(ip),
2846 * then search the l2vpn evpn table for it.
2848 build_evpn_type2_prefix(&ep
, mac
, ip
);
2849 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2850 (struct prefix
*)&ep
,
2851 (struct prefix_rd
*)rd_destp
);
2856 json_rd
= json_object_new_object();
2858 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2860 prefix2str(p
, prefix_str
, sizeof(prefix_str
));
2862 pi
= bgp_dest_get_bgp_path_info(dest
);
2864 /* RD header - per RD. */
2865 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2866 rd_str
, RD_ADDRSTRLEN
);
2871 json_prefix
= json_object_new_object();
2872 json_paths
= json_object_new_array();
2873 json_object_string_add(json_prefix
, "prefix",
2875 json_object_int_add(json_prefix
, "prefixLen",
2878 /* Prefix and num paths displayed once per prefix. */
2879 route_vty_out_detail_header(
2880 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2881 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2883 /* For EVPN, the prefix is displayed for each path (to
2884 * fit in with code that already exists).
2886 for (; pi
; pi
= pi
->next
) {
2887 json_object
*json_path
= NULL
;
2893 json_path
= json_object_new_array();
2895 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2896 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2900 json_object_array_add(json_paths
, json_path
);
2906 json_object_object_add(json_prefix
, "paths",
2908 json_object_object_add(json_rd
, prefix_str
,
2911 json_object_object_add(json
, rd_str
, json_rd
);
2913 json_object_free(json_rd
);
2918 bgp_dest_unlock_node(dest
);
2922 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2923 json_object_int_add(json
, "numPaths", path_cnt
);
2925 if (prefix_cnt
== 0) {
2926 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2928 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2929 prefix_cnt
, path_cnt
);
2935 * Display BGP EVPN routing table - all routes (vty handler).
2936 * If 'type' is non-zero, only routes matching that type are shown.
2938 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2939 json_object
*json
, int detail
)
2941 struct bgp_dest
*rd_dest
;
2942 struct bgp_table
*table
;
2943 struct bgp_dest
*dest
;
2944 struct bgp_path_info
*pi
;
2945 int header
= detail
? 0 : 1;
2949 uint32_t prefix_cnt
, path_cnt
;
2953 prefix_cnt
= path_cnt
= 0;
2955 /* EVPN routing table is a 2-level table with the first level being
2958 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2959 rd_dest
= bgp_route_next(rd_dest
)) {
2960 char rd_str
[RD_ADDRSTRLEN
];
2961 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2962 int add_rd_to_json
= 0;
2964 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2966 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2970 tbl_ver
= table
->version
;
2971 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2975 json_rd
= json_object_new_object();
2979 /* Display all prefixes for an RD */
2980 for (dest
= bgp_table_top(table
); dest
;
2981 dest
= bgp_route_next(dest
)) {
2982 json_object
*json_prefix
=
2983 NULL
; /* contains prefix under a RD */
2984 json_object
*json_paths
=
2985 NULL
; /* array of paths under a prefix*/
2986 const struct prefix_evpn
*evp
=
2987 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2989 char prefix_str
[BUFSIZ
];
2990 int add_prefix_to_json
= 0;
2991 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2993 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2994 sizeof(prefix_str
));
2996 if (type
&& evp
->prefix
.route_type
!= type
)
2999 pi
= bgp_dest_get_bgp_path_info(dest
);
3001 /* Overall header/legend displayed once. */
3003 bgp_evpn_show_route_header(vty
, bgp
,
3008 "%19s Extended Community\n"
3013 /* RD header - per RD. */
3015 bgp_evpn_show_route_rd_header(
3016 vty
, rd_dest
, json_rd
, rd_str
,
3025 json_prefix
= json_object_new_object();
3026 json_paths
= json_object_new_array();
3027 json_object_string_add(json_prefix
, "prefix",
3029 json_object_int_add(json_prefix
, "prefixLen",
3033 /* Prefix and num paths displayed once per prefix. */
3035 route_vty_out_detail_header(
3037 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
3038 SAFI_EVPN
, json_prefix
);
3040 /* For EVPN, the prefix is displayed for each path (to
3042 * with code that already exists).
3044 for (; pi
; pi
= pi
->next
) {
3045 json_object
*json_path
= NULL
;
3048 add_prefix_to_json
= 1;
3052 json_path
= json_object_new_array();
3055 route_vty_out_detail(
3056 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
3057 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3060 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3064 json_object_array_add(json_paths
,
3069 if (add_prefix_to_json
) {
3070 json_object_object_add(json_prefix
,
3073 json_object_object_add(json_rd
,
3077 json_object_free(json_prefix
);
3078 json_object_free(json_paths
);
3087 json_object_object_add(json
, rd_str
, json_rd
);
3089 json_object_free(json_rd
);
3096 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3097 json_object_int_add(json
, "numPaths", path_cnt
);
3099 if (prefix_cnt
== 0) {
3100 vty_out(vty
, "No EVPN prefixes %sexist\n",
3101 type
? "(of requested type) " : "");
3103 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3104 prefix_cnt
, path_cnt
,
3105 type
? " (of requested type)" : "");
3111 * Display specified VNI (vty handler)
3113 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3117 struct bgpevpn
*vpn
;
3119 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3122 display_vni(vty
, vpn
, json
);
3124 struct bgp
*bgp_temp
;
3125 struct listnode
*node
= NULL
;
3127 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3128 if (bgp_temp
->l3vni
== vni
) {
3130 display_l3vni(vty
, bgp_temp
, json
);
3137 vty_out(vty
, "{}\n");
3139 vty_out(vty
, "VNI not found\n");
3146 * Display a VNI (upon user query).
3148 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3152 struct bgp
*bgp_temp
= NULL
;
3153 struct listnode
*node
;
3157 vty_out(vty
, "Flags: * - Kernel\n");
3158 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3159 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3162 /* print all L2 VNIS */
3165 hash_iterate(bgp
->vnihash
,
3166 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3169 /* print all L3 VNIs */
3170 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3171 show_l3vni_entry(vty
, bgp_temp
, json
);
3175 * evpn - enable advertisement of svi MAC-IP
3177 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3181 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3183 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3186 bgp
->evpn_info
->advertise_svi_macip
= set
;
3187 bgp_zebra_advertise_svi_macip(bgp
,
3188 bgp
->evpn_info
->advertise_svi_macip
, 0);
3190 if (set
&& vpn
->advertise_svi_macip
)
3192 else if (!set
&& !vpn
->advertise_svi_macip
)
3195 vpn
->advertise_svi_macip
= set
;
3196 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3202 * evpn - enable advertisement of default g/w
3204 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3207 if (bgp
->advertise_gw_macip
)
3210 bgp
->advertise_gw_macip
= 1;
3211 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3213 if (vpn
->advertise_gw_macip
)
3216 vpn
->advertise_gw_macip
= 1;
3217 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3224 * evpn - disable advertisement of default g/w
3226 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3227 struct bgpevpn
*vpn
)
3230 if (!bgp
->advertise_gw_macip
)
3233 bgp
->advertise_gw_macip
= 0;
3234 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3236 if (!vpn
->advertise_gw_macip
)
3239 vpn
->advertise_gw_macip
= 0;
3240 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3247 * evpn - enable advertisement of default g/w
3249 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3250 afi_t afi
, bool add
)
3252 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3255 /* bail if we are already advertising default route */
3256 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3260 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3261 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3262 else if (afi
== AFI_IP6
)
3263 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3264 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3266 /* bail out if we havent advertised the default route */
3267 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3270 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3271 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3272 else if (afi
== AFI_IP6
)
3273 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3274 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3277 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3281 * evpn - enable advertisement of default g/w
3283 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3284 struct bgpevpn
*vpn
)
3286 if (vpn
->advertise_subnet
)
3289 vpn
->advertise_subnet
= 1;
3290 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3294 * evpn - disable advertisement of default g/w
3296 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3298 if (!vpn
->advertise_subnet
)
3301 vpn
->advertise_subnet
= 0;
3302 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3306 * EVPN (VNI advertisement) enabled. Register with zebra.
3308 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3310 bgp
->advertise_all_vni
= 1;
3312 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3316 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3317 * cache, EVPN routes (delete and withdraw from peers).
3319 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3321 bgp
->advertise_all_vni
= 0;
3322 bgp_set_evpn(bgp_get_default());
3323 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3324 bgp_evpn_cleanup_on_disable(bgp
);
3327 /* Set resolve overlay index flag */
3328 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3330 if (set
== bgp
->resolve_overlay_index
)
3334 bgp
->resolve_overlay_index
= true;
3335 hash_iterate(bgp
->vnihash
,
3336 (void (*)(struct hash_bucket
*, void *))
3337 bgp_evpn_handle_resolve_overlay_index_set
,
3342 (void (*)(struct hash_bucket
*, void *))
3343 bgp_evpn_handle_resolve_overlay_index_unset
,
3345 bgp
->resolve_overlay_index
= false;
3350 * EVPN - use RFC8365 to auto-derive RT
3352 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3354 bgp
->advertise_autort_rfc8365
= 1;
3355 bgp_evpn_handle_autort_change(bgp
);
3359 * EVPN - don't use RFC8365 to auto-derive RT
3361 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3363 bgp
->advertise_autort_rfc8365
= 0;
3364 bgp_evpn_handle_autort_change(bgp
);
3367 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3369 char buf1
[RD_ADDRSTRLEN
];
3371 struct listnode
*node
, *nnode
;
3372 struct ecommunity
*ecom
;
3374 if (is_vni_configured(vpn
)) {
3375 vty_out(vty
, " vni %d\n", vpn
->vni
);
3376 if (is_rd_configured(vpn
))
3377 vty_out(vty
, " rd %s\n",
3378 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3380 if (is_import_rt_configured(vpn
)) {
3381 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3383 ecom_str
= ecommunity_ecom2str(
3384 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3385 vty_out(vty
, " route-target import %s\n",
3387 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3391 if (is_export_rt_configured(vpn
)) {
3392 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3394 ecom_str
= ecommunity_ecom2str(
3395 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3396 vty_out(vty
, " route-target export %s\n",
3398 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3402 if (vpn
->advertise_gw_macip
)
3403 vty_out(vty
, " advertise-default-gw\n");
3405 if (vpn
->advertise_svi_macip
)
3406 vty_out(vty
, " advertise-svi-ip\n");
3408 if (vpn
->advertise_subnet
)
3409 vty_out(vty
, " advertise-subnet\n");
3411 vty_out(vty
, " exit-vni\n");
3415 #ifndef VTYSH_EXTRACT_PL
3416 #include "bgpd/bgp_evpn_vty_clippy.c"
3419 DEFPY(bgp_evpn_flood_control
,
3420 bgp_evpn_flood_control_cmd
,
3421 "[no$no] flooding <disable$disable|head-end-replication$her>",
3423 "Specify handling for BUM packets\n"
3424 "Do not flood any BUM packets\n"
3425 "Flood BUM packets using head-end replication\n")
3427 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3428 enum vxlan_flood_control flood_ctrl
;
3434 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3436 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3440 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3443 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3444 bgp_evpn_flood_control_change(bgp
);
3449 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3450 bgp_evpn_advertise_default_gw_vni_cmd
,
3451 "advertise-default-gw",
3452 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3454 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3455 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3460 evpn_set_advertise_default_gw(bgp
, vpn
);
3465 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3466 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3467 "no advertise-default-gw",
3469 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3471 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3472 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3477 evpn_unset_advertise_default_gw(bgp
, vpn
);
3483 DEFUN (bgp_evpn_advertise_default_gw
,
3484 bgp_evpn_advertise_default_gw_cmd
,
3485 "advertise-default-gw",
3486 "Advertise All default g/w mac-ip routes in EVPN\n")
3488 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3493 if (!EVPN_ENABLED(bgp
)) {
3495 "This command is only supported under the EVPN VRF\n");
3499 evpn_set_advertise_default_gw(bgp
, NULL
);
3504 DEFUN (no_bgp_evpn_advertise_default_gw
,
3505 no_bgp_evpn_advertise_default_gw_cmd
,
3506 "no advertise-default-gw",
3508 "Withdraw All default g/w mac-ip routes from EVPN\n")
3510 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3515 evpn_unset_advertise_default_gw(bgp
, NULL
);
3520 DEFUN (bgp_evpn_advertise_all_vni
,
3521 bgp_evpn_advertise_all_vni_cmd
,
3522 "advertise-all-vni",
3523 "Advertise All local VNIs\n")
3525 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3526 struct bgp
*bgp_evpn
= NULL
;
3531 bgp_evpn
= bgp_get_evpn();
3532 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3533 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3535 return CMD_WARNING_CONFIG_FAILED
;
3538 evpn_set_advertise_all_vni(bgp
);
3542 DEFUN (no_bgp_evpn_advertise_all_vni
,
3543 no_bgp_evpn_advertise_all_vni_cmd
,
3544 "no advertise-all-vni",
3546 "Advertise All local VNIs\n")
3548 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3552 evpn_unset_advertise_all_vni(bgp
);
3556 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3557 bgp_evpn_advertise_autort_rfc8365_cmd
,
3558 "autort rfc8365-compatible",
3559 "Auto-derivation of RT\n"
3560 "Auto-derivation of RT using RFC8365\n")
3562 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3566 evpn_set_advertise_autort_rfc8365(bgp
);
3570 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3571 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3572 "no autort rfc8365-compatible",
3574 "Auto-derivation of RT\n"
3575 "Auto-derivation of RT using RFC8365\n")
3577 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3581 evpn_unset_advertise_autort_rfc8365(bgp
);
3585 DEFUN (bgp_evpn_default_originate
,
3586 bgp_evpn_default_originate_cmd
,
3587 "default-originate <ipv4 | ipv6>",
3588 "originate a default route\n"
3589 "ipv4 address family\n"
3590 "ipv6 address family\n")
3594 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3598 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3599 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3603 DEFUN (no_bgp_evpn_default_originate
,
3604 no_bgp_evpn_default_originate_cmd
,
3605 "no default-originate <ipv4 | ipv6>",
3607 "withdraw a default route\n"
3608 "ipv4 address family\n"
3609 "ipv6 address family\n")
3613 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3617 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3618 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3622 DEFPY (dup_addr_detection
,
3623 dup_addr_detection_cmd
,
3624 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3625 "Duplicate address detection\n"
3626 "Max allowed moves before address detected as duplicate\n"
3627 "Num of max allowed moves (2-1000) default 5\n"
3628 "Duplicate address detection time\n"
3629 "Time in seconds (2-1800) default 180\n")
3631 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3636 if (!EVPN_ENABLED(bgp_vrf
)) {
3638 "This command is only supported under the EVPN VRF\n");
3642 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3645 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3647 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3649 bgp_zebra_dup_addr_detection(bgp_vrf
);
3654 DEFPY (dup_addr_detection_auto_recovery
,
3655 dup_addr_detection_auto_recovery_cmd
,
3656 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3657 "Duplicate address detection\n"
3658 "Duplicate address detection freeze\n"
3659 "Duplicate address detection permanent freeze\n"
3660 "Duplicate address detection freeze time (30-3600)\n")
3662 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3663 uint32_t freeze_time
= freeze_time_val
;
3668 if (!EVPN_ENABLED(bgp_vrf
)) {
3670 "This command is only supported under the EVPN VRF\n");
3674 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3675 bgp_vrf
->evpn_info
->dad_freeze
= true;
3676 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3678 bgp_zebra_dup_addr_detection(bgp_vrf
);
3683 DEFPY (no_dup_addr_detection
,
3684 no_dup_addr_detection_cmd
,
3685 "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>]",
3687 "Duplicate address detection\n"
3688 "Max allowed moves before address detected as duplicate\n"
3689 "Num of max allowed moves (2-1000) default 5\n"
3690 "Duplicate address detection time\n"
3691 "Time in seconds (2-1800) default 180\n"
3692 "Duplicate address detection freeze\n"
3693 "Duplicate address detection permanent freeze\n"
3694 "Duplicate address detection freeze time (30-3600)\n")
3696 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3697 uint32_t max_moves
= (uint32_t)max_moves_val
;
3698 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3703 if (!EVPN_ENABLED(bgp_vrf
)) {
3705 "This command is only supported under the EVPN VRF\n");
3710 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3712 /* Reset all parameters to default. */
3713 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3714 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3715 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3716 bgp_vrf
->evpn_info
->dad_freeze
= false;
3717 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3720 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3722 "%% Value does not match with config\n");
3725 bgp_vrf
->evpn_info
->dad_max_moves
=
3726 EVPN_DAD_DEFAULT_MAX_MOVES
;
3730 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3732 "%% Value does not match with config\n");
3735 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3739 if (bgp_vrf
->evpn_info
->dad_freeze_time
3742 "%% Value does not match with config\n");
3745 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3746 bgp_vrf
->evpn_info
->dad_freeze
= false;
3749 if (permanent_val
) {
3750 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3752 "%% Value does not match with config\n");
3755 bgp_vrf
->evpn_info
->dad_freeze
= false;
3759 bgp_zebra_dup_addr_detection(bgp_vrf
);
3764 DEFPY(bgp_evpn_advertise_svi_ip
,
3765 bgp_evpn_advertise_svi_ip_cmd
,
3766 "[no$no] advertise-svi-ip",
3768 "Advertise svi mac-ip routes in EVPN\n")
3770 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3776 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3778 if (!EVPN_ENABLED(bgp
)) {
3780 "This command is only supported under EVPN VRF\n");
3783 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3789 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3790 bgp_evpn_advertise_svi_ip_vni_cmd
,
3791 "[no$no] advertise-svi-ip",
3793 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3795 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3796 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3802 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3804 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3809 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3810 bgp_evpn_advertise_vni_subnet_cmd
,
3812 "Advertise the subnet corresponding to VNI\n")
3814 struct bgp
*bgp_vrf
= NULL
;
3815 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3816 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3821 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3825 evpn_set_advertise_subnet(bgp
, vpn
);
3829 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3830 no_bgp_evpn_advertise_vni_subnet_cmd
,
3831 "no advertise-subnet",
3833 "Advertise All local VNIs\n")
3835 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3836 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3841 evpn_unset_advertise_subnet(bgp
, vpn
);
3845 DEFUN (bgp_evpn_advertise_type5
,
3846 bgp_evpn_advertise_type5_cmd
,
3847 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map WORD]",
3848 "Advertise prefix routes\n"
3851 "advertise gateway IP overlay index\n"
3852 "route-map for filtering specific routes\n"
3853 "Name of the route map\n")
3855 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3862 int rmap_changed
= 0;
3863 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3865 bool adv_flag_changed
= false;
3867 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3868 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3869 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3871 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3873 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3875 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3876 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3879 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3883 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3885 "%%only ipv4 or ipv6 address families are supported");
3889 if (safi
!= SAFI_UNICAST
) {
3891 "%%only ipv4 unicast or ipv6 unicast are supported");
3895 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3896 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3897 vty_out(vty
, "%%Unknown overlay-index type specified");
3901 if (afi
== AFI_IP
) {
3902 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3903 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3904 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3905 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3908 * this is the case for first time ever configuration
3909 * adv ipv4 unicast is enabled for the first time.
3910 * So no need to reset any flag
3912 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3914 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3915 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3916 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3918 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3919 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3920 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3922 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3923 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3926 * This is modify case from gateway-ip
3927 * to no overlay index
3929 adv_flag_changed
= true;
3930 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3931 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3932 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3933 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3934 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3936 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3937 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3940 * This is modify case from no overlay index
3943 adv_flag_changed
= true;
3944 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3945 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3946 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3947 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3951 * Command is issued with the same option
3952 * (no overlay index or gateway-ip) which was
3953 * already configured. So nothing to do.
3954 * However, route-map may have been modified.
3955 * check if route-map has been modified.
3956 * If not, return an error
3962 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3963 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3964 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3965 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3968 * this is the case for first time ever configuration
3969 * adv ipv6 unicast is enabled for the first time.
3970 * So no need to reset any flag
3972 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3974 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3975 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3976 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3978 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3979 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3980 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3982 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3983 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3986 * This is modify case from gateway-ip
3987 * to no overlay index
3989 adv_flag_changed
= true;
3990 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3991 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3992 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3993 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3994 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3996 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3997 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
4000 * This is modify case from no overlay index
4003 adv_flag_changed
= true;
4004 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4005 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4006 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4007 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4011 * Command is issued with the same option
4012 * (no overlay index or gateway-ip) which was
4013 * already configured. So nothing to do.
4014 * However, route-map may have been modified.
4015 * check if route-map has been modified.
4016 * If not, return an error
4023 if ((rmap_changed
) || (adv_flag_changed
)) {
4025 /* If either of these are changed, then FRR needs to
4026 * withdraw already advertised type5 routes.
4028 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4030 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4031 XFREE(MTYPE_ROUTE_MAP_NAME
,
4032 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4033 route_map_counter_decrement(
4034 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4035 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4036 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4041 /* set the route-map for advertise command */
4042 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
4043 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
4044 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
4045 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
4046 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
4047 route_map_counter_increment(
4048 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
4051 /* advertise type-5 routes */
4052 if (advertise_type5_routes(bgp_vrf
, afi
))
4053 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
4057 DEFUN (no_bgp_evpn_advertise_type5
,
4058 no_bgp_evpn_advertise_type5_cmd
,
4059 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4061 "Advertise prefix routes\n"
4065 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4071 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4072 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4074 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4076 "%%only ipv4 or ipv6 address families are supported");
4080 if (safi
!= SAFI_UNICAST
) {
4082 "%%only ipv4 unicast or ipv6 unicast are supported");
4086 if (afi
== AFI_IP
) {
4088 /* if we are not advertising ipv4 prefix as type-5
4091 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4092 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4093 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4094 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4095 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4096 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4097 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4098 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4099 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4103 /* if we are not advertising ipv6 prefix as type-5
4106 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4107 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4108 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4109 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4110 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4111 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4112 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4113 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4114 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4118 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4119 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4120 XFREE(MTYPE_ROUTE_MAP_NAME
,
4121 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4122 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4123 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4129 DEFPY (bgp_evpn_use_es_l3nhg
,
4130 bgp_evpn_use_es_l3nhg_cmd
,
4131 "[no$no] use-es-l3nhg",
4133 "use L3 nexthop group for host routes with ES destination\n")
4135 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4139 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4140 bgp_evpn_ead_evi_rx_disable_cmd
,
4141 "[no$no] disable-ead-evi-rx",
4143 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4145 bool ead_evi_rx
= no
? true :false;
4147 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4148 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4149 bgp_evpn_switch_ead_evi_rx();
4154 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4155 bgp_evpn_ead_evi_tx_disable_cmd
,
4156 "[no$no] disable-ead-evi-tx",
4158 "Don't advertise EAD-EVI for local ESs\n")
4160 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4164 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4165 bgp_evpn_enable_resolve_overlay_index_cmd
,
4166 "[no$no] enable-resolve-overlay-index",
4168 "Enable Recursive Resolution of type-5 route overlay index\n")
4170 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4172 if (bgp
!= bgp_get_evpn()) {
4173 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4177 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4181 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4182 bgp_evpn_advertise_pip_ip_mac_cmd
,
4183 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4185 "evpn system primary IP\n"
4188 MAC_STR MAC_STR MAC_STR
)
4190 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4191 struct bgp
*bgp_evpn
= NULL
;
4193 if (EVPN_ENABLED(bgp_vrf
)) {
4195 "This command is supported under L3VNI BGP EVPN VRF\n");
4196 return CMD_WARNING_CONFIG_FAILED
;
4198 bgp_evpn
= bgp_get_evpn();
4201 /* pip is already enabled */
4202 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4205 bgp_vrf
->evpn_info
->advertise_pip
= true;
4206 if (ip
.s_addr
!= INADDR_ANY
) {
4207 /* Already configured with same IP */
4208 if (IPV4_ADDR_SAME(&ip
,
4209 &bgp_vrf
->evpn_info
->pip_ip_static
))
4212 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4213 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4215 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4217 /* default instance router-id assignemt */
4219 bgp_vrf
->evpn_info
->pip_ip
=
4220 bgp_evpn
->router_id
;
4223 if (!is_zero_mac(&mac
->eth_addr
)) {
4224 /* Already configured with same MAC */
4225 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4226 &mac
->eth_addr
, ETH_ALEN
) == 0)
4229 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4230 &mac
->eth_addr
, ETH_ALEN
);
4231 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4232 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4235 /* Copy zebra sys mac */
4236 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4237 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4238 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4243 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4245 /* Disable PIP feature */
4246 bgp_vrf
->evpn_info
->advertise_pip
= false;
4247 /* copy anycast mac */
4248 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4249 &bgp_vrf
->rmac
, ETH_ALEN
);
4251 /* remove MAC-IP option retain PIP knob. */
4252 if ((ip
.s_addr
!= INADDR_ANY
) &&
4253 !IPV4_ADDR_SAME(&ip
,
4254 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4256 "%% BGP EVPN PIP IP does not match\n");
4257 return CMD_WARNING_CONFIG_FAILED
;
4260 if (!is_zero_mac(&mac
->eth_addr
) &&
4261 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4262 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4264 "%% BGP EVPN PIP MAC does not match\n");
4265 return CMD_WARNING_CONFIG_FAILED
;
4267 /* pip_rmac can carry vrr_rmac reset only if it matches
4268 * with static value.
4270 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4271 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4273 /* Copy zebra sys mac */
4275 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4276 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4277 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4280 /* copy anycast mac */
4281 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4282 &bgp_vrf
->rmac
, ETH_ALEN
);
4286 /* reset user configured sys MAC */
4287 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4288 /* reset user configured sys IP */
4289 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4290 /* Assign default PIP IP (bgp instance router-id) */
4292 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4294 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4297 if (is_evpn_enabled()) {
4298 struct listnode
*node
= NULL
;
4299 struct bgpevpn
*vpn
= NULL
;
4302 * At this point if bgp_evpn is NULL and evpn is enabled
4303 * something stupid has gone wrong
4307 update_advertise_vrf_routes(bgp_vrf
);
4309 /* Update (svi) type-2 routes */
4310 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4311 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4313 update_routes_for_vni(bgp_evpn
, vpn
);
4321 * Display VNI information - for all or a specific VNI
4323 DEFUN(show_bgp_l2vpn_evpn_vni
,
4324 show_bgp_l2vpn_evpn_vni_cmd
,
4325 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4334 struct bgp
*bgp_evpn
;
4338 json_object
*json
= NULL
;
4339 uint32_t num_l2vnis
= 0;
4340 uint32_t num_l3vnis
= 0;
4341 uint32_t num_vnis
= 0;
4342 struct listnode
*node
= NULL
;
4343 struct bgp
*bgp_temp
= NULL
;
4345 uj
= use_json(argc
, argv
);
4347 bgp_evpn
= bgp_get_evpn();
4351 if (!argv_find(argv
, argc
, "evpn", &idx
))
4355 json
= json_object_new_object();
4357 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4359 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4361 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4362 if (bgp_temp
->l3vni
)
4365 num_vnis
= num_l2vnis
+ num_l3vnis
;
4367 json_object_string_add(json
, "advertiseGatewayMacip",
4368 bgp_evpn
->advertise_gw_macip
4371 json_object_string_add(json
, "advertiseSviMacIp",
4372 bgp_evpn
->evpn_info
->advertise_svi_macip
4373 ? "Enabled" : "Disabled");
4374 json_object_string_add(json
, "advertiseAllVnis",
4375 is_evpn_enabled() ? "Enabled"
4377 json_object_string_add(
4379 bgp_evpn
->vxlan_flood_ctrl
4380 == VXLAN_FLOOD_HEAD_END_REPL
4381 ? "Head-end replication"
4383 json_object_int_add(json
, "numVnis", num_vnis
);
4384 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4385 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4387 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4388 bgp_evpn
->advertise_gw_macip
? "Enabled"
4390 vty_out(vty
, "Advertise SVI Macip: %s\n",
4391 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4393 vty_out(vty
, "Advertise All VNI flag: %s\n",
4394 is_evpn_enabled() ? "Enabled" : "Disabled");
4395 vty_out(vty
, "BUM flooding: %s\n",
4396 bgp_evpn
->vxlan_flood_ctrl
4397 == VXLAN_FLOOD_HEAD_END_REPL
4398 ? "Head-end replication"
4400 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4401 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4403 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4407 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4410 /* Display specific VNI */
4411 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4412 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4416 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4417 json
, JSON_C_TO_STRING_PRETTY
));
4418 json_object_free(json
);
4424 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4425 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4426 "show bgp l2vpn evpn vni remote-ip-hash",
4434 struct bgp
*bgp_evpn
;
4437 bgp_evpn
= bgp_get_evpn();
4441 if (!argv_find(argv
, argc
, "evpn", &idx
))
4444 hash_iterate(bgp_evpn
->vnihash
,
4445 (void (*)(struct hash_bucket
*,
4446 void *))bgp_evpn_show_remote_ip_hash
,
4452 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4453 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4454 "show bgp l2vpn evpn vni-svi-hash",
4459 "Show vni-svi-hash\n")
4461 struct bgp
*bgp_evpn
;
4464 bgp_evpn
= bgp_get_evpn();
4468 if (!argv_find(argv
, argc
, "evpn", &idx
))
4471 hash_iterate(bgp_evpn
->vni_svi_hash
,
4472 (void (*)(struct hash_bucket
*,
4473 void *))bgp_evpn_show_vni_svi_hash
,
4479 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4480 show_bgp_l2vpn_evpn_es_evi_cmd
,
4481 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4487 "VxLAN Network Identifier\n"
4490 "Detailed information\n")
4493 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4495 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4500 DEFPY(show_bgp_l2vpn_evpn_es
,
4501 show_bgp_l2vpn_evpn_es_cmd
,
4502 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4507 "Ethernet Segment\n"
4509 "Detailed information\n"
4515 if (!str_to_esi(esi_str
, &esi
)) {
4516 vty_out(vty
, "%%Malformed ESI\n");
4519 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4522 bgp_evpn_es_show(vty
, uj
, !!detail
);
4528 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4529 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4530 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4531 "Ethernet Segment\n"
4537 if (!str_to_esi(esi_str
, &esi
)) {
4538 vty_out(vty
, "%%Malformed ESI\n");
4541 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4544 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4550 DEFPY(show_bgp_l2vpn_evpn_nh
,
4551 show_bgp_l2vpn_evpn_nh_cmd
,
4552 "show bgp l2vpn evpn next-hops [json$uj]",
4560 bgp_evpn_nh_show(vty
, uj
);
4566 * Display EVPN neighbor summary.
4568 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4569 "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]",
4572 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4573 "Summary of BGP neighbor status\n"
4574 "Show only sessions in Established state\n"
4575 "Show only sessions not in Established state\n"
4576 "Show only the specified neighbor session\n"
4577 "Neighbor to display information about\n"
4578 "Neighbor to display information about\n"
4579 "Neighbor on BGP configured interface\n"
4580 "Show only the specified remote AS sessions\n"
4582 "Internal (iBGP) AS sessions\n"
4583 "External (eBGP) AS sessions\n"
4584 "Shorten the information on BGP instances\n"
4585 "Increase table width for longer output\n" JSON_STR
)
4590 char *neighbor
= NULL
;
4591 as_t as
= 0; /* 0 means AS filter not set */
4592 int as_type
= AS_UNSPECIFIED
;
4593 uint16_t show_flags
= 0;
4595 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4596 vrf
= argv
[++idx_vrf
]->arg
;
4598 if (argv_find(argv
, argc
, "failed", &idx
))
4599 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4601 if (argv_find(argv
, argc
, "established", &idx
))
4602 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4605 if (argv_find(argv
, argc
, "neighbor", &idx
))
4606 neighbor
= argv
[idx
+ 1]->arg
;
4608 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4609 if (argv
[idx
+ 1]->arg
[0] == 'i')
4610 as_type
= AS_INTERNAL
;
4611 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4612 as_type
= AS_EXTERNAL
;
4614 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4617 if (argv_find(argv
, argc
, "terse", &idx
))
4618 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4620 if (argv_find(argv
, argc
, "wide", &idx
))
4621 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4623 if (use_json(argc
, argv
))
4624 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4626 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4627 as_type
, as
, show_flags
);
4630 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4634 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4635 /* Specific type is requested */
4636 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4637 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4638 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4639 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4640 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4641 *type
= BGP_EVPN_IMET_ROUTE
;
4642 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4643 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4644 *type
= BGP_EVPN_ES_ROUTE
;
4645 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4646 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4647 *type
= BGP_EVPN_AD_ROUTE
;
4648 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4649 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4650 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4659 * Display global EVPN routing table.
4661 DEFUN(show_bgp_l2vpn_evpn_route
,
4662 show_bgp_l2vpn_evpn_route_cmd
,
4663 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4669 "Display Detailed Information\n"
4671 EVPN_TYPE_ALL_LIST_HELP_STR
4678 json_object
*json
= NULL
;
4680 uj
= use_json(argc
, argv
);
4682 bgp
= bgp_get_evpn();
4687 json
= json_object_new_object();
4689 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4692 if (argv_find(argv
, argc
, "detail", &detail
))
4695 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4698 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4699 json
, JSON_C_TO_STRING_PRETTY
));
4700 json_object_free(json
);
4706 * Display global EVPN routing table for specific RD.
4708 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4709 show_bgp_l2vpn_evpn_route_rd_cmd
,
4710 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4716 EVPN_RT_DIST_HELP_STR
4717 EVPN_ASN_IP_HELP_STR
4718 "All VPN Route Distinguishers\n"
4720 EVPN_TYPE_ALL_LIST_HELP_STR
4725 struct prefix_rd prd
;
4728 json_object
*json
= NULL
;
4729 int idx_ext_community
= 0;
4732 bgp
= bgp_get_evpn();
4736 /* check if we need json output */
4737 uj
= use_json(argc
, argv
);
4739 json
= json_object_new_object();
4741 argv_find(argv
, argc
, "all", &rd_all
);
4744 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4745 &idx_ext_community
);
4746 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4748 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4753 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4757 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4759 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4762 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4763 json
, JSON_C_TO_STRING_PRETTY
));
4764 json_object_free(json
);
4771 * Display global EVPN routing table for specific RD and MACIP.
4773 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4774 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4775 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4781 EVPN_RT_DIST_HELP_STR
4782 EVPN_ASN_IP_HELP_STR
4783 "All VPN Route Distinguishers\n"
4785 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4787 "IP address (IPv4 or IPv6)\n"
4792 struct prefix_rd prd
;
4795 int idx_ext_community
= 0;
4799 json_object
*json
= NULL
;
4802 memset(&mac
, 0, sizeof(struct ethaddr
));
4803 memset(&ip
, 0, sizeof(struct ipaddr
));
4805 bgp
= bgp_get_evpn();
4809 /* check if we need json output */
4810 uj
= use_json(argc
, argv
);
4812 json
= json_object_new_object();
4815 argv_find(argv
, argc
, "all", &rd_all
);
4817 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4818 &idx_ext_community
);
4819 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4821 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4827 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4828 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4829 vty_out(vty
, "%% Malformed MAC address\n");
4834 /* get the ip if specified */
4835 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4836 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4837 vty_out(vty
, "%% Malformed IP address\n");
4843 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4845 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4848 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4849 json
, JSON_C_TO_STRING_PRETTY
));
4850 json_object_free(json
);
4856 /* Display per ESI routing table */
4857 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4858 show_bgp_l2vpn_evpn_route_esi_cmd
,
4859 "show bgp l2vpn evpn route esi ESI [json]",
4865 "Ethernet Segment Identifier\n"
4871 struct bgp
*bgp
= NULL
;
4872 json_object
*json
= NULL
;
4874 memset(&esi
, 0, sizeof(esi
));
4875 bgp
= bgp_get_evpn();
4879 uj
= use_json(argc
, argv
);
4881 json
= json_object_new_object();
4883 /* get the ESI - ESI-ID is at argv[6] */
4884 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4885 vty_out(vty
, "%% Malformed ESI\n");
4889 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4892 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4893 json
, JSON_C_TO_STRING_PRETTY
));
4894 json_object_free(json
);
4902 * Display per-VNI EVPN routing table.
4904 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4905 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4911 "VXLAN Network Identifier\n"
4914 EVPN_TYPE_1_HELP_STR
4915 EVPN_TYPE_1_HELP_STR
4916 EVPN_TYPE_2_HELP_STR
4917 EVPN_TYPE_2_HELP_STR
4918 EVPN_TYPE_3_HELP_STR
4919 EVPN_TYPE_3_HELP_STR
4921 "Remote VTEP IP address\n"
4926 struct in_addr vtep_ip
;
4931 json_object
*json
= NULL
;
4933 bgp
= bgp_get_evpn();
4937 /* check if we need json output */
4938 uj
= use_json(argc
, argv
);
4940 json
= json_object_new_object();
4942 if (!argv_find(argv
, argc
, "evpn", &idx
))
4947 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4949 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4952 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4953 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4954 vty_out(vty
, "%% Malformed VTEP IP address\n");
4959 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4962 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4963 json
, JSON_C_TO_STRING_PRETTY
));
4964 json_object_free(json
);
4971 * Display per-VNI EVPN routing table for specific MACIP.
4973 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4974 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4975 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4981 "VXLAN Network Identifier\n"
4984 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4986 "IP address (IPv4 or IPv6)\n"
4995 json_object
*json
= NULL
;
4997 bgp
= bgp_get_evpn();
5001 /* check if we need json output */
5002 uj
= use_json(argc
, argv
);
5004 json
= json_object_new_object();
5006 if (!argv_find(argv
, argc
, "evpn", &idx
))
5010 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5013 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
5014 vty_out(vty
, "%% Malformed MAC address\n");
5019 memset(&ip
, 0, sizeof(ip
));
5020 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
5022 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
5023 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
5024 vty_out(vty
, "%% Malformed IP address\n");
5029 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
5032 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5033 json
, JSON_C_TO_STRING_PRETTY
));
5034 json_object_free(json
);
5041 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
5043 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5044 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
5045 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
5051 "VXLAN Network Identifier\n"
5053 EVPN_TYPE_3_HELP_STR
5054 "Originating Router IP address\n"
5060 struct in_addr orig_ip
;
5063 json_object
*json
= NULL
;
5065 bgp
= bgp_get_evpn();
5069 /* check if we need json output */
5070 uj
= use_json(argc
, argv
);
5072 json
= json_object_new_object();
5074 if (!argv_find(argv
, argc
, "evpn", &idx
))
5078 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5081 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5083 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5087 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5090 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5091 json
, JSON_C_TO_STRING_PRETTY
));
5092 json_object_free(json
);
5099 * Display per-VNI EVPN routing table - for all VNIs.
5101 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5102 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5103 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5109 "VXLAN Network Identifier\n"
5111 "Print Detailed Output\n"
5113 "Remote VTEP IP address\n"
5117 struct in_addr vtep_ip
;
5120 json_object
*json
= NULL
;
5121 /* Detail Adjust. Adjust indexes according to detail option */
5124 bgp
= bgp_get_evpn();
5128 /* check if we need json output */
5129 uj
= use_json(argc
, argv
);
5131 json
= json_object_new_object();
5133 if (!argv_find(argv
, argc
, "evpn", &idx
))
5136 if (argv_find(argv
, argc
, "detail", &da
))
5139 /* vtep-ip position depends on detail option */
5141 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5143 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5144 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5145 vty_out(vty
, "%% Malformed VTEP IP address\n");
5150 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5153 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5154 json
, JSON_C_TO_STRING_PRETTY
));
5155 json_object_free(json
);
5162 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5163 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5164 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5165 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5166 "EVPN route information\n"
5167 "MAC IP routes in the EVI tables linked to the ES\n"
5169 "Detailed information\n" JSON_STR
)
5173 json_object
*json
= NULL
;
5176 if (!str_to_esi(esi_str
, &esi
)) {
5177 vty_out(vty
, "%%Malformed ESI\n");
5186 json
= json_object_new_object();
5187 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5189 vty_out(vty
, "%s\n",
5190 json_object_to_json_string_ext(
5191 json
, JSON_C_TO_STRING_PRETTY
));
5192 json_object_free(json
);
5199 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5200 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5201 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5202 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5203 "EVPN route information\n"
5204 "MAC IP routes in the global table linked to the ES\n"
5206 "Detailed information\n" JSON_STR
)
5210 json_object
*json
= NULL
;
5213 if (!str_to_esi(esi_str
, &esi
)) {
5214 vty_out(vty
, "%%Malformed ESI\n");
5223 json
= json_object_new_object();
5224 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5226 vty_out(vty
, "%s\n",
5227 json_object_to_json_string_ext(
5228 json
, JSON_C_TO_STRING_PRETTY
));
5229 json_object_free(json
);
5236 * Display EVPN import route-target hash table
5238 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5239 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5240 "show bgp l2vpn evpn vrf-import-rt [json]",
5245 "Show vrf import route target\n"
5249 struct bgp
*bgp_evpn
= NULL
;
5250 json_object
*json
= NULL
;
5252 bgp_evpn
= bgp_get_evpn();
5256 uj
= use_json(argc
, argv
);
5258 json
= json_object_new_object();
5260 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5263 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5264 json
, JSON_C_TO_STRING_PRETTY
));
5265 json_object_free(json
);
5272 * Display EVPN import route-target hash table
5274 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5275 show_bgp_l2vpn_evpn_import_rt_cmd
,
5276 "show bgp l2vpn evpn import-rt [json]",
5281 "Show import route target\n"
5286 json_object
*json
= NULL
;
5288 bgp
= bgp_get_evpn();
5292 uj
= use_json(argc
, argv
);
5294 json
= json_object_new_object();
5296 evpn_show_import_rts(vty
, bgp
, json
);
5299 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5300 json
, JSON_C_TO_STRING_PRETTY
));
5301 json_object_free(json
);
5307 DEFPY_HIDDEN(test_es_add
,
5309 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5312 "Ethernet-segment\n"
5313 "Ethernet-Segment Identifier\n"
5321 struct in_addr vtep_ip
;
5324 bgp
= bgp_get_evpn();
5326 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5330 if (!str_to_esi(esi_str
, &esi
)) {
5331 vty_out(vty
, "%%Malformed ESI\n");
5336 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5338 vty_out(vty
, "%%Failed to delete ES\n");
5342 if (state_str
&& !strcmp(state_str
, "up"))
5346 vtep_ip
= bgp
->router_id
;
5348 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5349 EVPN_MH_DF_PREF_MIN
, false);
5351 vty_out(vty
, "%%Failed to add ES\n");
5358 DEFPY_HIDDEN(test_es_vni_add
,
5359 test_es_vni_add_cmd
,
5360 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5363 "Ethernet-segment\n"
5364 "Ethernet-Segment Identifier\n"
5373 bgp
= bgp_get_evpn();
5375 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
5379 if (!str_to_esi(esi_str
, &esi
)) {
5380 vty_out(vty
, "%%Malformed ESI\n");
5385 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5387 vty_out(vty
, "%%Failed to deref ES VNI\n");
5391 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5393 vty_out(vty
, "%%Failed to ref ES VNI\n");
5400 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5401 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5405 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5406 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5407 "Summary of BGP neighbor status\n" JSON_STR
)
5409 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5410 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5411 SHOW_STR BGP_STR EVPN_HELP_STR
5413 "Display Detailed Information\n"
5415 EVPN_TYPE_2_HELP_STR
5416 EVPN_TYPE_2_HELP_STR
5417 EVPN_TYPE_3_HELP_STR
5418 EVPN_TYPE_3_HELP_STR
)
5421 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5422 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5423 SHOW_STR BGP_STR EVPN_HELP_STR
5425 EVPN_RT_DIST_HELP_STR
5426 EVPN_ASN_IP_HELP_STR
5428 EVPN_TYPE_2_HELP_STR
5429 EVPN_TYPE_2_HELP_STR
5430 EVPN_TYPE_3_HELP_STR
5431 EVPN_TYPE_3_HELP_STR
)
5434 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5435 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5436 SHOW_STR BGP_STR EVPN_HELP_STR
5438 EVPN_RT_DIST_HELP_STR
5439 EVPN_ASN_IP_HELP_STR
5441 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5443 "IP address (IPv4 or IPv6)\n")
5446 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5447 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5448 SHOW_STR BGP_STR EVPN_HELP_STR
5450 "VXLAN Network Identifier\n"
5453 EVPN_TYPE_2_HELP_STR
5454 EVPN_TYPE_2_HELP_STR
5455 EVPN_TYPE_3_HELP_STR
5456 EVPN_TYPE_3_HELP_STR
5458 "Remote VTEP IP address\n")
5460 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5461 show_bgp_evpn_route_vni_macip_cmd
,
5462 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5463 SHOW_STR BGP_STR EVPN_HELP_STR
5465 "VXLAN Network Identifier\n"
5468 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5470 "IP address (IPv4 or IPv6)\n")
5472 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5473 show_bgp_evpn_route_vni_multicast_cmd
,
5474 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5475 SHOW_STR BGP_STR EVPN_HELP_STR
5477 "VXLAN Network Identifier\n"
5479 EVPN_TYPE_3_HELP_STR
5480 "Originating Router IP address\n")
5482 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5483 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5484 SHOW_STR BGP_STR EVPN_HELP_STR
5486 "VXLAN Network Identifier\n"
5488 "Print Detailed Output\n"
5490 "Remote VTEP IP address\n")
5492 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5493 "show bgp evpn import-rt",
5494 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5496 DEFUN_NOSH (bgp_evpn_vni
,
5498 "vni " CMD_VNI_RANGE
,
5499 "VXLAN Network Identifier\n"
5503 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5504 struct bgpevpn
*vpn
;
5509 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5511 /* Create VNI, or mark as configured. */
5512 vpn
= evpn_create_update_vni(bgp
, vni
);
5514 vty_out(vty
, "%% Failed to create VNI \n");
5518 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5522 DEFUN (no_bgp_evpn_vni
,
5523 no_bgp_evpn_vni_cmd
,
5524 "no vni " CMD_VNI_RANGE
,
5526 "VXLAN Network Identifier\n"
5530 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5531 struct bgpevpn
*vpn
;
5536 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5538 /* Check if we should disallow. */
5539 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5541 vty_out(vty
, "%% Specified VNI does not exist\n");
5544 if (!is_vni_configured(vpn
)) {
5545 vty_out(vty
, "%% Specified VNI is not configured\n");
5549 evpn_delete_vni(bgp
, vpn
);
5553 DEFUN_NOSH (exit_vni
,
5556 "Exit from VNI mode\n")
5558 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5559 vty
->node
= BGP_EVPN_NODE
;
5563 DEFUN (bgp_evpn_vrf_rd
,
5564 bgp_evpn_vrf_rd_cmd
,
5565 "rd ASN:NN_OR_IP-ADDRESS:NN",
5566 EVPN_RT_DIST_HELP_STR
5567 EVPN_ASN_IP_HELP_STR
)
5570 struct prefix_rd prd
;
5571 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5576 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5578 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5582 /* If same as existing value, there is nothing more to do. */
5583 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5586 /* Configure or update the RD. */
5587 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5591 DEFUN (no_bgp_evpn_vrf_rd
,
5592 no_bgp_evpn_vrf_rd_cmd
,
5593 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5595 EVPN_RT_DIST_HELP_STR
5596 EVPN_ASN_IP_HELP_STR
)
5599 struct prefix_rd prd
;
5600 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5605 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5607 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5611 /* Check if we should disallow. */
5612 if (!is_vrf_rd_configured(bgp_vrf
)) {
5613 vty_out(vty
, "%% RD is not configured for this VRF\n");
5617 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5619 "%% RD specified does not match configuration for this VRF\n");
5623 evpn_unconfigure_vrf_rd(bgp_vrf
);
5627 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5628 no_bgp_evpn_vrf_rd_without_val_cmd
,
5631 EVPN_RT_DIST_HELP_STR
)
5633 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5638 /* Check if we should disallow. */
5639 if (!is_vrf_rd_configured(bgp_vrf
)) {
5640 vty_out(vty
, "%% RD is not configured for this VRF\n");
5644 evpn_unconfigure_vrf_rd(bgp_vrf
);
5648 DEFUN (bgp_evpn_vni_rd
,
5649 bgp_evpn_vni_rd_cmd
,
5650 "rd ASN:NN_OR_IP-ADDRESS:NN",
5651 EVPN_RT_DIST_HELP_STR
5652 EVPN_ASN_IP_HELP_STR
)
5654 struct prefix_rd prd
;
5655 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5656 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5662 if (!EVPN_ENABLED(bgp
)) {
5664 "This command is only supported under EVPN VRF\n");
5668 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5670 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5674 /* If same as existing value, there is nothing more to do. */
5675 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5678 /* Configure or update the RD. */
5679 evpn_configure_rd(bgp
, vpn
, &prd
);
5683 DEFUN (no_bgp_evpn_vni_rd
,
5684 no_bgp_evpn_vni_rd_cmd
,
5685 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5687 EVPN_RT_DIST_HELP_STR
5688 EVPN_ASN_IP_HELP_STR
)
5690 struct prefix_rd prd
;
5691 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5692 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5698 if (!EVPN_ENABLED(bgp
)) {
5700 "This command is only supported under EVPN VRF\n");
5704 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5706 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5710 /* Check if we should disallow. */
5711 if (!is_rd_configured(vpn
)) {
5712 vty_out(vty
, "%% RD is not configured for this VNI\n");
5716 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5718 "%% RD specified does not match configuration for this VNI\n");
5722 evpn_unconfigure_rd(bgp
, vpn
);
5726 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5727 no_bgp_evpn_vni_rd_without_val_cmd
,
5730 EVPN_RT_DIST_HELP_STR
)
5732 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5733 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5738 if (!EVPN_ENABLED(bgp
)) {
5740 "This command is only supported under EVPN VRF\n");
5744 /* Check if we should disallow. */
5745 if (!is_rd_configured(vpn
)) {
5746 vty_out(vty
, "%% RD is not configured for this VNI\n");
5750 evpn_unconfigure_rd(bgp
, vpn
);
5755 * Loop over all extended-communities in the route-target list rtl and
5756 * return 1 if we find ecomtarget
5758 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5759 struct ecommunity
*ecomtarget
)
5761 struct listnode
*node
, *nnode
;
5762 struct ecommunity
*ecom
;
5764 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5765 if (ecommunity_match(ecom
, ecomtarget
))
5772 /* display L3VNI related info for a VRF instance */
5773 DEFUN (show_bgp_vrf_l3vni_info
,
5774 show_bgp_vrf_l3vni_info_cmd
,
5775 "show bgp vrf VRFNAME vni [json]",
5783 char buf
[ETHER_ADDR_STRLEN
];
5784 char buf1
[INET6_ADDRSTRLEN
];
5785 char originator_ip
[BUFSIZ
] = {0};
5787 const char *name
= NULL
;
5788 struct bgp
*bgp
= NULL
;
5789 struct listnode
*node
= NULL
;
5790 struct bgpevpn
*vpn
= NULL
;
5791 struct ecommunity
*ecom
= NULL
;
5792 json_object
*json
= NULL
;
5793 json_object
*json_vnis
= NULL
;
5794 json_object
*json_export_rts
= NULL
;
5795 json_object
*json_import_rts
= NULL
;
5796 bool uj
= use_json(argc
, argv
);
5799 json
= json_object_new_object();
5800 json_vnis
= json_object_new_array();
5801 json_export_rts
= json_object_new_array();
5802 json_import_rts
= json_object_new_array();
5805 name
= argv
[idx_vrf
]->arg
;
5806 bgp
= bgp_lookup_by_name(name
);
5809 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5811 json_object_string_add(json
, "warning",
5812 "BGP instance not found");
5813 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5814 json_object_free(json
);
5820 vty_out(vty
, "BGP VRF: %s\n", name
);
5821 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5822 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5823 vty_out(vty
, " Rmac: %s\n",
5824 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5825 vty_out(vty
, " VNI Filter: %s\n",
5826 CHECK_FLAG(bgp
->vrf_flags
,
5827 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5828 ? "prefix-routes-only"
5830 vty_out(vty
, " L2-VNI List:\n");
5832 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5833 vty_out(vty
, "%u ", vpn
->vni
);
5835 vty_out(vty
, " Export-RTs:\n");
5837 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5838 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5840 vty_out(vty
, " Import-RTs:\n");
5842 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5843 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5845 vty_out(vty
, " RD: %s\n",
5846 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5848 json_object_string_add(json
, "vrf", name
);
5849 json_object_string_add(json
, "local-ip",
5850 inet_ntop(AF_INET
, &bgp
->originator_ip
,
5852 sizeof(originator_ip
)));
5853 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5854 json_object_string_add(
5856 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5857 json_object_string_add(
5859 CHECK_FLAG(bgp
->vrf_flags
,
5860 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5861 ? "prefix-routes-only"
5863 /* list of l2vnis */
5864 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5865 json_object_array_add(json_vnis
,
5866 json_object_new_int(vpn
->vni
));
5867 json_object_object_add(json
, "l2vnis", json_vnis
);
5870 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5871 json_object_array_add(
5873 json_object_new_string(ecommunity_str(ecom
)));
5874 json_object_object_add(json
, "export-rts", json_export_rts
);
5877 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5878 json_object_array_add(
5880 json_object_new_string(ecommunity_str(ecom
)));
5881 json_object_object_add(json
, "import-rts", json_import_rts
);
5882 json_object_string_add(
5884 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5888 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5889 json
, JSON_C_TO_STRING_PRETTY
));
5890 json_object_free(json
);
5895 /* import/export rt for l3vni-vrf */
5896 DEFUN (bgp_evpn_vrf_rt
,
5897 bgp_evpn_vrf_rt_cmd
,
5898 "route-target <both|import|export> RT",
5900 "import and export\n"
5903 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5906 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5907 struct ecommunity
*ecomadd
= NULL
;
5912 if (!strcmp(argv
[1]->arg
, "import"))
5913 rt_type
= RT_TYPE_IMPORT
;
5914 else if (!strcmp(argv
[1]->arg
, "export"))
5915 rt_type
= RT_TYPE_EXPORT
;
5916 else if (!strcmp(argv
[1]->arg
, "both"))
5917 rt_type
= RT_TYPE_BOTH
;
5919 vty_out(vty
, "%% Invalid Route Target type\n");
5923 /* Add/update the import route-target */
5924 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5925 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5926 ECOMMUNITY_ROUTE_TARGET
, 0);
5928 vty_out(vty
, "%% Malformed Route Target list\n");
5931 ecommunity_str(ecomadd
);
5933 /* Do nothing if we already have this import route-target */
5934 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5935 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5938 /* Add/update the export route-target */
5939 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5940 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5941 ECOMMUNITY_ROUTE_TARGET
, 0);
5943 vty_out(vty
, "%% Malformed Route Target list\n");
5946 ecommunity_str(ecomadd
);
5948 /* Do nothing if we already have this export route-target */
5949 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5950 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5956 DEFUN (no_bgp_evpn_vrf_rt
,
5957 no_bgp_evpn_vrf_rt_cmd
,
5958 "no route-target <both|import|export> RT",
5961 "import and export\n"
5964 EVPN_ASN_IP_HELP_STR
)
5966 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5967 int rt_type
, found_ecomdel
;
5968 struct ecommunity
*ecomdel
= NULL
;
5973 if (!strcmp(argv
[2]->arg
, "import"))
5974 rt_type
= RT_TYPE_IMPORT
;
5975 else if (!strcmp(argv
[2]->arg
, "export"))
5976 rt_type
= RT_TYPE_EXPORT
;
5977 else if (!strcmp(argv
[2]->arg
, "both"))
5978 rt_type
= RT_TYPE_BOTH
;
5980 vty_out(vty
, "%% Invalid Route Target type\n");
5984 if (rt_type
== RT_TYPE_IMPORT
) {
5985 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5987 "%% Import RT is not configured for this VRF\n");
5990 } else if (rt_type
== RT_TYPE_EXPORT
) {
5991 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5993 "%% Export RT is not configured for this VRF\n");
5996 } else if (rt_type
== RT_TYPE_BOTH
) {
5997 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5998 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6000 "%% Import/Export RT is not configured for this VRF\n");
6005 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6007 vty_out(vty
, "%% Malformed Route Target list\n");
6010 ecommunity_str(ecomdel
);
6012 if (rt_type
== RT_TYPE_IMPORT
) {
6013 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
6015 ecommunity_free(&ecomdel
);
6017 "%% RT specified does not match configuration for this VRF\n");
6020 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
6021 } else if (rt_type
== RT_TYPE_EXPORT
) {
6022 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6024 ecommunity_free(&ecomdel
);
6026 "%% RT specified does not match configuration for this VRF\n");
6029 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6030 } else if (rt_type
== RT_TYPE_BOTH
) {
6033 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
6035 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
6039 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
6041 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
6045 if (!found_ecomdel
) {
6046 ecommunity_free(&ecomdel
);
6048 "%% RT specified does not match configuration for this VRF\n");
6053 ecommunity_free(&ecomdel
);
6057 DEFUN (bgp_evpn_vni_rt
,
6058 bgp_evpn_vni_rt_cmd
,
6059 "route-target <both|import|export> RT",
6061 "import and export\n"
6064 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6066 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6067 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6069 struct ecommunity
*ecomadd
= NULL
;
6074 if (!EVPN_ENABLED(bgp
)) {
6076 "This command is only supported under EVPN VRF\n");
6080 if (!strcmp(argv
[1]->text
, "import"))
6081 rt_type
= RT_TYPE_IMPORT
;
6082 else if (!strcmp(argv
[1]->text
, "export"))
6083 rt_type
= RT_TYPE_EXPORT
;
6084 else if (!strcmp(argv
[1]->text
, "both"))
6085 rt_type
= RT_TYPE_BOTH
;
6087 vty_out(vty
, "%% Invalid Route Target type\n");
6091 /* Add/update the import route-target */
6092 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6093 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6094 ECOMMUNITY_ROUTE_TARGET
, 0);
6096 vty_out(vty
, "%% Malformed Route Target list\n");
6099 ecommunity_str(ecomadd
);
6101 /* Do nothing if we already have this import route-target */
6102 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6103 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6106 /* Add/update the export route-target */
6107 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6108 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
6109 ECOMMUNITY_ROUTE_TARGET
, 0);
6111 vty_out(vty
, "%% Malformed Route Target list\n");
6114 ecommunity_str(ecomadd
);
6116 /* Do nothing if we already have this export route-target */
6117 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6118 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6124 DEFUN (no_bgp_evpn_vni_rt
,
6125 no_bgp_evpn_vni_rt_cmd
,
6126 "no route-target <both|import|export> RT",
6129 "import and export\n"
6132 EVPN_ASN_IP_HELP_STR
)
6134 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6135 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6136 int rt_type
, found_ecomdel
;
6137 struct ecommunity
*ecomdel
= NULL
;
6142 if (!EVPN_ENABLED(bgp
)) {
6144 "This command is only supported under EVPN VRF\n");
6148 if (!strcmp(argv
[2]->text
, "import"))
6149 rt_type
= RT_TYPE_IMPORT
;
6150 else if (!strcmp(argv
[2]->text
, "export"))
6151 rt_type
= RT_TYPE_EXPORT
;
6152 else if (!strcmp(argv
[2]->text
, "both"))
6153 rt_type
= RT_TYPE_BOTH
;
6155 vty_out(vty
, "%% Invalid Route Target type\n");
6159 /* The user did "no route-target import", check to see if there are any
6160 * import route-targets configured. */
6161 if (rt_type
== RT_TYPE_IMPORT
) {
6162 if (!is_import_rt_configured(vpn
)) {
6164 "%% Import RT is not configured for this VNI\n");
6167 } else if (rt_type
== RT_TYPE_EXPORT
) {
6168 if (!is_export_rt_configured(vpn
)) {
6170 "%% Export RT is not configured for this VNI\n");
6173 } else if (rt_type
== RT_TYPE_BOTH
) {
6174 if (!is_import_rt_configured(vpn
)
6175 && !is_export_rt_configured(vpn
)) {
6177 "%% Import/Export RT is not configured for this VNI\n");
6182 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6184 vty_out(vty
, "%% Malformed Route Target list\n");
6187 ecommunity_str(ecomdel
);
6189 if (rt_type
== RT_TYPE_IMPORT
) {
6190 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6192 "%% RT specified does not match configuration for this VNI\n");
6195 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6196 } else if (rt_type
== RT_TYPE_EXPORT
) {
6197 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6199 "%% RT specified does not match configuration for this VNI\n");
6202 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6203 } else if (rt_type
== RT_TYPE_BOTH
) {
6206 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6207 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6211 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6212 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6216 if (!found_ecomdel
) {
6218 "%% RT specified does not match configuration for this VNI\n");
6226 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6227 no_bgp_evpn_vni_rt_without_val_cmd
,
6228 "no route-target <import|export>",
6234 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6235 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6241 if (!EVPN_ENABLED(bgp
)) {
6243 "This command is only supported under EVPN VRF\n");
6247 if (!strcmp(argv
[2]->text
, "import")) {
6248 rt_type
= RT_TYPE_IMPORT
;
6249 } else if (!strcmp(argv
[2]->text
, "export")) {
6250 rt_type
= RT_TYPE_EXPORT
;
6252 vty_out(vty
, "%% Invalid Route Target type\n");
6256 /* Check if we should disallow. */
6257 if (rt_type
== RT_TYPE_IMPORT
) {
6258 if (!is_import_rt_configured(vpn
)) {
6260 "%% Import RT is not configured for this VNI\n");
6264 if (!is_export_rt_configured(vpn
)) {
6266 "%% Export RT is not configured for this VNI\n");
6271 /* Unconfigure the RT. */
6272 if (rt_type
== RT_TYPE_IMPORT
)
6273 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6275 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6279 static int vni_cmp(const void **a
, const void **b
)
6281 const struct bgpevpn
*first
= *a
;
6282 const struct bgpevpn
*secnd
= *b
;
6284 return secnd
->vni
- first
->vni
;
6288 * Output EVPN configuration information.
6290 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6293 char buf1
[RD_ADDRSTRLEN
];
6294 char buf2
[INET6_ADDRSTRLEN
];
6296 if (bgp
->advertise_all_vni
)
6297 vty_out(vty
, " advertise-all-vni\n");
6300 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6301 struct listnode
*ln
;
6302 struct bgpevpn
*data
;
6304 list_sort(vnilist
, vni_cmp
);
6305 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6306 write_vni_config(vty
, data
);
6308 list_delete(&vnilist
);
6311 if (bgp
->advertise_autort_rfc8365
)
6312 vty_out(vty
, " autort rfc8365-compatible\n");
6314 if (bgp
->advertise_gw_macip
)
6315 vty_out(vty
, " advertise-default-gw\n");
6317 if (bgp
->evpn_info
->advertise_svi_macip
)
6318 vty_out(vty
, " advertise-svi-ip\n");
6320 if (bgp
->resolve_overlay_index
)
6321 vty_out(vty
, " enable-resolve-overlay-index\n");
6323 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6324 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6325 if (bgp_mh_info
->host_routes_use_l3nhg
)
6326 vty_out(vty
, " use-es-l3nhg\n");
6328 vty_out(vty
, " no use-es-l3nhg\n");
6331 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6332 if (bgp_mh_info
->ead_evi_rx
)
6333 vty_out(vty
, " no disable-ead-evi-rx\n");
6335 vty_out(vty
, " disable-ead-evi-rx\n");
6338 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6339 if (bgp_mh_info
->ead_evi_tx
)
6340 vty_out(vty
, " no disable-ead-evi-tx\n");
6342 vty_out(vty
, " disable-ead-evi-tx\n");
6345 if (!bgp
->evpn_info
->dup_addr_detect
)
6346 vty_out(vty
, " no dup-addr-detection\n");
6348 if (bgp
->evpn_info
->dad_max_moves
!=
6349 EVPN_DAD_DEFAULT_MAX_MOVES
||
6350 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6351 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6352 bgp
->evpn_info
->dad_max_moves
,
6353 bgp
->evpn_info
->dad_time
);
6355 if (bgp
->evpn_info
->dad_freeze
) {
6356 if (bgp
->evpn_info
->dad_freeze_time
)
6358 " dup-addr-detection freeze %u\n",
6359 bgp
->evpn_info
->dad_freeze_time
);
6362 " dup-addr-detection freeze permanent\n");
6365 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6366 vty_out(vty
, " flooding disable\n");
6368 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6369 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6370 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6371 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6372 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6375 " advertise ipv4 unicast\n");
6376 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6377 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6378 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6380 " advertise ipv4 unicast gateway-ip route-map %s\n",
6381 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6383 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6386 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6387 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6388 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6390 " advertise ipv6 unicast route-map %s\n",
6391 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6394 " advertise ipv6 unicast\n");
6395 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6396 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6397 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6399 " advertise ipv6 unicast gateway-ip route-map %s\n",
6400 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6402 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6405 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6406 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6407 vty_out(vty
, " default-originate ipv4\n");
6409 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6410 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6411 vty_out(vty
, " default-originate ipv6\n");
6413 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6414 if (!bgp
->evpn_info
->advertise_pip
)
6415 vty_out(vty
, " no advertise-pip\n");
6416 if (bgp
->evpn_info
->advertise_pip
) {
6417 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6419 vty_out(vty
, " advertise-pip ip %s",
6421 &bgp
->evpn_info
->pip_ip_static
,
6422 buf2
, INET_ADDRSTRLEN
));
6424 bgp
->evpn_info
->pip_rmac_static
))) {
6425 char buf
[ETHER_ADDR_STRLEN
];
6427 vty_out(vty
, " mac %s",
6437 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6438 vty_out(vty
, " rd %s\n",
6439 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6441 /* import route-target */
6442 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6444 struct listnode
*node
, *nnode
;
6445 struct ecommunity
*ecom
;
6447 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6449 ecom_str
= ecommunity_ecom2str(
6450 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6451 vty_out(vty
, " route-target import %s\n", ecom_str
);
6452 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6456 /* export route-target */
6457 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6459 struct listnode
*node
, *nnode
;
6460 struct ecommunity
*ecom
;
6462 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6464 ecom_str
= ecommunity_ecom2str(
6465 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6466 vty_out(vty
, " route-target export %s\n", ecom_str
);
6467 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6472 void bgp_ethernetvpn_init(void)
6474 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6475 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6476 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6477 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6478 install_element(VIEW_NODE
,
6479 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6480 install_element(VIEW_NODE
,
6481 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6484 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6487 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6488 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6489 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6490 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6491 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6492 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6493 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6494 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6495 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6496 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6497 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6498 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6499 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6500 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6501 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6502 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6503 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6504 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6505 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6506 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6507 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6508 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6509 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6510 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6511 install_element(BGP_EVPN_NODE
,
6512 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6515 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6516 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6518 /* "show bgp l2vpn evpn" commands. */
6519 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6520 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6521 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6522 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6523 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6524 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6525 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6526 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6527 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6528 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6529 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6530 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6531 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6532 install_element(VIEW_NODE
,
6533 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6534 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6535 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6536 install_element(VIEW_NODE
,
6537 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6538 install_element(VIEW_NODE
,
6539 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6540 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6541 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6543 /* "show bgp evpn" commands. */
6544 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6545 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6546 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6547 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6548 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6549 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6550 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6551 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6552 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6553 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6554 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6555 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6557 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6558 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6559 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6560 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6561 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6562 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6563 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6564 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6565 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6566 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6567 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6568 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6569 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6570 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6571 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6572 install_element(BGP_EVPN_VNI_NODE
,
6573 &bgp_evpn_advertise_default_gw_vni_cmd
);
6574 install_element(BGP_EVPN_VNI_NODE
,
6575 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6576 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6577 install_element(BGP_EVPN_VNI_NODE
,
6578 &no_bgp_evpn_advertise_vni_subnet_cmd
);