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
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
49 * Context for VNI hash walk - used by callbacks.
54 struct in_addr vtep_ip
;
59 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
63 uint8_t type
, sub_type
;
64 struct ecommunity_as eas
;
65 struct ecommunity_ip eip
;
66 struct listnode
*node
, *nnode
;
67 struct bgp
*tmp_bgp_vrf
= NULL
;
68 json_object
*json_rt
= NULL
;
69 json_object
*json_vrfs
= NULL
;
70 char rt_buf
[RT_ADDRSTRLEN
];
73 json_rt
= json_object_new_object();
74 json_vrfs
= json_object_new_array();
77 pnt
= (uint8_t *)&irt
->rt
.val
;
80 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
83 memset(&eas
, 0, sizeof(eas
));
85 case ECOMMUNITY_ENCODE_AS
:
86 eas
.as
= (*pnt
++ << 8);
88 ptr_get_be32(pnt
, &eas
.val
);
90 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
93 json_object_string_add(json_rt
, "rt", rt_buf
);
95 vty_out(vty
, "Route-target: %s", rt_buf
);
99 case ECOMMUNITY_ENCODE_IP
:
100 memcpy(&eip
.ip
, pnt
, 4);
102 eip
.val
= (*pnt
++ << 8);
105 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
109 json_object_string_add(json_rt
, "rt", rt_buf
);
111 vty_out(vty
, "Route-target: %s", rt_buf
);
115 case ECOMMUNITY_ENCODE_AS4
:
116 pnt
= ptr_get_be32(pnt
, &eas
.val
);
117 eas
.val
= (*pnt
++ << 8);
120 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
123 json_object_string_add(json_rt
, "rt", rt_buf
);
125 vty_out(vty
, "Route-target: %s", rt_buf
);
135 "\nList of VRFs importing routes with this route-target:\n");
138 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
140 json_object_array_add(
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
145 vty_out(vty
, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
150 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
151 json_object_object_add(json
, rt_buf
, json_rt
);
155 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 uint8_t type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (uint8_t *)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
219 json_object_string_add(json_rt
, "rt", rt_buf
);
221 vty_out(vty
, "Route-target: %s", rt_buf
);
225 case ECOMMUNITY_ENCODE_AS4
:
226 pnt
= ptr_get_be32(pnt
, &eas
.val
);
227 eas
.val
= (*pnt
++ << 8);
230 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
233 json_object_string_add(json_rt
, "rt", rt_buf
);
235 vty_out(vty
, "Route-target: %s", rt_buf
);
245 "\nList of VNIs importing routes with this route-target:\n");
248 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
250 json_object_array_add(
251 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
253 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
257 json_object_object_add(json_rt
, "vnis", json_vnis
);
258 json_object_object_add(json
, rt_buf
, json_rt
);
262 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
264 json_object
*json
= NULL
;
265 struct vty
*vty
= NULL
;
266 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
271 display_import_rt(vty
, irt
, json
);
276 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
277 struct bgp_node
*rd_rn
,
279 char *rd_str
, int len
)
286 pnt
= rd_rn
->p
.u
.val
;
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
292 vty_out(vty
, "Route Distinguisher: ");
296 decode_rd_as(pnt
+ 2, &rd_as
);
297 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
299 json_object_string_add(json
, "rd", rd_str
);
301 vty_out(vty
, "%s\n", rd_str
);
305 decode_rd_as4(pnt
+ 2, &rd_as
);
306 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
308 json_object_string_add(json
, "rd", rd_str
);
310 vty_out(vty
, "%s\n", rd_str
);
314 decode_rd_ip(pnt
+ 2, &rd_ip
);
315 snprintf(rd_str
, len
, "%s:%d", inet_ntoa(rd_ip
.ip
),
318 json_object_string_add(json
, "rd", rd_str
);
320 vty_out(vty
, "%s\n", rd_str
);
325 snprintf(rd_str
, len
, "Unknown");
326 json_object_string_add(json
, "rd", rd_str
);
328 snprintf(rd_str
, len
, "Unknown RD type");
329 vty_out(vty
, "%s\n", rd_str
);
335 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
336 uint64_t tbl_ver
, json_object
*json
)
339 " Network Next Hop Metric LocPrf Weight Path\n";
344 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
345 tbl_ver
, inet_ntoa(bgp
->router_id
));
347 "Status codes: s suppressed, d damped, h history, "
348 "* valid, > best, i - internal\n");
349 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
351 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
352 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
353 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
354 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
355 vty_out(vty
, "%s", ri_header
);
358 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
361 char buf1
[INET6_ADDRSTRLEN
];
363 struct listnode
*node
, *nnode
;
364 struct ecommunity
*ecom
;
365 json_object
*json_import_rtl
= NULL
;
366 json_object
*json_export_rtl
= NULL
;
367 char buf2
[ETHER_ADDR_STRLEN
];
369 json_import_rtl
= json_export_rtl
= 0;
372 json_import_rtl
= json_object_new_array();
373 json_export_rtl
= json_object_new_array();
374 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
375 json_object_string_add(json
, "type", "L3");
376 json_object_string_add(json
, "kernelFlag", "Yes");
377 json_object_string_add(
379 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
380 json_object_string_add(json
, "originatorIp",
381 inet_ntoa(bgp_vrf
->originator_ip
));
382 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
383 json_object_string_add(json
, "advertiseSviMacip", "n/a");
384 json_object_to_json_string_ext(json
,
385 JSON_C_TO_STRING_NOSLASHESCAPE
);
386 json_object_string_add(json
, "advertisePip",
387 bgp_vrf
->evpn_info
->advertise_pip
?
388 "Enabled" : "Disabled");
389 json_object_string_add(json
, "sysIP",
391 &bgp_vrf
->evpn_info
->pip_ip
,
392 buf1
, INET_ADDRSTRLEN
));
393 json_object_string_add(json
, "sysMac",
394 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
395 buf2
, sizeof(buf2
)));
396 json_object_string_add(json
, "rmac",
397 prefix_mac2str(&bgp_vrf
->rmac
,
398 buf2
, sizeof(buf2
)));
400 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
401 vty_out(vty
, " (known to the kernel)");
404 vty_out(vty
, " Type: %s\n", "L3");
405 vty_out(vty
, " Tenant VRF: %s\n",
406 vrf_id_to_name(bgp_vrf
->vrf_id
));
407 vty_out(vty
, " RD: %s\n",
408 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
409 vty_out(vty
, " Originator IP: %s\n",
410 inet_ntoa(bgp_vrf
->originator_ip
));
411 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
412 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
413 vty_out(vty
, " Advertise-pip: %s\n",
414 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
415 vty_out(vty
, " System-IP: %s\n",
416 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
417 buf1
, INET_ADDRSTRLEN
));
418 vty_out(vty
, " System-MAC: %s\n",
419 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
420 buf2
, sizeof(buf2
)));
421 vty_out(vty
, " Router-MAC: %s\n",
422 prefix_mac2str(&bgp_vrf
->rmac
,
423 buf2
, sizeof(buf2
)));
427 vty_out(vty
, " Import Route Target:\n");
429 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
430 ecom_str
= ecommunity_ecom2str(ecom
,
431 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
434 json_object_array_add(json_import_rtl
,
435 json_object_new_string(ecom_str
));
437 vty_out(vty
, " %s\n", ecom_str
);
439 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
443 json_object_object_add(json
, "importRts", json_import_rtl
);
445 vty_out(vty
, " Export Route Target:\n");
447 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
448 ecom_str
= ecommunity_ecom2str(ecom
,
449 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
452 json_object_array_add(json_export_rtl
,
453 json_object_new_string(ecom_str
));
455 vty_out(vty
, " %s\n", ecom_str
);
457 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
461 json_object_object_add(json
, "exportRts", json_export_rtl
);
464 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
466 struct in_addr
*vtep
;
467 char buf
[ESI_STR_LEN
];
468 char buf1
[RD_ADDRSTRLEN
];
469 char buf2
[INET6_ADDRSTRLEN
];
470 struct listnode
*node
= NULL
;
471 json_object
*json_vteps
= NULL
;
474 json_vteps
= json_object_new_array();
475 json_object_string_add(json
, "esi",
476 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
477 json_object_string_add(json
, "rd",
478 prefix_rd2str(&es
->prd
, buf1
,
480 json_object_string_add(
481 json
, "originatorIp",
482 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
484 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
485 json_object_array_add(
486 json_vteps
, json_object_new_string(
489 json_object_object_add(json
, "vteps", json_vteps
);
491 vty_out(vty
, "ESI: %s\n",
492 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
493 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
495 vty_out(vty
, " Originator-IP: %s\n",
496 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
498 vty_out(vty
, " VTEP List:\n");
499 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
500 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
505 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
507 char buf1
[RD_ADDRSTRLEN
];
509 struct listnode
*node
, *nnode
;
510 struct ecommunity
*ecom
;
511 json_object
*json_import_rtl
= NULL
;
512 json_object
*json_export_rtl
= NULL
;
513 struct bgp
*bgp_evpn
;
515 bgp_evpn
= bgp_get_evpn();
518 json_import_rtl
= json_object_new_array();
519 json_export_rtl
= json_object_new_array();
520 json_object_int_add(json
, "vni", vpn
->vni
);
521 json_object_string_add(json
, "type", "L2");
522 json_object_string_add(json
, "kernelFlag",
523 is_vni_live(vpn
) ? "Yes" : "No");
524 json_object_string_add(
526 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
527 json_object_string_add(json
, "originatorIp",
528 inet_ntoa(vpn
->originator_ip
));
529 json_object_string_add(json
, "mcastGroup",
530 inet_ntoa(vpn
->mcast_grp
));
531 /* per vni knob is enabled -- Enabled
532 * Global knob is enabled -- Active
533 * default -- Disabled
535 if (!vpn
->advertise_gw_macip
&&
536 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
537 json_object_string_add(json
, "advertiseGatewayMacip",
539 else if (vpn
->advertise_gw_macip
)
540 json_object_string_add(json
, "advertiseGatewayMacip",
543 json_object_string_add(json
, "advertiseGatewayMacip",
545 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
546 bgp_evpn
->evpn_info
->advertise_svi_macip
)
547 json_object_string_add(json
, "advertiseSviMacip",
549 else if (vpn
->advertise_svi_macip
)
550 json_object_string_add(json
, "advertiseSviMacip",
553 json_object_string_add(json
, "advertiseSviMacip",
556 vty_out(vty
, "VNI: %d", vpn
->vni
);
557 if (is_vni_live(vpn
))
558 vty_out(vty
, " (known to the kernel)");
561 vty_out(vty
, " Type: %s\n", "L2");
562 vty_out(vty
, " Tenant-Vrf: %s\n",
563 vrf_id_to_name(vpn
->tenant_vrf_id
));
564 vty_out(vty
, " RD: %s\n",
565 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
566 vty_out(vty
, " Originator IP: %s\n",
567 inet_ntoa(vpn
->originator_ip
));
568 vty_out(vty
, " Mcast group: %s\n",
569 inet_ntoa(vpn
->mcast_grp
));
570 if (!vpn
->advertise_gw_macip
&&
571 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
572 vty_out(vty
, " Advertise-gw-macip : %s\n",
574 else if (vpn
->advertise_gw_macip
)
575 vty_out(vty
, " Advertise-gw-macip : %s\n",
578 vty_out(vty
, " Advertise-gw-macip : %s\n",
580 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
581 bgp_evpn
->evpn_info
->advertise_svi_macip
)
582 vty_out(vty
, " Advertise-svi-macip : %s\n",
584 else if (vpn
->advertise_svi_macip
)
585 vty_out(vty
, " Advertise-svi-macip : %s\n",
588 vty_out(vty
, " Advertise-svi-macip : %s\n",
593 vty_out(vty
, " Import Route Target:\n");
595 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
596 ecom_str
= ecommunity_ecom2str(ecom
,
597 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
600 json_object_array_add(json_import_rtl
,
601 json_object_new_string(ecom_str
));
603 vty_out(vty
, " %s\n", ecom_str
);
605 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
609 json_object_object_add(json
, "importRts", json_import_rtl
);
611 vty_out(vty
, " Export Route Target:\n");
613 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
614 ecom_str
= ecommunity_ecom2str(ecom
,
615 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
618 json_object_array_add(json_export_rtl
,
619 json_object_new_string(ecom_str
));
621 vty_out(vty
, " %s\n", ecom_str
);
623 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
627 json_object_object_add(json
, "exportRts", json_export_rtl
);
630 static void show_esi_routes(struct bgp
*bgp
,
637 struct bgp_path_info
*pi
;
638 uint32_t prefix_cnt
, path_cnt
;
641 prefix_cnt
= path_cnt
= 0;
643 tbl_ver
= es
->route_table
->version
;
644 for (rn
= bgp_table_top(es
->route_table
); rn
;
645 rn
= bgp_route_next(rn
)) {
646 int add_prefix_to_json
= 0;
647 char prefix_str
[BUFSIZ
];
648 json_object
*json_paths
= NULL
;
649 json_object
*json_prefix
= NULL
;
651 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
655 json_prefix
= json_object_new_object();
657 pi
= bgp_node_get_bgp_path_info(rn
);
659 /* Overall header/legend displayed once. */
661 bgp_evpn_show_route_header(vty
, bgp
,
670 json_paths
= json_object_new_array();
672 /* For EVPN, the prefix is displayed for each path (to fit in
673 * with code that already exists).
675 for (; pi
; pi
= pi
->next
) {
676 json_object
*json_path
= NULL
;
679 json_path
= json_object_new_array();
681 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
684 json_object_array_add(json_paths
, json_path
);
687 add_prefix_to_json
= 1;
690 if (json
&& add_prefix_to_json
) {
691 json_object_string_add(json_prefix
, "prefix",
693 json_object_int_add(json_prefix
, "prefixLen",
695 json_object_object_add(json_prefix
, "paths",
697 json_object_object_add(json
, prefix_str
, json_prefix
);
702 json_object_int_add(json
, "numPrefix", prefix_cnt
);
703 json_object_int_add(json
, "numPaths", path_cnt
);
706 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
708 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
709 prefix_cnt
, path_cnt
);
713 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
714 struct vty
*vty
, struct in_addr vtep_ip
,
715 json_object
*json
, int detail
)
718 struct bgp_path_info
*pi
;
719 struct bgp_table
*table
;
720 int header
= detail
? 0 : 1;
722 uint32_t prefix_cnt
, path_cnt
;
724 prefix_cnt
= path_cnt
= 0;
726 table
= vpn
->route_table
;
727 tbl_ver
= table
->version
;
728 for (rn
= bgp_table_top(table
); rn
;
729 rn
= bgp_route_next(rn
)) {
730 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
731 int add_prefix_to_json
= 0;
732 char prefix_str
[BUFSIZ
];
733 json_object
*json_paths
= NULL
;
734 json_object
*json_prefix
= NULL
;
736 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
739 if (type
&& evp
->prefix
.route_type
!= type
)
743 json_prefix
= json_object_new_object();
745 pi
= bgp_node_get_bgp_path_info(rn
);
747 /* Overall header/legend displayed once. */
749 bgp_evpn_show_route_header(vty
, bgp
,
758 json_paths
= json_object_new_array();
760 /* For EVPN, the prefix is displayed for each path (to fit in
761 * with code that already exists).
763 for (; pi
; pi
= pi
->next
) {
764 json_object
*json_path
= NULL
;
767 && !IPV4_ADDR_SAME(&(vtep_ip
),
768 &(pi
->attr
->nexthop
)))
772 json_path
= json_object_new_array();
775 route_vty_out_detail(vty
, bgp
, rn
, pi
,
776 AFI_L2VPN
, SAFI_EVPN
,
779 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
783 json_object_array_add(json_paths
, json_path
);
786 add_prefix_to_json
= 1;
789 if (json
&& add_prefix_to_json
) {
790 json_object_string_add(json_prefix
, "prefix",
792 json_object_int_add(json_prefix
, "prefixLen",
794 json_object_object_add(json_prefix
, "paths",
796 json_object_object_add(json
, prefix_str
, json_prefix
);
801 json_object_int_add(json
, "numPrefix", prefix_cnt
);
802 json_object_int_add(json
, "numPaths", path_cnt
);
805 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
806 type
? "(of requested type) " : "");
808 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
809 prefix_cnt
, path_cnt
,
810 type
? " (of requested type)" : "");
815 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
817 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
818 struct vni_walk_ctx
*wctx
= arg
;
819 struct vty
*vty
= wctx
->vty
;
820 json_object
*json
= wctx
->json
;
821 json_object
*json_vni
= NULL
;
822 char vni_str
[VNI_STR_LEN
];
824 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
826 json_vni
= json_object_new_object();
827 json_object_int_add(json_vni
, "vni", vpn
->vni
);
829 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
832 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
836 json_object_object_add(json
, vni_str
, json_vni
);
839 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
842 json_object
*json_vni
= NULL
;
843 json_object
*json_import_rtl
= NULL
;
844 json_object
*json_export_rtl
= NULL
;
846 char buf2
[INET6_ADDRSTRLEN
];
849 struct listnode
*node
, *nnode
;
850 struct ecommunity
*ecom
;
856 json_vni
= json_object_new_object();
857 json_import_rtl
= json_object_new_array();
858 json_export_rtl
= json_object_new_array();
861 /* if an l3vni is present in bgp it is live */
866 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
867 json_object_string_add(json_vni
, "type", "L3");
868 json_object_string_add(json_vni
, "inKernel", "True");
869 json_object_string_add(json_vni
, "originatorIp",
870 inet_ntoa(bgp
->originator_ip
));
871 json_object_string_add(
873 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
875 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
876 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
879 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
880 ecom_str
= ecommunity_ecom2str(ecom
,
881 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
884 json_object_array_add(json_import_rtl
,
885 json_object_new_string(ecom_str
));
887 if (listcount(bgp
->vrf_import_rtl
) > 1)
888 sprintf(rt_buf
, "%s, ...", ecom_str
);
890 sprintf(rt_buf
, "%s", ecom_str
);
891 vty_out(vty
, " %-25s", rt_buf
);
894 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
896 /* If there are multiple import RTs we break here and show only
903 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
905 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
906 ecom_str
= ecommunity_ecom2str(ecom
,
907 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
910 json_object_array_add(json_export_rtl
,
911 json_object_new_string(ecom_str
));
913 if (listcount(bgp
->vrf_export_rtl
) > 1)
914 sprintf(rt_buf
, "%s, ...", ecom_str
);
916 sprintf(rt_buf
, "%s", ecom_str
);
917 vty_out(vty
, " %-25s", rt_buf
);
920 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
922 /* If there are multiple export RTs we break here and show only
929 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
932 char vni_str
[VNI_STR_LEN
];
934 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
935 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
936 json_object_object_add(json
, vni_str
, json_vni
);
942 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
944 char buf
[ESI_STR_LEN
];
945 char buf1
[RD_ADDRSTRLEN
];
946 char buf2
[INET6_ADDRSTRLEN
];
947 struct in_addr
*vtep
= NULL
;
948 struct vty
*vty
= args
[0];
949 json_object
*json
= args
[1];
950 json_object
*json_vteps
= NULL
;
951 struct listnode
*node
= NULL
;
952 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
955 json_vteps
= json_object_new_array();
956 json_object_string_add(json
, "esi",
957 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
958 json_object_string_add(json
, "type",
959 is_es_local(es
) ? "Local" : "Remote");
960 json_object_string_add(json
, "rd",
961 prefix_rd2str(&es
->prd
, buf1
,
963 json_object_string_add(
964 json
, "originatorIp",
965 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
967 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
968 json_object_array_add(json_vteps
,
969 json_object_new_string(
972 json_object_object_add(json
, "vteps", json_vteps
);
974 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
975 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
976 is_es_local(es
) ? "Local" : "Remote",
977 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
978 ipaddr2str(&es
->originator_ip
, buf2
,
980 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
984 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
988 json_object
*json_vni
= NULL
;
989 json_object
*json_import_rtl
= NULL
;
990 json_object
*json_export_rtl
= NULL
;
991 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
993 char buf2
[RD_ADDRSTRLEN
];
996 struct listnode
*node
, *nnode
;
997 struct ecommunity
*ecom
;
1003 json_vni
= json_object_new_object();
1004 json_import_rtl
= json_object_new_array();
1005 json_export_rtl
= json_object_new_array();
1009 if (is_vni_live(vpn
))
1013 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1014 json_object_string_add(json_vni
, "type", "L2");
1015 json_object_string_add(json_vni
, "inKernel",
1016 is_vni_live(vpn
) ? "True" : "False");
1017 json_object_string_add(json_vni
, "originatorIp",
1018 inet_ntoa(vpn
->originator_ip
));
1019 json_object_string_add(json_vni
, "originatorIp",
1020 inet_ntoa(vpn
->originator_ip
));
1021 json_object_string_add(
1023 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1025 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1026 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1029 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1030 ecom_str
= ecommunity_ecom2str(ecom
,
1031 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1034 json_object_array_add(json_import_rtl
,
1035 json_object_new_string(ecom_str
));
1037 if (listcount(vpn
->import_rtl
) > 1)
1038 sprintf(rt_buf
, "%s, ...", ecom_str
);
1040 sprintf(rt_buf
, "%s", ecom_str
);
1041 vty_out(vty
, " %-25s", rt_buf
);
1044 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1046 /* If there are multiple import RTs we break here and show only
1053 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1055 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1056 ecom_str
= ecommunity_ecom2str(ecom
,
1057 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1060 json_object_array_add(json_export_rtl
,
1061 json_object_new_string(ecom_str
));
1063 if (listcount(vpn
->export_rtl
) > 1)
1064 sprintf(rt_buf
, "%s, ...", ecom_str
);
1066 sprintf(rt_buf
, "%s", ecom_str
);
1067 vty_out(vty
, " %-25s", rt_buf
);
1070 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1072 /* If there are multiple export RTs we break here and show only
1079 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1082 char vni_str
[VNI_STR_LEN
];
1084 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1085 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1086 json_object_object_add(json
, vni_str
, json_vni
);
1092 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1093 enum bgp_show_type type
, void *output_arg
,
1094 int option
, bool use_json
)
1096 afi_t afi
= AFI_L2VPN
;
1098 struct bgp_table
*table
;
1099 struct bgp_node
*rn
;
1100 struct bgp_node
*rm
;
1101 struct bgp_path_info
*pi
;
1104 char rd_str
[RD_ADDRSTRLEN
];
1108 unsigned long output_count
= 0;
1109 unsigned long total_count
= 0;
1110 json_object
*json
= NULL
;
1111 json_object
*json_array
= NULL
;
1112 json_object
*json_prefix_info
= NULL
;
1114 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1116 bgp
= bgp_get_evpn();
1119 vty_out(vty
, "No BGP process is configured\n");
1121 vty_out(vty
, "{}\n");
1126 json
= json_object_new_object();
1128 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1129 rn
= bgp_route_next(rn
)) {
1131 json_object
*json_nroute
= NULL
;
1133 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1136 table
= bgp_node_get_bgp_table_info(rn
);
1141 tbl_ver
= table
->version
;
1143 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1144 pi
= bgp_node_get_bgp_path_info(rm
);
1149 for (; pi
; pi
= pi
->next
) {
1151 if (type
== bgp_show_type_neighbor
) {
1152 struct peer
*peer
= output_arg
;
1154 if (peer_cmp(peer
, pi
->peer
) != 0)
1157 if (type
== bgp_show_type_lcommunity_exact
) {
1158 struct lcommunity
*lcom
= output_arg
;
1160 if (!pi
->attr
->lcommunity
||
1162 pi
->attr
->lcommunity
, lcom
))
1165 if (type
== bgp_show_type_lcommunity
) {
1166 struct lcommunity
*lcom
= output_arg
;
1168 if (!pi
->attr
->lcommunity
||
1170 pi
->attr
->lcommunity
, lcom
))
1173 if (type
== bgp_show_type_community
) {
1174 struct community
*com
= output_arg
;
1176 if (!pi
->attr
->community
||
1178 pi
->attr
->community
, com
))
1181 if (type
== bgp_show_type_community_exact
) {
1182 struct community
*com
= output_arg
;
1184 if (!pi
->attr
->community
||
1186 pi
->attr
->community
, com
))
1191 json_object_int_add(
1192 json
, "bgpTableVersion",
1194 json_object_string_add(
1199 json_object_int_add(
1202 bgp
->default_local_pref
);
1203 json_object_int_add(
1207 if (option
== SHOW_DISPLAY_TAGS
)
1212 == SHOW_DISPLAY_OVERLAY
)
1216 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1224 json_object_new_object();
1225 bgp_evpn_show_route_rd_header(vty
, rn
,
1226 json_nroute
, rd_str
,
1230 if (use_json
&& !json_array
)
1231 json_array
= json_object_new_array();
1233 if (option
== SHOW_DISPLAY_TAGS
)
1234 route_vty_out_tag(vty
, &rm
->p
, pi
,
1235 no_display
, SAFI_EVPN
,
1237 else if (option
== SHOW_DISPLAY_OVERLAY
)
1238 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1242 route_vty_out(vty
, &rm
->p
, pi
,
1243 no_display
, SAFI_EVPN
,
1251 if (use_json
&& json_array
) {
1252 json_prefix_info
= json_object_new_object();
1254 json_object_string_add(json_prefix_info
,
1255 "prefix", bgp_evpn_route2str(
1256 (struct prefix_evpn
*)&rm
->p
, buf
,
1259 json_object_int_add(json_prefix_info
,
1260 "prefixLen", rm
->p
.prefixlen
);
1262 json_object_object_add(json_prefix_info
,
1263 "paths", json_array
);
1264 json_object_object_add(json_nroute
, buf
,
1270 if (use_json
&& json_nroute
)
1271 json_object_object_add(json
, rd_str
, json_nroute
);
1275 json_object_int_add(json
, "numPrefix", output_count
);
1276 json_object_int_add(json
, "totalPrefix", total_count
);
1277 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1278 json
, JSON_C_TO_STRING_PRETTY
));
1279 json_object_free(json
);
1281 if (output_count
== 0)
1282 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1286 "\nDisplayed %ld out of %ld total prefixes\n",
1287 output_count
, total_count
);
1292 DEFUN(show_ip_bgp_l2vpn_evpn
,
1293 show_ip_bgp_l2vpn_evpn_cmd
,
1294 "show [ip] bgp l2vpn evpn [json]",
1295 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1297 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1298 use_json(argc
, argv
));
1301 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1302 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1303 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1309 "Display information for a route distinguisher\n"
1310 "VPN Route Distinguisher\n" JSON_STR
)
1312 int idx_ext_community
= 0;
1314 struct prefix_rd prd
;
1316 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1318 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1320 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1323 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1324 use_json(argc
, argv
));
1327 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1328 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1329 "show [ip] bgp l2vpn evpn all tags",
1335 "Display information about all EVPN NLRIs\n"
1336 "Display BGP tags for prefixes\n")
1338 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1342 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1343 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1344 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1350 "Display information for a route distinguisher\n"
1351 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1353 int idx_ext_community
= 0;
1355 struct prefix_rd prd
;
1357 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1359 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1361 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1364 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1368 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1369 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1370 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1376 "Detailed information on TCP and BGP neighbor connections\n"
1377 "IPv4 Neighbor to display information about\n"
1378 "IPv6 Neighbor to display information about\n"
1379 "Neighbor on BGP configured interface\n"
1380 "Display routes learned from neighbor\n" JSON_STR
)
1384 char *peerstr
= NULL
;
1385 bool uj
= use_json(argc
, argv
);
1386 afi_t afi
= AFI_L2VPN
;
1387 safi_t safi
= SAFI_EVPN
;
1388 struct bgp
*bgp
= NULL
;
1390 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1393 vty_out(vty
, "No index\n");
1397 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1398 argv_find(argv
, argc
, "neighbors", &idx
);
1399 peerstr
= argv
[++idx
]->arg
;
1401 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1404 json_object
*json_no
= NULL
;
1405 json_no
= json_object_new_object();
1406 json_object_string_add(json_no
, "warning",
1407 "Malformed address");
1408 vty_out(vty
, "%s\n",
1409 json_object_to_json_string(json_no
));
1410 json_object_free(json_no
);
1412 vty_out(vty
, "Malformed address: %s\n",
1416 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1418 json_object
*json_no
= NULL
;
1419 json_no
= json_object_new_object();
1420 json_object_string_add(
1422 "No such neighbor or address family");
1423 vty_out(vty
, "%s\n",
1424 json_object_to_json_string(json_no
));
1425 json_object_free(json_no
);
1427 vty_out(vty
, "%% No such neighbor or address family\n");
1431 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1435 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1436 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1437 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1443 "Display information for a route distinguisher\n"
1444 "VPN Route Distinguisher\n"
1445 "Detailed information on TCP and BGP neighbor connections\n"
1446 "IPv4 Neighbor to display information about\n"
1447 "IPv6 Neighbor to display information about\n"
1448 "Neighbor on BGP configured interface\n"
1449 "Display routes learned from neighbor\n" JSON_STR
)
1451 int idx_ext_community
= 0;
1455 char *peerstr
= NULL
;
1456 struct prefix_rd prd
;
1457 bool uj
= use_json(argc
, argv
);
1458 afi_t afi
= AFI_L2VPN
;
1459 safi_t safi
= SAFI_EVPN
;
1460 struct bgp
*bgp
= NULL
;
1462 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1465 vty_out(vty
, "No index\n");
1469 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1470 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1473 json_object
*json_no
= NULL
;
1474 json_no
= json_object_new_object();
1475 json_object_string_add(json_no
, "warning",
1476 "Malformed Route Distinguisher");
1477 vty_out(vty
, "%s\n",
1478 json_object_to_json_string(json_no
));
1479 json_object_free(json_no
);
1481 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1485 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1486 argv_find(argv
, argc
, "neighbors", &idx
);
1487 peerstr
= argv
[++idx
]->arg
;
1489 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1492 json_object
*json_no
= NULL
;
1493 json_no
= json_object_new_object();
1494 json_object_string_add(json_no
, "warning",
1495 "Malformed address");
1496 vty_out(vty
, "%s\n",
1497 json_object_to_json_string(json_no
));
1498 json_object_free(json_no
);
1500 vty_out(vty
, "Malformed address: %s\n",
1504 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1506 json_object
*json_no
= NULL
;
1507 json_no
= json_object_new_object();
1508 json_object_string_add(
1510 "No such neighbor or address family");
1511 vty_out(vty
, "%s\n",
1512 json_object_to_json_string(json_no
));
1513 json_object_free(json_no
);
1515 vty_out(vty
, "%% No such neighbor or address family\n");
1519 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1523 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1524 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1525 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1531 "Detailed information on TCP and BGP neighbor connections\n"
1532 "IPv4 Neighbor to display information about\n"
1533 "IPv6 Neighbor to display information about\n"
1534 "Neighbor on BGP configured interface\n"
1535 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1539 bool uj
= use_json(argc
, argv
);
1540 struct bgp
*bgp
= NULL
;
1541 afi_t afi
= AFI_L2VPN
;
1542 safi_t safi
= SAFI_EVPN
;
1543 char *peerstr
= NULL
;
1548 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1551 vty_out(vty
, "No index\n");
1555 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1556 argv_find(argv
, argc
, "neighbors", &idx
);
1557 peerstr
= argv
[++idx
]->arg
;
1559 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1562 json_object
*json_no
= NULL
;
1563 json_no
= json_object_new_object();
1564 json_object_string_add(json_no
, "warning",
1565 "Malformed address");
1566 vty_out(vty
, "%s\n",
1567 json_object_to_json_string(json_no
));
1568 json_object_free(json_no
);
1570 vty_out(vty
, "Malformed address: %s\n",
1574 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1576 json_object
*json_no
= NULL
;
1577 json_no
= json_object_new_object();
1578 json_object_string_add(
1580 "No such neighbor or address family");
1581 vty_out(vty
, "%s\n",
1582 json_object_to_json_string(json_no
));
1583 json_object_free(json_no
);
1585 vty_out(vty
, "%% No such neighbor or address family\n");
1589 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1592 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1593 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1594 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1600 "Display information for a route distinguisher\n"
1601 "VPN Route Distinguisher\n"
1602 "Detailed information on TCP and BGP neighbor connections\n"
1603 "IPv4 Neighbor to display information about\n"
1604 "IPv6 Neighbor to display information about\n"
1605 "Neighbor on BGP configured interface\n"
1606 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1608 int idx_ext_community
= 0;
1612 struct prefix_rd prd
;
1613 struct bgp
*bgp
= NULL
;
1614 bool uj
= use_json(argc
, argv
);
1615 char *peerstr
= NULL
;
1616 afi_t afi
= AFI_L2VPN
;
1617 safi_t safi
= SAFI_EVPN
;
1625 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1628 vty_out(vty
, "No index\n");
1632 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1634 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1635 argv_find(argv
, argc
, "neighbors", &idx
);
1636 peerstr
= argv
[++idx
]->arg
;
1638 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1641 json_object
*json_no
= NULL
;
1642 json_no
= json_object_new_object();
1643 json_object_string_add(json_no
, "warning",
1644 "Malformed address");
1645 vty_out(vty
, "%s\n",
1646 json_object_to_json_string(json_no
));
1647 json_object_free(json_no
);
1649 vty_out(vty
, "Malformed address: %s\n",
1653 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1655 json_object
*json_no
= NULL
;
1656 json_no
= json_object_new_object();
1657 json_object_string_add(
1659 "No such neighbor or address family");
1660 vty_out(vty
, "%s\n",
1661 json_object_to_json_string(json_no
));
1662 json_object_free(json_no
);
1664 vty_out(vty
, "%% No such neighbor or address family\n");
1668 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1671 json_object
*json_no
= NULL
;
1672 json_no
= json_object_new_object();
1673 json_object_string_add(json_no
, "warning",
1674 "Malformed Route Distinguisher");
1675 vty_out(vty
, "%s\n",
1676 json_object_to_json_string(json_no
));
1677 json_object_free(json_no
);
1679 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1683 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1686 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1687 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1688 "show [ip] bgp l2vpn evpn all overlay [json]",
1694 "Display information about all EVPN NLRIs\n"
1695 "Display BGP Overlay Information for prefixes\n"
1698 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1699 SHOW_DISPLAY_OVERLAY
,
1700 use_json(argc
, argv
));
1703 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1704 show_ip_bgp_evpn_rd_overlay_cmd
,
1705 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1711 "Display information for a route distinguisher\n"
1712 "VPN Route Distinguisher\n"
1713 "Display BGP Overlay Information for prefixes\n")
1715 int idx_ext_community
= 0;
1717 struct prefix_rd prd
;
1719 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1721 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1723 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1726 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1727 SHOW_DISPLAY_OVERLAY
,
1728 use_json(argc
, argv
));
1731 DEFUN(show_bgp_l2vpn_evpn_com
,
1732 show_bgp_l2vpn_evpn_com_cmd
,
1733 "show bgp l2vpn evpn \
1734 <community AA:NN|large-community AA:BB:CC> \
1735 [exact-match] [json]",
1740 "Display routes matching the community\n"
1741 "Community number where AA and NN are (0-65535)\n"
1742 "Display routes matching the large-community\n"
1743 "List of large-community numbers\n"
1744 "Exact match of the communities\n"
1749 const char *clist_number_or_name
;
1750 int show_type
= bgp_show_type_normal
;
1751 struct community
*com
;
1752 struct lcommunity
*lcom
;
1754 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1755 clist_number_or_name
= argv
[++idx
]->arg
;
1756 show_type
= bgp_show_type_lcommunity
;
1758 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1759 show_type
= bgp_show_type_lcommunity_exact
;
1761 lcom
= lcommunity_str2com(clist_number_or_name
);
1763 vty_out(vty
, "%% Large-community malformed\n");
1767 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1768 SHOW_DISPLAY_STANDARD
,
1769 use_json(argc
, argv
));
1771 lcommunity_free(&lcom
);
1772 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1773 clist_number_or_name
= argv
[++idx
]->arg
;
1774 show_type
= bgp_show_type_community
;
1776 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1777 show_type
= bgp_show_type_community_exact
;
1779 com
= community_str2com(clist_number_or_name
);
1782 vty_out(vty
, "%% Community malformed: %s\n",
1783 clist_number_or_name
);
1787 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1788 SHOW_DISPLAY_STANDARD
,
1789 use_json(argc
, argv
));
1790 community_free(&com
);
1796 /* For testing purpose, static route of EVPN RT-5. */
1797 DEFUN(evpnrt5_network
,
1798 evpnrt5_network_cmd
,
1799 "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]",
1800 "Specify a network to announce via BGP\n"
1803 "Specify Route Distinguisher\n"
1804 "VPN Route Distinguisher\n"
1806 "Ethernet Tag Value\n"
1809 "Ethernet Segment Identifier\n"
1810 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1812 "Gateway IP ( A.B.C.D )\n"
1813 "Gateway IPv6 ( X:X::X:X )\n"
1814 "Router Mac Ext Comm\n"
1815 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1816 "Route-map to modify the attributes\n"
1817 "Name of the route map\n")
1819 int idx_ipv4_prefixlen
= 1;
1820 int idx_route_distinguisher
= 3;
1825 int idx_routermac
= 13;
1827 return bgp_static_set_safi(
1828 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1829 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1830 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1831 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1832 argv
[idx_routermac
]->arg
);
1835 /* For testing purpose, static route of EVPN RT-5. */
1836 DEFUN(no_evpnrt5_network
,
1837 no_evpnrt5_network_cmd
,
1838 "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>",
1840 "Specify a network to announce via BGP\n"
1843 "Specify Route Distinguisher\n"
1844 "VPN Route Distinguisher\n"
1846 "Ethernet Tag Value\n"
1849 "Ethernet Segment Identifier\n"
1850 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1851 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1853 int idx_ipv4_prefixlen
= 2;
1854 int idx_ext_community
= 4;
1859 return bgp_static_unset_safi(
1860 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1861 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1862 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1863 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1866 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1868 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1871 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1873 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1877 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1878 * check that this is a change.
1880 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1881 struct ecommunity
*ecomadd
)
1883 /* If the VNI is "live", we need to uninstall routes using the current
1884 * import RT(s) first before we update the import RT, and subsequently
1887 if (is_vni_live(vpn
))
1888 bgp_evpn_uninstall_routes(bgp
, vpn
);
1890 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1891 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1893 /* If the auto route-target is in use we must remove it */
1894 evpn_import_rt_delete_auto(bgp
, vpn
);
1896 /* Add new RT and rebuild the RT to VNI mapping */
1897 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1899 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1900 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1902 /* Install routes that match new import RT */
1903 if (is_vni_live(vpn
))
1904 bgp_evpn_install_routes(bgp
, vpn
);
1908 * Unconfigure Import RT(s) for a VNI (vty handler).
1910 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1911 struct ecommunity
*ecomdel
)
1913 struct listnode
*node
, *nnode
, *node_to_del
;
1914 struct ecommunity
*ecom
;
1916 /* Along the lines of "configure" except we have to reset to the
1919 if (is_vni_live(vpn
))
1920 bgp_evpn_uninstall_routes(bgp
, vpn
);
1922 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1923 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1925 /* Delete all import RTs */
1926 if (ecomdel
== NULL
) {
1927 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1928 ecommunity_free(&ecom
);
1929 list_delete_node(vpn
->import_rtl
, node
);
1933 /* Delete a specific import RT */
1937 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1938 if (ecommunity_match(ecom
, ecomdel
)) {
1939 ecommunity_free(&ecom
);
1946 list_delete_node(vpn
->import_rtl
, node_to_del
);
1949 assert(vpn
->import_rtl
);
1950 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1951 if (list_isempty(vpn
->import_rtl
)) {
1952 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1953 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1955 /* Rebuild the RT to VNI mapping */
1957 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1959 /* Install routes that match new import RT */
1960 if (is_vni_live(vpn
))
1961 bgp_evpn_install_routes(bgp
, vpn
);
1965 * Configure the Export RT for a VNI (vty handler). Caller expected to
1966 * check that this is a change. Note that only a single export RT is
1967 * allowed for a VNI and any change to configuration is implemented as
1968 * a "replace" (similar to other configuration).
1970 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1971 struct ecommunity
*ecomadd
)
1973 /* If the auto route-target is in use we must remove it */
1974 evpn_export_rt_delete_auto(bgp
, vpn
);
1976 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1977 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1979 if (is_vni_live(vpn
))
1980 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1984 * Unconfigure the Export RT for a VNI (vty handler)
1986 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1987 struct ecommunity
*ecomdel
)
1989 struct listnode
*node
, *nnode
, *node_to_del
;
1990 struct ecommunity
*ecom
;
1992 /* Delete all export RTs */
1993 if (ecomdel
== NULL
) {
1994 /* Reset to default and process all routes. */
1995 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1996 ecommunity_free(&ecom
);
1997 list_delete_node(vpn
->export_rtl
, node
);
2001 /* Delete a specific export RT */
2005 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2006 if (ecommunity_match(ecom
, ecomdel
)) {
2007 ecommunity_free(&ecom
);
2014 list_delete_node(vpn
->export_rtl
, node_to_del
);
2017 assert(vpn
->export_rtl
);
2018 if (list_isempty(vpn
->export_rtl
)) {
2019 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2020 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2023 if (is_vni_live(vpn
))
2024 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2028 * Configure RD for VRF
2030 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2032 /* If we have already advertise type-5 routes with a diffrent RD, we
2033 * have to delete and withdraw them firs
2035 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2038 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2039 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2041 /* We have a new RD for VRF.
2042 * Advertise all type-5 routes again with the new RD
2044 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2048 * Unconfigure RD for VRF
2050 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2052 /* If we have already advertise type-5 routes with a diffrent RD, we
2053 * have to delete and withdraw them firs
2055 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2057 /* fall back to default RD */
2058 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2059 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2061 /* We have a new RD for VRF.
2062 * Advertise all type-5 routes again with the new RD
2064 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2068 * Configure RD for a VNI (vty handler)
2070 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2071 struct prefix_rd
*rd
)
2073 /* If the VNI is "live", we need to delete and withdraw this VNI's
2074 * local routes with the prior RD first. Then, after updating RD,
2075 * need to re-advertise.
2077 if (is_vni_live(vpn
))
2078 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2081 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2082 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2084 if (is_vni_live(vpn
))
2085 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2089 * Unconfigure RD for a VNI (vty handler)
2091 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2093 /* If the VNI is "live", we need to delete and withdraw this VNI's
2094 * local routes with the prior RD first. Then, after resetting RD
2095 * to automatic value, need to re-advertise.
2097 if (is_vni_live(vpn
))
2098 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2100 /* reset RD to default */
2101 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2103 if (is_vni_live(vpn
))
2104 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2108 * Create VNI, if not already present (VTY handler). Mark as configured.
2110 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2112 struct bgpevpn
*vpn
;
2113 struct in_addr mcast_grp
= {INADDR_ANY
};
2118 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2120 /* Check if this L2VNI is already configured as L3VNI */
2121 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2124 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2129 /* tenant vrf will be updated when we get local_vni_add from
2132 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2136 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2142 /* Mark as configured. */
2143 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2148 * Delete VNI. If VNI does not exist in the system (i.e., just
2149 * configuration), all that is needed is to free it. Otherwise,
2150 * any parameters configured for the VNI need to be reset (with
2151 * appropriate action) and the VNI marked as unconfigured; the
2152 * VNI will continue to exist, purely as a "learnt" entity.
2154 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2156 assert(bgp
->vnihash
);
2158 if (!is_vni_live(vpn
)) {
2159 bgp_evpn_free(bgp
, vpn
);
2163 /* We need to take the unconfigure action for each parameter of this VNI
2164 * that is configured. Some optimization is possible, but not worth the
2165 * additional code for an operation that should be pretty rare.
2167 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2169 /* First, deal with the export side - RD and export RT changes. */
2170 if (is_rd_configured(vpn
))
2171 evpn_unconfigure_rd(bgp
, vpn
);
2172 if (is_export_rt_configured(vpn
))
2173 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2175 /* Next, deal with the import side. */
2176 if (is_import_rt_configured(vpn
))
2177 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2183 * Display import RT mapping to VRFs (vty handler)
2184 * bgp_evpn: evpn bgp instance
2186 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2194 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2195 (void (*)(struct hash_bucket
*,
2196 void *))show_vrf_import_rt_entry
,
2201 * Display import RT mapping to VNIs (vty handler)
2203 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2212 bgp
->import_rt_hash
,
2213 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2218 * Display EVPN routes for all VNIs - vty handler.
2220 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2221 struct in_addr vtep_ip
, json_object
*json
,
2225 struct vni_walk_ctx wctx
;
2227 num_vnis
= hashcount(bgp
->vnihash
);
2230 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2233 wctx
.vtep_ip
= vtep_ip
;
2235 wctx
.detail
= detail
;
2236 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2237 void *))show_vni_routes_hash
,
2242 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2244 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2245 vni_t vni
, struct in_addr orig_ip
,
2248 struct bgpevpn
*vpn
;
2249 struct prefix_evpn p
;
2250 struct bgp_node
*rn
;
2251 struct bgp_path_info
*pi
;
2252 uint32_t path_cnt
= 0;
2255 json_object
*json_paths
= NULL
;
2261 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2263 vty_out(vty
, "VNI not found\n");
2267 /* See if route exists. */
2268 build_evpn_type3_prefix(&p
, orig_ip
);
2269 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2270 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2272 vty_out(vty
, "%% Network not in table\n");
2277 json_paths
= json_object_new_array();
2279 /* Prefix and num paths displayed once per prefix. */
2280 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2282 /* Display each path for this prefix. */
2283 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2284 json_object
*json_path
= NULL
;
2287 json_path
= json_object_new_array();
2289 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2293 json_object_array_add(json_paths
, json_path
);
2300 json_object_object_add(json
, "paths", json_paths
);
2302 json_object_int_add(json
, "numPaths", path_cnt
);
2304 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2310 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2311 * By definition, only matching type-2 route will be displayed.
2313 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2314 vni_t vni
, struct ethaddr
*mac
,
2315 struct ipaddr
*ip
, json_object
*json
)
2317 struct bgpevpn
*vpn
;
2318 struct prefix_evpn p
;
2319 struct bgp_node
*rn
;
2320 struct bgp_path_info
*pi
;
2321 uint32_t path_cnt
= 0;
2324 json_object
*json_paths
= NULL
;
2330 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2333 vty_out(vty
, "VNI not found\n");
2337 /* See if route exists. Look for both non-sticky and sticky. */
2338 build_evpn_type2_prefix(&p
, mac
, ip
);
2339 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2340 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2342 vty_out(vty
, "%% Network not in table\n");
2347 json_paths
= json_object_new_array();
2349 /* Prefix and num paths displayed once per prefix. */
2350 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2352 /* Display each path for this prefix. */
2353 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2354 json_object
*json_path
= NULL
;
2357 json_path
= json_object_new_array();
2359 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2363 json_object_array_add(json_paths
, json_path
);
2370 json_object_object_add(json
, "paths", json_paths
);
2372 json_object_int_add(json
, "numPaths", path_cnt
);
2374 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2379 /* Disaplay EVPN routes for a ESI - VTY handler */
2380 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2381 esi_t
*esi
, json_object
*json
)
2383 struct evpnes
*es
= NULL
;
2386 es
= bgp_evpn_lookup_es(bgp
, esi
);
2389 vty_out(vty
, "ESI not found\n");
2393 show_esi_routes(bgp
, es
, vty
, json
);
2397 * Display EVPN routes for a VNI - vty handler.
2398 * If 'type' is non-zero, only routes matching that type are shown.
2399 * If the vtep_ip is non zero, only routes behind that vtep are shown
2401 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2402 int type
, struct in_addr vtep_ip
,
2405 struct bgpevpn
*vpn
;
2408 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2411 vty_out(vty
, "VNI not found\n");
2415 /* Walk this VNI's route table and display appropriate routes. */
2416 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2420 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2421 * IP (vty handler). By definition, only matching type-2 route will be
2424 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2425 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2426 struct ipaddr
*ip
, json_object
*json
)
2428 struct prefix_evpn p
;
2429 struct bgp_node
*rn
;
2430 struct bgp_path_info
*pi
;
2433 uint32_t path_cnt
= 0;
2434 json_object
*json_paths
= NULL
;
2435 char prefix_str
[BUFSIZ
];
2440 /* See if route exists. Look for both non-sticky and sticky. */
2441 build_evpn_type2_prefix(&p
, mac
, ip
);
2442 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2443 (struct prefix
*)&p
, prd
);
2444 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2446 vty_out(vty
, "%% Network not in table\n");
2450 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2451 sizeof(prefix_str
));
2453 /* Prefix and num paths displayed once per prefix. */
2454 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2457 json_paths
= json_object_new_array();
2459 /* Display each path for this prefix. */
2460 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2461 json_object
*json_path
= NULL
;
2464 json_path
= json_object_new_array();
2466 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2470 json_object_array_add(json_paths
, json_path
);
2475 if (json
&& path_cnt
) {
2477 json_object_object_add(json
, prefix_str
, json_paths
);
2478 json_object_int_add(json
, "numPaths", path_cnt
);
2480 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2486 * Display BGP EVPN routing table -- for specific RD (vty handler)
2487 * If 'type' is non-zero, only routes matching that type are shown.
2489 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2490 struct prefix_rd
*prd
, int type
,
2493 struct bgp_node
*rd_rn
;
2494 struct bgp_table
*table
;
2495 struct bgp_node
*rn
;
2496 struct bgp_path_info
*pi
;
2500 uint32_t prefix_cnt
, path_cnt
;
2501 char rd_str
[RD_ADDRSTRLEN
];
2502 json_object
*json_rd
= NULL
;
2503 int add_rd_to_json
= 0;
2507 prefix_cnt
= path_cnt
= 0;
2509 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2511 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2515 table
= bgp_node_get_bgp_table_info(rd_rn
);
2520 json_rd
= json_object_new_object();
2521 json_object_string_add(json_rd
, "rd", rd_str
);
2524 /* Display all prefixes with this RD. */
2525 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2526 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2527 json_object
*json_prefix
= NULL
;
2528 json_object
*json_paths
= NULL
;
2529 char prefix_str
[BUFSIZ
];
2530 int add_prefix_to_json
= 0;
2532 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2533 sizeof(prefix_str
));
2535 if (type
&& evp
->prefix
.route_type
!= type
)
2539 json_prefix
= json_object_new_object();
2541 pi
= bgp_node_get_bgp_path_info(rn
);
2543 /* RD header and legend - once overall. */
2544 if (rd_header
&& !json
) {
2546 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2548 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2550 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2554 /* Prefix and num paths displayed once per prefix. */
2555 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2562 json_paths
= json_object_new_array();
2564 /* Display each path for this prefix. */
2565 for (; pi
; pi
= pi
->next
) {
2566 json_object
*json_path
= NULL
;
2569 json_path
= json_object_new_array();
2571 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2575 json_object_array_add(json_paths
, json_path
);
2578 add_prefix_to_json
= 1;
2582 if (json
&& add_prefix_to_json
) {
2583 json_object_object_add(json_prefix
, "paths",
2585 json_object_object_add(json_rd
, prefix_str
,
2590 if (json
&& add_rd_to_json
)
2591 json_object_object_add(json
, rd_str
, json_rd
);
2594 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2595 json_object_int_add(json
, "numPaths", path_cnt
);
2597 if (prefix_cnt
== 0)
2598 vty_out(vty
, "No prefixes exist with this RD%s\n",
2599 type
? " (of requested type)" : "");
2602 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2603 prefix_cnt
, path_cnt
,
2604 type
? " (of requested type)" : "");
2609 * Display BGP EVPN routing table - all routes (vty handler).
2610 * If 'type' is non-zero, only routes matching that type are shown.
2612 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2613 json_object
*json
, int detail
)
2615 struct bgp_node
*rd_rn
;
2616 struct bgp_table
*table
;
2617 struct bgp_node
*rn
;
2618 struct bgp_path_info
*pi
;
2619 int header
= detail
? 0 : 1;
2623 uint32_t prefix_cnt
, path_cnt
;
2627 prefix_cnt
= path_cnt
= 0;
2629 /* EVPN routing table is a 2-level table with the first level being
2632 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2633 rd_rn
= bgp_route_next(rd_rn
)) {
2634 char rd_str
[RD_ADDRSTRLEN
];
2635 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2636 int add_rd_to_json
= 0;
2639 table
= bgp_node_get_bgp_table_info(rd_rn
);
2643 tbl_ver
= table
->version
;
2644 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2648 json_rd
= json_object_new_object();
2652 /* Display all prefixes for an RD */
2653 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2654 json_object
*json_prefix
=
2655 NULL
; /* contains prefix under a RD */
2656 json_object
*json_paths
=
2657 NULL
; /* array of paths under a prefix*/
2658 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2659 char prefix_str
[BUFSIZ
];
2660 int add_prefix_to_json
= 0;
2662 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2663 prefix_str
, sizeof(prefix_str
));
2665 if (type
&& evp
->prefix
.route_type
!= type
)
2668 pi
= bgp_node_get_bgp_path_info(rn
);
2670 /* Overall header/legend displayed once. */
2672 bgp_evpn_show_route_header(vty
, bgp
,
2677 "%19s Extended Community\n"
2682 /* RD header - per RD. */
2684 bgp_evpn_show_route_rd_header(
2685 vty
, rd_rn
, json_rd
, rd_str
,
2694 json_prefix
= json_object_new_object();
2695 json_paths
= json_object_new_array();
2696 json_object_string_add(json_prefix
, "prefix",
2698 json_object_int_add(json_prefix
, "prefixLen",
2702 /* Prefix and num paths displayed once per prefix. */
2704 route_vty_out_detail_header(
2706 (struct prefix_rd
*)&rd_rn
->p
,
2707 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2709 /* For EVPN, the prefix is displayed for each path (to
2711 * with code that already exists).
2713 for (; pi
; pi
= pi
->next
) {
2714 json_object
*json_path
= NULL
;
2716 add_prefix_to_json
= 1;
2720 json_path
= json_object_new_array();
2723 route_vty_out_detail(
2724 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2725 SAFI_EVPN
, json_path
);
2727 route_vty_out(vty
, &rn
->p
, pi
, 0,
2728 SAFI_EVPN
, json_path
);
2731 json_object_array_add(json_paths
,
2735 if (json
&& add_prefix_to_json
) {
2736 json_object_object_add(json_prefix
, "paths",
2738 json_object_object_add(json_rd
, prefix_str
,
2743 if (json
&& add_rd_to_json
)
2744 json_object_object_add(json
, rd_str
, json_rd
);
2748 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2749 json_object_int_add(json
, "numPaths", path_cnt
);
2751 if (prefix_cnt
== 0) {
2752 vty_out(vty
, "No EVPN prefixes %sexist\n",
2753 type
? "(of requested type) " : "");
2755 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2756 prefix_cnt
, path_cnt
,
2757 type
? " (of requested type)" : "");
2762 /* Display specific ES */
2763 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2766 struct evpnes
*es
= NULL
;
2768 es
= bgp_evpn_lookup_es(bgp
, esi
);
2770 display_es(vty
, es
, json
);
2773 vty_out(vty
, "{}\n");
2775 vty_out(vty
, "ESI not found\n");
2781 /* Display all ESs */
2782 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2788 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2789 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2794 hash_iterate(bgp
->esihash
,
2795 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2800 * Display specified VNI (vty handler)
2802 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2806 struct bgpevpn
*vpn
;
2808 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2811 display_vni(vty
, vpn
, json
);
2813 struct bgp
*bgp_temp
;
2814 struct listnode
*node
= NULL
;
2816 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2817 if (bgp_temp
->l3vni
== vni
) {
2819 display_l3vni(vty
, bgp_temp
, json
);
2826 vty_out(vty
, "{}\n");
2828 vty_out(vty
, "VNI not found\n");
2835 * Display a VNI (upon user query).
2837 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2841 struct bgp
*bgp_temp
= NULL
;
2842 struct listnode
*node
;
2846 vty_out(vty
, "Flags: * - Kernel\n");
2847 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2848 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2851 /* print all L2 VNIS */
2854 hash_iterate(bgp
->vnihash
,
2855 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2858 /* print all L3 VNIs */
2859 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2860 show_l3vni_entry(vty
, bgp_temp
, json
);
2864 * evpn - enable advertisement of svi MAC-IP
2866 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2870 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2872 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2875 bgp
->evpn_info
->advertise_svi_macip
= set
;
2876 bgp_zebra_advertise_svi_macip(bgp
,
2877 bgp
->evpn_info
->advertise_svi_macip
, 0);
2879 if (set
&& vpn
->advertise_svi_macip
)
2881 else if (!set
&& !vpn
->advertise_svi_macip
)
2884 vpn
->advertise_svi_macip
= set
;
2885 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2891 * evpn - enable advertisement of default g/w
2893 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2896 if (bgp
->advertise_gw_macip
)
2899 bgp
->advertise_gw_macip
= 1;
2900 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2902 if (vpn
->advertise_gw_macip
)
2905 vpn
->advertise_gw_macip
= 1;
2906 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2913 * evpn - disable advertisement of default g/w
2915 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2916 struct bgpevpn
*vpn
)
2919 if (!bgp
->advertise_gw_macip
)
2922 bgp
->advertise_gw_macip
= 0;
2923 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2925 if (!vpn
->advertise_gw_macip
)
2928 vpn
->advertise_gw_macip
= 0;
2929 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2936 * evpn - enable advertisement of default g/w
2938 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2939 afi_t afi
, bool add
)
2941 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2944 /* bail if we are already advertising default route */
2945 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2949 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2950 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2951 else if (afi
== AFI_IP6
)
2952 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2953 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2955 /* bail out if we havent advertised the default route */
2956 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2959 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2960 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2961 else if (afi
== AFI_IP6
)
2962 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2963 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2966 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2970 * evpn - enable advertisement of default g/w
2972 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2973 struct bgpevpn
*vpn
)
2975 if (vpn
->advertise_subnet
)
2978 vpn
->advertise_subnet
= 1;
2979 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2983 * evpn - disable advertisement of default g/w
2985 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2987 if (!vpn
->advertise_subnet
)
2990 vpn
->advertise_subnet
= 0;
2991 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2995 * EVPN (VNI advertisement) enabled. Register with zebra.
2997 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2999 bgp
->advertise_all_vni
= 1;
3001 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3005 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3006 * cache, EVPN routes (delete and withdraw from peers).
3008 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3010 bgp
->advertise_all_vni
= 0;
3011 bgp_set_evpn(bgp_get_default());
3012 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3013 bgp_evpn_cleanup_on_disable(bgp
);
3017 * EVPN - use RFC8365 to auto-derive RT
3019 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3021 bgp
->advertise_autort_rfc8365
= 1;
3022 bgp_evpn_handle_autort_change(bgp
);
3026 * EVPN - don't use RFC8365 to auto-derive RT
3028 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3030 bgp
->advertise_autort_rfc8365
= 0;
3031 bgp_evpn_handle_autort_change(bgp
);
3034 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3036 char buf1
[RD_ADDRSTRLEN
];
3038 struct listnode
*node
, *nnode
;
3039 struct ecommunity
*ecom
;
3041 if (is_vni_configured(vpn
)) {
3042 vty_out(vty
, " vni %d\n", vpn
->vni
);
3043 if (is_rd_configured(vpn
))
3044 vty_out(vty
, " rd %s\n",
3045 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3047 if (is_import_rt_configured(vpn
)) {
3048 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3050 ecom_str
= ecommunity_ecom2str(
3051 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3052 vty_out(vty
, " route-target import %s\n",
3054 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3058 if (is_export_rt_configured(vpn
)) {
3059 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3061 ecom_str
= ecommunity_ecom2str(
3062 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3063 vty_out(vty
, " route-target export %s\n",
3065 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3069 if (vpn
->advertise_gw_macip
)
3070 vty_out(vty
, " advertise-default-gw\n");
3072 if (vpn
->advertise_svi_macip
)
3073 vty_out(vty
, " advertise-svi-ip\n");
3075 if (vpn
->advertise_subnet
)
3076 vty_out(vty
, " advertise-subnet\n");
3078 vty_out(vty
, " exit-vni\n");
3082 #ifndef VTYSH_EXTRACT_PL
3083 #include "bgpd/bgp_evpn_vty_clippy.c"
3086 DEFPY(bgp_evpn_flood_control
,
3087 bgp_evpn_flood_control_cmd
,
3088 "[no$no] flooding <disable$disable|head-end-replication$her>",
3090 "Specify handling for BUM packets\n"
3091 "Do not flood any BUM packets\n"
3092 "Flood BUM packets using head-end replication\n")
3094 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3095 enum vxlan_flood_control flood_ctrl
;
3101 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3103 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3107 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3110 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3111 bgp_evpn_flood_control_change(bgp
);
3116 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3117 bgp_evpn_advertise_default_gw_vni_cmd
,
3118 "advertise-default-gw",
3119 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3121 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3122 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3127 evpn_set_advertise_default_gw(bgp
, vpn
);
3132 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3133 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3134 "no advertise-default-gw",
3136 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3138 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3139 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3144 evpn_unset_advertise_default_gw(bgp
, vpn
);
3150 DEFUN (bgp_evpn_advertise_default_gw
,
3151 bgp_evpn_advertise_default_gw_cmd
,
3152 "advertise-default-gw",
3153 "Advertise All default g/w mac-ip routes in EVPN\n")
3155 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3160 if (!EVPN_ENABLED(bgp
)) {
3162 "This command is only supported under the EVPN VRF\n");
3166 evpn_set_advertise_default_gw(bgp
, NULL
);
3171 DEFUN (no_bgp_evpn_advertise_default_gw
,
3172 no_bgp_evpn_advertise_default_gw_cmd
,
3173 "no advertise-default-gw",
3175 "Withdraw All default g/w mac-ip routes from EVPN\n")
3177 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3182 if (!EVPN_ENABLED(bgp
)) {
3184 "This command is only supported under the EVPN VRF\n");
3188 evpn_unset_advertise_default_gw(bgp
, NULL
);
3193 DEFUN (bgp_evpn_advertise_all_vni
,
3194 bgp_evpn_advertise_all_vni_cmd
,
3195 "advertise-all-vni",
3196 "Advertise All local VNIs\n")
3198 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3199 struct bgp
*bgp_evpn
= NULL
;
3204 bgp_evpn
= bgp_get_evpn();
3205 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3206 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3208 return CMD_WARNING_CONFIG_FAILED
;
3211 evpn_set_advertise_all_vni(bgp
);
3215 DEFUN (no_bgp_evpn_advertise_all_vni
,
3216 no_bgp_evpn_advertise_all_vni_cmd
,
3217 "no advertise-all-vni",
3219 "Advertise All local VNIs\n")
3221 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3225 evpn_unset_advertise_all_vni(bgp
);
3229 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3230 bgp_evpn_advertise_autort_rfc8365_cmd
,
3231 "autort rfc8365-compatible",
3232 "Auto-derivation of RT\n"
3233 "Auto-derivation of RT using RFC8365\n")
3235 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3239 evpn_set_advertise_autort_rfc8365(bgp
);
3243 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3244 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3245 "no autort rfc8365-compatible",
3247 "Auto-derivation of RT\n"
3248 "Auto-derivation of RT using RFC8365\n")
3250 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3254 evpn_unset_advertise_autort_rfc8365(bgp
);
3258 DEFUN (bgp_evpn_default_originate
,
3259 bgp_evpn_default_originate_cmd
,
3260 "default-originate <ipv4 | ipv6>",
3261 "originate a default route\n"
3262 "ipv4 address family\n"
3263 "ipv6 address family\n")
3267 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3271 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3272 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3276 DEFUN (no_bgp_evpn_default_originate
,
3277 no_bgp_evpn_default_originate_cmd
,
3278 "no default-originate <ipv4 | ipv6>",
3280 "withdraw a default route\n"
3281 "ipv4 address family\n"
3282 "ipv6 address family\n")
3286 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3290 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3291 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3295 DEFPY (dup_addr_detection
,
3296 dup_addr_detection_cmd
,
3297 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3298 "Duplicate address detection\n"
3299 "Max allowed moves before address detected as duplicate\n"
3300 "Num of max allowed moves (2-1000) default 5\n"
3301 "Duplicate address detection time\n"
3302 "Time in seconds (2-1800) default 180\n")
3304 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3309 if (!EVPN_ENABLED(bgp_vrf
)) {
3311 "This command is only supported under the EVPN VRF\n");
3315 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3318 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3320 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3322 bgp_zebra_dup_addr_detection(bgp_vrf
);
3327 DEFPY (dup_addr_detection_auto_recovery
,
3328 dup_addr_detection_auto_recovery_cmd
,
3329 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3330 "Duplicate address detection\n"
3331 "Duplicate address detection freeze\n"
3332 "Duplicate address detection permanent freeze\n"
3333 "Duplicate address detection freeze time (30-3600)\n")
3335 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3336 uint32_t freeze_time
= freeze_time_val
;
3341 if (!EVPN_ENABLED(bgp_vrf
)) {
3343 "This command is only supported under the EVPN VRF\n");
3347 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3348 bgp_vrf
->evpn_info
->dad_freeze
= true;
3349 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3351 bgp_zebra_dup_addr_detection(bgp_vrf
);
3356 DEFPY (no_dup_addr_detection
,
3357 no_dup_addr_detection_cmd
,
3358 "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>]",
3360 "Duplicate address detection\n"
3361 "Max allowed moves before address detected as duplicate\n"
3362 "Num of max allowed moves (2-1000) default 5\n"
3363 "Duplicate address detection time\n"
3364 "Time in seconds (2-1800) default 180\n"
3365 "Duplicate address detection freeze\n"
3366 "Duplicate address detection permanent freeze\n"
3367 "Duplicate address detection freeze time (30-3600)\n")
3369 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3370 uint32_t max_moves
= (uint32_t)max_moves_val
;
3371 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3376 if (!EVPN_ENABLED(bgp_vrf
)) {
3378 "This command is only supported under the EVPN VRF\n");
3383 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3385 /* Reset all parameters to default. */
3386 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3387 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3388 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3389 bgp_vrf
->evpn_info
->dad_freeze
= false;
3390 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3393 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3395 "%% Value does not match with config\n");
3398 bgp_vrf
->evpn_info
->dad_max_moves
=
3399 EVPN_DAD_DEFAULT_MAX_MOVES
;
3403 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3405 "%% Value does not match with config\n");
3408 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3412 if (bgp_vrf
->evpn_info
->dad_freeze_time
3415 "%% Value does not match with config\n");
3418 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3419 bgp_vrf
->evpn_info
->dad_freeze
= false;
3422 if (permanent_val
) {
3423 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3425 "%% Value does not match with config\n");
3428 bgp_vrf
->evpn_info
->dad_freeze
= false;
3432 bgp_zebra_dup_addr_detection(bgp_vrf
);
3437 DEFPY(bgp_evpn_advertise_svi_ip
,
3438 bgp_evpn_advertise_svi_ip_cmd
,
3439 "[no$no] advertise-svi-ip",
3441 "Advertise svi mac-ip routes in EVPN\n")
3443 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3448 if (!EVPN_ENABLED(bgp
)) {
3450 "This command is only supported under EVPN VRF\n");
3455 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3457 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3462 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3463 bgp_evpn_advertise_svi_ip_vni_cmd
,
3464 "[no$no] advertise-svi-ip",
3466 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3468 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3469 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3475 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3477 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3482 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3483 bgp_evpn_advertise_vni_subnet_cmd
,
3485 "Advertise the subnet corresponding to VNI\n")
3487 struct bgp
*bgp_vrf
= NULL
;
3488 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3489 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3494 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3498 evpn_set_advertise_subnet(bgp
, vpn
);
3502 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3503 no_bgp_evpn_advertise_vni_subnet_cmd
,
3504 "no advertise-subnet",
3506 "Advertise All local VNIs\n")
3508 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3509 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3514 evpn_unset_advertise_subnet(bgp
, vpn
);
3518 DEFUN (bgp_evpn_advertise_type5
,
3519 bgp_evpn_advertise_type5_cmd
,
3520 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3521 "Advertise prefix routes\n"
3524 "route-map for filtering specific routes\n"
3525 "Name of the route map\n")
3527 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3534 int rmap_changed
= 0;
3536 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3537 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3538 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3540 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3542 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3543 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3546 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3550 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3552 "%%only ipv4 or ipv6 address families are supported");
3556 if (safi
!= SAFI_UNICAST
) {
3558 "%%only ipv4 unicast or ipv6 unicast are supported");
3562 if (afi
== AFI_IP
) {
3564 /* if we are already advertising ipv4 prefix as type-5
3567 if (!rmap_changed
&&
3568 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3569 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3571 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3572 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3575 /* if we are already advertising ipv6 prefix as type-5
3578 if (!rmap_changed
&&
3579 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3580 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3582 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3583 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3587 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3588 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3589 XFREE(MTYPE_ROUTE_MAP_NAME
,
3590 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3591 route_map_counter_decrement(
3592 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3593 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3594 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3598 /* set the route-map for advertise command */
3599 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3600 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3601 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3602 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3603 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3604 route_map_counter_increment(
3605 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3608 /* advertise type-5 routes */
3609 if (advertise_type5_routes(bgp_vrf
, afi
))
3610 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3614 DEFUN (no_bgp_evpn_advertise_type5
,
3615 no_bgp_evpn_advertise_type5_cmd
,
3616 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3618 "Advertise prefix routes\n"
3622 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3628 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3629 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3631 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3633 "%%only ipv4 or ipv6 address families are supported");
3637 if (safi
!= SAFI_UNICAST
) {
3639 "%%only ipv4 unicast or ipv6 unicast are supported");
3643 if (afi
== AFI_IP
) {
3645 /* if we are not advertising ipv4 prefix as type-5
3648 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3649 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3650 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3651 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3652 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3656 /* if we are not advertising ipv6 prefix as type-5
3659 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3660 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3661 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3662 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3663 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3667 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3668 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3669 XFREE(MTYPE_ROUTE_MAP_NAME
,
3670 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3671 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3672 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3678 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3679 bgp_evpn_advertise_pip_ip_mac_cmd
,
3680 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3682 "evpn system primary IP\n"
3685 MAC_STR MAC_STR MAC_STR
)
3687 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3688 struct bgp
*bgp_evpn
= NULL
;
3690 if (EVPN_ENABLED(bgp_vrf
)) {
3692 "This command is supported under L3VNI BGP EVPN VRF\n");
3693 return CMD_WARNING_CONFIG_FAILED
;
3695 bgp_evpn
= bgp_get_evpn();
3698 /* pip is already enabled */
3699 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3702 bgp_vrf
->evpn_info
->advertise_pip
= true;
3703 if (ip
.s_addr
!= INADDR_ANY
) {
3704 /* Already configured with same IP */
3705 if (IPV4_ADDR_SAME(&ip
,
3706 &bgp_vrf
->evpn_info
->pip_ip_static
))
3709 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3710 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3712 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3714 /* default instance router-id assignemt */
3716 bgp_vrf
->evpn_info
->pip_ip
=
3717 bgp_evpn
->router_id
;
3720 if (!is_zero_mac(&mac
->eth_addr
)) {
3721 /* Already configured with same MAC */
3722 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3723 &mac
->eth_addr
, ETH_ALEN
) == 0)
3726 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3727 &mac
->eth_addr
, ETH_ALEN
);
3728 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3729 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3732 /* Copy zebra sys mac */
3733 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3734 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3735 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3740 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3742 /* Disable PIP feature */
3743 bgp_vrf
->evpn_info
->advertise_pip
= false;
3744 /* copy anycast mac */
3745 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3746 &bgp_vrf
->rmac
, ETH_ALEN
);
3748 /* remove MAC-IP option retain PIP knob. */
3749 if ((ip
.s_addr
!= INADDR_ANY
) &&
3750 !IPV4_ADDR_SAME(&ip
,
3751 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3753 "%% BGP EVPN PIP IP does not match\n");
3754 return CMD_WARNING_CONFIG_FAILED
;
3757 if (!is_zero_mac(&mac
->eth_addr
) &&
3758 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3759 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3761 "%% BGP EVPN PIP MAC does not match\n");
3762 return CMD_WARNING_CONFIG_FAILED
;
3764 /* pip_rmac can carry vrr_rmac reset only if it matches
3765 * with static value.
3767 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3768 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3770 /* Copy zebra sys mac */
3772 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3773 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3774 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3777 /* copy anycast mac */
3778 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3779 &bgp_vrf
->rmac
, ETH_ALEN
);
3783 /* reset user configured sys MAC */
3784 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3785 /* reset user configured sys IP */
3786 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3787 /* Assign default PIP IP (bgp instance router-id) */
3789 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3791 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3794 if (is_evpn_enabled()) {
3795 struct listnode
*node
= NULL
;
3796 struct bgpevpn
*vpn
= NULL
;
3798 update_advertise_vrf_routes(bgp_vrf
);
3800 /* Update (svi) type-2 routes */
3801 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3802 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3804 update_routes_for_vni(bgp_evpn
, vpn
);
3812 * Display VNI information - for all or a specific VNI
3814 DEFUN(show_bgp_l2vpn_evpn_vni
,
3815 show_bgp_l2vpn_evpn_vni_cmd
,
3816 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3825 struct bgp
*bgp_evpn
;
3829 json_object
*json
= NULL
;
3830 uint32_t num_l2vnis
= 0;
3831 uint32_t num_l3vnis
= 0;
3832 uint32_t num_vnis
= 0;
3833 struct listnode
*node
= NULL
;
3834 struct bgp
*bgp_temp
= NULL
;
3836 uj
= use_json(argc
, argv
);
3838 bgp_evpn
= bgp_get_evpn();
3842 if (!argv_find(argv
, argc
, "evpn", &idx
))
3846 json
= json_object_new_object();
3848 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3850 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3852 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3853 if (bgp_temp
->l3vni
)
3856 num_vnis
= num_l2vnis
+ num_l3vnis
;
3858 json_object_string_add(json
, "advertiseGatewayMacip",
3859 bgp_evpn
->advertise_gw_macip
3862 json_object_string_add(json
, "advertiseSviMacip",
3863 bgp_evpn
->evpn_info
->advertise_svi_macip
3864 ? "Enabled" : "Disabled");
3865 json_object_string_add(json
, "advertiseAllVnis",
3866 is_evpn_enabled() ? "Enabled"
3868 json_object_string_add(
3870 bgp_evpn
->vxlan_flood_ctrl
3871 == VXLAN_FLOOD_HEAD_END_REPL
3872 ? "Head-end replication"
3874 json_object_int_add(json
, "numVnis", num_vnis
);
3875 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3876 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3878 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3879 bgp_evpn
->advertise_gw_macip
? "Enabled"
3881 vty_out(vty
, "Advertise SVI Macip: %s\n",
3882 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3884 vty_out(vty
, "Advertise All VNI flag: %s\n",
3885 is_evpn_enabled() ? "Enabled" : "Disabled");
3886 vty_out(vty
, "BUM flooding: %s\n",
3887 bgp_evpn
->vxlan_flood_ctrl
3888 == VXLAN_FLOOD_HEAD_END_REPL
3889 ? "Head-end replication"
3891 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3892 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3894 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3898 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3901 /* Display specific VNI */
3902 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3903 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3907 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3908 json
, JSON_C_TO_STRING_PRETTY
));
3909 json_object_free(json
);
3916 DEFUN(show_bgp_l2vpn_evpn_es
,
3917 show_bgp_l2vpn_evpn_es_cmd
,
3918 "show bgp l2vpn evpn es [ESI] [json]",
3923 "ethernet-Segment\n"
3924 "Ethernet-Segment Identifier\n"
3930 json_object
*json
= NULL
;
3931 struct bgp
*bgp
= NULL
;
3933 memset(&esi
, 0, sizeof(esi
));
3934 uj
= use_json(argc
, argv
);
3936 bgp
= bgp_get_evpn();
3940 if (!argv_find(argv
, argc
, "evpn", &idx
))
3943 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3944 (!uj
&& argc
== (idx
+ 1) + 1)) {
3947 evpn_show_all_es(vty
, bgp
, json
);
3950 /* show a specific ES */
3952 /* get the ESI - ESI-ID is at argv[5] */
3953 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3954 vty_out(vty
, "%% Malformed ESI\n");
3957 evpn_show_es(vty
, bgp
, &esi
, json
);
3961 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3962 json
, JSON_C_TO_STRING_PRETTY
));
3963 json_object_free(json
);
3970 * Display EVPN neighbor summary.
3972 DEFUN(show_bgp_l2vpn_evpn_summary
,
3973 show_bgp_l2vpn_evpn_summary_cmd
,
3974 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3981 "Summary of BGP neighbor status\n"
3982 "Show only sessions not in Established state\n"
3986 bool uj
= use_json(argc
, argv
);
3988 bool show_failed
= false;
3990 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3991 vrf
= argv
[++idx_vrf
]->arg
;
3992 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3994 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3999 * Display global EVPN routing table.
4001 DEFUN(show_bgp_l2vpn_evpn_route
,
4002 show_bgp_l2vpn_evpn_route_cmd
,
4003 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
4008 "EVPN route information\n"
4009 "Display Detailed Information\n"
4010 "Specify Route type\n"
4011 "MAC-IP (Type-2) route\n"
4012 "Multicast (Type-3) route\n"
4013 "Ethernet Segment (type-4) route \n"
4014 "Prefix (type-5 )route\n"
4022 json_object
*json
= NULL
;
4024 uj
= use_json(argc
, argv
);
4026 bgp
= bgp_get_evpn();
4031 json
= json_object_new_object();
4034 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4035 /* Specific type is requested */
4036 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4037 type
= BGP_EVPN_MAC_IP_ROUTE
;
4038 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4039 type
= BGP_EVPN_IMET_ROUTE
;
4040 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
4041 type
= BGP_EVPN_ES_ROUTE
;
4042 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4043 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4048 if (argv_find(argv
, argc
, "detail", &detail
))
4051 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4054 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4055 json
, JSON_C_TO_STRING_PRETTY
));
4056 json_object_free(json
);
4062 * Display global EVPN routing table for specific RD.
4064 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4065 show_bgp_l2vpn_evpn_route_rd_cmd
,
4066 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
4071 "EVPN route information\n"
4072 "Route Distinguisher\n"
4073 "ASN:XX or A.B.C.D:XX\n"
4074 "Specify Route type\n"
4075 "MAC-IP (Type-2) route\n"
4076 "Multicast (Type-3) route\n"
4077 "Ethernet Segment route\n"
4083 struct prefix_rd prd
;
4088 json_object
*json
= NULL
;
4090 bgp
= bgp_get_evpn();
4094 /* check if we need json output */
4095 uj
= use_json(argc
, argv
);
4097 json
= json_object_new_object();
4100 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4101 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4104 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4110 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4111 /* Specific type is requested */
4112 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4113 type
= BGP_EVPN_MAC_IP_ROUTE
;
4114 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4115 type
= BGP_EVPN_IMET_ROUTE
;
4116 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
4117 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4122 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4125 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4126 json
, JSON_C_TO_STRING_PRETTY
));
4127 json_object_free(json
);
4134 * Display global EVPN routing table for specific RD and MACIP.
4136 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4137 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4138 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4143 "EVPN route information\n"
4144 "Route Distinguisher\n"
4145 "ASN:XX or A.B.C.D:XX\n"
4147 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4149 "IP address (IPv4 or IPv6)\n"
4154 struct prefix_rd prd
;
4161 json_object
*json
= NULL
;
4163 memset(&mac
, 0, sizeof(struct ethaddr
));
4164 memset(&ip
, 0, sizeof(struct ipaddr
));
4166 bgp
= bgp_get_evpn();
4170 /* check if we need json output */
4171 uj
= use_json(argc
, argv
);
4173 json
= json_object_new_object();
4176 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4177 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4179 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4185 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4186 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4187 vty_out(vty
, "%% Malformed MAC address\n");
4192 /* get the ip if specified */
4193 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4194 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4195 vty_out(vty
, "%% Malformed IP address\n");
4200 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4203 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4204 json
, JSON_C_TO_STRING_PRETTY
));
4205 json_object_free(json
);
4211 /* Display per ESI routing table */
4212 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4213 show_bgp_l2vpn_evpn_route_esi_cmd
,
4214 "show bgp l2vpn evpn route esi ESI [json]",
4219 "EVPN route information\n"
4220 "Ethernet Segment Identifier\n"
4226 struct bgp
*bgp
= NULL
;
4227 json_object
*json
= NULL
;
4229 memset(&esi
, 0, sizeof(esi
));
4230 bgp
= bgp_get_evpn();
4234 uj
= use_json(argc
, argv
);
4236 json
= json_object_new_object();
4238 /* get the ESI - ESI-ID is at argv[6] */
4239 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4240 vty_out(vty
, "%% Malformed ESI\n");
4244 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4247 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4248 json
, JSON_C_TO_STRING_PRETTY
));
4249 json_object_free(json
);
4257 * Display per-VNI EVPN routing table.
4259 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4260 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4265 "EVPN route information\n"
4266 "VXLAN Network Identifier\n"
4268 "Specify Route type\n"
4269 "MAC-IP (Type-2) route\n"
4270 "Multicast (Type-3) route\n"
4272 "Remote VTEP IP address\n"
4277 struct in_addr vtep_ip
;
4281 json_object
*json
= NULL
;
4283 bgp
= bgp_get_evpn();
4287 /* check if we need json output */
4288 uj
= use_json(argc
, argv
);
4290 json
= json_object_new_object();
4292 if (!argv_find(argv
, argc
, "evpn", &idx
))
4297 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4299 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4300 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4301 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4302 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4303 type
= BGP_EVPN_MAC_IP_ROUTE
;
4304 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4305 type
= BGP_EVPN_IMET_ROUTE
;
4308 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4309 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4310 vty_out(vty
, "%% Malformed VTEP IP address\n");
4317 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4320 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4321 json
, JSON_C_TO_STRING_PRETTY
));
4322 json_object_free(json
);
4329 * Display per-VNI EVPN routing table for specific MACIP.
4331 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4332 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4333 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4338 "EVPN route information\n"
4339 "VXLAN Network Identifier\n"
4342 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4344 "IP address (IPv4 or IPv6)\n"
4353 json_object
*json
= NULL
;
4355 bgp
= bgp_get_evpn();
4359 /* check if we need json output */
4360 uj
= use_json(argc
, argv
);
4362 json
= json_object_new_object();
4364 if (!argv_find(argv
, argc
, "evpn", &idx
))
4368 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4371 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4372 vty_out(vty
, "%% Malformed MAC address\n");
4377 memset(&ip
, 0, sizeof(ip
));
4378 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4380 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4381 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4382 vty_out(vty
, "%% Malformed IP address\n");
4387 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4390 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4391 json
, JSON_C_TO_STRING_PRETTY
));
4392 json_object_free(json
);
4399 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4401 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4402 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4403 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4408 "EVPN route information\n"
4409 "VXLAN Network Identifier\n"
4411 "Multicast (Type-3) route\n"
4412 "Originating Router IP address\n"
4418 struct in_addr orig_ip
;
4421 json_object
*json
= NULL
;
4423 bgp
= bgp_get_evpn();
4427 /* check if we need json output */
4428 uj
= use_json(argc
, argv
);
4430 json
= json_object_new_object();
4432 if (!argv_find(argv
, argc
, "evpn", &idx
))
4436 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4439 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4441 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4445 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4448 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4449 json
, JSON_C_TO_STRING_PRETTY
));
4450 json_object_free(json
);
4457 * Display per-VNI EVPN routing table - for all VNIs.
4459 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4460 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4461 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4466 "EVPN route information\n"
4467 "VXLAN Network Identifier\n"
4469 "Print Detailed Output\n"
4471 "Remote VTEP IP address\n"
4475 struct in_addr vtep_ip
;
4478 json_object
*json
= NULL
;
4479 /* Detail Adjust. Adjust indexes according to detail option */
4482 bgp
= bgp_get_evpn();
4486 /* check if we need json output */
4487 uj
= use_json(argc
, argv
);
4489 json
= json_object_new_object();
4491 if (!argv_find(argv
, argc
, "evpn", &idx
))
4494 if (argv_find(argv
, argc
, "detail", &da
))
4497 /* vtep-ip position depends on detail option */
4499 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4501 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4502 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4503 vty_out(vty
, "%% Malformed VTEP IP address\n");
4508 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4511 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4512 json
, JSON_C_TO_STRING_PRETTY
));
4513 json_object_free(json
);
4520 * Display EVPN import route-target hash table
4522 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4523 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4524 "show bgp l2vpn evpn vrf-import-rt [json]",
4529 "Show vrf import route target\n"
4533 struct bgp
*bgp_evpn
= NULL
;
4534 json_object
*json
= NULL
;
4536 bgp_evpn
= bgp_get_evpn();
4540 uj
= use_json(argc
, argv
);
4542 json
= json_object_new_object();
4544 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4547 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4548 json
, JSON_C_TO_STRING_PRETTY
));
4549 json_object_free(json
);
4556 * Display EVPN import route-target hash table
4558 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4559 show_bgp_l2vpn_evpn_import_rt_cmd
,
4560 "show bgp l2vpn evpn import-rt [json]",
4565 "Show import route target\n"
4570 json_object
*json
= NULL
;
4572 bgp
= bgp_get_evpn();
4576 uj
= use_json(argc
, argv
);
4578 json
= json_object_new_object();
4580 evpn_show_import_rts(vty
, bgp
, json
);
4583 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4584 json
, JSON_C_TO_STRING_PRETTY
));
4585 json_object_free(json
);
4591 DEFUN(test_adv_evpn_type4_route
,
4592 test_adv_evpn_type4_route_cmd
,
4594 "Advertise EVPN ES route\n"
4595 "Ethernet-segment\n"
4596 "Ethernet-Segment Identifier\n")
4601 struct ipaddr vtep_ip
;
4603 bgp
= bgp_get_evpn();
4605 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4609 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4610 vty_out(vty
, "%%Malformed ESI\n");
4614 vtep_ip
.ipa_type
= IPADDR_V4
;
4615 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4617 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4619 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4625 DEFUN(test_withdraw_evpn_type4_route
,
4626 test_withdraw_evpn_type4_route_cmd
,
4628 "Advertise EVPN ES route\n"
4629 "Ethernet-segment\n"
4630 "Ethernet-Segment Identifier\n")
4635 struct ipaddr vtep_ip
;
4637 bgp
= bgp_get_evpn();
4639 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4643 if (!bgp
->peer_self
) {
4644 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4648 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4649 vty_out(vty
, "%%Malformed ESI\n");
4653 vtep_ip
.ipa_type
= IPADDR_V4
;
4654 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4655 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4657 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4663 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4664 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4668 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4669 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4670 "Summary of BGP neighbor status\n" JSON_STR
)
4672 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4673 "show bgp evpn route [detail] [type <macip|multicast>]",
4674 SHOW_STR BGP_STR EVPN_HELP_STR
4675 "EVPN route information\n"
4676 "Display Detailed Information\n"
4677 "Specify Route type\n"
4678 "MAC-IP (Type-2) route\n"
4679 "Multicast (Type-3) route\n")
4682 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4683 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4684 SHOW_STR BGP_STR EVPN_HELP_STR
4685 "EVPN route information\n"
4686 "Route Distinguisher\n"
4687 "ASN:XX or A.B.C.D:XX\n"
4688 "Specify Route type\n"
4689 "MAC-IP (Type-2) route\n"
4690 "Multicast (Type-3) route\n")
4693 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4694 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4695 SHOW_STR BGP_STR EVPN_HELP_STR
4696 "EVPN route information\n"
4697 "Route Distinguisher\n"
4698 "ASN:XX or A.B.C.D:XX\n"
4700 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4702 "IP address (IPv4 or IPv6)\n")
4705 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4706 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4707 SHOW_STR BGP_STR EVPN_HELP_STR
4708 "EVPN route information\n"
4709 "VXLAN Network Identifier\n"
4711 "Specify Route type\n"
4712 "MAC-IP (Type-2) route\n"
4713 "Multicast (Type-3) route\n"
4715 "Remote VTEP IP address\n")
4717 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4718 show_bgp_evpn_route_vni_macip_cmd
,
4719 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4720 SHOW_STR BGP_STR EVPN_HELP_STR
4721 "EVPN route information\n"
4722 "VXLAN Network Identifier\n"
4725 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4727 "IP address (IPv4 or IPv6)\n")
4729 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4730 show_bgp_evpn_route_vni_multicast_cmd
,
4731 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4732 SHOW_STR BGP_STR EVPN_HELP_STR
4733 "EVPN route information\n"
4734 "VXLAN Network Identifier\n"
4736 "Multicast (Type-3) route\n"
4737 "Originating Router IP address\n")
4739 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4740 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4741 SHOW_STR BGP_STR EVPN_HELP_STR
4742 "EVPN route information\n"
4743 "VXLAN Network Identifier\n"
4745 "Print Detailed Output\n"
4747 "Remote VTEP IP address\n")
4749 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4750 "show bgp evpn import-rt",
4751 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4753 DEFUN_NOSH (bgp_evpn_vni
,
4755 "vni " CMD_VNI_RANGE
,
4756 "VXLAN Network Identifier\n"
4760 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4761 struct bgpevpn
*vpn
;
4766 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4768 /* Create VNI, or mark as configured. */
4769 vpn
= evpn_create_update_vni(bgp
, vni
);
4771 vty_out(vty
, "%% Failed to create VNI \n");
4775 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4779 DEFUN (no_bgp_evpn_vni
,
4780 no_bgp_evpn_vni_cmd
,
4781 "no vni " CMD_VNI_RANGE
,
4783 "VXLAN Network Identifier\n"
4787 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4788 struct bgpevpn
*vpn
;
4793 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4795 /* Check if we should disallow. */
4796 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4798 vty_out(vty
, "%% Specified VNI does not exist\n");
4801 if (!is_vni_configured(vpn
)) {
4802 vty_out(vty
, "%% Specified VNI is not configured\n");
4806 evpn_delete_vni(bgp
, vpn
);
4810 DEFUN_NOSH (exit_vni
,
4813 "Exit from VNI mode\n")
4815 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4816 vty
->node
= BGP_EVPN_NODE
;
4820 DEFUN (bgp_evpn_vrf_rd
,
4821 bgp_evpn_vrf_rd_cmd
,
4822 "rd ASN:NN_OR_IP-ADDRESS:NN",
4823 "Route Distinguisher\n"
4824 "ASN:XX or A.B.C.D:XX\n")
4827 struct prefix_rd prd
;
4828 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4833 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4835 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4839 /* If same as existing value, there is nothing more to do. */
4840 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4843 /* Configure or update the RD. */
4844 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4848 DEFUN (no_bgp_evpn_vrf_rd
,
4849 no_bgp_evpn_vrf_rd_cmd
,
4850 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4852 "Route Distinguisher\n"
4853 "ASN:XX or A.B.C.D:XX\n")
4856 struct prefix_rd prd
;
4857 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4862 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4864 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4868 /* Check if we should disallow. */
4869 if (!is_vrf_rd_configured(bgp_vrf
)) {
4870 vty_out(vty
, "%% RD is not configured for this VRF\n");
4874 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4876 "%% RD specified does not match configuration for this VRF\n");
4880 evpn_unconfigure_vrf_rd(bgp_vrf
);
4884 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4885 no_bgp_evpn_vrf_rd_without_val_cmd
,
4888 "Route Distinguisher\n")
4890 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4895 /* Check if we should disallow. */
4896 if (!is_vrf_rd_configured(bgp_vrf
)) {
4897 vty_out(vty
, "%% RD is not configured for this VRF\n");
4901 evpn_unconfigure_vrf_rd(bgp_vrf
);
4905 DEFUN (bgp_evpn_vni_rd
,
4906 bgp_evpn_vni_rd_cmd
,
4907 "rd ASN:NN_OR_IP-ADDRESS:NN",
4908 "Route Distinguisher\n"
4909 "ASN:XX or A.B.C.D:XX\n")
4911 struct prefix_rd prd
;
4912 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4913 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4919 if (!EVPN_ENABLED(bgp
)) {
4921 "This command is only supported under EVPN VRF\n");
4925 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4927 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4931 /* If same as existing value, there is nothing more to do. */
4932 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4935 /* Configure or update the RD. */
4936 evpn_configure_rd(bgp
, vpn
, &prd
);
4940 DEFUN (no_bgp_evpn_vni_rd
,
4941 no_bgp_evpn_vni_rd_cmd
,
4942 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4944 "Route Distinguisher\n"
4945 "ASN:XX or A.B.C.D:XX\n")
4947 struct prefix_rd prd
;
4948 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4949 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4955 if (!EVPN_ENABLED(bgp
)) {
4957 "This command is only supported under EVPN VRF\n");
4961 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4963 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4967 /* Check if we should disallow. */
4968 if (!is_rd_configured(vpn
)) {
4969 vty_out(vty
, "%% RD is not configured for this VNI\n");
4973 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4975 "%% RD specified does not match configuration for this VNI\n");
4979 evpn_unconfigure_rd(bgp
, vpn
);
4983 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4984 no_bgp_evpn_vni_rd_without_val_cmd
,
4987 "Route Distinguisher\n")
4989 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4990 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4995 if (!EVPN_ENABLED(bgp
)) {
4997 "This command is only supported under EVPN VRF\n");
5001 /* Check if we should disallow. */
5002 if (!is_rd_configured(vpn
)) {
5003 vty_out(vty
, "%% RD is not configured for this VNI\n");
5007 evpn_unconfigure_rd(bgp
, vpn
);
5012 * Loop over all extended-communities in the route-target list rtl and
5013 * return 1 if we find ecomtarget
5015 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5016 struct ecommunity
*ecomtarget
)
5018 struct listnode
*node
, *nnode
;
5019 struct ecommunity
*ecom
;
5021 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5022 if (ecommunity_match(ecom
, ecomtarget
))
5029 /* display L3VNI related info for a VRF instance */
5030 DEFUN (show_bgp_vrf_l3vni_info
,
5031 show_bgp_vrf_l3vni_info_cmd
,
5032 "show bgp vrf VRFNAME vni [json]",
5040 char buf
[ETHER_ADDR_STRLEN
];
5041 char buf1
[INET6_ADDRSTRLEN
];
5043 const char *name
= NULL
;
5044 struct bgp
*bgp
= NULL
;
5045 struct listnode
*node
= NULL
;
5046 struct bgpevpn
*vpn
= NULL
;
5047 struct ecommunity
*ecom
= NULL
;
5048 json_object
*json
= NULL
;
5049 json_object
*json_vnis
= NULL
;
5050 json_object
*json_export_rts
= NULL
;
5051 json_object
*json_import_rts
= NULL
;
5052 bool uj
= use_json(argc
, argv
);
5055 json
= json_object_new_object();
5056 json_vnis
= json_object_new_array();
5057 json_export_rts
= json_object_new_array();
5058 json_import_rts
= json_object_new_array();
5061 name
= argv
[idx_vrf
]->arg
;
5062 bgp
= bgp_lookup_by_name(name
);
5065 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5067 json_object_string_add(json
, "warning",
5068 "BGP instance not found");
5069 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5070 json_object_free(json
);
5076 vty_out(vty
, "BGP VRF: %s\n", name
);
5077 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
5078 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5079 vty_out(vty
, " Rmac: %s\n",
5080 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5081 vty_out(vty
, " VNI Filter: %s\n",
5082 CHECK_FLAG(bgp
->vrf_flags
,
5083 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5084 ? "prefix-routes-only"
5086 vty_out(vty
, " L2-VNI List:\n");
5088 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5089 vty_out(vty
, "%u ", vpn
->vni
);
5091 vty_out(vty
, " Export-RTs:\n");
5093 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5094 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5096 vty_out(vty
, " Import-RTs:\n");
5098 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5099 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5101 vty_out(vty
, " RD: %s\n",
5102 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5104 json_object_string_add(json
, "vrf", name
);
5105 json_object_string_add(json
, "local-ip",
5106 inet_ntoa(bgp
->originator_ip
));
5107 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5108 json_object_string_add(
5110 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5111 json_object_string_add(
5113 CHECK_FLAG(bgp
->vrf_flags
,
5114 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5115 ? "prefix-routes-only"
5117 /* list of l2vnis */
5118 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5119 json_object_array_add(json_vnis
,
5120 json_object_new_int(vpn
->vni
));
5121 json_object_object_add(json
, "l2vnis", json_vnis
);
5124 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5125 json_object_array_add(
5127 json_object_new_string(ecommunity_str(ecom
)));
5128 json_object_object_add(json
, "export-rts", json_export_rts
);
5131 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5132 json_object_array_add(
5134 json_object_new_string(ecommunity_str(ecom
)));
5135 json_object_object_add(json
, "import-rts", json_import_rts
);
5136 json_object_string_add(
5138 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5142 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5143 json
, JSON_C_TO_STRING_PRETTY
));
5144 json_object_free(json
);
5149 /* import/export rt for l3vni-vrf */
5150 DEFUN (bgp_evpn_vrf_rt
,
5151 bgp_evpn_vrf_rt_cmd
,
5152 "route-target <both|import|export> RT",
5154 "import and export\n"
5157 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5160 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5161 struct ecommunity
*ecomadd
= NULL
;
5166 if (!strcmp(argv
[1]->arg
, "import"))
5167 rt_type
= RT_TYPE_IMPORT
;
5168 else if (!strcmp(argv
[1]->arg
, "export"))
5169 rt_type
= RT_TYPE_EXPORT
;
5170 else if (!strcmp(argv
[1]->arg
, "both"))
5171 rt_type
= RT_TYPE_BOTH
;
5173 vty_out(vty
, "%% Invalid Route Target type\n");
5177 /* Add/update the import route-target */
5178 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5179 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5180 ECOMMUNITY_ROUTE_TARGET
, 0);
5182 vty_out(vty
, "%% Malformed Route Target list\n");
5185 ecommunity_str(ecomadd
);
5187 /* Do nothing if we already have this import route-target */
5188 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5189 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5192 /* Add/update the export route-target */
5193 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5194 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5195 ECOMMUNITY_ROUTE_TARGET
, 0);
5197 vty_out(vty
, "%% Malformed Route Target list\n");
5200 ecommunity_str(ecomadd
);
5202 /* Do nothing if we already have this export route-target */
5203 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5204 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5210 DEFUN (no_bgp_evpn_vrf_rt
,
5211 no_bgp_evpn_vrf_rt_cmd
,
5212 "no route-target <both|import|export> RT",
5215 "import and export\n"
5218 "ASN:XX or A.B.C.D:XX\n")
5220 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5221 int rt_type
, found_ecomdel
;
5222 struct ecommunity
*ecomdel
= NULL
;
5227 if (!strcmp(argv
[2]->arg
, "import"))
5228 rt_type
= RT_TYPE_IMPORT
;
5229 else if (!strcmp(argv
[2]->arg
, "export"))
5230 rt_type
= RT_TYPE_EXPORT
;
5231 else if (!strcmp(argv
[2]->arg
, "both"))
5232 rt_type
= RT_TYPE_BOTH
;
5234 vty_out(vty
, "%% Invalid Route Target type\n");
5238 if (rt_type
== RT_TYPE_IMPORT
) {
5239 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5241 "%% Import RT is not configured for this VRF\n");
5244 } else if (rt_type
== RT_TYPE_EXPORT
) {
5245 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5247 "%% Export RT is not configured for this VRF\n");
5250 } else if (rt_type
== RT_TYPE_BOTH
) {
5251 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5252 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5254 "%% Import/Export RT is not configured for this VRF\n");
5259 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5261 vty_out(vty
, "%% Malformed Route Target list\n");
5264 ecommunity_str(ecomdel
);
5266 if (rt_type
== RT_TYPE_IMPORT
) {
5267 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5270 "%% RT specified does not match configuration for this VRF\n");
5273 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5274 } else if (rt_type
== RT_TYPE_EXPORT
) {
5275 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5278 "%% RT specified does not match configuration for this VRF\n");
5281 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5282 } else if (rt_type
== RT_TYPE_BOTH
) {
5285 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5287 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5291 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5293 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5297 if (!found_ecomdel
) {
5299 "%% RT specified does not match configuration for this VRF\n");
5307 DEFUN (bgp_evpn_vni_rt
,
5308 bgp_evpn_vni_rt_cmd
,
5309 "route-target <both|import|export> RT",
5311 "import and export\n"
5314 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5316 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5317 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5319 struct ecommunity
*ecomadd
= NULL
;
5324 if (!EVPN_ENABLED(bgp
)) {
5326 "This command is only supported under EVPN VRF\n");
5330 if (!strcmp(argv
[1]->text
, "import"))
5331 rt_type
= RT_TYPE_IMPORT
;
5332 else if (!strcmp(argv
[1]->text
, "export"))
5333 rt_type
= RT_TYPE_EXPORT
;
5334 else if (!strcmp(argv
[1]->text
, "both"))
5335 rt_type
= RT_TYPE_BOTH
;
5337 vty_out(vty
, "%% Invalid Route Target type\n");
5341 /* Add/update the import route-target */
5342 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5343 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5344 ECOMMUNITY_ROUTE_TARGET
, 0);
5346 vty_out(vty
, "%% Malformed Route Target list\n");
5349 ecommunity_str(ecomadd
);
5351 /* Do nothing if we already have this import route-target */
5352 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5353 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5356 /* Add/update the export route-target */
5357 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5358 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5359 ECOMMUNITY_ROUTE_TARGET
, 0);
5361 vty_out(vty
, "%% Malformed Route Target list\n");
5364 ecommunity_str(ecomadd
);
5366 /* Do nothing if we already have this export route-target */
5367 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5368 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5374 DEFUN (no_bgp_evpn_vni_rt
,
5375 no_bgp_evpn_vni_rt_cmd
,
5376 "no route-target <both|import|export> RT",
5379 "import and export\n"
5382 "ASN:XX or A.B.C.D:XX\n")
5384 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5385 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5386 int rt_type
, found_ecomdel
;
5387 struct ecommunity
*ecomdel
= NULL
;
5392 if (!EVPN_ENABLED(bgp
)) {
5394 "This command is only supported under EVPN VRF\n");
5398 if (!strcmp(argv
[2]->text
, "import"))
5399 rt_type
= RT_TYPE_IMPORT
;
5400 else if (!strcmp(argv
[2]->text
, "export"))
5401 rt_type
= RT_TYPE_EXPORT
;
5402 else if (!strcmp(argv
[2]->text
, "both"))
5403 rt_type
= RT_TYPE_BOTH
;
5405 vty_out(vty
, "%% Invalid Route Target type\n");
5409 /* The user did "no route-target import", check to see if there are any
5410 * import route-targets configured. */
5411 if (rt_type
== RT_TYPE_IMPORT
) {
5412 if (!is_import_rt_configured(vpn
)) {
5414 "%% Import RT is not configured for this VNI\n");
5417 } else if (rt_type
== RT_TYPE_EXPORT
) {
5418 if (!is_export_rt_configured(vpn
)) {
5420 "%% Export RT is not configured for this VNI\n");
5423 } else if (rt_type
== RT_TYPE_BOTH
) {
5424 if (!is_import_rt_configured(vpn
)
5425 && !is_export_rt_configured(vpn
)) {
5427 "%% Import/Export RT is not configured for this VNI\n");
5432 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5434 vty_out(vty
, "%% Malformed Route Target list\n");
5437 ecommunity_str(ecomdel
);
5439 if (rt_type
== RT_TYPE_IMPORT
) {
5440 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5442 "%% RT specified does not match configuration for this VNI\n");
5445 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5446 } else if (rt_type
== RT_TYPE_EXPORT
) {
5447 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5449 "%% RT specified does not match configuration for this VNI\n");
5452 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5453 } else if (rt_type
== RT_TYPE_BOTH
) {
5456 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5457 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5461 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5462 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5466 if (!found_ecomdel
) {
5468 "%% RT specified does not match configuration for this VNI\n");
5476 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5477 no_bgp_evpn_vni_rt_without_val_cmd
,
5478 "no route-target <import|export>",
5484 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5485 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5491 if (!EVPN_ENABLED(bgp
)) {
5493 "This command is only supported under EVPN VRF\n");
5497 if (!strcmp(argv
[2]->text
, "import")) {
5498 rt_type
= RT_TYPE_IMPORT
;
5499 } else if (!strcmp(argv
[2]->text
, "export")) {
5500 rt_type
= RT_TYPE_EXPORT
;
5502 vty_out(vty
, "%% Invalid Route Target type\n");
5506 /* Check if we should disallow. */
5507 if (rt_type
== RT_TYPE_IMPORT
) {
5508 if (!is_import_rt_configured(vpn
)) {
5510 "%% Import RT is not configured for this VNI\n");
5514 if (!is_export_rt_configured(vpn
)) {
5516 "%% Export RT is not configured for this VNI\n");
5521 /* Unconfigure the RT. */
5522 if (rt_type
== RT_TYPE_IMPORT
)
5523 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5525 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5529 static int vni_cmp(const void **a
, const void **b
)
5531 const struct bgpevpn
*first
= *a
;
5532 const struct bgpevpn
*secnd
= *b
;
5534 return secnd
->vni
- first
->vni
;
5538 * Output EVPN configuration information.
5540 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5543 char buf1
[RD_ADDRSTRLEN
];
5544 char buf2
[INET6_ADDRSTRLEN
];
5547 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5548 struct listnode
*ln
;
5549 struct bgpevpn
*data
;
5551 list_sort(vnilist
, vni_cmp
);
5552 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5553 write_vni_config(vty
, data
);
5555 list_delete(&vnilist
);
5558 if (bgp
->advertise_all_vni
)
5559 vty_out(vty
, " advertise-all-vni\n");
5561 if (bgp
->advertise_autort_rfc8365
)
5562 vty_out(vty
, " autort rfc8365-compatible\n");
5564 if (bgp
->advertise_gw_macip
)
5565 vty_out(vty
, " advertise-default-gw\n");
5567 if (bgp
->evpn_info
->advertise_svi_macip
)
5568 vty_out(vty
, " advertise-svi-ip\n");
5570 if (!bgp
->evpn_info
->dup_addr_detect
)
5571 vty_out(vty
, " no dup-addr-detection\n");
5573 if (bgp
->evpn_info
->dad_max_moves
!=
5574 EVPN_DAD_DEFAULT_MAX_MOVES
||
5575 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5576 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5577 bgp
->evpn_info
->dad_max_moves
,
5578 bgp
->evpn_info
->dad_time
);
5580 if (bgp
->evpn_info
->dad_freeze
) {
5581 if (bgp
->evpn_info
->dad_freeze_time
)
5583 " dup-addr-detection freeze %u\n",
5584 bgp
->evpn_info
->dad_freeze_time
);
5587 " dup-addr-detection freeze permanent\n");
5590 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5591 vty_out(vty
, " flooding disable\n");
5593 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5594 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5595 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5596 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5597 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5599 vty_out(vty
, " advertise ipv4 unicast\n");
5602 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5603 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5604 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5605 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5606 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5608 vty_out(vty
, " advertise ipv6 unicast\n");
5611 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5612 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5613 vty_out(vty
, " default-originate ipv4\n");
5615 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5616 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5617 vty_out(vty
, " default-originate ipv6\n");
5619 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5620 if (!bgp
->evpn_info
->advertise_pip
)
5621 vty_out(vty
, " no advertise-pip\n");
5622 if (bgp
->evpn_info
->advertise_pip
) {
5623 if (bgp
->evpn_info
->pip_ip_static
.s_addr
!= INADDR_ANY
)
5624 vty_out(vty
, " advertise-pip ip %s",
5626 &bgp
->evpn_info
->pip_ip_static
,
5627 buf2
, INET_ADDRSTRLEN
));
5628 if (!is_zero_mac(&(bgp
->evpn_info
->pip_rmac_static
))) {
5629 char buf
[ETHER_ADDR_STRLEN
];
5631 vty_out(vty
, " mac %s",
5632 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
5638 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5639 vty_out(vty
, " rd %s\n",
5640 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5642 /* import route-target */
5643 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5645 struct listnode
*node
, *nnode
;
5646 struct ecommunity
*ecom
;
5648 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5650 ecom_str
= ecommunity_ecom2str(
5651 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5652 vty_out(vty
, " route-target import %s\n", ecom_str
);
5653 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5657 /* export route-target */
5658 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5660 struct listnode
*node
, *nnode
;
5661 struct ecommunity
*ecom
;
5663 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5665 ecom_str
= ecommunity_ecom2str(
5666 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5667 vty_out(vty
, " route-target export %s\n", ecom_str
);
5668 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5673 void bgp_ethernetvpn_init(void)
5675 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5676 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5677 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5678 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5679 install_element(VIEW_NODE
,
5680 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5681 install_element(VIEW_NODE
,
5682 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5685 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5688 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5689 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5690 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5691 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5692 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5693 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5694 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5695 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5696 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5697 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5698 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5699 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5700 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5701 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5702 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5703 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5704 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5705 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5706 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5707 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5708 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5711 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5712 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5714 /* "show bgp l2vpn evpn" commands. */
5715 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5716 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5717 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5718 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5719 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5720 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5721 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5722 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5723 install_element(VIEW_NODE
,
5724 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5725 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5726 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5727 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5728 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5730 /* "show bgp evpn" commands. */
5731 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5732 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5733 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5734 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5735 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5736 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5737 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5738 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5739 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5740 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5741 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5742 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5744 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5745 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5746 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5747 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5748 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5749 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5750 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5751 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5752 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5753 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5754 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5755 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5756 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5757 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5758 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5759 install_element(BGP_EVPN_VNI_NODE
,
5760 &bgp_evpn_advertise_default_gw_vni_cmd
);
5761 install_element(BGP_EVPN_VNI_NODE
,
5762 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5763 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5764 install_element(BGP_EVPN_VNI_NODE
,
5765 &no_bgp_evpn_advertise_vni_subnet_cmd
);