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
26 #include "bgpd/bgpd.h"
27 #include "bgpd/bgp_table.h"
28 #include "bgpd/bgp_attr.h"
29 #include "bgpd/bgp_route.h"
30 #include "bgpd/bgp_mplsvpn.h"
31 #include "bgpd/bgp_vpn.h"
32 #include "bgpd/bgp_evpn_vty.h"
33 #include "bgpd/bgp_evpn.h"
34 #include "bgpd/bgp_evpn_private.h"
35 #include "bgpd/bgp_zebra.h"
36 #include "bgpd/bgp_vty.h"
38 #define SHOW_DISPLAY_STANDARD 0
39 #define SHOW_DISPLAY_TAGS 1
40 #define SHOW_DISPLAY_OVERLAY 2
41 #define VNI_STR_LEN 32
44 * Context for VNI hash walk - used by callbacks.
49 struct in_addr vtep_ip
;
53 struct evpn_config_write
{
58 #if defined(HAVE_CUMULUS)
59 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
63 u_char type
, sub_type
;
64 struct ecommunity_as
{
68 struct ecommunity_ip
{
72 struct listnode
*node
, *nnode
;
73 struct bgpevpn
*tmp_vpn
;
74 json_object
*json_rt
= NULL
;
75 json_object
*json_vnis
= NULL
;
76 char rt_buf
[RT_ADDRSTRLEN
];
79 json_rt
= json_object_new_object ();
80 json_vnis
= json_object_new_array ();
83 /* TODO: This needs to go into a function */
85 pnt
= (u_char
*)&irt
->rt
.val
;
88 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
92 case ECOMMUNITY_ENCODE_AS
:
93 eas
.as
= (*pnt
++ << 8);
96 eas
.val
= (*pnt
++ << 24);
97 eas
.val
|= (*pnt
++ << 16);
98 eas
.val
|= (*pnt
++ << 8);
101 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
104 json_object_string_add(json_rt
, "rt", rt_buf
);
106 vty_out(vty
, "Route-target: %s", rt_buf
);
110 case ECOMMUNITY_ENCODE_IP
:
111 memcpy(&eip
.ip
, pnt
, 4);
113 eip
.val
= (*pnt
++ << 8);
116 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
126 case ECOMMUNITY_ENCODE_AS4
:
127 eas
.as
= (*pnt
++ << 24);
128 eas
.as
|= (*pnt
++ << 16);
129 eas
.as
|= (*pnt
++ << 8);
132 eas
.val
= (*pnt
++ << 8);
135 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
138 json_object_string_add(json_rt
, "rt", rt_buf
);
140 vty_out(vty
, "Route-target: %s", rt_buf
);
150 "\nList of VNIs importing routes with this route-target:\n");
153 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
155 json_object_array_add(
156 json_vnis
, json_object_new_int64(tmp_vpn
->vni
));
158 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
162 json_object_object_add(json_rt
, "vnis", json_vnis
);
163 json_object_object_add(json
, rt_buf
, json_rt
);
168 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
170 json_object
*json
= NULL
;
171 struct vty
*vty
= NULL
;
172 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
177 display_import_rt(vty
, irt
);
182 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
183 struct bgp_node
*rd_rn
,
190 char rd_str
[RD_ADDRSTRLEN
];
192 pnt
= rd_rn
->p
.u
.val
;
194 /* Decode RD type. */
195 type
= decode_rd_type(pnt
);
200 vty_out(vty
, "Route Distinguisher: ");
204 decode_rd_as(pnt
+ 2, &rd_as
);
205 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
209 decode_rd_ip(pnt
+ 2, &rd_ip
);
210 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
215 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
219 vty_out(vty
, "%s\n", rd_str
);
222 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
226 " Network Next Hop Metric LocPrf Weight Path\n";
232 vty_out(vty
, "BGP table version is 0, local router ID is %s\n",
233 inet_ntoa(bgp
->router_id
));
235 "Status codes: s suppressed, d damped, h history, "
236 "* valid, > best, i - internal\n");
237 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
239 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
240 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
241 vty_out(vty
, "%s", ri_header
);
244 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
246 char buf1
[INET6_ADDRSTRLEN
];
248 struct listnode
*node
, *nnode
;
249 struct ecommunity
*ecom
;
250 json_object
*json_import_rtl
;
251 json_object
*json_export_rtl
;
254 json_import_rtl
= json_object_new_array();
255 json_export_rtl
= json_object_new_array();
256 json_object_int_add(json
, "vni", vpn
->vni
);
257 json_object_string_add(json
, "kernelFlag",
258 is_vni_live(vpn
) ? "Yes" : "No");
259 json_object_string_add(
261 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
262 json_object_string_add(json
, "originatorIp",
263 inet_ntoa(vpn
->originator_ip
));
264 json_object_string_add(json
, "advertiseGatewayMacip",
265 vpn
->advertise_gw_macip
? "Yes" : "No");
267 vty_out(vty
, "VNI: %d", vpn
->vni
);
268 if (is_vni_live(vpn
))
269 vty_out(vty
, " (known to the kernel)");
272 vty_out(vty
, " RD: %s\n",
273 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
274 vty_out(vty
, " Originator IP: %s\n",
275 inet_ntoa(vpn
->originator_ip
));
276 vty_out(vty
, " Advertise-gw-macip : %s\n",
277 vpn
->advertise_gw_macip
? "Yes" : "No");
281 vty_out(vty
, " Import Route Target:\n");
283 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
284 ecom_str
= ecommunity_ecom2str(ecom
,
285 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
288 json_object_array_add(json_import_rtl
,
289 json_object_new_string(ecom_str
));
291 vty_out(vty
, " %s\n", ecom_str
);
293 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
297 json_object_object_add(json
, "importRts", json_import_rtl
);
299 vty_out(vty
, " Export Route Target:\n");
301 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
302 ecom_str
= ecommunity_ecom2str(ecom
,
303 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
306 json_object_array_add(json_export_rtl
,
307 json_object_new_string(ecom_str
));
309 vty_out(vty
, " %s\n", ecom_str
);
311 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
315 json_object_object_add(json
, "exportRts", json_export_rtl
);
318 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
319 struct vty
*vty
, struct in_addr vtep_ip
,
325 u_int32_t prefix_cnt
, path_cnt
;
327 prefix_cnt
= path_cnt
= 0;
329 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
330 rn
= bgp_route_next(rn
)) {
331 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
332 int add_prefix_to_json
= 0;
333 char prefix_str
[BUFSIZ
];
334 json_object
*json_paths
= NULL
;
335 json_object
*json_prefix
= NULL
;
337 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
340 if (type
&& evp
->prefix
.route_type
!= type
)
344 json_prefix
= json_object_new_object();
347 /* Overall header/legend displayed once. */
349 bgp_evpn_show_route_header(vty
, bgp
, json
);
357 json_paths
= json_object_new_array();
359 /* For EVPN, the prefix is displayed for each path (to fit in
360 * with code that already exists).
362 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
363 json_object
*json_path
= NULL
;
366 && !IPV4_ADDR_SAME(&(vtep_ip
),
367 &(ri
->attr
->nexthop
)))
371 json_path
= json_object_new_array();
373 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
376 json_object_array_add(json_paths
, json_path
);
379 add_prefix_to_json
= 1;
382 if (json
&& add_prefix_to_json
) {
383 json_object_string_add(json_prefix
, "prefix",
385 json_object_int_add(json_prefix
, "prefixLen",
387 json_object_object_add(json_prefix
, "paths",
389 json_object_object_add(json
, prefix_str
, json_prefix
);
394 json_object_int_add(json
, "numPrefix", prefix_cnt
);
395 json_object_int_add(json
, "numPaths", path_cnt
);
398 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
399 type
? "(of requested type) " : "");
401 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s",
402 prefix_cnt
, path_cnt
,
403 type
? " (of requested type)" : "");
407 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
409 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
410 struct vni_walk_ctx
*wctx
= arg
;
411 struct vty
*vty
= wctx
->vty
;
412 json_object
*json
= wctx
->json
;
413 json_object
*json_vni
= NULL
;
414 char vni_str
[VNI_STR_LEN
];
416 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
418 json_vni
= json_object_new_object();
419 json_object_int_add(json_vni
, "vni", vpn
->vni
);
421 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
424 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
427 json_object_object_add(json
, vni_str
, json_vni
);
430 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
434 json_object
*json_vni
;
435 json_object
*json_import_rtl
;
436 json_object
*json_export_rtl
;
437 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
439 char buf2
[INET6_ADDRSTRLEN
];
442 struct listnode
*node
, *nnode
;
443 struct ecommunity
*ecom
;
449 json_vni
= json_object_new_object();
450 json_import_rtl
= json_object_new_array();
451 json_export_rtl
= json_object_new_array();
455 if (is_vni_live(vpn
))
459 json_object_int_add(json_vni
, "vni", vpn
->vni
);
460 json_object_string_add(json_vni
, "inKernel",
461 is_vni_live(vpn
) ? "True" : "False");
462 json_object_string_add(json_vni
, "originatorIp",
463 inet_ntoa(vpn
->originator_ip
));
464 json_object_string_add(
466 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
468 vty_out(vty
, "%-1s %-10u %-15s %-21s", buf1
, vpn
->vni
,
469 inet_ntoa(vpn
->originator_ip
),
470 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
473 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
474 ecom_str
= ecommunity_ecom2str(ecom
,
475 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
478 json_object_array_add(json_import_rtl
,
479 json_object_new_string(ecom_str
));
481 if (listcount(vpn
->import_rtl
) > 1)
482 sprintf(rt_buf
, "%s, ...", ecom_str
);
484 sprintf(rt_buf
, "%s", ecom_str
);
485 vty_out(vty
, " %-25s", rt_buf
);
488 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
490 /* If there are multiple import RTs we break here and show only
497 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
499 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
500 ecom_str
= ecommunity_ecom2str(ecom
,
501 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
504 json_object_array_add(json_export_rtl
,
505 json_object_new_string(ecom_str
));
507 if (listcount(vpn
->export_rtl
) > 1)
508 sprintf(rt_buf
, "%s, ...", ecom_str
);
510 sprintf(rt_buf
, "%s", ecom_str
);
511 vty_out(vty
, " %-25s", rt_buf
);
514 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
516 /* If there are multiple export RTs we break here and show only
523 char vni_str
[VNI_STR_LEN
];
524 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
525 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
526 json_object_object_add(json
, vni_str
, json_vni
);
531 #endif /* HAVE_CUMULUS */
533 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
534 enum bgp_show_type type
, void *output_arg
,
535 int option
, u_char use_json
)
537 afi_t afi
= AFI_L2VPN
;
539 struct bgp_table
*table
;
546 unsigned long output_count
= 0;
547 unsigned long total_count
= 0;
548 json_object
*json
= NULL
;
549 json_object
*json_nroute
= NULL
;
550 json_object
*json_array
= NULL
;
551 json_object
*json_scode
= NULL
;
552 json_object
*json_ocode
= NULL
;
554 bgp
= bgp_get_default();
557 vty_out(vty
, "No BGP process is configured\n");
559 vty_out(vty
, "{}\n");
564 json_scode
= json_object_new_object();
565 json_ocode
= json_object_new_object();
566 json
= json_object_new_object();
567 json_nroute
= json_object_new_object();
569 json_object_string_add(json_scode
, "suppressed", "s");
570 json_object_string_add(json_scode
, "damped", "d");
571 json_object_string_add(json_scode
, "history", "h");
572 json_object_string_add(json_scode
, "valid", "*");
573 json_object_string_add(json_scode
, "best", ">");
574 json_object_string_add(json_scode
, "internal", "i");
576 json_object_string_add(json_ocode
, "igp", "i");
577 json_object_string_add(json_ocode
, "egp", "e");
578 json_object_string_add(json_ocode
, "incomplete", "?");
581 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
582 rn
= bgp_route_next(rn
)) {
584 continue; /* XXX json TODO */
586 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
589 if ((table
= rn
->info
) != NULL
) {
592 for (rm
= bgp_table_top(table
); rm
;
593 rm
= bgp_route_next(rm
))
594 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
596 if (type
== bgp_show_type_neighbor
) {
597 union sockunion
*su
=
600 if (ri
->peer
->su_remote
== NULL
609 == SHOW_DISPLAY_TAGS
) {
614 json_object_string_add(
619 json_object_object_add(
623 json_object_object_add(
630 == SHOW_DISPLAY_TAGS
)
635 == SHOW_DISPLAY_OVERLAY
)
640 "BGP table version is 0, local router ID is %s\n",
644 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
646 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
661 /* Decode RD type. */
662 type
= decode_rd_type(pnt
);
663 /* Decode RD value. */
664 if (type
== RD_TYPE_AS
)
665 decode_rd_as(pnt
+ 2,
667 else if (type
== RD_TYPE_AS4
)
668 decode_rd_as4(pnt
+ 2,
670 else if (type
== RD_TYPE_IP
)
671 decode_rd_ip(pnt
+ 2,
675 if (type
== RD_TYPE_AS
676 || type
== RD_TYPE_AS4
)
688 json_object_string_add(
690 "routeDistinguisher",
694 "Route Distinguisher: ");
695 if (type
== RD_TYPE_AS
)
713 vty_out(vty
, "\n\n");
719 json_object_new_array();
722 if (option
== SHOW_DISPLAY_TAGS
)
725 SAFI_EVPN
, json_array
);
726 else if (option
== SHOW_DISPLAY_OVERLAY
)
727 route_vty_out_overlay(
731 route_vty_out(vty
, &rm
->p
, ri
,
739 if (output_count
== 0)
740 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
742 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
743 output_count
, total_count
);
747 DEFUN(show_ip_bgp_l2vpn_evpn
,
748 show_ip_bgp_l2vpn_evpn_cmd
,
749 "show [ip] bgp l2vpn evpn [json]",
750 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
752 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
753 use_json(argc
, argv
));
756 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
757 show_ip_bgp_l2vpn_evpn_rd_cmd
,
758 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
764 "Display information for a route distinguisher\n"
765 "VPN Route Distinguisher\n" JSON_STR
)
767 int idx_ext_community
= 0;
769 struct prefix_rd prd
;
771 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
773 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
775 vty_out(vty
, "%% Malformed Route Distinguisher\n");
778 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
779 use_json(argc
, argv
));
782 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
783 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
784 "show [ip] bgp l2vpn evpn all tags",
790 "Display information about all EVPN NLRIs\n"
791 "Display BGP tags for prefixes\n")
793 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
797 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
798 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
799 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
805 "Display information for a route distinguisher\n"
806 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
808 int idx_ext_community
= 0;
810 struct prefix_rd prd
;
812 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
814 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
816 vty_out(vty
, "%% Malformed Route Distinguisher\n");
819 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
823 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
824 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
825 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
831 "Display information about all EVPN NLRIs\n"
832 "Detailed information on TCP and BGP neighbor connections\n"
833 "Neighbor to display information about\n"
834 "Display routes learned from neighbor\n" JSON_STR
)
840 u_char uj
= use_json(argc
, argv
);
842 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
844 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
847 json_object
*json_no
= NULL
;
848 json_no
= json_object_new_object();
849 json_object_string_add(json_no
, "warning",
850 "Malformed address");
852 json_object_to_json_string(json_no
));
853 json_object_free(json_no
);
855 vty_out(vty
, "Malformed address: %s\n",
856 argv
[idx_ipv4
]->arg
);
860 peer
= peer_lookup(NULL
, &su
);
861 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
863 json_object
*json_no
= NULL
;
864 json_no
= json_object_new_object();
865 json_object_string_add(
867 "No such neighbor or address family");
869 json_object_to_json_string(json_no
));
870 json_object_free(json_no
);
872 vty_out(vty
, "%% No such neighbor or address family\n");
876 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
880 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
881 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
882 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
888 "Display information for a route distinguisher\n"
889 "VPN Route Distinguisher\n"
890 "Detailed information on TCP and BGP neighbor connections\n"
891 "Neighbor to display information about\n"
892 "Display routes learned from neighbor\n" JSON_STR
)
894 int idx_ext_community
= 0;
899 struct prefix_rd prd
;
900 u_char uj
= use_json(argc
, argv
);
902 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
903 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
905 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
908 json_object
*json_no
= NULL
;
909 json_no
= json_object_new_object();
910 json_object_string_add(json_no
, "warning",
911 "Malformed Route Distinguisher");
913 json_object_to_json_string(json_no
));
914 json_object_free(json_no
);
916 vty_out(vty
, "%% Malformed Route Distinguisher\n");
920 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
923 json_object
*json_no
= NULL
;
924 json_no
= json_object_new_object();
925 json_object_string_add(json_no
, "warning",
926 "Malformed address");
928 json_object_to_json_string(json_no
));
929 json_object_free(json_no
);
931 vty_out(vty
, "Malformed address: %s\n",
932 argv
[idx_ext_community
]->arg
);
936 peer
= peer_lookup(NULL
, &su
);
937 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
939 json_object
*json_no
= NULL
;
940 json_no
= json_object_new_object();
941 json_object_string_add(
943 "No such neighbor or address family");
945 json_object_to_json_string(json_no
));
946 json_object_free(json_no
);
948 vty_out(vty
, "%% No such neighbor or address family\n");
952 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
956 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
957 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
958 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
964 "Display information about all EVPN NLRIs\n"
965 "Detailed information on TCP and BGP neighbor connections\n"
966 "Neighbor to display information about\n"
967 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
973 u_char uj
= use_json(argc
, argv
);
975 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
977 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
980 json_object
*json_no
= NULL
;
981 json_no
= json_object_new_object();
982 json_object_string_add(json_no
, "warning",
983 "Malformed address");
985 json_object_to_json_string(json_no
));
986 json_object_free(json_no
);
988 vty_out(vty
, "Malformed address: %s\n",
989 argv
[idx_ipv4
]->arg
);
992 peer
= peer_lookup(NULL
, &su
);
993 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
995 json_object
*json_no
= NULL
;
996 json_no
= json_object_new_object();
997 json_object_string_add(
999 "No such neighbor or address family");
1000 vty_out(vty
, "%s\n",
1001 json_object_to_json_string(json_no
));
1002 json_object_free(json_no
);
1004 vty_out(vty
, "%% No such neighbor or address family\n");
1008 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1011 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1012 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1013 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
1019 "Display information for a route distinguisher\n"
1020 "VPN Route Distinguisher\n"
1021 "Detailed information on TCP and BGP neighbor connections\n"
1022 "Neighbor to display information about\n"
1023 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1025 int idx_ext_community
= 0;
1029 struct prefix_rd prd
;
1031 u_char uj
= use_json(argc
, argv
);
1033 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
1034 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1036 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1039 json_object
*json_no
= NULL
;
1040 json_no
= json_object_new_object();
1041 json_object_string_add(json_no
, "warning",
1042 "Malformed address");
1043 vty_out(vty
, "%s\n",
1044 json_object_to_json_string(json_no
));
1045 json_object_free(json_no
);
1047 vty_out(vty
, "Malformed address: %s\n",
1048 argv
[idx_ext_community
]->arg
);
1051 peer
= peer_lookup(NULL
, &su
);
1052 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1054 json_object
*json_no
= NULL
;
1055 json_no
= json_object_new_object();
1056 json_object_string_add(
1058 "No such neighbor or address family");
1059 vty_out(vty
, "%s\n",
1060 json_object_to_json_string(json_no
));
1061 json_object_free(json_no
);
1063 vty_out(vty
, "%% No such neighbor or address family\n");
1067 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1070 json_object
*json_no
= NULL
;
1071 json_no
= json_object_new_object();
1072 json_object_string_add(json_no
, "warning",
1073 "Malformed Route Distinguisher");
1074 vty_out(vty
, "%s\n",
1075 json_object_to_json_string(json_no
));
1076 json_object_free(json_no
);
1078 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1082 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1085 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1086 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1087 "show [ip] bgp l2vpn evpn all overlay",
1093 "Display information about all EVPN NLRIs\n"
1094 "Display BGP Overlay Information for prefixes\n")
1096 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1097 SHOW_DISPLAY_OVERLAY
,
1098 use_json(argc
, argv
));
1101 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1102 show_ip_bgp_evpn_rd_overlay_cmd
,
1103 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
1109 "Display information for a route distinguisher\n"
1110 "VPN Route Distinguisher\n"
1111 "Display BGP Overlay Information for prefixes\n")
1113 int idx_ext_community
= 0;
1115 struct prefix_rd prd
;
1117 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
1119 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1121 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1124 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1125 SHOW_DISPLAY_OVERLAY
,
1126 use_json(argc
, argv
));
1129 /* For testing purpose, static route of MPLS-VPN. */
1130 DEFUN(evpnrt5_network
,
1131 evpnrt5_network_cmd
,
1132 "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]",
1133 "Specify a network to announce via BGP\n"
1136 "Specify Route Distinguisher\n"
1137 "VPN Route Distinguisher\n"
1139 "Ethernet Tag Value\n"
1142 "Ethernet Segment Identifier\n"
1143 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1145 "Gateway IP ( A.B.C.D )\n"
1146 "Gateway IPv6 ( X:X::X:X )\n"
1147 "Router Mac Ext Comm\n"
1148 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1149 "Route-map to modify the attributes\n"
1150 "Name of the route map\n")
1152 int idx_ipv4_prefixlen
= 1;
1153 int idx_ext_community
= 3;
1158 int idx_routermac
= 13;
1160 return bgp_static_set_safi(
1161 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1162 argv
[idx_ext_community
]->arg
, argv
[idx_word
]->arg
,
1163 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
1164 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1165 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1166 argv
[idx_routermac
]->arg
);
1169 /* For testing purpose, static route of MPLS-VPN. */
1170 DEFUN(no_evpnrt5_network
,
1171 no_evpnrt5_network_cmd
,
1172 "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>",
1174 "Specify a network to announce via BGP\n"
1177 "Specify Route Distinguisher\n"
1178 "VPN Route Distinguisher\n"
1180 "Ethernet Tag Value\n"
1183 "Ethernet Segment Identifier\n"
1184 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1185 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1187 int idx_ipv4_prefixlen
= 2;
1188 int idx_ext_community
= 4;
1193 return bgp_static_unset_safi(
1194 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1195 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1196 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1197 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1200 #if defined(HAVE_CUMULUS)
1201 static void evpn_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1204 struct listnode
*node
, *nnode
, *node_to_del
;
1205 struct ecommunity
*ecom
, *ecom_auto
;
1206 struct ecommunity_val eval
;
1208 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
1210 ecom_auto
= ecommunity_new();
1211 ecommunity_add_val(ecom_auto
, &eval
);
1214 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
1215 if (ecommunity_match(ecom
, ecom_auto
)) {
1216 ecommunity_free(&ecom
);
1222 list_delete_node(rtl
, node_to_del
);
1224 ecommunity_free(&ecom_auto
);
1227 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1229 evpn_rt_delete_auto(bgp
, vpn
, vpn
->import_rtl
);
1232 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1234 evpn_rt_delete_auto(bgp
, vpn
, vpn
->export_rtl
);
1238 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1239 * check that this is a change.
1241 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1242 struct ecommunity
*ecomadd
)
1244 /* If the VNI is "live", we need to uninstall routes using the current
1245 * import RT(s) first before we update the import RT, and subsequently
1248 if (is_vni_live(vpn
))
1249 bgp_evpn_uninstall_routes(bgp
, vpn
);
1251 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1252 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1254 /* If the auto route-target is in use we must remove it */
1255 evpn_import_rt_delete_auto(bgp
, vpn
);
1257 /* Add new RT and rebuild the RT to VNI mapping */
1258 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1260 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1261 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1263 /* Install routes that match new import RT */
1264 if (is_vni_live(vpn
))
1265 bgp_evpn_install_routes(bgp
, vpn
);
1269 * Unconfigure Import RT(s) for a VNI (vty handler).
1271 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1272 struct ecommunity
*ecomdel
)
1274 struct listnode
*node
, *nnode
, *node_to_del
;
1275 struct ecommunity
*ecom
;
1277 /* Along the lines of "configure" except we have to reset to the
1280 if (is_vni_live(vpn
))
1281 bgp_evpn_uninstall_routes(bgp
, vpn
);
1283 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1284 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1286 /* Delete all import RTs */
1287 if (ecomdel
== NULL
) {
1288 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1289 ecommunity_free(&ecom
);
1291 list_delete_all_node(vpn
->import_rtl
);
1294 /* Delete a specific import RT */
1298 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1299 if (ecommunity_match(ecom
, ecomdel
)) {
1300 ecommunity_free(&ecom
);
1307 list_delete_node(vpn
->import_rtl
, node_to_del
);
1310 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1311 if (list_isempty(vpn
->import_rtl
)) {
1312 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1313 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1315 /* Rebuild the RT to VNI mapping */
1317 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1319 /* Install routes that match new import RT */
1320 if (is_vni_live(vpn
))
1321 bgp_evpn_install_routes(bgp
, vpn
);
1325 * Configure the Export RT for a VNI (vty handler). Caller expected to
1326 * check that this is a change. Note that only a single export RT is
1327 * allowed for a VNI and any change to configuration is implemented as
1328 * a "replace" (similar to other configuration).
1330 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1331 struct ecommunity
*ecomadd
)
1333 /* If the auto route-target is in use we must remove it */
1334 evpn_export_rt_delete_auto(bgp
, vpn
);
1336 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1337 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1339 if (is_vni_live(vpn
))
1340 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1344 * Unconfigure the Export RT for a VNI (vty handler)
1346 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1347 struct ecommunity
*ecomdel
)
1349 struct listnode
*node
, *nnode
, *node_to_del
;
1350 struct ecommunity
*ecom
;
1352 /* Delete all export RTs */
1353 if (ecomdel
== NULL
) {
1354 /* Reset to default and process all routes. */
1355 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1356 ecommunity_free(&ecom
);
1358 list_delete_all_node(vpn
->export_rtl
);
1361 /* Delete a specific export RT */
1365 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1366 if (ecommunity_match(ecom
, ecomdel
)) {
1367 ecommunity_free(&ecom
);
1374 list_delete_node(vpn
->export_rtl
, node_to_del
);
1377 if (list_isempty(vpn
->export_rtl
)) {
1378 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1379 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1382 if (is_vni_live(vpn
))
1383 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1387 * Configure RD for a VNI (vty handler)
1389 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1390 struct prefix_rd
*rd
)
1392 /* If the VNI is "live", we need to delete and withdraw this VNI's
1393 * local routes with the prior RD first. Then, after updating RD,
1394 * need to re-advertise.
1396 if (is_vni_live(vpn
))
1397 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1400 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1401 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1403 if (is_vni_live(vpn
))
1404 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1408 * Unconfigure RD for a VNI (vty handler)
1410 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1412 /* If the VNI is "live", we need to delete and withdraw this VNI's
1413 * local routes with the prior RD first. Then, after resetting RD
1414 * to automatic value, need to re-advertise.
1416 if (is_vni_live(vpn
))
1417 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1419 /* reset RD to default */
1420 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1422 if (is_vni_live(vpn
))
1423 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1427 * Create VNI, if not already present (VTY handler). Mark as configured.
1429 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1431 struct bgpevpn
*vpn
;
1436 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1438 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
);
1441 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1447 /* Mark as configured. */
1448 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1453 * Delete VNI. If VNI does not exist in the system (i.e., just
1454 * configuration), all that is needed is to free it. Otherwise,
1455 * any parameters configured for the VNI need to be reset (with
1456 * appropriate action) and the VNI marked as unconfigured; the
1457 * VNI will continue to exist, purely as a "learnt" entity.
1459 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1461 assert(bgp
->vnihash
);
1463 if (!is_vni_live(vpn
)) {
1464 bgp_evpn_free(bgp
, vpn
);
1468 /* We need to take the unconfigure action for each parameter of this VNI
1469 * that is configured. Some optimization is possible, but not worth the
1470 * additional code for an operation that should be pretty rare.
1472 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1474 /* First, deal with the export side - RD and export RT changes. */
1475 if (is_rd_configured(vpn
))
1476 evpn_unconfigure_rd(bgp
, vpn
);
1477 if (is_export_rt_configured(vpn
))
1478 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1480 /* Next, deal with the import side. */
1481 if (is_import_rt_configured(vpn
))
1482 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1488 * Display import RT mapping to VNIs (vty handler)
1490 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1499 bgp
->import_rt_hash
,
1500 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1505 * Display EVPN routes for all VNIs - vty handler.
1507 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1508 struct in_addr vtep_ip
,
1512 struct vni_walk_ctx wctx
;
1514 num_vnis
= hashcount(bgp
->vnihash
);
1517 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1520 wctx
.vtep_ip
= vtep_ip
;
1522 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1523 void *))show_vni_routes_hash
,
1528 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1530 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1531 vni_t vni
, struct in_addr orig_ip
,
1534 struct bgpevpn
*vpn
;
1535 struct prefix_evpn p
;
1536 struct bgp_node
*rn
;
1537 struct bgp_info
*ri
;
1538 u_int32_t path_cnt
= 0;
1541 json_object
*json_paths
= NULL
;
1547 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1549 vty_out(vty
, "VNI not found\n");
1553 /* See if route exists. */
1554 build_evpn_type3_prefix(&p
, orig_ip
);
1555 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1556 if (!rn
|| !rn
->info
) {
1558 vty_out(vty
, "%% Network not in table\n");
1563 json_paths
= json_object_new_array();
1565 /* Prefix and num paths displayed once per prefix. */
1566 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1568 /* Display each path for this prefix. */
1569 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1570 json_object
*json_path
= NULL
;
1573 json_path
= json_object_new_array();
1575 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1579 json_object_array_add(json_paths
, json_path
);
1586 json_object_object_add(json
, "paths", json_paths
);
1588 json_object_int_add(json
, "numPaths", path_cnt
);
1590 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1596 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1597 * By definition, only matching type-2 route will be displayed.
1599 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1600 vni_t vni
, struct ethaddr
*mac
,
1601 struct ipaddr
*ip
, json_object
*json
)
1603 struct bgpevpn
*vpn
;
1604 struct prefix_evpn p
;
1605 struct bgp_node
*rn
;
1606 struct bgp_info
*ri
;
1607 u_int32_t path_cnt
= 0;
1610 json_object
*json_paths
= NULL
;
1616 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1619 vty_out(vty
, "VNI not found\n");
1623 /* See if route exists. Look for both non-sticky and sticky. */
1624 build_evpn_type2_prefix(&p
, mac
, ip
);
1625 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1626 if (!rn
|| !rn
->info
) {
1628 vty_out(vty
, "%% Network not in table\n");
1633 json_paths
= json_object_new_array();
1635 /* Prefix and num paths displayed once per prefix. */
1636 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1638 /* Display each path for this prefix. */
1639 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1640 json_object
*json_path
= NULL
;
1643 json_path
= json_object_new_array();
1645 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1649 json_object_array_add(json_paths
, json_path
);
1656 json_object_object_add(json
, "paths", json_paths
);
1658 json_object_int_add(json
, "numPaths", path_cnt
);
1660 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1666 * Display EVPN routes for a VNI - vty handler.
1667 * If 'type' is non-zero, only routes matching that type are shown.
1668 * If the vtep_ip is non zero, only routes behind that vtep are shown
1670 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1671 int type
, struct in_addr vtep_ip
,
1674 struct bgpevpn
*vpn
;
1677 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1680 vty_out(vty
, "VNI not found\n");
1684 /* Walk this VNI's route table and display appropriate routes. */
1685 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
1689 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1690 * IP (vty handler). By definition, only matching type-2 route will be
1693 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1694 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1695 struct ipaddr
*ip
, json_object
*json
)
1697 struct prefix_evpn p
;
1698 struct bgp_node
*rn
;
1699 struct bgp_info
*ri
;
1702 u_int32_t path_cnt
= 0;
1703 json_object
*json_paths
= NULL
;
1704 char prefix_str
[BUFSIZ
];
1709 /* See if route exists. Look for both non-sticky and sticky. */
1710 build_evpn_type2_prefix(&p
, mac
, ip
);
1711 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1712 (struct prefix
*)&p
, prd
);
1713 if (!rn
|| !rn
->info
) {
1715 vty_out(vty
, "%% Network not in table\n");
1719 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
1720 sizeof(prefix_str
));
1722 /* Prefix and num paths displayed once per prefix. */
1723 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
1726 json_paths
= json_object_new_array();
1728 /* Display each path for this prefix. */
1729 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1730 json_object
*json_path
= NULL
;
1733 json_path
= json_object_new_array();
1735 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1739 json_object_array_add(json_paths
, json_path
);
1744 if (json
&& path_cnt
) {
1746 json_object_object_add(json
, prefix_str
, json_paths
);
1747 json_object_int_add(json
, "numPaths", path_cnt
);
1749 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1755 * Display BGP EVPN routing table -- for specific RD (vty handler)
1756 * If 'type' is non-zero, only routes matching that type are shown.
1758 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
1759 struct prefix_rd
*prd
, int type
,
1762 struct bgp_node
*rd_rn
;
1763 struct bgp_table
*table
;
1764 struct bgp_node
*rn
;
1765 struct bgp_info
*ri
;
1769 u_int32_t prefix_cnt
, path_cnt
;
1770 char rd_str
[RD_ADDRSTRLEN
];
1771 json_object
*json_rd
= NULL
;
1772 int add_rd_to_json
= 0;
1776 prefix_cnt
= path_cnt
= 0;
1778 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
1780 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1784 table
= (struct bgp_table
*)rd_rn
->info
;
1789 json_rd
= json_object_new_object();
1790 json_object_string_add(json_rd
, "rd", rd_str
);
1793 /* Display all prefixes with this RD. */
1794 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1795 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1796 json_object
*json_prefix
= NULL
;
1797 json_object
*json_paths
= NULL
;
1798 char prefix_str
[BUFSIZ
];
1799 int add_prefix_to_json
= 0;
1801 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
1802 sizeof(prefix_str
));
1804 if (type
&& evp
->prefix
.route_type
!= type
)
1808 json_prefix
= json_object_new_object();
1811 /* RD header and legend - once overall. */
1812 if (rd_header
&& !json
) {
1814 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1817 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1822 /* Prefix and num paths displayed once per prefix. */
1823 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
1830 json_paths
= json_object_new_array();
1832 /* Display each path for this prefix. */
1833 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1834 json_object
*json_path
= NULL
;
1837 json_path
= json_object_new_array();
1839 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1843 json_object_array_add(json_paths
, json_path
);
1846 add_prefix_to_json
= 1;
1850 if (json
&& add_prefix_to_json
) {
1851 json_object_object_add(json_prefix
, "paths",
1853 json_object_object_add(json_rd
, prefix_str
,
1858 if (json
&& add_rd_to_json
)
1859 json_object_object_add(json
, rd_str
, json_rd
);
1862 json_object_int_add(json
, "numPrefix", prefix_cnt
);
1863 json_object_int_add(json
, "numPaths", path_cnt
);
1865 if (prefix_cnt
== 0)
1866 vty_out(vty
, "No prefixes exist with this RD%s\n",
1867 type
? " (of requested type)" : "");
1870 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
1871 prefix_cnt
, path_cnt
,
1872 type
? " (of requested type)" : "");
1877 * Display BGP EVPN routing table - all routes (vty handler).
1878 * If 'type' is non-zero, only routes matching that type are shown.
1880 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
1883 struct bgp_node
*rd_rn
;
1884 struct bgp_table
*table
;
1885 struct bgp_node
*rn
;
1886 struct bgp_info
*ri
;
1891 u_int32_t prefix_cnt
, path_cnt
;
1895 prefix_cnt
= path_cnt
= 0;
1897 /* EVPN routing table is a 2-level table with the first level being
1900 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1901 rd_rn
= bgp_route_next(rd_rn
)) {
1902 char rd_str
[RD_ADDRSTRLEN
];
1903 json_object
*json_rd
= NULL
; /* contains routes for an RD */
1904 int add_rd_to_json
= 0;
1906 table
= (struct bgp_table
*)rd_rn
->info
;
1910 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
1914 json_rd
= json_object_new_object();
1915 json_object_string_add(json_rd
, "rd", rd_str
);
1920 /* Display all prefixes for an RD */
1921 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1922 json_object
*json_prefix
=
1923 NULL
; /* contains prefix under a RD */
1924 json_object
*json_paths
=
1925 NULL
; /* array of paths under a prefix*/
1926 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1927 char prefix_str
[BUFSIZ
];
1928 int add_prefix_to_json
= 0;
1930 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
1931 prefix_str
, sizeof(prefix_str
));
1933 if (type
&& evp
->prefix
.route_type
!= type
)
1937 /* Overall header/legend displayed once. */
1939 bgp_evpn_show_route_header(vty
, bgp
,
1944 /* RD header - per RD. */
1946 bgp_evpn_show_route_rd_header(
1955 json_prefix
= json_object_new_object();
1956 json_paths
= json_object_new_array();
1957 json_object_string_add(json_prefix
, "prefix",
1959 json_object_int_add(json_prefix
, "prefixLen",
1963 /* For EVPN, the prefix is displayed for each path (to
1965 * with code that already exists).
1967 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1968 json_object
*json_path
= NULL
;
1970 add_prefix_to_json
= 1;
1974 json_path
= json_object_new_array();
1976 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
1980 json_object_array_add(json_paths
,
1984 if (json
&& add_prefix_to_json
) {
1985 json_object_object_add(json_prefix
, "paths",
1987 json_object_object_add(json_rd
, prefix_str
,
1992 if (json
&& add_rd_to_json
)
1993 json_object_object_add(json
, rd_str
, json_rd
);
1997 json_object_int_add(json
, "numPrefix", prefix_cnt
);
1998 json_object_int_add(json
, "numPaths", path_cnt
);
2000 if (prefix_cnt
== 0) {
2001 vty_out(vty
, "No EVPN prefixes %sexist\n",
2002 type
? "(of requested type) " : "");
2004 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2005 prefix_cnt
, path_cnt
,
2006 type
? " (of requested type)" : "");
2012 * Display specified VNI (vty handler)
2014 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2017 struct bgpevpn
*vpn
;
2019 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2022 vty_out(vty
, "{}\n");
2024 vty_out(vty
, "VNI not found\n");
2029 display_vni(vty
, vpn
, json
);
2033 * Display a VNI (upon user query).
2035 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2041 num_vnis
= hashcount(bgp
->vnihash
);
2046 json_object_int_add(json
, "numVnis", num_vnis
);
2048 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
2049 vty_out(vty
, "Flags: * - Kernel\n");
2050 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s\n", "VNI",
2051 "Orig IP", "RD", "Import RT", "Export RT");
2056 hash_iterate(bgp
->vnihash
,
2057 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2062 * evpn - enable advertisement of default g/w
2064 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2067 if (bgp
->advertise_gw_macip
)
2070 bgp
->advertise_gw_macip
= 1;
2071 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2073 if (vpn
->advertise_gw_macip
)
2076 vpn
->advertise_gw_macip
= 1;
2077 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2084 * evpn - disable advertisement of default g/w
2086 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2087 struct bgpevpn
*vpn
)
2090 if (!bgp
->advertise_gw_macip
)
2093 bgp
->advertise_gw_macip
= 0;
2094 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2096 if (!vpn
->advertise_gw_macip
)
2099 vpn
->advertise_gw_macip
= 0;
2100 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2107 * EVPN (VNI advertisement) enabled. Register with zebra.
2109 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2111 bgp
->advertise_all_vni
= 1;
2112 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2116 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2117 * cache, EVPN routes (delete and withdraw from peers).
2119 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2121 bgp
->advertise_all_vni
= 0;
2122 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2123 bgp_evpn_cleanup_on_disable(bgp
);
2125 #endif /* HAVE_CUMULUS */
2127 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
, int *write
)
2129 char buf1
[INET6_ADDRSTRLEN
];
2130 afi_t afi
= AFI_L2VPN
;
2131 safi_t safi
= SAFI_EVPN
;
2133 struct listnode
*node
, *nnode
;
2134 struct ecommunity
*ecom
;
2136 if (is_vni_configured(vpn
)) {
2137 bgp_config_write_family_header(vty
, afi
, safi
, write
);
2138 vty_out(vty
, " vni %d\n", vpn
->vni
);
2139 if (is_rd_configured(vpn
))
2140 vty_out(vty
, " rd %s\n",
2141 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
2143 if (is_import_rt_configured(vpn
)) {
2144 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2146 ecom_str
= ecommunity_ecom2str(
2147 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2148 vty_out(vty
, " route-target import %s\n",
2150 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2154 if (is_export_rt_configured(vpn
)) {
2155 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2157 ecom_str
= ecommunity_ecom2str(
2158 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2159 vty_out(vty
, " route-target export %s\n",
2161 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2165 if (vpn
->advertise_gw_macip
)
2166 vty_out(vty
, " advertise-default-gw\n");
2168 vty_out(vty
, " exit-vni\n");
2172 static void write_vni_config_for_entry(struct hash_backet
*backet
,
2173 struct evpn_config_write
*cfg
)
2175 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2176 write_vni_config(cfg
->vty
, vpn
, &cfg
->write
);
2179 #if defined(HAVE_CUMULUS)
2180 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2181 bgp_evpn_advertise_default_gw_vni_cmd
,
2182 "advertise-default-gw",
2183 "Advertise defualt g/w mac-ip routes in EVPN for a VNI\n")
2185 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2186 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2194 evpn_set_advertise_default_gw(bgp
, vpn
);
2199 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2200 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2201 "no advertise-default-gw",
2203 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2205 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2206 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2214 evpn_unset_advertise_default_gw(bgp
, vpn
);
2220 DEFUN (bgp_evpn_advertise_default_gw
,
2221 bgp_evpn_advertise_default_gw_cmd
,
2222 "advertise-default-gw",
2223 "Advertise All defualt g/w mac-ip routes in EVPN\n")
2225 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2230 evpn_set_advertise_default_gw(bgp
, NULL
);
2235 DEFUN (no_bgp_evpn_advertise_default_gw
,
2236 no_bgp_evpn_advertise_default_gw_cmd
,
2237 "no advertise-default-gw",
2239 "Withdraw All default g/w mac-ip routes from EVPN\n")
2241 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2246 evpn_unset_advertise_default_gw(bgp
, NULL
);
2251 DEFUN (bgp_evpn_advertise_all_vni
,
2252 bgp_evpn_advertise_all_vni_cmd
,
2253 "advertise-all-vni",
2254 "Advertise All local VNIs\n")
2256 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2260 evpn_set_advertise_all_vni(bgp
);
2264 DEFUN (no_bgp_evpn_advertise_all_vni
,
2265 no_bgp_evpn_advertise_all_vni_cmd
,
2266 "no advertise-all-vni",
2268 "Advertise All local VNIs\n")
2270 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2274 evpn_unset_advertise_all_vni(bgp
);
2279 * Display VNI information - for all or a specific VNI
2281 DEFUN(show_bgp_l2vpn_evpn_vni
,
2282 show_bgp_l2vpn_evpn_vni_cmd
,
2283 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2296 json_object
*json
= NULL
;
2298 uj
= use_json(argc
, argv
);
2300 bgp
= bgp_get_default();
2304 if (!argv_find(argv
, argc
, "evpn", &idx
))
2308 json
= json_object_new_object();
2310 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
2312 json_object_string_add(json
, "advertiseGatewayMacip",
2313 bgp
->advertise_gw_macip
2316 json_object_string_add(json
, "advertiseAllVnis",
2317 bgp
->advertise_all_vni
2321 vty_out(vty
, "Advertise Gateway Macip: %s\n",
2322 bgp
->advertise_gw_macip
? "Enabled"
2325 /* Display all VNIs */
2326 vty_out(vty
, "Advertise All VNI flag: %s\n",
2327 bgp
->advertise_all_vni
? "Enabled"
2331 evpn_show_all_vnis(vty
, bgp
, json
);
2335 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
2338 /* Display specific VNI */
2339 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
2340 evpn_show_vni(vty
, bgp
, vni
, json
);
2344 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2345 json
, JSON_C_TO_STRING_PRETTY
));
2346 json_object_free(json
);
2353 * Display EVPN neighbor summary.
2355 DEFUN(show_bgp_l2vpn_evpn_summary
,
2356 show_bgp_l2vpn_evpn_summary_cmd
,
2357 "show bgp l2vpn evpn summary [json]",
2362 "Summary of BGP neighbor status\n"
2365 u_char uj
= use_json(argc
, argv
);
2366 return bgp_show_summary_vty(vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
2370 * Display global EVPN routing table.
2372 DEFUN(show_bgp_l2vpn_evpn_route
, show_bgp_l2vpn_evpn_route_cmd
,
2373 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2378 "EVPN route information\n"
2379 "Specify Route type\n"
2380 "MAC-IP (Type-2) route\n"
2381 "Multicast (Type-3) route\n"
2388 json_object
*json
= NULL
;
2390 uj
= use_json(argc
, argv
);
2392 bgp
= bgp_get_default();
2397 json
= json_object_new_object();
2400 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2401 /* Specific type is requested */
2402 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2403 type
= BGP_EVPN_MAC_IP_ROUTE
;
2404 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2405 type
= BGP_EVPN_IMET_ROUTE
;
2410 evpn_show_all_routes(vty
, bgp
, type
, json
);
2413 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2414 json
, JSON_C_TO_STRING_PRETTY
));
2415 json_object_free(json
);
2422 * Display global EVPN routing table for specific RD.
2424 DEFUN(show_bgp_l2vpn_evpn_route_rd
, show_bgp_l2vpn_evpn_route_rd_cmd
,
2425 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]",
2430 "EVPN route information\n"
2431 "Route Distinguisher\n"
2432 "ASN:XX or A.B.C.D:XX\n"
2433 "Specify Route type\n"
2434 "MAC-IP (Type-2) route\n"
2435 "Multicast (Type-3) route\n"
2440 struct prefix_rd prd
;
2445 json_object
*json
= NULL
;
2447 bgp
= bgp_get_default();
2451 /* check if we need json output */
2452 uj
= use_json(argc
, argv
);
2454 json
= json_object_new_object();
2457 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2458 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2461 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2467 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2468 /* Specific type is requested */
2469 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2470 type
= BGP_EVPN_MAC_IP_ROUTE
;
2471 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2472 type
= BGP_EVPN_IMET_ROUTE
;
2477 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
2480 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2481 json
, JSON_C_TO_STRING_PRETTY
));
2482 json_object_free(json
);
2489 * Display global EVPN routing table for specific RD and MACIP.
2491 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
2492 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
2493 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]",
2498 "EVPN route information\n"
2499 "Route Distinguisher\n"
2500 "ASN:XX or A.B.C.D:XX\n"
2502 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2504 "IP address (IPv4 or IPv6)\n"
2509 struct prefix_rd prd
;
2516 json_object
*json
= NULL
;
2518 memset(&mac
, 0, sizeof(struct ethaddr
));
2519 memset(&ip
, 0, sizeof(struct ipaddr
));
2521 bgp
= bgp_get_default();
2525 /* check if we need json output */
2526 uj
= use_json(argc
, argv
);
2528 json
= json_object_new_object();
2531 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2532 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2534 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2540 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
2541 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
2542 vty_out(vty
, "%% Malformed MAC address\n");
2547 /* get the ip if specified */
2548 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
2549 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
2550 vty_out(vty
, "%% Malformed IP address\n");
2555 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
2558 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2559 json
, JSON_C_TO_STRING_PRETTY
));
2560 json_object_free(json
);
2567 * Display per-VNI EVPN routing table.
2569 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
2570 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2575 "EVPN route information\n"
2576 "VXLAN Network Identifier\n"
2578 "Specify Route type\n"
2579 "MAC-IP (Type-2) route\n"
2580 "Multicast (Type-3) route\n"
2582 "Remote VTEP IP address\n"
2587 struct in_addr vtep_ip
;
2591 json_object
*json
= NULL
;
2593 bgp
= bgp_get_default();
2597 /* check if we need json output */
2598 uj
= use_json(argc
, argv
);
2600 json
= json_object_new_object();
2602 if (!argv_find(argv
, argc
, "evpn", &idx
))
2607 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2609 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
2610 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
2611 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
2612 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
2613 type
= BGP_EVPN_MAC_IP_ROUTE
;
2614 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
2615 type
= BGP_EVPN_IMET_ROUTE
;
2618 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
2619 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
2620 vty_out(vty
, "%% Malformed VTEP IP address\n");
2627 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
2630 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2631 json
, JSON_C_TO_STRING_PRETTY
));
2632 json_object_free(json
);
2639 * Display per-VNI EVPN routing table for specific MACIP.
2641 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
2642 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
2643 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2648 "EVPN route information\n"
2649 "VXLAN Network Identifier\n"
2652 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2654 "IP address (IPv4 or IPv6)\n"
2663 json_object
*json
= NULL
;
2665 bgp
= bgp_get_default();
2669 /* check if we need json output */
2670 uj
= use_json(argc
, argv
);
2672 json
= json_object_new_object();
2674 if (!argv_find(argv
, argc
, "evpn", &idx
))
2678 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2681 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
2682 vty_out(vty
, "%% Malformed MAC address\n");
2687 memset(&ip
, 0, sizeof(ip
));
2688 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
2690 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
2691 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
2692 vty_out(vty
, "%% Malformed IP address\n");
2697 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
2700 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2701 json
, JSON_C_TO_STRING_PRETTY
));
2702 json_object_free(json
);
2709 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
2711 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
2712 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
2713 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
2718 "EVPN route information\n"
2719 "VXLAN Network Identifier\n"
2721 "Multicast (Type-3) route\n"
2722 "Originating Router IP address\n"
2728 struct in_addr orig_ip
;
2731 json_object
*json
= NULL
;
2733 bgp
= bgp_get_default();
2737 /* check if we need json output */
2738 uj
= use_json(argc
, argv
);
2740 json
= json_object_new_object();
2742 if (!argv_find(argv
, argc
, "evpn", &idx
))
2746 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2749 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
2751 vty_out(vty
, "%% Malformed Originating Router IP address\n");
2755 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
2758 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2759 json
, JSON_C_TO_STRING_PRETTY
));
2760 json_object_free(json
);
2767 * Display per-VNI EVPN routing table - for all VNIs.
2769 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_l2vpn_evpn_route_vni_all_cmd
,
2770 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
2775 "EVPN route information\n"
2776 "VXLAN Network Identifier\n"
2779 "Remote VTEP IP address\n"
2783 struct in_addr vtep_ip
;
2786 json_object
*json
= NULL
;
2788 bgp
= bgp_get_default();
2792 /* check if we need json output */
2793 uj
= use_json(argc
, argv
);
2795 json
= json_object_new_object();
2797 if (!argv_find(argv
, argc
, "evpn", &idx
))
2801 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
2802 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
2803 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
2804 vty_out(vty
, "%% Malformed VTEP IP address\n");
2809 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
2812 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2813 json
, JSON_C_TO_STRING_PRETTY
));
2814 json_object_free(json
);
2821 * Display EVPN import route-target hash table
2823 DEFUN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_l2vpn_evpn_import_rt_cmd
,
2824 "show bgp l2vpn evpn import-rt [json]",
2829 "Show import route target\n"
2834 json_object
*json
= NULL
;
2836 bgp
= bgp_get_default();
2840 uj
= use_json(argc
, argv
);
2842 json
= json_object_new_object();
2844 evpn_show_import_rts(vty
, bgp
, json
);
2847 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2848 json
, JSON_C_TO_STRING_PRETTY
));
2849 json_object_free(json
);
2855 #if defined(HAVE_CUMULUS)
2856 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
2857 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
2861 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
2862 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
2863 "Summary of BGP neighbor status\n"
2866 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
2867 "show bgp evpn route [type <macip|multicast>]",
2868 SHOW_STR BGP_STR EVPN_HELP_STR
2869 "EVPN route information\n"
2870 "Specify Route type\n"
2871 "MAC-IP (Type-2) route\n"
2872 "Multicast (Type-3) route\n")
2875 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
2876 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
2877 SHOW_STR BGP_STR EVPN_HELP_STR
2878 "EVPN route information\n"
2879 "Route Distinguisher\n"
2880 "ASN:XX or A.B.C.D:XX\n"
2881 "Specify Route type\n"
2882 "MAC-IP (Type-2) route\n"
2883 "Multicast (Type-3) route\n")
2886 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
2887 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
2888 SHOW_STR BGP_STR EVPN_HELP_STR
2889 "EVPN route information\n"
2890 "Route Distinguisher\n"
2891 "ASN:XX or A.B.C.D:XX\n"
2893 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2895 "IP address (IPv4 or IPv6)\n")
2898 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
2899 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
2900 SHOW_STR BGP_STR EVPN_HELP_STR
2901 "EVPN route information\n"
2902 "VXLAN Network Identifier\n"
2904 "Specify Route type\n"
2905 "MAC-IP (Type-2) route\n"
2906 "Multicast (Type-3) route\n"
2908 "Remote VTEP IP address\n")
2910 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
2911 show_bgp_evpn_route_vni_macip_cmd
,
2912 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
2913 SHOW_STR BGP_STR EVPN_HELP_STR
2914 "EVPN route information\n"
2915 "VXLAN Network Identifier\n"
2918 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2920 "IP address (IPv4 or IPv6)\n")
2922 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
2923 show_bgp_evpn_route_vni_multicast_cmd
,
2924 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2925 SHOW_STR BGP_STR EVPN_HELP_STR
2926 "EVPN route information\n"
2927 "VXLAN Network Identifier\n"
2929 "Multicast (Type-3) route\n"
2930 "Originating Router IP address\n")
2932 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
2933 "show bgp evpn route vni all [vtep A.B.C.D]",
2934 SHOW_STR BGP_STR EVPN_HELP_STR
2935 "EVPN route information\n"
2936 "VXLAN Network Identifier\n"
2939 "Remote VTEP IP address\n")
2941 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
2942 "show bgp evpn import-rt",
2943 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
2946 DEFUN_NOSH (bgp_evpn_vni
,
2949 "VXLAN Network Identifier\n"
2953 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2954 struct bgpevpn
*vpn
;
2959 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2961 /* Create VNI, or mark as configured. */
2962 vpn
= evpn_create_update_vni(bgp
, vni
);
2964 vty_out(vty
, "%% Failed to create VNI \n");
2968 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
2972 DEFUN (no_bgp_evpn_vni
,
2973 no_bgp_evpn_vni_cmd
,
2974 "no vni (1-16777215)",
2976 "VXLAN Network Identifier\n"
2980 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2981 struct bgpevpn
*vpn
;
2986 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2988 /* Check if we should disallow. */
2989 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2991 vty_out(vty
, "%% Specified VNI does not exist\n");
2994 if (!is_vni_configured(vpn
)) {
2995 vty_out(vty
, "%% Specified VNI is not configured\n");
2999 evpn_delete_vni(bgp
, vpn
);
3003 DEFUN_NOSH (exit_vni
,
3006 "Exit from VNI mode\n")
3008 if (vty
->node
== BGP_EVPN_VNI_NODE
)
3009 vty
->node
= BGP_EVPN_NODE
;
3013 DEFUN (bgp_evpn_vni_rd
,
3014 bgp_evpn_vni_rd_cmd
,
3015 "rd ASN:nn_or_IP-address:nn",
3016 "Route Distinguisher\n"
3017 "ASN:XX or A.B.C.D:XX\n")
3019 struct prefix_rd prd
;
3020 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3021 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3027 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3029 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3033 /* If same as existing value, there is nothing more to do. */
3034 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
3037 /* Configure or update the RD. */
3038 evpn_configure_rd(bgp
, vpn
, &prd
);
3042 DEFUN (no_bgp_evpn_vni_rd
,
3043 no_bgp_evpn_vni_rd_cmd
,
3044 "no rd ASN:nn_or_IP-address:nn",
3046 "Route Distinguisher\n"
3047 "ASN:XX or A.B.C.D:XX\n")
3049 struct prefix_rd prd
;
3050 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3051 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3057 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3059 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3063 /* Check if we should disallow. */
3064 if (!is_rd_configured(vpn
)) {
3065 vty_out(vty
, "%% RD is not configured for this VNI\n");
3069 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
3071 "%% RD specified does not match configuration for this VNI\n");
3075 evpn_unconfigure_rd(bgp
, vpn
);
3079 DEFUN (no_bgp_evpn_vni_rd_without_val
,
3080 no_bgp_evpn_vni_rd_without_val_cmd
,
3083 "Route Distinguisher\n")
3085 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3086 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3091 /* Check if we should disallow. */
3092 if (!is_rd_configured(vpn
)) {
3093 vty_out(vty
, "%% RD is not configured for this VNI\n");
3097 evpn_unconfigure_rd(bgp
, vpn
);
3102 * Loop over all extended-communities in the route-target list rtl and
3103 * return 1 if we find ecomtarget
3105 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
3106 struct ecommunity
*ecomtarget
)
3108 struct listnode
*node
, *nnode
;
3109 struct ecommunity
*ecom
;
3111 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
3112 if (ecommunity_match(ecom
, ecomtarget
))
3120 DEFUN (bgp_evpn_vni_rt
,
3121 bgp_evpn_vni_rt_cmd
,
3122 "route-target <both|import|export> RT",
3124 "import and export\n"
3127 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3129 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3130 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3132 struct ecommunity
*ecomadd
= NULL
;
3137 if (!strcmp(argv
[1]->arg
, "import"))
3138 rt_type
= RT_TYPE_IMPORT
;
3139 else if (!strcmp(argv
[1]->arg
, "export"))
3140 rt_type
= RT_TYPE_EXPORT
;
3141 else if (!strcmp(argv
[1]->arg
, "both"))
3142 rt_type
= RT_TYPE_BOTH
;
3144 vty_out(vty
, "%% Invalid Route Target type\n");
3148 /* Add/update the import route-target */
3149 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
3150 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3151 ECOMMUNITY_ROUTE_TARGET
, 0);
3153 vty_out(vty
, "%% Malformed Route Target list\n");
3156 ecommunity_str(ecomadd
);
3158 /* Do nothing if we already have this import route-target */
3159 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
3160 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
3163 /* Add/update the export route-target */
3164 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
3165 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3166 ECOMMUNITY_ROUTE_TARGET
, 0);
3168 vty_out(vty
, "%% Malformed Route Target list\n");
3171 ecommunity_str(ecomadd
);
3173 /* Do nothing if we already have this export route-target */
3174 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
3175 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
3181 DEFUN (no_bgp_evpn_vni_rt
,
3182 no_bgp_evpn_vni_rt_cmd
,
3183 "no route-target <both|import|export> RT",
3186 "import and export\n"
3189 "ASN:XX or A.B.C.D:XX\n")
3191 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3192 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3193 int rt_type
, found_ecomdel
;
3194 struct ecommunity
*ecomdel
= NULL
;
3199 if (!strcmp(argv
[2]->arg
, "import"))
3200 rt_type
= RT_TYPE_IMPORT
;
3201 else if (!strcmp(argv
[2]->arg
, "export"))
3202 rt_type
= RT_TYPE_EXPORT
;
3203 else if (!strcmp(argv
[2]->arg
, "both"))
3204 rt_type
= RT_TYPE_BOTH
;
3206 vty_out(vty
, "%% Invalid Route Target type\n");
3210 /* The user did "no route-target import", check to see if there are any
3211 * import route-targets configured. */
3212 if (rt_type
== RT_TYPE_IMPORT
) {
3213 if (!is_import_rt_configured(vpn
)) {
3215 "%% Import RT is not configured for this VNI\n");
3218 } else if (rt_type
== RT_TYPE_EXPORT
) {
3219 if (!is_export_rt_configured(vpn
)) {
3221 "%% Export RT is not configured for this VNI\n");
3224 } else if (rt_type
== RT_TYPE_BOTH
) {
3225 if (!is_import_rt_configured(vpn
)
3226 && !is_export_rt_configured(vpn
)) {
3228 "%% Import/Export RT is not configured for this VNI\n");
3233 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
3235 vty_out(vty
, "%% Malformed Route Target list\n");
3238 ecommunity_str(ecomdel
);
3240 if (rt_type
== RT_TYPE_IMPORT
) {
3241 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3243 "%% RT specified does not match configuration for this VNI\n");
3246 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3247 } else if (rt_type
== RT_TYPE_EXPORT
) {
3248 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3250 "%% RT specified does not match configuration for this VNI\n");
3253 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3254 } else if (rt_type
== RT_TYPE_BOTH
) {
3257 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3258 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3262 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3263 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3267 if (!found_ecomdel
) {
3269 "%% RT specified does not match configuration for this VNI\n");
3277 DEFUN (no_bgp_evpn_vni_rt_without_val
,
3278 no_bgp_evpn_vni_rt_without_val_cmd
,
3279 "no route-target <import|export>",
3285 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3286 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3292 if (!strcmp(argv
[2]->arg
, "import")) {
3293 rt_type
= RT_TYPE_IMPORT
;
3294 } else if (!strcmp(argv
[2]->arg
, "export")) {
3295 rt_type
= RT_TYPE_EXPORT
;
3297 vty_out(vty
, "%% Invalid Route Target type\n");
3301 /* Check if we should disallow. */
3302 if (rt_type
== RT_TYPE_IMPORT
) {
3303 if (!is_import_rt_configured(vpn
)) {
3305 "%% Import RT is not configured for this VNI\n");
3309 if (!is_export_rt_configured(vpn
)) {
3311 "%% Export RT is not configured for this VNI\n");
3316 /* Unconfigure the RT. */
3317 if (rt_type
== RT_TYPE_IMPORT
)
3318 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
3320 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
3325 * Output EVPN configuration information.
3327 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
3328 safi_t safi
, int *write
)
3330 struct evpn_config_write cfg
;
3335 hash_iterate(bgp
->vnihash
,
3336 (void (*)(struct hash_backet
*,
3337 void *))write_vni_config_for_entry
,
3342 if (bgp
->advertise_all_vni
) {
3343 bgp_config_write_family_header(vty
, afi
, safi
, write
);
3344 vty_out(vty
, " advertise-all-vni\n");
3347 if (bgp
->advertise_gw_macip
) {
3348 bgp_config_write_family_header(vty
, afi
, safi
, write
);
3349 vty_out(vty
, " advertise-default-gw\n");
3353 void bgp_ethernetvpn_init(void)
3355 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
3356 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
3357 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
3358 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
3359 install_element(VIEW_NODE
,
3360 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
3361 install_element(VIEW_NODE
,
3362 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
3365 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
3368 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
3369 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
3370 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
3371 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
3372 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
3373 #if defined(HAVE_CUMULUS)
3374 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
3375 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
3376 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
3377 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
3379 /* "show bgp l2vpn evpn" commands. */
3380 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
3381 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
3382 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
3383 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
3384 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
3385 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
3386 install_element(VIEW_NODE
,
3387 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
3388 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
3389 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
3390 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
3392 /* "show bgp evpn" commands. */
3393 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
3394 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
3395 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
3396 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
3397 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
3398 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
3399 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
3400 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
3401 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
3402 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
3404 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
3405 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
3406 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
3407 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
3408 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
3409 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
3410 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
3411 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
3412 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
3413 install_element(BGP_EVPN_VNI_NODE
,
3414 &bgp_evpn_advertise_default_gw_vni_cmd
);
3415 install_element(BGP_EVPN_VNI_NODE
,
3416 &no_bgp_evpn_advertise_default_gw_vni_cmd
);