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
, json
);
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
];
525 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
526 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
527 json_object_object_add(json
, vni_str
, json_vni
);
532 #endif /* HAVE_CUMULUS */
534 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
535 enum bgp_show_type type
, void *output_arg
,
536 int option
, u_char use_json
)
538 afi_t afi
= AFI_L2VPN
;
540 struct bgp_table
*table
;
547 unsigned long output_count
= 0;
548 unsigned long total_count
= 0;
549 json_object
*json
= NULL
;
550 json_object
*json_nroute
= NULL
;
551 json_object
*json_array
= NULL
;
552 json_object
*json_scode
= NULL
;
553 json_object
*json_ocode
= NULL
;
555 bgp
= bgp_get_default();
558 vty_out(vty
, "No BGP process is configured\n");
560 vty_out(vty
, "{}\n");
565 json_scode
= json_object_new_object();
566 json_ocode
= json_object_new_object();
567 json
= json_object_new_object();
568 json_nroute
= json_object_new_object();
570 json_object_string_add(json_scode
, "suppressed", "s");
571 json_object_string_add(json_scode
, "damped", "d");
572 json_object_string_add(json_scode
, "history", "h");
573 json_object_string_add(json_scode
, "valid", "*");
574 json_object_string_add(json_scode
, "best", ">");
575 json_object_string_add(json_scode
, "internal", "i");
577 json_object_string_add(json_ocode
, "igp", "i");
578 json_object_string_add(json_ocode
, "egp", "e");
579 json_object_string_add(json_ocode
, "incomplete", "?");
582 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
583 rn
= bgp_route_next(rn
)) {
585 continue; /* XXX json TODO */
587 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
590 if ((table
= rn
->info
) != NULL
) {
593 for (rm
= bgp_table_top(table
); rm
;
594 rm
= bgp_route_next(rm
))
595 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
597 if (type
== bgp_show_type_neighbor
) {
598 union sockunion
*su
=
601 if (ri
->peer
->su_remote
== NULL
610 == SHOW_DISPLAY_TAGS
) {
615 json_object_string_add(
620 json_object_object_add(
624 json_object_object_add(
631 == SHOW_DISPLAY_TAGS
)
636 == SHOW_DISPLAY_OVERLAY
)
641 "BGP table version is 0, local router ID is %s\n",
645 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
647 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
662 /* Decode RD type. */
663 type
= decode_rd_type(pnt
);
664 /* Decode RD value. */
665 if (type
== RD_TYPE_AS
)
666 decode_rd_as(pnt
+ 2,
668 else if (type
== RD_TYPE_AS4
)
669 decode_rd_as4(pnt
+ 2,
671 else if (type
== RD_TYPE_IP
)
672 decode_rd_ip(pnt
+ 2,
676 if (type
== RD_TYPE_AS
677 || type
== RD_TYPE_AS4
)
689 json_object_string_add(
691 "routeDistinguisher",
695 "Route Distinguisher: ");
696 if (type
== RD_TYPE_AS
)
714 vty_out(vty
, "\n\n");
720 json_object_new_array();
723 if (option
== SHOW_DISPLAY_TAGS
)
726 SAFI_EVPN
, json_array
);
727 else if (option
== SHOW_DISPLAY_OVERLAY
)
728 route_vty_out_overlay(
732 route_vty_out(vty
, &rm
->p
, ri
,
740 if (output_count
== 0)
741 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
743 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
744 output_count
, total_count
);
748 DEFUN(show_ip_bgp_l2vpn_evpn
,
749 show_ip_bgp_l2vpn_evpn_cmd
,
750 "show [ip] bgp l2vpn evpn [json]",
751 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
753 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
754 use_json(argc
, argv
));
757 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
758 show_ip_bgp_l2vpn_evpn_rd_cmd
,
759 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
765 "Display information for a route distinguisher\n"
766 "VPN Route Distinguisher\n" JSON_STR
)
768 int idx_ext_community
= 0;
770 struct prefix_rd prd
;
772 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
774 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
776 vty_out(vty
, "%% Malformed Route Distinguisher\n");
779 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
780 use_json(argc
, argv
));
783 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
784 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
785 "show [ip] bgp l2vpn evpn all tags",
791 "Display information about all EVPN NLRIs\n"
792 "Display BGP tags for prefixes\n")
794 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
798 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
799 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
800 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
806 "Display information for a route distinguisher\n"
807 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
809 int idx_ext_community
= 0;
811 struct prefix_rd prd
;
813 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
815 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
817 vty_out(vty
, "%% Malformed Route Distinguisher\n");
820 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
824 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
825 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
826 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
832 "Display information about all EVPN NLRIs\n"
833 "Detailed information on TCP and BGP neighbor connections\n"
834 "Neighbor to display information about\n"
835 "Display routes learned from neighbor\n" JSON_STR
)
841 u_char uj
= use_json(argc
, argv
);
843 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
845 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
848 json_object
*json_no
= NULL
;
849 json_no
= json_object_new_object();
850 json_object_string_add(json_no
, "warning",
851 "Malformed address");
853 json_object_to_json_string(json_no
));
854 json_object_free(json_no
);
856 vty_out(vty
, "Malformed address: %s\n",
857 argv
[idx_ipv4
]->arg
);
861 peer
= peer_lookup(NULL
, &su
);
862 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
864 json_object
*json_no
= NULL
;
865 json_no
= json_object_new_object();
866 json_object_string_add(
868 "No such neighbor or address family");
870 json_object_to_json_string(json_no
));
871 json_object_free(json_no
);
873 vty_out(vty
, "%% No such neighbor or address family\n");
877 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
881 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
882 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
883 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
889 "Display information for a route distinguisher\n"
890 "VPN Route Distinguisher\n"
891 "Detailed information on TCP and BGP neighbor connections\n"
892 "Neighbor to display information about\n"
893 "Display routes learned from neighbor\n" JSON_STR
)
895 int idx_ext_community
= 0;
900 struct prefix_rd prd
;
901 u_char uj
= use_json(argc
, argv
);
903 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
904 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
906 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
909 json_object
*json_no
= NULL
;
910 json_no
= json_object_new_object();
911 json_object_string_add(json_no
, "warning",
912 "Malformed Route Distinguisher");
914 json_object_to_json_string(json_no
));
915 json_object_free(json_no
);
917 vty_out(vty
, "%% Malformed Route Distinguisher\n");
921 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
924 json_object
*json_no
= NULL
;
925 json_no
= json_object_new_object();
926 json_object_string_add(json_no
, "warning",
927 "Malformed address");
929 json_object_to_json_string(json_no
));
930 json_object_free(json_no
);
932 vty_out(vty
, "Malformed address: %s\n",
933 argv
[idx_ext_community
]->arg
);
937 peer
= peer_lookup(NULL
, &su
);
938 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
940 json_object
*json_no
= NULL
;
941 json_no
= json_object_new_object();
942 json_object_string_add(
944 "No such neighbor or address family");
946 json_object_to_json_string(json_no
));
947 json_object_free(json_no
);
949 vty_out(vty
, "%% No such neighbor or address family\n");
953 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
957 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
958 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
959 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
965 "Display information about all EVPN NLRIs\n"
966 "Detailed information on TCP and BGP neighbor connections\n"
967 "Neighbor to display information about\n"
968 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
974 u_char uj
= use_json(argc
, argv
);
976 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
978 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
981 json_object
*json_no
= NULL
;
982 json_no
= json_object_new_object();
983 json_object_string_add(json_no
, "warning",
984 "Malformed address");
986 json_object_to_json_string(json_no
));
987 json_object_free(json_no
);
989 vty_out(vty
, "Malformed address: %s\n",
990 argv
[idx_ipv4
]->arg
);
993 peer
= peer_lookup(NULL
, &su
);
994 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
996 json_object
*json_no
= NULL
;
997 json_no
= json_object_new_object();
998 json_object_string_add(
1000 "No such neighbor or address family");
1001 vty_out(vty
, "%s\n",
1002 json_object_to_json_string(json_no
));
1003 json_object_free(json_no
);
1005 vty_out(vty
, "%% No such neighbor or address family\n");
1009 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1012 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1013 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1014 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
1020 "Display information for a route distinguisher\n"
1021 "VPN Route Distinguisher\n"
1022 "Detailed information on TCP and BGP neighbor connections\n"
1023 "Neighbor to display information about\n"
1024 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1026 int idx_ext_community
= 0;
1030 struct prefix_rd prd
;
1032 u_char uj
= use_json(argc
, argv
);
1034 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
1035 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1037 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1040 json_object
*json_no
= NULL
;
1041 json_no
= json_object_new_object();
1042 json_object_string_add(json_no
, "warning",
1043 "Malformed address");
1044 vty_out(vty
, "%s\n",
1045 json_object_to_json_string(json_no
));
1046 json_object_free(json_no
);
1048 vty_out(vty
, "Malformed address: %s\n",
1049 argv
[idx_ext_community
]->arg
);
1052 peer
= peer_lookup(NULL
, &su
);
1053 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1055 json_object
*json_no
= NULL
;
1056 json_no
= json_object_new_object();
1057 json_object_string_add(
1059 "No such neighbor or address family");
1060 vty_out(vty
, "%s\n",
1061 json_object_to_json_string(json_no
));
1062 json_object_free(json_no
);
1064 vty_out(vty
, "%% No such neighbor or address family\n");
1068 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1071 json_object
*json_no
= NULL
;
1072 json_no
= json_object_new_object();
1073 json_object_string_add(json_no
, "warning",
1074 "Malformed Route Distinguisher");
1075 vty_out(vty
, "%s\n",
1076 json_object_to_json_string(json_no
));
1077 json_object_free(json_no
);
1079 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1083 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1086 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1087 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1088 "show [ip] bgp l2vpn evpn all overlay",
1094 "Display information about all EVPN NLRIs\n"
1095 "Display BGP Overlay Information for prefixes\n")
1097 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1098 SHOW_DISPLAY_OVERLAY
,
1099 use_json(argc
, argv
));
1102 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1103 show_ip_bgp_evpn_rd_overlay_cmd
,
1104 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
1110 "Display information for a route distinguisher\n"
1111 "VPN Route Distinguisher\n"
1112 "Display BGP Overlay Information for prefixes\n")
1114 int idx_ext_community
= 0;
1116 struct prefix_rd prd
;
1118 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
1120 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1122 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1125 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1126 SHOW_DISPLAY_OVERLAY
,
1127 use_json(argc
, argv
));
1130 /* For testing purpose, static route of MPLS-VPN. */
1131 DEFUN(evpnrt5_network
,
1132 evpnrt5_network_cmd
,
1133 "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]",
1134 "Specify a network to announce via BGP\n"
1137 "Specify Route Distinguisher\n"
1138 "VPN Route Distinguisher\n"
1140 "Ethernet Tag Value\n"
1143 "Ethernet Segment Identifier\n"
1144 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1146 "Gateway IP ( A.B.C.D )\n"
1147 "Gateway IPv6 ( X:X::X:X )\n"
1148 "Router Mac Ext Comm\n"
1149 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1150 "Route-map to modify the attributes\n"
1151 "Name of the route map\n")
1153 int idx_ipv4_prefixlen
= 1;
1154 int idx_ext_community
= 3;
1159 int idx_routermac
= 13;
1161 return bgp_static_set_safi(
1162 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1163 argv
[idx_ext_community
]->arg
, argv
[idx_word
]->arg
,
1164 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
1165 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1166 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1167 argv
[idx_routermac
]->arg
);
1170 /* For testing purpose, static route of MPLS-VPN. */
1171 DEFUN(no_evpnrt5_network
,
1172 no_evpnrt5_network_cmd
,
1173 "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>",
1175 "Specify a network to announce via BGP\n"
1178 "Specify Route Distinguisher\n"
1179 "VPN Route Distinguisher\n"
1181 "Ethernet Tag Value\n"
1184 "Ethernet Segment Identifier\n"
1185 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1186 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1188 int idx_ipv4_prefixlen
= 2;
1189 int idx_ext_community
= 4;
1194 return bgp_static_unset_safi(
1195 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1196 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1197 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1198 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1201 #if defined(HAVE_CUMULUS)
1202 static void evpn_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1205 struct listnode
*node
, *nnode
, *node_to_del
;
1206 struct ecommunity
*ecom
, *ecom_auto
;
1207 struct ecommunity_val eval
;
1209 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
1211 ecom_auto
= ecommunity_new();
1212 ecommunity_add_val(ecom_auto
, &eval
);
1215 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
1216 if (ecommunity_match(ecom
, ecom_auto
)) {
1217 ecommunity_free(&ecom
);
1223 list_delete_node(rtl
, node_to_del
);
1225 ecommunity_free(&ecom_auto
);
1228 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1230 evpn_rt_delete_auto(bgp
, vpn
, vpn
->import_rtl
);
1233 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1235 evpn_rt_delete_auto(bgp
, vpn
, vpn
->export_rtl
);
1239 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1240 * check that this is a change.
1242 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1243 struct ecommunity
*ecomadd
)
1245 /* If the VNI is "live", we need to uninstall routes using the current
1246 * import RT(s) first before we update the import RT, and subsequently
1249 if (is_vni_live(vpn
))
1250 bgp_evpn_uninstall_routes(bgp
, vpn
);
1252 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1253 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1255 /* If the auto route-target is in use we must remove it */
1256 evpn_import_rt_delete_auto(bgp
, vpn
);
1258 /* Add new RT and rebuild the RT to VNI mapping */
1259 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1261 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1262 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1264 /* Install routes that match new import RT */
1265 if (is_vni_live(vpn
))
1266 bgp_evpn_install_routes(bgp
, vpn
);
1270 * Unconfigure Import RT(s) for a VNI (vty handler).
1272 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1273 struct ecommunity
*ecomdel
)
1275 struct listnode
*node
, *nnode
, *node_to_del
;
1276 struct ecommunity
*ecom
;
1278 /* Along the lines of "configure" except we have to reset to the
1281 if (is_vni_live(vpn
))
1282 bgp_evpn_uninstall_routes(bgp
, vpn
);
1284 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1285 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1287 /* Delete all import RTs */
1288 if (ecomdel
== NULL
) {
1289 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1290 ecommunity_free(&ecom
);
1292 list_delete_all_node(vpn
->import_rtl
);
1295 /* Delete a specific import RT */
1299 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1300 if (ecommunity_match(ecom
, ecomdel
)) {
1301 ecommunity_free(&ecom
);
1308 list_delete_node(vpn
->import_rtl
, node_to_del
);
1311 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1312 if (list_isempty(vpn
->import_rtl
)) {
1313 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1314 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1316 /* Rebuild the RT to VNI mapping */
1318 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1320 /* Install routes that match new import RT */
1321 if (is_vni_live(vpn
))
1322 bgp_evpn_install_routes(bgp
, vpn
);
1326 * Configure the Export RT for a VNI (vty handler). Caller expected to
1327 * check that this is a change. Note that only a single export RT is
1328 * allowed for a VNI and any change to configuration is implemented as
1329 * a "replace" (similar to other configuration).
1331 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1332 struct ecommunity
*ecomadd
)
1334 /* If the auto route-target is in use we must remove it */
1335 evpn_export_rt_delete_auto(bgp
, vpn
);
1337 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1338 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1340 if (is_vni_live(vpn
))
1341 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1345 * Unconfigure the Export RT for a VNI (vty handler)
1347 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1348 struct ecommunity
*ecomdel
)
1350 struct listnode
*node
, *nnode
, *node_to_del
;
1351 struct ecommunity
*ecom
;
1353 /* Delete all export RTs */
1354 if (ecomdel
== NULL
) {
1355 /* Reset to default and process all routes. */
1356 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1357 ecommunity_free(&ecom
);
1359 list_delete_all_node(vpn
->export_rtl
);
1362 /* Delete a specific export RT */
1366 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1367 if (ecommunity_match(ecom
, ecomdel
)) {
1368 ecommunity_free(&ecom
);
1375 list_delete_node(vpn
->export_rtl
, node_to_del
);
1378 if (list_isempty(vpn
->export_rtl
)) {
1379 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1380 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1383 if (is_vni_live(vpn
))
1384 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1388 * Configure RD for a VNI (vty handler)
1390 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1391 struct prefix_rd
*rd
)
1393 /* If the VNI is "live", we need to delete and withdraw this VNI's
1394 * local routes with the prior RD first. Then, after updating RD,
1395 * need to re-advertise.
1397 if (is_vni_live(vpn
))
1398 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1401 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1402 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1404 if (is_vni_live(vpn
))
1405 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1409 * Unconfigure RD for a VNI (vty handler)
1411 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1413 /* If the VNI is "live", we need to delete and withdraw this VNI's
1414 * local routes with the prior RD first. Then, after resetting RD
1415 * to automatic value, need to re-advertise.
1417 if (is_vni_live(vpn
))
1418 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1420 /* reset RD to default */
1421 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1423 if (is_vni_live(vpn
))
1424 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1428 * Create VNI, if not already present (VTY handler). Mark as configured.
1430 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1432 struct bgpevpn
*vpn
;
1437 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1439 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
);
1442 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1448 /* Mark as configured. */
1449 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1454 * Delete VNI. If VNI does not exist in the system (i.e., just
1455 * configuration), all that is needed is to free it. Otherwise,
1456 * any parameters configured for the VNI need to be reset (with
1457 * appropriate action) and the VNI marked as unconfigured; the
1458 * VNI will continue to exist, purely as a "learnt" entity.
1460 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1462 assert(bgp
->vnihash
);
1464 if (!is_vni_live(vpn
)) {
1465 bgp_evpn_free(bgp
, vpn
);
1469 /* We need to take the unconfigure action for each parameter of this VNI
1470 * that is configured. Some optimization is possible, but not worth the
1471 * additional code for an operation that should be pretty rare.
1473 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1475 /* First, deal with the export side - RD and export RT changes. */
1476 if (is_rd_configured(vpn
))
1477 evpn_unconfigure_rd(bgp
, vpn
);
1478 if (is_export_rt_configured(vpn
))
1479 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1481 /* Next, deal with the import side. */
1482 if (is_import_rt_configured(vpn
))
1483 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1489 * Display import RT mapping to VNIs (vty handler)
1491 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1500 bgp
->import_rt_hash
,
1501 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1506 * Display EVPN routes for all VNIs - vty handler.
1508 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1509 struct in_addr vtep_ip
,
1513 struct vni_walk_ctx wctx
;
1515 num_vnis
= hashcount(bgp
->vnihash
);
1518 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1521 wctx
.vtep_ip
= vtep_ip
;
1523 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1524 void *))show_vni_routes_hash
,
1529 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1531 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1532 vni_t vni
, struct in_addr orig_ip
,
1535 struct bgpevpn
*vpn
;
1536 struct prefix_evpn p
;
1537 struct bgp_node
*rn
;
1538 struct bgp_info
*ri
;
1539 u_int32_t path_cnt
= 0;
1542 json_object
*json_paths
= NULL
;
1548 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1550 vty_out(vty
, "VNI not found\n");
1554 /* See if route exists. */
1555 build_evpn_type3_prefix(&p
, orig_ip
);
1556 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1557 if (!rn
|| !rn
->info
) {
1559 vty_out(vty
, "%% Network not in table\n");
1564 json_paths
= json_object_new_array();
1566 /* Prefix and num paths displayed once per prefix. */
1567 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1569 /* Display each path for this prefix. */
1570 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1571 json_object
*json_path
= NULL
;
1574 json_path
= json_object_new_array();
1576 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1580 json_object_array_add(json_paths
, json_path
);
1587 json_object_object_add(json
, "paths", json_paths
);
1589 json_object_int_add(json
, "numPaths", path_cnt
);
1591 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1597 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1598 * By definition, only matching type-2 route will be displayed.
1600 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1601 vni_t vni
, struct ethaddr
*mac
,
1602 struct ipaddr
*ip
, json_object
*json
)
1604 struct bgpevpn
*vpn
;
1605 struct prefix_evpn p
;
1606 struct bgp_node
*rn
;
1607 struct bgp_info
*ri
;
1608 u_int32_t path_cnt
= 0;
1611 json_object
*json_paths
= NULL
;
1617 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1620 vty_out(vty
, "VNI not found\n");
1624 /* See if route exists. Look for both non-sticky and sticky. */
1625 build_evpn_type2_prefix(&p
, mac
, ip
);
1626 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1627 if (!rn
|| !rn
->info
) {
1629 vty_out(vty
, "%% Network not in table\n");
1634 json_paths
= json_object_new_array();
1636 /* Prefix and num paths displayed once per prefix. */
1637 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1639 /* Display each path for this prefix. */
1640 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1641 json_object
*json_path
= NULL
;
1644 json_path
= json_object_new_array();
1646 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1650 json_object_array_add(json_paths
, json_path
);
1657 json_object_object_add(json
, "paths", json_paths
);
1659 json_object_int_add(json
, "numPaths", path_cnt
);
1661 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1667 * Display EVPN routes for a VNI - vty handler.
1668 * If 'type' is non-zero, only routes matching that type are shown.
1669 * If the vtep_ip is non zero, only routes behind that vtep are shown
1671 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1672 int type
, struct in_addr vtep_ip
,
1675 struct bgpevpn
*vpn
;
1678 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1681 vty_out(vty
, "VNI not found\n");
1685 /* Walk this VNI's route table and display appropriate routes. */
1686 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
1690 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1691 * IP (vty handler). By definition, only matching type-2 route will be
1694 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1695 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1696 struct ipaddr
*ip
, json_object
*json
)
1698 struct prefix_evpn p
;
1699 struct bgp_node
*rn
;
1700 struct bgp_info
*ri
;
1703 u_int32_t path_cnt
= 0;
1704 json_object
*json_paths
= NULL
;
1705 char prefix_str
[BUFSIZ
];
1710 /* See if route exists. Look for both non-sticky and sticky. */
1711 build_evpn_type2_prefix(&p
, mac
, ip
);
1712 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1713 (struct prefix
*)&p
, prd
);
1714 if (!rn
|| !rn
->info
) {
1716 vty_out(vty
, "%% Network not in table\n");
1720 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
1721 sizeof(prefix_str
));
1723 /* Prefix and num paths displayed once per prefix. */
1724 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
1727 json_paths
= json_object_new_array();
1729 /* Display each path for this prefix. */
1730 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1731 json_object
*json_path
= NULL
;
1734 json_path
= json_object_new_array();
1736 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1740 json_object_array_add(json_paths
, json_path
);
1745 if (json
&& path_cnt
) {
1747 json_object_object_add(json
, prefix_str
, json_paths
);
1748 json_object_int_add(json
, "numPaths", path_cnt
);
1750 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1756 * Display BGP EVPN routing table -- for specific RD (vty handler)
1757 * If 'type' is non-zero, only routes matching that type are shown.
1759 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
1760 struct prefix_rd
*prd
, int type
,
1763 struct bgp_node
*rd_rn
;
1764 struct bgp_table
*table
;
1765 struct bgp_node
*rn
;
1766 struct bgp_info
*ri
;
1770 u_int32_t prefix_cnt
, path_cnt
;
1771 char rd_str
[RD_ADDRSTRLEN
];
1772 json_object
*json_rd
= NULL
;
1773 int add_rd_to_json
= 0;
1777 prefix_cnt
= path_cnt
= 0;
1779 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
1781 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1785 table
= (struct bgp_table
*)rd_rn
->info
;
1790 json_rd
= json_object_new_object();
1791 json_object_string_add(json_rd
, "rd", rd_str
);
1794 /* Display all prefixes with this RD. */
1795 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1796 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1797 json_object
*json_prefix
= NULL
;
1798 json_object
*json_paths
= NULL
;
1799 char prefix_str
[BUFSIZ
];
1800 int add_prefix_to_json
= 0;
1802 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
1803 sizeof(prefix_str
));
1805 if (type
&& evp
->prefix
.route_type
!= type
)
1809 json_prefix
= json_object_new_object();
1812 /* RD header and legend - once overall. */
1813 if (rd_header
&& !json
) {
1815 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1818 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1823 /* Prefix and num paths displayed once per prefix. */
1824 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
1831 json_paths
= json_object_new_array();
1833 /* Display each path for this prefix. */
1834 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1835 json_object
*json_path
= NULL
;
1838 json_path
= json_object_new_array();
1840 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1844 json_object_array_add(json_paths
, json_path
);
1847 add_prefix_to_json
= 1;
1851 if (json
&& add_prefix_to_json
) {
1852 json_object_object_add(json_prefix
, "paths",
1854 json_object_object_add(json_rd
, prefix_str
,
1859 if (json
&& add_rd_to_json
)
1860 json_object_object_add(json
, rd_str
, json_rd
);
1863 json_object_int_add(json
, "numPrefix", prefix_cnt
);
1864 json_object_int_add(json
, "numPaths", path_cnt
);
1866 if (prefix_cnt
== 0)
1867 vty_out(vty
, "No prefixes exist with this RD%s\n",
1868 type
? " (of requested type)" : "");
1871 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
1872 prefix_cnt
, path_cnt
,
1873 type
? " (of requested type)" : "");
1878 * Display BGP EVPN routing table - all routes (vty handler).
1879 * If 'type' is non-zero, only routes matching that type are shown.
1881 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
1884 struct bgp_node
*rd_rn
;
1885 struct bgp_table
*table
;
1886 struct bgp_node
*rn
;
1887 struct bgp_info
*ri
;
1892 u_int32_t prefix_cnt
, path_cnt
;
1896 prefix_cnt
= path_cnt
= 0;
1898 /* EVPN routing table is a 2-level table with the first level being
1901 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1902 rd_rn
= bgp_route_next(rd_rn
)) {
1903 char rd_str
[RD_ADDRSTRLEN
];
1904 json_object
*json_rd
= NULL
; /* contains routes for an RD */
1905 int add_rd_to_json
= 0;
1907 table
= (struct bgp_table
*)rd_rn
->info
;
1911 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
1915 json_rd
= json_object_new_object();
1916 json_object_string_add(json_rd
, "rd", rd_str
);
1921 /* Display all prefixes for an RD */
1922 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1923 json_object
*json_prefix
=
1924 NULL
; /* contains prefix under a RD */
1925 json_object
*json_paths
=
1926 NULL
; /* array of paths under a prefix*/
1927 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1928 char prefix_str
[BUFSIZ
];
1929 int add_prefix_to_json
= 0;
1931 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
1932 prefix_str
, sizeof(prefix_str
));
1934 if (type
&& evp
->prefix
.route_type
!= type
)
1938 /* Overall header/legend displayed once. */
1940 bgp_evpn_show_route_header(vty
, bgp
,
1945 /* RD header - per RD. */
1947 bgp_evpn_show_route_rd_header(
1956 json_prefix
= json_object_new_object();
1957 json_paths
= json_object_new_array();
1958 json_object_string_add(json_prefix
, "prefix",
1960 json_object_int_add(json_prefix
, "prefixLen",
1964 /* For EVPN, the prefix is displayed for each path (to
1966 * with code that already exists).
1968 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1969 json_object
*json_path
= NULL
;
1971 add_prefix_to_json
= 1;
1975 json_path
= json_object_new_array();
1977 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
1981 json_object_array_add(json_paths
,
1985 if (json
&& add_prefix_to_json
) {
1986 json_object_object_add(json_prefix
, "paths",
1988 json_object_object_add(json_rd
, prefix_str
,
1993 if (json
&& add_rd_to_json
)
1994 json_object_object_add(json
, rd_str
, json_rd
);
1998 json_object_int_add(json
, "numPrefix", prefix_cnt
);
1999 json_object_int_add(json
, "numPaths", path_cnt
);
2001 if (prefix_cnt
== 0) {
2002 vty_out(vty
, "No EVPN prefixes %sexist\n",
2003 type
? "(of requested type) " : "");
2005 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2006 prefix_cnt
, path_cnt
,
2007 type
? " (of requested type)" : "");
2013 * Display specified VNI (vty handler)
2015 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2018 struct bgpevpn
*vpn
;
2020 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2023 vty_out(vty
, "{}\n");
2025 vty_out(vty
, "VNI not found\n");
2030 display_vni(vty
, vpn
, json
);
2034 * Display a VNI (upon user query).
2036 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2042 num_vnis
= hashcount(bgp
->vnihash
);
2047 json_object_int_add(json
, "numVnis", num_vnis
);
2049 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
2050 vty_out(vty
, "Flags: * - Kernel\n");
2051 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s\n", "VNI",
2052 "Orig IP", "RD", "Import RT", "Export RT");
2057 hash_iterate(bgp
->vnihash
,
2058 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2063 * evpn - enable advertisement of default g/w
2065 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2068 if (bgp
->advertise_gw_macip
)
2071 bgp
->advertise_gw_macip
= 1;
2072 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2074 if (vpn
->advertise_gw_macip
)
2077 vpn
->advertise_gw_macip
= 1;
2078 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2085 * evpn - disable advertisement of default g/w
2087 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2088 struct bgpevpn
*vpn
)
2091 if (!bgp
->advertise_gw_macip
)
2094 bgp
->advertise_gw_macip
= 0;
2095 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2097 if (!vpn
->advertise_gw_macip
)
2100 vpn
->advertise_gw_macip
= 0;
2101 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2108 * EVPN (VNI advertisement) enabled. Register with zebra.
2110 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2112 bgp
->advertise_all_vni
= 1;
2113 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2117 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2118 * cache, EVPN routes (delete and withdraw from peers).
2120 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2122 bgp
->advertise_all_vni
= 0;
2123 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2124 bgp_evpn_cleanup_on_disable(bgp
);
2126 #endif /* HAVE_CUMULUS */
2128 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
, int *write
)
2130 char buf1
[INET6_ADDRSTRLEN
];
2131 afi_t afi
= AFI_L2VPN
;
2132 safi_t safi
= SAFI_EVPN
;
2134 struct listnode
*node
, *nnode
;
2135 struct ecommunity
*ecom
;
2137 if (is_vni_configured(vpn
)) {
2138 bgp_config_write_family_header(vty
, afi
, safi
, write
);
2139 vty_out(vty
, " vni %d\n", vpn
->vni
);
2140 if (is_rd_configured(vpn
))
2141 vty_out(vty
, " rd %s\n",
2142 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
2144 if (is_import_rt_configured(vpn
)) {
2145 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2147 ecom_str
= ecommunity_ecom2str(
2148 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2149 vty_out(vty
, " route-target import %s\n",
2151 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2155 if (is_export_rt_configured(vpn
)) {
2156 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2158 ecom_str
= ecommunity_ecom2str(
2159 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2160 vty_out(vty
, " route-target export %s\n",
2162 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2166 if (vpn
->advertise_gw_macip
)
2167 vty_out(vty
, " advertise-default-gw\n");
2169 vty_out(vty
, " exit-vni\n");
2173 static void write_vni_config_for_entry(struct hash_backet
*backet
,
2174 struct evpn_config_write
*cfg
)
2176 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2177 write_vni_config(cfg
->vty
, vpn
, &cfg
->write
);
2180 #if defined(HAVE_CUMULUS)
2181 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2182 bgp_evpn_advertise_default_gw_vni_cmd
,
2183 "advertise-default-gw",
2184 "Advertise defualt g/w mac-ip routes in EVPN for a VNI\n")
2186 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2187 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2195 evpn_set_advertise_default_gw(bgp
, vpn
);
2200 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2201 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2202 "no advertise-default-gw",
2204 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2206 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2207 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2215 evpn_unset_advertise_default_gw(bgp
, vpn
);
2221 DEFUN (bgp_evpn_advertise_default_gw
,
2222 bgp_evpn_advertise_default_gw_cmd
,
2223 "advertise-default-gw",
2224 "Advertise All defualt g/w mac-ip routes in EVPN\n")
2226 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2231 evpn_set_advertise_default_gw(bgp
, NULL
);
2236 DEFUN (no_bgp_evpn_advertise_default_gw
,
2237 no_bgp_evpn_advertise_default_gw_cmd
,
2238 "no advertise-default-gw",
2240 "Withdraw All default g/w mac-ip routes from EVPN\n")
2242 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2247 evpn_unset_advertise_default_gw(bgp
, NULL
);
2252 DEFUN (bgp_evpn_advertise_all_vni
,
2253 bgp_evpn_advertise_all_vni_cmd
,
2254 "advertise-all-vni",
2255 "Advertise All local VNIs\n")
2257 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2261 evpn_set_advertise_all_vni(bgp
);
2265 DEFUN (no_bgp_evpn_advertise_all_vni
,
2266 no_bgp_evpn_advertise_all_vni_cmd
,
2267 "no advertise-all-vni",
2269 "Advertise All local VNIs\n")
2271 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2275 evpn_unset_advertise_all_vni(bgp
);
2280 * Display VNI information - for all or a specific VNI
2282 DEFUN(show_bgp_l2vpn_evpn_vni
,
2283 show_bgp_l2vpn_evpn_vni_cmd
,
2284 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2297 json_object
*json
= NULL
;
2299 uj
= use_json(argc
, argv
);
2301 bgp
= bgp_get_default();
2305 if (!argv_find(argv
, argc
, "evpn", &idx
))
2309 json
= json_object_new_object();
2311 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
2313 json_object_string_add(json
, "advertiseGatewayMacip",
2314 bgp
->advertise_gw_macip
2317 json_object_string_add(json
, "advertiseAllVnis",
2318 bgp
->advertise_all_vni
2322 vty_out(vty
, "Advertise Gateway Macip: %s\n",
2323 bgp
->advertise_gw_macip
? "Enabled"
2326 /* Display all VNIs */
2327 vty_out(vty
, "Advertise All VNI flag: %s\n",
2328 bgp
->advertise_all_vni
? "Enabled"
2332 evpn_show_all_vnis(vty
, bgp
, json
);
2336 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
2339 /* Display specific VNI */
2340 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
2341 evpn_show_vni(vty
, bgp
, vni
, json
);
2345 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2346 json
, JSON_C_TO_STRING_PRETTY
));
2347 json_object_free(json
);
2354 * Display EVPN neighbor summary.
2356 DEFUN(show_bgp_l2vpn_evpn_summary
,
2357 show_bgp_l2vpn_evpn_summary_cmd
,
2358 "show bgp l2vpn evpn summary [json]",
2363 "Summary of BGP neighbor status\n"
2366 u_char uj
= use_json(argc
, argv
);
2367 return bgp_show_summary_vty(vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
2371 * Display global EVPN routing table.
2373 DEFUN(show_bgp_l2vpn_evpn_route
, show_bgp_l2vpn_evpn_route_cmd
,
2374 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2379 "EVPN route information\n"
2380 "Specify Route type\n"
2381 "MAC-IP (Type-2) route\n"
2382 "Multicast (Type-3) route\n"
2389 json_object
*json
= NULL
;
2391 uj
= use_json(argc
, argv
);
2393 bgp
= bgp_get_default();
2398 json
= json_object_new_object();
2401 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2402 /* Specific type is requested */
2403 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2404 type
= BGP_EVPN_MAC_IP_ROUTE
;
2405 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2406 type
= BGP_EVPN_IMET_ROUTE
;
2411 evpn_show_all_routes(vty
, bgp
, type
, json
);
2414 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2415 json
, JSON_C_TO_STRING_PRETTY
));
2416 json_object_free(json
);
2423 * Display global EVPN routing table for specific RD.
2425 DEFUN(show_bgp_l2vpn_evpn_route_rd
, show_bgp_l2vpn_evpn_route_rd_cmd
,
2426 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>] [json]",
2431 "EVPN route information\n"
2432 "Route Distinguisher\n"
2433 "ASN:XX or A.B.C.D:XX\n"
2434 "Specify Route type\n"
2435 "MAC-IP (Type-2) route\n"
2436 "Multicast (Type-3) route\n"
2441 struct prefix_rd prd
;
2446 json_object
*json
= NULL
;
2448 bgp
= bgp_get_default();
2452 /* check if we need json output */
2453 uj
= use_json(argc
, argv
);
2455 json
= json_object_new_object();
2458 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2459 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2462 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2468 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2469 /* Specific type is requested */
2470 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2471 type
= BGP_EVPN_MAC_IP_ROUTE
;
2472 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2473 type
= BGP_EVPN_IMET_ROUTE
;
2478 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
2481 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2482 json
, JSON_C_TO_STRING_PRETTY
));
2483 json_object_free(json
);
2490 * Display global EVPN routing table for specific RD and MACIP.
2492 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
2493 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
2494 "show bgp l2vpn evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD] [json]",
2499 "EVPN route information\n"
2500 "Route Distinguisher\n"
2501 "ASN:XX or A.B.C.D:XX\n"
2503 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2505 "IP address (IPv4 or IPv6)\n"
2510 struct prefix_rd prd
;
2517 json_object
*json
= NULL
;
2519 memset(&mac
, 0, sizeof(struct ethaddr
));
2520 memset(&ip
, 0, sizeof(struct ipaddr
));
2522 bgp
= bgp_get_default();
2526 /* check if we need json output */
2527 uj
= use_json(argc
, argv
);
2529 json
= json_object_new_object();
2532 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2533 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2535 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2541 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
2542 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
2543 vty_out(vty
, "%% Malformed MAC address\n");
2548 /* get the ip if specified */
2549 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
2550 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
2551 vty_out(vty
, "%% Malformed IP address\n");
2556 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
2559 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2560 json
, JSON_C_TO_STRING_PRETTY
));
2561 json_object_free(json
);
2568 * Display per-VNI EVPN routing table.
2570 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
2571 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2576 "EVPN route information\n"
2577 "VXLAN Network Identifier\n"
2579 "Specify Route type\n"
2580 "MAC-IP (Type-2) route\n"
2581 "Multicast (Type-3) route\n"
2583 "Remote VTEP IP address\n"
2588 struct in_addr vtep_ip
;
2592 json_object
*json
= NULL
;
2594 bgp
= bgp_get_default();
2598 /* check if we need json output */
2599 uj
= use_json(argc
, argv
);
2601 json
= json_object_new_object();
2603 if (!argv_find(argv
, argc
, "evpn", &idx
))
2608 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2610 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
2611 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
2612 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
2613 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
2614 type
= BGP_EVPN_MAC_IP_ROUTE
;
2615 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
2616 type
= BGP_EVPN_IMET_ROUTE
;
2619 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
2620 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
2621 vty_out(vty
, "%% Malformed VTEP IP address\n");
2628 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
2631 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2632 json
, JSON_C_TO_STRING_PRETTY
));
2633 json_object_free(json
);
2640 * Display per-VNI EVPN routing table for specific MACIP.
2642 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
2643 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
2644 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2649 "EVPN route information\n"
2650 "VXLAN Network Identifier\n"
2653 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2655 "IP address (IPv4 or IPv6)\n"
2664 json_object
*json
= NULL
;
2666 bgp
= bgp_get_default();
2670 /* check if we need json output */
2671 uj
= use_json(argc
, argv
);
2673 json
= json_object_new_object();
2675 if (!argv_find(argv
, argc
, "evpn", &idx
))
2679 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2682 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
2683 vty_out(vty
, "%% Malformed MAC address\n");
2688 memset(&ip
, 0, sizeof(ip
));
2689 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
2691 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
2692 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
2693 vty_out(vty
, "%% Malformed IP address\n");
2698 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
2701 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2702 json
, JSON_C_TO_STRING_PRETTY
));
2703 json_object_free(json
);
2710 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
2712 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
2713 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
2714 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
2719 "EVPN route information\n"
2720 "VXLAN Network Identifier\n"
2722 "Multicast (Type-3) route\n"
2723 "Originating Router IP address\n"
2729 struct in_addr orig_ip
;
2732 json_object
*json
= NULL
;
2734 bgp
= bgp_get_default();
2738 /* check if we need json output */
2739 uj
= use_json(argc
, argv
);
2741 json
= json_object_new_object();
2743 if (!argv_find(argv
, argc
, "evpn", &idx
))
2747 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2750 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
2752 vty_out(vty
, "%% Malformed Originating Router IP address\n");
2756 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
2759 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2760 json
, JSON_C_TO_STRING_PRETTY
));
2761 json_object_free(json
);
2768 * Display per-VNI EVPN routing table - for all VNIs.
2770 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_l2vpn_evpn_route_vni_all_cmd
,
2771 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
2776 "EVPN route information\n"
2777 "VXLAN Network Identifier\n"
2780 "Remote VTEP IP address\n"
2784 struct in_addr vtep_ip
;
2787 json_object
*json
= NULL
;
2789 bgp
= bgp_get_default();
2793 /* check if we need json output */
2794 uj
= use_json(argc
, argv
);
2796 json
= json_object_new_object();
2798 if (!argv_find(argv
, argc
, "evpn", &idx
))
2802 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
2803 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
2804 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
2805 vty_out(vty
, "%% Malformed VTEP IP address\n");
2810 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
2813 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2814 json
, JSON_C_TO_STRING_PRETTY
));
2815 json_object_free(json
);
2822 * Display EVPN import route-target hash table
2824 DEFUN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_l2vpn_evpn_import_rt_cmd
,
2825 "show bgp l2vpn evpn import-rt [json]",
2830 "Show import route target\n"
2835 json_object
*json
= NULL
;
2837 bgp
= bgp_get_default();
2841 uj
= use_json(argc
, argv
);
2843 json
= json_object_new_object();
2845 evpn_show_import_rts(vty
, bgp
, json
);
2848 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2849 json
, JSON_C_TO_STRING_PRETTY
));
2850 json_object_free(json
);
2856 #if defined(HAVE_CUMULUS)
2857 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
2858 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
2862 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
2863 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
2864 "Summary of BGP neighbor status\n"
2867 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
2868 "show bgp evpn route [type <macip|multicast>]",
2869 SHOW_STR BGP_STR EVPN_HELP_STR
2870 "EVPN route information\n"
2871 "Specify Route type\n"
2872 "MAC-IP (Type-2) route\n"
2873 "Multicast (Type-3) route\n")
2876 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
2877 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
2878 SHOW_STR BGP_STR EVPN_HELP_STR
2879 "EVPN route information\n"
2880 "Route Distinguisher\n"
2881 "ASN:XX or A.B.C.D:XX\n"
2882 "Specify Route type\n"
2883 "MAC-IP (Type-2) route\n"
2884 "Multicast (Type-3) route\n")
2887 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
2888 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
2889 SHOW_STR BGP_STR EVPN_HELP_STR
2890 "EVPN route information\n"
2891 "Route Distinguisher\n"
2892 "ASN:XX or A.B.C.D:XX\n"
2894 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2896 "IP address (IPv4 or IPv6)\n")
2899 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
2900 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
2901 SHOW_STR BGP_STR EVPN_HELP_STR
2902 "EVPN route information\n"
2903 "VXLAN Network Identifier\n"
2905 "Specify Route type\n"
2906 "MAC-IP (Type-2) route\n"
2907 "Multicast (Type-3) route\n"
2909 "Remote VTEP IP address\n")
2911 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
2912 show_bgp_evpn_route_vni_macip_cmd
,
2913 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
2914 SHOW_STR BGP_STR EVPN_HELP_STR
2915 "EVPN route information\n"
2916 "VXLAN Network Identifier\n"
2919 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2921 "IP address (IPv4 or IPv6)\n")
2923 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
2924 show_bgp_evpn_route_vni_multicast_cmd
,
2925 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2926 SHOW_STR BGP_STR EVPN_HELP_STR
2927 "EVPN route information\n"
2928 "VXLAN Network Identifier\n"
2930 "Multicast (Type-3) route\n"
2931 "Originating Router IP address\n")
2933 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
2934 "show bgp evpn route vni all [vtep A.B.C.D]",
2935 SHOW_STR BGP_STR EVPN_HELP_STR
2936 "EVPN route information\n"
2937 "VXLAN Network Identifier\n"
2940 "Remote VTEP IP address\n")
2942 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
2943 "show bgp evpn import-rt",
2944 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
2947 DEFUN_NOSH (bgp_evpn_vni
,
2950 "VXLAN Network Identifier\n"
2954 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2955 struct bgpevpn
*vpn
;
2960 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2962 /* Create VNI, or mark as configured. */
2963 vpn
= evpn_create_update_vni(bgp
, vni
);
2965 vty_out(vty
, "%% Failed to create VNI \n");
2969 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
2973 DEFUN (no_bgp_evpn_vni
,
2974 no_bgp_evpn_vni_cmd
,
2975 "no vni (1-16777215)",
2977 "VXLAN Network Identifier\n"
2981 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2982 struct bgpevpn
*vpn
;
2987 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2989 /* Check if we should disallow. */
2990 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2992 vty_out(vty
, "%% Specified VNI does not exist\n");
2995 if (!is_vni_configured(vpn
)) {
2996 vty_out(vty
, "%% Specified VNI is not configured\n");
3000 evpn_delete_vni(bgp
, vpn
);
3004 DEFUN_NOSH (exit_vni
,
3007 "Exit from VNI mode\n")
3009 if (vty
->node
== BGP_EVPN_VNI_NODE
)
3010 vty
->node
= BGP_EVPN_NODE
;
3014 DEFUN (bgp_evpn_vni_rd
,
3015 bgp_evpn_vni_rd_cmd
,
3016 "rd ASN:nn_or_IP-address:nn",
3017 "Route Distinguisher\n"
3018 "ASN:XX or A.B.C.D:XX\n")
3020 struct prefix_rd prd
;
3021 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3022 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3028 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3030 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3034 /* If same as existing value, there is nothing more to do. */
3035 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
3038 /* Configure or update the RD. */
3039 evpn_configure_rd(bgp
, vpn
, &prd
);
3043 DEFUN (no_bgp_evpn_vni_rd
,
3044 no_bgp_evpn_vni_rd_cmd
,
3045 "no rd ASN:nn_or_IP-address:nn",
3047 "Route Distinguisher\n"
3048 "ASN:XX or A.B.C.D:XX\n")
3050 struct prefix_rd prd
;
3051 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3052 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3058 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3060 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3064 /* Check if we should disallow. */
3065 if (!is_rd_configured(vpn
)) {
3066 vty_out(vty
, "%% RD is not configured for this VNI\n");
3070 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
3072 "%% RD specified does not match configuration for this VNI\n");
3076 evpn_unconfigure_rd(bgp
, vpn
);
3080 DEFUN (no_bgp_evpn_vni_rd_without_val
,
3081 no_bgp_evpn_vni_rd_without_val_cmd
,
3084 "Route Distinguisher\n")
3086 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3087 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3092 /* Check if we should disallow. */
3093 if (!is_rd_configured(vpn
)) {
3094 vty_out(vty
, "%% RD is not configured for this VNI\n");
3098 evpn_unconfigure_rd(bgp
, vpn
);
3103 * Loop over all extended-communities in the route-target list rtl and
3104 * return 1 if we find ecomtarget
3106 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
3107 struct ecommunity
*ecomtarget
)
3109 struct listnode
*node
, *nnode
;
3110 struct ecommunity
*ecom
;
3112 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
3113 if (ecommunity_match(ecom
, ecomtarget
))
3121 DEFUN (bgp_evpn_vni_rt
,
3122 bgp_evpn_vni_rt_cmd
,
3123 "route-target <both|import|export> RT",
3125 "import and export\n"
3128 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3130 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3131 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3133 struct ecommunity
*ecomadd
= NULL
;
3138 if (!strcmp(argv
[1]->arg
, "import"))
3139 rt_type
= RT_TYPE_IMPORT
;
3140 else if (!strcmp(argv
[1]->arg
, "export"))
3141 rt_type
= RT_TYPE_EXPORT
;
3142 else if (!strcmp(argv
[1]->arg
, "both"))
3143 rt_type
= RT_TYPE_BOTH
;
3145 vty_out(vty
, "%% Invalid Route Target type\n");
3149 /* Add/update the import route-target */
3150 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
3151 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3152 ECOMMUNITY_ROUTE_TARGET
, 0);
3154 vty_out(vty
, "%% Malformed Route Target list\n");
3157 ecommunity_str(ecomadd
);
3159 /* Do nothing if we already have this import route-target */
3160 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
3161 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
3164 /* Add/update the export route-target */
3165 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
3166 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3167 ECOMMUNITY_ROUTE_TARGET
, 0);
3169 vty_out(vty
, "%% Malformed Route Target list\n");
3172 ecommunity_str(ecomadd
);
3174 /* Do nothing if we already have this export route-target */
3175 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
3176 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
3182 DEFUN (no_bgp_evpn_vni_rt
,
3183 no_bgp_evpn_vni_rt_cmd
,
3184 "no route-target <both|import|export> RT",
3187 "import and export\n"
3190 "ASN:XX or A.B.C.D:XX\n")
3192 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3193 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3194 int rt_type
, found_ecomdel
;
3195 struct ecommunity
*ecomdel
= NULL
;
3200 if (!strcmp(argv
[2]->arg
, "import"))
3201 rt_type
= RT_TYPE_IMPORT
;
3202 else if (!strcmp(argv
[2]->arg
, "export"))
3203 rt_type
= RT_TYPE_EXPORT
;
3204 else if (!strcmp(argv
[2]->arg
, "both"))
3205 rt_type
= RT_TYPE_BOTH
;
3207 vty_out(vty
, "%% Invalid Route Target type\n");
3211 /* The user did "no route-target import", check to see if there are any
3212 * import route-targets configured. */
3213 if (rt_type
== RT_TYPE_IMPORT
) {
3214 if (!is_import_rt_configured(vpn
)) {
3216 "%% Import RT is not configured for this VNI\n");
3219 } else if (rt_type
== RT_TYPE_EXPORT
) {
3220 if (!is_export_rt_configured(vpn
)) {
3222 "%% Export RT is not configured for this VNI\n");
3225 } else if (rt_type
== RT_TYPE_BOTH
) {
3226 if (!is_import_rt_configured(vpn
)
3227 && !is_export_rt_configured(vpn
)) {
3229 "%% Import/Export RT is not configured for this VNI\n");
3234 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
3236 vty_out(vty
, "%% Malformed Route Target list\n");
3239 ecommunity_str(ecomdel
);
3241 if (rt_type
== RT_TYPE_IMPORT
) {
3242 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3244 "%% RT specified does not match configuration for this VNI\n");
3247 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3248 } else if (rt_type
== RT_TYPE_EXPORT
) {
3249 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3251 "%% RT specified does not match configuration for this VNI\n");
3254 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3255 } else if (rt_type
== RT_TYPE_BOTH
) {
3258 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3259 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3263 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3264 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3268 if (!found_ecomdel
) {
3270 "%% RT specified does not match configuration for this VNI\n");
3278 DEFUN (no_bgp_evpn_vni_rt_without_val
,
3279 no_bgp_evpn_vni_rt_without_val_cmd
,
3280 "no route-target <import|export>",
3286 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3287 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3293 if (!strcmp(argv
[2]->arg
, "import")) {
3294 rt_type
= RT_TYPE_IMPORT
;
3295 } else if (!strcmp(argv
[2]->arg
, "export")) {
3296 rt_type
= RT_TYPE_EXPORT
;
3298 vty_out(vty
, "%% Invalid Route Target type\n");
3302 /* Check if we should disallow. */
3303 if (rt_type
== RT_TYPE_IMPORT
) {
3304 if (!is_import_rt_configured(vpn
)) {
3306 "%% Import RT is not configured for this VNI\n");
3310 if (!is_export_rt_configured(vpn
)) {
3312 "%% Export RT is not configured for this VNI\n");
3317 /* Unconfigure the RT. */
3318 if (rt_type
== RT_TYPE_IMPORT
)
3319 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
3321 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
3326 * Output EVPN configuration information.
3328 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
3329 safi_t safi
, int *write
)
3331 struct evpn_config_write cfg
;
3336 hash_iterate(bgp
->vnihash
,
3337 (void (*)(struct hash_backet
*,
3338 void *))write_vni_config_for_entry
,
3343 if (bgp
->advertise_all_vni
) {
3344 bgp_config_write_family_header(vty
, afi
, safi
, write
);
3345 vty_out(vty
, " advertise-all-vni\n");
3348 if (bgp
->advertise_gw_macip
) {
3349 bgp_config_write_family_header(vty
, afi
, safi
, write
);
3350 vty_out(vty
, " advertise-default-gw\n");
3354 void bgp_ethernetvpn_init(void)
3356 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
3357 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
3358 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
3359 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
3360 install_element(VIEW_NODE
,
3361 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
3362 install_element(VIEW_NODE
,
3363 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
3366 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
3369 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
3370 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
3371 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
3372 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
3373 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
3374 #if defined(HAVE_CUMULUS)
3375 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
3376 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
3377 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
3378 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
3380 /* "show bgp l2vpn evpn" commands. */
3381 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
3382 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
3383 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
3384 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
3385 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
3386 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
3387 install_element(VIEW_NODE
,
3388 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
3389 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
3390 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
3391 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
3393 /* "show bgp evpn" commands. */
3394 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
3395 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
3396 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
3397 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
3398 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
3399 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
3400 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
3401 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
3402 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
3403 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
3405 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
3406 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
3407 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
3408 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
3409 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
3410 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
3411 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
3412 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
3413 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
3414 install_element(BGP_EVPN_VNI_NODE
,
3415 &bgp_evpn_advertise_default_gw_vni_cmd
);
3416 install_element(BGP_EVPN_VNI_NODE
,
3417 &no_bgp_evpn_advertise_default_gw_vni_cmd
);