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;
691 if (add_prefix_to_json
) {
692 json_object_string_add(json_prefix
, "prefix",
694 json_object_int_add(json_prefix
, "prefixLen",
696 json_object_object_add(json_prefix
, "paths",
698 json_object_object_add(json
, prefix_str
,
701 json_object_free(json_paths
);
702 json_object_free(json_prefix
);
710 json_object_int_add(json
, "numPrefix", prefix_cnt
);
711 json_object_int_add(json
, "numPaths", path_cnt
);
714 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
716 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
717 prefix_cnt
, path_cnt
);
721 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
722 struct vty
*vty
, struct in_addr vtep_ip
,
723 json_object
*json
, int detail
)
726 struct bgp_path_info
*pi
;
727 struct bgp_table
*table
;
728 int header
= detail
? 0 : 1;
730 uint32_t prefix_cnt
, path_cnt
;
732 prefix_cnt
= path_cnt
= 0;
734 table
= vpn
->route_table
;
735 tbl_ver
= table
->version
;
736 for (rn
= bgp_table_top(table
); rn
;
737 rn
= bgp_route_next(rn
)) {
738 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
739 int add_prefix_to_json
= 0;
740 char prefix_str
[BUFSIZ
];
741 json_object
*json_paths
= NULL
;
742 json_object
*json_prefix
= NULL
;
744 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
747 if (type
&& evp
->prefix
.route_type
!= type
)
751 json_prefix
= json_object_new_object();
753 pi
= bgp_node_get_bgp_path_info(rn
);
755 /* Overall header/legend displayed once. */
757 bgp_evpn_show_route_header(vty
, bgp
,
766 json_paths
= json_object_new_array();
768 /* For EVPN, the prefix is displayed for each path (to fit in
769 * with code that already exists).
771 for (; pi
; pi
= pi
->next
) {
772 json_object
*json_path
= NULL
;
775 && !IPV4_ADDR_SAME(&(vtep_ip
),
776 &(pi
->attr
->nexthop
)))
780 json_path
= json_object_new_array();
783 route_vty_out_detail(vty
, bgp
, rn
, pi
,
784 AFI_L2VPN
, SAFI_EVPN
,
787 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
791 json_object_array_add(json_paths
, json_path
);
794 add_prefix_to_json
= 1;
798 if (add_prefix_to_json
) {
799 json_object_string_add(json_prefix
, "prefix",
801 json_object_int_add(json_prefix
, "prefixLen",
803 json_object_object_add(json_prefix
, "paths",
805 json_object_object_add(json
, prefix_str
,
808 json_object_free(json_paths
);
809 json_object_free(json_prefix
);
817 json_object_int_add(json
, "numPrefix", prefix_cnt
);
818 json_object_int_add(json
, "numPaths", path_cnt
);
821 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
822 type
? "(of requested type) " : "");
824 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
825 prefix_cnt
, path_cnt
,
826 type
? " (of requested type)" : "");
831 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
833 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
834 struct vni_walk_ctx
*wctx
= arg
;
835 struct vty
*vty
= wctx
->vty
;
836 json_object
*json
= wctx
->json
;
837 json_object
*json_vni
= NULL
;
838 char vni_str
[VNI_STR_LEN
];
840 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
842 json_vni
= json_object_new_object();
843 json_object_int_add(json_vni
, "vni", vpn
->vni
);
845 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
848 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
852 json_object_object_add(json
, vni_str
, json_vni
);
855 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
858 json_object
*json_vni
= NULL
;
859 json_object
*json_import_rtl
= NULL
;
860 json_object
*json_export_rtl
= NULL
;
862 char buf2
[INET6_ADDRSTRLEN
];
865 struct listnode
*node
, *nnode
;
866 struct ecommunity
*ecom
;
872 json_vni
= json_object_new_object();
873 json_import_rtl
= json_object_new_array();
874 json_export_rtl
= json_object_new_array();
877 /* if an l3vni is present in bgp it is live */
882 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
883 json_object_string_add(json_vni
, "type", "L3");
884 json_object_string_add(json_vni
, "inKernel", "True");
885 json_object_string_add(json_vni
, "originatorIp",
886 inet_ntoa(bgp
->originator_ip
));
887 json_object_string_add(
889 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
891 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
892 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
895 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
896 ecom_str
= ecommunity_ecom2str(ecom
,
897 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
900 json_object_array_add(json_import_rtl
,
901 json_object_new_string(ecom_str
));
903 if (listcount(bgp
->vrf_import_rtl
) > 1)
904 sprintf(rt_buf
, "%s, ...", ecom_str
);
906 sprintf(rt_buf
, "%s", ecom_str
);
907 vty_out(vty
, " %-25s", rt_buf
);
910 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
912 /* If there are multiple import RTs we break here and show only
919 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
921 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
922 ecom_str
= ecommunity_ecom2str(ecom
,
923 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
926 json_object_array_add(json_export_rtl
,
927 json_object_new_string(ecom_str
));
929 if (listcount(bgp
->vrf_export_rtl
) > 1)
930 sprintf(rt_buf
, "%s, ...", ecom_str
);
932 sprintf(rt_buf
, "%s", ecom_str
);
933 vty_out(vty
, " %-25s", rt_buf
);
936 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
938 /* If there are multiple export RTs we break here and show only
945 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
948 char vni_str
[VNI_STR_LEN
];
950 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
951 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
952 json_object_object_add(json
, vni_str
, json_vni
);
958 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
960 char buf
[ESI_STR_LEN
];
961 char buf1
[RD_ADDRSTRLEN
];
962 char buf2
[INET6_ADDRSTRLEN
];
963 struct in_addr
*vtep
= NULL
;
964 struct vty
*vty
= args
[0];
965 json_object
*json
= args
[1];
966 json_object
*json_vteps
= NULL
;
967 struct listnode
*node
= NULL
;
968 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
971 json_vteps
= json_object_new_array();
972 json_object_string_add(json
, "esi",
973 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
974 json_object_string_add(json
, "type",
975 is_es_local(es
) ? "Local" : "Remote");
976 json_object_string_add(json
, "rd",
977 prefix_rd2str(&es
->prd
, buf1
,
979 json_object_string_add(
980 json
, "originatorIp",
981 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
983 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
984 json_object_array_add(json_vteps
,
985 json_object_new_string(
988 json_object_object_add(json
, "vteps", json_vteps
);
990 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
991 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
992 is_es_local(es
) ? "Local" : "Remote",
993 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
994 ipaddr2str(&es
->originator_ip
, buf2
,
996 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
1000 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1004 json_object
*json_vni
= NULL
;
1005 json_object
*json_import_rtl
= NULL
;
1006 json_object
*json_export_rtl
= NULL
;
1007 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1009 char buf2
[RD_ADDRSTRLEN
];
1012 struct listnode
*node
, *nnode
;
1013 struct ecommunity
*ecom
;
1019 json_vni
= json_object_new_object();
1020 json_import_rtl
= json_object_new_array();
1021 json_export_rtl
= json_object_new_array();
1025 if (is_vni_live(vpn
))
1029 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1030 json_object_string_add(json_vni
, "type", "L2");
1031 json_object_string_add(json_vni
, "inKernel",
1032 is_vni_live(vpn
) ? "True" : "False");
1033 json_object_string_add(json_vni
, "originatorIp",
1034 inet_ntoa(vpn
->originator_ip
));
1035 json_object_string_add(json_vni
, "originatorIp",
1036 inet_ntoa(vpn
->originator_ip
));
1037 json_object_string_add(
1039 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1041 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1042 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1045 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1046 ecom_str
= ecommunity_ecom2str(ecom
,
1047 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1050 json_object_array_add(json_import_rtl
,
1051 json_object_new_string(ecom_str
));
1053 if (listcount(vpn
->import_rtl
) > 1)
1054 sprintf(rt_buf
, "%s, ...", ecom_str
);
1056 sprintf(rt_buf
, "%s", ecom_str
);
1057 vty_out(vty
, " %-25s", rt_buf
);
1060 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1062 /* If there are multiple import RTs we break here and show only
1069 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1071 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1072 ecom_str
= ecommunity_ecom2str(ecom
,
1073 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1076 json_object_array_add(json_export_rtl
,
1077 json_object_new_string(ecom_str
));
1079 if (listcount(vpn
->export_rtl
) > 1)
1080 sprintf(rt_buf
, "%s, ...", ecom_str
);
1082 sprintf(rt_buf
, "%s", ecom_str
);
1083 vty_out(vty
, " %-25s", rt_buf
);
1086 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1088 /* If there are multiple export RTs we break here and show only
1095 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1098 char vni_str
[VNI_STR_LEN
];
1100 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1101 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1102 json_object_object_add(json
, vni_str
, json_vni
);
1108 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1109 enum bgp_show_type type
, void *output_arg
,
1110 int option
, bool use_json
)
1112 afi_t afi
= AFI_L2VPN
;
1114 struct bgp_table
*table
;
1115 struct bgp_node
*rn
;
1116 struct bgp_node
*rm
;
1117 struct bgp_path_info
*pi
;
1120 char rd_str
[RD_ADDRSTRLEN
];
1124 unsigned long output_count
= 0;
1125 unsigned long total_count
= 0;
1126 json_object
*json
= NULL
;
1127 json_object
*json_array
= NULL
;
1128 json_object
*json_prefix_info
= NULL
;
1130 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1132 bgp
= bgp_get_evpn();
1135 vty_out(vty
, "No BGP process is configured\n");
1137 vty_out(vty
, "{}\n");
1142 json
= json_object_new_object();
1144 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1145 rn
= bgp_route_next(rn
)) {
1147 json_object
*json_nroute
= NULL
;
1149 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1152 table
= bgp_node_get_bgp_table_info(rn
);
1157 tbl_ver
= table
->version
;
1159 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1160 pi
= bgp_node_get_bgp_path_info(rm
);
1165 for (; pi
; pi
= pi
->next
) {
1167 if (type
== bgp_show_type_neighbor
) {
1168 struct peer
*peer
= output_arg
;
1170 if (peer_cmp(peer
, pi
->peer
) != 0)
1173 if (type
== bgp_show_type_lcommunity_exact
) {
1174 struct lcommunity
*lcom
= output_arg
;
1176 if (!pi
->attr
->lcommunity
||
1178 pi
->attr
->lcommunity
, lcom
))
1181 if (type
== bgp_show_type_lcommunity
) {
1182 struct lcommunity
*lcom
= output_arg
;
1184 if (!pi
->attr
->lcommunity
||
1186 pi
->attr
->lcommunity
, lcom
))
1189 if (type
== bgp_show_type_community
) {
1190 struct community
*com
= output_arg
;
1192 if (!pi
->attr
->community
||
1194 pi
->attr
->community
, com
))
1197 if (type
== bgp_show_type_community_exact
) {
1198 struct community
*com
= output_arg
;
1200 if (!pi
->attr
->community
||
1202 pi
->attr
->community
, com
))
1207 json_object_int_add(
1208 json
, "bgpTableVersion",
1210 json_object_string_add(
1215 json_object_int_add(
1218 bgp
->default_local_pref
);
1219 json_object_int_add(
1223 if (option
== SHOW_DISPLAY_TAGS
)
1228 == SHOW_DISPLAY_OVERLAY
)
1232 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1240 json_object_new_object();
1241 bgp_evpn_show_route_rd_header(vty
, rn
,
1242 json_nroute
, rd_str
,
1246 if (use_json
&& !json_array
)
1247 json_array
= json_object_new_array();
1249 if (option
== SHOW_DISPLAY_TAGS
)
1250 route_vty_out_tag(vty
, &rm
->p
, pi
,
1251 no_display
, SAFI_EVPN
,
1253 else if (option
== SHOW_DISPLAY_OVERLAY
)
1254 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1258 route_vty_out(vty
, &rm
->p
, pi
,
1259 no_display
, SAFI_EVPN
,
1267 if (use_json
&& json_array
) {
1268 json_prefix_info
= json_object_new_object();
1270 json_object_string_add(json_prefix_info
,
1271 "prefix", bgp_evpn_route2str(
1272 (struct prefix_evpn
*)&rm
->p
, buf
,
1275 json_object_int_add(json_prefix_info
,
1276 "prefixLen", rm
->p
.prefixlen
);
1278 json_object_object_add(json_prefix_info
,
1279 "paths", json_array
);
1280 json_object_object_add(json_nroute
, buf
,
1286 if (use_json
&& json_nroute
)
1287 json_object_object_add(json
, rd_str
, json_nroute
);
1291 json_object_int_add(json
, "numPrefix", output_count
);
1292 json_object_int_add(json
, "totalPrefix", total_count
);
1293 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1294 json
, JSON_C_TO_STRING_PRETTY
));
1295 json_object_free(json
);
1297 if (output_count
== 0)
1298 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1302 "\nDisplayed %ld out of %ld total prefixes\n",
1303 output_count
, total_count
);
1308 DEFUN(show_ip_bgp_l2vpn_evpn
,
1309 show_ip_bgp_l2vpn_evpn_cmd
,
1310 "show [ip] bgp l2vpn evpn [json]",
1311 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1313 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1314 use_json(argc
, argv
));
1317 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1318 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1319 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1325 "Display information for a route distinguisher\n"
1326 "VPN Route Distinguisher\n" JSON_STR
)
1328 int idx_ext_community
= 0;
1330 struct prefix_rd prd
;
1332 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1334 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1336 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1339 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1340 use_json(argc
, argv
));
1343 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1344 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1345 "show [ip] bgp l2vpn evpn all tags",
1351 "Display information about all EVPN NLRIs\n"
1352 "Display BGP tags for prefixes\n")
1354 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1358 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1359 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1360 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1366 "Display information for a route distinguisher\n"
1367 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1369 int idx_ext_community
= 0;
1371 struct prefix_rd prd
;
1373 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1375 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1377 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1380 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1384 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1385 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1386 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1392 "Detailed information on TCP and BGP neighbor connections\n"
1393 "IPv4 Neighbor to display information about\n"
1394 "IPv6 Neighbor to display information about\n"
1395 "Neighbor on BGP configured interface\n"
1396 "Display routes learned from neighbor\n" JSON_STR
)
1400 char *peerstr
= NULL
;
1401 bool uj
= use_json(argc
, argv
);
1402 afi_t afi
= AFI_L2VPN
;
1403 safi_t safi
= SAFI_EVPN
;
1404 struct bgp
*bgp
= NULL
;
1406 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1409 vty_out(vty
, "No index\n");
1413 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1414 argv_find(argv
, argc
, "neighbors", &idx
);
1415 peerstr
= argv
[++idx
]->arg
;
1417 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1420 json_object
*json_no
= NULL
;
1421 json_no
= json_object_new_object();
1422 json_object_string_add(json_no
, "warning",
1423 "Malformed address");
1424 vty_out(vty
, "%s\n",
1425 json_object_to_json_string(json_no
));
1426 json_object_free(json_no
);
1428 vty_out(vty
, "Malformed address: %s\n",
1432 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1434 json_object
*json_no
= NULL
;
1435 json_no
= json_object_new_object();
1436 json_object_string_add(
1438 "No such neighbor or address family");
1439 vty_out(vty
, "%s\n",
1440 json_object_to_json_string(json_no
));
1441 json_object_free(json_no
);
1443 vty_out(vty
, "%% No such neighbor or address family\n");
1447 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1451 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1452 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1453 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1459 "Display information for a route distinguisher\n"
1460 "VPN Route Distinguisher\n"
1461 "Detailed information on TCP and BGP neighbor connections\n"
1462 "IPv4 Neighbor to display information about\n"
1463 "IPv6 Neighbor to display information about\n"
1464 "Neighbor on BGP configured interface\n"
1465 "Display routes learned from neighbor\n" JSON_STR
)
1467 int idx_ext_community
= 0;
1471 char *peerstr
= NULL
;
1472 struct prefix_rd prd
;
1473 bool uj
= use_json(argc
, argv
);
1474 afi_t afi
= AFI_L2VPN
;
1475 safi_t safi
= SAFI_EVPN
;
1476 struct bgp
*bgp
= NULL
;
1478 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1481 vty_out(vty
, "No index\n");
1485 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1486 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1489 json_object
*json_no
= NULL
;
1490 json_no
= json_object_new_object();
1491 json_object_string_add(json_no
, "warning",
1492 "Malformed Route Distinguisher");
1493 vty_out(vty
, "%s\n",
1494 json_object_to_json_string(json_no
));
1495 json_object_free(json_no
);
1497 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1501 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1502 argv_find(argv
, argc
, "neighbors", &idx
);
1503 peerstr
= argv
[++idx
]->arg
;
1505 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1508 json_object
*json_no
= NULL
;
1509 json_no
= json_object_new_object();
1510 json_object_string_add(json_no
, "warning",
1511 "Malformed address");
1512 vty_out(vty
, "%s\n",
1513 json_object_to_json_string(json_no
));
1514 json_object_free(json_no
);
1516 vty_out(vty
, "Malformed address: %s\n",
1520 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1522 json_object
*json_no
= NULL
;
1523 json_no
= json_object_new_object();
1524 json_object_string_add(
1526 "No such neighbor or address family");
1527 vty_out(vty
, "%s\n",
1528 json_object_to_json_string(json_no
));
1529 json_object_free(json_no
);
1531 vty_out(vty
, "%% No such neighbor or address family\n");
1535 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1539 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1540 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1541 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1547 "Detailed information on TCP and BGP neighbor connections\n"
1548 "IPv4 Neighbor to display information about\n"
1549 "IPv6 Neighbor to display information about\n"
1550 "Neighbor on BGP configured interface\n"
1551 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1555 bool uj
= use_json(argc
, argv
);
1556 struct bgp
*bgp
= NULL
;
1557 afi_t afi
= AFI_L2VPN
;
1558 safi_t safi
= SAFI_EVPN
;
1559 char *peerstr
= NULL
;
1564 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1567 vty_out(vty
, "No index\n");
1571 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1572 argv_find(argv
, argc
, "neighbors", &idx
);
1573 peerstr
= argv
[++idx
]->arg
;
1575 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1578 json_object
*json_no
= NULL
;
1579 json_no
= json_object_new_object();
1580 json_object_string_add(json_no
, "warning",
1581 "Malformed address");
1582 vty_out(vty
, "%s\n",
1583 json_object_to_json_string(json_no
));
1584 json_object_free(json_no
);
1586 vty_out(vty
, "Malformed address: %s\n",
1590 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1592 json_object
*json_no
= NULL
;
1593 json_no
= json_object_new_object();
1594 json_object_string_add(
1596 "No such neighbor or address family");
1597 vty_out(vty
, "%s\n",
1598 json_object_to_json_string(json_no
));
1599 json_object_free(json_no
);
1601 vty_out(vty
, "%% No such neighbor or address family\n");
1605 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1608 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1609 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1610 "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]",
1616 "Display information for a route distinguisher\n"
1617 "VPN Route Distinguisher\n"
1618 "Detailed information on TCP and BGP neighbor connections\n"
1619 "IPv4 Neighbor to display information about\n"
1620 "IPv6 Neighbor to display information about\n"
1621 "Neighbor on BGP configured interface\n"
1622 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1624 int idx_ext_community
= 0;
1628 struct prefix_rd prd
;
1629 struct bgp
*bgp
= NULL
;
1630 bool uj
= use_json(argc
, argv
);
1631 char *peerstr
= NULL
;
1632 afi_t afi
= AFI_L2VPN
;
1633 safi_t safi
= SAFI_EVPN
;
1641 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1644 vty_out(vty
, "No index\n");
1648 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1650 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1651 argv_find(argv
, argc
, "neighbors", &idx
);
1652 peerstr
= argv
[++idx
]->arg
;
1654 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1657 json_object
*json_no
= NULL
;
1658 json_no
= json_object_new_object();
1659 json_object_string_add(json_no
, "warning",
1660 "Malformed address");
1661 vty_out(vty
, "%s\n",
1662 json_object_to_json_string(json_no
));
1663 json_object_free(json_no
);
1665 vty_out(vty
, "Malformed address: %s\n",
1669 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1671 json_object
*json_no
= NULL
;
1672 json_no
= json_object_new_object();
1673 json_object_string_add(
1675 "No such neighbor or address family");
1676 vty_out(vty
, "%s\n",
1677 json_object_to_json_string(json_no
));
1678 json_object_free(json_no
);
1680 vty_out(vty
, "%% No such neighbor or address family\n");
1684 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1687 json_object
*json_no
= NULL
;
1688 json_no
= json_object_new_object();
1689 json_object_string_add(json_no
, "warning",
1690 "Malformed Route Distinguisher");
1691 vty_out(vty
, "%s\n",
1692 json_object_to_json_string(json_no
));
1693 json_object_free(json_no
);
1695 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1699 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1702 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1703 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1704 "show [ip] bgp l2vpn evpn all overlay [json]",
1710 "Display information about all EVPN NLRIs\n"
1711 "Display BGP Overlay Information for prefixes\n"
1714 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1715 SHOW_DISPLAY_OVERLAY
,
1716 use_json(argc
, argv
));
1719 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1720 show_ip_bgp_evpn_rd_overlay_cmd
,
1721 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1727 "Display information for a route distinguisher\n"
1728 "VPN Route Distinguisher\n"
1729 "Display BGP Overlay Information for prefixes\n")
1731 int idx_ext_community
= 0;
1733 struct prefix_rd prd
;
1735 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1737 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1739 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1742 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1743 SHOW_DISPLAY_OVERLAY
,
1744 use_json(argc
, argv
));
1747 DEFUN(show_bgp_l2vpn_evpn_com
,
1748 show_bgp_l2vpn_evpn_com_cmd
,
1749 "show bgp l2vpn evpn \
1750 <community AA:NN|large-community AA:BB:CC> \
1751 [exact-match] [json]",
1756 "Display routes matching the community\n"
1757 "Community number where AA and NN are (0-65535)\n"
1758 "Display routes matching the large-community\n"
1759 "List of large-community numbers\n"
1760 "Exact match of the communities\n"
1765 const char *clist_number_or_name
;
1766 int show_type
= bgp_show_type_normal
;
1767 struct community
*com
;
1768 struct lcommunity
*lcom
;
1770 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1771 clist_number_or_name
= argv
[++idx
]->arg
;
1772 show_type
= bgp_show_type_lcommunity
;
1774 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1775 show_type
= bgp_show_type_lcommunity_exact
;
1777 lcom
= lcommunity_str2com(clist_number_or_name
);
1779 vty_out(vty
, "%% Large-community malformed\n");
1783 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1784 SHOW_DISPLAY_STANDARD
,
1785 use_json(argc
, argv
));
1787 lcommunity_free(&lcom
);
1788 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1789 clist_number_or_name
= argv
[++idx
]->arg
;
1790 show_type
= bgp_show_type_community
;
1792 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1793 show_type
= bgp_show_type_community_exact
;
1795 com
= community_str2com(clist_number_or_name
);
1798 vty_out(vty
, "%% Community malformed: %s\n",
1799 clist_number_or_name
);
1803 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1804 SHOW_DISPLAY_STANDARD
,
1805 use_json(argc
, argv
));
1806 community_free(&com
);
1812 /* For testing purpose, static route of EVPN RT-5. */
1813 DEFUN(evpnrt5_network
,
1814 evpnrt5_network_cmd
,
1815 "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]",
1816 "Specify a network to announce via BGP\n"
1819 "Specify Route Distinguisher\n"
1820 "VPN Route Distinguisher\n"
1822 "Ethernet Tag Value\n"
1825 "Ethernet Segment Identifier\n"
1826 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1828 "Gateway IP ( A.B.C.D )\n"
1829 "Gateway IPv6 ( X:X::X:X )\n"
1830 "Router Mac Ext Comm\n"
1831 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1832 "Route-map to modify the attributes\n"
1833 "Name of the route map\n")
1835 int idx_ipv4_prefixlen
= 1;
1836 int idx_route_distinguisher
= 3;
1841 int idx_routermac
= 13;
1843 return bgp_static_set_safi(
1844 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1845 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1846 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1847 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1848 argv
[idx_routermac
]->arg
);
1851 /* For testing purpose, static route of EVPN RT-5. */
1852 DEFUN(no_evpnrt5_network
,
1853 no_evpnrt5_network_cmd
,
1854 "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>",
1856 "Specify a network to announce via BGP\n"
1859 "Specify Route Distinguisher\n"
1860 "VPN Route Distinguisher\n"
1862 "Ethernet Tag Value\n"
1865 "Ethernet Segment Identifier\n"
1866 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1867 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1869 int idx_ipv4_prefixlen
= 2;
1870 int idx_ext_community
= 4;
1875 return bgp_static_unset_safi(
1876 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1877 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1878 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1879 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1882 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1884 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1887 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1889 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1893 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1894 * check that this is a change.
1896 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1897 struct ecommunity
*ecomadd
)
1899 /* If the VNI is "live", we need to uninstall routes using the current
1900 * import RT(s) first before we update the import RT, and subsequently
1903 if (is_vni_live(vpn
))
1904 bgp_evpn_uninstall_routes(bgp
, vpn
);
1906 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1907 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1909 /* If the auto route-target is in use we must remove it */
1910 evpn_import_rt_delete_auto(bgp
, vpn
);
1912 /* Add new RT and rebuild the RT to VNI mapping */
1913 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1915 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1916 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1918 /* Install routes that match new import RT */
1919 if (is_vni_live(vpn
))
1920 bgp_evpn_install_routes(bgp
, vpn
);
1924 * Unconfigure Import RT(s) for a VNI (vty handler).
1926 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1927 struct ecommunity
*ecomdel
)
1929 struct listnode
*node
, *nnode
, *node_to_del
;
1930 struct ecommunity
*ecom
;
1932 /* Along the lines of "configure" except we have to reset to the
1935 if (is_vni_live(vpn
))
1936 bgp_evpn_uninstall_routes(bgp
, vpn
);
1938 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1939 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1941 /* Delete all import RTs */
1942 if (ecomdel
== NULL
) {
1943 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1944 ecommunity_free(&ecom
);
1945 list_delete_node(vpn
->import_rtl
, node
);
1949 /* Delete a specific import RT */
1953 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1954 if (ecommunity_match(ecom
, ecomdel
)) {
1955 ecommunity_free(&ecom
);
1962 list_delete_node(vpn
->import_rtl
, node_to_del
);
1965 assert(vpn
->import_rtl
);
1966 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1967 if (list_isempty(vpn
->import_rtl
)) {
1968 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1969 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1971 /* Rebuild the RT to VNI mapping */
1973 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1975 /* Install routes that match new import RT */
1976 if (is_vni_live(vpn
))
1977 bgp_evpn_install_routes(bgp
, vpn
);
1981 * Configure the Export RT for a VNI (vty handler). Caller expected to
1982 * check that this is a change. Note that only a single export RT is
1983 * allowed for a VNI and any change to configuration is implemented as
1984 * a "replace" (similar to other configuration).
1986 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1987 struct ecommunity
*ecomadd
)
1989 /* If the auto route-target is in use we must remove it */
1990 evpn_export_rt_delete_auto(bgp
, vpn
);
1992 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1993 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1995 if (is_vni_live(vpn
))
1996 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2000 * Unconfigure the Export RT for a VNI (vty handler)
2002 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2003 struct ecommunity
*ecomdel
)
2005 struct listnode
*node
, *nnode
, *node_to_del
;
2006 struct ecommunity
*ecom
;
2008 /* Delete all export RTs */
2009 if (ecomdel
== NULL
) {
2010 /* Reset to default and process all routes. */
2011 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2012 ecommunity_free(&ecom
);
2013 list_delete_node(vpn
->export_rtl
, node
);
2017 /* Delete a specific export RT */
2021 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2022 if (ecommunity_match(ecom
, ecomdel
)) {
2023 ecommunity_free(&ecom
);
2030 list_delete_node(vpn
->export_rtl
, node_to_del
);
2033 assert(vpn
->export_rtl
);
2034 if (list_isempty(vpn
->export_rtl
)) {
2035 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2036 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2039 if (is_vni_live(vpn
))
2040 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2044 * Configure RD for VRF
2046 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2048 /* If we have already advertise type-5 routes with a diffrent RD, we
2049 * have to delete and withdraw them firs
2051 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2054 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2055 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2057 /* We have a new RD for VRF.
2058 * Advertise all type-5 routes again with the new RD
2060 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2064 * Unconfigure RD for VRF
2066 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2068 /* If we have already advertise type-5 routes with a diffrent RD, we
2069 * have to delete and withdraw them firs
2071 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2073 /* fall back to default RD */
2074 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2075 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2077 /* We have a new RD for VRF.
2078 * Advertise all type-5 routes again with the new RD
2080 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2084 * Configure RD for a VNI (vty handler)
2086 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2087 struct prefix_rd
*rd
)
2089 /* If the VNI is "live", we need to delete and withdraw this VNI's
2090 * local routes with the prior RD first. Then, after updating RD,
2091 * need to re-advertise.
2093 if (is_vni_live(vpn
))
2094 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2097 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2098 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2100 if (is_vni_live(vpn
))
2101 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2105 * Unconfigure RD for a VNI (vty handler)
2107 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2109 /* If the VNI is "live", we need to delete and withdraw this VNI's
2110 * local routes with the prior RD first. Then, after resetting RD
2111 * to automatic value, need to re-advertise.
2113 if (is_vni_live(vpn
))
2114 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2116 /* reset RD to default */
2117 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2119 if (is_vni_live(vpn
))
2120 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2124 * Create VNI, if not already present (VTY handler). Mark as configured.
2126 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2128 struct bgpevpn
*vpn
;
2129 struct in_addr mcast_grp
= {INADDR_ANY
};
2134 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2136 /* Check if this L2VNI is already configured as L3VNI */
2137 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2140 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2145 /* tenant vrf will be updated when we get local_vni_add from
2148 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2152 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2158 /* Mark as configured. */
2159 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2164 * Delete VNI. If VNI does not exist in the system (i.e., just
2165 * configuration), all that is needed is to free it. Otherwise,
2166 * any parameters configured for the VNI need to be reset (with
2167 * appropriate action) and the VNI marked as unconfigured; the
2168 * VNI will continue to exist, purely as a "learnt" entity.
2170 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2172 assert(bgp
->vnihash
);
2174 if (!is_vni_live(vpn
)) {
2175 bgp_evpn_free(bgp
, vpn
);
2179 /* We need to take the unconfigure action for each parameter of this VNI
2180 * that is configured. Some optimization is possible, but not worth the
2181 * additional code for an operation that should be pretty rare.
2183 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2185 /* First, deal with the export side - RD and export RT changes. */
2186 if (is_rd_configured(vpn
))
2187 evpn_unconfigure_rd(bgp
, vpn
);
2188 if (is_export_rt_configured(vpn
))
2189 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2191 /* Next, deal with the import side. */
2192 if (is_import_rt_configured(vpn
))
2193 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2199 * Display import RT mapping to VRFs (vty handler)
2200 * bgp_evpn: evpn bgp instance
2202 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2210 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2211 (void (*)(struct hash_bucket
*,
2212 void *))show_vrf_import_rt_entry
,
2217 * Display import RT mapping to VNIs (vty handler)
2219 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2228 bgp
->import_rt_hash
,
2229 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2234 * Display EVPN routes for all VNIs - vty handler.
2236 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2237 struct in_addr vtep_ip
, json_object
*json
,
2241 struct vni_walk_ctx wctx
;
2243 num_vnis
= hashcount(bgp
->vnihash
);
2246 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2249 wctx
.vtep_ip
= vtep_ip
;
2251 wctx
.detail
= detail
;
2252 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2253 void *))show_vni_routes_hash
,
2258 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2260 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2261 vni_t vni
, struct in_addr orig_ip
,
2264 struct bgpevpn
*vpn
;
2265 struct prefix_evpn p
;
2266 struct bgp_node
*rn
;
2267 struct bgp_path_info
*pi
;
2268 uint32_t path_cnt
= 0;
2271 json_object
*json_paths
= NULL
;
2277 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2279 vty_out(vty
, "VNI not found\n");
2283 /* See if route exists. */
2284 build_evpn_type3_prefix(&p
, orig_ip
);
2285 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2286 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2288 vty_out(vty
, "%% Network not in table\n");
2293 json_paths
= json_object_new_array();
2295 /* Prefix and num paths displayed once per prefix. */
2296 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2298 /* Display each path for this prefix. */
2299 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2300 json_object
*json_path
= NULL
;
2303 json_path
= json_object_new_array();
2305 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2309 json_object_array_add(json_paths
, json_path
);
2316 json_object_object_add(json
, "paths", json_paths
);
2318 json_object_int_add(json
, "numPaths", path_cnt
);
2320 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2326 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2327 * By definition, only matching type-2 route will be displayed.
2329 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2330 vni_t vni
, struct ethaddr
*mac
,
2331 struct ipaddr
*ip
, json_object
*json
)
2333 struct bgpevpn
*vpn
;
2334 struct prefix_evpn p
;
2335 struct bgp_node
*rn
;
2336 struct bgp_path_info
*pi
;
2337 uint32_t path_cnt
= 0;
2340 json_object
*json_paths
= NULL
;
2346 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2349 vty_out(vty
, "VNI not found\n");
2353 /* See if route exists. Look for both non-sticky and sticky. */
2354 build_evpn_type2_prefix(&p
, mac
, ip
);
2355 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2356 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2358 vty_out(vty
, "%% Network not in table\n");
2363 json_paths
= json_object_new_array();
2365 /* Prefix and num paths displayed once per prefix. */
2366 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2368 /* Display each path for this prefix. */
2369 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2370 json_object
*json_path
= NULL
;
2373 json_path
= json_object_new_array();
2375 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2379 json_object_array_add(json_paths
, json_path
);
2386 json_object_object_add(json
, "paths", json_paths
);
2388 json_object_int_add(json
, "numPaths", path_cnt
);
2390 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2395 /* Disaplay EVPN routes for a ESI - VTY handler */
2396 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2397 esi_t
*esi
, json_object
*json
)
2399 struct evpnes
*es
= NULL
;
2402 es
= bgp_evpn_lookup_es(bgp
, esi
);
2405 vty_out(vty
, "ESI not found\n");
2409 show_esi_routes(bgp
, es
, vty
, json
);
2413 * Display EVPN routes for a VNI - vty handler.
2414 * If 'type' is non-zero, only routes matching that type are shown.
2415 * If the vtep_ip is non zero, only routes behind that vtep are shown
2417 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2418 int type
, struct in_addr vtep_ip
,
2421 struct bgpevpn
*vpn
;
2424 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2427 vty_out(vty
, "VNI not found\n");
2431 /* Walk this VNI's route table and display appropriate routes. */
2432 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2436 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2437 * IP (vty handler). By definition, only matching type-2 route will be
2440 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2441 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2442 struct ipaddr
*ip
, json_object
*json
)
2444 struct prefix_evpn p
;
2445 struct bgp_node
*rn
;
2446 struct bgp_path_info
*pi
;
2449 uint32_t path_cnt
= 0;
2450 json_object
*json_paths
= NULL
;
2451 char prefix_str
[BUFSIZ
];
2456 /* See if route exists. Look for both non-sticky and sticky. */
2457 build_evpn_type2_prefix(&p
, mac
, ip
);
2458 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2459 (struct prefix
*)&p
, prd
);
2460 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2462 vty_out(vty
, "%% Network not in table\n");
2466 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2467 sizeof(prefix_str
));
2469 /* Prefix and num paths displayed once per prefix. */
2470 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2473 json_paths
= json_object_new_array();
2475 /* Display each path for this prefix. */
2476 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2477 json_object
*json_path
= NULL
;
2480 json_path
= json_object_new_array();
2482 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2486 json_object_array_add(json_paths
, json_path
);
2491 if (json
&& path_cnt
) {
2493 json_object_object_add(json
, prefix_str
, json_paths
);
2494 json_object_int_add(json
, "numPaths", path_cnt
);
2496 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2502 * Display BGP EVPN routing table -- for specific RD (vty handler)
2503 * If 'type' is non-zero, only routes matching that type are shown.
2505 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2506 struct prefix_rd
*prd
, int type
,
2509 struct bgp_node
*rd_rn
;
2510 struct bgp_table
*table
;
2511 struct bgp_node
*rn
;
2512 struct bgp_path_info
*pi
;
2516 uint32_t prefix_cnt
, path_cnt
;
2517 char rd_str
[RD_ADDRSTRLEN
];
2518 json_object
*json_rd
= NULL
;
2519 int add_rd_to_json
= 0;
2523 prefix_cnt
= path_cnt
= 0;
2525 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2527 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2531 table
= bgp_node_get_bgp_table_info(rd_rn
);
2536 json_rd
= json_object_new_object();
2537 json_object_string_add(json_rd
, "rd", rd_str
);
2540 /* Display all prefixes with this RD. */
2541 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2542 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2543 json_object
*json_prefix
= NULL
;
2544 json_object
*json_paths
= NULL
;
2545 char prefix_str
[BUFSIZ
];
2546 int add_prefix_to_json
= 0;
2548 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2549 sizeof(prefix_str
));
2551 if (type
&& evp
->prefix
.route_type
!= type
)
2555 json_prefix
= json_object_new_object();
2557 pi
= bgp_node_get_bgp_path_info(rn
);
2559 /* RD header and legend - once overall. */
2560 if (rd_header
&& !json
) {
2562 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2564 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2566 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2570 /* Prefix and num paths displayed once per prefix. */
2571 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2578 json_paths
= json_object_new_array();
2580 /* Display each path for this prefix. */
2581 for (; pi
; pi
= pi
->next
) {
2582 json_object
*json_path
= NULL
;
2585 json_path
= json_object_new_array();
2587 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2591 json_object_array_add(json_paths
, json_path
);
2594 add_prefix_to_json
= 1;
2599 if (add_prefix_to_json
) {
2600 json_object_object_add(json_prefix
, "paths",
2602 json_object_object_add(json_rd
, prefix_str
,
2605 json_object_free(json_paths
);
2606 json_object_free(json_prefix
);
2615 json_object_object_add(json
, rd_str
, json_rd
);
2617 json_object_free(json_rd
);
2621 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2622 json_object_int_add(json
, "numPaths", path_cnt
);
2624 if (prefix_cnt
== 0)
2625 vty_out(vty
, "No prefixes exist with this RD%s\n",
2626 type
? " (of requested type)" : "");
2629 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2630 prefix_cnt
, path_cnt
,
2631 type
? " (of requested type)" : "");
2636 * Display BGP EVPN routing table - all routes (vty handler).
2637 * If 'type' is non-zero, only routes matching that type are shown.
2639 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2640 json_object
*json
, int detail
)
2642 struct bgp_node
*rd_rn
;
2643 struct bgp_table
*table
;
2644 struct bgp_node
*rn
;
2645 struct bgp_path_info
*pi
;
2646 int header
= detail
? 0 : 1;
2650 uint32_t prefix_cnt
, path_cnt
;
2654 prefix_cnt
= path_cnt
= 0;
2656 /* EVPN routing table is a 2-level table with the first level being
2659 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2660 rd_rn
= bgp_route_next(rd_rn
)) {
2661 char rd_str
[RD_ADDRSTRLEN
];
2662 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2663 int add_rd_to_json
= 0;
2666 table
= bgp_node_get_bgp_table_info(rd_rn
);
2670 tbl_ver
= table
->version
;
2671 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2675 json_rd
= json_object_new_object();
2679 /* Display all prefixes for an RD */
2680 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2681 json_object
*json_prefix
=
2682 NULL
; /* contains prefix under a RD */
2683 json_object
*json_paths
=
2684 NULL
; /* array of paths under a prefix*/
2685 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2686 char prefix_str
[BUFSIZ
];
2687 int add_prefix_to_json
= 0;
2689 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2690 prefix_str
, sizeof(prefix_str
));
2692 if (type
&& evp
->prefix
.route_type
!= type
)
2695 pi
= bgp_node_get_bgp_path_info(rn
);
2697 /* Overall header/legend displayed once. */
2699 bgp_evpn_show_route_header(vty
, bgp
,
2704 "%19s Extended Community\n"
2709 /* RD header - per RD. */
2711 bgp_evpn_show_route_rd_header(
2712 vty
, rd_rn
, json_rd
, rd_str
,
2721 json_prefix
= json_object_new_object();
2722 json_paths
= json_object_new_array();
2723 json_object_string_add(json_prefix
, "prefix",
2725 json_object_int_add(json_prefix
, "prefixLen",
2729 /* Prefix and num paths displayed once per prefix. */
2731 route_vty_out_detail_header(
2733 (struct prefix_rd
*)&rd_rn
->p
,
2734 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2736 /* For EVPN, the prefix is displayed for each path (to
2738 * with code that already exists).
2740 for (; pi
; pi
= pi
->next
) {
2741 json_object
*json_path
= NULL
;
2743 add_prefix_to_json
= 1;
2747 json_path
= json_object_new_array();
2750 route_vty_out_detail(
2751 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2752 SAFI_EVPN
, json_path
);
2754 route_vty_out(vty
, &rn
->p
, pi
, 0,
2755 SAFI_EVPN
, json_path
);
2758 json_object_array_add(json_paths
,
2763 if (add_prefix_to_json
) {
2764 json_object_object_add(json_prefix
,
2767 json_object_object_add(json_rd
,
2771 json_object_free(json_prefix
);
2772 json_object_free(json_paths
);
2781 json_object_object_add(json
, rd_str
, json_rd
);
2783 json_object_free(json_rd
);
2790 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2791 json_object_int_add(json
, "numPaths", path_cnt
);
2793 if (prefix_cnt
== 0) {
2794 vty_out(vty
, "No EVPN prefixes %sexist\n",
2795 type
? "(of requested type) " : "");
2797 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2798 prefix_cnt
, path_cnt
,
2799 type
? " (of requested type)" : "");
2804 /* Display specific ES */
2805 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2808 struct evpnes
*es
= NULL
;
2810 es
= bgp_evpn_lookup_es(bgp
, esi
);
2812 display_es(vty
, es
, json
);
2815 vty_out(vty
, "{}\n");
2817 vty_out(vty
, "ESI not found\n");
2823 /* Display all ESs */
2824 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2830 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2831 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2836 hash_iterate(bgp
->esihash
,
2837 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2842 * Display specified VNI (vty handler)
2844 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2848 struct bgpevpn
*vpn
;
2850 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2853 display_vni(vty
, vpn
, json
);
2855 struct bgp
*bgp_temp
;
2856 struct listnode
*node
= NULL
;
2858 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2859 if (bgp_temp
->l3vni
== vni
) {
2861 display_l3vni(vty
, bgp_temp
, json
);
2868 vty_out(vty
, "{}\n");
2870 vty_out(vty
, "VNI not found\n");
2877 * Display a VNI (upon user query).
2879 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2883 struct bgp
*bgp_temp
= NULL
;
2884 struct listnode
*node
;
2888 vty_out(vty
, "Flags: * - Kernel\n");
2889 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2890 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2893 /* print all L2 VNIS */
2896 hash_iterate(bgp
->vnihash
,
2897 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2900 /* print all L3 VNIs */
2901 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2902 show_l3vni_entry(vty
, bgp_temp
, json
);
2906 * evpn - enable advertisement of svi MAC-IP
2908 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2912 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2914 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2917 bgp
->evpn_info
->advertise_svi_macip
= set
;
2918 bgp_zebra_advertise_svi_macip(bgp
,
2919 bgp
->evpn_info
->advertise_svi_macip
, 0);
2921 if (set
&& vpn
->advertise_svi_macip
)
2923 else if (!set
&& !vpn
->advertise_svi_macip
)
2926 vpn
->advertise_svi_macip
= set
;
2927 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2933 * evpn - enable advertisement of default g/w
2935 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2938 if (bgp
->advertise_gw_macip
)
2941 bgp
->advertise_gw_macip
= 1;
2942 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2944 if (vpn
->advertise_gw_macip
)
2947 vpn
->advertise_gw_macip
= 1;
2948 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2955 * evpn - disable advertisement of default g/w
2957 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2958 struct bgpevpn
*vpn
)
2961 if (!bgp
->advertise_gw_macip
)
2964 bgp
->advertise_gw_macip
= 0;
2965 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2967 if (!vpn
->advertise_gw_macip
)
2970 vpn
->advertise_gw_macip
= 0;
2971 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2978 * evpn - enable advertisement of default g/w
2980 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2981 afi_t afi
, bool add
)
2983 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2986 /* bail if we are already advertising default route */
2987 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2991 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2992 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2993 else if (afi
== AFI_IP6
)
2994 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2995 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2997 /* bail out if we havent advertised the default route */
2998 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3001 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3002 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3003 else if (afi
== AFI_IP6
)
3004 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3005 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3008 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3012 * evpn - enable advertisement of default g/w
3014 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3015 struct bgpevpn
*vpn
)
3017 if (vpn
->advertise_subnet
)
3020 vpn
->advertise_subnet
= 1;
3021 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3025 * evpn - disable advertisement of default g/w
3027 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3029 if (!vpn
->advertise_subnet
)
3032 vpn
->advertise_subnet
= 0;
3033 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3037 * EVPN (VNI advertisement) enabled. Register with zebra.
3039 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3041 bgp
->advertise_all_vni
= 1;
3043 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3047 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3048 * cache, EVPN routes (delete and withdraw from peers).
3050 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3052 bgp
->advertise_all_vni
= 0;
3053 bgp_set_evpn(bgp_get_default());
3054 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3055 bgp_evpn_cleanup_on_disable(bgp
);
3059 * EVPN - use RFC8365 to auto-derive RT
3061 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3063 bgp
->advertise_autort_rfc8365
= 1;
3064 bgp_evpn_handle_autort_change(bgp
);
3068 * EVPN - don't use RFC8365 to auto-derive RT
3070 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3072 bgp
->advertise_autort_rfc8365
= 0;
3073 bgp_evpn_handle_autort_change(bgp
);
3076 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3078 char buf1
[RD_ADDRSTRLEN
];
3080 struct listnode
*node
, *nnode
;
3081 struct ecommunity
*ecom
;
3083 if (is_vni_configured(vpn
)) {
3084 vty_out(vty
, " vni %d\n", vpn
->vni
);
3085 if (is_rd_configured(vpn
))
3086 vty_out(vty
, " rd %s\n",
3087 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3089 if (is_import_rt_configured(vpn
)) {
3090 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3092 ecom_str
= ecommunity_ecom2str(
3093 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3094 vty_out(vty
, " route-target import %s\n",
3096 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3100 if (is_export_rt_configured(vpn
)) {
3101 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3103 ecom_str
= ecommunity_ecom2str(
3104 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3105 vty_out(vty
, " route-target export %s\n",
3107 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3111 if (vpn
->advertise_gw_macip
)
3112 vty_out(vty
, " advertise-default-gw\n");
3114 if (vpn
->advertise_svi_macip
)
3115 vty_out(vty
, " advertise-svi-ip\n");
3117 if (vpn
->advertise_subnet
)
3118 vty_out(vty
, " advertise-subnet\n");
3120 vty_out(vty
, " exit-vni\n");
3124 #ifndef VTYSH_EXTRACT_PL
3125 #include "bgpd/bgp_evpn_vty_clippy.c"
3128 DEFPY(bgp_evpn_flood_control
,
3129 bgp_evpn_flood_control_cmd
,
3130 "[no$no] flooding <disable$disable|head-end-replication$her>",
3132 "Specify handling for BUM packets\n"
3133 "Do not flood any BUM packets\n"
3134 "Flood BUM packets using head-end replication\n")
3136 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3137 enum vxlan_flood_control flood_ctrl
;
3143 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3145 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3149 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3152 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3153 bgp_evpn_flood_control_change(bgp
);
3158 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3159 bgp_evpn_advertise_default_gw_vni_cmd
,
3160 "advertise-default-gw",
3161 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3163 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3164 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3169 evpn_set_advertise_default_gw(bgp
, vpn
);
3174 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3175 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3176 "no advertise-default-gw",
3178 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3180 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3181 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3186 evpn_unset_advertise_default_gw(bgp
, vpn
);
3192 DEFUN (bgp_evpn_advertise_default_gw
,
3193 bgp_evpn_advertise_default_gw_cmd
,
3194 "advertise-default-gw",
3195 "Advertise All default g/w mac-ip routes in EVPN\n")
3197 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3202 if (!EVPN_ENABLED(bgp
)) {
3204 "This command is only supported under the EVPN VRF\n");
3208 evpn_set_advertise_default_gw(bgp
, NULL
);
3213 DEFUN (no_bgp_evpn_advertise_default_gw
,
3214 no_bgp_evpn_advertise_default_gw_cmd
,
3215 "no advertise-default-gw",
3217 "Withdraw All default g/w mac-ip routes from EVPN\n")
3219 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3224 if (!EVPN_ENABLED(bgp
)) {
3226 "This command is only supported under the EVPN VRF\n");
3230 evpn_unset_advertise_default_gw(bgp
, NULL
);
3235 DEFUN (bgp_evpn_advertise_all_vni
,
3236 bgp_evpn_advertise_all_vni_cmd
,
3237 "advertise-all-vni",
3238 "Advertise All local VNIs\n")
3240 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3241 struct bgp
*bgp_evpn
= NULL
;
3246 bgp_evpn
= bgp_get_evpn();
3247 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3248 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3250 return CMD_WARNING_CONFIG_FAILED
;
3253 evpn_set_advertise_all_vni(bgp
);
3257 DEFUN (no_bgp_evpn_advertise_all_vni
,
3258 no_bgp_evpn_advertise_all_vni_cmd
,
3259 "no advertise-all-vni",
3261 "Advertise All local VNIs\n")
3263 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3267 evpn_unset_advertise_all_vni(bgp
);
3271 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3272 bgp_evpn_advertise_autort_rfc8365_cmd
,
3273 "autort rfc8365-compatible",
3274 "Auto-derivation of RT\n"
3275 "Auto-derivation of RT using RFC8365\n")
3277 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3281 evpn_set_advertise_autort_rfc8365(bgp
);
3285 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3286 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3287 "no autort rfc8365-compatible",
3289 "Auto-derivation of RT\n"
3290 "Auto-derivation of RT using RFC8365\n")
3292 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3296 evpn_unset_advertise_autort_rfc8365(bgp
);
3300 DEFUN (bgp_evpn_default_originate
,
3301 bgp_evpn_default_originate_cmd
,
3302 "default-originate <ipv4 | ipv6>",
3303 "originate a default route\n"
3304 "ipv4 address family\n"
3305 "ipv6 address family\n")
3309 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3313 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3314 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3318 DEFUN (no_bgp_evpn_default_originate
,
3319 no_bgp_evpn_default_originate_cmd
,
3320 "no default-originate <ipv4 | ipv6>",
3322 "withdraw a default route\n"
3323 "ipv4 address family\n"
3324 "ipv6 address family\n")
3328 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3332 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3333 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3337 DEFPY (dup_addr_detection
,
3338 dup_addr_detection_cmd
,
3339 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3340 "Duplicate address detection\n"
3341 "Max allowed moves before address detected as duplicate\n"
3342 "Num of max allowed moves (2-1000) default 5\n"
3343 "Duplicate address detection time\n"
3344 "Time in seconds (2-1800) default 180\n")
3346 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3351 if (!EVPN_ENABLED(bgp_vrf
)) {
3353 "This command is only supported under the EVPN VRF\n");
3357 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3360 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3362 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3364 bgp_zebra_dup_addr_detection(bgp_vrf
);
3369 DEFPY (dup_addr_detection_auto_recovery
,
3370 dup_addr_detection_auto_recovery_cmd
,
3371 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3372 "Duplicate address detection\n"
3373 "Duplicate address detection freeze\n"
3374 "Duplicate address detection permanent freeze\n"
3375 "Duplicate address detection freeze time (30-3600)\n")
3377 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3378 uint32_t freeze_time
= freeze_time_val
;
3383 if (!EVPN_ENABLED(bgp_vrf
)) {
3385 "This command is only supported under the EVPN VRF\n");
3389 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3390 bgp_vrf
->evpn_info
->dad_freeze
= true;
3391 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3393 bgp_zebra_dup_addr_detection(bgp_vrf
);
3398 DEFPY (no_dup_addr_detection
,
3399 no_dup_addr_detection_cmd
,
3400 "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>]",
3402 "Duplicate address detection\n"
3403 "Max allowed moves before address detected as duplicate\n"
3404 "Num of max allowed moves (2-1000) default 5\n"
3405 "Duplicate address detection time\n"
3406 "Time in seconds (2-1800) default 180\n"
3407 "Duplicate address detection freeze\n"
3408 "Duplicate address detection permanent freeze\n"
3409 "Duplicate address detection freeze time (30-3600)\n")
3411 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3412 uint32_t max_moves
= (uint32_t)max_moves_val
;
3413 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3418 if (!EVPN_ENABLED(bgp_vrf
)) {
3420 "This command is only supported under the EVPN VRF\n");
3425 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3427 /* Reset all parameters to default. */
3428 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3429 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3430 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3431 bgp_vrf
->evpn_info
->dad_freeze
= false;
3432 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3435 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3437 "%% Value does not match with config\n");
3440 bgp_vrf
->evpn_info
->dad_max_moves
=
3441 EVPN_DAD_DEFAULT_MAX_MOVES
;
3445 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3447 "%% Value does not match with config\n");
3450 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3454 if (bgp_vrf
->evpn_info
->dad_freeze_time
3457 "%% Value does not match with config\n");
3460 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3461 bgp_vrf
->evpn_info
->dad_freeze
= false;
3464 if (permanent_val
) {
3465 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3467 "%% Value does not match with config\n");
3470 bgp_vrf
->evpn_info
->dad_freeze
= false;
3474 bgp_zebra_dup_addr_detection(bgp_vrf
);
3479 DEFPY(bgp_evpn_advertise_svi_ip
,
3480 bgp_evpn_advertise_svi_ip_cmd
,
3481 "[no$no] advertise-svi-ip",
3483 "Advertise svi mac-ip routes in EVPN\n")
3485 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3490 if (!EVPN_ENABLED(bgp
)) {
3492 "This command is only supported under EVPN VRF\n");
3497 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3499 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3504 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3505 bgp_evpn_advertise_svi_ip_vni_cmd
,
3506 "[no$no] advertise-svi-ip",
3508 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3510 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3511 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3517 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3519 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3524 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3525 bgp_evpn_advertise_vni_subnet_cmd
,
3527 "Advertise the subnet corresponding to VNI\n")
3529 struct bgp
*bgp_vrf
= NULL
;
3530 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3531 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3536 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3540 evpn_set_advertise_subnet(bgp
, vpn
);
3544 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3545 no_bgp_evpn_advertise_vni_subnet_cmd
,
3546 "no advertise-subnet",
3548 "Advertise All local VNIs\n")
3550 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3551 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3556 evpn_unset_advertise_subnet(bgp
, vpn
);
3560 DEFUN (bgp_evpn_advertise_type5
,
3561 bgp_evpn_advertise_type5_cmd
,
3562 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3563 "Advertise prefix routes\n"
3566 "route-map for filtering specific routes\n"
3567 "Name of the route map\n")
3569 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3576 int rmap_changed
= 0;
3578 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3579 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3580 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3582 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3584 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3585 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3588 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3592 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3594 "%%only ipv4 or ipv6 address families are supported");
3598 if (safi
!= SAFI_UNICAST
) {
3600 "%%only ipv4 unicast or ipv6 unicast are supported");
3604 if (afi
== AFI_IP
) {
3606 /* if we are already advertising ipv4 prefix as type-5
3609 if (!rmap_changed
&&
3610 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3611 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3613 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3614 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3617 /* if we are already advertising ipv6 prefix as type-5
3620 if (!rmap_changed
&&
3621 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3622 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3624 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3625 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3629 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3630 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3631 XFREE(MTYPE_ROUTE_MAP_NAME
,
3632 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3633 route_map_counter_decrement(
3634 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3635 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3636 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3640 /* set the route-map for advertise command */
3641 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3642 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3643 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3644 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3645 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3646 route_map_counter_increment(
3647 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3650 /* advertise type-5 routes */
3651 if (advertise_type5_routes(bgp_vrf
, afi
))
3652 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3656 DEFUN (no_bgp_evpn_advertise_type5
,
3657 no_bgp_evpn_advertise_type5_cmd
,
3658 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3660 "Advertise prefix routes\n"
3664 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3670 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3671 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3673 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3675 "%%only ipv4 or ipv6 address families are supported");
3679 if (safi
!= SAFI_UNICAST
) {
3681 "%%only ipv4 unicast or ipv6 unicast are supported");
3685 if (afi
== AFI_IP
) {
3687 /* if we are not advertising ipv4 prefix as type-5
3690 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3691 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3692 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3693 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3694 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3698 /* if we are not advertising ipv6 prefix as type-5
3701 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3702 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3703 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3704 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3705 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3709 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3710 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3711 XFREE(MTYPE_ROUTE_MAP_NAME
,
3712 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3713 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3714 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3720 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3721 bgp_evpn_advertise_pip_ip_mac_cmd
,
3722 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3724 "evpn system primary IP\n"
3727 MAC_STR MAC_STR MAC_STR
)
3729 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3730 struct bgp
*bgp_evpn
= NULL
;
3732 if (EVPN_ENABLED(bgp_vrf
)) {
3734 "This command is supported under L3VNI BGP EVPN VRF\n");
3735 return CMD_WARNING_CONFIG_FAILED
;
3737 bgp_evpn
= bgp_get_evpn();
3740 /* pip is already enabled */
3741 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3744 bgp_vrf
->evpn_info
->advertise_pip
= true;
3745 if (ip
.s_addr
!= INADDR_ANY
) {
3746 /* Already configured with same IP */
3747 if (IPV4_ADDR_SAME(&ip
,
3748 &bgp_vrf
->evpn_info
->pip_ip_static
))
3751 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3752 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3754 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3756 /* default instance router-id assignemt */
3758 bgp_vrf
->evpn_info
->pip_ip
=
3759 bgp_evpn
->router_id
;
3762 if (!is_zero_mac(&mac
->eth_addr
)) {
3763 /* Already configured with same MAC */
3764 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3765 &mac
->eth_addr
, ETH_ALEN
) == 0)
3768 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3769 &mac
->eth_addr
, ETH_ALEN
);
3770 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3771 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3774 /* Copy zebra sys mac */
3775 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3776 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3777 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3782 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3784 /* Disable PIP feature */
3785 bgp_vrf
->evpn_info
->advertise_pip
= false;
3786 /* copy anycast mac */
3787 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3788 &bgp_vrf
->rmac
, ETH_ALEN
);
3790 /* remove MAC-IP option retain PIP knob. */
3791 if ((ip
.s_addr
!= INADDR_ANY
) &&
3792 !IPV4_ADDR_SAME(&ip
,
3793 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3795 "%% BGP EVPN PIP IP does not match\n");
3796 return CMD_WARNING_CONFIG_FAILED
;
3799 if (!is_zero_mac(&mac
->eth_addr
) &&
3800 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3801 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3803 "%% BGP EVPN PIP MAC does not match\n");
3804 return CMD_WARNING_CONFIG_FAILED
;
3806 /* pip_rmac can carry vrr_rmac reset only if it matches
3807 * with static value.
3809 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3810 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3812 /* Copy zebra sys mac */
3814 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3815 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3816 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3819 /* copy anycast mac */
3820 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3821 &bgp_vrf
->rmac
, ETH_ALEN
);
3825 /* reset user configured sys MAC */
3826 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3827 /* reset user configured sys IP */
3828 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3829 /* Assign default PIP IP (bgp instance router-id) */
3831 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3833 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3836 if (is_evpn_enabled()) {
3837 struct listnode
*node
= NULL
;
3838 struct bgpevpn
*vpn
= NULL
;
3840 update_advertise_vrf_routes(bgp_vrf
);
3842 /* Update (svi) type-2 routes */
3843 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3844 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3846 update_routes_for_vni(bgp_evpn
, vpn
);
3854 * Display VNI information - for all or a specific VNI
3856 DEFUN(show_bgp_l2vpn_evpn_vni
,
3857 show_bgp_l2vpn_evpn_vni_cmd
,
3858 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3867 struct bgp
*bgp_evpn
;
3871 json_object
*json
= NULL
;
3872 uint32_t num_l2vnis
= 0;
3873 uint32_t num_l3vnis
= 0;
3874 uint32_t num_vnis
= 0;
3875 struct listnode
*node
= NULL
;
3876 struct bgp
*bgp_temp
= NULL
;
3878 uj
= use_json(argc
, argv
);
3880 bgp_evpn
= bgp_get_evpn();
3884 if (!argv_find(argv
, argc
, "evpn", &idx
))
3888 json
= json_object_new_object();
3890 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3892 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3894 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3895 if (bgp_temp
->l3vni
)
3898 num_vnis
= num_l2vnis
+ num_l3vnis
;
3900 json_object_string_add(json
, "advertiseGatewayMacip",
3901 bgp_evpn
->advertise_gw_macip
3904 json_object_string_add(json
, "advertiseSviMacip",
3905 bgp_evpn
->evpn_info
->advertise_svi_macip
3906 ? "Enabled" : "Disabled");
3907 json_object_string_add(json
, "advertiseAllVnis",
3908 is_evpn_enabled() ? "Enabled"
3910 json_object_string_add(
3912 bgp_evpn
->vxlan_flood_ctrl
3913 == VXLAN_FLOOD_HEAD_END_REPL
3914 ? "Head-end replication"
3916 json_object_int_add(json
, "numVnis", num_vnis
);
3917 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3918 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3920 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3921 bgp_evpn
->advertise_gw_macip
? "Enabled"
3923 vty_out(vty
, "Advertise SVI Macip: %s\n",
3924 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3926 vty_out(vty
, "Advertise All VNI flag: %s\n",
3927 is_evpn_enabled() ? "Enabled" : "Disabled");
3928 vty_out(vty
, "BUM flooding: %s\n",
3929 bgp_evpn
->vxlan_flood_ctrl
3930 == VXLAN_FLOOD_HEAD_END_REPL
3931 ? "Head-end replication"
3933 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3934 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3936 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3940 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3943 /* Display specific VNI */
3944 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3945 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3949 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3950 json
, JSON_C_TO_STRING_PRETTY
));
3951 json_object_free(json
);
3958 DEFUN(show_bgp_l2vpn_evpn_es
,
3959 show_bgp_l2vpn_evpn_es_cmd
,
3960 "show bgp l2vpn evpn es [ESI] [json]",
3965 "ethernet-Segment\n"
3966 "Ethernet-Segment Identifier\n"
3972 json_object
*json
= NULL
;
3973 struct bgp
*bgp
= NULL
;
3975 memset(&esi
, 0, sizeof(esi
));
3976 uj
= use_json(argc
, argv
);
3978 bgp
= bgp_get_evpn();
3982 if (!argv_find(argv
, argc
, "evpn", &idx
))
3985 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3986 (!uj
&& argc
== (idx
+ 1) + 1)) {
3989 evpn_show_all_es(vty
, bgp
, json
);
3992 /* show a specific ES */
3994 /* get the ESI - ESI-ID is at argv[5] */
3995 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3996 vty_out(vty
, "%% Malformed ESI\n");
3999 evpn_show_es(vty
, bgp
, &esi
, json
);
4003 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4004 json
, JSON_C_TO_STRING_PRETTY
));
4005 json_object_free(json
);
4012 * Display EVPN neighbor summary.
4014 DEFUN(show_bgp_l2vpn_evpn_summary
,
4015 show_bgp_l2vpn_evpn_summary_cmd
,
4016 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
4023 "Summary of BGP neighbor status\n"
4024 "Show only sessions not in Established state\n"
4028 bool uj
= use_json(argc
, argv
);
4030 bool show_failed
= false;
4032 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4033 vrf
= argv
[++idx_vrf
]->arg
;
4034 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
4036 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
4041 * Display global EVPN routing table.
4043 DEFUN(show_bgp_l2vpn_evpn_route
,
4044 show_bgp_l2vpn_evpn_route_cmd
,
4045 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
4050 "EVPN route information\n"
4051 "Display Detailed Information\n"
4052 "Specify Route type\n"
4053 "MAC-IP (Type-2) route\n"
4054 "Multicast (Type-3) route\n"
4055 "Ethernet Segment (type-4) route \n"
4056 "Prefix (type-5 )route\n"
4064 json_object
*json
= NULL
;
4066 uj
= use_json(argc
, argv
);
4068 bgp
= bgp_get_evpn();
4073 json
= json_object_new_object();
4076 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4077 /* Specific type is requested */
4078 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4079 type
= BGP_EVPN_MAC_IP_ROUTE
;
4080 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4081 type
= BGP_EVPN_IMET_ROUTE
;
4082 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
4083 type
= BGP_EVPN_ES_ROUTE
;
4084 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4085 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4090 if (argv_find(argv
, argc
, "detail", &detail
))
4093 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4096 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4097 json
, JSON_C_TO_STRING_PRETTY
));
4098 json_object_free(json
);
4104 * Display global EVPN routing table for specific RD.
4106 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4107 show_bgp_l2vpn_evpn_route_rd_cmd
,
4108 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
4113 "EVPN route information\n"
4114 "Route Distinguisher\n"
4115 "ASN:XX or A.B.C.D:XX\n"
4116 "Specify Route type\n"
4117 "MAC-IP (Type-2) route\n"
4118 "Multicast (Type-3) route\n"
4119 "Ethernet Segment route\n"
4125 struct prefix_rd prd
;
4130 json_object
*json
= NULL
;
4132 bgp
= bgp_get_evpn();
4136 /* check if we need json output */
4137 uj
= use_json(argc
, argv
);
4139 json
= json_object_new_object();
4142 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4143 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4146 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4152 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4153 /* Specific type is requested */
4154 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4155 type
= BGP_EVPN_MAC_IP_ROUTE
;
4156 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4157 type
= BGP_EVPN_IMET_ROUTE
;
4158 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
4159 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4164 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4167 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4168 json
, JSON_C_TO_STRING_PRETTY
));
4169 json_object_free(json
);
4176 * Display global EVPN routing table for specific RD and MACIP.
4178 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4179 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4180 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4185 "EVPN route information\n"
4186 "Route Distinguisher\n"
4187 "ASN:XX or A.B.C.D:XX\n"
4189 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4191 "IP address (IPv4 or IPv6)\n"
4196 struct prefix_rd prd
;
4203 json_object
*json
= NULL
;
4205 memset(&mac
, 0, sizeof(struct ethaddr
));
4206 memset(&ip
, 0, sizeof(struct ipaddr
));
4208 bgp
= bgp_get_evpn();
4212 /* check if we need json output */
4213 uj
= use_json(argc
, argv
);
4215 json
= json_object_new_object();
4218 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4219 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4221 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4227 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4228 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4229 vty_out(vty
, "%% Malformed MAC address\n");
4234 /* get the ip if specified */
4235 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4236 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4237 vty_out(vty
, "%% Malformed IP address\n");
4242 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4245 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4246 json
, JSON_C_TO_STRING_PRETTY
));
4247 json_object_free(json
);
4253 /* Display per ESI routing table */
4254 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4255 show_bgp_l2vpn_evpn_route_esi_cmd
,
4256 "show bgp l2vpn evpn route esi ESI [json]",
4261 "EVPN route information\n"
4262 "Ethernet Segment Identifier\n"
4268 struct bgp
*bgp
= NULL
;
4269 json_object
*json
= NULL
;
4271 memset(&esi
, 0, sizeof(esi
));
4272 bgp
= bgp_get_evpn();
4276 uj
= use_json(argc
, argv
);
4278 json
= json_object_new_object();
4280 /* get the ESI - ESI-ID is at argv[6] */
4281 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4282 vty_out(vty
, "%% Malformed ESI\n");
4286 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4289 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4290 json
, JSON_C_TO_STRING_PRETTY
));
4291 json_object_free(json
);
4299 * Display per-VNI EVPN routing table.
4301 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4302 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4307 "EVPN route information\n"
4308 "VXLAN Network Identifier\n"
4310 "Specify Route type\n"
4311 "MAC-IP (Type-2) route\n"
4312 "Multicast (Type-3) route\n"
4314 "Remote VTEP IP address\n"
4319 struct in_addr vtep_ip
;
4323 json_object
*json
= NULL
;
4325 bgp
= bgp_get_evpn();
4329 /* check if we need json output */
4330 uj
= use_json(argc
, argv
);
4332 json
= json_object_new_object();
4334 if (!argv_find(argv
, argc
, "evpn", &idx
))
4339 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4341 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4342 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4343 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4344 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4345 type
= BGP_EVPN_MAC_IP_ROUTE
;
4346 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4347 type
= BGP_EVPN_IMET_ROUTE
;
4350 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4351 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4352 vty_out(vty
, "%% Malformed VTEP IP address\n");
4359 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4362 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4363 json
, JSON_C_TO_STRING_PRETTY
));
4364 json_object_free(json
);
4371 * Display per-VNI EVPN routing table for specific MACIP.
4373 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4374 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4375 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4380 "EVPN route information\n"
4381 "VXLAN Network Identifier\n"
4384 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4386 "IP address (IPv4 or IPv6)\n"
4395 json_object
*json
= NULL
;
4397 bgp
= bgp_get_evpn();
4401 /* check if we need json output */
4402 uj
= use_json(argc
, argv
);
4404 json
= json_object_new_object();
4406 if (!argv_find(argv
, argc
, "evpn", &idx
))
4410 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4413 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4414 vty_out(vty
, "%% Malformed MAC address\n");
4419 memset(&ip
, 0, sizeof(ip
));
4420 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4422 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4423 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4424 vty_out(vty
, "%% Malformed IP address\n");
4429 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4432 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4433 json
, JSON_C_TO_STRING_PRETTY
));
4434 json_object_free(json
);
4441 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4443 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4444 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4445 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4450 "EVPN route information\n"
4451 "VXLAN Network Identifier\n"
4453 "Multicast (Type-3) route\n"
4454 "Originating Router IP address\n"
4460 struct in_addr orig_ip
;
4463 json_object
*json
= NULL
;
4465 bgp
= bgp_get_evpn();
4469 /* check if we need json output */
4470 uj
= use_json(argc
, argv
);
4472 json
= json_object_new_object();
4474 if (!argv_find(argv
, argc
, "evpn", &idx
))
4478 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4481 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4483 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4487 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4490 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4491 json
, JSON_C_TO_STRING_PRETTY
));
4492 json_object_free(json
);
4499 * Display per-VNI EVPN routing table - for all VNIs.
4501 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4502 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4503 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4508 "EVPN route information\n"
4509 "VXLAN Network Identifier\n"
4511 "Print Detailed Output\n"
4513 "Remote VTEP IP address\n"
4517 struct in_addr vtep_ip
;
4520 json_object
*json
= NULL
;
4521 /* Detail Adjust. Adjust indexes according to detail option */
4524 bgp
= bgp_get_evpn();
4528 /* check if we need json output */
4529 uj
= use_json(argc
, argv
);
4531 json
= json_object_new_object();
4533 if (!argv_find(argv
, argc
, "evpn", &idx
))
4536 if (argv_find(argv
, argc
, "detail", &da
))
4539 /* vtep-ip position depends on detail option */
4541 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4543 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4544 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4545 vty_out(vty
, "%% Malformed VTEP IP address\n");
4550 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4553 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4554 json
, JSON_C_TO_STRING_PRETTY
));
4555 json_object_free(json
);
4562 * Display EVPN import route-target hash table
4564 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4565 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4566 "show bgp l2vpn evpn vrf-import-rt [json]",
4571 "Show vrf import route target\n"
4575 struct bgp
*bgp_evpn
= NULL
;
4576 json_object
*json
= NULL
;
4578 bgp_evpn
= bgp_get_evpn();
4582 uj
= use_json(argc
, argv
);
4584 json
= json_object_new_object();
4586 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4589 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4590 json
, JSON_C_TO_STRING_PRETTY
));
4591 json_object_free(json
);
4598 * Display EVPN import route-target hash table
4600 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4601 show_bgp_l2vpn_evpn_import_rt_cmd
,
4602 "show bgp l2vpn evpn import-rt [json]",
4607 "Show import route target\n"
4612 json_object
*json
= NULL
;
4614 bgp
= bgp_get_evpn();
4618 uj
= use_json(argc
, argv
);
4620 json
= json_object_new_object();
4622 evpn_show_import_rts(vty
, bgp
, json
);
4625 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4626 json
, JSON_C_TO_STRING_PRETTY
));
4627 json_object_free(json
);
4633 DEFUN(test_adv_evpn_type4_route
,
4634 test_adv_evpn_type4_route_cmd
,
4636 "Advertise EVPN ES route\n"
4637 "Ethernet-segment\n"
4638 "Ethernet-Segment Identifier\n")
4643 struct ipaddr vtep_ip
;
4645 bgp
= bgp_get_evpn();
4647 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4651 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4652 vty_out(vty
, "%%Malformed ESI\n");
4656 vtep_ip
.ipa_type
= IPADDR_V4
;
4657 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4659 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4661 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4667 DEFUN(test_withdraw_evpn_type4_route
,
4668 test_withdraw_evpn_type4_route_cmd
,
4670 "Advertise EVPN ES route\n"
4671 "Ethernet-segment\n"
4672 "Ethernet-Segment Identifier\n")
4677 struct ipaddr vtep_ip
;
4679 bgp
= bgp_get_evpn();
4681 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4685 if (!bgp
->peer_self
) {
4686 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4690 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4691 vty_out(vty
, "%%Malformed ESI\n");
4695 vtep_ip
.ipa_type
= IPADDR_V4
;
4696 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4697 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4699 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4705 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4706 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4710 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4711 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4712 "Summary of BGP neighbor status\n" JSON_STR
)
4714 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4715 "show bgp evpn route [detail] [type <macip|multicast>]",
4716 SHOW_STR BGP_STR EVPN_HELP_STR
4717 "EVPN route information\n"
4718 "Display Detailed Information\n"
4719 "Specify Route type\n"
4720 "MAC-IP (Type-2) route\n"
4721 "Multicast (Type-3) route\n")
4724 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4725 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4726 SHOW_STR BGP_STR EVPN_HELP_STR
4727 "EVPN route information\n"
4728 "Route Distinguisher\n"
4729 "ASN:XX or A.B.C.D:XX\n"
4730 "Specify Route type\n"
4731 "MAC-IP (Type-2) route\n"
4732 "Multicast (Type-3) route\n")
4735 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4736 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4737 SHOW_STR BGP_STR EVPN_HELP_STR
4738 "EVPN route information\n"
4739 "Route Distinguisher\n"
4740 "ASN:XX or A.B.C.D:XX\n"
4742 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4744 "IP address (IPv4 or IPv6)\n")
4747 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4748 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4749 SHOW_STR BGP_STR EVPN_HELP_STR
4750 "EVPN route information\n"
4751 "VXLAN Network Identifier\n"
4753 "Specify Route type\n"
4754 "MAC-IP (Type-2) route\n"
4755 "Multicast (Type-3) route\n"
4757 "Remote VTEP IP address\n")
4759 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4760 show_bgp_evpn_route_vni_macip_cmd
,
4761 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4762 SHOW_STR BGP_STR EVPN_HELP_STR
4763 "EVPN route information\n"
4764 "VXLAN Network Identifier\n"
4767 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4769 "IP address (IPv4 or IPv6)\n")
4771 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4772 show_bgp_evpn_route_vni_multicast_cmd
,
4773 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4774 SHOW_STR BGP_STR EVPN_HELP_STR
4775 "EVPN route information\n"
4776 "VXLAN Network Identifier\n"
4778 "Multicast (Type-3) route\n"
4779 "Originating Router IP address\n")
4781 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4782 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4783 SHOW_STR BGP_STR EVPN_HELP_STR
4784 "EVPN route information\n"
4785 "VXLAN Network Identifier\n"
4787 "Print Detailed Output\n"
4789 "Remote VTEP IP address\n")
4791 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4792 "show bgp evpn import-rt",
4793 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4795 DEFUN_NOSH (bgp_evpn_vni
,
4797 "vni " CMD_VNI_RANGE
,
4798 "VXLAN Network Identifier\n"
4802 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4803 struct bgpevpn
*vpn
;
4808 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4810 /* Create VNI, or mark as configured. */
4811 vpn
= evpn_create_update_vni(bgp
, vni
);
4813 vty_out(vty
, "%% Failed to create VNI \n");
4817 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4821 DEFUN (no_bgp_evpn_vni
,
4822 no_bgp_evpn_vni_cmd
,
4823 "no vni " CMD_VNI_RANGE
,
4825 "VXLAN Network Identifier\n"
4829 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4830 struct bgpevpn
*vpn
;
4835 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4837 /* Check if we should disallow. */
4838 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4840 vty_out(vty
, "%% Specified VNI does not exist\n");
4843 if (!is_vni_configured(vpn
)) {
4844 vty_out(vty
, "%% Specified VNI is not configured\n");
4848 evpn_delete_vni(bgp
, vpn
);
4852 DEFUN_NOSH (exit_vni
,
4855 "Exit from VNI mode\n")
4857 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4858 vty
->node
= BGP_EVPN_NODE
;
4862 DEFUN (bgp_evpn_vrf_rd
,
4863 bgp_evpn_vrf_rd_cmd
,
4864 "rd ASN:NN_OR_IP-ADDRESS:NN",
4865 "Route Distinguisher\n"
4866 "ASN:XX or A.B.C.D:XX\n")
4869 struct prefix_rd prd
;
4870 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4875 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4877 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4881 /* If same as existing value, there is nothing more to do. */
4882 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4885 /* Configure or update the RD. */
4886 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4890 DEFUN (no_bgp_evpn_vrf_rd
,
4891 no_bgp_evpn_vrf_rd_cmd
,
4892 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4894 "Route Distinguisher\n"
4895 "ASN:XX or A.B.C.D:XX\n")
4898 struct prefix_rd prd
;
4899 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4904 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4906 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4910 /* Check if we should disallow. */
4911 if (!is_vrf_rd_configured(bgp_vrf
)) {
4912 vty_out(vty
, "%% RD is not configured for this VRF\n");
4916 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4918 "%% RD specified does not match configuration for this VRF\n");
4922 evpn_unconfigure_vrf_rd(bgp_vrf
);
4926 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4927 no_bgp_evpn_vrf_rd_without_val_cmd
,
4930 "Route Distinguisher\n")
4932 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4937 /* Check if we should disallow. */
4938 if (!is_vrf_rd_configured(bgp_vrf
)) {
4939 vty_out(vty
, "%% RD is not configured for this VRF\n");
4943 evpn_unconfigure_vrf_rd(bgp_vrf
);
4947 DEFUN (bgp_evpn_vni_rd
,
4948 bgp_evpn_vni_rd_cmd
,
4949 "rd ASN:NN_OR_IP-ADDRESS:NN",
4950 "Route Distinguisher\n"
4951 "ASN:XX or A.B.C.D:XX\n")
4953 struct prefix_rd prd
;
4954 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4955 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4961 if (!EVPN_ENABLED(bgp
)) {
4963 "This command is only supported under EVPN VRF\n");
4967 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4969 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4973 /* If same as existing value, there is nothing more to do. */
4974 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4977 /* Configure or update the RD. */
4978 evpn_configure_rd(bgp
, vpn
, &prd
);
4982 DEFUN (no_bgp_evpn_vni_rd
,
4983 no_bgp_evpn_vni_rd_cmd
,
4984 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4986 "Route Distinguisher\n"
4987 "ASN:XX or A.B.C.D:XX\n")
4989 struct prefix_rd prd
;
4990 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4991 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4997 if (!EVPN_ENABLED(bgp
)) {
4999 "This command is only supported under EVPN VRF\n");
5003 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5005 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5009 /* Check if we should disallow. */
5010 if (!is_rd_configured(vpn
)) {
5011 vty_out(vty
, "%% RD is not configured for this VNI\n");
5015 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5017 "%% RD specified does not match configuration for this VNI\n");
5021 evpn_unconfigure_rd(bgp
, vpn
);
5025 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5026 no_bgp_evpn_vni_rd_without_val_cmd
,
5029 "Route Distinguisher\n")
5031 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5032 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5037 if (!EVPN_ENABLED(bgp
)) {
5039 "This command is only supported under EVPN VRF\n");
5043 /* Check if we should disallow. */
5044 if (!is_rd_configured(vpn
)) {
5045 vty_out(vty
, "%% RD is not configured for this VNI\n");
5049 evpn_unconfigure_rd(bgp
, vpn
);
5054 * Loop over all extended-communities in the route-target list rtl and
5055 * return 1 if we find ecomtarget
5057 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5058 struct ecommunity
*ecomtarget
)
5060 struct listnode
*node
, *nnode
;
5061 struct ecommunity
*ecom
;
5063 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5064 if (ecommunity_match(ecom
, ecomtarget
))
5071 /* display L3VNI related info for a VRF instance */
5072 DEFUN (show_bgp_vrf_l3vni_info
,
5073 show_bgp_vrf_l3vni_info_cmd
,
5074 "show bgp vrf VRFNAME vni [json]",
5082 char buf
[ETHER_ADDR_STRLEN
];
5083 char buf1
[INET6_ADDRSTRLEN
];
5085 const char *name
= NULL
;
5086 struct bgp
*bgp
= NULL
;
5087 struct listnode
*node
= NULL
;
5088 struct bgpevpn
*vpn
= NULL
;
5089 struct ecommunity
*ecom
= NULL
;
5090 json_object
*json
= NULL
;
5091 json_object
*json_vnis
= NULL
;
5092 json_object
*json_export_rts
= NULL
;
5093 json_object
*json_import_rts
= NULL
;
5094 bool uj
= use_json(argc
, argv
);
5097 json
= json_object_new_object();
5098 json_vnis
= json_object_new_array();
5099 json_export_rts
= json_object_new_array();
5100 json_import_rts
= json_object_new_array();
5103 name
= argv
[idx_vrf
]->arg
;
5104 bgp
= bgp_lookup_by_name(name
);
5107 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5109 json_object_string_add(json
, "warning",
5110 "BGP instance not found");
5111 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5112 json_object_free(json
);
5118 vty_out(vty
, "BGP VRF: %s\n", name
);
5119 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
5120 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5121 vty_out(vty
, " Rmac: %s\n",
5122 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5123 vty_out(vty
, " VNI Filter: %s\n",
5124 CHECK_FLAG(bgp
->vrf_flags
,
5125 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5126 ? "prefix-routes-only"
5128 vty_out(vty
, " L2-VNI List:\n");
5130 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5131 vty_out(vty
, "%u ", vpn
->vni
);
5133 vty_out(vty
, " Export-RTs:\n");
5135 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5136 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5138 vty_out(vty
, " Import-RTs:\n");
5140 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5141 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5143 vty_out(vty
, " RD: %s\n",
5144 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5146 json_object_string_add(json
, "vrf", name
);
5147 json_object_string_add(json
, "local-ip",
5148 inet_ntoa(bgp
->originator_ip
));
5149 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5150 json_object_string_add(
5152 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5153 json_object_string_add(
5155 CHECK_FLAG(bgp
->vrf_flags
,
5156 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5157 ? "prefix-routes-only"
5159 /* list of l2vnis */
5160 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5161 json_object_array_add(json_vnis
,
5162 json_object_new_int(vpn
->vni
));
5163 json_object_object_add(json
, "l2vnis", json_vnis
);
5166 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5167 json_object_array_add(
5169 json_object_new_string(ecommunity_str(ecom
)));
5170 json_object_object_add(json
, "export-rts", json_export_rts
);
5173 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5174 json_object_array_add(
5176 json_object_new_string(ecommunity_str(ecom
)));
5177 json_object_object_add(json
, "import-rts", json_import_rts
);
5178 json_object_string_add(
5180 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5184 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5185 json
, JSON_C_TO_STRING_PRETTY
));
5186 json_object_free(json
);
5191 /* import/export rt for l3vni-vrf */
5192 DEFUN (bgp_evpn_vrf_rt
,
5193 bgp_evpn_vrf_rt_cmd
,
5194 "route-target <both|import|export> RT",
5196 "import and export\n"
5199 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5202 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5203 struct ecommunity
*ecomadd
= NULL
;
5208 if (!strcmp(argv
[1]->arg
, "import"))
5209 rt_type
= RT_TYPE_IMPORT
;
5210 else if (!strcmp(argv
[1]->arg
, "export"))
5211 rt_type
= RT_TYPE_EXPORT
;
5212 else if (!strcmp(argv
[1]->arg
, "both"))
5213 rt_type
= RT_TYPE_BOTH
;
5215 vty_out(vty
, "%% Invalid Route Target type\n");
5219 /* Add/update the import route-target */
5220 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5221 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5222 ECOMMUNITY_ROUTE_TARGET
, 0);
5224 vty_out(vty
, "%% Malformed Route Target list\n");
5227 ecommunity_str(ecomadd
);
5229 /* Do nothing if we already have this import route-target */
5230 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5231 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5234 /* Add/update the export route-target */
5235 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5236 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5237 ECOMMUNITY_ROUTE_TARGET
, 0);
5239 vty_out(vty
, "%% Malformed Route Target list\n");
5242 ecommunity_str(ecomadd
);
5244 /* Do nothing if we already have this export route-target */
5245 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5246 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5252 DEFUN (no_bgp_evpn_vrf_rt
,
5253 no_bgp_evpn_vrf_rt_cmd
,
5254 "no route-target <both|import|export> RT",
5257 "import and export\n"
5260 "ASN:XX or A.B.C.D:XX\n")
5262 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5263 int rt_type
, found_ecomdel
;
5264 struct ecommunity
*ecomdel
= NULL
;
5269 if (!strcmp(argv
[2]->arg
, "import"))
5270 rt_type
= RT_TYPE_IMPORT
;
5271 else if (!strcmp(argv
[2]->arg
, "export"))
5272 rt_type
= RT_TYPE_EXPORT
;
5273 else if (!strcmp(argv
[2]->arg
, "both"))
5274 rt_type
= RT_TYPE_BOTH
;
5276 vty_out(vty
, "%% Invalid Route Target type\n");
5280 if (rt_type
== RT_TYPE_IMPORT
) {
5281 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5283 "%% Import RT is not configured for this VRF\n");
5286 } else if (rt_type
== RT_TYPE_EXPORT
) {
5287 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5289 "%% Export RT is not configured for this VRF\n");
5292 } else if (rt_type
== RT_TYPE_BOTH
) {
5293 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5294 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5296 "%% Import/Export RT is not configured for this VRF\n");
5301 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5303 vty_out(vty
, "%% Malformed Route Target list\n");
5306 ecommunity_str(ecomdel
);
5308 if (rt_type
== RT_TYPE_IMPORT
) {
5309 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5312 "%% RT specified does not match configuration for this VRF\n");
5315 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5316 } else if (rt_type
== RT_TYPE_EXPORT
) {
5317 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5320 "%% RT specified does not match configuration for this VRF\n");
5323 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5324 } else if (rt_type
== RT_TYPE_BOTH
) {
5327 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5329 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5333 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5335 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5339 if (!found_ecomdel
) {
5341 "%% RT specified does not match configuration for this VRF\n");
5349 DEFUN (bgp_evpn_vni_rt
,
5350 bgp_evpn_vni_rt_cmd
,
5351 "route-target <both|import|export> RT",
5353 "import and export\n"
5356 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5358 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5359 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5361 struct ecommunity
*ecomadd
= NULL
;
5366 if (!EVPN_ENABLED(bgp
)) {
5368 "This command is only supported under EVPN VRF\n");
5372 if (!strcmp(argv
[1]->text
, "import"))
5373 rt_type
= RT_TYPE_IMPORT
;
5374 else if (!strcmp(argv
[1]->text
, "export"))
5375 rt_type
= RT_TYPE_EXPORT
;
5376 else if (!strcmp(argv
[1]->text
, "both"))
5377 rt_type
= RT_TYPE_BOTH
;
5379 vty_out(vty
, "%% Invalid Route Target type\n");
5383 /* Add/update the import route-target */
5384 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5385 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5386 ECOMMUNITY_ROUTE_TARGET
, 0);
5388 vty_out(vty
, "%% Malformed Route Target list\n");
5391 ecommunity_str(ecomadd
);
5393 /* Do nothing if we already have this import route-target */
5394 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5395 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5398 /* Add/update the export route-target */
5399 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5400 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5401 ECOMMUNITY_ROUTE_TARGET
, 0);
5403 vty_out(vty
, "%% Malformed Route Target list\n");
5406 ecommunity_str(ecomadd
);
5408 /* Do nothing if we already have this export route-target */
5409 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5410 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5416 DEFUN (no_bgp_evpn_vni_rt
,
5417 no_bgp_evpn_vni_rt_cmd
,
5418 "no route-target <both|import|export> RT",
5421 "import and export\n"
5424 "ASN:XX or A.B.C.D:XX\n")
5426 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5427 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5428 int rt_type
, found_ecomdel
;
5429 struct ecommunity
*ecomdel
= NULL
;
5434 if (!EVPN_ENABLED(bgp
)) {
5436 "This command is only supported under EVPN VRF\n");
5440 if (!strcmp(argv
[2]->text
, "import"))
5441 rt_type
= RT_TYPE_IMPORT
;
5442 else if (!strcmp(argv
[2]->text
, "export"))
5443 rt_type
= RT_TYPE_EXPORT
;
5444 else if (!strcmp(argv
[2]->text
, "both"))
5445 rt_type
= RT_TYPE_BOTH
;
5447 vty_out(vty
, "%% Invalid Route Target type\n");
5451 /* The user did "no route-target import", check to see if there are any
5452 * import route-targets configured. */
5453 if (rt_type
== RT_TYPE_IMPORT
) {
5454 if (!is_import_rt_configured(vpn
)) {
5456 "%% Import RT is not configured for this VNI\n");
5459 } else if (rt_type
== RT_TYPE_EXPORT
) {
5460 if (!is_export_rt_configured(vpn
)) {
5462 "%% Export RT is not configured for this VNI\n");
5465 } else if (rt_type
== RT_TYPE_BOTH
) {
5466 if (!is_import_rt_configured(vpn
)
5467 && !is_export_rt_configured(vpn
)) {
5469 "%% Import/Export RT is not configured for this VNI\n");
5474 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5476 vty_out(vty
, "%% Malformed Route Target list\n");
5479 ecommunity_str(ecomdel
);
5481 if (rt_type
== RT_TYPE_IMPORT
) {
5482 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5484 "%% RT specified does not match configuration for this VNI\n");
5487 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5488 } else if (rt_type
== RT_TYPE_EXPORT
) {
5489 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5491 "%% RT specified does not match configuration for this VNI\n");
5494 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5495 } else if (rt_type
== RT_TYPE_BOTH
) {
5498 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5499 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5503 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5504 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5508 if (!found_ecomdel
) {
5510 "%% RT specified does not match configuration for this VNI\n");
5518 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5519 no_bgp_evpn_vni_rt_without_val_cmd
,
5520 "no route-target <import|export>",
5526 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5527 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5533 if (!EVPN_ENABLED(bgp
)) {
5535 "This command is only supported under EVPN VRF\n");
5539 if (!strcmp(argv
[2]->text
, "import")) {
5540 rt_type
= RT_TYPE_IMPORT
;
5541 } else if (!strcmp(argv
[2]->text
, "export")) {
5542 rt_type
= RT_TYPE_EXPORT
;
5544 vty_out(vty
, "%% Invalid Route Target type\n");
5548 /* Check if we should disallow. */
5549 if (rt_type
== RT_TYPE_IMPORT
) {
5550 if (!is_import_rt_configured(vpn
)) {
5552 "%% Import RT is not configured for this VNI\n");
5556 if (!is_export_rt_configured(vpn
)) {
5558 "%% Export RT is not configured for this VNI\n");
5563 /* Unconfigure the RT. */
5564 if (rt_type
== RT_TYPE_IMPORT
)
5565 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5567 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5571 static int vni_cmp(const void **a
, const void **b
)
5573 const struct bgpevpn
*first
= *a
;
5574 const struct bgpevpn
*secnd
= *b
;
5576 return secnd
->vni
- first
->vni
;
5580 * Output EVPN configuration information.
5582 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5585 char buf1
[RD_ADDRSTRLEN
];
5586 char buf2
[INET6_ADDRSTRLEN
];
5589 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5590 struct listnode
*ln
;
5591 struct bgpevpn
*data
;
5593 list_sort(vnilist
, vni_cmp
);
5594 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5595 write_vni_config(vty
, data
);
5597 list_delete(&vnilist
);
5600 if (bgp
->advertise_all_vni
)
5601 vty_out(vty
, " advertise-all-vni\n");
5603 if (bgp
->advertise_autort_rfc8365
)
5604 vty_out(vty
, " autort rfc8365-compatible\n");
5606 if (bgp
->advertise_gw_macip
)
5607 vty_out(vty
, " advertise-default-gw\n");
5609 if (bgp
->evpn_info
->advertise_svi_macip
)
5610 vty_out(vty
, " advertise-svi-ip\n");
5612 if (!bgp
->evpn_info
->dup_addr_detect
)
5613 vty_out(vty
, " no dup-addr-detection\n");
5615 if (bgp
->evpn_info
->dad_max_moves
!=
5616 EVPN_DAD_DEFAULT_MAX_MOVES
||
5617 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5618 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5619 bgp
->evpn_info
->dad_max_moves
,
5620 bgp
->evpn_info
->dad_time
);
5622 if (bgp
->evpn_info
->dad_freeze
) {
5623 if (bgp
->evpn_info
->dad_freeze_time
)
5625 " dup-addr-detection freeze %u\n",
5626 bgp
->evpn_info
->dad_freeze_time
);
5629 " dup-addr-detection freeze permanent\n");
5632 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5633 vty_out(vty
, " flooding disable\n");
5635 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5636 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5637 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5638 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5639 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5641 vty_out(vty
, " advertise ipv4 unicast\n");
5644 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5645 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5646 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5647 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5648 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5650 vty_out(vty
, " advertise ipv6 unicast\n");
5653 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5654 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5655 vty_out(vty
, " default-originate ipv4\n");
5657 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5658 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5659 vty_out(vty
, " default-originate ipv6\n");
5661 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5662 if (!bgp
->evpn_info
->advertise_pip
)
5663 vty_out(vty
, " no advertise-pip\n");
5664 if (bgp
->evpn_info
->advertise_pip
) {
5665 if (bgp
->evpn_info
->pip_ip_static
.s_addr
5667 vty_out(vty
, " advertise-pip ip %s",
5669 &bgp
->evpn_info
->pip_ip_static
,
5670 buf2
, INET_ADDRSTRLEN
));
5672 bgp
->evpn_info
->pip_rmac_static
))) {
5673 char buf
[ETHER_ADDR_STRLEN
];
5675 vty_out(vty
, " mac %s",
5685 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5686 vty_out(vty
, " rd %s\n",
5687 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5689 /* import route-target */
5690 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5692 struct listnode
*node
, *nnode
;
5693 struct ecommunity
*ecom
;
5695 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5697 ecom_str
= ecommunity_ecom2str(
5698 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5699 vty_out(vty
, " route-target import %s\n", ecom_str
);
5700 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5704 /* export route-target */
5705 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5707 struct listnode
*node
, *nnode
;
5708 struct ecommunity
*ecom
;
5710 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5712 ecom_str
= ecommunity_ecom2str(
5713 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5714 vty_out(vty
, " route-target export %s\n", ecom_str
);
5715 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5720 void bgp_ethernetvpn_init(void)
5722 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5723 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5724 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5725 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5726 install_element(VIEW_NODE
,
5727 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5728 install_element(VIEW_NODE
,
5729 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5732 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5735 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5736 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5737 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5738 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5739 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5740 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5741 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5742 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5743 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5744 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5745 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5746 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5747 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5748 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5749 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5750 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5751 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5752 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5753 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5754 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5755 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5758 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5759 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5761 /* "show bgp l2vpn evpn" commands. */
5762 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5763 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5764 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5765 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5766 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5767 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5768 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5769 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5770 install_element(VIEW_NODE
,
5771 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5772 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5773 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5774 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5775 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5777 /* "show bgp evpn" commands. */
5778 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5779 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5780 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5781 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5782 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5783 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5784 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5785 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5786 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5787 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5788 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5789 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5791 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5792 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5793 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5794 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5795 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5796 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5797 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5798 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5799 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5800 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5801 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5802 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5803 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5804 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5805 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5806 install_element(BGP_EVPN_VNI_NODE
,
5807 &bgp_evpn_advertise_default_gw_vni_cmd
);
5808 install_element(BGP_EVPN_VNI_NODE
,
5809 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5810 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5811 install_element(BGP_EVPN_VNI_NODE
,
5812 &no_bgp_evpn_advertise_vni_subnet_cmd
);