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(
430 json
, "originatorIp",
431 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
433 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
434 json_object_array_add(
435 json_vteps
, json_object_new_string(
438 json_object_object_add(json
, "vteps", json_vteps
);
440 vty_out(vty
, "ESI: %s\n",
441 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
442 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
444 vty_out(vty
, " Originator-IP: %s\n",
445 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
447 vty_out(vty
, " VTEP List:\n");
448 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
449 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
454 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
456 char buf1
[RD_ADDRSTRLEN
];
458 struct listnode
*node
, *nnode
;
459 struct ecommunity
*ecom
;
460 json_object
*json_import_rtl
= NULL
;
461 json_object
*json_export_rtl
= NULL
;
464 json_import_rtl
= json_object_new_array();
465 json_export_rtl
= json_object_new_array();
466 json_object_int_add(json
, "vni", vpn
->vni
);
467 json_object_string_add(json
, "type", "L2");
468 json_object_string_add(json
, "kernelFlag",
469 is_vni_live(vpn
) ? "Yes" : "No");
470 json_object_string_add(
472 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
473 json_object_string_add(json
, "originatorIp",
474 inet_ntoa(vpn
->originator_ip
));
475 json_object_string_add(json
, "advertiseGatewayMacip",
476 vpn
->advertise_gw_macip
? "Yes" : "No");
478 vty_out(vty
, "VNI: %d", vpn
->vni
);
479 if (is_vni_live(vpn
))
480 vty_out(vty
, " (known to the kernel)");
483 vty_out(vty
, " Type: %s\n", "L2");
484 vty_out(vty
, " Tenant-Vrf: %s\n",
485 vrf_id_to_name(vpn
->tenant_vrf_id
));
486 vty_out(vty
, " RD: %s\n",
487 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
488 vty_out(vty
, " Originator IP: %s\n",
489 inet_ntoa(vpn
->originator_ip
));
490 vty_out(vty
, " Advertise-gw-macip : %s\n",
491 vpn
->advertise_gw_macip
? "Yes" : "No");
495 vty_out(vty
, " Import Route Target:\n");
497 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
498 ecom_str
= ecommunity_ecom2str(ecom
,
499 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
502 json_object_array_add(json_import_rtl
,
503 json_object_new_string(ecom_str
));
505 vty_out(vty
, " %s\n", ecom_str
);
507 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
511 json_object_object_add(json
, "importRts", json_import_rtl
);
513 vty_out(vty
, " Export Route Target:\n");
515 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
516 ecom_str
= ecommunity_ecom2str(ecom
,
517 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
520 json_object_array_add(json_export_rtl
,
521 json_object_new_string(ecom_str
));
523 vty_out(vty
, " %s\n", ecom_str
);
525 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
529 json_object_object_add(json
, "exportRts", json_export_rtl
);
532 static void show_esi_routes(struct bgp
*bgp
,
540 uint32_t prefix_cnt
, path_cnt
;
543 prefix_cnt
= path_cnt
= 0;
545 tbl_ver
= es
->route_table
->version
;
546 for (rn
= bgp_table_top(es
->route_table
); rn
;
547 rn
= bgp_route_next(rn
)) {
548 int add_prefix_to_json
= 0;
549 char prefix_str
[BUFSIZ
];
550 json_object
*json_paths
= NULL
;
551 json_object
*json_prefix
= NULL
;
553 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
557 json_prefix
= json_object_new_object();
560 /* Overall header/legend displayed once. */
562 bgp_evpn_show_route_header(vty
, bgp
,
571 json_paths
= json_object_new_array();
573 /* For EVPN, the prefix is displayed for each path (to fit in
574 * with code that already exists).
576 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
577 json_object
*json_path
= NULL
;
580 json_path
= json_object_new_array();
582 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
585 json_object_array_add(json_paths
, json_path
);
588 add_prefix_to_json
= 1;
591 if (json
&& add_prefix_to_json
) {
592 json_object_string_add(json_prefix
, "prefix",
594 json_object_int_add(json_prefix
, "prefixLen",
596 json_object_object_add(json_prefix
, "paths",
598 json_object_object_add(json
, prefix_str
, json_prefix
);
603 json_object_int_add(json
, "numPrefix", prefix_cnt
);
604 json_object_int_add(json
, "numPaths", path_cnt
);
607 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
609 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
610 prefix_cnt
, path_cnt
);
614 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
615 struct vty
*vty
, struct in_addr vtep_ip
,
620 struct bgp_table
*table
;
623 uint32_t prefix_cnt
, path_cnt
;
625 prefix_cnt
= path_cnt
= 0;
627 table
= vpn
->route_table
;
628 tbl_ver
= table
->version
;
629 for (rn
= bgp_table_top(table
); rn
;
630 rn
= bgp_route_next(rn
)) {
631 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
632 int add_prefix_to_json
= 0;
633 char prefix_str
[BUFSIZ
];
634 json_object
*json_paths
= NULL
;
635 json_object
*json_prefix
= NULL
;
637 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
640 if (type
&& evp
->prefix
.route_type
!= type
)
644 json_prefix
= json_object_new_object();
647 /* Overall header/legend displayed once. */
649 bgp_evpn_show_route_header(vty
, bgp
,
658 json_paths
= json_object_new_array();
660 /* For EVPN, the prefix is displayed for each path (to fit in
661 * with code that already exists).
663 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
664 json_object
*json_path
= NULL
;
667 && !IPV4_ADDR_SAME(&(vtep_ip
),
668 &(ri
->attr
->nexthop
)))
672 json_path
= json_object_new_array();
674 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
677 json_object_array_add(json_paths
, json_path
);
680 add_prefix_to_json
= 1;
683 if (json
&& add_prefix_to_json
) {
684 json_object_string_add(json_prefix
, "prefix",
686 json_object_int_add(json_prefix
, "prefixLen",
688 json_object_object_add(json_prefix
, "paths",
690 json_object_object_add(json
, prefix_str
, json_prefix
);
695 json_object_int_add(json
, "numPrefix", prefix_cnt
);
696 json_object_int_add(json
, "numPaths", path_cnt
);
699 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
700 type
? "(of requested type) " : "");
702 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
703 prefix_cnt
, path_cnt
,
704 type
? " (of requested type)" : "");
708 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
710 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
711 struct vni_walk_ctx
*wctx
= arg
;
712 struct vty
*vty
= wctx
->vty
;
713 json_object
*json
= wctx
->json
;
714 json_object
*json_vni
= NULL
;
715 char vni_str
[VNI_STR_LEN
];
717 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
719 json_vni
= json_object_new_object();
720 json_object_int_add(json_vni
, "vni", vpn
->vni
);
722 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
725 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
728 json_object_object_add(json
, vni_str
, json_vni
);
731 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
734 json_object
*json_vni
= NULL
;
735 json_object
*json_import_rtl
= NULL
;
736 json_object
*json_export_rtl
= NULL
;
738 char buf2
[INET6_ADDRSTRLEN
];
741 struct listnode
*node
, *nnode
;
742 struct ecommunity
*ecom
;
748 json_vni
= json_object_new_object();
749 json_import_rtl
= json_object_new_array();
750 json_export_rtl
= json_object_new_array();
753 /* if an l3vni is present in bgp it is live */
758 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
759 json_object_string_add(json_vni
, "type", "L3");
760 json_object_string_add(json_vni
, "inKernel", "True");
761 json_object_string_add(json_vni
, "originatorIp",
762 inet_ntoa(bgp
->originator_ip
));
763 json_object_string_add(
765 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
767 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
768 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
771 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
772 ecom_str
= ecommunity_ecom2str(ecom
,
773 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
776 json_object_array_add(json_import_rtl
,
777 json_object_new_string(ecom_str
));
779 if (listcount(bgp
->vrf_import_rtl
) > 1)
780 sprintf(rt_buf
, "%s, ...", ecom_str
);
782 sprintf(rt_buf
, "%s", ecom_str
);
783 vty_out(vty
, " %-25s", rt_buf
);
786 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
788 /* If there are multiple import RTs we break here and show only
795 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
797 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
798 ecom_str
= ecommunity_ecom2str(ecom
,
799 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
802 json_object_array_add(json_export_rtl
,
803 json_object_new_string(ecom_str
));
805 if (listcount(bgp
->vrf_export_rtl
) > 1)
806 sprintf(rt_buf
, "%s, ...", ecom_str
);
808 sprintf(rt_buf
, "%s", ecom_str
);
809 vty_out(vty
, " %-25s", rt_buf
);
812 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
814 /* If there are multiple export RTs we break here and show only
821 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
824 char vni_str
[VNI_STR_LEN
];
826 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
827 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
828 json_object_object_add(json
, vni_str
, json_vni
);
834 static void show_es_entry(struct hash_backet
*backet
, void *args
[])
836 char buf
[ESI_STR_LEN
];
837 char buf1
[RD_ADDRSTRLEN
];
838 char buf2
[INET6_ADDRSTRLEN
];
839 struct in_addr
*vtep
= NULL
;
840 struct vty
*vty
= args
[0];
841 json_object
*json
= args
[1];
842 json_object
*json_vteps
= NULL
;
843 struct listnode
*node
= NULL
;
844 struct evpnes
*es
= (struct evpnes
*)backet
->data
;
847 json_vteps
= json_object_new_array();
848 json_object_string_add(json
, "esi",
849 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
850 json_object_string_add(json
, "type",
851 is_es_local(es
) ? "Local" : "Remote");
852 json_object_string_add(json
, "rd",
853 prefix_rd2str(&es
->prd
, buf1
,
855 json_object_string_add(
856 json
, "originatorIp",
857 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
859 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
860 json_object_array_add(json_vteps
,
861 json_object_new_string(
864 json_object_object_add(json
, "vteps", json_vteps
);
866 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
867 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
868 is_es_local(es
) ? "Local" : "Remote",
869 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
870 ipaddr2str(&es
->originator_ip
, buf2
,
872 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
876 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
880 json_object
*json_vni
= NULL
;
881 json_object
*json_import_rtl
= NULL
;
882 json_object
*json_export_rtl
= NULL
;
883 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
885 char buf2
[RD_ADDRSTRLEN
];
888 struct listnode
*node
, *nnode
;
889 struct ecommunity
*ecom
;
895 json_vni
= json_object_new_object();
896 json_import_rtl
= json_object_new_array();
897 json_export_rtl
= json_object_new_array();
901 if (is_vni_live(vpn
))
905 json_object_int_add(json_vni
, "vni", vpn
->vni
);
906 json_object_string_add(json_vni
, "type", "L2");
907 json_object_string_add(json_vni
, "inKernel",
908 is_vni_live(vpn
) ? "True" : "False");
909 json_object_string_add(json_vni
, "originatorIp",
910 inet_ntoa(vpn
->originator_ip
));
911 json_object_string_add(json_vni
, "originatorIp",
912 inet_ntoa(vpn
->originator_ip
));
913 json_object_string_add(
915 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
917 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
918 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
921 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
922 ecom_str
= ecommunity_ecom2str(ecom
,
923 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
926 json_object_array_add(json_import_rtl
,
927 json_object_new_string(ecom_str
));
929 if (listcount(vpn
->import_rtl
) > 1)
930 sprintf(rt_buf
, "%s, ...", ecom_str
);
932 sprintf(rt_buf
, "%s", ecom_str
);
933 vty_out(vty
, " %-25s", rt_buf
);
936 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
938 /* If there are multiple import RTs we break here and show only
945 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
947 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
948 ecom_str
= ecommunity_ecom2str(ecom
,
949 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
952 json_object_array_add(json_export_rtl
,
953 json_object_new_string(ecom_str
));
955 if (listcount(vpn
->export_rtl
) > 1)
956 sprintf(rt_buf
, "%s, ...", ecom_str
);
958 sprintf(rt_buf
, "%s", ecom_str
);
959 vty_out(vty
, " %-25s", rt_buf
);
962 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
964 /* If there are multiple export RTs we break here and show only
971 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
974 char vni_str
[VNI_STR_LEN
];
976 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
977 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
978 json_object_object_add(json
, vni_str
, json_vni
);
983 #endif /* HAVE_CUMULUS */
985 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
986 enum bgp_show_type type
, void *output_arg
,
987 int option
, uint8_t use_json
)
989 afi_t afi
= AFI_L2VPN
;
991 struct bgp_table
*table
;
998 unsigned long output_count
= 0;
999 unsigned long total_count
= 0;
1000 json_object
*json
= NULL
;
1001 json_object
*json_nroute
= NULL
;
1002 json_object
*json_array
= NULL
;
1003 json_object
*json_scode
= NULL
;
1004 json_object
*json_ocode
= NULL
;
1006 bgp
= bgp_get_default();
1009 vty_out(vty
, "No BGP process is configured\n");
1011 vty_out(vty
, "{}\n");
1016 json_scode
= json_object_new_object();
1017 json_ocode
= json_object_new_object();
1018 json
= json_object_new_object();
1019 json_nroute
= json_object_new_object();
1021 json_object_string_add(json_scode
, "suppressed", "s");
1022 json_object_string_add(json_scode
, "damped", "d");
1023 json_object_string_add(json_scode
, "history", "h");
1024 json_object_string_add(json_scode
, "valid", "*");
1025 json_object_string_add(json_scode
, "best", ">");
1026 json_object_string_add(json_scode
, "internal", "i");
1028 json_object_string_add(json_ocode
, "igp", "i");
1029 json_object_string_add(json_ocode
, "egp", "e");
1030 json_object_string_add(json_ocode
, "incomplete", "?");
1033 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1034 rn
= bgp_route_next(rn
)) {
1038 continue; /* XXX json TODO */
1040 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1043 if ((table
= rn
->info
) == NULL
)
1047 tbl_ver
= table
->version
;
1049 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1050 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
1052 if (type
== bgp_show_type_neighbor
) {
1053 union sockunion
*su
= output_arg
;
1055 if (ri
->peer
->su_remote
== NULL
1057 ri
->peer
->su_remote
, su
))
1063 == SHOW_DISPLAY_TAGS
) {
1064 json_object_int_add(
1068 json_object_string_add(
1073 json_object_object_add(
1077 json_object_object_add(
1083 if (option
== SHOW_DISPLAY_TAGS
)
1088 == SHOW_DISPLAY_OVERLAY
)
1093 "BGP table version is %" PRIu64
", local router ID is %s\n",
1098 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1100 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1101 vty_out(vty
, V4_HEADER
);
1114 /* Decode RD type. */
1115 type
= decode_rd_type(pnt
);
1116 /* Decode RD value. */
1117 if (type
== RD_TYPE_AS
)
1118 decode_rd_as(pnt
+ 2, &rd_as
);
1119 else if (type
== RD_TYPE_AS4
)
1120 decode_rd_as4(pnt
+ 2, &rd_as
);
1121 else if (type
== RD_TYPE_IP
)
1122 decode_rd_ip(pnt
+ 2, &rd_ip
);
1124 char buffer
[BUFSIZ
];
1125 if (type
== RD_TYPE_AS
1126 || type
== RD_TYPE_AS4
)
1127 sprintf(buffer
, "%u:%d",
1130 else if (type
== RD_TYPE_IP
)
1131 sprintf(buffer
, "%s:%d",
1135 json_object_string_add(
1137 "routeDistinguisher",
1141 "Route Distinguisher: ");
1142 if (type
== RD_TYPE_AS
)
1147 else if (type
== RD_TYPE_AS4
)
1152 else if (type
== RD_TYPE_IP
)
1153 vty_out(vty
, "ip %s:%d",
1157 vty_out(vty
, "\n\n");
1162 json_array
= json_object_new_array();
1165 if (option
== SHOW_DISPLAY_TAGS
)
1166 route_vty_out_tag(vty
, &rm
->p
, ri
, 0,
1169 else if (option
== SHOW_DISPLAY_OVERLAY
)
1170 route_vty_out_overlay(vty
, &rm
->p
, ri
,
1173 route_vty_out(vty
, &rm
->p
, ri
, 0,
1174 SAFI_EVPN
, json_array
);
1179 if (output_count
== 0)
1180 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1182 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1183 output_count
, total_count
);
1187 DEFUN(show_ip_bgp_l2vpn_evpn
,
1188 show_ip_bgp_l2vpn_evpn_cmd
,
1189 "show [ip] bgp l2vpn evpn [json]",
1190 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1192 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1193 use_json(argc
, argv
));
1196 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1197 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1198 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1204 "Display information for a route distinguisher\n"
1205 "VPN Route Distinguisher\n" JSON_STR
)
1207 int idx_ext_community
= 0;
1209 struct prefix_rd prd
;
1211 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1213 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1215 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1218 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1219 use_json(argc
, argv
));
1222 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1223 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1224 "show [ip] bgp l2vpn evpn all tags",
1230 "Display information about all EVPN NLRIs\n"
1231 "Display BGP tags for prefixes\n")
1233 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1237 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1238 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1239 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1245 "Display information for a route distinguisher\n"
1246 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1248 int idx_ext_community
= 0;
1250 struct prefix_rd prd
;
1252 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1254 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1256 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1259 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1263 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1264 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1265 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1271 "Display information about all EVPN NLRIs\n"
1272 "Detailed information on TCP and BGP neighbor connections\n"
1273 "Neighbor to display information about\n"
1274 "Display routes learned from neighbor\n" JSON_STR
)
1280 uint8_t uj
= use_json(argc
, argv
);
1282 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1284 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1287 json_object
*json_no
= NULL
;
1288 json_no
= json_object_new_object();
1289 json_object_string_add(json_no
, "warning",
1290 "Malformed address");
1291 vty_out(vty
, "%s\n",
1292 json_object_to_json_string(json_no
));
1293 json_object_free(json_no
);
1295 vty_out(vty
, "Malformed address: %s\n",
1296 argv
[idx_ipv4
]->arg
);
1300 peer
= peer_lookup(NULL
, &su
);
1301 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1303 json_object
*json_no
= NULL
;
1304 json_no
= json_object_new_object();
1305 json_object_string_add(
1307 "No such neighbor or address family");
1308 vty_out(vty
, "%s\n",
1309 json_object_to_json_string(json_no
));
1310 json_object_free(json_no
);
1312 vty_out(vty
, "%% No such neighbor or address family\n");
1316 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1320 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1321 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1322 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1328 "Display information for a route distinguisher\n"
1329 "VPN Route Distinguisher\n"
1330 "Detailed information on TCP and BGP neighbor connections\n"
1331 "Neighbor to display information about\n"
1332 "Display routes learned from neighbor\n" JSON_STR
)
1334 int idx_ext_community
= 0;
1339 struct prefix_rd prd
;
1340 uint8_t uj
= use_json(argc
, argv
);
1342 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1343 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1345 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1348 json_object
*json_no
= NULL
;
1349 json_no
= json_object_new_object();
1350 json_object_string_add(json_no
, "warning",
1351 "Malformed Route Distinguisher");
1352 vty_out(vty
, "%s\n",
1353 json_object_to_json_string(json_no
));
1354 json_object_free(json_no
);
1356 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1360 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1363 json_object
*json_no
= NULL
;
1364 json_no
= json_object_new_object();
1365 json_object_string_add(json_no
, "warning",
1366 "Malformed address");
1367 vty_out(vty
, "%s\n",
1368 json_object_to_json_string(json_no
));
1369 json_object_free(json_no
);
1371 vty_out(vty
, "Malformed address: %s\n",
1372 argv
[idx_ext_community
]->arg
);
1376 peer
= peer_lookup(NULL
, &su
);
1377 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1379 json_object
*json_no
= NULL
;
1380 json_no
= json_object_new_object();
1381 json_object_string_add(
1383 "No such neighbor or address family");
1384 vty_out(vty
, "%s\n",
1385 json_object_to_json_string(json_no
));
1386 json_object_free(json_no
);
1388 vty_out(vty
, "%% No such neighbor or address family\n");
1392 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1396 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1397 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1398 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1404 "Display information about all EVPN NLRIs\n"
1405 "Detailed information on TCP and BGP neighbor connections\n"
1406 "Neighbor to display information about\n"
1407 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1413 uint8_t uj
= use_json(argc
, argv
);
1415 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1417 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1420 json_object
*json_no
= NULL
;
1421 json_no
= json_object_new_object();
1422 json_object_string_add(json_no
, "warning",
1423 "Malformed address");
1424 vty_out(vty
, "%s\n",
1425 json_object_to_json_string(json_no
));
1426 json_object_free(json_no
);
1428 vty_out(vty
, "Malformed address: %s\n",
1429 argv
[idx_ipv4
]->arg
);
1432 peer
= peer_lookup(NULL
, &su
);
1433 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1435 json_object
*json_no
= NULL
;
1436 json_no
= json_object_new_object();
1437 json_object_string_add(
1439 "No such neighbor or address family");
1440 vty_out(vty
, "%s\n",
1441 json_object_to_json_string(json_no
));
1442 json_object_free(json_no
);
1444 vty_out(vty
, "%% No such neighbor or address family\n");
1448 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1451 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1452 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1453 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1459 "Display information for a route distinguisher\n"
1460 "VPN Route Distinguisher\n"
1461 "Detailed information on TCP and BGP neighbor connections\n"
1462 "Neighbor to display information about\n"
1463 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1465 int idx_ext_community
= 0;
1469 struct prefix_rd prd
;
1471 uint8_t uj
= use_json(argc
, argv
);
1473 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1474 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1476 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1479 json_object
*json_no
= NULL
;
1480 json_no
= json_object_new_object();
1481 json_object_string_add(json_no
, "warning",
1482 "Malformed address");
1483 vty_out(vty
, "%s\n",
1484 json_object_to_json_string(json_no
));
1485 json_object_free(json_no
);
1487 vty_out(vty
, "Malformed address: %s\n",
1488 argv
[idx_ext_community
]->arg
);
1491 peer
= peer_lookup(NULL
, &su
);
1492 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1494 json_object
*json_no
= NULL
;
1495 json_no
= json_object_new_object();
1496 json_object_string_add(
1498 "No such neighbor or address family");
1499 vty_out(vty
, "%s\n",
1500 json_object_to_json_string(json_no
));
1501 json_object_free(json_no
);
1503 vty_out(vty
, "%% No such neighbor or address family\n");
1507 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1510 json_object
*json_no
= NULL
;
1511 json_no
= json_object_new_object();
1512 json_object_string_add(json_no
, "warning",
1513 "Malformed Route Distinguisher");
1514 vty_out(vty
, "%s\n",
1515 json_object_to_json_string(json_no
));
1516 json_object_free(json_no
);
1518 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1522 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1525 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1526 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1527 "show [ip] bgp l2vpn evpn all overlay",
1533 "Display information about all EVPN NLRIs\n"
1534 "Display BGP Overlay Information for prefixes\n")
1536 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1537 SHOW_DISPLAY_OVERLAY
,
1538 use_json(argc
, argv
));
1541 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1542 show_ip_bgp_evpn_rd_overlay_cmd
,
1543 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1549 "Display information for a route distinguisher\n"
1550 "VPN Route Distinguisher\n"
1551 "Display BGP Overlay Information for prefixes\n")
1553 int idx_ext_community
= 0;
1555 struct prefix_rd prd
;
1557 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1559 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1561 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1564 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1565 SHOW_DISPLAY_OVERLAY
,
1566 use_json(argc
, argv
));
1569 /* For testing purpose, static route of MPLS-VPN. */
1570 DEFUN(evpnrt5_network
,
1571 evpnrt5_network_cmd
,
1572 "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]",
1573 "Specify a network to announce via BGP\n"
1576 "Specify Route Distinguisher\n"
1577 "VPN Route Distinguisher\n"
1579 "Ethernet Tag Value\n"
1582 "Ethernet Segment Identifier\n"
1583 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1585 "Gateway IP ( A.B.C.D )\n"
1586 "Gateway IPv6 ( X:X::X:X )\n"
1587 "Router Mac Ext Comm\n"
1588 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1589 "Route-map to modify the attributes\n"
1590 "Name of the route map\n")
1592 int idx_ipv4_prefixlen
= 1;
1593 int idx_route_distinguisher
= 3;
1598 int idx_routermac
= 13;
1600 return bgp_static_set_safi(
1601 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1602 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1603 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1604 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1605 argv
[idx_routermac
]->arg
);
1608 /* For testing purpose, static route of MPLS-VPN. */
1609 DEFUN(no_evpnrt5_network
,
1610 no_evpnrt5_network_cmd
,
1611 "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>",
1613 "Specify a network to announce via BGP\n"
1616 "Specify Route Distinguisher\n"
1617 "VPN Route Distinguisher\n"
1619 "Ethernet Tag Value\n"
1622 "Ethernet Segment Identifier\n"
1623 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1624 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1626 int idx_ipv4_prefixlen
= 2;
1627 int idx_ext_community
= 4;
1632 return bgp_static_unset_safi(
1633 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1634 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1635 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1636 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1639 #if defined(HAVE_CUMULUS)
1641 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1643 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1646 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1648 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1652 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1653 * check that this is a change.
1655 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1656 struct ecommunity
*ecomadd
)
1658 /* If the VNI is "live", we need to uninstall routes using the current
1659 * import RT(s) first before we update the import RT, and subsequently
1662 if (is_vni_live(vpn
))
1663 bgp_evpn_uninstall_routes(bgp
, vpn
);
1665 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1666 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1668 /* If the auto route-target is in use we must remove it */
1669 evpn_import_rt_delete_auto(bgp
, vpn
);
1671 /* Add new RT and rebuild the RT to VNI mapping */
1672 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1674 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1675 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1677 /* Install routes that match new import RT */
1678 if (is_vni_live(vpn
))
1679 bgp_evpn_install_routes(bgp
, vpn
);
1683 * Unconfigure Import RT(s) for a VNI (vty handler).
1685 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1686 struct ecommunity
*ecomdel
)
1688 struct listnode
*node
, *nnode
, *node_to_del
;
1689 struct ecommunity
*ecom
;
1691 /* Along the lines of "configure" except we have to reset to the
1694 if (is_vni_live(vpn
))
1695 bgp_evpn_uninstall_routes(bgp
, vpn
);
1697 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1698 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1700 /* Delete all import RTs */
1701 if (ecomdel
== NULL
) {
1702 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1703 ecommunity_free(&ecom
);
1705 list_delete_all_node(vpn
->import_rtl
);
1708 /* Delete a specific import RT */
1712 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1713 if (ecommunity_match(ecom
, ecomdel
)) {
1714 ecommunity_free(&ecom
);
1721 list_delete_node(vpn
->import_rtl
, node_to_del
);
1724 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1725 if (list_isempty(vpn
->import_rtl
)) {
1726 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1727 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1729 /* Rebuild the RT to VNI mapping */
1731 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1733 /* Install routes that match new import RT */
1734 if (is_vni_live(vpn
))
1735 bgp_evpn_install_routes(bgp
, vpn
);
1739 * Configure the Export RT for a VNI (vty handler). Caller expected to
1740 * check that this is a change. Note that only a single export RT is
1741 * allowed for a VNI and any change to configuration is implemented as
1742 * a "replace" (similar to other configuration).
1744 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1745 struct ecommunity
*ecomadd
)
1747 /* If the auto route-target is in use we must remove it */
1748 evpn_export_rt_delete_auto(bgp
, vpn
);
1750 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1751 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1753 if (is_vni_live(vpn
))
1754 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1758 * Unconfigure the Export RT for a VNI (vty handler)
1760 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1761 struct ecommunity
*ecomdel
)
1763 struct listnode
*node
, *nnode
, *node_to_del
;
1764 struct ecommunity
*ecom
;
1766 /* Delete all export RTs */
1767 if (ecomdel
== NULL
) {
1768 /* Reset to default and process all routes. */
1769 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1770 ecommunity_free(&ecom
);
1772 list_delete_all_node(vpn
->export_rtl
);
1775 /* Delete a specific export RT */
1779 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1780 if (ecommunity_match(ecom
, ecomdel
)) {
1781 ecommunity_free(&ecom
);
1788 list_delete_node(vpn
->export_rtl
, node_to_del
);
1791 if (list_isempty(vpn
->export_rtl
)) {
1792 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1793 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1796 if (is_vni_live(vpn
))
1797 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1801 * Configure RD for VRF
1803 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1805 /* If we have already advertise type-5 routes with a diffrent RD, we
1806 * have to delete and withdraw them firs
1808 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1811 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1812 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1814 /* We have a new RD for VRF.
1815 * Advertise all type-5 routes again with the new RD
1817 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1821 * Unconfigure RD for VRF
1823 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1825 /* If we have already advertise type-5 routes with a diffrent RD, we
1826 * have to delete and withdraw them firs
1828 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1830 /* fall back to default RD */
1831 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1833 /* We have a new RD for VRF.
1834 * Advertise all type-5 routes again with the new RD
1836 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1840 * Configure RD for a VNI (vty handler)
1842 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1843 struct prefix_rd
*rd
)
1845 /* If the VNI is "live", we need to delete and withdraw this VNI's
1846 * local routes with the prior RD first. Then, after updating RD,
1847 * need to re-advertise.
1849 if (is_vni_live(vpn
))
1850 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1853 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1854 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1856 if (is_vni_live(vpn
))
1857 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1861 * Unconfigure RD for a VNI (vty handler)
1863 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1865 /* If the VNI is "live", we need to delete and withdraw this VNI's
1866 * local routes with the prior RD first. Then, after resetting RD
1867 * to automatic value, need to re-advertise.
1869 if (is_vni_live(vpn
))
1870 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1872 /* reset RD to default */
1873 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1875 if (is_vni_live(vpn
))
1876 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1880 * Create VNI, if not already present (VTY handler). Mark as configured.
1882 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1884 struct bgpevpn
*vpn
;
1889 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1891 /* tenant vrf will be updated when we get local_vni_add from
1894 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1897 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1903 /* Mark as configured. */
1904 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1909 * Delete VNI. If VNI does not exist in the system (i.e., just
1910 * configuration), all that is needed is to free it. Otherwise,
1911 * any parameters configured for the VNI need to be reset (with
1912 * appropriate action) and the VNI marked as unconfigured; the
1913 * VNI will continue to exist, purely as a "learnt" entity.
1915 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1917 assert(bgp
->vnihash
);
1919 if (!is_vni_live(vpn
)) {
1920 bgp_evpn_free(bgp
, vpn
);
1924 /* We need to take the unconfigure action for each parameter of this VNI
1925 * that is configured. Some optimization is possible, but not worth the
1926 * additional code for an operation that should be pretty rare.
1928 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1930 /* First, deal with the export side - RD and export RT changes. */
1931 if (is_rd_configured(vpn
))
1932 evpn_unconfigure_rd(bgp
, vpn
);
1933 if (is_export_rt_configured(vpn
))
1934 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1936 /* Next, deal with the import side. */
1937 if (is_import_rt_configured(vpn
))
1938 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1944 * Display import RT mapping to VRFs (vty handler)
1945 * bgp_def: default bgp instance
1947 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1955 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1956 (void (*)(struct hash_backet
*,
1957 void *))show_vrf_import_rt_entry
,
1962 * Display import RT mapping to VNIs (vty handler)
1964 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1973 bgp
->import_rt_hash
,
1974 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1979 * Display EVPN routes for all VNIs - vty handler.
1981 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1982 struct in_addr vtep_ip
, json_object
*json
)
1985 struct vni_walk_ctx wctx
;
1987 num_vnis
= hashcount(bgp
->vnihash
);
1990 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1993 wctx
.vtep_ip
= vtep_ip
;
1995 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1996 void *))show_vni_routes_hash
,
2001 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2003 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2004 vni_t vni
, struct in_addr orig_ip
,
2007 struct bgpevpn
*vpn
;
2008 struct prefix_evpn p
;
2009 struct bgp_node
*rn
;
2010 struct bgp_info
*ri
;
2011 uint32_t path_cnt
= 0;
2014 json_object
*json_paths
= NULL
;
2020 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2022 vty_out(vty
, "VNI not found\n");
2026 /* See if route exists. */
2027 build_evpn_type3_prefix(&p
, orig_ip
);
2028 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2029 if (!rn
|| !rn
->info
) {
2031 vty_out(vty
, "%% Network not in table\n");
2036 json_paths
= json_object_new_array();
2038 /* Prefix and num paths displayed once per prefix. */
2039 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2041 /* Display each path for this prefix. */
2042 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2043 json_object
*json_path
= NULL
;
2046 json_path
= json_object_new_array();
2048 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2052 json_object_array_add(json_paths
, json_path
);
2059 json_object_object_add(json
, "paths", json_paths
);
2061 json_object_int_add(json
, "numPaths", path_cnt
);
2063 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2069 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2070 * By definition, only matching type-2 route will be displayed.
2072 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2073 vni_t vni
, struct ethaddr
*mac
,
2074 struct ipaddr
*ip
, json_object
*json
)
2076 struct bgpevpn
*vpn
;
2077 struct prefix_evpn p
;
2078 struct bgp_node
*rn
;
2079 struct bgp_info
*ri
;
2080 uint32_t path_cnt
= 0;
2083 json_object
*json_paths
= NULL
;
2089 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2092 vty_out(vty
, "VNI not found\n");
2096 /* See if route exists. Look for both non-sticky and sticky. */
2097 build_evpn_type2_prefix(&p
, mac
, ip
);
2098 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2099 if (!rn
|| !rn
->info
) {
2101 vty_out(vty
, "%% Network not in table\n");
2106 json_paths
= json_object_new_array();
2108 /* Prefix and num paths displayed once per prefix. */
2109 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2111 /* Display each path for this prefix. */
2112 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2113 json_object
*json_path
= NULL
;
2116 json_path
= json_object_new_array();
2118 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2122 json_object_array_add(json_paths
, json_path
);
2129 json_object_object_add(json
, "paths", json_paths
);
2131 json_object_int_add(json
, "numPaths", path_cnt
);
2133 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2138 /* Disaplay EVPN routes for a ESI - VTY handler */
2139 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2140 esi_t
*esi
, json_object
*json
)
2142 struct evpnes
*es
= NULL
;
2145 es
= bgp_evpn_lookup_es(bgp
, esi
);
2148 vty_out(vty
, "ESI not found\n");
2152 show_esi_routes(bgp
, es
, vty
, json
);
2156 * Display EVPN routes for a VNI - vty handler.
2157 * If 'type' is non-zero, only routes matching that type are shown.
2158 * If the vtep_ip is non zero, only routes behind that vtep are shown
2160 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2161 int type
, struct in_addr vtep_ip
,
2164 struct bgpevpn
*vpn
;
2167 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2170 vty_out(vty
, "VNI not found\n");
2174 /* Walk this VNI's route table and display appropriate routes. */
2175 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2179 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2180 * IP (vty handler). By definition, only matching type-2 route will be
2183 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2184 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2185 struct ipaddr
*ip
, json_object
*json
)
2187 struct prefix_evpn p
;
2188 struct bgp_node
*rn
;
2189 struct bgp_info
*ri
;
2192 uint32_t path_cnt
= 0;
2193 json_object
*json_paths
= NULL
;
2194 char prefix_str
[BUFSIZ
];
2199 /* See if route exists. Look for both non-sticky and sticky. */
2200 build_evpn_type2_prefix(&p
, mac
, ip
);
2201 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2202 (struct prefix
*)&p
, prd
);
2203 if (!rn
|| !rn
->info
) {
2205 vty_out(vty
, "%% Network not in table\n");
2209 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2210 sizeof(prefix_str
));
2212 /* Prefix and num paths displayed once per prefix. */
2213 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2216 json_paths
= json_object_new_array();
2218 /* Display each path for this prefix. */
2219 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2220 json_object
*json_path
= NULL
;
2223 json_path
= json_object_new_array();
2225 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2229 json_object_array_add(json_paths
, json_path
);
2234 if (json
&& path_cnt
) {
2236 json_object_object_add(json
, prefix_str
, json_paths
);
2237 json_object_int_add(json
, "numPaths", path_cnt
);
2239 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2245 * Display BGP EVPN routing table -- for specific RD (vty handler)
2246 * If 'type' is non-zero, only routes matching that type are shown.
2248 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2249 struct prefix_rd
*prd
, int type
,
2252 struct bgp_node
*rd_rn
;
2253 struct bgp_table
*table
;
2254 struct bgp_node
*rn
;
2255 struct bgp_info
*ri
;
2259 uint32_t prefix_cnt
, path_cnt
;
2260 char rd_str
[RD_ADDRSTRLEN
];
2261 json_object
*json_rd
= NULL
;
2262 int add_rd_to_json
= 0;
2266 prefix_cnt
= path_cnt
= 0;
2268 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2270 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2274 table
= (struct bgp_table
*)rd_rn
->info
;
2279 json_rd
= json_object_new_object();
2280 json_object_string_add(json_rd
, "rd", rd_str
);
2283 /* Display all prefixes with this RD. */
2284 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2285 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2286 json_object
*json_prefix
= NULL
;
2287 json_object
*json_paths
= NULL
;
2288 char prefix_str
[BUFSIZ
];
2289 int add_prefix_to_json
= 0;
2291 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2292 sizeof(prefix_str
));
2294 if (type
&& evp
->prefix
.route_type
!= type
)
2298 json_prefix
= json_object_new_object();
2301 /* RD header and legend - once overall. */
2302 if (rd_header
&& !json
) {
2304 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2306 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2308 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2312 /* Prefix and num paths displayed once per prefix. */
2313 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2320 json_paths
= json_object_new_array();
2322 /* Display each path for this prefix. */
2323 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2324 json_object
*json_path
= NULL
;
2327 json_path
= json_object_new_array();
2329 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2333 json_object_array_add(json_paths
, json_path
);
2336 add_prefix_to_json
= 1;
2340 if (json
&& add_prefix_to_json
) {
2341 json_object_object_add(json_prefix
, "paths",
2343 json_object_object_add(json_rd
, prefix_str
,
2348 if (json
&& add_rd_to_json
)
2349 json_object_object_add(json
, rd_str
, json_rd
);
2352 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2353 json_object_int_add(json
, "numPaths", path_cnt
);
2355 if (prefix_cnt
== 0)
2356 vty_out(vty
, "No prefixes exist with this RD%s\n",
2357 type
? " (of requested type)" : "");
2360 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2361 prefix_cnt
, path_cnt
,
2362 type
? " (of requested type)" : "");
2367 * Display BGP EVPN routing table - all routes (vty handler).
2368 * If 'type' is non-zero, only routes matching that type are shown.
2370 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2373 struct bgp_node
*rd_rn
;
2374 struct bgp_table
*table
;
2375 struct bgp_node
*rn
;
2376 struct bgp_info
*ri
;
2381 uint32_t prefix_cnt
, path_cnt
;
2385 prefix_cnt
= path_cnt
= 0;
2387 /* EVPN routing table is a 2-level table with the first level being
2390 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2391 rd_rn
= bgp_route_next(rd_rn
)) {
2392 char rd_str
[RD_ADDRSTRLEN
];
2393 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2394 int add_rd_to_json
= 0;
2397 table
= (struct bgp_table
*)rd_rn
->info
;
2401 tbl_ver
= table
->version
;
2402 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2406 json_rd
= json_object_new_object();
2407 json_object_string_add(json_rd
, "rd", rd_str
);
2412 /* Display all prefixes for an RD */
2413 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2414 json_object
*json_prefix
=
2415 NULL
; /* contains prefix under a RD */
2416 json_object
*json_paths
=
2417 NULL
; /* array of paths under a prefix*/
2418 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2419 char prefix_str
[BUFSIZ
];
2420 int add_prefix_to_json
= 0;
2422 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2423 prefix_str
, sizeof(prefix_str
));
2425 if (type
&& evp
->prefix
.route_type
!= type
)
2429 /* Overall header/legend displayed once. */
2431 bgp_evpn_show_route_header(vty
, bgp
,
2437 /* RD header - per RD. */
2439 bgp_evpn_show_route_rd_header(
2448 json_prefix
= json_object_new_object();
2449 json_paths
= json_object_new_array();
2450 json_object_string_add(json_prefix
, "prefix",
2452 json_object_int_add(json_prefix
, "prefixLen",
2456 /* For EVPN, the prefix is displayed for each path (to
2458 * with code that already exists).
2460 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2461 json_object
*json_path
= NULL
;
2463 add_prefix_to_json
= 1;
2467 json_path
= json_object_new_array();
2469 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
2473 json_object_array_add(json_paths
,
2477 if (json
&& add_prefix_to_json
) {
2478 json_object_object_add(json_prefix
, "paths",
2480 json_object_object_add(json_rd
, prefix_str
,
2485 if (json
&& add_rd_to_json
)
2486 json_object_object_add(json
, rd_str
, json_rd
);
2490 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2491 json_object_int_add(json
, "numPaths", path_cnt
);
2493 if (prefix_cnt
== 0) {
2494 vty_out(vty
, "No EVPN prefixes %sexist\n",
2495 type
? "(of requested type) " : "");
2497 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2498 prefix_cnt
, path_cnt
,
2499 type
? " (of requested type)" : "");
2504 /* Display specific ES */
2505 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2508 struct evpnes
*es
= NULL
;
2510 es
= bgp_evpn_lookup_es(bgp
, esi
);
2512 display_es(vty
, es
, json
);
2515 vty_out(vty
, "{}\n");
2517 vty_out(vty
, "ESI not found\n");
2523 /* Display all ESs */
2524 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2530 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2531 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2536 hash_iterate(bgp
->esihash
,
2537 (void (*)(struct hash_backet
*, void *))show_es_entry
,
2542 * Display specified VNI (vty handler)
2544 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2548 struct bgpevpn
*vpn
;
2550 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2553 display_vni(vty
, vpn
, json
);
2555 struct bgp
*bgp_temp
;
2556 struct listnode
*node
= NULL
;
2558 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2559 if (bgp_temp
->l3vni
== vni
) {
2561 display_l3vni(vty
, bgp_temp
, json
);
2568 vty_out(vty
, "{}\n");
2570 vty_out(vty
, "VNI not found\n");
2577 * Display a VNI (upon user query).
2579 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2583 struct bgp
*bgp_temp
= NULL
;
2584 struct listnode
*node
;
2588 vty_out(vty
, "Flags: * - Kernel\n");
2589 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2590 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2593 /* print all L2 VNIS */
2596 hash_iterate(bgp
->vnihash
,
2597 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2600 /* print all L3 VNIs */
2601 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2602 show_l3vni_entry(vty
, bgp_temp
, json
);
2606 * evpn - enable advertisement of default g/w
2608 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2611 if (bgp
->advertise_gw_macip
)
2614 bgp
->advertise_gw_macip
= 1;
2615 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2617 if (vpn
->advertise_gw_macip
)
2620 vpn
->advertise_gw_macip
= 1;
2621 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2628 * evpn - disable advertisement of default g/w
2630 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2631 struct bgpevpn
*vpn
)
2634 if (!bgp
->advertise_gw_macip
)
2637 bgp
->advertise_gw_macip
= 0;
2638 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2640 if (!vpn
->advertise_gw_macip
)
2643 vpn
->advertise_gw_macip
= 0;
2644 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2651 * evpn - enable advertisement of default g/w
2653 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2656 struct prefix ip_prefix
;
2657 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2659 /* form the default prefix 0.0.0.0/0 */
2660 memset(&ip_prefix
, 0, sizeof(struct prefix
));
2661 ip_prefix
.family
= afi2family(afi
);
2662 ip_prefix
.prefixlen
= 0;
2665 /* bail if we are already advertising default route */
2666 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2670 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2671 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2672 else if (afi
== AFI_IP6
)
2673 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2674 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2675 bgp_evpn_advertise_type5_route(bgp_vrf
, &ip_prefix
,
2678 /* bail out if we havent advertised the default route */
2679 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2682 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2683 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2684 else if (afi
== AFI_IP6
)
2685 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2686 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2687 bgp_evpn_withdraw_type5_route(bgp_vrf
, &ip_prefix
,
2693 * evpn - enable advertisement of default g/w
2695 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2696 struct bgpevpn
*vpn
)
2698 if (vpn
->advertise_subnet
)
2701 vpn
->advertise_subnet
= 1;
2702 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2706 * evpn - disable advertisement of default g/w
2708 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2710 if (!vpn
->advertise_subnet
)
2713 vpn
->advertise_subnet
= 0;
2714 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2718 * EVPN (VNI advertisement) enabled. Register with zebra.
2720 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2722 bgp
->advertise_all_vni
= 1;
2723 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2727 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2728 * cache, EVPN routes (delete and withdraw from peers).
2730 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2732 bgp
->advertise_all_vni
= 0;
2733 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2734 bgp_evpn_cleanup_on_disable(bgp
);
2738 * EVPN - use RFC8365 to auto-derive RT
2740 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2742 bgp
->advertise_autort_rfc8365
= 1;
2743 bgp_evpn_handle_autort_change(bgp
);
2747 * EVPN - don't use RFC8365 to auto-derive RT
2749 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2751 bgp
->advertise_autort_rfc8365
= 0;
2752 bgp_evpn_handle_autort_change(bgp
);
2754 #endif /* HAVE_CUMULUS */
2756 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2758 char buf1
[RD_ADDRSTRLEN
];
2760 struct listnode
*node
, *nnode
;
2761 struct ecommunity
*ecom
;
2763 if (is_vni_configured(vpn
)) {
2764 vty_out(vty
, " vni %d\n", vpn
->vni
);
2765 if (is_rd_configured(vpn
))
2766 vty_out(vty
, " rd %s\n",
2767 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2769 if (is_import_rt_configured(vpn
)) {
2770 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2772 ecom_str
= ecommunity_ecom2str(
2773 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2774 vty_out(vty
, " route-target import %s\n",
2776 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2780 if (is_export_rt_configured(vpn
)) {
2781 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2783 ecom_str
= ecommunity_ecom2str(
2784 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2785 vty_out(vty
, " route-target export %s\n",
2787 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2791 if (vpn
->advertise_gw_macip
)
2792 vty_out(vty
, " advertise-default-gw\n");
2794 if (vpn
->advertise_subnet
)
2795 vty_out(vty
, " advertise-subnet\n");
2797 vty_out(vty
, " exit-vni\n");
2801 #if defined(HAVE_CUMULUS)
2802 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2803 bgp_evpn_advertise_default_gw_vni_cmd
,
2804 "advertise-default-gw",
2805 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2807 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2808 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2816 evpn_set_advertise_default_gw(bgp
, vpn
);
2821 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2822 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2823 "no advertise-default-gw",
2825 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2827 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2828 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2836 evpn_unset_advertise_default_gw(bgp
, vpn
);
2842 DEFUN (bgp_evpn_advertise_default_gw
,
2843 bgp_evpn_advertise_default_gw_cmd
,
2844 "advertise-default-gw",
2845 "Advertise All default g/w mac-ip routes in EVPN\n")
2847 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2852 evpn_set_advertise_default_gw(bgp
, NULL
);
2857 DEFUN (no_bgp_evpn_advertise_default_gw
,
2858 no_bgp_evpn_advertise_default_gw_cmd
,
2859 "no advertise-default-gw",
2861 "Withdraw All default g/w mac-ip routes from EVPN\n")
2863 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2868 evpn_unset_advertise_default_gw(bgp
, NULL
);
2873 DEFUN (bgp_evpn_advertise_all_vni
,
2874 bgp_evpn_advertise_all_vni_cmd
,
2875 "advertise-all-vni",
2876 "Advertise All local VNIs\n")
2878 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2882 evpn_set_advertise_all_vni(bgp
);
2886 DEFUN (no_bgp_evpn_advertise_all_vni
,
2887 no_bgp_evpn_advertise_all_vni_cmd
,
2888 "no advertise-all-vni",
2890 "Advertise All local VNIs\n")
2892 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2896 evpn_unset_advertise_all_vni(bgp
);
2900 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2901 bgp_evpn_advertise_autort_rfc8365_cmd
,
2902 "autort rfc8365-compatible",
2903 "Auto-derivation of RT\n"
2904 "Auto-derivation of RT using RFC8365\n")
2906 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2910 evpn_set_advertise_autort_rfc8365(bgp
);
2914 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
2915 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
2916 "no autort rfc8365-compatible",
2918 "Auto-derivation of RT\n"
2919 "Auto-derivation of RT using RFC8365\n")
2921 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2925 evpn_unset_advertise_autort_rfc8365(bgp
);
2929 DEFUN (bgp_evpn_default_originate
,
2930 bgp_evpn_default_originate_cmd
,
2931 "default-originate <ipv4 | ipv6>",
2932 "originate a default route\n"
2933 "ipv4 address family\n"
2934 "ipv6 address family\n")
2938 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2942 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2943 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 1);
2947 DEFUN (no_bgp_evpn_default_originate
,
2948 no_bgp_evpn_default_originate_cmd
,
2949 "no default-originate <ipv4 | ipv6>",
2951 "withdraw a default route\n"
2952 "ipv4 address family\n"
2953 "ipv6 address family\n")
2957 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2961 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2962 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 0);
2966 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
2967 bgp_evpn_advertise_vni_subnet_cmd
,
2969 "Advertise the subnet corresponding to VNI\n")
2971 struct bgp
*bgp_vrf
= NULL
;
2972 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2973 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2981 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
2985 evpn_set_advertise_subnet(bgp
, vpn
);
2989 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
2990 no_bgp_evpn_advertise_vni_subnet_cmd
,
2991 "no advertise-subnet",
2993 "Advertise All local VNIs\n")
2995 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2996 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3004 evpn_unset_advertise_subnet(bgp
, vpn
);
3008 DEFUN (bgp_evpn_advertise_type5
,
3009 bgp_evpn_advertise_type5_cmd
,
3010 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3011 "Advertise prefix routes\n"
3014 "route-map for filtering specific routes\n"
3015 "Name of the route map\n")
3017 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3024 int rmap_changed
= 0;
3026 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3027 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3028 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3030 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3032 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3033 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3036 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3040 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3042 "%%only ipv4 or ipv6 address families are supported");
3046 if (safi
!= SAFI_UNICAST
) {
3048 "%%only ipv4 unicast or ipv6 unicast are supported");
3052 if (afi
== AFI_IP
) {
3054 /* if we are already advertising ipv4 prefix as type-5
3057 if (!rmap_changed
&&
3058 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3059 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3061 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3062 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3065 /* if we are already advertising ipv6 prefix as type-5
3068 if (!rmap_changed
&&
3069 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3070 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3072 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3073 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3077 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3078 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3079 XFREE(MTYPE_ROUTE_MAP_NAME
,
3080 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3081 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3082 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3086 /* set the route-map for advertise command */
3087 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3088 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3089 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3090 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3091 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3094 /* advertise type-5 routes */
3095 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3099 DEFUN (no_bgp_evpn_advertise_type5
,
3100 no_bgp_evpn_advertise_type5_cmd
,
3101 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3103 "Advertise prefix routes\n"
3107 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3113 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3114 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3116 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3118 "%%only ipv4 or ipv6 address families are supported");
3122 if (safi
!= SAFI_UNICAST
) {
3124 "%%only ipv4 unicast or ipv6 unicast are supported");
3128 if (afi
== AFI_IP
) {
3130 /* if we are not advertising ipv4 prefix as type-5
3133 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3134 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3135 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3136 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3137 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3141 /* if we are not advertising ipv6 prefix as type-5
3144 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3145 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3146 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3147 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3148 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3152 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3153 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3154 XFREE(MTYPE_ROUTE_MAP_NAME
,
3155 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3156 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3157 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3164 * Display VNI information - for all or a specific VNI
3166 DEFUN(show_bgp_l2vpn_evpn_vni
,
3167 show_bgp_l2vpn_evpn_vni_cmd
,
3168 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
3177 struct bgp
*bgp_def
;
3181 json_object
*json
= NULL
;
3182 uint32_t num_l2vnis
= 0;
3183 uint32_t num_l3vnis
= 0;
3184 uint32_t num_vnis
= 0;
3185 struct listnode
*node
= NULL
;
3186 struct bgp
*bgp_temp
= NULL
;
3188 uj
= use_json(argc
, argv
);
3190 bgp_def
= bgp_get_default();
3194 if (!argv_find(argv
, argc
, "evpn", &idx
))
3198 json
= json_object_new_object();
3200 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3202 num_l2vnis
= hashcount(bgp_def
->vnihash
);
3204 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3205 if (bgp_temp
->l3vni
)
3208 num_vnis
= num_l2vnis
+ num_l3vnis
;
3210 json_object_string_add(json
, "advertiseGatewayMacip",
3211 bgp_def
->advertise_gw_macip
3214 json_object_string_add(json
, "advertiseAllVnis",
3215 is_evpn_enabled() ? "Enabled"
3217 json_object_int_add(json
, "numVnis", num_vnis
);
3218 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3219 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3221 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3222 bgp_def
->advertise_gw_macip
? "Enabled"
3224 vty_out(vty
, "Advertise All VNI flag: %s\n",
3225 is_evpn_enabled() ? "Enabled" : "Disabled");
3226 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3227 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3229 evpn_show_all_vnis(vty
, bgp_def
, json
);
3233 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3236 /* Display specific VNI */
3237 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3238 evpn_show_vni(vty
, bgp_def
, vni
, json
);
3242 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3243 json
, JSON_C_TO_STRING_PRETTY
));
3244 json_object_free(json
);
3251 DEFUN(show_bgp_l2vpn_evpn_es
,
3252 show_bgp_l2vpn_evpn_es_cmd
,
3253 "show bgp l2vpn evpn es [ESI] [json]",
3258 "ethernet-Segment\n"
3259 "Ethernet-Segment Identifier\n"
3265 json_object
*json
= NULL
;
3266 struct bgp
*bgp
= NULL
;
3268 uj
= use_json(argc
, argv
);
3270 bgp
= bgp_get_default();
3274 if (!argv_find(argv
, argc
, "evpn", &idx
))
3277 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3278 (!uj
&& argc
== (idx
+ 1) + 1)) {
3281 evpn_show_all_es(vty
, bgp
, json
);
3284 /* show a specific ES */
3286 /* get the ESI - ESI-ID is at argv[5] */
3287 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3288 vty_out(vty
, "%% Malformed ESI\n");
3291 evpn_show_es(vty
, bgp
, &esi
, json
);
3295 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3296 json
, JSON_C_TO_STRING_PRETTY
));
3297 json_object_free(json
);
3304 * Display EVPN neighbor summary.
3306 DEFUN(show_bgp_l2vpn_evpn_summary
,
3307 show_bgp_l2vpn_evpn_summary_cmd
,
3308 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3315 "Summary of BGP neighbor status\n"
3319 uint8_t uj
= use_json(argc
, argv
);
3322 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3323 vrf
= argv
[++idx_vrf
]->arg
;
3324 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3328 * Display global EVPN routing table.
3330 DEFUN(show_bgp_l2vpn_evpn_route
,
3331 show_bgp_l2vpn_evpn_route_cmd
,
3332 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3337 "EVPN route information\n"
3338 "Specify Route type\n"
3339 "MAC-IP (Type-2) route\n"
3340 "Multicast (Type-3) route\n"
3341 "Ethernet Segment (type-4) route \n"
3342 "Prefix (type-5 )route\n"
3349 json_object
*json
= NULL
;
3351 uj
= use_json(argc
, argv
);
3353 bgp
= bgp_get_default();
3358 json
= json_object_new_object();
3361 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3362 /* Specific type is requested */
3363 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3364 type
= BGP_EVPN_MAC_IP_ROUTE
;
3365 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3366 type
= BGP_EVPN_IMET_ROUTE
;
3367 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3368 type
= BGP_EVPN_ES_ROUTE
;
3369 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3370 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3375 evpn_show_all_routes(vty
, bgp
, type
, json
);
3378 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3379 json
, JSON_C_TO_STRING_PRETTY
));
3380 json_object_free(json
);
3386 * Display global EVPN routing table for specific RD.
3388 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3389 show_bgp_l2vpn_evpn_route_rd_cmd
,
3390 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3395 "EVPN route information\n"
3396 "Route Distinguisher\n"
3397 "ASN:XX or A.B.C.D:XX\n"
3398 "Specify Route type\n"
3399 "MAC-IP (Type-2) route\n"
3400 "Multicast (Type-3) route\n"
3401 "Ethernet Segment route\n"
3407 struct prefix_rd prd
;
3412 json_object
*json
= NULL
;
3414 bgp
= bgp_get_default();
3418 /* check if we need json output */
3419 uj
= use_json(argc
, argv
);
3421 json
= json_object_new_object();
3424 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3425 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3428 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3434 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3435 /* Specific type is requested */
3436 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3437 type
= BGP_EVPN_MAC_IP_ROUTE
;
3438 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3439 type
= BGP_EVPN_IMET_ROUTE
;
3440 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3441 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3446 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3449 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3450 json
, JSON_C_TO_STRING_PRETTY
));
3451 json_object_free(json
);
3458 * Display global EVPN routing table for specific RD and MACIP.
3460 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3461 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3462 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3467 "EVPN route information\n"
3468 "Route Distinguisher\n"
3469 "ASN:XX or A.B.C.D:XX\n"
3471 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3473 "IP address (IPv4 or IPv6)\n"
3478 struct prefix_rd prd
;
3485 json_object
*json
= NULL
;
3487 memset(&mac
, 0, sizeof(struct ethaddr
));
3488 memset(&ip
, 0, sizeof(struct ipaddr
));
3490 bgp
= bgp_get_default();
3494 /* check if we need json output */
3495 uj
= use_json(argc
, argv
);
3497 json
= json_object_new_object();
3500 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3501 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3503 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3509 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3510 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3511 vty_out(vty
, "%% Malformed MAC address\n");
3516 /* get the ip if specified */
3517 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3518 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3519 vty_out(vty
, "%% Malformed IP address\n");
3524 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3527 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3528 json
, JSON_C_TO_STRING_PRETTY
));
3529 json_object_free(json
);
3535 /* Display per ESI routing table */
3536 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3537 show_bgp_l2vpn_evpn_route_esi_cmd
,
3538 "show bgp l2vpn evpn route esi ESI [json]",
3543 "EVPN route information\n"
3544 "Ethernet Segment Identifier\n"
3550 struct bgp
*bgp
= NULL
;
3551 json_object
*json
= NULL
;
3553 bgp
= bgp_get_default();
3557 uj
= use_json(argc
, argv
);
3559 json
= json_object_new_object();
3561 /* get the ESI - ESI-ID is at argv[6] */
3562 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3563 vty_out(vty
, "%% Malformed ESI\n");
3567 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3570 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3571 json
, JSON_C_TO_STRING_PRETTY
));
3572 json_object_free(json
);
3580 * Display per-VNI EVPN routing table.
3582 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3583 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3588 "EVPN route information\n"
3589 "VXLAN Network Identifier\n"
3591 "Specify Route type\n"
3592 "MAC-IP (Type-2) route\n"
3593 "Multicast (Type-3) route\n"
3595 "Remote VTEP IP address\n"
3600 struct in_addr vtep_ip
;
3604 json_object
*json
= NULL
;
3606 bgp
= bgp_get_default();
3610 /* check if we need json output */
3611 uj
= use_json(argc
, argv
);
3613 json
= json_object_new_object();
3615 if (!argv_find(argv
, argc
, "evpn", &idx
))
3620 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3622 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3623 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3624 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3625 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3626 type
= BGP_EVPN_MAC_IP_ROUTE
;
3627 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3628 type
= BGP_EVPN_IMET_ROUTE
;
3631 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3632 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3633 vty_out(vty
, "%% Malformed VTEP IP address\n");
3640 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3643 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3644 json
, JSON_C_TO_STRING_PRETTY
));
3645 json_object_free(json
);
3652 * Display per-VNI EVPN routing table for specific MACIP.
3654 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3655 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3656 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3661 "EVPN route information\n"
3662 "VXLAN Network Identifier\n"
3665 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3667 "IP address (IPv4 or IPv6)\n"
3676 json_object
*json
= NULL
;
3678 bgp
= bgp_get_default();
3682 /* check if we need json output */
3683 uj
= use_json(argc
, argv
);
3685 json
= json_object_new_object();
3687 if (!argv_find(argv
, argc
, "evpn", &idx
))
3691 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3694 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3695 vty_out(vty
, "%% Malformed MAC address\n");
3700 memset(&ip
, 0, sizeof(ip
));
3701 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3703 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3704 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3705 vty_out(vty
, "%% Malformed IP address\n");
3710 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3713 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3714 json
, JSON_C_TO_STRING_PRETTY
));
3715 json_object_free(json
);
3722 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3724 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3725 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3726 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3731 "EVPN route information\n"
3732 "VXLAN Network Identifier\n"
3734 "Multicast (Type-3) route\n"
3735 "Originating Router IP address\n"
3741 struct in_addr orig_ip
;
3744 json_object
*json
= NULL
;
3746 bgp
= bgp_get_default();
3750 /* check if we need json output */
3751 uj
= use_json(argc
, argv
);
3753 json
= json_object_new_object();
3755 if (!argv_find(argv
, argc
, "evpn", &idx
))
3759 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3762 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3764 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3768 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3771 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3772 json
, JSON_C_TO_STRING_PRETTY
));
3773 json_object_free(json
);
3780 * Display per-VNI EVPN routing table - for all VNIs.
3782 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3783 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3784 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3789 "EVPN route information\n"
3790 "VXLAN Network Identifier\n"
3793 "Remote VTEP IP address\n"
3797 struct in_addr vtep_ip
;
3800 json_object
*json
= NULL
;
3802 bgp
= bgp_get_default();
3806 /* check if we need json output */
3807 uj
= use_json(argc
, argv
);
3809 json
= json_object_new_object();
3811 if (!argv_find(argv
, argc
, "evpn", &idx
))
3815 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3816 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3817 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3818 vty_out(vty
, "%% Malformed VTEP IP address\n");
3823 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3826 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3827 json
, JSON_C_TO_STRING_PRETTY
));
3828 json_object_free(json
);
3835 * Display EVPN import route-target hash table
3837 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3838 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3839 "show bgp l2vpn evpn vrf-import-rt [json]",
3844 "Show vrf import route target\n"
3848 struct bgp
*bgp_def
= NULL
;
3849 json_object
*json
= NULL
;
3851 bgp_def
= bgp_get_default();
3855 uj
= use_json(argc
, argv
);
3857 json
= json_object_new_object();
3859 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
3862 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3863 json
, JSON_C_TO_STRING_PRETTY
));
3864 json_object_free(json
);
3871 * Display EVPN import route-target hash table
3873 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
3874 show_bgp_l2vpn_evpn_import_rt_cmd
,
3875 "show bgp l2vpn evpn import-rt [json]",
3880 "Show import route target\n"
3885 json_object
*json
= NULL
;
3887 bgp
= bgp_get_default();
3891 uj
= use_json(argc
, argv
);
3893 json
= json_object_new_object();
3895 evpn_show_import_rts(vty
, bgp
, json
);
3898 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3899 json
, JSON_C_TO_STRING_PRETTY
));
3900 json_object_free(json
);
3906 #if defined(HAVE_CUMULUS)
3907 DEFUN(test_adv_evpn_type4_route
,
3908 test_adv_evpn_type4_route_cmd
,
3910 "Advertise EVPN ES route\n"
3911 "Ethernet-segment\n"
3912 "Ethernet-Segment Identifier\n")
3917 struct ipaddr vtep_ip
;
3919 bgp
= bgp_get_default();
3921 vty_out(vty
, "%%Default BGP instance not yet created\n");
3925 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
3926 vty_out(vty
, "%%Malformed ESI\n");
3930 vtep_ip
.ipa_type
= IPADDR_V4
;
3931 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3933 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
3935 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
3941 DEFUN(test_withdraw_evpn_type4_route
,
3942 test_withdraw_evpn_type4_route_cmd
,
3944 "Advertise EVPN ES route\n"
3945 "Ethernet-segment\n"
3946 "Ethernet-Segment Identifier\n")
3951 struct ipaddr vtep_ip
;
3953 bgp
= bgp_get_default();
3955 vty_out(vty
, "%%Default BGP instance not yet created\n");
3959 if (!bgp
->peer_self
) {
3960 vty_out(vty
, "%%BGP instance doesnt have self peer\n");
3964 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
3965 vty_out(vty
, "%%Malformed ESI\n");
3969 vtep_ip
.ipa_type
= IPADDR_V4
;
3970 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3971 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
3973 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
3979 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
3980 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3984 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
3985 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3986 "Summary of BGP neighbor status\n" JSON_STR
)
3988 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
3989 "show bgp evpn route [type <macip|multicast>]",
3990 SHOW_STR BGP_STR EVPN_HELP_STR
3991 "EVPN route information\n"
3992 "Specify Route type\n"
3993 "MAC-IP (Type-2) route\n"
3994 "Multicast (Type-3) route\n")
3997 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
3998 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3999 SHOW_STR BGP_STR EVPN_HELP_STR
4000 "EVPN route information\n"
4001 "Route Distinguisher\n"
4002 "ASN:XX or A.B.C.D:XX\n"
4003 "Specify Route type\n"
4004 "MAC-IP (Type-2) route\n"
4005 "Multicast (Type-3) route\n")
4008 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4009 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4010 SHOW_STR BGP_STR EVPN_HELP_STR
4011 "EVPN route information\n"
4012 "Route Distinguisher\n"
4013 "ASN:XX or A.B.C.D:XX\n"
4015 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4017 "IP address (IPv4 or IPv6)\n")
4020 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4021 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
4022 SHOW_STR BGP_STR EVPN_HELP_STR
4023 "EVPN route information\n"
4024 "VXLAN Network Identifier\n"
4026 "Specify Route type\n"
4027 "MAC-IP (Type-2) route\n"
4028 "Multicast (Type-3) route\n"
4030 "Remote VTEP IP address\n")
4032 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4033 show_bgp_evpn_route_vni_macip_cmd
,
4034 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
4035 SHOW_STR BGP_STR EVPN_HELP_STR
4036 "EVPN route information\n"
4037 "VXLAN Network Identifier\n"
4040 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4042 "IP address (IPv4 or IPv6)\n")
4044 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4045 show_bgp_evpn_route_vni_multicast_cmd
,
4046 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
4047 SHOW_STR BGP_STR EVPN_HELP_STR
4048 "EVPN route information\n"
4049 "VXLAN Network Identifier\n"
4051 "Multicast (Type-3) route\n"
4052 "Originating Router IP address\n")
4054 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4055 "show bgp evpn route vni all [vtep A.B.C.D]",
4056 SHOW_STR BGP_STR EVPN_HELP_STR
4057 "EVPN route information\n"
4058 "VXLAN Network Identifier\n"
4061 "Remote VTEP IP address\n")
4063 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4064 "show bgp evpn import-rt",
4065 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4068 DEFUN_NOSH (bgp_evpn_vni
,
4071 "VXLAN Network Identifier\n"
4075 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4076 struct bgpevpn
*vpn
;
4081 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4083 /* Create VNI, or mark as configured. */
4084 vpn
= evpn_create_update_vni(bgp
, vni
);
4086 vty_out(vty
, "%% Failed to create VNI \n");
4090 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4094 DEFUN (no_bgp_evpn_vni
,
4095 no_bgp_evpn_vni_cmd
,
4096 "no vni (1-16777215)",
4098 "VXLAN Network Identifier\n"
4102 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4103 struct bgpevpn
*vpn
;
4108 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4110 /* Check if we should disallow. */
4111 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4113 vty_out(vty
, "%% Specified VNI does not exist\n");
4116 if (!is_vni_configured(vpn
)) {
4117 vty_out(vty
, "%% Specified VNI is not configured\n");
4121 evpn_delete_vni(bgp
, vpn
);
4125 DEFUN_NOSH (exit_vni
,
4128 "Exit from VNI mode\n")
4130 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4131 vty
->node
= BGP_EVPN_NODE
;
4135 DEFUN (bgp_evpn_vrf_rd
,
4136 bgp_evpn_vrf_rd_cmd
,
4137 "rd ASN:NN_OR_IP-ADDRESS:NN",
4138 "Route Distinguisher\n"
4139 "ASN:XX or A.B.C.D:XX\n")
4142 struct prefix_rd prd
;
4143 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4148 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4150 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4154 /* If same as existing value, there is nothing more to do. */
4155 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4158 /* Configure or update the RD. */
4159 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4163 DEFUN (no_bgp_evpn_vrf_rd
,
4164 no_bgp_evpn_vrf_rd_cmd
,
4165 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4167 "Route Distinguisher\n"
4168 "ASN:XX or A.B.C.D:XX\n")
4171 struct prefix_rd prd
;
4172 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4177 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4179 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4183 /* Check if we should disallow. */
4184 if (!is_vrf_rd_configured(bgp_vrf
)) {
4185 vty_out(vty
, "%% RD is not configured for this VRF\n");
4189 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4191 "%% RD specified does not match configuration for this VRF\n");
4195 evpn_unconfigure_vrf_rd(bgp_vrf
);
4199 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4200 no_bgp_evpn_vrf_rd_without_val_cmd
,
4203 "Route Distinguisher\n")
4205 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4210 /* Check if we should disallow. */
4211 if (!is_vrf_rd_configured(bgp_vrf
)) {
4212 vty_out(vty
, "%% RD is not configured for this VRF\n");
4216 evpn_unconfigure_vrf_rd(bgp_vrf
);
4220 DEFUN (bgp_evpn_vni_rd
,
4221 bgp_evpn_vni_rd_cmd
,
4222 "rd ASN:NN_OR_IP-ADDRESS:NN",
4223 "Route Distinguisher\n"
4224 "ASN:XX or A.B.C.D:XX\n")
4226 struct prefix_rd prd
;
4227 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4228 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4234 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4236 "This command is only supported under Default VRF\n");
4240 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4242 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4246 /* If same as existing value, there is nothing more to do. */
4247 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4250 /* Configure or update the RD. */
4251 evpn_configure_rd(bgp
, vpn
, &prd
);
4255 DEFUN (no_bgp_evpn_vni_rd
,
4256 no_bgp_evpn_vni_rd_cmd
,
4257 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4259 "Route Distinguisher\n"
4260 "ASN:XX or A.B.C.D:XX\n")
4262 struct prefix_rd prd
;
4263 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4264 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4270 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4272 "This command is only supported under Default VRF\n");
4276 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4278 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4282 /* Check if we should disallow. */
4283 if (!is_rd_configured(vpn
)) {
4284 vty_out(vty
, "%% RD is not configured for this VNI\n");
4288 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4290 "%% RD specified does not match configuration for this VNI\n");
4294 evpn_unconfigure_rd(bgp
, vpn
);
4298 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4299 no_bgp_evpn_vni_rd_without_val_cmd
,
4302 "Route Distinguisher\n")
4304 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4305 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4310 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4312 "This command is only supported under Default VRF\n");
4316 /* Check if we should disallow. */
4317 if (!is_rd_configured(vpn
)) {
4318 vty_out(vty
, "%% RD is not configured for this VNI\n");
4322 evpn_unconfigure_rd(bgp
, vpn
);
4327 * Loop over all extended-communities in the route-target list rtl and
4328 * return 1 if we find ecomtarget
4330 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4331 struct ecommunity
*ecomtarget
)
4333 struct listnode
*node
, *nnode
;
4334 struct ecommunity
*ecom
;
4336 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4337 if (ecommunity_match(ecom
, ecomtarget
))
4344 /* display L3VNI related info for a VRF instance */
4345 DEFUN (show_bgp_vrf_l3vni_info
,
4346 show_bgp_vrf_l3vni_info_cmd
,
4347 "show bgp vrf VRFNAME vni [json]",
4355 char buf
[ETHER_ADDR_STRLEN
];
4356 char buf1
[INET6_ADDRSTRLEN
];
4358 const char *name
= NULL
;
4359 struct bgp
*bgp
= NULL
;
4360 struct listnode
*node
= NULL
;
4361 struct bgpevpn
*vpn
= NULL
;
4362 struct ecommunity
*ecom
= NULL
;
4363 json_object
*json
= NULL
;
4364 json_object
*json_vnis
= NULL
;
4365 json_object
*json_export_rts
= NULL
;
4366 json_object
*json_import_rts
= NULL
;
4367 uint8_t uj
= use_json(argc
, argv
);
4370 json
= json_object_new_object();
4371 json_vnis
= json_object_new_array();
4372 json_export_rts
= json_object_new_array();
4373 json_import_rts
= json_object_new_array();
4376 name
= argv
[idx_vrf
]->arg
;
4377 bgp
= bgp_lookup_by_name(name
);
4380 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4382 json_object_string_add(json
, "warning",
4383 "BGP instance not found");
4384 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4385 json_object_free(json
);
4391 vty_out(vty
, "BGP VRF: %s\n", name
);
4392 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4393 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4394 vty_out(vty
, " Rmac: %s\n",
4395 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4396 vty_out(vty
, " VNI Filter: %s\n",
4397 CHECK_FLAG(bgp
->vrf_flags
,
4398 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4399 ? "prefix-routes-only"
4401 vty_out(vty
, " L2-VNI List:\n");
4403 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4404 vty_out(vty
, "%u ", vpn
->vni
);
4406 vty_out(vty
, " Export-RTs:\n");
4408 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4409 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4411 vty_out(vty
, " Import-RTs:\n");
4413 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4414 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4416 vty_out(vty
, " RD: %s\n",
4417 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4419 json_object_string_add(json
, "vrf", name
);
4420 json_object_string_add(json
, "local-ip",
4421 inet_ntoa(bgp
->originator_ip
));
4422 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4423 json_object_string_add(
4425 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4426 json_object_string_add(
4428 CHECK_FLAG(bgp
->vrf_flags
,
4429 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4430 ? "prefix-routes-only"
4432 /* list of l2vnis */
4433 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4434 json_object_array_add(json_vnis
,
4435 json_object_new_int(vpn
->vni
));
4436 json_object_object_add(json
, "l2vnis", json_vnis
);
4439 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4440 json_object_array_add(
4442 json_object_new_string(ecommunity_str(ecom
)));
4443 json_object_object_add(json
, "export-rts", json_export_rts
);
4446 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4447 json_object_array_add(
4449 json_object_new_string(ecommunity_str(ecom
)));
4450 json_object_object_add(json
, "import-rts", json_import_rts
);
4451 json_object_string_add(
4453 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4457 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4458 json
, JSON_C_TO_STRING_PRETTY
));
4459 json_object_free(json
);
4464 /* import/export rt for l3vni-vrf */
4465 DEFUN (bgp_evpn_vrf_rt
,
4466 bgp_evpn_vrf_rt_cmd
,
4467 "route-target <both|import|export> RT",
4469 "import and export\n"
4472 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4475 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4476 struct ecommunity
*ecomadd
= NULL
;
4481 if (!strcmp(argv
[1]->arg
, "import"))
4482 rt_type
= RT_TYPE_IMPORT
;
4483 else if (!strcmp(argv
[1]->arg
, "export"))
4484 rt_type
= RT_TYPE_EXPORT
;
4485 else if (!strcmp(argv
[1]->arg
, "both"))
4486 rt_type
= RT_TYPE_BOTH
;
4488 vty_out(vty
, "%% Invalid Route Target type\n");
4492 /* Add/update the import route-target */
4493 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4494 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4495 ECOMMUNITY_ROUTE_TARGET
, 0);
4497 vty_out(vty
, "%% Malformed Route Target list\n");
4500 ecommunity_str(ecomadd
);
4502 /* Do nothing if we already have this import route-target */
4503 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4504 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4507 /* Add/update the export route-target */
4508 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4509 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4510 ECOMMUNITY_ROUTE_TARGET
, 0);
4512 vty_out(vty
, "%% Malformed Route Target list\n");
4515 ecommunity_str(ecomadd
);
4517 /* Do nothing if we already have this export route-target */
4518 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4519 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4525 DEFUN (no_bgp_evpn_vrf_rt
,
4526 no_bgp_evpn_vrf_rt_cmd
,
4527 "no route-target <both|import|export> RT",
4530 "import and export\n"
4533 "ASN:XX or A.B.C.D:XX\n")
4535 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4536 int rt_type
, found_ecomdel
;
4537 struct ecommunity
*ecomdel
= NULL
;
4542 if (!strcmp(argv
[2]->arg
, "import"))
4543 rt_type
= RT_TYPE_IMPORT
;
4544 else if (!strcmp(argv
[2]->arg
, "export"))
4545 rt_type
= RT_TYPE_EXPORT
;
4546 else if (!strcmp(argv
[2]->arg
, "both"))
4547 rt_type
= RT_TYPE_BOTH
;
4549 vty_out(vty
, "%% Invalid Route Target type\n");
4553 if (rt_type
== RT_TYPE_IMPORT
) {
4554 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4556 "%% Import RT is not configured for this VRF\n");
4559 } else if (rt_type
== RT_TYPE_EXPORT
) {
4560 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4562 "%% Export RT is not configured for this VRF\n");
4565 } else if (rt_type
== RT_TYPE_BOTH
) {
4566 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4567 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4569 "%% Import/Export RT is not configured for this VRF\n");
4574 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4576 vty_out(vty
, "%% Malformed Route Target list\n");
4579 ecommunity_str(ecomdel
);
4581 if (rt_type
== RT_TYPE_IMPORT
) {
4582 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4585 "%% RT specified does not match configuration for this VRF\n");
4588 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4589 } else if (rt_type
== RT_TYPE_EXPORT
) {
4590 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4593 "%% RT specified does not match configuration for this VRF\n");
4596 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4597 } else if (rt_type
== RT_TYPE_BOTH
) {
4600 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4602 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4606 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4608 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4612 if (!found_ecomdel
) {
4614 "%% RT specified does not match configuration for this VRF\n");
4622 DEFUN (bgp_evpn_vni_rt
,
4623 bgp_evpn_vni_rt_cmd
,
4624 "route-target <both|import|export> RT",
4626 "import and export\n"
4629 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4631 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4632 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4634 struct ecommunity
*ecomadd
= NULL
;
4639 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4641 "This command is only supported under Default VRF\n");
4645 if (!strcmp(argv
[1]->text
, "import"))
4646 rt_type
= RT_TYPE_IMPORT
;
4647 else if (!strcmp(argv
[1]->text
, "export"))
4648 rt_type
= RT_TYPE_EXPORT
;
4649 else if (!strcmp(argv
[1]->text
, "both"))
4650 rt_type
= RT_TYPE_BOTH
;
4652 vty_out(vty
, "%% Invalid Route Target type\n");
4656 /* Add/update the import route-target */
4657 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4658 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4659 ECOMMUNITY_ROUTE_TARGET
, 0);
4661 vty_out(vty
, "%% Malformed Route Target list\n");
4664 ecommunity_str(ecomadd
);
4666 /* Do nothing if we already have this import route-target */
4667 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4668 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4671 /* Add/update the export route-target */
4672 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4673 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4674 ECOMMUNITY_ROUTE_TARGET
, 0);
4676 vty_out(vty
, "%% Malformed Route Target list\n");
4679 ecommunity_str(ecomadd
);
4681 /* Do nothing if we already have this export route-target */
4682 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4683 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4689 DEFUN (no_bgp_evpn_vni_rt
,
4690 no_bgp_evpn_vni_rt_cmd
,
4691 "no route-target <both|import|export> RT",
4694 "import and export\n"
4697 "ASN:XX or A.B.C.D:XX\n")
4699 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4700 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4701 int rt_type
, found_ecomdel
;
4702 struct ecommunity
*ecomdel
= NULL
;
4707 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4709 "This command is only supported under Default VRF\n");
4713 if (!strcmp(argv
[2]->text
, "import"))
4714 rt_type
= RT_TYPE_IMPORT
;
4715 else if (!strcmp(argv
[2]->text
, "export"))
4716 rt_type
= RT_TYPE_EXPORT
;
4717 else if (!strcmp(argv
[2]->text
, "both"))
4718 rt_type
= RT_TYPE_BOTH
;
4720 vty_out(vty
, "%% Invalid Route Target type\n");
4724 /* The user did "no route-target import", check to see if there are any
4725 * import route-targets configured. */
4726 if (rt_type
== RT_TYPE_IMPORT
) {
4727 if (!is_import_rt_configured(vpn
)) {
4729 "%% Import RT is not configured for this VNI\n");
4732 } else if (rt_type
== RT_TYPE_EXPORT
) {
4733 if (!is_export_rt_configured(vpn
)) {
4735 "%% Export RT is not configured for this VNI\n");
4738 } else if (rt_type
== RT_TYPE_BOTH
) {
4739 if (!is_import_rt_configured(vpn
)
4740 && !is_export_rt_configured(vpn
)) {
4742 "%% Import/Export RT is not configured for this VNI\n");
4747 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4749 vty_out(vty
, "%% Malformed Route Target list\n");
4752 ecommunity_str(ecomdel
);
4754 if (rt_type
== RT_TYPE_IMPORT
) {
4755 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4757 "%% RT specified does not match configuration for this VNI\n");
4760 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4761 } else if (rt_type
== RT_TYPE_EXPORT
) {
4762 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4764 "%% RT specified does not match configuration for this VNI\n");
4767 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4768 } else if (rt_type
== RT_TYPE_BOTH
) {
4771 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4772 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4776 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4777 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4781 if (!found_ecomdel
) {
4783 "%% RT specified does not match configuration for this VNI\n");
4791 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4792 no_bgp_evpn_vni_rt_without_val_cmd
,
4793 "no route-target <import|export>",
4799 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4800 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4806 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4808 "This command is only supported under Default VRF\n");
4812 if (!strcmp(argv
[2]->text
, "import")) {
4813 rt_type
= RT_TYPE_IMPORT
;
4814 } else if (!strcmp(argv
[2]->text
, "export")) {
4815 rt_type
= RT_TYPE_EXPORT
;
4817 vty_out(vty
, "%% Invalid Route Target type\n");
4821 /* Check if we should disallow. */
4822 if (rt_type
== RT_TYPE_IMPORT
) {
4823 if (!is_import_rt_configured(vpn
)) {
4825 "%% Import RT is not configured for this VNI\n");
4829 if (!is_export_rt_configured(vpn
)) {
4831 "%% Export RT is not configured for this VNI\n");
4836 /* Unconfigure the RT. */
4837 if (rt_type
== RT_TYPE_IMPORT
)
4838 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4840 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
4845 static int vni_cmp(const void **a
, const void **b
)
4847 const struct bgpevpn
*first
= *a
;
4848 const struct bgpevpn
*secnd
= *b
;
4850 return secnd
->vni
- first
->vni
;
4854 * Output EVPN configuration information.
4856 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4859 char buf1
[RD_ADDRSTRLEN
];
4862 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
4863 struct listnode
*ln
;
4864 struct bgpevpn
*data
;
4866 list_sort(vnilist
, vni_cmp
);
4867 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
4868 write_vni_config(vty
, data
);
4870 list_delete_and_null(&vnilist
);
4873 if (bgp
->advertise_all_vni
)
4874 vty_out(vty
, " advertise-all-vni\n");
4876 if (bgp
->advertise_autort_rfc8365
)
4877 vty_out(vty
, " autort rfc8365-compatible\n");
4879 if (bgp
->advertise_gw_macip
)
4880 vty_out(vty
, " advertise-default-gw\n");
4882 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4883 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
4884 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
4885 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
4886 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
4888 vty_out(vty
, " advertise ipv4 unicast\n");
4891 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4892 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
4893 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
4894 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
4895 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
4897 vty_out(vty
, " advertise ipv6 unicast\n");
4900 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4901 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
4902 vty_out(vty
, " default-originate ipv4\n");
4904 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4905 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
4906 vty_out(vty
, " default-originate ipv6\n");
4908 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
4909 vty_out(vty
, " rd %s\n",
4910 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
4912 /* import route-target */
4913 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4915 struct listnode
*node
, *nnode
;
4916 struct ecommunity
*ecom
;
4918 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
4920 ecom_str
= ecommunity_ecom2str(
4921 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4922 vty_out(vty
, " route-target import %s\n", ecom_str
);
4923 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4927 /* export route-target */
4928 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4930 struct listnode
*node
, *nnode
;
4931 struct ecommunity
*ecom
;
4933 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
4935 ecom_str
= ecommunity_ecom2str(
4936 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4937 vty_out(vty
, " route-target export %s\n", ecom_str
);
4938 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4943 void bgp_ethernetvpn_init(void)
4945 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
4946 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
4947 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
4948 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
4949 install_element(VIEW_NODE
,
4950 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
4951 install_element(VIEW_NODE
,
4952 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
4955 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
4958 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
4959 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
4960 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
4961 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
4962 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
4963 #if defined(HAVE_CUMULUS)
4964 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
4965 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
4966 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
4967 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
4968 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
4969 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
4970 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
4971 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
4972 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
4973 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
4976 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
4977 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
4979 /* "show bgp l2vpn evpn" commands. */
4980 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
4981 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
4982 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
4983 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
4984 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
4985 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
4986 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
4987 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
4988 install_element(VIEW_NODE
,
4989 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
4990 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
4991 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
4992 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
4993 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
4995 /* "show bgp evpn" commands. */
4996 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
4997 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
4998 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
4999 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5000 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5001 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5002 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5003 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5004 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5005 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5006 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5008 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5009 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5010 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5011 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5012 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5013 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5014 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5015 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5016 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5017 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5018 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5019 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5020 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5021 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5022 install_element(BGP_EVPN_VNI_NODE
,
5023 &bgp_evpn_advertise_default_gw_vni_cmd
);
5024 install_element(BGP_EVPN_VNI_NODE
,
5025 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5026 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5027 install_element(BGP_EVPN_VNI_NODE
,
5028 &no_bgp_evpn_advertise_vni_subnet_cmd
);