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",
390 inet_ntoa(bgp_vrf
->evpn_info
->pip_ip
));
391 json_object_string_add(json
, "sysMac",
392 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
393 buf2
, sizeof(buf2
)));
394 json_object_string_add(json
, "rmac",
395 prefix_mac2str(&bgp_vrf
->rmac
,
396 buf2
, sizeof(buf2
)));
398 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
399 vty_out(vty
, " (known to the kernel)");
402 vty_out(vty
, " Type: %s\n", "L3");
403 vty_out(vty
, " Tenant VRF: %s\n",
404 vrf_id_to_name(bgp_vrf
->vrf_id
));
405 vty_out(vty
, " RD: %s\n",
406 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
407 vty_out(vty
, " Originator IP: %s\n",
408 inet_ntoa(bgp_vrf
->originator_ip
));
409 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
410 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
411 vty_out(vty
, " Advertise-pip: %s\n",
412 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
413 vty_out(vty
, " System-IP: %s\n",
414 inet_ntoa(bgp_vrf
->evpn_info
->pip_ip
));
415 vty_out(vty
, " System-MAC: %s\n",
416 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
417 buf2
, sizeof(buf2
)));
418 vty_out(vty
, " Router-MAC: %s\n",
419 prefix_mac2str(&bgp_vrf
->rmac
,
420 buf2
, sizeof(buf2
)));
424 vty_out(vty
, " Import Route Target:\n");
426 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
427 ecom_str
= ecommunity_ecom2str(ecom
,
428 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
431 json_object_array_add(json_import_rtl
,
432 json_object_new_string(ecom_str
));
434 vty_out(vty
, " %s\n", ecom_str
);
436 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
440 json_object_object_add(json
, "importRts", json_import_rtl
);
442 vty_out(vty
, " Export Route Target:\n");
444 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
445 ecom_str
= ecommunity_ecom2str(ecom
,
446 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
449 json_object_array_add(json_export_rtl
,
450 json_object_new_string(ecom_str
));
452 vty_out(vty
, " %s\n", ecom_str
);
454 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
458 json_object_object_add(json
, "exportRts", json_export_rtl
);
461 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
463 struct in_addr
*vtep
;
464 char buf
[ESI_STR_LEN
];
465 char buf1
[RD_ADDRSTRLEN
];
466 char buf2
[INET6_ADDRSTRLEN
];
467 struct listnode
*node
= NULL
;
468 json_object
*json_vteps
= NULL
;
471 json_vteps
= json_object_new_array();
472 json_object_string_add(json
, "esi",
473 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
474 json_object_string_add(json
, "rd",
475 prefix_rd2str(&es
->prd
, buf1
,
477 json_object_string_add(
478 json
, "originatorIp",
479 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
481 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
482 json_object_array_add(
483 json_vteps
, json_object_new_string(
486 json_object_object_add(json
, "vteps", json_vteps
);
488 vty_out(vty
, "ESI: %s\n",
489 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
490 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
492 vty_out(vty
, " Originator-IP: %s\n",
493 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
495 vty_out(vty
, " VTEP List:\n");
496 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
497 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
502 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
504 char buf1
[RD_ADDRSTRLEN
];
506 struct listnode
*node
, *nnode
;
507 struct ecommunity
*ecom
;
508 json_object
*json_import_rtl
= NULL
;
509 json_object
*json_export_rtl
= NULL
;
510 struct bgp
*bgp_evpn
;
512 bgp_evpn
= bgp_get_evpn();
515 json_import_rtl
= json_object_new_array();
516 json_export_rtl
= json_object_new_array();
517 json_object_int_add(json
, "vni", vpn
->vni
);
518 json_object_string_add(json
, "type", "L2");
519 json_object_string_add(json
, "kernelFlag",
520 is_vni_live(vpn
) ? "Yes" : "No");
521 json_object_string_add(
523 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
524 json_object_string_add(json
, "originatorIp",
525 inet_ntoa(vpn
->originator_ip
));
526 json_object_string_add(json
, "mcastGroup",
527 inet_ntoa(vpn
->mcast_grp
));
528 /* per vni knob is enabled -- Enabled
529 * Global knob is enabled -- Active
530 * default -- Disabled
532 if (!vpn
->advertise_gw_macip
&&
533 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
534 json_object_string_add(json
, "advertiseGatewayMacip",
536 else if (vpn
->advertise_gw_macip
)
537 json_object_string_add(json
, "advertiseGatewayMacip",
540 json_object_string_add(json
, "advertiseGatewayMacip",
542 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
543 bgp_evpn
->evpn_info
->advertise_svi_macip
)
544 json_object_string_add(json
, "advertiseSviMacip",
546 else if (vpn
->advertise_svi_macip
)
547 json_object_string_add(json
, "advertiseSviMacip",
550 json_object_string_add(json
, "advertiseSviMacip",
553 vty_out(vty
, "VNI: %d", vpn
->vni
);
554 if (is_vni_live(vpn
))
555 vty_out(vty
, " (known to the kernel)");
558 vty_out(vty
, " Type: %s\n", "L2");
559 vty_out(vty
, " Tenant-Vrf: %s\n",
560 vrf_id_to_name(vpn
->tenant_vrf_id
));
561 vty_out(vty
, " RD: %s\n",
562 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
563 vty_out(vty
, " Originator IP: %s\n",
564 inet_ntoa(vpn
->originator_ip
));
565 vty_out(vty
, " Mcast group: %s\n",
566 inet_ntoa(vpn
->mcast_grp
));
567 if (!vpn
->advertise_gw_macip
&&
568 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
569 vty_out(vty
, " Advertise-gw-macip : %s\n",
571 else if (vpn
->advertise_gw_macip
)
572 vty_out(vty
, " Advertise-gw-macip : %s\n",
575 vty_out(vty
, " Advertise-gw-macip : %s\n",
577 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
578 bgp_evpn
->evpn_info
->advertise_svi_macip
)
579 vty_out(vty
, " Advertise-svi-macip : %s\n",
581 else if (vpn
->advertise_svi_macip
)
582 vty_out(vty
, " Advertise-svi-macip : %s\n",
585 vty_out(vty
, " Advertise-svi-macip : %s\n",
590 vty_out(vty
, " Import Route Target:\n");
592 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
593 ecom_str
= ecommunity_ecom2str(ecom
,
594 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
597 json_object_array_add(json_import_rtl
,
598 json_object_new_string(ecom_str
));
600 vty_out(vty
, " %s\n", ecom_str
);
602 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
606 json_object_object_add(json
, "importRts", json_import_rtl
);
608 vty_out(vty
, " Export Route Target:\n");
610 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
611 ecom_str
= ecommunity_ecom2str(ecom
,
612 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
615 json_object_array_add(json_export_rtl
,
616 json_object_new_string(ecom_str
));
618 vty_out(vty
, " %s\n", ecom_str
);
620 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
624 json_object_object_add(json
, "exportRts", json_export_rtl
);
627 static void show_esi_routes(struct bgp
*bgp
,
634 struct bgp_path_info
*pi
;
635 uint32_t prefix_cnt
, path_cnt
;
638 prefix_cnt
= path_cnt
= 0;
640 tbl_ver
= es
->route_table
->version
;
641 for (rn
= bgp_table_top(es
->route_table
); rn
;
642 rn
= bgp_route_next(rn
)) {
643 int add_prefix_to_json
= 0;
644 char prefix_str
[BUFSIZ
];
645 json_object
*json_paths
= NULL
;
646 json_object
*json_prefix
= NULL
;
648 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
652 json_prefix
= json_object_new_object();
654 pi
= bgp_node_get_bgp_path_info(rn
);
656 /* Overall header/legend displayed once. */
658 bgp_evpn_show_route_header(vty
, bgp
,
667 json_paths
= json_object_new_array();
669 /* For EVPN, the prefix is displayed for each path (to fit in
670 * with code that already exists).
672 for (; pi
; pi
= pi
->next
) {
673 json_object
*json_path
= NULL
;
676 json_path
= json_object_new_array();
678 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
681 json_object_array_add(json_paths
, json_path
);
684 add_prefix_to_json
= 1;
687 if (json
&& add_prefix_to_json
) {
688 json_object_string_add(json_prefix
, "prefix",
690 json_object_int_add(json_prefix
, "prefixLen",
692 json_object_object_add(json_prefix
, "paths",
694 json_object_object_add(json
, prefix_str
, json_prefix
);
699 json_object_int_add(json
, "numPrefix", prefix_cnt
);
700 json_object_int_add(json
, "numPaths", path_cnt
);
703 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
705 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
706 prefix_cnt
, path_cnt
);
710 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
711 struct vty
*vty
, struct in_addr vtep_ip
,
712 json_object
*json
, int detail
)
715 struct bgp_path_info
*pi
;
716 struct bgp_table
*table
;
717 int header
= detail
? 0 : 1;
719 uint32_t prefix_cnt
, path_cnt
;
721 prefix_cnt
= path_cnt
= 0;
723 table
= vpn
->route_table
;
724 tbl_ver
= table
->version
;
725 for (rn
= bgp_table_top(table
); rn
;
726 rn
= bgp_route_next(rn
)) {
727 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
728 int add_prefix_to_json
= 0;
729 char prefix_str
[BUFSIZ
];
730 json_object
*json_paths
= NULL
;
731 json_object
*json_prefix
= NULL
;
733 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
736 if (type
&& evp
->prefix
.route_type
!= type
)
740 json_prefix
= json_object_new_object();
742 pi
= bgp_node_get_bgp_path_info(rn
);
744 /* Overall header/legend displayed once. */
746 bgp_evpn_show_route_header(vty
, bgp
,
755 json_paths
= json_object_new_array();
757 /* For EVPN, the prefix is displayed for each path (to fit in
758 * with code that already exists).
760 for (; pi
; pi
= pi
->next
) {
761 json_object
*json_path
= NULL
;
764 && !IPV4_ADDR_SAME(&(vtep_ip
),
765 &(pi
->attr
->nexthop
)))
769 json_path
= json_object_new_array();
772 route_vty_out_detail(vty
, bgp
, rn
, pi
,
773 AFI_L2VPN
, SAFI_EVPN
,
776 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
780 json_object_array_add(json_paths
, json_path
);
783 add_prefix_to_json
= 1;
786 if (json
&& add_prefix_to_json
) {
787 json_object_string_add(json_prefix
, "prefix",
789 json_object_int_add(json_prefix
, "prefixLen",
791 json_object_object_add(json_prefix
, "paths",
793 json_object_object_add(json
, prefix_str
, json_prefix
);
798 json_object_int_add(json
, "numPrefix", prefix_cnt
);
799 json_object_int_add(json
, "numPaths", path_cnt
);
802 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
803 type
? "(of requested type) " : "");
805 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
806 prefix_cnt
, path_cnt
,
807 type
? " (of requested type)" : "");
812 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
814 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
815 struct vni_walk_ctx
*wctx
= arg
;
816 struct vty
*vty
= wctx
->vty
;
817 json_object
*json
= wctx
->json
;
818 json_object
*json_vni
= NULL
;
819 char vni_str
[VNI_STR_LEN
];
821 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
823 json_vni
= json_object_new_object();
824 json_object_int_add(json_vni
, "vni", vpn
->vni
);
826 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
829 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
833 json_object_object_add(json
, vni_str
, json_vni
);
836 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
839 json_object
*json_vni
= NULL
;
840 json_object
*json_import_rtl
= NULL
;
841 json_object
*json_export_rtl
= NULL
;
843 char buf2
[INET6_ADDRSTRLEN
];
846 struct listnode
*node
, *nnode
;
847 struct ecommunity
*ecom
;
853 json_vni
= json_object_new_object();
854 json_import_rtl
= json_object_new_array();
855 json_export_rtl
= json_object_new_array();
858 /* if an l3vni is present in bgp it is live */
863 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
864 json_object_string_add(json_vni
, "type", "L3");
865 json_object_string_add(json_vni
, "inKernel", "True");
866 json_object_string_add(json_vni
, "originatorIp",
867 inet_ntoa(bgp
->originator_ip
));
868 json_object_string_add(
870 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
872 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
873 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
876 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
877 ecom_str
= ecommunity_ecom2str(ecom
,
878 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
881 json_object_array_add(json_import_rtl
,
882 json_object_new_string(ecom_str
));
884 if (listcount(bgp
->vrf_import_rtl
) > 1)
885 sprintf(rt_buf
, "%s, ...", ecom_str
);
887 sprintf(rt_buf
, "%s", ecom_str
);
888 vty_out(vty
, " %-25s", rt_buf
);
891 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
893 /* If there are multiple import RTs we break here and show only
900 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
902 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
903 ecom_str
= ecommunity_ecom2str(ecom
,
904 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
907 json_object_array_add(json_export_rtl
,
908 json_object_new_string(ecom_str
));
910 if (listcount(bgp
->vrf_export_rtl
) > 1)
911 sprintf(rt_buf
, "%s, ...", ecom_str
);
913 sprintf(rt_buf
, "%s", ecom_str
);
914 vty_out(vty
, " %-25s", rt_buf
);
917 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
919 /* If there are multiple export RTs we break here and show only
926 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
929 char vni_str
[VNI_STR_LEN
];
931 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
932 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
933 json_object_object_add(json
, vni_str
, json_vni
);
939 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
941 char buf
[ESI_STR_LEN
];
942 char buf1
[RD_ADDRSTRLEN
];
943 char buf2
[INET6_ADDRSTRLEN
];
944 struct in_addr
*vtep
= NULL
;
945 struct vty
*vty
= args
[0];
946 json_object
*json
= args
[1];
947 json_object
*json_vteps
= NULL
;
948 struct listnode
*node
= NULL
;
949 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
952 json_vteps
= json_object_new_array();
953 json_object_string_add(json
, "esi",
954 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
955 json_object_string_add(json
, "type",
956 is_es_local(es
) ? "Local" : "Remote");
957 json_object_string_add(json
, "rd",
958 prefix_rd2str(&es
->prd
, buf1
,
960 json_object_string_add(
961 json
, "originatorIp",
962 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
964 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
965 json_object_array_add(json_vteps
,
966 json_object_new_string(
969 json_object_object_add(json
, "vteps", json_vteps
);
971 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
972 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
973 is_es_local(es
) ? "Local" : "Remote",
974 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
975 ipaddr2str(&es
->originator_ip
, buf2
,
977 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
981 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
985 json_object
*json_vni
= NULL
;
986 json_object
*json_import_rtl
= NULL
;
987 json_object
*json_export_rtl
= NULL
;
988 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
990 char buf2
[RD_ADDRSTRLEN
];
993 struct listnode
*node
, *nnode
;
994 struct ecommunity
*ecom
;
1000 json_vni
= json_object_new_object();
1001 json_import_rtl
= json_object_new_array();
1002 json_export_rtl
= json_object_new_array();
1006 if (is_vni_live(vpn
))
1010 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1011 json_object_string_add(json_vni
, "type", "L2");
1012 json_object_string_add(json_vni
, "inKernel",
1013 is_vni_live(vpn
) ? "True" : "False");
1014 json_object_string_add(json_vni
, "originatorIp",
1015 inet_ntoa(vpn
->originator_ip
));
1016 json_object_string_add(json_vni
, "originatorIp",
1017 inet_ntoa(vpn
->originator_ip
));
1018 json_object_string_add(
1020 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1022 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1023 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1026 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1027 ecom_str
= ecommunity_ecom2str(ecom
,
1028 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1031 json_object_array_add(json_import_rtl
,
1032 json_object_new_string(ecom_str
));
1034 if (listcount(vpn
->import_rtl
) > 1)
1035 sprintf(rt_buf
, "%s, ...", ecom_str
);
1037 sprintf(rt_buf
, "%s", ecom_str
);
1038 vty_out(vty
, " %-25s", rt_buf
);
1041 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1043 /* If there are multiple import RTs we break here and show only
1050 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1052 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1053 ecom_str
= ecommunity_ecom2str(ecom
,
1054 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1057 json_object_array_add(json_export_rtl
,
1058 json_object_new_string(ecom_str
));
1060 if (listcount(vpn
->export_rtl
) > 1)
1061 sprintf(rt_buf
, "%s, ...", ecom_str
);
1063 sprintf(rt_buf
, "%s", ecom_str
);
1064 vty_out(vty
, " %-25s", rt_buf
);
1067 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1069 /* If there are multiple export RTs we break here and show only
1076 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1079 char vni_str
[VNI_STR_LEN
];
1081 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1082 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1083 json_object_object_add(json
, vni_str
, json_vni
);
1089 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1090 enum bgp_show_type type
, void *output_arg
,
1091 int option
, bool use_json
)
1093 afi_t afi
= AFI_L2VPN
;
1095 struct bgp_table
*table
;
1096 struct bgp_node
*rn
;
1097 struct bgp_node
*rm
;
1098 struct bgp_path_info
*pi
;
1101 char rd_str
[RD_ADDRSTRLEN
];
1105 unsigned long output_count
= 0;
1106 unsigned long total_count
= 0;
1107 json_object
*json
= NULL
;
1108 json_object
*json_array
= NULL
;
1109 json_object
*json_prefix_info
= NULL
;
1111 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1113 bgp
= bgp_get_evpn();
1116 vty_out(vty
, "No BGP process is configured\n");
1118 vty_out(vty
, "{}\n");
1123 json
= json_object_new_object();
1125 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1126 rn
= bgp_route_next(rn
)) {
1128 json_object
*json_nroute
= NULL
;
1130 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1133 table
= bgp_node_get_bgp_table_info(rn
);
1138 tbl_ver
= table
->version
;
1140 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1141 pi
= bgp_node_get_bgp_path_info(rm
);
1146 for (; pi
; pi
= pi
->next
) {
1148 if (type
== bgp_show_type_neighbor
) {
1149 struct peer
*peer
= output_arg
;
1151 if (peer_cmp(peer
, pi
->peer
) != 0)
1154 if (type
== bgp_show_type_lcommunity_exact
) {
1155 struct lcommunity
*lcom
= output_arg
;
1157 if (!pi
->attr
->lcommunity
||
1159 pi
->attr
->lcommunity
, lcom
))
1162 if (type
== bgp_show_type_lcommunity
) {
1163 struct lcommunity
*lcom
= output_arg
;
1165 if (!pi
->attr
->lcommunity
||
1167 pi
->attr
->lcommunity
, lcom
))
1170 if (type
== bgp_show_type_community
) {
1171 struct community
*com
= output_arg
;
1173 if (!pi
->attr
->community
||
1175 pi
->attr
->community
, com
))
1178 if (type
== bgp_show_type_community_exact
) {
1179 struct community
*com
= output_arg
;
1181 if (!pi
->attr
->community
||
1183 pi
->attr
->community
, com
))
1188 json_object_int_add(
1189 json
, "bgpTableVersion",
1191 json_object_string_add(
1196 json_object_int_add(
1199 bgp
->default_local_pref
);
1200 json_object_int_add(
1204 if (option
== SHOW_DISPLAY_TAGS
)
1209 == SHOW_DISPLAY_OVERLAY
)
1213 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1221 json_object_new_object();
1222 bgp_evpn_show_route_rd_header(vty
, rn
,
1223 json_nroute
, rd_str
,
1227 if (use_json
&& !json_array
)
1228 json_array
= json_object_new_array();
1230 if (option
== SHOW_DISPLAY_TAGS
)
1231 route_vty_out_tag(vty
, &rm
->p
, pi
,
1232 no_display
, SAFI_EVPN
,
1234 else if (option
== SHOW_DISPLAY_OVERLAY
)
1235 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1239 route_vty_out(vty
, &rm
->p
, pi
,
1240 no_display
, SAFI_EVPN
,
1248 if (use_json
&& json_array
) {
1249 json_prefix_info
= json_object_new_object();
1251 json_object_string_add(json_prefix_info
,
1252 "prefix", bgp_evpn_route2str(
1253 (struct prefix_evpn
*)&rm
->p
, buf
,
1256 json_object_int_add(json_prefix_info
,
1257 "prefixLen", rm
->p
.prefixlen
);
1259 json_object_object_add(json_prefix_info
,
1260 "paths", json_array
);
1261 json_object_object_add(json_nroute
, buf
,
1267 if (use_json
&& json_nroute
)
1268 json_object_object_add(json
, rd_str
, json_nroute
);
1272 json_object_int_add(json
, "numPrefix", output_count
);
1273 json_object_int_add(json
, "totalPrefix", total_count
);
1274 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1275 json
, JSON_C_TO_STRING_PRETTY
));
1276 json_object_free(json
);
1278 if (output_count
== 0)
1279 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1283 "\nDisplayed %ld out of %ld total prefixes\n",
1284 output_count
, total_count
);
1289 DEFUN(show_ip_bgp_l2vpn_evpn
,
1290 show_ip_bgp_l2vpn_evpn_cmd
,
1291 "show [ip] bgp l2vpn evpn [json]",
1292 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1294 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1295 use_json(argc
, argv
));
1298 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1299 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1300 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1306 "Display information for a route distinguisher\n"
1307 "VPN Route Distinguisher\n" JSON_STR
)
1309 int idx_ext_community
= 0;
1311 struct prefix_rd prd
;
1313 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1315 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1317 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1320 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1321 use_json(argc
, argv
));
1324 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1325 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1326 "show [ip] bgp l2vpn evpn all tags",
1332 "Display information about all EVPN NLRIs\n"
1333 "Display BGP tags for prefixes\n")
1335 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1339 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1340 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1341 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1347 "Display information for a route distinguisher\n"
1348 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1350 int idx_ext_community
= 0;
1352 struct prefix_rd prd
;
1354 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1356 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1358 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1361 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1365 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1366 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1367 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1373 "Detailed information on TCP and BGP neighbor connections\n"
1374 "IPv4 Neighbor to display information about\n"
1375 "IPv6 Neighbor to display information about\n"
1376 "Neighbor on BGP configured interface\n"
1377 "Display routes learned from neighbor\n" JSON_STR
)
1381 char *peerstr
= NULL
;
1382 bool uj
= use_json(argc
, argv
);
1383 afi_t afi
= AFI_L2VPN
;
1384 safi_t safi
= SAFI_EVPN
;
1385 struct bgp
*bgp
= NULL
;
1387 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1390 vty_out(vty
, "No index\n");
1394 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1395 argv_find(argv
, argc
, "neighbors", &idx
);
1396 peerstr
= argv
[++idx
]->arg
;
1398 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1401 json_object
*json_no
= NULL
;
1402 json_no
= json_object_new_object();
1403 json_object_string_add(json_no
, "warning",
1404 "Malformed address");
1405 vty_out(vty
, "%s\n",
1406 json_object_to_json_string(json_no
));
1407 json_object_free(json_no
);
1409 vty_out(vty
, "Malformed address: %s\n",
1413 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1415 json_object
*json_no
= NULL
;
1416 json_no
= json_object_new_object();
1417 json_object_string_add(
1419 "No such neighbor or address family");
1420 vty_out(vty
, "%s\n",
1421 json_object_to_json_string(json_no
));
1422 json_object_free(json_no
);
1424 vty_out(vty
, "%% No such neighbor or address family\n");
1428 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1432 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1433 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1434 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1440 "Display information for a route distinguisher\n"
1441 "VPN Route Distinguisher\n"
1442 "Detailed information on TCP and BGP neighbor connections\n"
1443 "IPv4 Neighbor to display information about\n"
1444 "IPv6 Neighbor to display information about\n"
1445 "Neighbor on BGP configured interface\n"
1446 "Display routes learned from neighbor\n" JSON_STR
)
1448 int idx_ext_community
= 0;
1452 char *peerstr
= NULL
;
1453 struct prefix_rd prd
;
1454 bool uj
= use_json(argc
, argv
);
1455 afi_t afi
= AFI_L2VPN
;
1456 safi_t safi
= SAFI_EVPN
;
1457 struct bgp
*bgp
= NULL
;
1459 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1462 vty_out(vty
, "No index\n");
1466 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1467 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1470 json_object
*json_no
= NULL
;
1471 json_no
= json_object_new_object();
1472 json_object_string_add(json_no
, "warning",
1473 "Malformed Route Distinguisher");
1474 vty_out(vty
, "%s\n",
1475 json_object_to_json_string(json_no
));
1476 json_object_free(json_no
);
1478 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1482 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1483 argv_find(argv
, argc
, "neighbors", &idx
);
1484 peerstr
= argv
[++idx
]->arg
;
1486 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1489 json_object
*json_no
= NULL
;
1490 json_no
= json_object_new_object();
1491 json_object_string_add(json_no
, "warning",
1492 "Malformed address");
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 address: %s\n",
1501 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1503 json_object
*json_no
= NULL
;
1504 json_no
= json_object_new_object();
1505 json_object_string_add(
1507 "No such neighbor or address family");
1508 vty_out(vty
, "%s\n",
1509 json_object_to_json_string(json_no
));
1510 json_object_free(json_no
);
1512 vty_out(vty
, "%% No such neighbor or address family\n");
1516 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1520 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1521 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1522 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1528 "Detailed information on TCP and BGP neighbor connections\n"
1529 "IPv4 Neighbor to display information about\n"
1530 "IPv6 Neighbor to display information about\n"
1531 "Neighbor on BGP configured interface\n"
1532 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1536 bool uj
= use_json(argc
, argv
);
1537 struct bgp
*bgp
= NULL
;
1538 afi_t afi
= AFI_L2VPN
;
1539 safi_t safi
= SAFI_EVPN
;
1540 char *peerstr
= NULL
;
1545 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1548 vty_out(vty
, "No index\n");
1552 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1553 argv_find(argv
, argc
, "neighbors", &idx
);
1554 peerstr
= argv
[++idx
]->arg
;
1556 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1559 json_object
*json_no
= NULL
;
1560 json_no
= json_object_new_object();
1561 json_object_string_add(json_no
, "warning",
1562 "Malformed address");
1563 vty_out(vty
, "%s\n",
1564 json_object_to_json_string(json_no
));
1565 json_object_free(json_no
);
1567 vty_out(vty
, "Malformed address: %s\n",
1571 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1573 json_object
*json_no
= NULL
;
1574 json_no
= json_object_new_object();
1575 json_object_string_add(
1577 "No such neighbor or address family");
1578 vty_out(vty
, "%s\n",
1579 json_object_to_json_string(json_no
));
1580 json_object_free(json_no
);
1582 vty_out(vty
, "%% No such neighbor or address family\n");
1586 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1589 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1590 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1591 "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]",
1597 "Display information for a route distinguisher\n"
1598 "VPN Route Distinguisher\n"
1599 "Detailed information on TCP and BGP neighbor connections\n"
1600 "IPv4 Neighbor to display information about\n"
1601 "IPv6 Neighbor to display information about\n"
1602 "Neighbor on BGP configured interface\n"
1603 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1605 int idx_ext_community
= 0;
1609 struct prefix_rd prd
;
1610 struct bgp
*bgp
= NULL
;
1611 bool uj
= use_json(argc
, argv
);
1612 char *peerstr
= NULL
;
1613 afi_t afi
= AFI_L2VPN
;
1614 safi_t safi
= SAFI_EVPN
;
1622 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1625 vty_out(vty
, "No index\n");
1629 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1631 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1632 argv_find(argv
, argc
, "neighbors", &idx
);
1633 peerstr
= argv
[++idx
]->arg
;
1635 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1638 json_object
*json_no
= NULL
;
1639 json_no
= json_object_new_object();
1640 json_object_string_add(json_no
, "warning",
1641 "Malformed address");
1642 vty_out(vty
, "%s\n",
1643 json_object_to_json_string(json_no
));
1644 json_object_free(json_no
);
1646 vty_out(vty
, "Malformed address: %s\n",
1650 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1652 json_object
*json_no
= NULL
;
1653 json_no
= json_object_new_object();
1654 json_object_string_add(
1656 "No such neighbor or address family");
1657 vty_out(vty
, "%s\n",
1658 json_object_to_json_string(json_no
));
1659 json_object_free(json_no
);
1661 vty_out(vty
, "%% No such neighbor or address family\n");
1665 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1668 json_object
*json_no
= NULL
;
1669 json_no
= json_object_new_object();
1670 json_object_string_add(json_no
, "warning",
1671 "Malformed Route Distinguisher");
1672 vty_out(vty
, "%s\n",
1673 json_object_to_json_string(json_no
));
1674 json_object_free(json_no
);
1676 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1680 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1683 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1684 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1685 "show [ip] bgp l2vpn evpn all overlay [json]",
1691 "Display information about all EVPN NLRIs\n"
1692 "Display BGP Overlay Information for prefixes\n"
1695 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1696 SHOW_DISPLAY_OVERLAY
,
1697 use_json(argc
, argv
));
1700 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1701 show_ip_bgp_evpn_rd_overlay_cmd
,
1702 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1708 "Display information for a route distinguisher\n"
1709 "VPN Route Distinguisher\n"
1710 "Display BGP Overlay Information for prefixes\n")
1712 int idx_ext_community
= 0;
1714 struct prefix_rd prd
;
1716 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1718 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1720 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1723 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1724 SHOW_DISPLAY_OVERLAY
,
1725 use_json(argc
, argv
));
1728 DEFUN(show_bgp_l2vpn_evpn_com
,
1729 show_bgp_l2vpn_evpn_com_cmd
,
1730 "show bgp l2vpn evpn \
1731 <community AA:NN|large-community AA:BB:CC> \
1732 [exact-match] [json]",
1737 "Display routes matching the community\n"
1738 "Community number where AA and NN are (0-65535)\n"
1739 "Display routes matching the large-community\n"
1740 "List of large-community numbers\n"
1741 "Exact match of the communities\n"
1746 const char *clist_number_or_name
;
1747 int show_type
= bgp_show_type_normal
;
1748 struct community
*com
;
1749 struct lcommunity
*lcom
;
1751 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1752 clist_number_or_name
= argv
[++idx
]->arg
;
1753 show_type
= bgp_show_type_lcommunity
;
1755 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1756 show_type
= bgp_show_type_lcommunity_exact
;
1758 lcom
= lcommunity_str2com(clist_number_or_name
);
1760 vty_out(vty
, "%% Large-community malformed\n");
1764 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1765 SHOW_DISPLAY_STANDARD
,
1766 use_json(argc
, argv
));
1768 lcommunity_free(&lcom
);
1769 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1770 clist_number_or_name
= argv
[++idx
]->arg
;
1771 show_type
= bgp_show_type_community
;
1773 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1774 show_type
= bgp_show_type_community_exact
;
1776 com
= community_str2com(clist_number_or_name
);
1779 vty_out(vty
, "%% Community malformed: %s\n",
1780 clist_number_or_name
);
1784 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1785 SHOW_DISPLAY_STANDARD
,
1786 use_json(argc
, argv
));
1787 community_free(&com
);
1793 /* For testing purpose, static route of EVPN RT-5. */
1794 DEFUN(evpnrt5_network
,
1795 evpnrt5_network_cmd
,
1796 "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]",
1797 "Specify a network to announce via BGP\n"
1800 "Specify Route Distinguisher\n"
1801 "VPN Route Distinguisher\n"
1803 "Ethernet Tag Value\n"
1806 "Ethernet Segment Identifier\n"
1807 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1809 "Gateway IP ( A.B.C.D )\n"
1810 "Gateway IPv6 ( X:X::X:X )\n"
1811 "Router Mac Ext Comm\n"
1812 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1813 "Route-map to modify the attributes\n"
1814 "Name of the route map\n")
1816 int idx_ipv4_prefixlen
= 1;
1817 int idx_route_distinguisher
= 3;
1822 int idx_routermac
= 13;
1824 return bgp_static_set_safi(
1825 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1826 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1827 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1828 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1829 argv
[idx_routermac
]->arg
);
1832 /* For testing purpose, static route of EVPN RT-5. */
1833 DEFUN(no_evpnrt5_network
,
1834 no_evpnrt5_network_cmd
,
1835 "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>",
1837 "Specify a network to announce via BGP\n"
1840 "Specify Route Distinguisher\n"
1841 "VPN Route Distinguisher\n"
1843 "Ethernet Tag Value\n"
1846 "Ethernet Segment Identifier\n"
1847 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1848 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1850 int idx_ipv4_prefixlen
= 2;
1851 int idx_ext_community
= 4;
1856 return bgp_static_unset_safi(
1857 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1858 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1859 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1860 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1863 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1865 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1868 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1870 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1874 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1875 * check that this is a change.
1877 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1878 struct ecommunity
*ecomadd
)
1880 /* If the VNI is "live", we need to uninstall routes using the current
1881 * import RT(s) first before we update the import RT, and subsequently
1884 if (is_vni_live(vpn
))
1885 bgp_evpn_uninstall_routes(bgp
, vpn
);
1887 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1888 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1890 /* If the auto route-target is in use we must remove it */
1891 evpn_import_rt_delete_auto(bgp
, vpn
);
1893 /* Add new RT and rebuild the RT to VNI mapping */
1894 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1896 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1897 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1899 /* Install routes that match new import RT */
1900 if (is_vni_live(vpn
))
1901 bgp_evpn_install_routes(bgp
, vpn
);
1905 * Unconfigure Import RT(s) for a VNI (vty handler).
1907 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1908 struct ecommunity
*ecomdel
)
1910 struct listnode
*node
, *nnode
, *node_to_del
;
1911 struct ecommunity
*ecom
;
1913 /* Along the lines of "configure" except we have to reset to the
1916 if (is_vni_live(vpn
))
1917 bgp_evpn_uninstall_routes(bgp
, vpn
);
1919 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1920 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1922 /* Delete all import RTs */
1923 if (ecomdel
== NULL
) {
1924 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1925 ecommunity_free(&ecom
);
1926 list_delete_node(vpn
->import_rtl
, node
);
1930 /* Delete a specific import RT */
1934 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1935 if (ecommunity_match(ecom
, ecomdel
)) {
1936 ecommunity_free(&ecom
);
1943 list_delete_node(vpn
->import_rtl
, node_to_del
);
1946 assert(vpn
->import_rtl
);
1947 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1948 if (list_isempty(vpn
->import_rtl
)) {
1949 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1950 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1952 /* Rebuild the RT to VNI mapping */
1954 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1956 /* Install routes that match new import RT */
1957 if (is_vni_live(vpn
))
1958 bgp_evpn_install_routes(bgp
, vpn
);
1962 * Configure the Export RT for a VNI (vty handler). Caller expected to
1963 * check that this is a change. Note that only a single export RT is
1964 * allowed for a VNI and any change to configuration is implemented as
1965 * a "replace" (similar to other configuration).
1967 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1968 struct ecommunity
*ecomadd
)
1970 /* If the auto route-target is in use we must remove it */
1971 evpn_export_rt_delete_auto(bgp
, vpn
);
1973 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1974 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1976 if (is_vni_live(vpn
))
1977 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1981 * Unconfigure the Export RT for a VNI (vty handler)
1983 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1984 struct ecommunity
*ecomdel
)
1986 struct listnode
*node
, *nnode
, *node_to_del
;
1987 struct ecommunity
*ecom
;
1989 /* Delete all export RTs */
1990 if (ecomdel
== NULL
) {
1991 /* Reset to default and process all routes. */
1992 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1993 ecommunity_free(&ecom
);
1994 list_delete_node(vpn
->export_rtl
, node
);
1998 /* Delete a specific export RT */
2002 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2003 if (ecommunity_match(ecom
, ecomdel
)) {
2004 ecommunity_free(&ecom
);
2011 list_delete_node(vpn
->export_rtl
, node_to_del
);
2014 assert(vpn
->export_rtl
);
2015 if (list_isempty(vpn
->export_rtl
)) {
2016 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2017 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2020 if (is_vni_live(vpn
))
2021 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2025 * Configure RD for VRF
2027 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2029 /* If we have already advertise type-5 routes with a diffrent RD, we
2030 * have to delete and withdraw them firs
2032 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2035 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2036 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2038 /* We have a new RD for VRF.
2039 * Advertise all type-5 routes again with the new RD
2041 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2045 * Unconfigure RD for VRF
2047 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2049 /* If we have already advertise type-5 routes with a diffrent RD, we
2050 * have to delete and withdraw them firs
2052 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2054 /* fall back to default RD */
2055 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2056 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2058 /* We have a new RD for VRF.
2059 * Advertise all type-5 routes again with the new RD
2061 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2065 * Configure RD for a VNI (vty handler)
2067 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2068 struct prefix_rd
*rd
)
2070 /* If the VNI is "live", we need to delete and withdraw this VNI's
2071 * local routes with the prior RD first. Then, after updating RD,
2072 * need to re-advertise.
2074 if (is_vni_live(vpn
))
2075 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2078 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2079 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2081 if (is_vni_live(vpn
))
2082 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2086 * Unconfigure RD for a VNI (vty handler)
2088 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2090 /* If the VNI is "live", we need to delete and withdraw this VNI's
2091 * local routes with the prior RD first. Then, after resetting RD
2092 * to automatic value, need to re-advertise.
2094 if (is_vni_live(vpn
))
2095 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2097 /* reset RD to default */
2098 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2100 if (is_vni_live(vpn
))
2101 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2105 * Create VNI, if not already present (VTY handler). Mark as configured.
2107 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2109 struct bgpevpn
*vpn
;
2110 struct in_addr mcast_grp
= {INADDR_ANY
};
2115 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2117 /* Check if this L2VNI is already configured as L3VNI */
2118 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2121 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2126 /* tenant vrf will be updated when we get local_vni_add from
2129 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2133 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2139 /* Mark as configured. */
2140 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2145 * Delete VNI. If VNI does not exist in the system (i.e., just
2146 * configuration), all that is needed is to free it. Otherwise,
2147 * any parameters configured for the VNI need to be reset (with
2148 * appropriate action) and the VNI marked as unconfigured; the
2149 * VNI will continue to exist, purely as a "learnt" entity.
2151 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2153 assert(bgp
->vnihash
);
2155 if (!is_vni_live(vpn
)) {
2156 bgp_evpn_free(bgp
, vpn
);
2160 /* We need to take the unconfigure action for each parameter of this VNI
2161 * that is configured. Some optimization is possible, but not worth the
2162 * additional code for an operation that should be pretty rare.
2164 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2166 /* First, deal with the export side - RD and export RT changes. */
2167 if (is_rd_configured(vpn
))
2168 evpn_unconfigure_rd(bgp
, vpn
);
2169 if (is_export_rt_configured(vpn
))
2170 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2172 /* Next, deal with the import side. */
2173 if (is_import_rt_configured(vpn
))
2174 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2180 * Display import RT mapping to VRFs (vty handler)
2181 * bgp_evpn: evpn bgp instance
2183 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2191 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2192 (void (*)(struct hash_bucket
*,
2193 void *))show_vrf_import_rt_entry
,
2198 * Display import RT mapping to VNIs (vty handler)
2200 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2209 bgp
->import_rt_hash
,
2210 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2215 * Display EVPN routes for all VNIs - vty handler.
2217 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2218 struct in_addr vtep_ip
, json_object
*json
,
2222 struct vni_walk_ctx wctx
;
2224 num_vnis
= hashcount(bgp
->vnihash
);
2227 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2230 wctx
.vtep_ip
= vtep_ip
;
2232 wctx
.detail
= detail
;
2233 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2234 void *))show_vni_routes_hash
,
2239 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2241 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2242 vni_t vni
, struct in_addr orig_ip
,
2245 struct bgpevpn
*vpn
;
2246 struct prefix_evpn p
;
2247 struct bgp_node
*rn
;
2248 struct bgp_path_info
*pi
;
2249 uint32_t path_cnt
= 0;
2252 json_object
*json_paths
= NULL
;
2258 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2260 vty_out(vty
, "VNI not found\n");
2264 /* See if route exists. */
2265 build_evpn_type3_prefix(&p
, orig_ip
);
2266 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2267 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2269 vty_out(vty
, "%% Network not in table\n");
2274 json_paths
= json_object_new_array();
2276 /* Prefix and num paths displayed once per prefix. */
2277 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2279 /* Display each path for this prefix. */
2280 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2281 json_object
*json_path
= NULL
;
2284 json_path
= json_object_new_array();
2286 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2290 json_object_array_add(json_paths
, json_path
);
2297 json_object_object_add(json
, "paths", json_paths
);
2299 json_object_int_add(json
, "numPaths", path_cnt
);
2301 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2307 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2308 * By definition, only matching type-2 route will be displayed.
2310 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2311 vni_t vni
, struct ethaddr
*mac
,
2312 struct ipaddr
*ip
, json_object
*json
)
2314 struct bgpevpn
*vpn
;
2315 struct prefix_evpn p
;
2316 struct bgp_node
*rn
;
2317 struct bgp_path_info
*pi
;
2318 uint32_t path_cnt
= 0;
2321 json_object
*json_paths
= NULL
;
2327 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2330 vty_out(vty
, "VNI not found\n");
2334 /* See if route exists. Look for both non-sticky and sticky. */
2335 build_evpn_type2_prefix(&p
, mac
, ip
);
2336 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2337 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2339 vty_out(vty
, "%% Network not in table\n");
2344 json_paths
= json_object_new_array();
2346 /* Prefix and num paths displayed once per prefix. */
2347 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2349 /* Display each path for this prefix. */
2350 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2351 json_object
*json_path
= NULL
;
2354 json_path
= json_object_new_array();
2356 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2360 json_object_array_add(json_paths
, json_path
);
2367 json_object_object_add(json
, "paths", json_paths
);
2369 json_object_int_add(json
, "numPaths", path_cnt
);
2371 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2376 /* Disaplay EVPN routes for a ESI - VTY handler */
2377 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2378 esi_t
*esi
, json_object
*json
)
2380 struct evpnes
*es
= NULL
;
2383 es
= bgp_evpn_lookup_es(bgp
, esi
);
2386 vty_out(vty
, "ESI not found\n");
2390 show_esi_routes(bgp
, es
, vty
, json
);
2394 * Display EVPN routes for a VNI - vty handler.
2395 * If 'type' is non-zero, only routes matching that type are shown.
2396 * If the vtep_ip is non zero, only routes behind that vtep are shown
2398 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2399 int type
, struct in_addr vtep_ip
,
2402 struct bgpevpn
*vpn
;
2405 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2408 vty_out(vty
, "VNI not found\n");
2412 /* Walk this VNI's route table and display appropriate routes. */
2413 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2417 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2418 * IP (vty handler). By definition, only matching type-2 route will be
2421 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2422 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2423 struct ipaddr
*ip
, json_object
*json
)
2425 struct prefix_evpn p
;
2426 struct bgp_node
*rn
;
2427 struct bgp_path_info
*pi
;
2430 uint32_t path_cnt
= 0;
2431 json_object
*json_paths
= NULL
;
2432 char prefix_str
[BUFSIZ
];
2437 /* See if route exists. Look for both non-sticky and sticky. */
2438 build_evpn_type2_prefix(&p
, mac
, ip
);
2439 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2440 (struct prefix
*)&p
, prd
);
2441 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2443 vty_out(vty
, "%% Network not in table\n");
2447 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2448 sizeof(prefix_str
));
2450 /* Prefix and num paths displayed once per prefix. */
2451 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2454 json_paths
= json_object_new_array();
2456 /* Display each path for this prefix. */
2457 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2458 json_object
*json_path
= NULL
;
2461 json_path
= json_object_new_array();
2463 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2467 json_object_array_add(json_paths
, json_path
);
2472 if (json
&& path_cnt
) {
2474 json_object_object_add(json
, prefix_str
, json_paths
);
2475 json_object_int_add(json
, "numPaths", path_cnt
);
2477 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2483 * Display BGP EVPN routing table -- for specific RD (vty handler)
2484 * If 'type' is non-zero, only routes matching that type are shown.
2486 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2487 struct prefix_rd
*prd
, int type
,
2490 struct bgp_node
*rd_rn
;
2491 struct bgp_table
*table
;
2492 struct bgp_node
*rn
;
2493 struct bgp_path_info
*pi
;
2497 uint32_t prefix_cnt
, path_cnt
;
2498 char rd_str
[RD_ADDRSTRLEN
];
2499 json_object
*json_rd
= NULL
;
2500 int add_rd_to_json
= 0;
2504 prefix_cnt
= path_cnt
= 0;
2506 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2508 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2512 table
= bgp_node_get_bgp_table_info(rd_rn
);
2517 json_rd
= json_object_new_object();
2518 json_object_string_add(json_rd
, "rd", rd_str
);
2521 /* Display all prefixes with this RD. */
2522 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2523 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2524 json_object
*json_prefix
= NULL
;
2525 json_object
*json_paths
= NULL
;
2526 char prefix_str
[BUFSIZ
];
2527 int add_prefix_to_json
= 0;
2529 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2530 sizeof(prefix_str
));
2532 if (type
&& evp
->prefix
.route_type
!= type
)
2536 json_prefix
= json_object_new_object();
2538 pi
= bgp_node_get_bgp_path_info(rn
);
2540 /* RD header and legend - once overall. */
2541 if (rd_header
&& !json
) {
2543 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2545 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2547 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2551 /* Prefix and num paths displayed once per prefix. */
2552 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2559 json_paths
= json_object_new_array();
2561 /* Display each path for this prefix. */
2562 for (; pi
; pi
= pi
->next
) {
2563 json_object
*json_path
= NULL
;
2566 json_path
= json_object_new_array();
2568 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2572 json_object_array_add(json_paths
, json_path
);
2575 add_prefix_to_json
= 1;
2579 if (json
&& add_prefix_to_json
) {
2580 json_object_object_add(json_prefix
, "paths",
2582 json_object_object_add(json_rd
, prefix_str
,
2587 if (json
&& add_rd_to_json
)
2588 json_object_object_add(json
, rd_str
, json_rd
);
2591 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2592 json_object_int_add(json
, "numPaths", path_cnt
);
2594 if (prefix_cnt
== 0)
2595 vty_out(vty
, "No prefixes exist with this RD%s\n",
2596 type
? " (of requested type)" : "");
2599 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2600 prefix_cnt
, path_cnt
,
2601 type
? " (of requested type)" : "");
2606 * Display BGP EVPN routing table - all routes (vty handler).
2607 * If 'type' is non-zero, only routes matching that type are shown.
2609 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2610 json_object
*json
, int detail
)
2612 struct bgp_node
*rd_rn
;
2613 struct bgp_table
*table
;
2614 struct bgp_node
*rn
;
2615 struct bgp_path_info
*pi
;
2616 int header
= detail
? 0 : 1;
2620 uint32_t prefix_cnt
, path_cnt
;
2624 prefix_cnt
= path_cnt
= 0;
2626 /* EVPN routing table is a 2-level table with the first level being
2629 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2630 rd_rn
= bgp_route_next(rd_rn
)) {
2631 char rd_str
[RD_ADDRSTRLEN
];
2632 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2633 int add_rd_to_json
= 0;
2636 table
= bgp_node_get_bgp_table_info(rd_rn
);
2640 tbl_ver
= table
->version
;
2641 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2645 json_rd
= json_object_new_object();
2649 /* Display all prefixes for an RD */
2650 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2651 json_object
*json_prefix
=
2652 NULL
; /* contains prefix under a RD */
2653 json_object
*json_paths
=
2654 NULL
; /* array of paths under a prefix*/
2655 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2656 char prefix_str
[BUFSIZ
];
2657 int add_prefix_to_json
= 0;
2659 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2660 prefix_str
, sizeof(prefix_str
));
2662 if (type
&& evp
->prefix
.route_type
!= type
)
2665 pi
= bgp_node_get_bgp_path_info(rn
);
2667 /* Overall header/legend displayed once. */
2669 bgp_evpn_show_route_header(vty
, bgp
,
2674 "%19s Extended Community\n"
2679 /* RD header - per RD. */
2681 bgp_evpn_show_route_rd_header(
2682 vty
, rd_rn
, json_rd
, rd_str
,
2691 json_prefix
= json_object_new_object();
2692 json_paths
= json_object_new_array();
2693 json_object_string_add(json_prefix
, "prefix",
2695 json_object_int_add(json_prefix
, "prefixLen",
2699 /* Prefix and num paths displayed once per prefix. */
2701 route_vty_out_detail_header(
2703 (struct prefix_rd
*)&rd_rn
->p
,
2704 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2706 /* For EVPN, the prefix is displayed for each path (to
2708 * with code that already exists).
2710 for (; pi
; pi
= pi
->next
) {
2711 json_object
*json_path
= NULL
;
2713 add_prefix_to_json
= 1;
2717 json_path
= json_object_new_array();
2720 route_vty_out_detail(
2721 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2722 SAFI_EVPN
, json_path
);
2724 route_vty_out(vty
, &rn
->p
, pi
, 0,
2725 SAFI_EVPN
, json_path
);
2728 json_object_array_add(json_paths
,
2732 if (json
&& add_prefix_to_json
) {
2733 json_object_object_add(json_prefix
, "paths",
2735 json_object_object_add(json_rd
, prefix_str
,
2740 if (json
&& add_rd_to_json
)
2741 json_object_object_add(json
, rd_str
, json_rd
);
2745 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2746 json_object_int_add(json
, "numPaths", path_cnt
);
2748 if (prefix_cnt
== 0) {
2749 vty_out(vty
, "No EVPN prefixes %sexist\n",
2750 type
? "(of requested type) " : "");
2752 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2753 prefix_cnt
, path_cnt
,
2754 type
? " (of requested type)" : "");
2759 /* Display specific ES */
2760 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2763 struct evpnes
*es
= NULL
;
2765 es
= bgp_evpn_lookup_es(bgp
, esi
);
2767 display_es(vty
, es
, json
);
2770 vty_out(vty
, "{}\n");
2772 vty_out(vty
, "ESI not found\n");
2778 /* Display all ESs */
2779 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2785 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2786 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2791 hash_iterate(bgp
->esihash
,
2792 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2797 * Display specified VNI (vty handler)
2799 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2803 struct bgpevpn
*vpn
;
2805 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2808 display_vni(vty
, vpn
, json
);
2810 struct bgp
*bgp_temp
;
2811 struct listnode
*node
= NULL
;
2813 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2814 if (bgp_temp
->l3vni
== vni
) {
2816 display_l3vni(vty
, bgp_temp
, json
);
2823 vty_out(vty
, "{}\n");
2825 vty_out(vty
, "VNI not found\n");
2832 * Display a VNI (upon user query).
2834 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2838 struct bgp
*bgp_temp
= NULL
;
2839 struct listnode
*node
;
2843 vty_out(vty
, "Flags: * - Kernel\n");
2844 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2845 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2848 /* print all L2 VNIS */
2851 hash_iterate(bgp
->vnihash
,
2852 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2855 /* print all L3 VNIs */
2856 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2857 show_l3vni_entry(vty
, bgp_temp
, json
);
2861 * evpn - enable advertisement of svi MAC-IP
2863 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2867 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2869 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2872 bgp
->evpn_info
->advertise_svi_macip
= set
;
2873 bgp_zebra_advertise_svi_macip(bgp
,
2874 bgp
->evpn_info
->advertise_svi_macip
, 0);
2876 if (set
&& vpn
->advertise_svi_macip
)
2878 else if (!set
&& !vpn
->advertise_svi_macip
)
2881 vpn
->advertise_svi_macip
= set
;
2882 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2888 * evpn - enable advertisement of default g/w
2890 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2893 if (bgp
->advertise_gw_macip
)
2896 bgp
->advertise_gw_macip
= 1;
2897 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2899 if (vpn
->advertise_gw_macip
)
2902 vpn
->advertise_gw_macip
= 1;
2903 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2910 * evpn - disable advertisement of default g/w
2912 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2913 struct bgpevpn
*vpn
)
2916 if (!bgp
->advertise_gw_macip
)
2919 bgp
->advertise_gw_macip
= 0;
2920 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2922 if (!vpn
->advertise_gw_macip
)
2925 vpn
->advertise_gw_macip
= 0;
2926 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2933 * evpn - enable advertisement of default g/w
2935 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2936 afi_t afi
, bool add
)
2938 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2941 /* bail if we are already advertising default route */
2942 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2946 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2947 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2948 else if (afi
== AFI_IP6
)
2949 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2950 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2952 /* bail out if we havent advertised the default route */
2953 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2956 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2957 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2958 else if (afi
== AFI_IP6
)
2959 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2960 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2963 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2967 * evpn - enable advertisement of default g/w
2969 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2970 struct bgpevpn
*vpn
)
2972 if (vpn
->advertise_subnet
)
2975 vpn
->advertise_subnet
= 1;
2976 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2980 * evpn - disable advertisement of default g/w
2982 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2984 if (!vpn
->advertise_subnet
)
2987 vpn
->advertise_subnet
= 0;
2988 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2992 * EVPN (VNI advertisement) enabled. Register with zebra.
2994 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2996 bgp
->advertise_all_vni
= 1;
2998 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3002 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3003 * cache, EVPN routes (delete and withdraw from peers).
3005 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3007 bgp
->advertise_all_vni
= 0;
3008 bgp_set_evpn(bgp_get_default());
3009 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3010 bgp_evpn_cleanup_on_disable(bgp
);
3014 * EVPN - use RFC8365 to auto-derive RT
3016 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3018 bgp
->advertise_autort_rfc8365
= 1;
3019 bgp_evpn_handle_autort_change(bgp
);
3023 * EVPN - don't use RFC8365 to auto-derive RT
3025 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3027 bgp
->advertise_autort_rfc8365
= 0;
3028 bgp_evpn_handle_autort_change(bgp
);
3031 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3033 char buf1
[RD_ADDRSTRLEN
];
3035 struct listnode
*node
, *nnode
;
3036 struct ecommunity
*ecom
;
3038 if (is_vni_configured(vpn
)) {
3039 vty_out(vty
, " vni %d\n", vpn
->vni
);
3040 if (is_rd_configured(vpn
))
3041 vty_out(vty
, " rd %s\n",
3042 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3044 if (is_import_rt_configured(vpn
)) {
3045 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3047 ecom_str
= ecommunity_ecom2str(
3048 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3049 vty_out(vty
, " route-target import %s\n",
3051 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3055 if (is_export_rt_configured(vpn
)) {
3056 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3058 ecom_str
= ecommunity_ecom2str(
3059 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3060 vty_out(vty
, " route-target export %s\n",
3062 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3066 if (vpn
->advertise_gw_macip
)
3067 vty_out(vty
, " advertise-default-gw\n");
3069 if (vpn
->advertise_svi_macip
)
3070 vty_out(vty
, " advertise-svi-ip\n");
3072 if (vpn
->advertise_subnet
)
3073 vty_out(vty
, " advertise-subnet\n");
3075 vty_out(vty
, " exit-vni\n");
3079 #ifndef VTYSH_EXTRACT_PL
3080 #include "bgpd/bgp_evpn_vty_clippy.c"
3083 DEFPY(bgp_evpn_flood_control
,
3084 bgp_evpn_flood_control_cmd
,
3085 "[no$no] flooding <disable$disable|head-end-replication$her>",
3087 "Specify handling for BUM packets\n"
3088 "Do not flood any BUM packets\n"
3089 "Flood BUM packets using head-end replication\n")
3091 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3092 enum vxlan_flood_control flood_ctrl
;
3098 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3100 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3104 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3107 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3108 bgp_evpn_flood_control_change(bgp
);
3113 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3114 bgp_evpn_advertise_default_gw_vni_cmd
,
3115 "advertise-default-gw",
3116 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3118 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3119 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3124 evpn_set_advertise_default_gw(bgp
, vpn
);
3129 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3130 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3131 "no advertise-default-gw",
3133 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3135 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3136 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3141 evpn_unset_advertise_default_gw(bgp
, vpn
);
3147 DEFUN (bgp_evpn_advertise_default_gw
,
3148 bgp_evpn_advertise_default_gw_cmd
,
3149 "advertise-default-gw",
3150 "Advertise All default g/w mac-ip routes in EVPN\n")
3152 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3157 if (!EVPN_ENABLED(bgp
)) {
3159 "This command is only supported under the EVPN VRF\n");
3163 evpn_set_advertise_default_gw(bgp
, NULL
);
3168 DEFUN (no_bgp_evpn_advertise_default_gw
,
3169 no_bgp_evpn_advertise_default_gw_cmd
,
3170 "no advertise-default-gw",
3172 "Withdraw All default g/w mac-ip routes from EVPN\n")
3174 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3179 if (!EVPN_ENABLED(bgp
)) {
3181 "This command is only supported under the EVPN VRF\n");
3185 evpn_unset_advertise_default_gw(bgp
, NULL
);
3190 DEFUN (bgp_evpn_advertise_all_vni
,
3191 bgp_evpn_advertise_all_vni_cmd
,
3192 "advertise-all-vni",
3193 "Advertise All local VNIs\n")
3195 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3196 struct bgp
*bgp_evpn
= NULL
;
3201 bgp_evpn
= bgp_get_evpn();
3202 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3203 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3205 return CMD_WARNING_CONFIG_FAILED
;
3208 evpn_set_advertise_all_vni(bgp
);
3212 DEFUN (no_bgp_evpn_advertise_all_vni
,
3213 no_bgp_evpn_advertise_all_vni_cmd
,
3214 "no advertise-all-vni",
3216 "Advertise All local VNIs\n")
3218 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3222 evpn_unset_advertise_all_vni(bgp
);
3226 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3227 bgp_evpn_advertise_autort_rfc8365_cmd
,
3228 "autort rfc8365-compatible",
3229 "Auto-derivation of RT\n"
3230 "Auto-derivation of RT using RFC8365\n")
3232 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3236 evpn_set_advertise_autort_rfc8365(bgp
);
3240 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3241 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3242 "no autort rfc8365-compatible",
3244 "Auto-derivation of RT\n"
3245 "Auto-derivation of RT using RFC8365\n")
3247 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3251 evpn_unset_advertise_autort_rfc8365(bgp
);
3255 DEFUN (bgp_evpn_default_originate
,
3256 bgp_evpn_default_originate_cmd
,
3257 "default-originate <ipv4 | ipv6>",
3258 "originate a default route\n"
3259 "ipv4 address family\n"
3260 "ipv6 address family\n")
3264 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3268 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3269 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3273 DEFUN (no_bgp_evpn_default_originate
,
3274 no_bgp_evpn_default_originate_cmd
,
3275 "no default-originate <ipv4 | ipv6>",
3277 "withdraw a default route\n"
3278 "ipv4 address family\n"
3279 "ipv6 address family\n")
3283 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3287 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3288 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3292 DEFPY (dup_addr_detection
,
3293 dup_addr_detection_cmd
,
3294 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3295 "Duplicate address detection\n"
3296 "Max allowed moves before address detected as duplicate\n"
3297 "Num of max allowed moves (2-1000) default 5\n"
3298 "Duplicate address detection time\n"
3299 "Time in seconds (2-1800) default 180\n")
3301 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3306 if (!EVPN_ENABLED(bgp_vrf
)) {
3308 "This command is only supported under the EVPN VRF\n");
3312 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3315 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3317 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3319 bgp_zebra_dup_addr_detection(bgp_vrf
);
3324 DEFPY (dup_addr_detection_auto_recovery
,
3325 dup_addr_detection_auto_recovery_cmd
,
3326 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3327 "Duplicate address detection\n"
3328 "Duplicate address detection freeze\n"
3329 "Duplicate address detection permanent freeze\n"
3330 "Duplicate address detection freeze time (30-3600)\n")
3332 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3333 uint32_t freeze_time
= freeze_time_val
;
3338 if (!EVPN_ENABLED(bgp_vrf
)) {
3340 "This command is only supported under the EVPN VRF\n");
3344 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3345 bgp_vrf
->evpn_info
->dad_freeze
= true;
3346 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3348 bgp_zebra_dup_addr_detection(bgp_vrf
);
3353 DEFPY (no_dup_addr_detection
,
3354 no_dup_addr_detection_cmd
,
3355 "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>]",
3357 "Duplicate address detection\n"
3358 "Max allowed moves before address detected as duplicate\n"
3359 "Num of max allowed moves (2-1000) default 5\n"
3360 "Duplicate address detection time\n"
3361 "Time in seconds (2-1800) default 180\n"
3362 "Duplicate address detection freeze\n"
3363 "Duplicate address detection permanent freeze\n"
3364 "Duplicate address detection freeze time (30-3600)\n")
3366 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3367 uint32_t max_moves
= (uint32_t)max_moves_val
;
3368 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3373 if (!EVPN_ENABLED(bgp_vrf
)) {
3375 "This command is only supported under the EVPN VRF\n");
3380 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3382 /* Reset all parameters to default. */
3383 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3384 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3385 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3386 bgp_vrf
->evpn_info
->dad_freeze
= false;
3387 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3390 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3392 "%% Value does not match with config\n");
3395 bgp_vrf
->evpn_info
->dad_max_moves
=
3396 EVPN_DAD_DEFAULT_MAX_MOVES
;
3400 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3402 "%% Value does not match with config\n");
3405 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3409 if (bgp_vrf
->evpn_info
->dad_freeze_time
3412 "%% Value does not match with config\n");
3415 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3416 bgp_vrf
->evpn_info
->dad_freeze
= false;
3419 if (permanent_val
) {
3420 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3422 "%% Value does not match with config\n");
3425 bgp_vrf
->evpn_info
->dad_freeze
= false;
3429 bgp_zebra_dup_addr_detection(bgp_vrf
);
3434 DEFPY(bgp_evpn_advertise_svi_ip
,
3435 bgp_evpn_advertise_svi_ip_cmd
,
3436 "[no$no] advertise-svi-ip",
3438 "Advertise svi mac-ip routes in EVPN\n")
3440 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3445 if (!EVPN_ENABLED(bgp
)) {
3447 "This command is only supported under EVPN VRF\n");
3452 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3454 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3459 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3460 bgp_evpn_advertise_svi_ip_vni_cmd
,
3461 "[no$no] advertise-svi-ip",
3463 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3465 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3466 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3472 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3474 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3479 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3480 bgp_evpn_advertise_vni_subnet_cmd
,
3482 "Advertise the subnet corresponding to VNI\n")
3484 struct bgp
*bgp_vrf
= NULL
;
3485 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3486 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3491 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3495 evpn_set_advertise_subnet(bgp
, vpn
);
3499 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3500 no_bgp_evpn_advertise_vni_subnet_cmd
,
3501 "no advertise-subnet",
3503 "Advertise All local VNIs\n")
3505 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3506 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3511 evpn_unset_advertise_subnet(bgp
, vpn
);
3515 DEFUN (bgp_evpn_advertise_type5
,
3516 bgp_evpn_advertise_type5_cmd
,
3517 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3518 "Advertise prefix routes\n"
3521 "route-map for filtering specific routes\n"
3522 "Name of the route map\n")
3524 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3531 int rmap_changed
= 0;
3533 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3534 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3535 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3537 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3539 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3540 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3543 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3547 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3549 "%%only ipv4 or ipv6 address families are supported");
3553 if (safi
!= SAFI_UNICAST
) {
3555 "%%only ipv4 unicast or ipv6 unicast are supported");
3559 if (afi
== AFI_IP
) {
3561 /* if we are already advertising ipv4 prefix as type-5
3564 if (!rmap_changed
&&
3565 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3566 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3568 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3569 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3572 /* if we are already advertising ipv6 prefix as type-5
3575 if (!rmap_changed
&&
3576 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3577 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3579 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3580 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3584 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3585 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3586 XFREE(MTYPE_ROUTE_MAP_NAME
,
3587 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3588 route_map_counter_decrement(
3589 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3590 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3591 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3595 /* set the route-map for advertise command */
3596 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3597 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3598 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3599 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3600 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3601 route_map_counter_increment(
3602 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3605 /* advertise type-5 routes */
3606 if (advertise_type5_routes(bgp_vrf
, afi
))
3607 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3611 DEFUN (no_bgp_evpn_advertise_type5
,
3612 no_bgp_evpn_advertise_type5_cmd
,
3613 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3615 "Advertise prefix routes\n"
3619 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3625 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3626 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3628 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3630 "%%only ipv4 or ipv6 address families are supported");
3634 if (safi
!= SAFI_UNICAST
) {
3636 "%%only ipv4 unicast or ipv6 unicast are supported");
3640 if (afi
== AFI_IP
) {
3642 /* if we are not advertising ipv4 prefix as type-5
3645 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3646 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3647 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3648 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3649 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3653 /* if we are not advertising ipv6 prefix as type-5
3656 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3657 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3658 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3659 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3660 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3664 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3665 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3666 XFREE(MTYPE_ROUTE_MAP_NAME
,
3667 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3668 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3669 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3675 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3676 bgp_evpn_advertise_pip_ip_mac_cmd
,
3677 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3679 "evpn system primary IP\n"
3682 MAC_STR MAC_STR MAC_STR
)
3684 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3685 struct bgp
*bgp_evpn
= NULL
;
3687 if (EVPN_ENABLED(bgp_vrf
)) {
3689 "This command is supported under L3VNI BGP EVPN VRF\n");
3692 bgp_evpn
= bgp_get_evpn();
3695 /* pip is already enabled */
3696 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3699 bgp_vrf
->evpn_info
->advertise_pip
= true;
3700 if (ip
.s_addr
!= INADDR_ANY
) {
3701 /* Already configured with same IP */
3702 if (IPV4_ADDR_SAME(&ip
,
3703 &bgp_vrf
->evpn_info
->pip_ip_static
))
3706 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3707 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3709 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3711 /* default instance router-id assignemt */
3713 bgp_vrf
->evpn_info
->pip_ip
=
3714 bgp_evpn
->router_id
;
3717 if (!is_zero_mac(&mac
->eth_addr
)) {
3718 /* Already configured with same MAC */
3719 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3720 &mac
->eth_addr
, ETH_ALEN
) == 0)
3723 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3724 &mac
->eth_addr
, ETH_ALEN
);
3725 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3726 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3729 /* Copy zebra sys mac */
3730 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3731 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3732 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3737 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3739 /* Disable PIP feature */
3740 bgp_vrf
->evpn_info
->advertise_pip
= false;
3741 /* copy anycast mac */
3742 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3743 &bgp_vrf
->rmac
, ETH_ALEN
);
3745 /* remove MAC-IP option retain PIP knob. */
3746 if ((ip
.s_addr
!= INADDR_ANY
) &&
3747 !IPV4_ADDR_SAME(&ip
,
3748 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3750 "%% BGP EVPN PIP IP does not match\n");
3751 return CMD_WARNING_CONFIG_FAILED
;
3754 if (!is_zero_mac(&mac
->eth_addr
) &&
3755 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3756 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3758 "%% BGP EVPN PIP MAC does not match\n");
3759 return CMD_WARNING_CONFIG_FAILED
;
3761 /* pip_rmac can carry vrr_rmac reset only if it matches
3762 * with static value.
3764 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3765 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3767 /* Copy zebra sys mac */
3769 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3770 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3771 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3774 /* copy anycast mac */
3775 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3776 &bgp_vrf
->rmac
, ETH_ALEN
);
3780 /* reset user configured sys MAC */
3781 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3782 /* reset user configured sys IP */
3783 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3784 /* Assign default PIP IP (bgp instance router-id) */
3786 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3788 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3791 if (is_evpn_enabled()) {
3792 struct listnode
*node
= NULL
;
3793 struct bgpevpn
*vpn
= NULL
;
3795 update_advertise_vrf_routes(bgp_vrf
);
3797 /* Update (svi) type-2 routes */
3798 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3799 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3801 update_routes_for_vni(bgp_evpn
, vpn
);
3809 * Display VNI information - for all or a specific VNI
3811 DEFUN(show_bgp_l2vpn_evpn_vni
,
3812 show_bgp_l2vpn_evpn_vni_cmd
,
3813 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3822 struct bgp
*bgp_evpn
;
3826 json_object
*json
= NULL
;
3827 uint32_t num_l2vnis
= 0;
3828 uint32_t num_l3vnis
= 0;
3829 uint32_t num_vnis
= 0;
3830 struct listnode
*node
= NULL
;
3831 struct bgp
*bgp_temp
= NULL
;
3833 uj
= use_json(argc
, argv
);
3835 bgp_evpn
= bgp_get_evpn();
3839 if (!argv_find(argv
, argc
, "evpn", &idx
))
3843 json
= json_object_new_object();
3845 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3847 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3849 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3850 if (bgp_temp
->l3vni
)
3853 num_vnis
= num_l2vnis
+ num_l3vnis
;
3855 json_object_string_add(json
, "advertiseGatewayMacip",
3856 bgp_evpn
->advertise_gw_macip
3859 json_object_string_add(json
, "advertiseSviMacip",
3860 bgp_evpn
->evpn_info
->advertise_svi_macip
3861 ? "Enabled" : "Disabled");
3862 json_object_string_add(json
, "advertiseAllVnis",
3863 is_evpn_enabled() ? "Enabled"
3865 json_object_string_add(
3867 bgp_evpn
->vxlan_flood_ctrl
3868 == VXLAN_FLOOD_HEAD_END_REPL
3869 ? "Head-end replication"
3871 json_object_int_add(json
, "numVnis", num_vnis
);
3872 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3873 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3875 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3876 bgp_evpn
->advertise_gw_macip
? "Enabled"
3878 vty_out(vty
, "Advertise SVI Macip: %s\n",
3879 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3881 vty_out(vty
, "Advertise All VNI flag: %s\n",
3882 is_evpn_enabled() ? "Enabled" : "Disabled");
3883 vty_out(vty
, "BUM flooding: %s\n",
3884 bgp_evpn
->vxlan_flood_ctrl
3885 == VXLAN_FLOOD_HEAD_END_REPL
3886 ? "Head-end replication"
3888 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3889 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3891 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3895 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3898 /* Display specific VNI */
3899 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3900 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3904 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3905 json
, JSON_C_TO_STRING_PRETTY
));
3906 json_object_free(json
);
3913 DEFUN(show_bgp_l2vpn_evpn_es
,
3914 show_bgp_l2vpn_evpn_es_cmd
,
3915 "show bgp l2vpn evpn es [ESI] [json]",
3920 "ethernet-Segment\n"
3921 "Ethernet-Segment Identifier\n"
3927 json_object
*json
= NULL
;
3928 struct bgp
*bgp
= NULL
;
3930 memset(&esi
, 0, sizeof(esi
));
3931 uj
= use_json(argc
, argv
);
3933 bgp
= bgp_get_evpn();
3937 if (!argv_find(argv
, argc
, "evpn", &idx
))
3940 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3941 (!uj
&& argc
== (idx
+ 1) + 1)) {
3944 evpn_show_all_es(vty
, bgp
, json
);
3947 /* show a specific ES */
3949 /* get the ESI - ESI-ID is at argv[5] */
3950 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3951 vty_out(vty
, "%% Malformed ESI\n");
3954 evpn_show_es(vty
, bgp
, &esi
, json
);
3958 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3959 json
, JSON_C_TO_STRING_PRETTY
));
3960 json_object_free(json
);
3967 * Display EVPN neighbor summary.
3969 DEFUN(show_bgp_l2vpn_evpn_summary
,
3970 show_bgp_l2vpn_evpn_summary_cmd
,
3971 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
3978 "Summary of BGP neighbor status\n"
3979 "Show only sessions not in Established state\n"
3983 bool uj
= use_json(argc
, argv
);
3985 bool show_failed
= false;
3987 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3988 vrf
= argv
[++idx_vrf
]->arg
;
3989 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
3991 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
3996 * Display global EVPN routing table.
3998 DEFUN(show_bgp_l2vpn_evpn_route
,
3999 show_bgp_l2vpn_evpn_route_cmd
,
4000 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
4005 "EVPN route information\n"
4006 "Display Detailed Information\n"
4007 "Specify Route type\n"
4008 "MAC-IP (Type-2) route\n"
4009 "Multicast (Type-3) route\n"
4010 "Ethernet Segment (type-4) route \n"
4011 "Prefix (type-5 )route\n"
4019 json_object
*json
= NULL
;
4021 uj
= use_json(argc
, argv
);
4023 bgp
= bgp_get_evpn();
4028 json
= json_object_new_object();
4031 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4032 /* Specific type is requested */
4033 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4034 type
= BGP_EVPN_MAC_IP_ROUTE
;
4035 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4036 type
= BGP_EVPN_IMET_ROUTE
;
4037 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
4038 type
= BGP_EVPN_ES_ROUTE
;
4039 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4040 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4045 if (argv_find(argv
, argc
, "detail", &detail
))
4048 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4051 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4052 json
, JSON_C_TO_STRING_PRETTY
));
4053 json_object_free(json
);
4059 * Display global EVPN routing table for specific RD.
4061 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4062 show_bgp_l2vpn_evpn_route_rd_cmd
,
4063 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
4068 "EVPN route information\n"
4069 "Route Distinguisher\n"
4070 "ASN:XX or A.B.C.D:XX\n"
4071 "Specify Route type\n"
4072 "MAC-IP (Type-2) route\n"
4073 "Multicast (Type-3) route\n"
4074 "Ethernet Segment route\n"
4080 struct prefix_rd prd
;
4085 json_object
*json
= NULL
;
4087 bgp
= bgp_get_evpn();
4091 /* check if we need json output */
4092 uj
= use_json(argc
, argv
);
4094 json
= json_object_new_object();
4097 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4098 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4101 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4107 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4108 /* Specific type is requested */
4109 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4110 type
= BGP_EVPN_MAC_IP_ROUTE
;
4111 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4112 type
= BGP_EVPN_IMET_ROUTE
;
4113 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
4114 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4119 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4122 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4123 json
, JSON_C_TO_STRING_PRETTY
));
4124 json_object_free(json
);
4131 * Display global EVPN routing table for specific RD and MACIP.
4133 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4134 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4135 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4140 "EVPN route information\n"
4141 "Route Distinguisher\n"
4142 "ASN:XX or A.B.C.D:XX\n"
4144 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4146 "IP address (IPv4 or IPv6)\n"
4151 struct prefix_rd prd
;
4158 json_object
*json
= NULL
;
4160 memset(&mac
, 0, sizeof(struct ethaddr
));
4161 memset(&ip
, 0, sizeof(struct ipaddr
));
4163 bgp
= bgp_get_evpn();
4167 /* check if we need json output */
4168 uj
= use_json(argc
, argv
);
4170 json
= json_object_new_object();
4173 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4174 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4176 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4182 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4183 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4184 vty_out(vty
, "%% Malformed MAC address\n");
4189 /* get the ip if specified */
4190 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4191 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4192 vty_out(vty
, "%% Malformed IP address\n");
4197 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4200 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4201 json
, JSON_C_TO_STRING_PRETTY
));
4202 json_object_free(json
);
4208 /* Display per ESI routing table */
4209 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4210 show_bgp_l2vpn_evpn_route_esi_cmd
,
4211 "show bgp l2vpn evpn route esi ESI [json]",
4216 "EVPN route information\n"
4217 "Ethernet Segment Identifier\n"
4223 struct bgp
*bgp
= NULL
;
4224 json_object
*json
= NULL
;
4226 memset(&esi
, 0, sizeof(esi
));
4227 bgp
= bgp_get_evpn();
4231 uj
= use_json(argc
, argv
);
4233 json
= json_object_new_object();
4235 /* get the ESI - ESI-ID is at argv[6] */
4236 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4237 vty_out(vty
, "%% Malformed ESI\n");
4241 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4244 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4245 json
, JSON_C_TO_STRING_PRETTY
));
4246 json_object_free(json
);
4254 * Display per-VNI EVPN routing table.
4256 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4257 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4262 "EVPN route information\n"
4263 "VXLAN Network Identifier\n"
4265 "Specify Route type\n"
4266 "MAC-IP (Type-2) route\n"
4267 "Multicast (Type-3) route\n"
4269 "Remote VTEP IP address\n"
4274 struct in_addr vtep_ip
;
4278 json_object
*json
= NULL
;
4280 bgp
= bgp_get_evpn();
4284 /* check if we need json output */
4285 uj
= use_json(argc
, argv
);
4287 json
= json_object_new_object();
4289 if (!argv_find(argv
, argc
, "evpn", &idx
))
4294 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4296 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4297 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4298 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4299 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4300 type
= BGP_EVPN_MAC_IP_ROUTE
;
4301 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4302 type
= BGP_EVPN_IMET_ROUTE
;
4305 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4306 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4307 vty_out(vty
, "%% Malformed VTEP IP address\n");
4314 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4317 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4318 json
, JSON_C_TO_STRING_PRETTY
));
4319 json_object_free(json
);
4326 * Display per-VNI EVPN routing table for specific MACIP.
4328 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4329 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4330 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4335 "EVPN route information\n"
4336 "VXLAN Network Identifier\n"
4339 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4341 "IP address (IPv4 or IPv6)\n"
4350 json_object
*json
= NULL
;
4352 bgp
= bgp_get_evpn();
4356 /* check if we need json output */
4357 uj
= use_json(argc
, argv
);
4359 json
= json_object_new_object();
4361 if (!argv_find(argv
, argc
, "evpn", &idx
))
4365 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4368 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4369 vty_out(vty
, "%% Malformed MAC address\n");
4374 memset(&ip
, 0, sizeof(ip
));
4375 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4377 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4378 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4379 vty_out(vty
, "%% Malformed IP address\n");
4384 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4387 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4388 json
, JSON_C_TO_STRING_PRETTY
));
4389 json_object_free(json
);
4396 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4398 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4399 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4400 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4405 "EVPN route information\n"
4406 "VXLAN Network Identifier\n"
4408 "Multicast (Type-3) route\n"
4409 "Originating Router IP address\n"
4415 struct in_addr orig_ip
;
4418 json_object
*json
= NULL
;
4420 bgp
= bgp_get_evpn();
4424 /* check if we need json output */
4425 uj
= use_json(argc
, argv
);
4427 json
= json_object_new_object();
4429 if (!argv_find(argv
, argc
, "evpn", &idx
))
4433 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4436 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4438 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4442 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4445 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4446 json
, JSON_C_TO_STRING_PRETTY
));
4447 json_object_free(json
);
4454 * Display per-VNI EVPN routing table - for all VNIs.
4456 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4457 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4458 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4463 "EVPN route information\n"
4464 "VXLAN Network Identifier\n"
4466 "Print Detailed Output\n"
4468 "Remote VTEP IP address\n"
4472 struct in_addr vtep_ip
;
4475 json_object
*json
= NULL
;
4476 /* Detail Adjust. Adjust indexes according to detail option */
4479 bgp
= bgp_get_evpn();
4483 /* check if we need json output */
4484 uj
= use_json(argc
, argv
);
4486 json
= json_object_new_object();
4488 if (!argv_find(argv
, argc
, "evpn", &idx
))
4491 if (argv_find(argv
, argc
, "detail", &da
))
4494 /* vtep-ip position depends on detail option */
4496 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4498 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4499 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4500 vty_out(vty
, "%% Malformed VTEP IP address\n");
4505 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4508 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4509 json
, JSON_C_TO_STRING_PRETTY
));
4510 json_object_free(json
);
4517 * Display EVPN import route-target hash table
4519 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4520 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4521 "show bgp l2vpn evpn vrf-import-rt [json]",
4526 "Show vrf import route target\n"
4530 struct bgp
*bgp_evpn
= NULL
;
4531 json_object
*json
= NULL
;
4533 bgp_evpn
= bgp_get_evpn();
4537 uj
= use_json(argc
, argv
);
4539 json
= json_object_new_object();
4541 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4544 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4545 json
, JSON_C_TO_STRING_PRETTY
));
4546 json_object_free(json
);
4553 * Display EVPN import route-target hash table
4555 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4556 show_bgp_l2vpn_evpn_import_rt_cmd
,
4557 "show bgp l2vpn evpn import-rt [json]",
4562 "Show import route target\n"
4567 json_object
*json
= NULL
;
4569 bgp
= bgp_get_evpn();
4573 uj
= use_json(argc
, argv
);
4575 json
= json_object_new_object();
4577 evpn_show_import_rts(vty
, bgp
, json
);
4580 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4581 json
, JSON_C_TO_STRING_PRETTY
));
4582 json_object_free(json
);
4588 DEFUN(test_adv_evpn_type4_route
,
4589 test_adv_evpn_type4_route_cmd
,
4591 "Advertise EVPN ES route\n"
4592 "Ethernet-segment\n"
4593 "Ethernet-Segment Identifier\n")
4598 struct ipaddr vtep_ip
;
4600 bgp
= bgp_get_evpn();
4602 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4606 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4607 vty_out(vty
, "%%Malformed ESI\n");
4611 vtep_ip
.ipa_type
= IPADDR_V4
;
4612 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4614 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4616 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4622 DEFUN(test_withdraw_evpn_type4_route
,
4623 test_withdraw_evpn_type4_route_cmd
,
4625 "Advertise EVPN ES route\n"
4626 "Ethernet-segment\n"
4627 "Ethernet-Segment Identifier\n")
4632 struct ipaddr vtep_ip
;
4634 bgp
= bgp_get_evpn();
4636 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4640 if (!bgp
->peer_self
) {
4641 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4645 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4646 vty_out(vty
, "%%Malformed ESI\n");
4650 vtep_ip
.ipa_type
= IPADDR_V4
;
4651 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4652 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4654 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4660 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4661 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4665 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4666 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4667 "Summary of BGP neighbor status\n" JSON_STR
)
4669 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4670 "show bgp evpn route [detail] [type <macip|multicast>]",
4671 SHOW_STR BGP_STR EVPN_HELP_STR
4672 "EVPN route information\n"
4673 "Display Detailed Information\n"
4674 "Specify Route type\n"
4675 "MAC-IP (Type-2) route\n"
4676 "Multicast (Type-3) route\n")
4679 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4680 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4681 SHOW_STR BGP_STR EVPN_HELP_STR
4682 "EVPN route information\n"
4683 "Route Distinguisher\n"
4684 "ASN:XX or A.B.C.D:XX\n"
4685 "Specify Route type\n"
4686 "MAC-IP (Type-2) route\n"
4687 "Multicast (Type-3) route\n")
4690 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4691 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4692 SHOW_STR BGP_STR EVPN_HELP_STR
4693 "EVPN route information\n"
4694 "Route Distinguisher\n"
4695 "ASN:XX or A.B.C.D:XX\n"
4697 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4699 "IP address (IPv4 or IPv6)\n")
4702 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4703 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4704 SHOW_STR BGP_STR EVPN_HELP_STR
4705 "EVPN route information\n"
4706 "VXLAN Network Identifier\n"
4708 "Specify Route type\n"
4709 "MAC-IP (Type-2) route\n"
4710 "Multicast (Type-3) route\n"
4712 "Remote VTEP IP address\n")
4714 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4715 show_bgp_evpn_route_vni_macip_cmd
,
4716 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4717 SHOW_STR BGP_STR EVPN_HELP_STR
4718 "EVPN route information\n"
4719 "VXLAN Network Identifier\n"
4722 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4724 "IP address (IPv4 or IPv6)\n")
4726 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4727 show_bgp_evpn_route_vni_multicast_cmd
,
4728 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4729 SHOW_STR BGP_STR EVPN_HELP_STR
4730 "EVPN route information\n"
4731 "VXLAN Network Identifier\n"
4733 "Multicast (Type-3) route\n"
4734 "Originating Router IP address\n")
4736 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4737 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4738 SHOW_STR BGP_STR EVPN_HELP_STR
4739 "EVPN route information\n"
4740 "VXLAN Network Identifier\n"
4742 "Print Detailed Output\n"
4744 "Remote VTEP IP address\n")
4746 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4747 "show bgp evpn import-rt",
4748 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4750 DEFUN_NOSH (bgp_evpn_vni
,
4752 "vni " CMD_VNI_RANGE
,
4753 "VXLAN Network Identifier\n"
4757 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4758 struct bgpevpn
*vpn
;
4763 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4765 /* Create VNI, or mark as configured. */
4766 vpn
= evpn_create_update_vni(bgp
, vni
);
4768 vty_out(vty
, "%% Failed to create VNI \n");
4772 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4776 DEFUN (no_bgp_evpn_vni
,
4777 no_bgp_evpn_vni_cmd
,
4778 "no vni " CMD_VNI_RANGE
,
4780 "VXLAN Network Identifier\n"
4784 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4785 struct bgpevpn
*vpn
;
4790 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4792 /* Check if we should disallow. */
4793 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4795 vty_out(vty
, "%% Specified VNI does not exist\n");
4798 if (!is_vni_configured(vpn
)) {
4799 vty_out(vty
, "%% Specified VNI is not configured\n");
4803 evpn_delete_vni(bgp
, vpn
);
4807 DEFUN_NOSH (exit_vni
,
4810 "Exit from VNI mode\n")
4812 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4813 vty
->node
= BGP_EVPN_NODE
;
4817 DEFUN (bgp_evpn_vrf_rd
,
4818 bgp_evpn_vrf_rd_cmd
,
4819 "rd ASN:NN_OR_IP-ADDRESS:NN",
4820 "Route Distinguisher\n"
4821 "ASN:XX or A.B.C.D:XX\n")
4824 struct prefix_rd prd
;
4825 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4830 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4832 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4836 /* If same as existing value, there is nothing more to do. */
4837 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4840 /* Configure or update the RD. */
4841 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4845 DEFUN (no_bgp_evpn_vrf_rd
,
4846 no_bgp_evpn_vrf_rd_cmd
,
4847 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4849 "Route Distinguisher\n"
4850 "ASN:XX or A.B.C.D:XX\n")
4853 struct prefix_rd prd
;
4854 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4859 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4861 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4865 /* Check if we should disallow. */
4866 if (!is_vrf_rd_configured(bgp_vrf
)) {
4867 vty_out(vty
, "%% RD is not configured for this VRF\n");
4871 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4873 "%% RD specified does not match configuration for this VRF\n");
4877 evpn_unconfigure_vrf_rd(bgp_vrf
);
4881 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4882 no_bgp_evpn_vrf_rd_without_val_cmd
,
4885 "Route Distinguisher\n")
4887 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4892 /* Check if we should disallow. */
4893 if (!is_vrf_rd_configured(bgp_vrf
)) {
4894 vty_out(vty
, "%% RD is not configured for this VRF\n");
4898 evpn_unconfigure_vrf_rd(bgp_vrf
);
4902 DEFUN (bgp_evpn_vni_rd
,
4903 bgp_evpn_vni_rd_cmd
,
4904 "rd ASN:NN_OR_IP-ADDRESS:NN",
4905 "Route Distinguisher\n"
4906 "ASN:XX or A.B.C.D:XX\n")
4908 struct prefix_rd prd
;
4909 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4910 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4916 if (!EVPN_ENABLED(bgp
)) {
4918 "This command is only supported under EVPN VRF\n");
4922 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4924 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4928 /* If same as existing value, there is nothing more to do. */
4929 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4932 /* Configure or update the RD. */
4933 evpn_configure_rd(bgp
, vpn
, &prd
);
4937 DEFUN (no_bgp_evpn_vni_rd
,
4938 no_bgp_evpn_vni_rd_cmd
,
4939 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4941 "Route Distinguisher\n"
4942 "ASN:XX or A.B.C.D:XX\n")
4944 struct prefix_rd prd
;
4945 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4946 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4952 if (!EVPN_ENABLED(bgp
)) {
4954 "This command is only supported under EVPN VRF\n");
4958 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4960 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4964 /* Check if we should disallow. */
4965 if (!is_rd_configured(vpn
)) {
4966 vty_out(vty
, "%% RD is not configured for this VNI\n");
4970 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4972 "%% RD specified does not match configuration for this VNI\n");
4976 evpn_unconfigure_rd(bgp
, vpn
);
4980 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4981 no_bgp_evpn_vni_rd_without_val_cmd
,
4984 "Route Distinguisher\n")
4986 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4987 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4992 if (!EVPN_ENABLED(bgp
)) {
4994 "This command is only supported under EVPN VRF\n");
4998 /* Check if we should disallow. */
4999 if (!is_rd_configured(vpn
)) {
5000 vty_out(vty
, "%% RD is not configured for this VNI\n");
5004 evpn_unconfigure_rd(bgp
, vpn
);
5009 * Loop over all extended-communities in the route-target list rtl and
5010 * return 1 if we find ecomtarget
5012 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5013 struct ecommunity
*ecomtarget
)
5015 struct listnode
*node
, *nnode
;
5016 struct ecommunity
*ecom
;
5018 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5019 if (ecommunity_match(ecom
, ecomtarget
))
5026 /* display L3VNI related info for a VRF instance */
5027 DEFUN (show_bgp_vrf_l3vni_info
,
5028 show_bgp_vrf_l3vni_info_cmd
,
5029 "show bgp vrf VRFNAME vni [json]",
5037 char buf
[ETHER_ADDR_STRLEN
];
5038 char buf1
[INET6_ADDRSTRLEN
];
5040 const char *name
= NULL
;
5041 struct bgp
*bgp
= NULL
;
5042 struct listnode
*node
= NULL
;
5043 struct bgpevpn
*vpn
= NULL
;
5044 struct ecommunity
*ecom
= NULL
;
5045 json_object
*json
= NULL
;
5046 json_object
*json_vnis
= NULL
;
5047 json_object
*json_export_rts
= NULL
;
5048 json_object
*json_import_rts
= NULL
;
5049 bool uj
= use_json(argc
, argv
);
5052 json
= json_object_new_object();
5053 json_vnis
= json_object_new_array();
5054 json_export_rts
= json_object_new_array();
5055 json_import_rts
= json_object_new_array();
5058 name
= argv
[idx_vrf
]->arg
;
5059 bgp
= bgp_lookup_by_name(name
);
5062 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5064 json_object_string_add(json
, "warning",
5065 "BGP instance not found");
5066 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5067 json_object_free(json
);
5073 vty_out(vty
, "BGP VRF: %s\n", name
);
5074 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
5075 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5076 vty_out(vty
, " Rmac: %s\n",
5077 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5078 vty_out(vty
, " VNI Filter: %s\n",
5079 CHECK_FLAG(bgp
->vrf_flags
,
5080 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5081 ? "prefix-routes-only"
5083 vty_out(vty
, " L2-VNI List:\n");
5085 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5086 vty_out(vty
, "%u ", vpn
->vni
);
5088 vty_out(vty
, " Export-RTs:\n");
5090 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5091 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5093 vty_out(vty
, " Import-RTs:\n");
5095 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5096 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5098 vty_out(vty
, " RD: %s\n",
5099 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5101 json_object_string_add(json
, "vrf", name
);
5102 json_object_string_add(json
, "local-ip",
5103 inet_ntoa(bgp
->originator_ip
));
5104 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5105 json_object_string_add(
5107 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5108 json_object_string_add(
5110 CHECK_FLAG(bgp
->vrf_flags
,
5111 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5112 ? "prefix-routes-only"
5114 /* list of l2vnis */
5115 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5116 json_object_array_add(json_vnis
,
5117 json_object_new_int(vpn
->vni
));
5118 json_object_object_add(json
, "l2vnis", json_vnis
);
5121 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5122 json_object_array_add(
5124 json_object_new_string(ecommunity_str(ecom
)));
5125 json_object_object_add(json
, "export-rts", json_export_rts
);
5128 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5129 json_object_array_add(
5131 json_object_new_string(ecommunity_str(ecom
)));
5132 json_object_object_add(json
, "import-rts", json_import_rts
);
5133 json_object_string_add(
5135 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5139 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5140 json
, JSON_C_TO_STRING_PRETTY
));
5141 json_object_free(json
);
5146 /* import/export rt for l3vni-vrf */
5147 DEFUN (bgp_evpn_vrf_rt
,
5148 bgp_evpn_vrf_rt_cmd
,
5149 "route-target <both|import|export> RT",
5151 "import and export\n"
5154 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5157 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5158 struct ecommunity
*ecomadd
= NULL
;
5163 if (!strcmp(argv
[1]->arg
, "import"))
5164 rt_type
= RT_TYPE_IMPORT
;
5165 else if (!strcmp(argv
[1]->arg
, "export"))
5166 rt_type
= RT_TYPE_EXPORT
;
5167 else if (!strcmp(argv
[1]->arg
, "both"))
5168 rt_type
= RT_TYPE_BOTH
;
5170 vty_out(vty
, "%% Invalid Route Target type\n");
5174 /* Add/update the import route-target */
5175 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5176 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5177 ECOMMUNITY_ROUTE_TARGET
, 0);
5179 vty_out(vty
, "%% Malformed Route Target list\n");
5182 ecommunity_str(ecomadd
);
5184 /* Do nothing if we already have this import route-target */
5185 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5186 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5189 /* Add/update the export route-target */
5190 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5191 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5192 ECOMMUNITY_ROUTE_TARGET
, 0);
5194 vty_out(vty
, "%% Malformed Route Target list\n");
5197 ecommunity_str(ecomadd
);
5199 /* Do nothing if we already have this export route-target */
5200 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5201 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5207 DEFUN (no_bgp_evpn_vrf_rt
,
5208 no_bgp_evpn_vrf_rt_cmd
,
5209 "no route-target <both|import|export> RT",
5212 "import and export\n"
5215 "ASN:XX or A.B.C.D:XX\n")
5217 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5218 int rt_type
, found_ecomdel
;
5219 struct ecommunity
*ecomdel
= NULL
;
5224 if (!strcmp(argv
[2]->arg
, "import"))
5225 rt_type
= RT_TYPE_IMPORT
;
5226 else if (!strcmp(argv
[2]->arg
, "export"))
5227 rt_type
= RT_TYPE_EXPORT
;
5228 else if (!strcmp(argv
[2]->arg
, "both"))
5229 rt_type
= RT_TYPE_BOTH
;
5231 vty_out(vty
, "%% Invalid Route Target type\n");
5235 if (rt_type
== RT_TYPE_IMPORT
) {
5236 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5238 "%% Import RT is not configured for this VRF\n");
5241 } else if (rt_type
== RT_TYPE_EXPORT
) {
5242 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5244 "%% Export RT is not configured for this VRF\n");
5247 } else if (rt_type
== RT_TYPE_BOTH
) {
5248 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5249 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5251 "%% Import/Export RT is not configured for this VRF\n");
5256 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5258 vty_out(vty
, "%% Malformed Route Target list\n");
5261 ecommunity_str(ecomdel
);
5263 if (rt_type
== RT_TYPE_IMPORT
) {
5264 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5267 "%% RT specified does not match configuration for this VRF\n");
5270 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5271 } else if (rt_type
== RT_TYPE_EXPORT
) {
5272 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5275 "%% RT specified does not match configuration for this VRF\n");
5278 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5279 } else if (rt_type
== RT_TYPE_BOTH
) {
5282 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5284 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5288 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5290 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5294 if (!found_ecomdel
) {
5296 "%% RT specified does not match configuration for this VRF\n");
5304 DEFUN (bgp_evpn_vni_rt
,
5305 bgp_evpn_vni_rt_cmd
,
5306 "route-target <both|import|export> RT",
5308 "import and export\n"
5311 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5313 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5314 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5316 struct ecommunity
*ecomadd
= NULL
;
5321 if (!EVPN_ENABLED(bgp
)) {
5323 "This command is only supported under EVPN VRF\n");
5327 if (!strcmp(argv
[1]->text
, "import"))
5328 rt_type
= RT_TYPE_IMPORT
;
5329 else if (!strcmp(argv
[1]->text
, "export"))
5330 rt_type
= RT_TYPE_EXPORT
;
5331 else if (!strcmp(argv
[1]->text
, "both"))
5332 rt_type
= RT_TYPE_BOTH
;
5334 vty_out(vty
, "%% Invalid Route Target type\n");
5338 /* Add/update the import route-target */
5339 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5340 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5341 ECOMMUNITY_ROUTE_TARGET
, 0);
5343 vty_out(vty
, "%% Malformed Route Target list\n");
5346 ecommunity_str(ecomadd
);
5348 /* Do nothing if we already have this import route-target */
5349 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5350 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5353 /* Add/update the export route-target */
5354 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5355 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5356 ECOMMUNITY_ROUTE_TARGET
, 0);
5358 vty_out(vty
, "%% Malformed Route Target list\n");
5361 ecommunity_str(ecomadd
);
5363 /* Do nothing if we already have this export route-target */
5364 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5365 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5371 DEFUN (no_bgp_evpn_vni_rt
,
5372 no_bgp_evpn_vni_rt_cmd
,
5373 "no route-target <both|import|export> RT",
5376 "import and export\n"
5379 "ASN:XX or A.B.C.D:XX\n")
5381 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5382 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5383 int rt_type
, found_ecomdel
;
5384 struct ecommunity
*ecomdel
= NULL
;
5389 if (!EVPN_ENABLED(bgp
)) {
5391 "This command is only supported under EVPN VRF\n");
5395 if (!strcmp(argv
[2]->text
, "import"))
5396 rt_type
= RT_TYPE_IMPORT
;
5397 else if (!strcmp(argv
[2]->text
, "export"))
5398 rt_type
= RT_TYPE_EXPORT
;
5399 else if (!strcmp(argv
[2]->text
, "both"))
5400 rt_type
= RT_TYPE_BOTH
;
5402 vty_out(vty
, "%% Invalid Route Target type\n");
5406 /* The user did "no route-target import", check to see if there are any
5407 * import route-targets configured. */
5408 if (rt_type
== RT_TYPE_IMPORT
) {
5409 if (!is_import_rt_configured(vpn
)) {
5411 "%% Import RT is not configured for this VNI\n");
5414 } else if (rt_type
== RT_TYPE_EXPORT
) {
5415 if (!is_export_rt_configured(vpn
)) {
5417 "%% Export RT is not configured for this VNI\n");
5420 } else if (rt_type
== RT_TYPE_BOTH
) {
5421 if (!is_import_rt_configured(vpn
)
5422 && !is_export_rt_configured(vpn
)) {
5424 "%% Import/Export RT is not configured for this VNI\n");
5429 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5431 vty_out(vty
, "%% Malformed Route Target list\n");
5434 ecommunity_str(ecomdel
);
5436 if (rt_type
== RT_TYPE_IMPORT
) {
5437 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5439 "%% RT specified does not match configuration for this VNI\n");
5442 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5443 } else if (rt_type
== RT_TYPE_EXPORT
) {
5444 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5446 "%% RT specified does not match configuration for this VNI\n");
5449 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5450 } else if (rt_type
== RT_TYPE_BOTH
) {
5453 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5454 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5458 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5459 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5463 if (!found_ecomdel
) {
5465 "%% RT specified does not match configuration for this VNI\n");
5473 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5474 no_bgp_evpn_vni_rt_without_val_cmd
,
5475 "no route-target <import|export>",
5481 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5482 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5488 if (!EVPN_ENABLED(bgp
)) {
5490 "This command is only supported under EVPN VRF\n");
5494 if (!strcmp(argv
[2]->text
, "import")) {
5495 rt_type
= RT_TYPE_IMPORT
;
5496 } else if (!strcmp(argv
[2]->text
, "export")) {
5497 rt_type
= RT_TYPE_EXPORT
;
5499 vty_out(vty
, "%% Invalid Route Target type\n");
5503 /* Check if we should disallow. */
5504 if (rt_type
== RT_TYPE_IMPORT
) {
5505 if (!is_import_rt_configured(vpn
)) {
5507 "%% Import RT is not configured for this VNI\n");
5511 if (!is_export_rt_configured(vpn
)) {
5513 "%% Export RT is not configured for this VNI\n");
5518 /* Unconfigure the RT. */
5519 if (rt_type
== RT_TYPE_IMPORT
)
5520 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5522 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5526 static int vni_cmp(const void **a
, const void **b
)
5528 const struct bgpevpn
*first
= *a
;
5529 const struct bgpevpn
*secnd
= *b
;
5531 return secnd
->vni
- first
->vni
;
5535 * Output EVPN configuration information.
5537 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5540 char buf1
[RD_ADDRSTRLEN
];
5543 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5544 struct listnode
*ln
;
5545 struct bgpevpn
*data
;
5547 list_sort(vnilist
, vni_cmp
);
5548 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5549 write_vni_config(vty
, data
);
5551 list_delete(&vnilist
);
5554 if (bgp
->advertise_all_vni
)
5555 vty_out(vty
, " advertise-all-vni\n");
5557 if (bgp
->advertise_autort_rfc8365
)
5558 vty_out(vty
, " autort rfc8365-compatible\n");
5560 if (bgp
->advertise_gw_macip
)
5561 vty_out(vty
, " advertise-default-gw\n");
5563 if (bgp
->evpn_info
->advertise_svi_macip
)
5564 vty_out(vty
, " advertise-svi-ip\n");
5566 if (!bgp
->evpn_info
->dup_addr_detect
)
5567 vty_out(vty
, " no dup-addr-detection\n");
5569 if (bgp
->evpn_info
->dad_max_moves
!=
5570 EVPN_DAD_DEFAULT_MAX_MOVES
||
5571 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5572 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5573 bgp
->evpn_info
->dad_max_moves
,
5574 bgp
->evpn_info
->dad_time
);
5576 if (bgp
->evpn_info
->dad_freeze
) {
5577 if (bgp
->evpn_info
->dad_freeze_time
)
5579 " dup-addr-detection freeze %u\n",
5580 bgp
->evpn_info
->dad_freeze_time
);
5583 " dup-addr-detection freeze permanent\n");
5586 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5587 vty_out(vty
, " flooding disable\n");
5589 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5590 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5591 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5592 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5593 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5595 vty_out(vty
, " advertise ipv4 unicast\n");
5598 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5599 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5600 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5601 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5602 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5604 vty_out(vty
, " advertise ipv6 unicast\n");
5607 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5608 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5609 vty_out(vty
, " default-originate ipv4\n");
5611 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5612 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5613 vty_out(vty
, " default-originate ipv6\n");
5615 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5616 if (!bgp
->evpn_info
->advertise_pip
)
5617 vty_out(vty
, " no advertise-pip\n");
5618 if (bgp
->evpn_info
->advertise_pip
) {
5619 if (bgp
->evpn_info
->pip_ip_static
.s_addr
!= INADDR_ANY
)
5620 vty_out(vty
, " advertise-pip ip %s",
5621 inet_ntoa(bgp
->evpn_info
->pip_ip_static
));
5622 if (!is_zero_mac(&(bgp
->evpn_info
->pip_rmac_static
))) {
5623 char buf
[ETHER_ADDR_STRLEN
];
5625 vty_out(vty
, " mac %s",
5626 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
5632 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5633 vty_out(vty
, " rd %s\n",
5634 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5636 /* import route-target */
5637 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5639 struct listnode
*node
, *nnode
;
5640 struct ecommunity
*ecom
;
5642 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5644 ecom_str
= ecommunity_ecom2str(
5645 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5646 vty_out(vty
, " route-target import %s\n", ecom_str
);
5647 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5651 /* export route-target */
5652 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5654 struct listnode
*node
, *nnode
;
5655 struct ecommunity
*ecom
;
5657 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5659 ecom_str
= ecommunity_ecom2str(
5660 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5661 vty_out(vty
, " route-target export %s\n", ecom_str
);
5662 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5667 void bgp_ethernetvpn_init(void)
5669 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5670 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5671 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5672 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5673 install_element(VIEW_NODE
,
5674 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5675 install_element(VIEW_NODE
,
5676 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5679 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5682 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5683 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5684 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5685 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5686 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5687 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5688 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5689 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5690 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5691 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5692 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5693 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5694 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5695 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5696 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5697 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5698 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5699 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5700 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5701 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5702 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5705 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5706 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5708 /* "show bgp l2vpn evpn" commands. */
5709 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5710 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5711 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5712 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5713 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5714 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5715 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5716 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5717 install_element(VIEW_NODE
,
5718 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5719 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5720 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5721 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5722 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5724 /* "show bgp evpn" commands. */
5725 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5726 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5727 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5728 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5729 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5730 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5731 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5732 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5733 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5734 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5735 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5736 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5738 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5739 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5740 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5741 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5742 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5743 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5744 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5745 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5746 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5747 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5748 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5749 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5750 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5751 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5752 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5753 install_element(BGP_EVPN_VNI_NODE
,
5754 &bgp_evpn_advertise_default_gw_vni_cmd
);
5755 install_element(BGP_EVPN_VNI_NODE
,
5756 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5757 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5758 install_element(BGP_EVPN_VNI_NODE
,
5759 &no_bgp_evpn_advertise_vni_subnet_cmd
);