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_ecommunity.h"
40 #define SHOW_DISPLAY_STANDARD 0
41 #define SHOW_DISPLAY_TAGS 1
42 #define SHOW_DISPLAY_OVERLAY 2
43 #define VNI_STR_LEN 32
46 * Context for VNI hash walk - used by callbacks.
51 struct in_addr vtep_ip
;
55 #if defined(HAVE_CUMULUS)
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_int64(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(json
,"originatorIp",
430 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
432 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
433 json_object_array_add(json_vteps
,
434 json_object_new_string(inet_ntoa(*vtep
)));
436 json_object_object_add(json
, "vteps", json_vteps
);
438 vty_out(vty
, "ESI: %s\n",
439 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
440 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
442 vty_out(vty
, " Originator-IP: %s\n",
443 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
445 vty_out(vty
, " VTEP List:\n");
446 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
447 vty_out(vty
," %s\n", inet_ntoa(*vtep
));
452 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
454 char buf1
[RD_ADDRSTRLEN
];
456 struct listnode
*node
, *nnode
;
457 struct ecommunity
*ecom
;
458 json_object
*json_import_rtl
= NULL
;
459 json_object
*json_export_rtl
= NULL
;
462 json_import_rtl
= json_object_new_array();
463 json_export_rtl
= json_object_new_array();
464 json_object_int_add(json
, "vni", vpn
->vni
);
465 json_object_string_add(json
, "type", "L2");
466 json_object_string_add(json
, "kernelFlag",
467 is_vni_live(vpn
) ? "Yes" : "No");
468 json_object_string_add(
470 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
471 json_object_string_add(json
, "originatorIp",
472 inet_ntoa(vpn
->originator_ip
));
473 json_object_string_add(json
, "advertiseGatewayMacip",
474 vpn
->advertise_gw_macip
? "Yes" : "No");
476 vty_out(vty
, "VNI: %d", vpn
->vni
);
477 if (is_vni_live(vpn
))
478 vty_out(vty
, " (known to the kernel)");
481 vty_out(vty
, " Type: %s\n", "L2");
482 vty_out(vty
, " Tenant-Vrf: %s\n",
483 vrf_id_to_name(vpn
->tenant_vrf_id
));
484 vty_out(vty
, " RD: %s\n",
485 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
486 vty_out(vty
, " Originator IP: %s\n",
487 inet_ntoa(vpn
->originator_ip
));
488 vty_out(vty
, " Advertise-gw-macip : %s\n",
489 vpn
->advertise_gw_macip
? "Yes" : "No");
493 vty_out(vty
, " Import Route Target:\n");
495 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
496 ecom_str
= ecommunity_ecom2str(ecom
,
497 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
500 json_object_array_add(json_import_rtl
,
501 json_object_new_string(ecom_str
));
503 vty_out(vty
, " %s\n", ecom_str
);
505 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
509 json_object_object_add(json
, "importRts", json_import_rtl
);
511 vty_out(vty
, " Export Route Target:\n");
513 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
514 ecom_str
= ecommunity_ecom2str(ecom
,
515 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
518 json_object_array_add(json_export_rtl
,
519 json_object_new_string(ecom_str
));
521 vty_out(vty
, " %s\n", ecom_str
);
523 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
527 json_object_object_add(json
, "exportRts", json_export_rtl
);
530 static void show_esi_routes(struct bgp
*bgp
,
538 uint32_t prefix_cnt
, path_cnt
;
541 prefix_cnt
= path_cnt
= 0;
543 tbl_ver
= es
->route_table
->version
;
544 for (rn
= bgp_table_top(es
->route_table
); rn
;
545 rn
= bgp_route_next(rn
)) {
546 int add_prefix_to_json
= 0;
547 char prefix_str
[BUFSIZ
];
548 json_object
*json_paths
= NULL
;
549 json_object
*json_prefix
= NULL
;
551 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
555 json_prefix
= json_object_new_object();
558 /* Overall header/legend displayed once. */
560 bgp_evpn_show_route_header(vty
, bgp
,
569 json_paths
= json_object_new_array();
571 /* For EVPN, the prefix is displayed for each path (to fit in
572 * with code that already exists).
574 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
575 json_object
*json_path
= NULL
;
578 json_path
= json_object_new_array();
580 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
583 json_object_array_add(json_paths
, json_path
);
586 add_prefix_to_json
= 1;
589 if (json
&& add_prefix_to_json
) {
590 json_object_string_add(json_prefix
, "prefix",
592 json_object_int_add(json_prefix
, "prefixLen",
594 json_object_object_add(json_prefix
, "paths",
596 json_object_object_add(json
, prefix_str
, json_prefix
);
601 json_object_int_add(json
, "numPrefix", prefix_cnt
);
602 json_object_int_add(json
, "numPaths", path_cnt
);
605 vty_out(vty
, "No EVPN prefixes exist for this ESI");
607 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
608 prefix_cnt
, path_cnt
);
612 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
613 struct vty
*vty
, struct in_addr vtep_ip
,
618 struct bgp_table
*table
;
621 uint32_t prefix_cnt
, path_cnt
;
623 prefix_cnt
= path_cnt
= 0;
625 table
= vpn
->route_table
;
626 tbl_ver
= table
->version
;
627 for (rn
= bgp_table_top(table
); rn
;
628 rn
= bgp_route_next(rn
)) {
629 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
630 int add_prefix_to_json
= 0;
631 char prefix_str
[BUFSIZ
];
632 json_object
*json_paths
= NULL
;
633 json_object
*json_prefix
= NULL
;
635 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
638 if (type
&& evp
->prefix
.route_type
!= type
)
642 json_prefix
= json_object_new_object();
645 /* Overall header/legend displayed once. */
647 bgp_evpn_show_route_header(vty
, bgp
,
656 json_paths
= json_object_new_array();
658 /* For EVPN, the prefix is displayed for each path (to fit in
659 * with code that already exists).
661 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
662 json_object
*json_path
= NULL
;
665 && !IPV4_ADDR_SAME(&(vtep_ip
),
666 &(ri
->attr
->nexthop
)))
670 json_path
= json_object_new_array();
672 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
675 json_object_array_add(json_paths
, json_path
);
678 add_prefix_to_json
= 1;
681 if (json
&& add_prefix_to_json
) {
682 json_object_string_add(json_prefix
, "prefix",
684 json_object_int_add(json_prefix
, "prefixLen",
686 json_object_object_add(json_prefix
, "paths",
688 json_object_object_add(json
, prefix_str
, json_prefix
);
693 json_object_int_add(json
, "numPrefix", prefix_cnt
);
694 json_object_int_add(json
, "numPaths", path_cnt
);
697 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
698 type
? "(of requested type) " : "");
700 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
701 prefix_cnt
, path_cnt
,
702 type
? " (of requested type)" : "");
706 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
708 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
709 struct vni_walk_ctx
*wctx
= arg
;
710 struct vty
*vty
= wctx
->vty
;
711 json_object
*json
= wctx
->json
;
712 json_object
*json_vni
= NULL
;
713 char vni_str
[VNI_STR_LEN
];
715 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
717 json_vni
= json_object_new_object();
718 json_object_int_add(json_vni
, "vni", vpn
->vni
);
720 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
723 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
726 json_object_object_add(json
, vni_str
, json_vni
);
729 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
732 json_object
*json_vni
= NULL
;
733 json_object
*json_import_rtl
= NULL
;
734 json_object
*json_export_rtl
= NULL
;
736 char buf2
[INET6_ADDRSTRLEN
];
739 struct listnode
*node
, *nnode
;
740 struct ecommunity
*ecom
;
746 json_vni
= json_object_new_object();
747 json_import_rtl
= json_object_new_array();
748 json_export_rtl
= json_object_new_array();
751 /* if an l3vni is present in bgp it is live */
756 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
757 json_object_string_add(json_vni
, "type", "L3");
758 json_object_string_add(json_vni
, "inKernel", "True");
759 json_object_string_add(json_vni
, "originatorIp",
760 inet_ntoa(bgp
->originator_ip
));
761 json_object_string_add(
763 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
765 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
766 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
769 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
770 ecom_str
= ecommunity_ecom2str(ecom
,
771 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
774 json_object_array_add(json_import_rtl
,
775 json_object_new_string(ecom_str
));
777 if (listcount(bgp
->vrf_import_rtl
) > 1)
778 sprintf(rt_buf
, "%s, ...", ecom_str
);
780 sprintf(rt_buf
, "%s", ecom_str
);
781 vty_out(vty
, " %-25s", rt_buf
);
784 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
786 /* If there are multiple import RTs we break here and show only
793 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
795 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
796 ecom_str
= ecommunity_ecom2str(ecom
,
797 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
800 json_object_array_add(json_export_rtl
,
801 json_object_new_string(ecom_str
));
803 if (listcount(bgp
->vrf_export_rtl
) > 1)
804 sprintf(rt_buf
, "%s, ...", ecom_str
);
806 sprintf(rt_buf
, "%s", ecom_str
);
807 vty_out(vty
, " %-25s", rt_buf
);
810 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
812 /* If there are multiple export RTs we break here and show only
819 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
822 char vni_str
[VNI_STR_LEN
];
824 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
825 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
826 json_object_object_add(json
, vni_str
, json_vni
);
832 static void show_es_entry(struct hash_backet
*backet
, void *args
[])
834 char buf
[ESI_STR_LEN
];
835 char buf1
[RD_ADDRSTRLEN
];
836 char buf2
[INET6_ADDRSTRLEN
];
837 struct in_addr
*vtep
= NULL
;
838 struct vty
*vty
= args
[0];
839 json_object
*json
= args
[1];
840 json_object
*json_vteps
= NULL
;
841 struct listnode
*node
= NULL
;
842 struct evpnes
*es
= (struct evpnes
*)backet
->data
;
845 json_vteps
= json_object_new_array();
846 json_object_string_add(json
, "esi",
847 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
848 json_object_string_add(json
, "type",
849 is_es_local(es
) ? "Local" : "Remote");
850 json_object_string_add(json
, "rd",
851 prefix_rd2str(&es
->prd
, buf1
,
853 json_object_string_add(json
,"originatorIp",
854 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
856 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
857 json_object_array_add(json_vteps
,
858 json_object_new_string(
861 json_object_object_add(json
, "vteps", json_vteps
);
863 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
864 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
865 is_es_local(es
) ? "Local" : "Remote",
866 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
867 ipaddr2str(&es
->originator_ip
, buf2
,
869 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
873 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
877 json_object
*json_vni
= NULL
;
878 json_object
*json_import_rtl
= NULL
;
879 json_object
*json_export_rtl
= NULL
;
880 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
882 char buf2
[RD_ADDRSTRLEN
];
885 struct listnode
*node
, *nnode
;
886 struct ecommunity
*ecom
;
892 json_vni
= json_object_new_object();
893 json_import_rtl
= json_object_new_array();
894 json_export_rtl
= json_object_new_array();
898 if (is_vni_live(vpn
))
902 json_object_int_add(json_vni
, "vni", vpn
->vni
);
903 json_object_string_add(json_vni
, "type", "L2");
904 json_object_string_add(json_vni
, "inKernel",
905 is_vni_live(vpn
) ? "True" : "False");
906 json_object_string_add(json_vni
, "originatorIp",
907 inet_ntoa(vpn
->originator_ip
));
908 json_object_string_add(json_vni
, "originatorIp",
909 inet_ntoa(vpn
->originator_ip
));
910 json_object_string_add(
912 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
914 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
915 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
918 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
919 ecom_str
= ecommunity_ecom2str(ecom
,
920 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
923 json_object_array_add(json_import_rtl
,
924 json_object_new_string(ecom_str
));
926 if (listcount(vpn
->import_rtl
) > 1)
927 sprintf(rt_buf
, "%s, ...", ecom_str
);
929 sprintf(rt_buf
, "%s", ecom_str
);
930 vty_out(vty
, " %-25s", rt_buf
);
933 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
935 /* If there are multiple import RTs we break here and show only
942 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
944 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
945 ecom_str
= ecommunity_ecom2str(ecom
,
946 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
949 json_object_array_add(json_export_rtl
,
950 json_object_new_string(ecom_str
));
952 if (listcount(vpn
->export_rtl
) > 1)
953 sprintf(rt_buf
, "%s, ...", ecom_str
);
955 sprintf(rt_buf
, "%s", ecom_str
);
956 vty_out(vty
, " %-25s", rt_buf
);
959 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
961 /* If there are multiple export RTs we break here and show only
968 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
971 char vni_str
[VNI_STR_LEN
];
973 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
974 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
975 json_object_object_add(json
, vni_str
, json_vni
);
980 #endif /* HAVE_CUMULUS */
982 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
983 enum bgp_show_type type
, void *output_arg
,
984 int option
, uint8_t use_json
)
986 afi_t afi
= AFI_L2VPN
;
988 struct bgp_table
*table
;
995 unsigned long output_count
= 0;
996 unsigned long total_count
= 0;
997 json_object
*json
= NULL
;
998 json_object
*json_nroute
= NULL
;
999 json_object
*json_array
= NULL
;
1000 json_object
*json_scode
= NULL
;
1001 json_object
*json_ocode
= NULL
;
1003 bgp
= bgp_get_default();
1006 vty_out(vty
, "No BGP process is configured\n");
1008 vty_out(vty
, "{}\n");
1013 json_scode
= json_object_new_object();
1014 json_ocode
= json_object_new_object();
1015 json
= json_object_new_object();
1016 json_nroute
= json_object_new_object();
1018 json_object_string_add(json_scode
, "suppressed", "s");
1019 json_object_string_add(json_scode
, "damped", "d");
1020 json_object_string_add(json_scode
, "history", "h");
1021 json_object_string_add(json_scode
, "valid", "*");
1022 json_object_string_add(json_scode
, "best", ">");
1023 json_object_string_add(json_scode
, "internal", "i");
1025 json_object_string_add(json_ocode
, "igp", "i");
1026 json_object_string_add(json_ocode
, "egp", "e");
1027 json_object_string_add(json_ocode
, "incomplete", "?");
1030 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1031 rn
= bgp_route_next(rn
)) {
1035 continue; /* XXX json TODO */
1037 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1040 if ((table
= rn
->info
) == NULL
)
1044 tbl_ver
= table
->version
;
1046 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1047 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
1049 if (type
== bgp_show_type_neighbor
) {
1050 union sockunion
*su
= output_arg
;
1052 if (ri
->peer
->su_remote
== NULL
1054 ri
->peer
->su_remote
, su
))
1060 == SHOW_DISPLAY_TAGS
) {
1061 json_object_int_add(
1065 json_object_string_add(
1070 json_object_object_add(
1074 json_object_object_add(
1080 if (option
== SHOW_DISPLAY_TAGS
)
1085 == SHOW_DISPLAY_OVERLAY
)
1090 "BGP table version is %" PRIu64
", local router ID is %s\n",
1095 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1097 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1098 vty_out(vty
, V4_HEADER
);
1111 /* Decode RD type. */
1112 type
= decode_rd_type(pnt
);
1113 /* Decode RD value. */
1114 if (type
== RD_TYPE_AS
)
1115 decode_rd_as(pnt
+ 2, &rd_as
);
1116 else if (type
== RD_TYPE_AS4
)
1117 decode_rd_as4(pnt
+ 2, &rd_as
);
1118 else if (type
== RD_TYPE_IP
)
1119 decode_rd_ip(pnt
+ 2, &rd_ip
);
1121 char buffer
[BUFSIZ
];
1122 if (type
== RD_TYPE_AS
1123 || type
== RD_TYPE_AS4
)
1124 sprintf(buffer
, "%u:%d",
1127 else if (type
== RD_TYPE_IP
)
1128 sprintf(buffer
, "%s:%d",
1132 json_object_string_add(
1134 "routeDistinguisher",
1138 "Route Distinguisher: ");
1139 if (type
== RD_TYPE_AS
)
1144 else if (type
== RD_TYPE_AS4
)
1149 else if (type
== RD_TYPE_IP
)
1150 vty_out(vty
, "ip %s:%d",
1154 vty_out(vty
, "\n\n");
1159 json_array
= json_object_new_array();
1162 if (option
== SHOW_DISPLAY_TAGS
)
1163 route_vty_out_tag(vty
, &rm
->p
, ri
, 0,
1166 else if (option
== SHOW_DISPLAY_OVERLAY
)
1167 route_vty_out_overlay(vty
, &rm
->p
, ri
,
1170 route_vty_out(vty
, &rm
->p
, ri
, 0,
1171 SAFI_EVPN
, json_array
);
1176 if (output_count
== 0)
1177 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1179 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1180 output_count
, total_count
);
1184 DEFUN(show_ip_bgp_l2vpn_evpn
,
1185 show_ip_bgp_l2vpn_evpn_cmd
,
1186 "show [ip] bgp l2vpn evpn [json]",
1187 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1189 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1190 use_json(argc
, argv
));
1193 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1194 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1195 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1201 "Display information for a route distinguisher\n"
1202 "VPN Route Distinguisher\n" JSON_STR
)
1204 int idx_ext_community
= 0;
1206 struct prefix_rd prd
;
1208 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1210 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1212 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1215 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1216 use_json(argc
, argv
));
1219 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1220 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1221 "show [ip] bgp l2vpn evpn all tags",
1227 "Display information about all EVPN NLRIs\n"
1228 "Display BGP tags for prefixes\n")
1230 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1234 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1235 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1236 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1242 "Display information for a route distinguisher\n"
1243 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1245 int idx_ext_community
= 0;
1247 struct prefix_rd prd
;
1249 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1251 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1253 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1256 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1260 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1261 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1262 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1268 "Display information about all EVPN NLRIs\n"
1269 "Detailed information on TCP and BGP neighbor connections\n"
1270 "Neighbor to display information about\n"
1271 "Display routes learned from neighbor\n" JSON_STR
)
1277 uint8_t uj
= use_json(argc
, argv
);
1279 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1281 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1284 json_object
*json_no
= NULL
;
1285 json_no
= json_object_new_object();
1286 json_object_string_add(json_no
, "warning",
1287 "Malformed address");
1288 vty_out(vty
, "%s\n",
1289 json_object_to_json_string(json_no
));
1290 json_object_free(json_no
);
1292 vty_out(vty
, "Malformed address: %s\n",
1293 argv
[idx_ipv4
]->arg
);
1297 peer
= peer_lookup(NULL
, &su
);
1298 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1300 json_object
*json_no
= NULL
;
1301 json_no
= json_object_new_object();
1302 json_object_string_add(
1304 "No such neighbor or address family");
1305 vty_out(vty
, "%s\n",
1306 json_object_to_json_string(json_no
));
1307 json_object_free(json_no
);
1309 vty_out(vty
, "%% No such neighbor or address family\n");
1313 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1317 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1318 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1319 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1325 "Display information for a route distinguisher\n"
1326 "VPN Route Distinguisher\n"
1327 "Detailed information on TCP and BGP neighbor connections\n"
1328 "Neighbor to display information about\n"
1329 "Display routes learned from neighbor\n" JSON_STR
)
1331 int idx_ext_community
= 0;
1336 struct prefix_rd prd
;
1337 uint8_t uj
= use_json(argc
, argv
);
1339 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1340 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1342 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1345 json_object
*json_no
= NULL
;
1346 json_no
= json_object_new_object();
1347 json_object_string_add(json_no
, "warning",
1348 "Malformed Route Distinguisher");
1349 vty_out(vty
, "%s\n",
1350 json_object_to_json_string(json_no
));
1351 json_object_free(json_no
);
1353 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1357 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1360 json_object
*json_no
= NULL
;
1361 json_no
= json_object_new_object();
1362 json_object_string_add(json_no
, "warning",
1363 "Malformed address");
1364 vty_out(vty
, "%s\n",
1365 json_object_to_json_string(json_no
));
1366 json_object_free(json_no
);
1368 vty_out(vty
, "Malformed address: %s\n",
1369 argv
[idx_ext_community
]->arg
);
1373 peer
= peer_lookup(NULL
, &su
);
1374 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1376 json_object
*json_no
= NULL
;
1377 json_no
= json_object_new_object();
1378 json_object_string_add(
1380 "No such neighbor or address family");
1381 vty_out(vty
, "%s\n",
1382 json_object_to_json_string(json_no
));
1383 json_object_free(json_no
);
1385 vty_out(vty
, "%% No such neighbor or address family\n");
1389 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1393 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1394 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1395 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1401 "Display information about all EVPN NLRIs\n"
1402 "Detailed information on TCP and BGP neighbor connections\n"
1403 "Neighbor to display information about\n"
1404 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1410 uint8_t uj
= use_json(argc
, argv
);
1412 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1414 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1417 json_object
*json_no
= NULL
;
1418 json_no
= json_object_new_object();
1419 json_object_string_add(json_no
, "warning",
1420 "Malformed address");
1421 vty_out(vty
, "%s\n",
1422 json_object_to_json_string(json_no
));
1423 json_object_free(json_no
);
1425 vty_out(vty
, "Malformed address: %s\n",
1426 argv
[idx_ipv4
]->arg
);
1429 peer
= peer_lookup(NULL
, &su
);
1430 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1432 json_object
*json_no
= NULL
;
1433 json_no
= json_object_new_object();
1434 json_object_string_add(
1436 "No such neighbor or address family");
1437 vty_out(vty
, "%s\n",
1438 json_object_to_json_string(json_no
));
1439 json_object_free(json_no
);
1441 vty_out(vty
, "%% No such neighbor or address family\n");
1445 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1448 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1449 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1450 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1456 "Display information for a route distinguisher\n"
1457 "VPN Route Distinguisher\n"
1458 "Detailed information on TCP and BGP neighbor connections\n"
1459 "Neighbor to display information about\n"
1460 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1462 int idx_ext_community
= 0;
1466 struct prefix_rd prd
;
1468 uint8_t uj
= use_json(argc
, argv
);
1470 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1471 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1473 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1476 json_object
*json_no
= NULL
;
1477 json_no
= json_object_new_object();
1478 json_object_string_add(json_no
, "warning",
1479 "Malformed address");
1480 vty_out(vty
, "%s\n",
1481 json_object_to_json_string(json_no
));
1482 json_object_free(json_no
);
1484 vty_out(vty
, "Malformed address: %s\n",
1485 argv
[idx_ext_community
]->arg
);
1488 peer
= peer_lookup(NULL
, &su
);
1489 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1491 json_object
*json_no
= NULL
;
1492 json_no
= json_object_new_object();
1493 json_object_string_add(
1495 "No such neighbor or address family");
1496 vty_out(vty
, "%s\n",
1497 json_object_to_json_string(json_no
));
1498 json_object_free(json_no
);
1500 vty_out(vty
, "%% No such neighbor or address family\n");
1504 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1507 json_object
*json_no
= NULL
;
1508 json_no
= json_object_new_object();
1509 json_object_string_add(json_no
, "warning",
1510 "Malformed Route Distinguisher");
1511 vty_out(vty
, "%s\n",
1512 json_object_to_json_string(json_no
));
1513 json_object_free(json_no
);
1515 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1519 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1522 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1523 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1524 "show [ip] bgp l2vpn evpn all overlay",
1530 "Display information about all EVPN NLRIs\n"
1531 "Display BGP Overlay Information for prefixes\n")
1533 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1534 SHOW_DISPLAY_OVERLAY
,
1535 use_json(argc
, argv
));
1538 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1539 show_ip_bgp_evpn_rd_overlay_cmd
,
1540 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1546 "Display information for a route distinguisher\n"
1547 "VPN Route Distinguisher\n"
1548 "Display BGP Overlay Information for prefixes\n")
1550 int idx_ext_community
= 0;
1552 struct prefix_rd prd
;
1554 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1556 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1558 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1561 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1562 SHOW_DISPLAY_OVERLAY
,
1563 use_json(argc
, argv
));
1566 /* For testing purpose, static route of MPLS-VPN. */
1567 DEFUN(evpnrt5_network
,
1568 evpnrt5_network_cmd
,
1569 "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]",
1570 "Specify a network to announce via BGP\n"
1573 "Specify Route Distinguisher\n"
1574 "VPN Route Distinguisher\n"
1576 "Ethernet Tag Value\n"
1579 "Ethernet Segment Identifier\n"
1580 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1582 "Gateway IP ( A.B.C.D )\n"
1583 "Gateway IPv6 ( X:X::X:X )\n"
1584 "Router Mac Ext Comm\n"
1585 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1586 "Route-map to modify the attributes\n"
1587 "Name of the route map\n")
1589 int idx_ipv4_prefixlen
= 1;
1590 int idx_route_distinguisher
= 3;
1595 int idx_routermac
= 13;
1597 return bgp_static_set_safi(
1598 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1599 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1600 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1601 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1602 argv
[idx_routermac
]->arg
);
1605 /* For testing purpose, static route of MPLS-VPN. */
1606 DEFUN(no_evpnrt5_network
,
1607 no_evpnrt5_network_cmd
,
1608 "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>",
1610 "Specify a network to announce via BGP\n"
1613 "Specify Route Distinguisher\n"
1614 "VPN Route Distinguisher\n"
1616 "Ethernet Tag Value\n"
1619 "Ethernet Segment Identifier\n"
1620 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1621 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1623 int idx_ipv4_prefixlen
= 2;
1624 int idx_ext_community
= 4;
1629 return bgp_static_unset_safi(
1630 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1631 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1632 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1633 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1636 #if defined(HAVE_CUMULUS)
1638 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1640 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1643 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1645 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1649 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1650 * check that this is a change.
1652 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1653 struct ecommunity
*ecomadd
)
1655 /* If the VNI is "live", we need to uninstall routes using the current
1656 * import RT(s) first before we update the import RT, and subsequently
1659 if (is_vni_live(vpn
))
1660 bgp_evpn_uninstall_routes(bgp
, vpn
);
1662 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1663 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1665 /* If the auto route-target is in use we must remove it */
1666 evpn_import_rt_delete_auto(bgp
, vpn
);
1668 /* Add new RT and rebuild the RT to VNI mapping */
1669 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1671 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1672 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1674 /* Install routes that match new import RT */
1675 if (is_vni_live(vpn
))
1676 bgp_evpn_install_routes(bgp
, vpn
);
1680 * Unconfigure Import RT(s) for a VNI (vty handler).
1682 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1683 struct ecommunity
*ecomdel
)
1685 struct listnode
*node
, *nnode
, *node_to_del
;
1686 struct ecommunity
*ecom
;
1688 /* Along the lines of "configure" except we have to reset to the
1691 if (is_vni_live(vpn
))
1692 bgp_evpn_uninstall_routes(bgp
, vpn
);
1694 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1695 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1697 /* Delete all import RTs */
1698 if (ecomdel
== NULL
) {
1699 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1700 ecommunity_free(&ecom
);
1702 list_delete_all_node(vpn
->import_rtl
);
1705 /* Delete a specific import RT */
1709 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1710 if (ecommunity_match(ecom
, ecomdel
)) {
1711 ecommunity_free(&ecom
);
1718 list_delete_node(vpn
->import_rtl
, node_to_del
);
1721 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1722 if (list_isempty(vpn
->import_rtl
)) {
1723 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1724 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1726 /* Rebuild the RT to VNI mapping */
1728 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1730 /* Install routes that match new import RT */
1731 if (is_vni_live(vpn
))
1732 bgp_evpn_install_routes(bgp
, vpn
);
1736 * Configure the Export RT for a VNI (vty handler). Caller expected to
1737 * check that this is a change. Note that only a single export RT is
1738 * allowed for a VNI and any change to configuration is implemented as
1739 * a "replace" (similar to other configuration).
1741 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1742 struct ecommunity
*ecomadd
)
1744 /* If the auto route-target is in use we must remove it */
1745 evpn_export_rt_delete_auto(bgp
, vpn
);
1747 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1748 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1750 if (is_vni_live(vpn
))
1751 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1755 * Unconfigure the Export RT for a VNI (vty handler)
1757 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1758 struct ecommunity
*ecomdel
)
1760 struct listnode
*node
, *nnode
, *node_to_del
;
1761 struct ecommunity
*ecom
;
1763 /* Delete all export RTs */
1764 if (ecomdel
== NULL
) {
1765 /* Reset to default and process all routes. */
1766 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1767 ecommunity_free(&ecom
);
1769 list_delete_all_node(vpn
->export_rtl
);
1772 /* Delete a specific export RT */
1776 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1777 if (ecommunity_match(ecom
, ecomdel
)) {
1778 ecommunity_free(&ecom
);
1785 list_delete_node(vpn
->export_rtl
, node_to_del
);
1788 if (list_isempty(vpn
->export_rtl
)) {
1789 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1790 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1793 if (is_vni_live(vpn
))
1794 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1798 * Configure RD for VRF
1800 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1802 /* If we have already advertise type-5 routes with a diffrent RD, we
1803 * have to delete and withdraw them firs
1805 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1808 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1809 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1811 /* We have a new RD for VRF.
1812 * Advertise all type-5 routes again with the new RD
1814 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1818 * Unconfigure RD for VRF
1820 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1822 /* If we have already advertise type-5 routes with a diffrent RD, we
1823 * have to delete and withdraw them firs
1825 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1827 /* fall back to default RD */
1828 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1830 /* We have a new RD for VRF.
1831 * Advertise all type-5 routes again with the new RD
1833 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1837 * Configure RD for a VNI (vty handler)
1839 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1840 struct prefix_rd
*rd
)
1842 /* If the VNI is "live", we need to delete and withdraw this VNI's
1843 * local routes with the prior RD first. Then, after updating RD,
1844 * need to re-advertise.
1846 if (is_vni_live(vpn
))
1847 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1850 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1851 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1853 if (is_vni_live(vpn
))
1854 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1858 * Unconfigure RD for a VNI (vty handler)
1860 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1862 /* If the VNI is "live", we need to delete and withdraw this VNI's
1863 * local routes with the prior RD first. Then, after resetting RD
1864 * to automatic value, need to re-advertise.
1866 if (is_vni_live(vpn
))
1867 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1869 /* reset RD to default */
1870 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1872 if (is_vni_live(vpn
))
1873 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1877 * Create VNI, if not already present (VTY handler). Mark as configured.
1879 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1881 struct bgpevpn
*vpn
;
1886 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1888 /* tenant vrf will be updated when we get local_vni_add from
1891 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1894 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1900 /* Mark as configured. */
1901 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1906 * Delete VNI. If VNI does not exist in the system (i.e., just
1907 * configuration), all that is needed is to free it. Otherwise,
1908 * any parameters configured for the VNI need to be reset (with
1909 * appropriate action) and the VNI marked as unconfigured; the
1910 * VNI will continue to exist, purely as a "learnt" entity.
1912 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1914 assert(bgp
->vnihash
);
1916 if (!is_vni_live(vpn
)) {
1917 bgp_evpn_free(bgp
, vpn
);
1921 /* We need to take the unconfigure action for each parameter of this VNI
1922 * that is configured. Some optimization is possible, but not worth the
1923 * additional code for an operation that should be pretty rare.
1925 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1927 /* First, deal with the export side - RD and export RT changes. */
1928 if (is_rd_configured(vpn
))
1929 evpn_unconfigure_rd(bgp
, vpn
);
1930 if (is_export_rt_configured(vpn
))
1931 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1933 /* Next, deal with the import side. */
1934 if (is_import_rt_configured(vpn
))
1935 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1941 * Display import RT mapping to VRFs (vty handler)
1942 * bgp_def: default bgp instance
1944 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1952 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1953 (void (*)(struct hash_backet
*,
1954 void *))show_vrf_import_rt_entry
,
1959 * Display import RT mapping to VNIs (vty handler)
1961 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1970 bgp
->import_rt_hash
,
1971 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1976 * Display EVPN routes for all VNIs - vty handler.
1978 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1979 struct in_addr vtep_ip
, json_object
*json
)
1982 struct vni_walk_ctx wctx
;
1984 num_vnis
= hashcount(bgp
->vnihash
);
1987 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1990 wctx
.vtep_ip
= vtep_ip
;
1992 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1993 void *))show_vni_routes_hash
,
1998 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2000 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2001 vni_t vni
, struct in_addr orig_ip
,
2004 struct bgpevpn
*vpn
;
2005 struct prefix_evpn p
;
2006 struct bgp_node
*rn
;
2007 struct bgp_info
*ri
;
2008 uint32_t path_cnt
= 0;
2011 json_object
*json_paths
= NULL
;
2017 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2019 vty_out(vty
, "VNI not found\n");
2023 /* See if route exists. */
2024 build_evpn_type3_prefix(&p
, orig_ip
);
2025 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2026 if (!rn
|| !rn
->info
) {
2028 vty_out(vty
, "%% Network not in table\n");
2033 json_paths
= json_object_new_array();
2035 /* Prefix and num paths displayed once per prefix. */
2036 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2038 /* Display each path for this prefix. */
2039 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2040 json_object
*json_path
= NULL
;
2043 json_path
= json_object_new_array();
2045 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2049 json_object_array_add(json_paths
, json_path
);
2056 json_object_object_add(json
, "paths", json_paths
);
2058 json_object_int_add(json
, "numPaths", path_cnt
);
2060 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2066 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2067 * By definition, only matching type-2 route will be displayed.
2069 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2070 vni_t vni
, struct ethaddr
*mac
,
2071 struct ipaddr
*ip
, json_object
*json
)
2073 struct bgpevpn
*vpn
;
2074 struct prefix_evpn p
;
2075 struct bgp_node
*rn
;
2076 struct bgp_info
*ri
;
2077 uint32_t path_cnt
= 0;
2080 json_object
*json_paths
= NULL
;
2086 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2089 vty_out(vty
, "VNI not found\n");
2093 /* See if route exists. Look for both non-sticky and sticky. */
2094 build_evpn_type2_prefix(&p
, mac
, ip
);
2095 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2096 if (!rn
|| !rn
->info
) {
2098 vty_out(vty
, "%% Network not in table\n");
2103 json_paths
= json_object_new_array();
2105 /* Prefix and num paths displayed once per prefix. */
2106 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2108 /* Display each path for this prefix. */
2109 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2110 json_object
*json_path
= NULL
;
2113 json_path
= json_object_new_array();
2115 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2119 json_object_array_add(json_paths
, json_path
);
2126 json_object_object_add(json
, "paths", json_paths
);
2128 json_object_int_add(json
, "numPaths", path_cnt
);
2130 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2135 /* Disaplay EVPN routes for a ESI - VTY handler */
2136 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2137 esi_t
*esi
, json_object
*json
)
2139 struct evpnes
*es
= NULL
;
2142 es
= bgp_evpn_lookup_es(bgp
, esi
);
2145 vty_out(vty
, "ESI not found\n");
2149 show_esi_routes(bgp
, es
, vty
, json
);
2153 * Display EVPN routes for a VNI - vty handler.
2154 * If 'type' is non-zero, only routes matching that type are shown.
2155 * If the vtep_ip is non zero, only routes behind that vtep are shown
2157 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2158 int type
, struct in_addr vtep_ip
,
2161 struct bgpevpn
*vpn
;
2164 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2167 vty_out(vty
, "VNI not found\n");
2171 /* Walk this VNI's route table and display appropriate routes. */
2172 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2176 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2177 * IP (vty handler). By definition, only matching type-2 route will be
2180 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2181 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2182 struct ipaddr
*ip
, json_object
*json
)
2184 struct prefix_evpn p
;
2185 struct bgp_node
*rn
;
2186 struct bgp_info
*ri
;
2189 uint32_t path_cnt
= 0;
2190 json_object
*json_paths
= NULL
;
2191 char prefix_str
[BUFSIZ
];
2196 /* See if route exists. Look for both non-sticky and sticky. */
2197 build_evpn_type2_prefix(&p
, mac
, ip
);
2198 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2199 (struct prefix
*)&p
, prd
);
2200 if (!rn
|| !rn
->info
) {
2202 vty_out(vty
, "%% Network not in table\n");
2206 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2207 sizeof(prefix_str
));
2209 /* Prefix and num paths displayed once per prefix. */
2210 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2213 json_paths
= json_object_new_array();
2215 /* Display each path for this prefix. */
2216 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2217 json_object
*json_path
= NULL
;
2220 json_path
= json_object_new_array();
2222 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2226 json_object_array_add(json_paths
, json_path
);
2231 if (json
&& path_cnt
) {
2233 json_object_object_add(json
, prefix_str
, json_paths
);
2234 json_object_int_add(json
, "numPaths", path_cnt
);
2236 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2242 * Display BGP EVPN routing table -- for specific RD (vty handler)
2243 * If 'type' is non-zero, only routes matching that type are shown.
2245 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2246 struct prefix_rd
*prd
, int type
,
2249 struct bgp_node
*rd_rn
;
2250 struct bgp_table
*table
;
2251 struct bgp_node
*rn
;
2252 struct bgp_info
*ri
;
2256 uint32_t prefix_cnt
, path_cnt
;
2257 char rd_str
[RD_ADDRSTRLEN
];
2258 json_object
*json_rd
= NULL
;
2259 int add_rd_to_json
= 0;
2263 prefix_cnt
= path_cnt
= 0;
2265 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2267 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2271 table
= (struct bgp_table
*)rd_rn
->info
;
2276 json_rd
= json_object_new_object();
2277 json_object_string_add(json_rd
, "rd", rd_str
);
2280 /* Display all prefixes with this RD. */
2281 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2282 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2283 json_object
*json_prefix
= NULL
;
2284 json_object
*json_paths
= NULL
;
2285 char prefix_str
[BUFSIZ
];
2286 int add_prefix_to_json
= 0;
2288 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2289 sizeof(prefix_str
));
2291 if (type
&& evp
->prefix
.route_type
!= type
)
2295 json_prefix
= json_object_new_object();
2298 /* RD header and legend - once overall. */
2299 if (rd_header
&& !json
) {
2301 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2303 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2305 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2309 /* Prefix and num paths displayed once per prefix. */
2310 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2317 json_paths
= json_object_new_array();
2319 /* Display each path for this prefix. */
2320 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2321 json_object
*json_path
= NULL
;
2324 json_path
= json_object_new_array();
2326 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2330 json_object_array_add(json_paths
, json_path
);
2333 add_prefix_to_json
= 1;
2337 if (json
&& add_prefix_to_json
) {
2338 json_object_object_add(json_prefix
, "paths",
2340 json_object_object_add(json_rd
, prefix_str
,
2345 if (json
&& add_rd_to_json
)
2346 json_object_object_add(json
, rd_str
, json_rd
);
2349 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2350 json_object_int_add(json
, "numPaths", path_cnt
);
2352 if (prefix_cnt
== 0)
2353 vty_out(vty
, "No prefixes exist with this RD%s\n",
2354 type
? " (of requested type)" : "");
2357 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2358 prefix_cnt
, path_cnt
,
2359 type
? " (of requested type)" : "");
2364 * Display BGP EVPN routing table - all routes (vty handler).
2365 * If 'type' is non-zero, only routes matching that type are shown.
2367 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2370 struct bgp_node
*rd_rn
;
2371 struct bgp_table
*table
;
2372 struct bgp_node
*rn
;
2373 struct bgp_info
*ri
;
2378 uint32_t prefix_cnt
, path_cnt
;
2382 prefix_cnt
= path_cnt
= 0;
2384 /* EVPN routing table is a 2-level table with the first level being
2387 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2388 rd_rn
= bgp_route_next(rd_rn
)) {
2389 char rd_str
[RD_ADDRSTRLEN
];
2390 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2391 int add_rd_to_json
= 0;
2394 table
= (struct bgp_table
*)rd_rn
->info
;
2398 tbl_ver
= table
->version
;
2399 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2403 json_rd
= json_object_new_object();
2404 json_object_string_add(json_rd
, "rd", rd_str
);
2409 /* Display all prefixes for an RD */
2410 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2411 json_object
*json_prefix
=
2412 NULL
; /* contains prefix under a RD */
2413 json_object
*json_paths
=
2414 NULL
; /* array of paths under a prefix*/
2415 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2416 char prefix_str
[BUFSIZ
];
2417 int add_prefix_to_json
= 0;
2419 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2420 prefix_str
, sizeof(prefix_str
));
2422 if (type
&& evp
->prefix
.route_type
!= type
)
2426 /* Overall header/legend displayed once. */
2428 bgp_evpn_show_route_header(vty
, bgp
,
2434 /* RD header - per RD. */
2436 bgp_evpn_show_route_rd_header(
2445 json_prefix
= json_object_new_object();
2446 json_paths
= json_object_new_array();
2447 json_object_string_add(json_prefix
, "prefix",
2449 json_object_int_add(json_prefix
, "prefixLen",
2453 /* For EVPN, the prefix is displayed for each path (to
2455 * with code that already exists).
2457 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2458 json_object
*json_path
= NULL
;
2460 add_prefix_to_json
= 1;
2464 json_path
= json_object_new_array();
2466 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
2470 json_object_array_add(json_paths
,
2474 if (json
&& add_prefix_to_json
) {
2475 json_object_object_add(json_prefix
, "paths",
2477 json_object_object_add(json_rd
, prefix_str
,
2482 if (json
&& add_rd_to_json
)
2483 json_object_object_add(json
, rd_str
, json_rd
);
2487 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2488 json_object_int_add(json
, "numPaths", path_cnt
);
2490 if (prefix_cnt
== 0) {
2491 vty_out(vty
, "No EVPN prefixes %sexist\n",
2492 type
? "(of requested type) " : "");
2494 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2495 prefix_cnt
, path_cnt
,
2496 type
? " (of requested type)" : "");
2501 /* Display specific ES */
2502 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2505 struct evpnes
*es
= NULL
;
2507 es
= bgp_evpn_lookup_es(bgp
, esi
);
2509 display_es(vty
, es
, json
);
2512 vty_out(vty
, "{}\n");
2514 vty_out(vty
, "ESI not found\n");
2520 /* Display all ESs */
2521 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
, json_object
*json
)
2526 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2527 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2532 hash_iterate(bgp
->esihash
,
2533 (void (*)(struct hash_backet
*, void *))show_es_entry
,
2538 * Display specified VNI (vty handler)
2540 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2544 struct bgpevpn
*vpn
;
2546 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2549 display_vni(vty
, vpn
, json
);
2551 struct bgp
*bgp_temp
;
2552 struct listnode
*node
= NULL
;
2554 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2555 if (bgp_temp
->l3vni
== vni
) {
2557 display_l3vni(vty
, bgp_temp
, json
);
2564 vty_out(vty
, "{}\n");
2566 vty_out(vty
, "VNI not found\n");
2573 * Display a VNI (upon user query).
2575 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2579 struct bgp
*bgp_temp
= NULL
;
2580 struct listnode
*node
;
2584 vty_out(vty
, "Flags: * - Kernel\n");
2585 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2586 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2589 /* print all L2 VNIS */
2592 hash_iterate(bgp
->vnihash
,
2593 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2596 /* print all L3 VNIs */
2597 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2598 show_l3vni_entry(vty
, bgp_temp
, json
);
2602 * evpn - enable advertisement of default g/w
2604 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2607 if (bgp
->advertise_gw_macip
)
2610 bgp
->advertise_gw_macip
= 1;
2611 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2613 if (vpn
->advertise_gw_macip
)
2616 vpn
->advertise_gw_macip
= 1;
2617 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2624 * evpn - disable advertisement of default g/w
2626 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2627 struct bgpevpn
*vpn
)
2630 if (!bgp
->advertise_gw_macip
)
2633 bgp
->advertise_gw_macip
= 0;
2634 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2636 if (!vpn
->advertise_gw_macip
)
2639 vpn
->advertise_gw_macip
= 0;
2640 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2647 * evpn - enable advertisement of default g/w
2649 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2652 struct prefix ip_prefix
;
2653 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2655 /* form the default prefix 0.0.0.0/0 */
2656 memset(&ip_prefix
, 0, sizeof(struct prefix
));
2657 ip_prefix
.family
= afi2family(afi
);
2658 ip_prefix
.prefixlen
= 0;
2661 /* bail if we are already advertising default route */
2662 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2666 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2667 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2668 else if (afi
== AFI_IP6
)
2669 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2670 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2671 bgp_evpn_advertise_type5_route(bgp_vrf
, &ip_prefix
,
2674 /* bail out if we havent advertised the default route */
2675 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2678 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2679 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2680 else if (afi
== AFI_IP6
)
2681 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2682 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2683 bgp_evpn_withdraw_type5_route(bgp_vrf
, &ip_prefix
,
2689 * evpn - enable advertisement of default g/w
2691 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2692 struct bgpevpn
*vpn
)
2694 if (vpn
->advertise_subnet
)
2697 vpn
->advertise_subnet
= 1;
2698 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2702 * evpn - disable advertisement of default g/w
2704 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2706 if (!vpn
->advertise_subnet
)
2709 vpn
->advertise_subnet
= 0;
2710 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2714 * EVPN (VNI advertisement) enabled. Register with zebra.
2716 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2718 bgp
->advertise_all_vni
= 1;
2719 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2723 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2724 * cache, EVPN routes (delete and withdraw from peers).
2726 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2728 bgp
->advertise_all_vni
= 0;
2729 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2730 bgp_evpn_cleanup_on_disable(bgp
);
2734 * EVPN - use RFC8365 to auto-derive RT
2736 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2738 bgp
->advertise_autort_rfc8365
= 1;
2739 bgp_evpn_handle_autort_change(bgp
);
2743 * EVPN - don't use RFC8365 to auto-derive RT
2745 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2747 bgp
->advertise_autort_rfc8365
= 0;
2748 bgp_evpn_handle_autort_change(bgp
);
2750 #endif /* HAVE_CUMULUS */
2752 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2754 char buf1
[RD_ADDRSTRLEN
];
2756 struct listnode
*node
, *nnode
;
2757 struct ecommunity
*ecom
;
2759 if (is_vni_configured(vpn
)) {
2760 vty_out(vty
, " vni %d\n", vpn
->vni
);
2761 if (is_rd_configured(vpn
))
2762 vty_out(vty
, " rd %s\n",
2763 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2765 if (is_import_rt_configured(vpn
)) {
2766 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2768 ecom_str
= ecommunity_ecom2str(
2769 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2770 vty_out(vty
, " route-target import %s\n",
2772 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2776 if (is_export_rt_configured(vpn
)) {
2777 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2779 ecom_str
= ecommunity_ecom2str(
2780 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2781 vty_out(vty
, " route-target export %s\n",
2783 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2787 if (vpn
->advertise_gw_macip
)
2788 vty_out(vty
, " advertise-default-gw\n");
2790 if (vpn
->advertise_subnet
)
2791 vty_out(vty
, " advertise-subnet\n");
2793 vty_out(vty
, " exit-vni\n");
2797 #if defined(HAVE_CUMULUS)
2798 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2799 bgp_evpn_advertise_default_gw_vni_cmd
,
2800 "advertise-default-gw",
2801 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2803 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2804 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2812 evpn_set_advertise_default_gw(bgp
, vpn
);
2817 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2818 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2819 "no advertise-default-gw",
2821 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2823 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2824 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2832 evpn_unset_advertise_default_gw(bgp
, vpn
);
2838 DEFUN (bgp_evpn_advertise_default_gw
,
2839 bgp_evpn_advertise_default_gw_cmd
,
2840 "advertise-default-gw",
2841 "Advertise All default g/w mac-ip routes in EVPN\n")
2843 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2848 evpn_set_advertise_default_gw(bgp
, NULL
);
2853 DEFUN (no_bgp_evpn_advertise_default_gw
,
2854 no_bgp_evpn_advertise_default_gw_cmd
,
2855 "no advertise-default-gw",
2857 "Withdraw All default g/w mac-ip routes from EVPN\n")
2859 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2864 evpn_unset_advertise_default_gw(bgp
, NULL
);
2869 DEFUN (bgp_evpn_advertise_all_vni
,
2870 bgp_evpn_advertise_all_vni_cmd
,
2871 "advertise-all-vni",
2872 "Advertise All local VNIs\n")
2874 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2878 evpn_set_advertise_all_vni(bgp
);
2882 DEFUN (no_bgp_evpn_advertise_all_vni
,
2883 no_bgp_evpn_advertise_all_vni_cmd
,
2884 "no advertise-all-vni",
2886 "Advertise All local VNIs\n")
2888 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2892 evpn_unset_advertise_all_vni(bgp
);
2896 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2897 bgp_evpn_advertise_autort_rfc8365_cmd
,
2898 "autort rfc8365-compatible",
2899 "Auto-derivation of RT\n"
2900 "Auto-derivation of RT using RFC8365\n")
2902 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2906 evpn_set_advertise_autort_rfc8365(bgp
);
2910 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
2911 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
2912 "no autort rfc8365-compatible",
2914 "Auto-derivation of RT\n"
2915 "Auto-derivation of RT using RFC8365\n")
2917 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2921 evpn_unset_advertise_autort_rfc8365(bgp
);
2925 DEFUN (bgp_evpn_default_originate
,
2926 bgp_evpn_default_originate_cmd
,
2927 "default-originate <ipv4 | ipv6>",
2928 "originate a default route\n"
2929 "ipv4 address family\n"
2930 "ipv6 address family\n")
2934 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2938 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2939 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 1);
2943 DEFUN (no_bgp_evpn_default_originate
,
2944 no_bgp_evpn_default_originate_cmd
,
2945 "no default-originate <ipv4 | ipv6>",
2947 "withdraw a default route\n"
2948 "ipv4 address family\n"
2949 "ipv6 address family\n")
2953 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2957 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2958 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 0);
2962 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
2963 bgp_evpn_advertise_vni_subnet_cmd
,
2965 "Advertise the subnet corresponding to VNI\n")
2967 struct bgp
*bgp_vrf
= NULL
;
2968 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2969 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2977 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
2981 evpn_set_advertise_subnet(bgp
, vpn
);
2985 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
2986 no_bgp_evpn_advertise_vni_subnet_cmd
,
2987 "no advertise-subnet",
2989 "Advertise All local VNIs\n")
2991 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2992 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3000 evpn_unset_advertise_subnet(bgp
, vpn
);
3004 DEFUN (bgp_evpn_advertise_type5
,
3005 bgp_evpn_advertise_type5_cmd
,
3006 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3007 "Advertise prefix routes\n"
3010 "route-map for filtering specific routes\n"
3011 "Name of the route map\n")
3013 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3020 int rmap_changed
= 0;
3022 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3023 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3024 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3026 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3028 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3029 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3032 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3036 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3038 "%%only ipv4 or ipv6 address families are supported");
3042 if (safi
!= SAFI_UNICAST
) {
3044 "%%only ipv4 unicast or ipv6 unicast are supported");
3048 if (afi
== AFI_IP
) {
3050 /* if we are already advertising ipv4 prefix as type-5
3053 if (!rmap_changed
&&
3054 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3055 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3057 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3058 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3061 /* if we are already advertising ipv6 prefix as type-5
3064 if (!rmap_changed
&&
3065 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3066 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3068 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3069 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3073 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3074 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3075 XFREE(MTYPE_ROUTE_MAP_NAME
,
3076 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3077 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3078 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3082 /* set the route-map for advertise command */
3083 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3084 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3085 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3086 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3087 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3090 /* advertise type-5 routes */
3091 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3095 DEFUN (no_bgp_evpn_advertise_type5
,
3096 no_bgp_evpn_advertise_type5_cmd
,
3097 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3099 "Advertise prefix routes\n"
3103 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3109 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3110 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3112 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3114 "%%only ipv4 or ipv6 address families are supported");
3118 if (safi
!= SAFI_UNICAST
) {
3120 "%%only ipv4 unicast or ipv6 unicast are supported");
3124 if (afi
== AFI_IP
) {
3126 /* if we are not advertising ipv4 prefix as type-5
3129 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3130 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3131 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3132 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3133 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3137 /* if we are not advertising ipv6 prefix as type-5
3140 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3141 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3142 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3143 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3144 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3148 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3149 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3150 XFREE(MTYPE_ROUTE_MAP_NAME
,
3151 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3152 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3153 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3160 * Display VNI information - for all or a specific VNI
3162 DEFUN(show_bgp_l2vpn_evpn_vni
,
3163 show_bgp_l2vpn_evpn_vni_cmd
,
3164 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
3173 struct bgp
*bgp_def
;
3177 json_object
*json
= NULL
;
3178 uint32_t num_l2vnis
= 0;
3179 uint32_t num_l3vnis
= 0;
3180 uint32_t num_vnis
= 0;
3181 struct listnode
*node
= NULL
;
3182 struct bgp
*bgp_temp
= NULL
;
3184 uj
= use_json(argc
, argv
);
3186 bgp_def
= bgp_get_default();
3190 if (!argv_find(argv
, argc
, "evpn", &idx
))
3194 json
= json_object_new_object();
3196 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3198 num_l2vnis
= hashcount(bgp_def
->vnihash
);
3200 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3201 if (bgp_temp
->l3vni
)
3204 num_vnis
= num_l2vnis
+ num_l3vnis
;
3206 json_object_string_add(json
, "advertiseGatewayMacip",
3207 bgp_def
->advertise_gw_macip
3210 json_object_string_add(json
, "advertiseAllVnis",
3211 is_evpn_enabled() ? "Enabled"
3213 json_object_int_add(json
, "numVnis", num_vnis
);
3214 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3215 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3217 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3218 bgp_def
->advertise_gw_macip
? "Enabled"
3220 vty_out(vty
, "Advertise All VNI flag: %s\n",
3221 is_evpn_enabled() ? "Enabled" : "Disabled");
3222 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3223 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3225 evpn_show_all_vnis(vty
, bgp_def
, json
);
3229 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3232 /* Display specific VNI */
3233 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3234 evpn_show_vni(vty
, bgp_def
, vni
, json
);
3238 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3239 json
, JSON_C_TO_STRING_PRETTY
));
3240 json_object_free(json
);
3247 DEFUN(show_bgp_l2vpn_evpn_es
,
3248 show_bgp_l2vpn_evpn_es_cmd
,
3249 "show bgp l2vpn evpn es [ESI] [json]",
3254 "ethernet-Segment\n"
3255 "Ethernet-Segment Identifier\n")
3260 json_object
*json
= NULL
;
3261 struct bgp
*bgp
= NULL
;
3263 uj
= use_json(argc
, argv
);
3265 bgp
= bgp_get_default();
3269 if (!argv_find(argv
, argc
, "evpn", &idx
))
3272 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3273 (!uj
&& argc
== (idx
+ 1) + 1)) {
3276 evpn_show_all_es(vty
, bgp
, json
);
3279 /* show a specific ES */
3281 /* get the ESI - ESI-ID is at argv[5] */
3282 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3283 vty_out(vty
, "%% Malformed ESI\n");
3286 evpn_show_es(vty
, bgp
, &esi
, json
);
3290 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3291 json
, JSON_C_TO_STRING_PRETTY
));
3292 json_object_free(json
);
3299 * Display EVPN neighbor summary.
3301 DEFUN(show_bgp_l2vpn_evpn_summary
,
3302 show_bgp_l2vpn_evpn_summary_cmd
,
3303 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3310 "Summary of BGP neighbor status\n"
3314 uint8_t uj
= use_json(argc
, argv
);
3317 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3318 vrf
= argv
[++idx_vrf
]->arg
;
3319 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3323 * Display global EVPN routing table.
3325 DEFUN(show_bgp_l2vpn_evpn_route
,
3326 show_bgp_l2vpn_evpn_route_cmd
,
3327 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3332 "EVPN route information\n"
3333 "Specify Route type\n"
3334 "MAC-IP (Type-2) route\n"
3335 "Multicast (Type-3) route\n"
3336 "Ethernet Segment (type-4) route \n"
3337 "Prefix (type-5 )route\n"
3344 json_object
*json
= NULL
;
3346 uj
= use_json(argc
, argv
);
3348 bgp
= bgp_get_default();
3353 json
= json_object_new_object();
3356 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3357 /* Specific type is requested */
3358 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3359 type
= BGP_EVPN_MAC_IP_ROUTE
;
3360 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3361 type
= BGP_EVPN_IMET_ROUTE
;
3362 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3363 type
= BGP_EVPN_ES_ROUTE
;
3364 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3365 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3370 evpn_show_all_routes(vty
, bgp
, type
, json
);
3373 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3374 json
, JSON_C_TO_STRING_PRETTY
));
3375 json_object_free(json
);
3381 * Display global EVPN routing table for specific RD.
3383 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3384 show_bgp_l2vpn_evpn_route_rd_cmd
,
3385 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3390 "EVPN route information\n"
3391 "Route Distinguisher\n"
3392 "ASN:XX or A.B.C.D:XX\n"
3393 "Specify Route type\n"
3394 "MAC-IP (Type-2) route\n"
3395 "Multicast (Type-3) route\n"
3396 "Ethernet Segment route\n"
3402 struct prefix_rd prd
;
3407 json_object
*json
= NULL
;
3409 bgp
= bgp_get_default();
3413 /* check if we need json output */
3414 uj
= use_json(argc
, argv
);
3416 json
= json_object_new_object();
3419 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3420 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3423 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3429 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3430 /* Specific type is requested */
3431 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3432 type
= BGP_EVPN_MAC_IP_ROUTE
;
3433 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3434 type
= BGP_EVPN_IMET_ROUTE
;
3435 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3436 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3441 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3444 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3445 json
, JSON_C_TO_STRING_PRETTY
));
3446 json_object_free(json
);
3453 * Display global EVPN routing table for specific RD and MACIP.
3455 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3456 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3457 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3462 "EVPN route information\n"
3463 "Route Distinguisher\n"
3464 "ASN:XX or A.B.C.D:XX\n"
3466 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3468 "IP address (IPv4 or IPv6)\n"
3473 struct prefix_rd prd
;
3480 json_object
*json
= NULL
;
3482 memset(&mac
, 0, sizeof(struct ethaddr
));
3483 memset(&ip
, 0, sizeof(struct ipaddr
));
3485 bgp
= bgp_get_default();
3489 /* check if we need json output */
3490 uj
= use_json(argc
, argv
);
3492 json
= json_object_new_object();
3495 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3496 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3498 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3504 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3505 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3506 vty_out(vty
, "%% Malformed MAC address\n");
3511 /* get the ip if specified */
3512 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3513 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3514 vty_out(vty
, "%% Malformed IP address\n");
3519 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3522 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3523 json
, JSON_C_TO_STRING_PRETTY
));
3524 json_object_free(json
);
3530 /* Display per ESI routing table */
3531 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3532 show_bgp_l2vpn_evpn_route_esi_cmd
,
3533 "show bgp l2vpn evpn route esi ESI [json]",
3538 "EVPN route information\n"
3539 "Ethernet Segment Identifier\n"
3545 struct bgp
*bgp
= NULL
;
3546 json_object
*json
= NULL
;
3548 bgp
= bgp_get_default();
3552 uj
= use_json(argc
, argv
);
3554 json
= json_object_new_object();
3556 /* get the ESI - ESI-ID is at argv[6] */
3557 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3558 vty_out(vty
, "%% Malformed ESI\n");
3562 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3565 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3566 json
, JSON_C_TO_STRING_PRETTY
));
3567 json_object_free(json
);
3575 * Display per-VNI EVPN routing table.
3577 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3578 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3583 "EVPN route information\n"
3584 "VXLAN Network Identifier\n"
3586 "Specify Route type\n"
3587 "MAC-IP (Type-2) route\n"
3588 "Multicast (Type-3) route\n"
3590 "Remote VTEP IP address\n"
3595 struct in_addr vtep_ip
;
3599 json_object
*json
= NULL
;
3601 bgp
= bgp_get_default();
3605 /* check if we need json output */
3606 uj
= use_json(argc
, argv
);
3608 json
= json_object_new_object();
3610 if (!argv_find(argv
, argc
, "evpn", &idx
))
3615 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3617 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3618 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3619 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3620 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3621 type
= BGP_EVPN_MAC_IP_ROUTE
;
3622 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3623 type
= BGP_EVPN_IMET_ROUTE
;
3626 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3627 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3628 vty_out(vty
, "%% Malformed VTEP IP address\n");
3635 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3638 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3639 json
, JSON_C_TO_STRING_PRETTY
));
3640 json_object_free(json
);
3647 * Display per-VNI EVPN routing table for specific MACIP.
3649 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3650 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3651 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3656 "EVPN route information\n"
3657 "VXLAN Network Identifier\n"
3660 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3662 "IP address (IPv4 or IPv6)\n"
3671 json_object
*json
= NULL
;
3673 bgp
= bgp_get_default();
3677 /* check if we need json output */
3678 uj
= use_json(argc
, argv
);
3680 json
= json_object_new_object();
3682 if (!argv_find(argv
, argc
, "evpn", &idx
))
3686 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3689 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3690 vty_out(vty
, "%% Malformed MAC address\n");
3695 memset(&ip
, 0, sizeof(ip
));
3696 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3698 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3699 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3700 vty_out(vty
, "%% Malformed IP address\n");
3705 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3708 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3709 json
, JSON_C_TO_STRING_PRETTY
));
3710 json_object_free(json
);
3717 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3719 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3720 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3721 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3726 "EVPN route information\n"
3727 "VXLAN Network Identifier\n"
3729 "Multicast (Type-3) route\n"
3730 "Originating Router IP address\n"
3736 struct in_addr orig_ip
;
3739 json_object
*json
= NULL
;
3741 bgp
= bgp_get_default();
3745 /* check if we need json output */
3746 uj
= use_json(argc
, argv
);
3748 json
= json_object_new_object();
3750 if (!argv_find(argv
, argc
, "evpn", &idx
))
3754 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3757 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3759 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3763 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3766 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3767 json
, JSON_C_TO_STRING_PRETTY
));
3768 json_object_free(json
);
3775 * Display per-VNI EVPN routing table - for all VNIs.
3777 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3778 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3779 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3784 "EVPN route information\n"
3785 "VXLAN Network Identifier\n"
3788 "Remote VTEP IP address\n"
3792 struct in_addr vtep_ip
;
3795 json_object
*json
= NULL
;
3797 bgp
= bgp_get_default();
3801 /* check if we need json output */
3802 uj
= use_json(argc
, argv
);
3804 json
= json_object_new_object();
3806 if (!argv_find(argv
, argc
, "evpn", &idx
))
3810 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3811 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3812 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3813 vty_out(vty
, "%% Malformed VTEP IP address\n");
3818 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3821 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3822 json
, JSON_C_TO_STRING_PRETTY
));
3823 json_object_free(json
);
3830 * Display EVPN import route-target hash table
3832 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3833 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3834 "show bgp l2vpn evpn vrf-import-rt [json]",
3839 "Show vrf import route target\n"
3843 struct bgp
*bgp_def
= NULL
;
3844 json_object
*json
= NULL
;
3846 bgp_def
= bgp_get_default();
3850 uj
= use_json(argc
, argv
);
3852 json
= json_object_new_object();
3854 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
3857 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3858 json
, JSON_C_TO_STRING_PRETTY
));
3859 json_object_free(json
);
3866 * Display EVPN import route-target hash table
3868 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
3869 show_bgp_l2vpn_evpn_import_rt_cmd
,
3870 "show bgp l2vpn evpn import-rt [json]",
3875 "Show import route target\n"
3880 json_object
*json
= NULL
;
3882 bgp
= bgp_get_default();
3886 uj
= use_json(argc
, argv
);
3888 json
= json_object_new_object();
3890 evpn_show_import_rts(vty
, bgp
, json
);
3893 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3894 json
, JSON_C_TO_STRING_PRETTY
));
3895 json_object_free(json
);
3901 #if defined(HAVE_CUMULUS)
3902 DEFUN(test_adv_evpn_type4_route
,
3903 test_adv_evpn_type4_route_cmd
,
3905 "Advertise EVPN ES route\n"
3906 "Ethernet-segment\n"
3907 "Ethernet-Segment Identifier\n")
3912 struct ipaddr vtep_ip
;
3914 bgp
= bgp_get_default();
3916 vty_out(vty
, "%%Default BGP instance not yet created\n");
3920 if(!str_to_esi(argv
[2]->arg
, &esi
)) {
3921 vty_out(vty
, "%%Malformed ESI\n");
3925 vtep_ip
.ipa_type
= IPADDR_V4
;
3926 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3928 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
3930 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
3936 DEFUN(test_withdraw_evpn_type4_route
,
3937 test_withdraw_evpn_type4_route_cmd
,
3939 "Advertise EVPN ES route\n"
3940 "Ethernet-segment\n"
3941 "Ethernet-Segment Identifier\n")
3946 struct ipaddr vtep_ip
;
3948 bgp
= bgp_get_default();
3950 vty_out(vty
, "%%Default BGP instance not yet created\n");
3954 if (!bgp
->peer_self
) {
3955 vty_out(vty
, "%%BGP instance doesnt have self peer\n");
3959 if(!str_to_esi(argv
[2]->arg
, &esi
)) {
3960 vty_out(vty
, "%%Malformed ESI\n");
3964 vtep_ip
.ipa_type
= IPADDR_V4
;
3965 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3966 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
3968 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
3974 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
3975 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3979 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
3980 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3981 "Summary of BGP neighbor status\n" JSON_STR
)
3983 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
3984 "show bgp evpn route [type <macip|multicast>]",
3985 SHOW_STR BGP_STR EVPN_HELP_STR
3986 "EVPN route information\n"
3987 "Specify Route type\n"
3988 "MAC-IP (Type-2) route\n"
3989 "Multicast (Type-3) route\n")
3992 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
3993 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3994 SHOW_STR BGP_STR EVPN_HELP_STR
3995 "EVPN route information\n"
3996 "Route Distinguisher\n"
3997 "ASN:XX or A.B.C.D:XX\n"
3998 "Specify Route type\n"
3999 "MAC-IP (Type-2) route\n"
4000 "Multicast (Type-3) route\n")
4003 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4004 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4005 SHOW_STR BGP_STR EVPN_HELP_STR
4006 "EVPN route information\n"
4007 "Route Distinguisher\n"
4008 "ASN:XX or A.B.C.D:XX\n"
4010 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4012 "IP address (IPv4 or IPv6)\n")
4015 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4016 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
4017 SHOW_STR BGP_STR EVPN_HELP_STR
4018 "EVPN route information\n"
4019 "VXLAN Network Identifier\n"
4021 "Specify Route type\n"
4022 "MAC-IP (Type-2) route\n"
4023 "Multicast (Type-3) route\n"
4025 "Remote VTEP IP address\n")
4027 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4028 show_bgp_evpn_route_vni_macip_cmd
,
4029 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
4030 SHOW_STR BGP_STR EVPN_HELP_STR
4031 "EVPN route information\n"
4032 "VXLAN Network Identifier\n"
4035 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4037 "IP address (IPv4 or IPv6)\n")
4039 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4040 show_bgp_evpn_route_vni_multicast_cmd
,
4041 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
4042 SHOW_STR BGP_STR EVPN_HELP_STR
4043 "EVPN route information\n"
4044 "VXLAN Network Identifier\n"
4046 "Multicast (Type-3) route\n"
4047 "Originating Router IP address\n")
4049 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4050 "show bgp evpn route vni all [vtep A.B.C.D]",
4051 SHOW_STR BGP_STR EVPN_HELP_STR
4052 "EVPN route information\n"
4053 "VXLAN Network Identifier\n"
4056 "Remote VTEP IP address\n")
4058 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4059 "show bgp evpn import-rt",
4060 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4063 DEFUN_NOSH (bgp_evpn_vni
,
4066 "VXLAN Network Identifier\n"
4070 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4071 struct bgpevpn
*vpn
;
4076 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4078 /* Create VNI, or mark as configured. */
4079 vpn
= evpn_create_update_vni(bgp
, vni
);
4081 vty_out(vty
, "%% Failed to create VNI \n");
4085 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4089 DEFUN (no_bgp_evpn_vni
,
4090 no_bgp_evpn_vni_cmd
,
4091 "no vni (1-16777215)",
4093 "VXLAN Network Identifier\n"
4097 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4098 struct bgpevpn
*vpn
;
4103 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4105 /* Check if we should disallow. */
4106 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4108 vty_out(vty
, "%% Specified VNI does not exist\n");
4111 if (!is_vni_configured(vpn
)) {
4112 vty_out(vty
, "%% Specified VNI is not configured\n");
4116 evpn_delete_vni(bgp
, vpn
);
4120 DEFUN_NOSH (exit_vni
,
4123 "Exit from VNI mode\n")
4125 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4126 vty
->node
= BGP_EVPN_NODE
;
4130 DEFUN (bgp_evpn_vrf_rd
,
4131 bgp_evpn_vrf_rd_cmd
,
4132 "rd ASN:NN_OR_IP-ADDRESS:NN",
4133 "Route Distinguisher\n"
4134 "ASN:XX or A.B.C.D:XX\n")
4137 struct prefix_rd prd
;
4138 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4143 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4145 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4149 /* If same as existing value, there is nothing more to do. */
4150 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4153 /* Configure or update the RD. */
4154 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4158 DEFUN (no_bgp_evpn_vrf_rd
,
4159 no_bgp_evpn_vrf_rd_cmd
,
4160 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4162 "Route Distinguisher\n"
4163 "ASN:XX or A.B.C.D:XX\n")
4166 struct prefix_rd prd
;
4167 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4172 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4174 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4178 /* Check if we should disallow. */
4179 if (!is_vrf_rd_configured(bgp_vrf
)) {
4180 vty_out(vty
, "%% RD is not configured for this VRF\n");
4184 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4186 "%% RD specified does not match configuration for this VRF\n");
4190 evpn_unconfigure_vrf_rd(bgp_vrf
);
4194 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4195 no_bgp_evpn_vrf_rd_without_val_cmd
,
4198 "Route Distinguisher\n")
4200 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4205 /* Check if we should disallow. */
4206 if (!is_vrf_rd_configured(bgp_vrf
)) {
4207 vty_out(vty
, "%% RD is not configured for this VRF\n");
4211 evpn_unconfigure_vrf_rd(bgp_vrf
);
4215 DEFUN (bgp_evpn_vni_rd
,
4216 bgp_evpn_vni_rd_cmd
,
4217 "rd ASN:NN_OR_IP-ADDRESS:NN",
4218 "Route Distinguisher\n"
4219 "ASN:XX or A.B.C.D:XX\n")
4221 struct prefix_rd prd
;
4222 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4223 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4229 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4231 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4235 /* If same as existing value, there is nothing more to do. */
4236 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4239 /* Configure or update the RD. */
4240 evpn_configure_rd(bgp
, vpn
, &prd
);
4244 DEFUN (no_bgp_evpn_vni_rd
,
4245 no_bgp_evpn_vni_rd_cmd
,
4246 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4248 "Route Distinguisher\n"
4249 "ASN:XX or A.B.C.D:XX\n")
4251 struct prefix_rd prd
;
4252 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4253 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4259 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4261 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4265 /* Check if we should disallow. */
4266 if (!is_rd_configured(vpn
)) {
4267 vty_out(vty
, "%% RD is not configured for this VNI\n");
4271 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4273 "%% RD specified does not match configuration for this VNI\n");
4277 evpn_unconfigure_rd(bgp
, vpn
);
4281 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4282 no_bgp_evpn_vni_rd_without_val_cmd
,
4285 "Route Distinguisher\n")
4287 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4288 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4293 /* Check if we should disallow. */
4294 if (!is_rd_configured(vpn
)) {
4295 vty_out(vty
, "%% RD is not configured for this VNI\n");
4299 evpn_unconfigure_rd(bgp
, vpn
);
4304 * Loop over all extended-communities in the route-target list rtl and
4305 * return 1 if we find ecomtarget
4307 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4308 struct ecommunity
*ecomtarget
)
4310 struct listnode
*node
, *nnode
;
4311 struct ecommunity
*ecom
;
4313 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4314 if (ecommunity_match(ecom
, ecomtarget
))
4321 /* display L3VNI related info for a VRF instance */
4322 DEFUN (show_bgp_vrf_l3vni_info
,
4323 show_bgp_vrf_l3vni_info_cmd
,
4324 "show bgp vrf VRFNAME vni [json]",
4332 char buf
[ETHER_ADDR_STRLEN
];
4333 char buf1
[INET6_ADDRSTRLEN
];
4335 const char *name
= NULL
;
4336 struct bgp
*bgp
= NULL
;
4337 struct listnode
*node
= NULL
;
4338 struct bgpevpn
*vpn
= NULL
;
4339 struct ecommunity
*ecom
= NULL
;
4340 json_object
*json
= NULL
;
4341 json_object
*json_vnis
= NULL
;
4342 json_object
*json_export_rts
= NULL
;
4343 json_object
*json_import_rts
= NULL
;
4344 uint8_t uj
= use_json(argc
, argv
);
4347 json
= json_object_new_object();
4348 json_vnis
= json_object_new_array();
4349 json_export_rts
= json_object_new_array();
4350 json_import_rts
= json_object_new_array();
4353 name
= argv
[idx_vrf
]->arg
;
4354 bgp
= bgp_lookup_by_name(name
);
4357 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4359 json_object_string_add(json
, "warning",
4360 "BGP instance not found");
4361 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4362 json_object_free(json
);
4368 vty_out(vty
, "BGP VRF: %s\n", name
);
4369 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4370 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4371 vty_out(vty
, " Rmac: %s\n",
4372 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4373 vty_out(vty
, " VNI Filter: %s\n",
4374 CHECK_FLAG(bgp
->vrf_flags
,
4375 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4376 ? "prefix-routes-only"
4378 vty_out(vty
, " L2-VNI List:\n");
4380 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4381 vty_out(vty
, "%u ", vpn
->vni
);
4383 vty_out(vty
, " Export-RTs:\n");
4385 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4386 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4388 vty_out(vty
, " Import-RTs:\n");
4390 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4391 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4393 vty_out(vty
, " RD: %s\n",
4394 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4396 json_object_string_add(json
, "vrf", name
);
4397 json_object_string_add(json
, "local-ip",
4398 inet_ntoa(bgp
->originator_ip
));
4399 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4400 json_object_string_add(
4402 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4403 json_object_string_add(
4405 CHECK_FLAG(bgp
->vrf_flags
,
4406 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4407 ? "prefix-routes-only"
4409 /* list of l2vnis */
4410 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4411 json_object_array_add(json_vnis
,
4412 json_object_new_int(vpn
->vni
));
4413 json_object_object_add(json
, "l2vnis", json_vnis
);
4416 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4417 json_object_array_add(
4419 json_object_new_string(ecommunity_str(ecom
)));
4420 json_object_object_add(json
, "export-rts", json_export_rts
);
4423 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4424 json_object_array_add(
4426 json_object_new_string(ecommunity_str(ecom
)));
4427 json_object_object_add(json
, "import-rts", json_import_rts
);
4428 json_object_string_add(
4430 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4434 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4435 json
, JSON_C_TO_STRING_PRETTY
));
4436 json_object_free(json
);
4441 /* import/export rt for l3vni-vrf */
4442 DEFUN (bgp_evpn_vrf_rt
,
4443 bgp_evpn_vrf_rt_cmd
,
4444 "route-target <both|import|export> RT",
4446 "import and export\n"
4449 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4452 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4453 struct ecommunity
*ecomadd
= NULL
;
4458 if (!strcmp(argv
[1]->arg
, "import"))
4459 rt_type
= RT_TYPE_IMPORT
;
4460 else if (!strcmp(argv
[1]->arg
, "export"))
4461 rt_type
= RT_TYPE_EXPORT
;
4462 else if (!strcmp(argv
[1]->arg
, "both"))
4463 rt_type
= RT_TYPE_BOTH
;
4465 vty_out(vty
, "%% Invalid Route Target type\n");
4469 /* Add/update the import route-target */
4470 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4471 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4472 ECOMMUNITY_ROUTE_TARGET
, 0);
4474 vty_out(vty
, "%% Malformed Route Target list\n");
4477 ecommunity_str(ecomadd
);
4479 /* Do nothing if we already have this import route-target */
4480 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4481 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4484 /* Add/update the export route-target */
4485 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4486 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4487 ECOMMUNITY_ROUTE_TARGET
, 0);
4489 vty_out(vty
, "%% Malformed Route Target list\n");
4492 ecommunity_str(ecomadd
);
4494 /* Do nothing if we already have this export route-target */
4495 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4496 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4502 DEFUN (no_bgp_evpn_vrf_rt
,
4503 no_bgp_evpn_vrf_rt_cmd
,
4504 "no route-target <both|import|export> RT",
4507 "import and export\n"
4510 "ASN:XX or A.B.C.D:XX\n")
4512 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4513 int rt_type
, found_ecomdel
;
4514 struct ecommunity
*ecomdel
= NULL
;
4519 if (!strcmp(argv
[2]->arg
, "import"))
4520 rt_type
= RT_TYPE_IMPORT
;
4521 else if (!strcmp(argv
[2]->arg
, "export"))
4522 rt_type
= RT_TYPE_EXPORT
;
4523 else if (!strcmp(argv
[2]->arg
, "both"))
4524 rt_type
= RT_TYPE_BOTH
;
4526 vty_out(vty
, "%% Invalid Route Target type\n");
4530 if (rt_type
== RT_TYPE_IMPORT
) {
4531 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4533 "%% Import RT is not configured for this VRF\n");
4536 } else if (rt_type
== RT_TYPE_EXPORT
) {
4537 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4539 "%% Export RT is not configured for this VRF\n");
4542 } else if (rt_type
== RT_TYPE_BOTH
) {
4543 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4544 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4546 "%% Import/Export RT is not configured for this VRF\n");
4551 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4553 vty_out(vty
, "%% Malformed Route Target list\n");
4556 ecommunity_str(ecomdel
);
4558 if (rt_type
== RT_TYPE_IMPORT
) {
4559 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4562 "%% RT specified does not match configuration for this VRF\n");
4565 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4566 } else if (rt_type
== RT_TYPE_EXPORT
) {
4567 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4570 "%% RT specified does not match configuration for this VRF\n");
4573 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4574 } else if (rt_type
== RT_TYPE_BOTH
) {
4577 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4579 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4583 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4585 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4589 if (!found_ecomdel
) {
4591 "%% RT specified does not match configuration for this VRF\n");
4599 DEFUN (bgp_evpn_vni_rt
,
4600 bgp_evpn_vni_rt_cmd
,
4601 "route-target <both|import|export> RT",
4603 "import and export\n"
4606 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4608 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4609 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4611 struct ecommunity
*ecomadd
= NULL
;
4616 if (!strcmp(argv
[1]->text
, "import"))
4617 rt_type
= RT_TYPE_IMPORT
;
4618 else if (!strcmp(argv
[1]->text
, "export"))
4619 rt_type
= RT_TYPE_EXPORT
;
4620 else if (!strcmp(argv
[1]->text
, "both"))
4621 rt_type
= RT_TYPE_BOTH
;
4623 vty_out(vty
, "%% Invalid Route Target type\n");
4627 /* Add/update the import route-target */
4628 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4629 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4630 ECOMMUNITY_ROUTE_TARGET
, 0);
4632 vty_out(vty
, "%% Malformed Route Target list\n");
4635 ecommunity_str(ecomadd
);
4637 /* Do nothing if we already have this import route-target */
4638 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4639 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4642 /* Add/update the export route-target */
4643 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4644 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4645 ECOMMUNITY_ROUTE_TARGET
, 0);
4647 vty_out(vty
, "%% Malformed Route Target list\n");
4650 ecommunity_str(ecomadd
);
4652 /* Do nothing if we already have this export route-target */
4653 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4654 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4660 DEFUN (no_bgp_evpn_vni_rt
,
4661 no_bgp_evpn_vni_rt_cmd
,
4662 "no route-target <both|import|export> RT",
4665 "import and export\n"
4668 "ASN:XX or A.B.C.D:XX\n")
4670 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4671 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4672 int rt_type
, found_ecomdel
;
4673 struct ecommunity
*ecomdel
= NULL
;
4678 if (!strcmp(argv
[2]->text
, "import"))
4679 rt_type
= RT_TYPE_IMPORT
;
4680 else if (!strcmp(argv
[2]->text
, "export"))
4681 rt_type
= RT_TYPE_EXPORT
;
4682 else if (!strcmp(argv
[2]->text
, "both"))
4683 rt_type
= RT_TYPE_BOTH
;
4685 vty_out(vty
, "%% Invalid Route Target type\n");
4689 /* The user did "no route-target import", check to see if there are any
4690 * import route-targets configured. */
4691 if (rt_type
== RT_TYPE_IMPORT
) {
4692 if (!is_import_rt_configured(vpn
)) {
4694 "%% Import RT is not configured for this VNI\n");
4697 } else if (rt_type
== RT_TYPE_EXPORT
) {
4698 if (!is_export_rt_configured(vpn
)) {
4700 "%% Export RT is not configured for this VNI\n");
4703 } else if (rt_type
== RT_TYPE_BOTH
) {
4704 if (!is_import_rt_configured(vpn
)
4705 && !is_export_rt_configured(vpn
)) {
4707 "%% Import/Export RT is not configured for this VNI\n");
4712 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4714 vty_out(vty
, "%% Malformed Route Target list\n");
4717 ecommunity_str(ecomdel
);
4719 if (rt_type
== RT_TYPE_IMPORT
) {
4720 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4722 "%% RT specified does not match configuration for this VNI\n");
4725 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4726 } else if (rt_type
== RT_TYPE_EXPORT
) {
4727 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4729 "%% RT specified does not match configuration for this VNI\n");
4732 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4733 } else if (rt_type
== RT_TYPE_BOTH
) {
4736 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4737 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4741 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4742 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4746 if (!found_ecomdel
) {
4748 "%% RT specified does not match configuration for this VNI\n");
4756 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4757 no_bgp_evpn_vni_rt_without_val_cmd
,
4758 "no route-target <import|export>",
4764 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4765 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4771 if (!strcmp(argv
[2]->text
, "import")) {
4772 rt_type
= RT_TYPE_IMPORT
;
4773 } else if (!strcmp(argv
[2]->text
, "export")) {
4774 rt_type
= RT_TYPE_EXPORT
;
4776 vty_out(vty
, "%% Invalid Route Target type\n");
4780 /* Check if we should disallow. */
4781 if (rt_type
== RT_TYPE_IMPORT
) {
4782 if (!is_import_rt_configured(vpn
)) {
4784 "%% Import RT is not configured for this VNI\n");
4788 if (!is_export_rt_configured(vpn
)) {
4790 "%% Export RT is not configured for this VNI\n");
4795 /* Unconfigure the RT. */
4796 if (rt_type
== RT_TYPE_IMPORT
)
4797 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4799 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
4804 static int vni_cmp(const void **a
, const void **b
)
4806 const struct bgpevpn
*first
= *a
;
4807 const struct bgpevpn
*secnd
= *b
;
4809 return secnd
->vni
- first
->vni
;
4813 * Output EVPN configuration information.
4815 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4818 char buf1
[RD_ADDRSTRLEN
];
4821 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
4822 struct listnode
*ln
;
4823 struct bgpevpn
*data
;
4825 list_sort(vnilist
, vni_cmp
);
4826 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
4827 write_vni_config(vty
, data
);
4829 list_delete_and_null(&vnilist
);
4832 if (bgp
->advertise_all_vni
)
4833 vty_out(vty
, " advertise-all-vni\n");
4835 if (bgp
->advertise_autort_rfc8365
)
4836 vty_out(vty
, " autort rfc8365-compatible\n");
4838 if (bgp
->advertise_gw_macip
)
4839 vty_out(vty
, " advertise-default-gw\n");
4841 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4842 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
4843 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
4844 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
4845 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
4847 vty_out(vty
, " advertise ipv4 unicast\n");
4850 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4851 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
4852 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
4853 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
4854 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
4856 vty_out(vty
, " advertise ipv6 unicast\n");
4859 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4860 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
4861 vty_out(vty
, " default-originate ipv4\n");
4863 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4864 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
4865 vty_out(vty
, " default-originate ipv6\n");
4867 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
4868 vty_out(vty
, " rd %s\n",
4869 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
4871 /* import route-target */
4872 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4874 struct listnode
*node
, *nnode
;
4875 struct ecommunity
*ecom
;
4877 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
4879 ecom_str
= ecommunity_ecom2str(
4880 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4881 vty_out(vty
, " route-target import %s\n", ecom_str
);
4882 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4886 /* export route-target */
4887 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4889 struct listnode
*node
, *nnode
;
4890 struct ecommunity
*ecom
;
4892 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
4894 ecom_str
= ecommunity_ecom2str(
4895 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4896 vty_out(vty
, " route-target export %s\n", ecom_str
);
4897 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4902 void bgp_ethernetvpn_init(void)
4904 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
4905 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
4906 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
4907 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
4908 install_element(VIEW_NODE
,
4909 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
4910 install_element(VIEW_NODE
,
4911 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
4914 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
4917 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
4918 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
4919 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
4920 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
4921 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
4922 #if defined(HAVE_CUMULUS)
4923 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
4924 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
4925 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
4926 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
4927 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
4928 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
4929 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
4930 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
4931 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
4932 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
4935 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
4936 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
4938 /* "show bgp l2vpn evpn" commands. */
4939 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
4940 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
4941 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
4942 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
4943 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
4944 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
4945 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
4946 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
4947 install_element(VIEW_NODE
,
4948 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
4949 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
4950 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
4951 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
4952 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
4954 /* "show bgp evpn" commands. */
4955 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
4956 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
4957 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
4958 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
4959 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
4960 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
4961 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
4962 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
4963 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
4964 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
4965 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
4967 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4968 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
4969 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4970 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
4971 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
4972 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
4973 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
4974 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
4975 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
4976 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
4977 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
4978 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
4979 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
4980 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
4981 install_element(BGP_EVPN_VNI_NODE
,
4982 &bgp_evpn_advertise_default_gw_vni_cmd
);
4983 install_element(BGP_EVPN_VNI_NODE
,
4984 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
4985 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
4986 install_element(BGP_EVPN_VNI_NODE
,
4987 &no_bgp_evpn_advertise_vni_subnet_cmd
);