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"
41 #define SHOW_DISPLAY_STANDARD 0
42 #define SHOW_DISPLAY_TAGS 1
43 #define SHOW_DISPLAY_OVERLAY 2
44 #define VNI_STR_LEN 32
47 * Context for VNI hash walk - used by callbacks.
52 struct in_addr vtep_ip
;
56 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
60 uint8_t type
, sub_type
;
61 struct ecommunity_as eas
;
62 struct ecommunity_ip eip
;
63 struct listnode
*node
, *nnode
;
64 struct bgp
*tmp_bgp_vrf
= NULL
;
65 json_object
*json_rt
= NULL
;
66 json_object
*json_vrfs
= NULL
;
67 char rt_buf
[RT_ADDRSTRLEN
];
70 json_rt
= json_object_new_object();
71 json_vrfs
= json_object_new_array();
74 pnt
= (uint8_t *)&irt
->rt
.val
;
77 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
80 memset(&eas
, 0, sizeof(eas
));
82 case ECOMMUNITY_ENCODE_AS
:
83 eas
.as
= (*pnt
++ << 8);
85 ptr_get_be32(pnt
, &eas
.val
);
87 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
90 json_object_string_add(json_rt
, "rt", rt_buf
);
92 vty_out(vty
, "Route-target: %s", rt_buf
);
96 case ECOMMUNITY_ENCODE_IP
:
97 memcpy(&eip
.ip
, pnt
, 4);
99 eip
.val
= (*pnt
++ << 8);
102 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
106 json_object_string_add(json_rt
, "rt", rt_buf
);
108 vty_out(vty
, "Route-target: %s", rt_buf
);
112 case ECOMMUNITY_ENCODE_AS4
:
113 pnt
= ptr_get_be32(pnt
, &eas
.val
);
114 eas
.val
= (*pnt
++ << 8);
117 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
132 "\nList of VRFs importing routes with this route-target:\n");
135 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
137 json_object_array_add(
139 json_object_new_string(
140 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
142 vty_out(vty
, " %s\n",
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
147 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
148 json_object_object_add(json
, rt_buf
, json_rt
);
152 static void show_vrf_import_rt_entry(struct hash_backet
*backet
, void *args
[])
154 json_object
*json
= NULL
;
155 struct vty
*vty
= NULL
;
156 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)backet
->data
;
158 vty
= (struct vty
*)args
[0];
159 json
= (struct json_object
*)args
[1];
161 display_vrf_import_rt(vty
, irt
, json
);
164 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
168 uint8_t type
, sub_type
;
169 struct ecommunity_as eas
;
170 struct ecommunity_ip eip
;
171 struct listnode
*node
, *nnode
;
172 struct bgpevpn
*tmp_vpn
;
173 json_object
*json_rt
= NULL
;
174 json_object
*json_vnis
= NULL
;
175 char rt_buf
[RT_ADDRSTRLEN
];
178 json_rt
= json_object_new_object();
179 json_vnis
= json_object_new_array();
182 /* TODO: This needs to go into a function */
184 pnt
= (uint8_t *)&irt
->rt
.val
;
187 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
190 memset(&eas
, 0, sizeof(eas
));
192 case ECOMMUNITY_ENCODE_AS
:
193 eas
.as
= (*pnt
++ << 8);
195 ptr_get_be32(pnt
, &eas
.val
);
197 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
200 json_object_string_add(json_rt
, "rt", rt_buf
);
202 vty_out(vty
, "Route-target: %s", rt_buf
);
206 case ECOMMUNITY_ENCODE_IP
:
207 memcpy(&eip
.ip
, pnt
, 4);
209 eip
.val
= (*pnt
++ << 8);
212 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
216 json_object_string_add(json_rt
, "rt", rt_buf
);
218 vty_out(vty
, "Route-target: %s", rt_buf
);
222 case ECOMMUNITY_ENCODE_AS4
:
223 pnt
= ptr_get_be32(pnt
, &eas
.val
);
224 eas
.val
= (*pnt
++ << 8);
227 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
230 json_object_string_add(json_rt
, "rt", rt_buf
);
232 vty_out(vty
, "Route-target: %s", rt_buf
);
242 "\nList of VNIs importing routes with this route-target:\n");
245 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
247 json_object_array_add(
248 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
250 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
254 json_object_object_add(json_rt
, "vnis", json_vnis
);
255 json_object_object_add(json
, rt_buf
, json_rt
);
259 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
261 json_object
*json
= NULL
;
262 struct vty
*vty
= NULL
;
263 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
268 display_import_rt(vty
, irt
, json
);
273 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
274 struct bgp_node
*rd_rn
,
281 char rd_str
[RD_ADDRSTRLEN
];
283 pnt
= rd_rn
->p
.u
.val
;
285 /* Decode RD type. */
286 type
= decode_rd_type(pnt
);
291 vty_out(vty
, "Route Distinguisher: ");
295 decode_rd_as(pnt
+ 2, &rd_as
);
296 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
300 decode_rd_ip(pnt
+ 2, &rd_ip
);
301 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
306 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
310 vty_out(vty
, "%s\n", rd_str
);
313 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
314 uint64_t tbl_ver
, json_object
*json
)
317 " Network Next Hop Metric LocPrf Weight Path\n";
322 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
323 tbl_ver
, inet_ntoa(bgp
->router_id
));
325 "Status codes: s suppressed, d damped, h history, "
326 "* valid, > best, i - internal\n");
327 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
329 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
330 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
331 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
332 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
333 vty_out(vty
, "%s", ri_header
);
336 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
339 char buf1
[INET6_ADDRSTRLEN
];
341 struct listnode
*node
, *nnode
;
342 struct ecommunity
*ecom
;
343 json_object
*json_import_rtl
= NULL
;
344 json_object
*json_export_rtl
= NULL
;
346 json_import_rtl
= json_export_rtl
= 0;
349 json_import_rtl
= json_object_new_array();
350 json_export_rtl
= json_object_new_array();
351 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
352 json_object_string_add(json
, "type", "L3");
353 json_object_string_add(json
, "kernelFlag", "Yes");
354 json_object_string_add(
356 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
357 json_object_string_add(json
, "originatorIp",
358 inet_ntoa(bgp_vrf
->originator_ip
));
359 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
361 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
362 vty_out(vty
, " (known to the kernel)");
365 vty_out(vty
, " Type: %s\n", "L3");
366 vty_out(vty
, " Tenant VRF: %s\n",
367 vrf_id_to_name(bgp_vrf
->vrf_id
));
368 vty_out(vty
, " RD: %s\n",
369 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
370 vty_out(vty
, " Originator IP: %s\n",
371 inet_ntoa(bgp_vrf
->originator_ip
));
372 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
376 vty_out(vty
, " Import Route Target:\n");
378 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
379 ecom_str
= ecommunity_ecom2str(ecom
,
380 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
383 json_object_array_add(json_import_rtl
,
384 json_object_new_string(ecom_str
));
386 vty_out(vty
, " %s\n", ecom_str
);
388 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
392 json_object_object_add(json
, "importRts", json_import_rtl
);
394 vty_out(vty
, " Export Route Target:\n");
396 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
397 ecom_str
= ecommunity_ecom2str(ecom
,
398 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
401 json_object_array_add(json_export_rtl
,
402 json_object_new_string(ecom_str
));
404 vty_out(vty
, " %s\n", ecom_str
);
406 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
410 json_object_object_add(json
, "exportRts", json_export_rtl
);
413 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
415 struct in_addr
*vtep
;
416 char buf
[ESI_STR_LEN
];
417 char buf1
[RD_ADDRSTRLEN
];
418 char buf2
[INET6_ADDRSTRLEN
];
419 struct listnode
*node
= NULL
;
420 json_object
*json_vteps
= NULL
;
423 json_vteps
= json_object_new_array();
424 json_object_string_add(json
, "esi",
425 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
426 json_object_string_add(json
, "rd",
427 prefix_rd2str(&es
->prd
, buf1
,
429 json_object_string_add(
430 json
, "originatorIp",
431 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
433 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
434 json_object_array_add(
435 json_vteps
, json_object_new_string(
438 json_object_object_add(json
, "vteps", json_vteps
);
440 vty_out(vty
, "ESI: %s\n",
441 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
442 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
444 vty_out(vty
, " Originator-IP: %s\n",
445 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
447 vty_out(vty
, " VTEP List:\n");
448 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
449 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
454 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
456 char buf1
[RD_ADDRSTRLEN
];
458 struct listnode
*node
, *nnode
;
459 struct ecommunity
*ecom
;
460 json_object
*json_import_rtl
= NULL
;
461 json_object
*json_export_rtl
= NULL
;
464 json_import_rtl
= json_object_new_array();
465 json_export_rtl
= json_object_new_array();
466 json_object_int_add(json
, "vni", vpn
->vni
);
467 json_object_string_add(json
, "type", "L2");
468 json_object_string_add(json
, "kernelFlag",
469 is_vni_live(vpn
) ? "Yes" : "No");
470 json_object_string_add(
472 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
473 json_object_string_add(json
, "originatorIp",
474 inet_ntoa(vpn
->originator_ip
));
475 json_object_string_add(json
, "advertiseGatewayMacip",
476 vpn
->advertise_gw_macip
? "Yes" : "No");
478 vty_out(vty
, "VNI: %d", vpn
->vni
);
479 if (is_vni_live(vpn
))
480 vty_out(vty
, " (known to the kernel)");
483 vty_out(vty
, " Type: %s\n", "L2");
484 vty_out(vty
, " Tenant-Vrf: %s\n",
485 vrf_id_to_name(vpn
->tenant_vrf_id
));
486 vty_out(vty
, " RD: %s\n",
487 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
488 vty_out(vty
, " Originator IP: %s\n",
489 inet_ntoa(vpn
->originator_ip
));
490 vty_out(vty
, " Advertise-gw-macip : %s\n",
491 vpn
->advertise_gw_macip
? "Yes" : "No");
495 vty_out(vty
, " Import Route Target:\n");
497 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
498 ecom_str
= ecommunity_ecom2str(ecom
,
499 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
502 json_object_array_add(json_import_rtl
,
503 json_object_new_string(ecom_str
));
505 vty_out(vty
, " %s\n", ecom_str
);
507 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
511 json_object_object_add(json
, "importRts", json_import_rtl
);
513 vty_out(vty
, " Export Route Target:\n");
515 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
516 ecom_str
= ecommunity_ecom2str(ecom
,
517 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
520 json_object_array_add(json_export_rtl
,
521 json_object_new_string(ecom_str
));
523 vty_out(vty
, " %s\n", ecom_str
);
525 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
529 json_object_object_add(json
, "exportRts", json_export_rtl
);
532 static void show_esi_routes(struct bgp
*bgp
,
539 struct bgp_path_info
*pi
;
540 uint32_t prefix_cnt
, path_cnt
;
543 prefix_cnt
= path_cnt
= 0;
545 tbl_ver
= es
->route_table
->version
;
546 for (rn
= bgp_table_top(es
->route_table
); rn
;
547 rn
= bgp_route_next(rn
)) {
548 int add_prefix_to_json
= 0;
549 char prefix_str
[BUFSIZ
];
550 json_object
*json_paths
= NULL
;
551 json_object
*json_prefix
= NULL
;
553 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
557 json_prefix
= json_object_new_object();
559 pi
= bgp_node_get_bgp_path_info(rn
);
561 /* Overall header/legend displayed once. */
563 bgp_evpn_show_route_header(vty
, bgp
,
572 json_paths
= json_object_new_array();
574 /* For EVPN, the prefix is displayed for each path (to fit in
575 * with code that already exists).
577 for (; pi
; pi
= pi
->next
) {
578 json_object
*json_path
= NULL
;
581 json_path
= json_object_new_array();
583 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
586 json_object_array_add(json_paths
, json_path
);
589 add_prefix_to_json
= 1;
592 if (json
&& add_prefix_to_json
) {
593 json_object_string_add(json_prefix
, "prefix",
595 json_object_int_add(json_prefix
, "prefixLen",
597 json_object_object_add(json_prefix
, "paths",
599 json_object_object_add(json
, prefix_str
, json_prefix
);
604 json_object_int_add(json
, "numPrefix", prefix_cnt
);
605 json_object_int_add(json
, "numPaths", path_cnt
);
608 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
610 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
611 prefix_cnt
, path_cnt
);
615 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
616 struct vty
*vty
, struct in_addr vtep_ip
,
620 struct bgp_path_info
*pi
;
621 struct bgp_table
*table
;
624 uint32_t prefix_cnt
, path_cnt
;
626 prefix_cnt
= path_cnt
= 0;
628 table
= vpn
->route_table
;
629 tbl_ver
= table
->version
;
630 for (rn
= bgp_table_top(table
); rn
;
631 rn
= bgp_route_next(rn
)) {
632 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
633 int add_prefix_to_json
= 0;
634 char prefix_str
[BUFSIZ
];
635 json_object
*json_paths
= NULL
;
636 json_object
*json_prefix
= NULL
;
638 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
641 if (type
&& evp
->prefix
.route_type
!= type
)
645 json_prefix
= json_object_new_object();
647 pi
= bgp_node_get_bgp_path_info(rn
);
649 /* Overall header/legend displayed once. */
651 bgp_evpn_show_route_header(vty
, bgp
,
660 json_paths
= json_object_new_array();
662 /* For EVPN, the prefix is displayed for each path (to fit in
663 * with code that already exists).
665 for (; pi
; pi
= pi
->next
) {
666 json_object
*json_path
= NULL
;
669 && !IPV4_ADDR_SAME(&(vtep_ip
),
670 &(pi
->attr
->nexthop
)))
674 json_path
= json_object_new_array();
676 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
679 json_object_array_add(json_paths
, json_path
);
682 add_prefix_to_json
= 1;
685 if (json
&& add_prefix_to_json
) {
686 json_object_string_add(json_prefix
, "prefix",
688 json_object_int_add(json_prefix
, "prefixLen",
690 json_object_object_add(json_prefix
, "paths",
692 json_object_object_add(json
, prefix_str
, json_prefix
);
697 json_object_int_add(json
, "numPrefix", prefix_cnt
);
698 json_object_int_add(json
, "numPaths", path_cnt
);
701 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
702 type
? "(of requested type) " : "");
704 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
705 prefix_cnt
, path_cnt
,
706 type
? " (of requested type)" : "");
710 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
712 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
713 struct vni_walk_ctx
*wctx
= arg
;
714 struct vty
*vty
= wctx
->vty
;
715 json_object
*json
= wctx
->json
;
716 json_object
*json_vni
= NULL
;
717 char vni_str
[VNI_STR_LEN
];
719 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
721 json_vni
= json_object_new_object();
722 json_object_int_add(json_vni
, "vni", vpn
->vni
);
724 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
727 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
730 json_object_object_add(json
, vni_str
, json_vni
);
733 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
736 json_object
*json_vni
= NULL
;
737 json_object
*json_import_rtl
= NULL
;
738 json_object
*json_export_rtl
= NULL
;
740 char buf2
[INET6_ADDRSTRLEN
];
743 struct listnode
*node
, *nnode
;
744 struct ecommunity
*ecom
;
750 json_vni
= json_object_new_object();
751 json_import_rtl
= json_object_new_array();
752 json_export_rtl
= json_object_new_array();
755 /* if an l3vni is present in bgp it is live */
760 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
761 json_object_string_add(json_vni
, "type", "L3");
762 json_object_string_add(json_vni
, "inKernel", "True");
763 json_object_string_add(json_vni
, "originatorIp",
764 inet_ntoa(bgp
->originator_ip
));
765 json_object_string_add(
767 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
769 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
770 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
773 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
774 ecom_str
= ecommunity_ecom2str(ecom
,
775 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
778 json_object_array_add(json_import_rtl
,
779 json_object_new_string(ecom_str
));
781 if (listcount(bgp
->vrf_import_rtl
) > 1)
782 sprintf(rt_buf
, "%s, ...", ecom_str
);
784 sprintf(rt_buf
, "%s", ecom_str
);
785 vty_out(vty
, " %-25s", rt_buf
);
788 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
790 /* If there are multiple import RTs we break here and show only
797 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
799 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
800 ecom_str
= ecommunity_ecom2str(ecom
,
801 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
804 json_object_array_add(json_export_rtl
,
805 json_object_new_string(ecom_str
));
807 if (listcount(bgp
->vrf_export_rtl
) > 1)
808 sprintf(rt_buf
, "%s, ...", ecom_str
);
810 sprintf(rt_buf
, "%s", ecom_str
);
811 vty_out(vty
, " %-25s", rt_buf
);
814 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
816 /* If there are multiple export RTs we break here and show only
823 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
826 char vni_str
[VNI_STR_LEN
];
828 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
829 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
830 json_object_object_add(json
, vni_str
, json_vni
);
836 static void show_es_entry(struct hash_backet
*backet
, void *args
[])
838 char buf
[ESI_STR_LEN
];
839 char buf1
[RD_ADDRSTRLEN
];
840 char buf2
[INET6_ADDRSTRLEN
];
841 struct in_addr
*vtep
= NULL
;
842 struct vty
*vty
= args
[0];
843 json_object
*json
= args
[1];
844 json_object
*json_vteps
= NULL
;
845 struct listnode
*node
= NULL
;
846 struct evpnes
*es
= (struct evpnes
*)backet
->data
;
849 json_vteps
= json_object_new_array();
850 json_object_string_add(json
, "esi",
851 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
852 json_object_string_add(json
, "type",
853 is_es_local(es
) ? "Local" : "Remote");
854 json_object_string_add(json
, "rd",
855 prefix_rd2str(&es
->prd
, buf1
,
857 json_object_string_add(
858 json
, "originatorIp",
859 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
861 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
862 json_object_array_add(json_vteps
,
863 json_object_new_string(
866 json_object_object_add(json
, "vteps", json_vteps
);
868 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
869 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
870 is_es_local(es
) ? "Local" : "Remote",
871 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
872 ipaddr2str(&es
->originator_ip
, buf2
,
874 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
878 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
882 json_object
*json_vni
= NULL
;
883 json_object
*json_import_rtl
= NULL
;
884 json_object
*json_export_rtl
= NULL
;
885 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
887 char buf2
[RD_ADDRSTRLEN
];
890 struct listnode
*node
, *nnode
;
891 struct ecommunity
*ecom
;
897 json_vni
= json_object_new_object();
898 json_import_rtl
= json_object_new_array();
899 json_export_rtl
= json_object_new_array();
903 if (is_vni_live(vpn
))
907 json_object_int_add(json_vni
, "vni", vpn
->vni
);
908 json_object_string_add(json_vni
, "type", "L2");
909 json_object_string_add(json_vni
, "inKernel",
910 is_vni_live(vpn
) ? "True" : "False");
911 json_object_string_add(json_vni
, "originatorIp",
912 inet_ntoa(vpn
->originator_ip
));
913 json_object_string_add(json_vni
, "originatorIp",
914 inet_ntoa(vpn
->originator_ip
));
915 json_object_string_add(
917 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
919 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
920 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
923 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
924 ecom_str
= ecommunity_ecom2str(ecom
,
925 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
928 json_object_array_add(json_import_rtl
,
929 json_object_new_string(ecom_str
));
931 if (listcount(vpn
->import_rtl
) > 1)
932 sprintf(rt_buf
, "%s, ...", ecom_str
);
934 sprintf(rt_buf
, "%s", ecom_str
);
935 vty_out(vty
, " %-25s", rt_buf
);
938 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
940 /* If there are multiple import RTs we break here and show only
947 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
949 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
950 ecom_str
= ecommunity_ecom2str(ecom
,
951 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
954 json_object_array_add(json_export_rtl
,
955 json_object_new_string(ecom_str
));
957 if (listcount(vpn
->export_rtl
) > 1)
958 sprintf(rt_buf
, "%s, ...", ecom_str
);
960 sprintf(rt_buf
, "%s", ecom_str
);
961 vty_out(vty
, " %-25s", rt_buf
);
964 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
966 /* If there are multiple export RTs we break here and show only
973 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
976 char vni_str
[VNI_STR_LEN
];
978 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
979 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
980 json_object_object_add(json
, vni_str
, json_vni
);
986 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
987 enum bgp_show_type type
, void *output_arg
,
988 int option
, bool use_json
)
990 afi_t afi
= AFI_L2VPN
;
992 struct bgp_table
*table
;
995 struct bgp_path_info
*pi
;
999 unsigned long output_count
= 0;
1000 unsigned long total_count
= 0;
1001 json_object
*json
= NULL
;
1002 json_object
*json_nroute
= NULL
;
1003 json_object
*json_array
= NULL
;
1004 json_object
*json_scode
= NULL
;
1005 json_object
*json_ocode
= NULL
;
1007 bgp
= bgp_get_default();
1010 vty_out(vty
, "No BGP process is configured\n");
1012 vty_out(vty
, "{}\n");
1017 json_scode
= json_object_new_object();
1018 json_ocode
= json_object_new_object();
1019 json
= json_object_new_object();
1020 json_nroute
= json_object_new_object();
1022 json_object_string_add(json_scode
, "suppressed", "s");
1023 json_object_string_add(json_scode
, "damped", "d");
1024 json_object_string_add(json_scode
, "history", "h");
1025 json_object_string_add(json_scode
, "valid", "*");
1026 json_object_string_add(json_scode
, "best", ">");
1027 json_object_string_add(json_scode
, "internal", "i");
1029 json_object_string_add(json_ocode
, "igp", "i");
1030 json_object_string_add(json_ocode
, "egp", "e");
1031 json_object_string_add(json_ocode
, "incomplete", "?");
1034 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1035 rn
= bgp_route_next(rn
)) {
1039 continue; /* XXX json TODO */
1041 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1044 table
= bgp_node_get_bgp_table_info(rn
);
1049 tbl_ver
= table
->version
;
1051 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1052 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
1055 if (type
== bgp_show_type_neighbor
) {
1056 union sockunion
*su
= output_arg
;
1058 if (pi
->peer
->su_remote
== NULL
1060 pi
->peer
->su_remote
, su
))
1066 == SHOW_DISPLAY_TAGS
) {
1067 json_object_int_add(
1071 json_object_string_add(
1076 json_object_object_add(
1080 json_object_object_add(
1086 if (option
== SHOW_DISPLAY_TAGS
)
1091 == SHOW_DISPLAY_OVERLAY
)
1096 "BGP table version is %" PRIu64
", local router ID is %s\n",
1101 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1103 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1104 vty_out(vty
, V4_HEADER
);
1117 /* Decode RD type. */
1118 type
= decode_rd_type(pnt
);
1119 /* Decode RD value. */
1120 if (type
== RD_TYPE_AS
)
1121 decode_rd_as(pnt
+ 2, &rd_as
);
1122 else if (type
== RD_TYPE_AS4
)
1123 decode_rd_as4(pnt
+ 2, &rd_as
);
1124 else if (type
== RD_TYPE_IP
)
1125 decode_rd_ip(pnt
+ 2, &rd_ip
);
1127 char buffer
[BUFSIZ
];
1128 if (type
== RD_TYPE_AS
1129 || type
== RD_TYPE_AS4
)
1130 sprintf(buffer
, "%u:%d",
1133 else if (type
== RD_TYPE_IP
)
1134 sprintf(buffer
, "%s:%d",
1138 json_object_string_add(
1140 "routeDistinguisher",
1144 "Route Distinguisher: ");
1145 if (type
== RD_TYPE_AS
)
1150 else if (type
== RD_TYPE_AS4
)
1155 else if (type
== RD_TYPE_IP
)
1156 vty_out(vty
, "ip %s:%d",
1160 vty_out(vty
, "\n\n");
1165 json_array
= json_object_new_array();
1168 if (option
== SHOW_DISPLAY_TAGS
)
1169 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1172 else if (option
== SHOW_DISPLAY_OVERLAY
)
1173 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1176 route_vty_out(vty
, &rm
->p
, pi
, 0,
1177 SAFI_EVPN
, json_array
);
1182 if (output_count
== 0)
1183 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1185 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1186 output_count
, total_count
);
1190 DEFUN(show_ip_bgp_l2vpn_evpn
,
1191 show_ip_bgp_l2vpn_evpn_cmd
,
1192 "show [ip] bgp l2vpn evpn [json]",
1193 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1195 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1196 use_json(argc
, argv
));
1199 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1200 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1201 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1207 "Display information for a route distinguisher\n"
1208 "VPN Route Distinguisher\n" JSON_STR
)
1210 int idx_ext_community
= 0;
1212 struct prefix_rd prd
;
1214 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1216 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1218 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1221 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1222 use_json(argc
, argv
));
1225 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1226 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1227 "show [ip] bgp l2vpn evpn all tags",
1233 "Display information about all EVPN NLRIs\n"
1234 "Display BGP tags for prefixes\n")
1236 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1240 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1241 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1242 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1248 "Display information for a route distinguisher\n"
1249 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1251 int idx_ext_community
= 0;
1253 struct prefix_rd prd
;
1255 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1257 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1259 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1262 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1266 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1267 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1268 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1274 "Display information about all EVPN NLRIs\n"
1275 "Detailed information on TCP and BGP neighbor connections\n"
1276 "Neighbor to display information about\n"
1277 "Display routes learned from neighbor\n" JSON_STR
)
1283 bool uj
= use_json(argc
, argv
);
1285 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1287 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1290 json_object
*json_no
= NULL
;
1291 json_no
= json_object_new_object();
1292 json_object_string_add(json_no
, "warning",
1293 "Malformed address");
1294 vty_out(vty
, "%s\n",
1295 json_object_to_json_string(json_no
));
1296 json_object_free(json_no
);
1298 vty_out(vty
, "Malformed address: %s\n",
1299 argv
[idx_ipv4
]->arg
);
1303 peer
= peer_lookup(NULL
, &su
);
1304 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1306 json_object
*json_no
= NULL
;
1307 json_no
= json_object_new_object();
1308 json_object_string_add(
1310 "No such neighbor or address family");
1311 vty_out(vty
, "%s\n",
1312 json_object_to_json_string(json_no
));
1313 json_object_free(json_no
);
1315 vty_out(vty
, "%% No such neighbor or address family\n");
1319 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1323 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1324 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1325 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1331 "Display information for a route distinguisher\n"
1332 "VPN Route Distinguisher\n"
1333 "Detailed information on TCP and BGP neighbor connections\n"
1334 "Neighbor to display information about\n"
1335 "Display routes learned from neighbor\n" JSON_STR
)
1337 int idx_ext_community
= 0;
1342 struct prefix_rd prd
;
1343 bool uj
= use_json(argc
, argv
);
1345 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1346 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1348 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1351 json_object
*json_no
= NULL
;
1352 json_no
= json_object_new_object();
1353 json_object_string_add(json_no
, "warning",
1354 "Malformed Route Distinguisher");
1355 vty_out(vty
, "%s\n",
1356 json_object_to_json_string(json_no
));
1357 json_object_free(json_no
);
1359 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1363 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1366 json_object
*json_no
= NULL
;
1367 json_no
= json_object_new_object();
1368 json_object_string_add(json_no
, "warning",
1369 "Malformed address");
1370 vty_out(vty
, "%s\n",
1371 json_object_to_json_string(json_no
));
1372 json_object_free(json_no
);
1374 vty_out(vty
, "Malformed address: %s\n",
1375 argv
[idx_ext_community
]->arg
);
1379 peer
= peer_lookup(NULL
, &su
);
1380 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1382 json_object
*json_no
= NULL
;
1383 json_no
= json_object_new_object();
1384 json_object_string_add(
1386 "No such neighbor or address family");
1387 vty_out(vty
, "%s\n",
1388 json_object_to_json_string(json_no
));
1389 json_object_free(json_no
);
1391 vty_out(vty
, "%% No such neighbor or address family\n");
1395 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1399 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1400 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1401 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1407 "Display information about all EVPN NLRIs\n"
1408 "Detailed information on TCP and BGP neighbor connections\n"
1409 "Neighbor to display information about\n"
1410 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1416 bool uj
= use_json(argc
, argv
);
1418 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1420 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1423 json_object
*json_no
= NULL
;
1424 json_no
= json_object_new_object();
1425 json_object_string_add(json_no
, "warning",
1426 "Malformed address");
1427 vty_out(vty
, "%s\n",
1428 json_object_to_json_string(json_no
));
1429 json_object_free(json_no
);
1431 vty_out(vty
, "Malformed address: %s\n",
1432 argv
[idx_ipv4
]->arg
);
1435 peer
= peer_lookup(NULL
, &su
);
1436 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1438 json_object
*json_no
= NULL
;
1439 json_no
= json_object_new_object();
1440 json_object_string_add(
1442 "No such neighbor or address family");
1443 vty_out(vty
, "%s\n",
1444 json_object_to_json_string(json_no
));
1445 json_object_free(json_no
);
1447 vty_out(vty
, "%% No such neighbor or address family\n");
1451 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1454 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1455 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1456 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1462 "Display information for a route distinguisher\n"
1463 "VPN Route Distinguisher\n"
1464 "Detailed information on TCP and BGP neighbor connections\n"
1465 "Neighbor to display information about\n"
1466 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1468 int idx_ext_community
= 0;
1472 struct prefix_rd prd
;
1474 bool uj
= use_json(argc
, argv
);
1476 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1477 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1479 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1482 json_object
*json_no
= NULL
;
1483 json_no
= json_object_new_object();
1484 json_object_string_add(json_no
, "warning",
1485 "Malformed address");
1486 vty_out(vty
, "%s\n",
1487 json_object_to_json_string(json_no
));
1488 json_object_free(json_no
);
1490 vty_out(vty
, "Malformed address: %s\n",
1491 argv
[idx_ext_community
]->arg
);
1494 peer
= peer_lookup(NULL
, &su
);
1495 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1497 json_object
*json_no
= NULL
;
1498 json_no
= json_object_new_object();
1499 json_object_string_add(
1501 "No such neighbor or address family");
1502 vty_out(vty
, "%s\n",
1503 json_object_to_json_string(json_no
));
1504 json_object_free(json_no
);
1506 vty_out(vty
, "%% No such neighbor or address family\n");
1510 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1513 json_object
*json_no
= NULL
;
1514 json_no
= json_object_new_object();
1515 json_object_string_add(json_no
, "warning",
1516 "Malformed Route Distinguisher");
1517 vty_out(vty
, "%s\n",
1518 json_object_to_json_string(json_no
));
1519 json_object_free(json_no
);
1521 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1525 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1528 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1529 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1530 "show [ip] bgp l2vpn evpn all overlay",
1536 "Display information about all EVPN NLRIs\n"
1537 "Display BGP Overlay Information for prefixes\n")
1539 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1540 SHOW_DISPLAY_OVERLAY
,
1541 use_json(argc
, argv
));
1544 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1545 show_ip_bgp_evpn_rd_overlay_cmd
,
1546 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1552 "Display information for a route distinguisher\n"
1553 "VPN Route Distinguisher\n"
1554 "Display BGP Overlay Information for prefixes\n")
1556 int idx_ext_community
= 0;
1558 struct prefix_rd prd
;
1560 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1562 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1564 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1567 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1568 SHOW_DISPLAY_OVERLAY
,
1569 use_json(argc
, argv
));
1572 /* For testing purpose, static route of MPLS-VPN. */
1573 DEFUN(evpnrt5_network
,
1574 evpnrt5_network_cmd
,
1575 "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]",
1576 "Specify a network to announce via BGP\n"
1579 "Specify Route Distinguisher\n"
1580 "VPN Route Distinguisher\n"
1582 "Ethernet Tag Value\n"
1585 "Ethernet Segment Identifier\n"
1586 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1588 "Gateway IP ( A.B.C.D )\n"
1589 "Gateway IPv6 ( X:X::X:X )\n"
1590 "Router Mac Ext Comm\n"
1591 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1592 "Route-map to modify the attributes\n"
1593 "Name of the route map\n")
1595 int idx_ipv4_prefixlen
= 1;
1596 int idx_route_distinguisher
= 3;
1601 int idx_routermac
= 13;
1603 return bgp_static_set_safi(
1604 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1605 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1606 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1607 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1608 argv
[idx_routermac
]->arg
);
1611 /* For testing purpose, static route of MPLS-VPN. */
1612 DEFUN(no_evpnrt5_network
,
1613 no_evpnrt5_network_cmd
,
1614 "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>",
1616 "Specify a network to announce via BGP\n"
1619 "Specify Route Distinguisher\n"
1620 "VPN Route Distinguisher\n"
1622 "Ethernet Tag Value\n"
1625 "Ethernet Segment Identifier\n"
1626 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1627 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1629 int idx_ipv4_prefixlen
= 2;
1630 int idx_ext_community
= 4;
1635 return bgp_static_unset_safi(
1636 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1637 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1638 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1639 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1642 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1644 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1647 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1649 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1653 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1654 * check that this is a change.
1656 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1657 struct ecommunity
*ecomadd
)
1659 /* If the VNI is "live", we need to uninstall routes using the current
1660 * import RT(s) first before we update the import RT, and subsequently
1663 if (is_vni_live(vpn
))
1664 bgp_evpn_uninstall_routes(bgp
, vpn
);
1666 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1667 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1669 /* If the auto route-target is in use we must remove it */
1670 evpn_import_rt_delete_auto(bgp
, vpn
);
1672 /* Add new RT and rebuild the RT to VNI mapping */
1673 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1675 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1676 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1678 /* Install routes that match new import RT */
1679 if (is_vni_live(vpn
))
1680 bgp_evpn_install_routes(bgp
, vpn
);
1684 * Unconfigure Import RT(s) for a VNI (vty handler).
1686 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1687 struct ecommunity
*ecomdel
)
1689 struct listnode
*node
, *nnode
, *node_to_del
;
1690 struct ecommunity
*ecom
;
1692 /* Along the lines of "configure" except we have to reset to the
1695 if (is_vni_live(vpn
))
1696 bgp_evpn_uninstall_routes(bgp
, vpn
);
1698 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1699 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1701 /* Delete all import RTs */
1702 if (ecomdel
== NULL
) {
1703 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1704 ecommunity_free(&ecom
);
1705 list_delete_node(vpn
->import_rtl
, node
);
1709 /* Delete a specific import RT */
1713 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1714 if (ecommunity_match(ecom
, ecomdel
)) {
1715 ecommunity_free(&ecom
);
1722 list_delete_node(vpn
->import_rtl
, node_to_del
);
1725 assert(vpn
->import_rtl
);
1726 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1727 if (list_isempty(vpn
->import_rtl
)) {
1728 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1729 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1731 /* Rebuild the RT to VNI mapping */
1733 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1735 /* Install routes that match new import RT */
1736 if (is_vni_live(vpn
))
1737 bgp_evpn_install_routes(bgp
, vpn
);
1741 * Configure the Export RT for a VNI (vty handler). Caller expected to
1742 * check that this is a change. Note that only a single export RT is
1743 * allowed for a VNI and any change to configuration is implemented as
1744 * a "replace" (similar to other configuration).
1746 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1747 struct ecommunity
*ecomadd
)
1749 /* If the auto route-target is in use we must remove it */
1750 evpn_export_rt_delete_auto(bgp
, vpn
);
1752 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1753 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1755 if (is_vni_live(vpn
))
1756 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1760 * Unconfigure the Export RT for a VNI (vty handler)
1762 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1763 struct ecommunity
*ecomdel
)
1765 struct listnode
*node
, *nnode
, *node_to_del
;
1766 struct ecommunity
*ecom
;
1768 /* Delete all export RTs */
1769 if (ecomdel
== NULL
) {
1770 /* Reset to default and process all routes. */
1771 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1772 ecommunity_free(&ecom
);
1773 list_delete_node(vpn
->export_rtl
, node
);
1777 /* Delete a specific export RT */
1781 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1782 if (ecommunity_match(ecom
, ecomdel
)) {
1783 ecommunity_free(&ecom
);
1790 list_delete_node(vpn
->export_rtl
, node_to_del
);
1793 assert(vpn
->export_rtl
);
1794 if (list_isempty(vpn
->export_rtl
)) {
1795 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1796 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1799 if (is_vni_live(vpn
))
1800 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1804 * Configure RD for VRF
1806 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1808 /* If we have already advertise type-5 routes with a diffrent RD, we
1809 * have to delete and withdraw them firs
1811 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1814 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1815 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1817 /* We have a new RD for VRF.
1818 * Advertise all type-5 routes again with the new RD
1820 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1824 * Unconfigure RD for VRF
1826 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1828 /* If we have already advertise type-5 routes with a diffrent RD, we
1829 * have to delete and withdraw them firs
1831 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1833 /* fall back to default RD */
1834 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1835 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1837 /* We have a new RD for VRF.
1838 * Advertise all type-5 routes again with the new RD
1840 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1844 * Configure RD for a VNI (vty handler)
1846 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1847 struct prefix_rd
*rd
)
1849 /* If the VNI is "live", we need to delete and withdraw this VNI's
1850 * local routes with the prior RD first. Then, after updating RD,
1851 * need to re-advertise.
1853 if (is_vni_live(vpn
))
1854 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1857 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1858 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1860 if (is_vni_live(vpn
))
1861 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1865 * Unconfigure RD for a VNI (vty handler)
1867 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1869 /* If the VNI is "live", we need to delete and withdraw this VNI's
1870 * local routes with the prior RD first. Then, after resetting RD
1871 * to automatic value, need to re-advertise.
1873 if (is_vni_live(vpn
))
1874 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1876 /* reset RD to default */
1877 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1879 if (is_vni_live(vpn
))
1880 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1884 * Create VNI, if not already present (VTY handler). Mark as configured.
1886 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1888 struct bgpevpn
*vpn
;
1893 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1895 /* Check if this L2VNI is already configured as L3VNI */
1896 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
1899 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1904 /* tenant vrf will be updated when we get local_vni_add from
1907 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1911 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1917 /* Mark as configured. */
1918 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1923 * Delete VNI. If VNI does not exist in the system (i.e., just
1924 * configuration), all that is needed is to free it. Otherwise,
1925 * any parameters configured for the VNI need to be reset (with
1926 * appropriate action) and the VNI marked as unconfigured; the
1927 * VNI will continue to exist, purely as a "learnt" entity.
1929 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1931 assert(bgp
->vnihash
);
1933 if (!is_vni_live(vpn
)) {
1934 bgp_evpn_free(bgp
, vpn
);
1938 /* We need to take the unconfigure action for each parameter of this VNI
1939 * that is configured. Some optimization is possible, but not worth the
1940 * additional code for an operation that should be pretty rare.
1942 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1944 /* First, deal with the export side - RD and export RT changes. */
1945 if (is_rd_configured(vpn
))
1946 evpn_unconfigure_rd(bgp
, vpn
);
1947 if (is_export_rt_configured(vpn
))
1948 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1950 /* Next, deal with the import side. */
1951 if (is_import_rt_configured(vpn
))
1952 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1958 * Display import RT mapping to VRFs (vty handler)
1959 * bgp_def: default bgp instance
1961 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1969 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1970 (void (*)(struct hash_backet
*,
1971 void *))show_vrf_import_rt_entry
,
1976 * Display import RT mapping to VNIs (vty handler)
1978 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1987 bgp
->import_rt_hash
,
1988 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1993 * Display EVPN routes for all VNIs - vty handler.
1995 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1996 struct in_addr vtep_ip
, json_object
*json
)
1999 struct vni_walk_ctx wctx
;
2001 num_vnis
= hashcount(bgp
->vnihash
);
2004 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2007 wctx
.vtep_ip
= vtep_ip
;
2009 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2010 void *))show_vni_routes_hash
,
2015 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2017 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2018 vni_t vni
, struct in_addr orig_ip
,
2021 struct bgpevpn
*vpn
;
2022 struct prefix_evpn p
;
2023 struct bgp_node
*rn
;
2024 struct bgp_path_info
*pi
;
2025 uint32_t path_cnt
= 0;
2028 json_object
*json_paths
= NULL
;
2034 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2036 vty_out(vty
, "VNI not found\n");
2040 /* See if route exists. */
2041 build_evpn_type3_prefix(&p
, orig_ip
);
2042 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2043 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2045 vty_out(vty
, "%% Network not in table\n");
2050 json_paths
= json_object_new_array();
2052 /* Prefix and num paths displayed once per prefix. */
2053 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2055 /* Display each path for this prefix. */
2056 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2057 json_object
*json_path
= NULL
;
2060 json_path
= json_object_new_array();
2062 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2066 json_object_array_add(json_paths
, json_path
);
2073 json_object_object_add(json
, "paths", json_paths
);
2075 json_object_int_add(json
, "numPaths", path_cnt
);
2077 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2083 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2084 * By definition, only matching type-2 route will be displayed.
2086 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2087 vni_t vni
, struct ethaddr
*mac
,
2088 struct ipaddr
*ip
, json_object
*json
)
2090 struct bgpevpn
*vpn
;
2091 struct prefix_evpn p
;
2092 struct bgp_node
*rn
;
2093 struct bgp_path_info
*pi
;
2094 uint32_t path_cnt
= 0;
2097 json_object
*json_paths
= NULL
;
2103 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2106 vty_out(vty
, "VNI not found\n");
2110 /* See if route exists. Look for both non-sticky and sticky. */
2111 build_evpn_type2_prefix(&p
, mac
, ip
);
2112 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2113 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2115 vty_out(vty
, "%% Network not in table\n");
2120 json_paths
= json_object_new_array();
2122 /* Prefix and num paths displayed once per prefix. */
2123 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2125 /* Display each path for this prefix. */
2126 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2127 json_object
*json_path
= NULL
;
2130 json_path
= json_object_new_array();
2132 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2136 json_object_array_add(json_paths
, json_path
);
2143 json_object_object_add(json
, "paths", json_paths
);
2145 json_object_int_add(json
, "numPaths", path_cnt
);
2147 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2152 /* Disaplay EVPN routes for a ESI - VTY handler */
2153 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2154 esi_t
*esi
, json_object
*json
)
2156 struct evpnes
*es
= NULL
;
2159 es
= bgp_evpn_lookup_es(bgp
, esi
);
2162 vty_out(vty
, "ESI not found\n");
2166 show_esi_routes(bgp
, es
, vty
, json
);
2170 * Display EVPN routes for a VNI - vty handler.
2171 * If 'type' is non-zero, only routes matching that type are shown.
2172 * If the vtep_ip is non zero, only routes behind that vtep are shown
2174 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2175 int type
, struct in_addr vtep_ip
,
2178 struct bgpevpn
*vpn
;
2181 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2184 vty_out(vty
, "VNI not found\n");
2188 /* Walk this VNI's route table and display appropriate routes. */
2189 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2193 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2194 * IP (vty handler). By definition, only matching type-2 route will be
2197 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2198 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2199 struct ipaddr
*ip
, json_object
*json
)
2201 struct prefix_evpn p
;
2202 struct bgp_node
*rn
;
2203 struct bgp_path_info
*pi
;
2206 uint32_t path_cnt
= 0;
2207 json_object
*json_paths
= NULL
;
2208 char prefix_str
[BUFSIZ
];
2213 /* See if route exists. Look for both non-sticky and sticky. */
2214 build_evpn_type2_prefix(&p
, mac
, ip
);
2215 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2216 (struct prefix
*)&p
, prd
);
2217 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2219 vty_out(vty
, "%% Network not in table\n");
2223 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2224 sizeof(prefix_str
));
2226 /* Prefix and num paths displayed once per prefix. */
2227 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2230 json_paths
= json_object_new_array();
2232 /* Display each path for this prefix. */
2233 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2234 json_object
*json_path
= NULL
;
2237 json_path
= json_object_new_array();
2239 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2243 json_object_array_add(json_paths
, json_path
);
2248 if (json
&& path_cnt
) {
2250 json_object_object_add(json
, prefix_str
, json_paths
);
2251 json_object_int_add(json
, "numPaths", path_cnt
);
2253 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2259 * Display BGP EVPN routing table -- for specific RD (vty handler)
2260 * If 'type' is non-zero, only routes matching that type are shown.
2262 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2263 struct prefix_rd
*prd
, int type
,
2266 struct bgp_node
*rd_rn
;
2267 struct bgp_table
*table
;
2268 struct bgp_node
*rn
;
2269 struct bgp_path_info
*pi
;
2273 uint32_t prefix_cnt
, path_cnt
;
2274 char rd_str
[RD_ADDRSTRLEN
];
2275 json_object
*json_rd
= NULL
;
2276 int add_rd_to_json
= 0;
2280 prefix_cnt
= path_cnt
= 0;
2282 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2284 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2288 table
= bgp_node_get_bgp_table_info(rd_rn
);
2293 json_rd
= json_object_new_object();
2294 json_object_string_add(json_rd
, "rd", rd_str
);
2297 /* Display all prefixes with this RD. */
2298 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2299 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2300 json_object
*json_prefix
= NULL
;
2301 json_object
*json_paths
= NULL
;
2302 char prefix_str
[BUFSIZ
];
2303 int add_prefix_to_json
= 0;
2305 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2306 sizeof(prefix_str
));
2308 if (type
&& evp
->prefix
.route_type
!= type
)
2312 json_prefix
= json_object_new_object();
2314 pi
= bgp_node_get_bgp_path_info(rn
);
2316 /* RD header and legend - once overall. */
2317 if (rd_header
&& !json
) {
2319 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2321 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2323 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2327 /* Prefix and num paths displayed once per prefix. */
2328 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2335 json_paths
= json_object_new_array();
2337 /* Display each path for this prefix. */
2338 for (; pi
; pi
= pi
->next
) {
2339 json_object
*json_path
= NULL
;
2342 json_path
= json_object_new_array();
2344 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2348 json_object_array_add(json_paths
, json_path
);
2351 add_prefix_to_json
= 1;
2355 if (json
&& add_prefix_to_json
) {
2356 json_object_object_add(json_prefix
, "paths",
2358 json_object_object_add(json_rd
, prefix_str
,
2363 if (json
&& add_rd_to_json
)
2364 json_object_object_add(json
, rd_str
, json_rd
);
2367 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2368 json_object_int_add(json
, "numPaths", path_cnt
);
2370 if (prefix_cnt
== 0)
2371 vty_out(vty
, "No prefixes exist with this RD%s\n",
2372 type
? " (of requested type)" : "");
2375 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2376 prefix_cnt
, path_cnt
,
2377 type
? " (of requested type)" : "");
2382 * Display BGP EVPN routing table - all routes (vty handler).
2383 * If 'type' is non-zero, only routes matching that type are shown.
2385 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2388 struct bgp_node
*rd_rn
;
2389 struct bgp_table
*table
;
2390 struct bgp_node
*rn
;
2391 struct bgp_path_info
*pi
;
2396 uint32_t prefix_cnt
, path_cnt
;
2400 prefix_cnt
= path_cnt
= 0;
2402 /* EVPN routing table is a 2-level table with the first level being
2405 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2406 rd_rn
= bgp_route_next(rd_rn
)) {
2407 char rd_str
[RD_ADDRSTRLEN
];
2408 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2409 int add_rd_to_json
= 0;
2412 table
= bgp_node_get_bgp_table_info(rd_rn
);
2416 tbl_ver
= table
->version
;
2417 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2421 json_rd
= json_object_new_object();
2422 json_object_string_add(json_rd
, "rd", rd_str
);
2427 /* Display all prefixes for an RD */
2428 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2429 json_object
*json_prefix
=
2430 NULL
; /* contains prefix under a RD */
2431 json_object
*json_paths
=
2432 NULL
; /* array of paths under a prefix*/
2433 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2434 char prefix_str
[BUFSIZ
];
2435 int add_prefix_to_json
= 0;
2437 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2438 prefix_str
, sizeof(prefix_str
));
2440 if (type
&& evp
->prefix
.route_type
!= type
)
2443 pi
= bgp_node_get_bgp_path_info(rn
);
2445 /* Overall header/legend displayed once. */
2447 bgp_evpn_show_route_header(vty
, bgp
,
2453 /* RD header - per RD. */
2455 bgp_evpn_show_route_rd_header(
2464 json_prefix
= json_object_new_object();
2465 json_paths
= json_object_new_array();
2466 json_object_string_add(json_prefix
, "prefix",
2468 json_object_int_add(json_prefix
, "prefixLen",
2472 /* For EVPN, the prefix is displayed for each path (to
2474 * with code that already exists).
2476 for (; pi
; pi
= pi
->next
) {
2477 json_object
*json_path
= NULL
;
2479 add_prefix_to_json
= 1;
2483 json_path
= json_object_new_array();
2485 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
2489 json_object_array_add(json_paths
,
2493 if (json
&& add_prefix_to_json
) {
2494 json_object_object_add(json_prefix
, "paths",
2496 json_object_object_add(json_rd
, prefix_str
,
2501 if (json
&& add_rd_to_json
)
2502 json_object_object_add(json
, rd_str
, json_rd
);
2506 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2507 json_object_int_add(json
, "numPaths", path_cnt
);
2509 if (prefix_cnt
== 0) {
2510 vty_out(vty
, "No EVPN prefixes %sexist\n",
2511 type
? "(of requested type) " : "");
2513 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2514 prefix_cnt
, path_cnt
,
2515 type
? " (of requested type)" : "");
2520 /* Display specific ES */
2521 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2524 struct evpnes
*es
= NULL
;
2526 es
= bgp_evpn_lookup_es(bgp
, esi
);
2528 display_es(vty
, es
, json
);
2531 vty_out(vty
, "{}\n");
2533 vty_out(vty
, "ESI not found\n");
2539 /* Display all ESs */
2540 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2546 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2547 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2552 hash_iterate(bgp
->esihash
,
2553 (void (*)(struct hash_backet
*, void *))show_es_entry
,
2558 * Display specified VNI (vty handler)
2560 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2564 struct bgpevpn
*vpn
;
2566 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2569 display_vni(vty
, vpn
, json
);
2571 struct bgp
*bgp_temp
;
2572 struct listnode
*node
= NULL
;
2574 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2575 if (bgp_temp
->l3vni
== vni
) {
2577 display_l3vni(vty
, bgp_temp
, json
);
2584 vty_out(vty
, "{}\n");
2586 vty_out(vty
, "VNI not found\n");
2593 * Display a VNI (upon user query).
2595 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2599 struct bgp
*bgp_temp
= NULL
;
2600 struct listnode
*node
;
2604 vty_out(vty
, "Flags: * - Kernel\n");
2605 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2606 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2609 /* print all L2 VNIS */
2612 hash_iterate(bgp
->vnihash
,
2613 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2616 /* print all L3 VNIs */
2617 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2618 show_l3vni_entry(vty
, bgp_temp
, json
);
2622 * evpn - enable advertisement of default g/w
2624 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2627 if (bgp
->advertise_gw_macip
)
2630 bgp
->advertise_gw_macip
= 1;
2631 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2633 if (vpn
->advertise_gw_macip
)
2636 vpn
->advertise_gw_macip
= 1;
2637 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2644 * evpn - disable advertisement of default g/w
2646 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2647 struct bgpevpn
*vpn
)
2650 if (!bgp
->advertise_gw_macip
)
2653 bgp
->advertise_gw_macip
= 0;
2654 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2656 if (!vpn
->advertise_gw_macip
)
2659 vpn
->advertise_gw_macip
= 0;
2660 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2667 * evpn - enable advertisement of default g/w
2669 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2670 afi_t afi
, bool add
)
2672 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2675 /* bail if we are already advertising default route */
2676 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2680 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2681 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2682 else if (afi
== AFI_IP6
)
2683 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2684 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2686 /* bail out if we havent advertised the default route */
2687 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2690 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2691 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2692 else if (afi
== AFI_IP6
)
2693 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2694 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2697 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2701 * evpn - enable advertisement of default g/w
2703 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2704 struct bgpevpn
*vpn
)
2706 if (vpn
->advertise_subnet
)
2709 vpn
->advertise_subnet
= 1;
2710 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2714 * evpn - disable advertisement of default g/w
2716 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2718 if (!vpn
->advertise_subnet
)
2721 vpn
->advertise_subnet
= 0;
2722 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2726 * EVPN (VNI advertisement) enabled. Register with zebra.
2728 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2730 bgp
->advertise_all_vni
= 1;
2731 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2735 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2736 * cache, EVPN routes (delete and withdraw from peers).
2738 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2740 bgp
->advertise_all_vni
= 0;
2741 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2742 bgp_evpn_cleanup_on_disable(bgp
);
2746 * EVPN - use RFC8365 to auto-derive RT
2748 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2750 bgp
->advertise_autort_rfc8365
= 1;
2751 bgp_evpn_handle_autort_change(bgp
);
2755 * EVPN - don't use RFC8365 to auto-derive RT
2757 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2759 bgp
->advertise_autort_rfc8365
= 0;
2760 bgp_evpn_handle_autort_change(bgp
);
2763 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2765 char buf1
[RD_ADDRSTRLEN
];
2767 struct listnode
*node
, *nnode
;
2768 struct ecommunity
*ecom
;
2770 if (is_vni_configured(vpn
)) {
2771 vty_out(vty
, " vni %d\n", vpn
->vni
);
2772 if (is_rd_configured(vpn
))
2773 vty_out(vty
, " rd %s\n",
2774 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2776 if (is_import_rt_configured(vpn
)) {
2777 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2779 ecom_str
= ecommunity_ecom2str(
2780 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2781 vty_out(vty
, " route-target import %s\n",
2783 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2787 if (is_export_rt_configured(vpn
)) {
2788 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2790 ecom_str
= ecommunity_ecom2str(
2791 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2792 vty_out(vty
, " route-target export %s\n",
2794 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2798 if (vpn
->advertise_gw_macip
)
2799 vty_out(vty
, " advertise-default-gw\n");
2801 if (vpn
->advertise_subnet
)
2802 vty_out(vty
, " advertise-subnet\n");
2804 vty_out(vty
, " exit-vni\n");
2808 #ifndef VTYSH_EXTRACT_PL
2809 #include "bgpd/bgp_evpn_vty_clippy.c"
2812 DEFPY(bgp_evpn_flood_control
,
2813 bgp_evpn_flood_control_cmd
,
2814 "[no$no] flooding <disable$disable|head-end-replication$her>",
2816 "Specify handling for BUM packets\n"
2817 "Do not flood any BUM packets\n"
2818 "Flood BUM packets using head-end replication\n")
2820 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2821 enum vxlan_flood_control flood_ctrl
;
2827 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
2829 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
2833 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
2836 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
2837 bgp_evpn_flood_control_change(bgp
);
2842 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2843 bgp_evpn_advertise_default_gw_vni_cmd
,
2844 "advertise-default-gw",
2845 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2847 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2848 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2853 evpn_set_advertise_default_gw(bgp
, vpn
);
2858 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2859 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2860 "no advertise-default-gw",
2862 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2864 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2865 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2870 evpn_unset_advertise_default_gw(bgp
, vpn
);
2876 DEFUN (bgp_evpn_advertise_default_gw
,
2877 bgp_evpn_advertise_default_gw_cmd
,
2878 "advertise-default-gw",
2879 "Advertise All default g/w mac-ip routes in EVPN\n")
2881 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2886 evpn_set_advertise_default_gw(bgp
, NULL
);
2891 DEFUN (no_bgp_evpn_advertise_default_gw
,
2892 no_bgp_evpn_advertise_default_gw_cmd
,
2893 "no advertise-default-gw",
2895 "Withdraw All default g/w mac-ip routes from EVPN\n")
2897 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2902 evpn_unset_advertise_default_gw(bgp
, NULL
);
2907 DEFUN (bgp_evpn_advertise_all_vni
,
2908 bgp_evpn_advertise_all_vni_cmd
,
2909 "advertise-all-vni",
2910 "Advertise All local VNIs\n")
2912 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2916 evpn_set_advertise_all_vni(bgp
);
2920 DEFUN (no_bgp_evpn_advertise_all_vni
,
2921 no_bgp_evpn_advertise_all_vni_cmd
,
2922 "no advertise-all-vni",
2924 "Advertise All local VNIs\n")
2926 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2930 evpn_unset_advertise_all_vni(bgp
);
2934 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2935 bgp_evpn_advertise_autort_rfc8365_cmd
,
2936 "autort rfc8365-compatible",
2937 "Auto-derivation of RT\n"
2938 "Auto-derivation of RT using RFC8365\n")
2940 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2944 evpn_set_advertise_autort_rfc8365(bgp
);
2948 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
2949 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
2950 "no autort rfc8365-compatible",
2952 "Auto-derivation of RT\n"
2953 "Auto-derivation of RT using RFC8365\n")
2955 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2959 evpn_unset_advertise_autort_rfc8365(bgp
);
2963 DEFUN (bgp_evpn_default_originate
,
2964 bgp_evpn_default_originate_cmd
,
2965 "default-originate <ipv4 | ipv6>",
2966 "originate a default route\n"
2967 "ipv4 address family\n"
2968 "ipv6 address family\n")
2972 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2976 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2977 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
2981 DEFUN (no_bgp_evpn_default_originate
,
2982 no_bgp_evpn_default_originate_cmd
,
2983 "no default-originate <ipv4 | ipv6>",
2985 "withdraw a default route\n"
2986 "ipv4 address family\n"
2987 "ipv6 address family\n")
2991 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2995 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2996 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3000 DEFPY (dup_addr_detection
,
3001 dup_addr_detection_cmd
,
3002 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3003 "Duplicate address detection\n"
3004 "Max allowed moves before address detected as duplicate\n"
3005 "Num of max allowed moves (2-1000) default 5\n"
3006 "Duplicate address detection time\n"
3007 "Time in seconds (2-1800) default 180\n")
3009 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3014 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3017 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3019 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3021 bgp_zebra_dup_addr_detection(bgp_vrf
);
3026 DEFPY (dup_addr_detection_auto_recovery
,
3027 dup_addr_detection_auto_recovery_cmd
,
3028 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3029 "Duplicate address detection\n"
3030 "Duplicate address detection freeze\n"
3031 "Duplicate address detection permanent freeze\n"
3032 "Duplicate address detection freeze time (30-3600)\n")
3034 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3035 uint32_t freeze_time
= freeze_time_val
;
3040 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3041 bgp_vrf
->evpn_info
->dad_freeze
= true;
3042 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3044 bgp_zebra_dup_addr_detection(bgp_vrf
);
3049 DEFPY (no_dup_addr_detection
,
3050 no_dup_addr_detection_cmd
,
3051 "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>]",
3053 "Duplicate address detection\n"
3054 "Max allowed moves before address detected as duplicate\n"
3055 "Num of max allowed moves (2-1000) default 5\n"
3056 "Duplicate address detection time\n"
3057 "Time in seconds (2-1800) default 180\n"
3058 "Duplicate address detection freeze\n"
3059 "Duplicate address detection permanent freeze\n"
3060 "Duplicate address detection freeze time (30-3600)\n")
3062 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3063 uint32_t max_moves
= (uint32_t)max_moves_val
;
3064 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3070 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3072 /* Reset all parameters to default. */
3073 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3074 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3075 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3076 bgp_vrf
->evpn_info
->dad_freeze
= false;
3077 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3080 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3082 "%% Value does not match with config\n");
3085 bgp_vrf
->evpn_info
->dad_max_moves
=
3086 EVPN_DAD_DEFAULT_MAX_MOVES
;
3090 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3092 "%% Value does not match with config\n");
3095 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3099 if (bgp_vrf
->evpn_info
->dad_freeze_time
3102 "%% Value does not match with config\n");
3105 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3106 bgp_vrf
->evpn_info
->dad_freeze
= false;
3109 if (permanent_val
) {
3110 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3112 "%% Value does not match with config\n");
3115 bgp_vrf
->evpn_info
->dad_freeze
= false;
3119 bgp_zebra_dup_addr_detection(bgp_vrf
);
3124 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3125 bgp_evpn_advertise_vni_subnet_cmd
,
3127 "Advertise the subnet corresponding to VNI\n")
3129 struct bgp
*bgp_vrf
= NULL
;
3130 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3131 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3136 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3140 evpn_set_advertise_subnet(bgp
, vpn
);
3144 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3145 no_bgp_evpn_advertise_vni_subnet_cmd
,
3146 "no advertise-subnet",
3148 "Advertise All local VNIs\n")
3150 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3151 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3156 evpn_unset_advertise_subnet(bgp
, vpn
);
3160 DEFUN (bgp_evpn_advertise_type5
,
3161 bgp_evpn_advertise_type5_cmd
,
3162 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3163 "Advertise prefix routes\n"
3166 "route-map for filtering specific routes\n"
3167 "Name of the route map\n")
3169 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3176 int rmap_changed
= 0;
3178 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3179 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3180 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3182 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3184 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3185 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3188 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3192 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3194 "%%only ipv4 or ipv6 address families are supported");
3198 if (safi
!= SAFI_UNICAST
) {
3200 "%%only ipv4 unicast or ipv6 unicast are supported");
3204 if (afi
== AFI_IP
) {
3206 /* if we are already advertising ipv4 prefix as type-5
3209 if (!rmap_changed
&&
3210 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3211 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3213 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3214 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3217 /* if we are already advertising ipv6 prefix as type-5
3220 if (!rmap_changed
&&
3221 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3222 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3224 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3225 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3229 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3230 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3231 XFREE(MTYPE_ROUTE_MAP_NAME
,
3232 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3233 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3234 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3238 /* set the route-map for advertise command */
3239 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3240 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3241 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3242 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3243 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3246 /* advertise type-5 routes */
3247 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3251 DEFUN (no_bgp_evpn_advertise_type5
,
3252 no_bgp_evpn_advertise_type5_cmd
,
3253 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3255 "Advertise prefix routes\n"
3259 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3265 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3266 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3268 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3270 "%%only ipv4 or ipv6 address families are supported");
3274 if (safi
!= SAFI_UNICAST
) {
3276 "%%only ipv4 unicast or ipv6 unicast are supported");
3280 if (afi
== AFI_IP
) {
3282 /* if we are not advertising ipv4 prefix as type-5
3285 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3286 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3287 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3288 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3289 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3293 /* if we are not advertising ipv6 prefix as type-5
3296 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3297 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3298 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3299 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3300 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3304 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3305 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3306 XFREE(MTYPE_ROUTE_MAP_NAME
,
3307 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3308 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3309 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3316 * Display VNI information - for all or a specific VNI
3318 DEFUN(show_bgp_l2vpn_evpn_vni
,
3319 show_bgp_l2vpn_evpn_vni_cmd
,
3320 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3329 struct bgp
*bgp_def
;
3333 json_object
*json
= NULL
;
3334 uint32_t num_l2vnis
= 0;
3335 uint32_t num_l3vnis
= 0;
3336 uint32_t num_vnis
= 0;
3337 struct listnode
*node
= NULL
;
3338 struct bgp
*bgp_temp
= NULL
;
3340 uj
= use_json(argc
, argv
);
3342 bgp_def
= bgp_get_default();
3346 if (!argv_find(argv
, argc
, "evpn", &idx
))
3350 json
= json_object_new_object();
3352 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3354 num_l2vnis
= hashcount(bgp_def
->vnihash
);
3356 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3357 if (bgp_temp
->l3vni
)
3360 num_vnis
= num_l2vnis
+ num_l3vnis
;
3362 json_object_string_add(json
, "advertiseGatewayMacip",
3363 bgp_def
->advertise_gw_macip
3366 json_object_string_add(json
, "advertiseAllVnis",
3367 is_evpn_enabled() ? "Enabled"
3369 json_object_string_add(
3371 bgp_def
->vxlan_flood_ctrl
3372 == VXLAN_FLOOD_HEAD_END_REPL
3373 ? "Head-end replication"
3375 json_object_int_add(json
, "numVnis", num_vnis
);
3376 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3377 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3379 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3380 bgp_def
->advertise_gw_macip
? "Enabled"
3382 vty_out(vty
, "Advertise All VNI flag: %s\n",
3383 is_evpn_enabled() ? "Enabled" : "Disabled");
3384 vty_out(vty
, "BUM flooding: %s\n",
3385 bgp_def
->vxlan_flood_ctrl
3386 == VXLAN_FLOOD_HEAD_END_REPL
3387 ? "Head-end replication"
3389 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3390 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3392 evpn_show_all_vnis(vty
, bgp_def
, json
);
3396 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3399 /* Display specific VNI */
3400 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3401 evpn_show_vni(vty
, bgp_def
, vni
, json
);
3405 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3406 json
, JSON_C_TO_STRING_PRETTY
));
3407 json_object_free(json
);
3414 DEFUN(show_bgp_l2vpn_evpn_es
,
3415 show_bgp_l2vpn_evpn_es_cmd
,
3416 "show bgp l2vpn evpn es [ESI] [json]",
3421 "ethernet-Segment\n"
3422 "Ethernet-Segment Identifier\n"
3428 json_object
*json
= NULL
;
3429 struct bgp
*bgp
= NULL
;
3431 memset(&esi
, 0, sizeof(esi
));
3432 uj
= use_json(argc
, argv
);
3434 bgp
= bgp_get_default();
3438 if (!argv_find(argv
, argc
, "evpn", &idx
))
3441 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3442 (!uj
&& argc
== (idx
+ 1) + 1)) {
3445 evpn_show_all_es(vty
, bgp
, json
);
3448 /* show a specific ES */
3450 /* get the ESI - ESI-ID is at argv[5] */
3451 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3452 vty_out(vty
, "%% Malformed ESI\n");
3455 evpn_show_es(vty
, bgp
, &esi
, json
);
3459 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3460 json
, JSON_C_TO_STRING_PRETTY
));
3461 json_object_free(json
);
3468 * Display EVPN neighbor summary.
3470 DEFUN(show_bgp_l2vpn_evpn_summary
,
3471 show_bgp_l2vpn_evpn_summary_cmd
,
3472 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3479 "Summary of BGP neighbor status\n"
3483 bool uj
= use_json(argc
, argv
);
3486 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3487 vrf
= argv
[++idx_vrf
]->arg
;
3488 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3492 * Display global EVPN routing table.
3494 DEFUN(show_bgp_l2vpn_evpn_route
,
3495 show_bgp_l2vpn_evpn_route_cmd
,
3496 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3501 "EVPN route information\n"
3502 "Specify Route type\n"
3503 "MAC-IP (Type-2) route\n"
3504 "Multicast (Type-3) route\n"
3505 "Ethernet Segment (type-4) route \n"
3506 "Prefix (type-5 )route\n"
3513 json_object
*json
= NULL
;
3515 uj
= use_json(argc
, argv
);
3517 bgp
= bgp_get_default();
3522 json
= json_object_new_object();
3525 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3526 /* Specific type is requested */
3527 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3528 type
= BGP_EVPN_MAC_IP_ROUTE
;
3529 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3530 type
= BGP_EVPN_IMET_ROUTE
;
3531 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3532 type
= BGP_EVPN_ES_ROUTE
;
3533 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3534 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3539 evpn_show_all_routes(vty
, bgp
, type
, json
);
3542 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3543 json
, JSON_C_TO_STRING_PRETTY
));
3544 json_object_free(json
);
3550 * Display global EVPN routing table for specific RD.
3552 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3553 show_bgp_l2vpn_evpn_route_rd_cmd
,
3554 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3559 "EVPN route information\n"
3560 "Route Distinguisher\n"
3561 "ASN:XX or A.B.C.D:XX\n"
3562 "Specify Route type\n"
3563 "MAC-IP (Type-2) route\n"
3564 "Multicast (Type-3) route\n"
3565 "Ethernet Segment route\n"
3571 struct prefix_rd prd
;
3576 json_object
*json
= NULL
;
3578 bgp
= bgp_get_default();
3582 /* check if we need json output */
3583 uj
= use_json(argc
, argv
);
3585 json
= json_object_new_object();
3588 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3589 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3592 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3598 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3599 /* Specific type is requested */
3600 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3601 type
= BGP_EVPN_MAC_IP_ROUTE
;
3602 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3603 type
= BGP_EVPN_IMET_ROUTE
;
3604 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3605 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3610 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3613 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3614 json
, JSON_C_TO_STRING_PRETTY
));
3615 json_object_free(json
);
3622 * Display global EVPN routing table for specific RD and MACIP.
3624 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3625 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3626 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3631 "EVPN route information\n"
3632 "Route Distinguisher\n"
3633 "ASN:XX or A.B.C.D:XX\n"
3635 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3637 "IP address (IPv4 or IPv6)\n"
3642 struct prefix_rd prd
;
3649 json_object
*json
= NULL
;
3651 memset(&mac
, 0, sizeof(struct ethaddr
));
3652 memset(&ip
, 0, sizeof(struct ipaddr
));
3654 bgp
= bgp_get_default();
3658 /* check if we need json output */
3659 uj
= use_json(argc
, argv
);
3661 json
= json_object_new_object();
3664 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3665 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3667 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3673 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3674 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3675 vty_out(vty
, "%% Malformed MAC address\n");
3680 /* get the ip if specified */
3681 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3682 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3683 vty_out(vty
, "%% Malformed IP address\n");
3688 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3691 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3692 json
, JSON_C_TO_STRING_PRETTY
));
3693 json_object_free(json
);
3699 /* Display per ESI routing table */
3700 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3701 show_bgp_l2vpn_evpn_route_esi_cmd
,
3702 "show bgp l2vpn evpn route esi ESI [json]",
3707 "EVPN route information\n"
3708 "Ethernet Segment Identifier\n"
3714 struct bgp
*bgp
= NULL
;
3715 json_object
*json
= NULL
;
3717 memset(&esi
, 0, sizeof(esi
));
3718 bgp
= bgp_get_default();
3722 uj
= use_json(argc
, argv
);
3724 json
= json_object_new_object();
3726 /* get the ESI - ESI-ID is at argv[6] */
3727 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3728 vty_out(vty
, "%% Malformed ESI\n");
3732 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3735 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3736 json
, JSON_C_TO_STRING_PRETTY
));
3737 json_object_free(json
);
3745 * Display per-VNI EVPN routing table.
3747 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3748 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3753 "EVPN route information\n"
3754 "VXLAN Network Identifier\n"
3756 "Specify Route type\n"
3757 "MAC-IP (Type-2) route\n"
3758 "Multicast (Type-3) route\n"
3760 "Remote VTEP IP address\n"
3765 struct in_addr vtep_ip
;
3769 json_object
*json
= NULL
;
3771 bgp
= bgp_get_default();
3775 /* check if we need json output */
3776 uj
= use_json(argc
, argv
);
3778 json
= json_object_new_object();
3780 if (!argv_find(argv
, argc
, "evpn", &idx
))
3785 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3787 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3788 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3789 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3790 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3791 type
= BGP_EVPN_MAC_IP_ROUTE
;
3792 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3793 type
= BGP_EVPN_IMET_ROUTE
;
3796 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3797 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3798 vty_out(vty
, "%% Malformed VTEP IP address\n");
3805 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3808 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3809 json
, JSON_C_TO_STRING_PRETTY
));
3810 json_object_free(json
);
3817 * Display per-VNI EVPN routing table for specific MACIP.
3819 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3820 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3821 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
3826 "EVPN route information\n"
3827 "VXLAN Network Identifier\n"
3830 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3832 "IP address (IPv4 or IPv6)\n"
3841 json_object
*json
= NULL
;
3843 bgp
= bgp_get_default();
3847 /* check if we need json output */
3848 uj
= use_json(argc
, argv
);
3850 json
= json_object_new_object();
3852 if (!argv_find(argv
, argc
, "evpn", &idx
))
3856 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3859 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3860 vty_out(vty
, "%% Malformed MAC address\n");
3865 memset(&ip
, 0, sizeof(ip
));
3866 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3868 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3869 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3870 vty_out(vty
, "%% Malformed IP address\n");
3875 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3878 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3879 json
, JSON_C_TO_STRING_PRETTY
));
3880 json_object_free(json
);
3887 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3889 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3890 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3891 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
3896 "EVPN route information\n"
3897 "VXLAN Network Identifier\n"
3899 "Multicast (Type-3) route\n"
3900 "Originating Router IP address\n"
3906 struct in_addr orig_ip
;
3909 json_object
*json
= NULL
;
3911 bgp
= bgp_get_default();
3915 /* check if we need json output */
3916 uj
= use_json(argc
, argv
);
3918 json
= json_object_new_object();
3920 if (!argv_find(argv
, argc
, "evpn", &idx
))
3924 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3927 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3929 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3933 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3936 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3937 json
, JSON_C_TO_STRING_PRETTY
));
3938 json_object_free(json
);
3945 * Display per-VNI EVPN routing table - for all VNIs.
3947 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3948 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3949 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3954 "EVPN route information\n"
3955 "VXLAN Network Identifier\n"
3958 "Remote VTEP IP address\n"
3962 struct in_addr vtep_ip
;
3965 json_object
*json
= NULL
;
3967 bgp
= bgp_get_default();
3971 /* check if we need json output */
3972 uj
= use_json(argc
, argv
);
3974 json
= json_object_new_object();
3976 if (!argv_find(argv
, argc
, "evpn", &idx
))
3980 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3981 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3982 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3983 vty_out(vty
, "%% Malformed VTEP IP address\n");
3988 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3991 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3992 json
, JSON_C_TO_STRING_PRETTY
));
3993 json_object_free(json
);
4000 * Display EVPN import route-target hash table
4002 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4003 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4004 "show bgp l2vpn evpn vrf-import-rt [json]",
4009 "Show vrf import route target\n"
4013 struct bgp
*bgp_def
= NULL
;
4014 json_object
*json
= NULL
;
4016 bgp_def
= bgp_get_default();
4020 uj
= use_json(argc
, argv
);
4022 json
= json_object_new_object();
4024 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
4027 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4028 json
, JSON_C_TO_STRING_PRETTY
));
4029 json_object_free(json
);
4036 * Display EVPN import route-target hash table
4038 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4039 show_bgp_l2vpn_evpn_import_rt_cmd
,
4040 "show bgp l2vpn evpn import-rt [json]",
4045 "Show import route target\n"
4050 json_object
*json
= NULL
;
4052 bgp
= bgp_get_default();
4056 uj
= use_json(argc
, argv
);
4058 json
= json_object_new_object();
4060 evpn_show_import_rts(vty
, bgp
, json
);
4063 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4064 json
, JSON_C_TO_STRING_PRETTY
));
4065 json_object_free(json
);
4071 DEFUN(test_adv_evpn_type4_route
,
4072 test_adv_evpn_type4_route_cmd
,
4074 "Advertise EVPN ES route\n"
4075 "Ethernet-segment\n"
4076 "Ethernet-Segment Identifier\n")
4081 struct ipaddr vtep_ip
;
4083 bgp
= bgp_get_default();
4085 vty_out(vty
, "%%Default BGP instance not yet created\n");
4089 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4090 vty_out(vty
, "%%Malformed ESI\n");
4094 vtep_ip
.ipa_type
= IPADDR_V4
;
4095 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4097 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4099 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4105 DEFUN(test_withdraw_evpn_type4_route
,
4106 test_withdraw_evpn_type4_route_cmd
,
4108 "Advertise EVPN ES route\n"
4109 "Ethernet-segment\n"
4110 "Ethernet-Segment Identifier\n")
4115 struct ipaddr vtep_ip
;
4117 bgp
= bgp_get_default();
4119 vty_out(vty
, "%%Default BGP instance not yet created\n");
4123 if (!bgp
->peer_self
) {
4124 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4128 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4129 vty_out(vty
, "%%Malformed ESI\n");
4133 vtep_ip
.ipa_type
= IPADDR_V4
;
4134 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4135 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4137 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4143 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4144 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4148 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4149 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4150 "Summary of BGP neighbor status\n" JSON_STR
)
4152 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4153 "show bgp evpn route [type <macip|multicast>]",
4154 SHOW_STR BGP_STR EVPN_HELP_STR
4155 "EVPN route information\n"
4156 "Specify Route type\n"
4157 "MAC-IP (Type-2) route\n"
4158 "Multicast (Type-3) route\n")
4161 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4162 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4163 SHOW_STR BGP_STR EVPN_HELP_STR
4164 "EVPN route information\n"
4165 "Route Distinguisher\n"
4166 "ASN:XX or A.B.C.D:XX\n"
4167 "Specify Route type\n"
4168 "MAC-IP (Type-2) route\n"
4169 "Multicast (Type-3) route\n")
4172 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4173 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4174 SHOW_STR BGP_STR EVPN_HELP_STR
4175 "EVPN route information\n"
4176 "Route Distinguisher\n"
4177 "ASN:XX or A.B.C.D:XX\n"
4179 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4181 "IP address (IPv4 or IPv6)\n")
4184 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4185 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4186 SHOW_STR BGP_STR EVPN_HELP_STR
4187 "EVPN route information\n"
4188 "VXLAN Network Identifier\n"
4190 "Specify Route type\n"
4191 "MAC-IP (Type-2) route\n"
4192 "Multicast (Type-3) route\n"
4194 "Remote VTEP IP address\n")
4196 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4197 show_bgp_evpn_route_vni_macip_cmd
,
4198 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4199 SHOW_STR BGP_STR EVPN_HELP_STR
4200 "EVPN route information\n"
4201 "VXLAN Network Identifier\n"
4204 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4206 "IP address (IPv4 or IPv6)\n")
4208 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4209 show_bgp_evpn_route_vni_multicast_cmd
,
4210 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4211 SHOW_STR BGP_STR EVPN_HELP_STR
4212 "EVPN route information\n"
4213 "VXLAN Network Identifier\n"
4215 "Multicast (Type-3) route\n"
4216 "Originating Router IP address\n")
4218 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4219 "show bgp evpn route vni all [vtep A.B.C.D]",
4220 SHOW_STR BGP_STR EVPN_HELP_STR
4221 "EVPN route information\n"
4222 "VXLAN Network Identifier\n"
4225 "Remote VTEP IP address\n")
4227 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4228 "show bgp evpn import-rt",
4229 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4231 DEFUN_NOSH (bgp_evpn_vni
,
4233 "vni " CMD_VNI_RANGE
,
4234 "VXLAN Network Identifier\n"
4238 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4239 struct bgpevpn
*vpn
;
4244 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4246 /* Create VNI, or mark as configured. */
4247 vpn
= evpn_create_update_vni(bgp
, vni
);
4249 vty_out(vty
, "%% Failed to create VNI \n");
4253 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4257 DEFUN (no_bgp_evpn_vni
,
4258 no_bgp_evpn_vni_cmd
,
4259 "no vni " CMD_VNI_RANGE
,
4261 "VXLAN Network Identifier\n"
4265 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4266 struct bgpevpn
*vpn
;
4271 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4273 /* Check if we should disallow. */
4274 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4276 vty_out(vty
, "%% Specified VNI does not exist\n");
4279 if (!is_vni_configured(vpn
)) {
4280 vty_out(vty
, "%% Specified VNI is not configured\n");
4284 evpn_delete_vni(bgp
, vpn
);
4288 DEFUN_NOSH (exit_vni
,
4291 "Exit from VNI mode\n")
4293 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4294 vty
->node
= BGP_EVPN_NODE
;
4298 DEFUN (bgp_evpn_vrf_rd
,
4299 bgp_evpn_vrf_rd_cmd
,
4300 "rd ASN:NN_OR_IP-ADDRESS:NN",
4301 "Route Distinguisher\n"
4302 "ASN:XX or A.B.C.D:XX\n")
4305 struct prefix_rd prd
;
4306 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4311 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4313 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4317 /* If same as existing value, there is nothing more to do. */
4318 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4321 /* Configure or update the RD. */
4322 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4326 DEFUN (no_bgp_evpn_vrf_rd
,
4327 no_bgp_evpn_vrf_rd_cmd
,
4328 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4330 "Route Distinguisher\n"
4331 "ASN:XX or A.B.C.D:XX\n")
4334 struct prefix_rd prd
;
4335 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4340 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4342 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4346 /* Check if we should disallow. */
4347 if (!is_vrf_rd_configured(bgp_vrf
)) {
4348 vty_out(vty
, "%% RD is not configured for this VRF\n");
4352 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4354 "%% RD specified does not match configuration for this VRF\n");
4358 evpn_unconfigure_vrf_rd(bgp_vrf
);
4362 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4363 no_bgp_evpn_vrf_rd_without_val_cmd
,
4366 "Route Distinguisher\n")
4368 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4373 /* Check if we should disallow. */
4374 if (!is_vrf_rd_configured(bgp_vrf
)) {
4375 vty_out(vty
, "%% RD is not configured for this VRF\n");
4379 evpn_unconfigure_vrf_rd(bgp_vrf
);
4383 DEFUN (bgp_evpn_vni_rd
,
4384 bgp_evpn_vni_rd_cmd
,
4385 "rd ASN:NN_OR_IP-ADDRESS:NN",
4386 "Route Distinguisher\n"
4387 "ASN:XX or A.B.C.D:XX\n")
4389 struct prefix_rd prd
;
4390 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4391 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4397 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4399 "This command is only supported under Default VRF\n");
4403 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4405 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4409 /* If same as existing value, there is nothing more to do. */
4410 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4413 /* Configure or update the RD. */
4414 evpn_configure_rd(bgp
, vpn
, &prd
);
4418 DEFUN (no_bgp_evpn_vni_rd
,
4419 no_bgp_evpn_vni_rd_cmd
,
4420 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4422 "Route Distinguisher\n"
4423 "ASN:XX or A.B.C.D:XX\n")
4425 struct prefix_rd prd
;
4426 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4427 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4433 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4435 "This command is only supported under Default VRF\n");
4439 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4441 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4445 /* Check if we should disallow. */
4446 if (!is_rd_configured(vpn
)) {
4447 vty_out(vty
, "%% RD is not configured for this VNI\n");
4451 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4453 "%% RD specified does not match configuration for this VNI\n");
4457 evpn_unconfigure_rd(bgp
, vpn
);
4461 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4462 no_bgp_evpn_vni_rd_without_val_cmd
,
4465 "Route Distinguisher\n")
4467 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4468 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4473 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4475 "This command is only supported under Default VRF\n");
4479 /* Check if we should disallow. */
4480 if (!is_rd_configured(vpn
)) {
4481 vty_out(vty
, "%% RD is not configured for this VNI\n");
4485 evpn_unconfigure_rd(bgp
, vpn
);
4490 * Loop over all extended-communities in the route-target list rtl and
4491 * return 1 if we find ecomtarget
4493 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4494 struct ecommunity
*ecomtarget
)
4496 struct listnode
*node
, *nnode
;
4497 struct ecommunity
*ecom
;
4499 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4500 if (ecommunity_match(ecom
, ecomtarget
))
4507 /* display L3VNI related info for a VRF instance */
4508 DEFUN (show_bgp_vrf_l3vni_info
,
4509 show_bgp_vrf_l3vni_info_cmd
,
4510 "show bgp vrf VRFNAME vni [json]",
4518 char buf
[ETHER_ADDR_STRLEN
];
4519 char buf1
[INET6_ADDRSTRLEN
];
4521 const char *name
= NULL
;
4522 struct bgp
*bgp
= NULL
;
4523 struct listnode
*node
= NULL
;
4524 struct bgpevpn
*vpn
= NULL
;
4525 struct ecommunity
*ecom
= NULL
;
4526 json_object
*json
= NULL
;
4527 json_object
*json_vnis
= NULL
;
4528 json_object
*json_export_rts
= NULL
;
4529 json_object
*json_import_rts
= NULL
;
4530 bool uj
= use_json(argc
, argv
);
4533 json
= json_object_new_object();
4534 json_vnis
= json_object_new_array();
4535 json_export_rts
= json_object_new_array();
4536 json_import_rts
= json_object_new_array();
4539 name
= argv
[idx_vrf
]->arg
;
4540 bgp
= bgp_lookup_by_name(name
);
4543 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4545 json_object_string_add(json
, "warning",
4546 "BGP instance not found");
4547 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4548 json_object_free(json
);
4554 vty_out(vty
, "BGP VRF: %s\n", name
);
4555 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4556 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4557 vty_out(vty
, " Rmac: %s\n",
4558 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4559 vty_out(vty
, " VNI Filter: %s\n",
4560 CHECK_FLAG(bgp
->vrf_flags
,
4561 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4562 ? "prefix-routes-only"
4564 vty_out(vty
, " L2-VNI List:\n");
4566 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4567 vty_out(vty
, "%u ", vpn
->vni
);
4569 vty_out(vty
, " Export-RTs:\n");
4571 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4572 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4574 vty_out(vty
, " Import-RTs:\n");
4576 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4577 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4579 vty_out(vty
, " RD: %s\n",
4580 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4582 json_object_string_add(json
, "vrf", name
);
4583 json_object_string_add(json
, "local-ip",
4584 inet_ntoa(bgp
->originator_ip
));
4585 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4586 json_object_string_add(
4588 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4589 json_object_string_add(
4591 CHECK_FLAG(bgp
->vrf_flags
,
4592 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4593 ? "prefix-routes-only"
4595 /* list of l2vnis */
4596 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4597 json_object_array_add(json_vnis
,
4598 json_object_new_int(vpn
->vni
));
4599 json_object_object_add(json
, "l2vnis", json_vnis
);
4602 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4603 json_object_array_add(
4605 json_object_new_string(ecommunity_str(ecom
)));
4606 json_object_object_add(json
, "export-rts", json_export_rts
);
4609 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4610 json_object_array_add(
4612 json_object_new_string(ecommunity_str(ecom
)));
4613 json_object_object_add(json
, "import-rts", json_import_rts
);
4614 json_object_string_add(
4616 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4620 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4621 json
, JSON_C_TO_STRING_PRETTY
));
4622 json_object_free(json
);
4627 /* import/export rt for l3vni-vrf */
4628 DEFUN (bgp_evpn_vrf_rt
,
4629 bgp_evpn_vrf_rt_cmd
,
4630 "route-target <both|import|export> RT",
4632 "import and export\n"
4635 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4638 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4639 struct ecommunity
*ecomadd
= NULL
;
4644 if (!strcmp(argv
[1]->arg
, "import"))
4645 rt_type
= RT_TYPE_IMPORT
;
4646 else if (!strcmp(argv
[1]->arg
, "export"))
4647 rt_type
= RT_TYPE_EXPORT
;
4648 else if (!strcmp(argv
[1]->arg
, "both"))
4649 rt_type
= RT_TYPE_BOTH
;
4651 vty_out(vty
, "%% Invalid Route Target type\n");
4655 /* Add/update the import route-target */
4656 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4657 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4658 ECOMMUNITY_ROUTE_TARGET
, 0);
4660 vty_out(vty
, "%% Malformed Route Target list\n");
4663 ecommunity_str(ecomadd
);
4665 /* Do nothing if we already have this import route-target */
4666 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4667 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4670 /* Add/update the export route-target */
4671 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4672 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4673 ECOMMUNITY_ROUTE_TARGET
, 0);
4675 vty_out(vty
, "%% Malformed Route Target list\n");
4678 ecommunity_str(ecomadd
);
4680 /* Do nothing if we already have this export route-target */
4681 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4682 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4688 DEFUN (no_bgp_evpn_vrf_rt
,
4689 no_bgp_evpn_vrf_rt_cmd
,
4690 "no route-target <both|import|export> RT",
4693 "import and export\n"
4696 "ASN:XX or A.B.C.D:XX\n")
4698 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4699 int rt_type
, found_ecomdel
;
4700 struct ecommunity
*ecomdel
= NULL
;
4705 if (!strcmp(argv
[2]->arg
, "import"))
4706 rt_type
= RT_TYPE_IMPORT
;
4707 else if (!strcmp(argv
[2]->arg
, "export"))
4708 rt_type
= RT_TYPE_EXPORT
;
4709 else if (!strcmp(argv
[2]->arg
, "both"))
4710 rt_type
= RT_TYPE_BOTH
;
4712 vty_out(vty
, "%% Invalid Route Target type\n");
4716 if (rt_type
== RT_TYPE_IMPORT
) {
4717 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4719 "%% Import RT is not configured for this VRF\n");
4722 } else if (rt_type
== RT_TYPE_EXPORT
) {
4723 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4725 "%% Export RT is not configured for this VRF\n");
4728 } else if (rt_type
== RT_TYPE_BOTH
) {
4729 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4730 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4732 "%% Import/Export RT is not configured for this VRF\n");
4737 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4739 vty_out(vty
, "%% Malformed Route Target list\n");
4742 ecommunity_str(ecomdel
);
4744 if (rt_type
== RT_TYPE_IMPORT
) {
4745 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4748 "%% RT specified does not match configuration for this VRF\n");
4751 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4752 } else if (rt_type
== RT_TYPE_EXPORT
) {
4753 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4756 "%% RT specified does not match configuration for this VRF\n");
4759 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4760 } else if (rt_type
== RT_TYPE_BOTH
) {
4763 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4765 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4769 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4771 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4775 if (!found_ecomdel
) {
4777 "%% RT specified does not match configuration for this VRF\n");
4785 DEFUN (bgp_evpn_vni_rt
,
4786 bgp_evpn_vni_rt_cmd
,
4787 "route-target <both|import|export> RT",
4789 "import and export\n"
4792 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4794 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4795 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4797 struct ecommunity
*ecomadd
= NULL
;
4802 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4804 "This command is only supported under Default VRF\n");
4808 if (!strcmp(argv
[1]->text
, "import"))
4809 rt_type
= RT_TYPE_IMPORT
;
4810 else if (!strcmp(argv
[1]->text
, "export"))
4811 rt_type
= RT_TYPE_EXPORT
;
4812 else if (!strcmp(argv
[1]->text
, "both"))
4813 rt_type
= RT_TYPE_BOTH
;
4815 vty_out(vty
, "%% Invalid Route Target type\n");
4819 /* Add/update the import route-target */
4820 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4821 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4822 ECOMMUNITY_ROUTE_TARGET
, 0);
4824 vty_out(vty
, "%% Malformed Route Target list\n");
4827 ecommunity_str(ecomadd
);
4829 /* Do nothing if we already have this import route-target */
4830 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4831 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4834 /* Add/update the export route-target */
4835 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4836 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4837 ECOMMUNITY_ROUTE_TARGET
, 0);
4839 vty_out(vty
, "%% Malformed Route Target list\n");
4842 ecommunity_str(ecomadd
);
4844 /* Do nothing if we already have this export route-target */
4845 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4846 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4852 DEFUN (no_bgp_evpn_vni_rt
,
4853 no_bgp_evpn_vni_rt_cmd
,
4854 "no route-target <both|import|export> RT",
4857 "import and export\n"
4860 "ASN:XX or A.B.C.D:XX\n")
4862 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4863 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4864 int rt_type
, found_ecomdel
;
4865 struct ecommunity
*ecomdel
= NULL
;
4870 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4872 "This command is only supported under Default VRF\n");
4876 if (!strcmp(argv
[2]->text
, "import"))
4877 rt_type
= RT_TYPE_IMPORT
;
4878 else if (!strcmp(argv
[2]->text
, "export"))
4879 rt_type
= RT_TYPE_EXPORT
;
4880 else if (!strcmp(argv
[2]->text
, "both"))
4881 rt_type
= RT_TYPE_BOTH
;
4883 vty_out(vty
, "%% Invalid Route Target type\n");
4887 /* The user did "no route-target import", check to see if there are any
4888 * import route-targets configured. */
4889 if (rt_type
== RT_TYPE_IMPORT
) {
4890 if (!is_import_rt_configured(vpn
)) {
4892 "%% Import RT is not configured for this VNI\n");
4895 } else if (rt_type
== RT_TYPE_EXPORT
) {
4896 if (!is_export_rt_configured(vpn
)) {
4898 "%% Export RT is not configured for this VNI\n");
4901 } else if (rt_type
== RT_TYPE_BOTH
) {
4902 if (!is_import_rt_configured(vpn
)
4903 && !is_export_rt_configured(vpn
)) {
4905 "%% Import/Export RT is not configured for this VNI\n");
4910 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4912 vty_out(vty
, "%% Malformed Route Target list\n");
4915 ecommunity_str(ecomdel
);
4917 if (rt_type
== RT_TYPE_IMPORT
) {
4918 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4920 "%% RT specified does not match configuration for this VNI\n");
4923 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4924 } else if (rt_type
== RT_TYPE_EXPORT
) {
4925 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4927 "%% RT specified does not match configuration for this VNI\n");
4930 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4931 } else if (rt_type
== RT_TYPE_BOTH
) {
4934 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4935 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4939 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4940 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4944 if (!found_ecomdel
) {
4946 "%% RT specified does not match configuration for this VNI\n");
4954 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4955 no_bgp_evpn_vni_rt_without_val_cmd
,
4956 "no route-target <import|export>",
4962 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4963 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4969 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4971 "This command is only supported under Default VRF\n");
4975 if (!strcmp(argv
[2]->text
, "import")) {
4976 rt_type
= RT_TYPE_IMPORT
;
4977 } else if (!strcmp(argv
[2]->text
, "export")) {
4978 rt_type
= RT_TYPE_EXPORT
;
4980 vty_out(vty
, "%% Invalid Route Target type\n");
4984 /* Check if we should disallow. */
4985 if (rt_type
== RT_TYPE_IMPORT
) {
4986 if (!is_import_rt_configured(vpn
)) {
4988 "%% Import RT is not configured for this VNI\n");
4992 if (!is_export_rt_configured(vpn
)) {
4994 "%% Export RT is not configured for this VNI\n");
4999 /* Unconfigure the RT. */
5000 if (rt_type
== RT_TYPE_IMPORT
)
5001 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5003 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5007 static int vni_cmp(const void **a
, const void **b
)
5009 const struct bgpevpn
*first
= *a
;
5010 const struct bgpevpn
*secnd
= *b
;
5012 return secnd
->vni
- first
->vni
;
5016 * Output EVPN configuration information.
5018 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5021 char buf1
[RD_ADDRSTRLEN
];
5024 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5025 struct listnode
*ln
;
5026 struct bgpevpn
*data
;
5028 list_sort(vnilist
, vni_cmp
);
5029 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5030 write_vni_config(vty
, data
);
5032 list_delete(&vnilist
);
5035 if (bgp
->advertise_all_vni
)
5036 vty_out(vty
, " advertise-all-vni\n");
5038 if (bgp
->advertise_autort_rfc8365
)
5039 vty_out(vty
, " autort rfc8365-compatible\n");
5041 if (bgp
->advertise_gw_macip
)
5042 vty_out(vty
, " advertise-default-gw\n");
5044 if (!bgp
->evpn_info
->dup_addr_detect
)
5045 vty_out(vty
, " no dup-addr-detection\n");
5047 if (bgp
->evpn_info
->dad_max_moves
!=
5048 EVPN_DAD_DEFAULT_MAX_MOVES
||
5049 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5050 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5051 bgp
->evpn_info
->dad_max_moves
,
5052 bgp
->evpn_info
->dad_time
);
5054 if (bgp
->evpn_info
->dad_freeze
) {
5055 if (bgp
->evpn_info
->dad_freeze_time
)
5057 " dup-addr-detection freeze %u\n",
5058 bgp
->evpn_info
->dad_freeze_time
);
5061 " dup-addr-detection freeze permanent\n");
5064 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5065 vty_out(vty
, " flooding disable\n");
5067 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5068 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5069 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5070 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5071 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5073 vty_out(vty
, " advertise ipv4 unicast\n");
5076 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5077 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5078 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5079 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5080 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5082 vty_out(vty
, " advertise ipv6 unicast\n");
5085 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5086 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5087 vty_out(vty
, " default-originate ipv4\n");
5089 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5090 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5091 vty_out(vty
, " default-originate ipv6\n");
5093 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5094 vty_out(vty
, " rd %s\n",
5095 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5097 /* import route-target */
5098 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5100 struct listnode
*node
, *nnode
;
5101 struct ecommunity
*ecom
;
5103 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5105 ecom_str
= ecommunity_ecom2str(
5106 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5107 vty_out(vty
, " route-target import %s\n", ecom_str
);
5108 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5112 /* export route-target */
5113 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5115 struct listnode
*node
, *nnode
;
5116 struct ecommunity
*ecom
;
5118 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5120 ecom_str
= ecommunity_ecom2str(
5121 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5122 vty_out(vty
, " route-target export %s\n", ecom_str
);
5123 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5128 void bgp_ethernetvpn_init(void)
5130 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5131 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5132 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5133 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5134 install_element(VIEW_NODE
,
5135 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
5136 install_element(VIEW_NODE
,
5137 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5140 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
5143 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5144 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5145 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5146 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5147 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5148 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5149 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5150 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5151 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5152 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5153 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5154 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5155 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5156 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5157 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5158 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5159 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5160 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5161 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5164 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5165 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5167 /* "show bgp l2vpn evpn" commands. */
5168 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5169 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5170 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5171 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5172 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5173 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5174 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5175 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5176 install_element(VIEW_NODE
,
5177 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5178 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5179 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5180 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5181 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5183 /* "show bgp evpn" commands. */
5184 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5185 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5186 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5187 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5188 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5189 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5190 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5191 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5192 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5193 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5194 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5196 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5197 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5198 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5199 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5200 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5201 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5202 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5203 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5204 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5205 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5206 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5207 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5208 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5209 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5210 install_element(BGP_EVPN_VNI_NODE
,
5211 &bgp_evpn_advertise_default_gw_vni_cmd
);
5212 install_element(BGP_EVPN_VNI_NODE
,
5213 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5214 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5215 install_element(BGP_EVPN_VNI_NODE
,
5216 &no_bgp_evpn_advertise_vni_subnet_cmd
);