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
43 * Context for VNI hash walk - used by callbacks.
48 struct in_addr vtep_ip
;
51 struct evpn_config_write
{
56 #if defined(HAVE_CUMULUS)
57 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
)
60 u_char type
, sub_type
;
61 struct ecommunity_as
{
65 struct ecommunity_ip
{
69 struct listnode
*node
, *nnode
;
70 struct bgpevpn
*tmp_vpn
;
73 /* TODO: This needs to go into a function */
75 pnt
= (u_char
*)&irt
->rt
.val
;
78 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
82 case ECOMMUNITY_ENCODE_AS
:
83 eas
.as
= (*pnt
++ << 8);
86 eas
.val
= (*pnt
++ << 24);
87 eas
.val
|= (*pnt
++ << 16);
88 eas
.val
|= (*pnt
++ << 8);
91 vty_out(vty
, "Route-target: %u:%u", eas
.as
, eas
.val
);
94 case ECOMMUNITY_ENCODE_IP
:
95 memcpy(&eip
.ip
, pnt
, 4);
97 eip
.val
= (*pnt
++ << 8);
100 vty_out(vty
, "Route-target: %s:%u", inet_ntoa(eip
.ip
), eip
.val
);
103 case ECOMMUNITY_ENCODE_AS4
:
104 eas
.as
= (*pnt
++ << 24);
105 eas
.as
|= (*pnt
++ << 16);
106 eas
.as
|= (*pnt
++ << 8);
109 eas
.val
= (*pnt
++ << 8);
112 vty_out(vty
, "Route-target: %u:%u", eas
.as
, eas
.val
);
120 vty_out(vty
, "List of VNIs importing routes with this route-target:\n");
122 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
))
123 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
126 static void show_import_rt_entry(struct hash_backet
*backet
, struct vty
*vty
)
128 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
129 display_import_rt(vty
, irt
);
132 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
133 struct bgp_node
*rd_rn
)
140 pnt
= rd_rn
->p
.u
.val
;
142 /* Decode RD type. */
143 type
= decode_rd_type(pnt
);
145 vty_out(vty
, "Route Distinguisher: ");
149 decode_rd_as(pnt
+ 2, &rd_as
);
150 vty_out(vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
154 decode_rd_ip(pnt
+ 2, &rd_ip
);
155 vty_out(vty
, "%s:%d", inet_ntoa(rd_ip
.ip
), rd_ip
.val
);
159 vty_out(vty
, "Unknown RD type");
166 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
)
169 " Network Next Hop Metric LocPrf Weight Path\n";
171 vty_out(vty
, "BGP table version is 0, local router ID is %s\n",
172 inet_ntoa(bgp
->router_id
));
174 "Status codes: s suppressed, d damped, h history, "
175 "* valid, > best, i - internal\n");
176 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
178 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
179 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
180 vty_out(vty
, "%s", ri_header
);
183 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
)
185 char buf1
[INET6_ADDRSTRLEN
];
187 struct listnode
*node
, *nnode
;
188 struct ecommunity
*ecom
;
190 vty_out(vty
, "VNI: %d", vpn
->vni
);
191 if (is_vni_live(vpn
))
192 vty_out(vty
, " (known to the kernel)");
195 vty_out(vty
, " RD: %s\n",
196 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
197 vty_out(vty
, " Originator IP: %s\n", inet_ntoa(vpn
->originator_ip
));
199 vty_out(vty
, " Import Route Target:\n");
200 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
201 ecom_str
= ecommunity_ecom2str(ecom
,
202 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
203 vty_out(vty
, " %s\n", ecom_str
);
204 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
207 vty_out(vty
, " Export Route Target:\n");
208 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
209 ecom_str
= ecommunity_ecom2str(ecom
,
210 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
211 vty_out(vty
, " %s\n", ecom_str
);
212 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
216 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
217 struct vty
*vty
, struct in_addr vtep_ip
)
222 u_int32_t prefix_cnt
, path_cnt
;
224 prefix_cnt
= path_cnt
= 0;
226 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
227 rn
= bgp_route_next(rn
)) {
228 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
230 if (type
&& evp
->prefix
.route_type
!= type
)
234 /* Overall header/legend displayed once. */
236 bgp_evpn_show_route_header(vty
, bgp
);
243 /* For EVPN, the prefix is displayed for each path (to fit in
244 * with code that already exists).
246 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
248 && !IPV4_ADDR_SAME(&(vtep_ip
),
249 &(ri
->attr
->nexthop
)))
253 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, NULL
);
258 vty_out(vty
, "No EVPN prefixes %sexist for this VNI\n",
259 type
? "(of requested type) " : "");
261 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
262 prefix_cnt
, path_cnt
,
263 type
? " (of requested type)" : "");
266 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
268 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
269 struct vni_walk_ctx
*wctx
= arg
;
270 struct vty
*vty
= wctx
->vty
;
272 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
273 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
);
276 static void show_vni_entry(struct hash_backet
*backet
, struct vty
*vty
)
278 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
280 char buf2
[INET6_ADDRSTRLEN
];
283 struct listnode
*node
, *nnode
;
284 struct ecommunity
*ecom
;
287 if (is_vni_live(vpn
))
290 vty_out(vty
, "%-1s %-10u %-15s %-21s", buf1
, vpn
->vni
,
291 inet_ntoa(vpn
->originator_ip
),
292 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
294 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
295 ecom_str
= ecommunity_ecom2str(ecom
,
296 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
298 if (listcount(vpn
->import_rtl
) > 1)
299 sprintf(rt_buf
, "%s, ...", ecom_str
);
301 sprintf(rt_buf
, "%s", ecom_str
);
302 vty_out(vty
, " %-25s", rt_buf
);
304 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
308 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
309 ecom_str
= ecommunity_ecom2str(ecom
,
310 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
312 if (listcount(vpn
->export_rtl
) > 1)
313 sprintf(rt_buf
, "%s, ...", ecom_str
);
315 sprintf(rt_buf
, "%s", ecom_str
);
316 vty_out(vty
, " %-25s", rt_buf
);
318 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
323 #endif /* HAVE_CUMULUS */
325 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
326 enum bgp_show_type type
, void *output_arg
,
327 int option
, u_char use_json
)
329 afi_t afi
= AFI_L2VPN
;
331 struct bgp_table
*table
;
338 unsigned long output_count
= 0;
339 unsigned long total_count
= 0;
340 json_object
*json
= NULL
;
341 json_object
*json_nroute
= NULL
;
342 json_object
*json_array
= NULL
;
343 json_object
*json_scode
= NULL
;
344 json_object
*json_ocode
= NULL
;
346 bgp
= bgp_get_default();
349 vty_out(vty
, "No BGP process is configured\n");
354 json_scode
= json_object_new_object();
355 json_ocode
= json_object_new_object();
356 json
= json_object_new_object();
357 json_nroute
= json_object_new_object();
359 json_object_string_add(json_scode
, "suppressed", "s");
360 json_object_string_add(json_scode
, "damped", "d");
361 json_object_string_add(json_scode
, "history", "h");
362 json_object_string_add(json_scode
, "valid", "*");
363 json_object_string_add(json_scode
, "best", ">");
364 json_object_string_add(json_scode
, "internal", "i");
366 json_object_string_add(json_ocode
, "igp", "i");
367 json_object_string_add(json_ocode
, "egp", "e");
368 json_object_string_add(json_ocode
, "incomplete", "?");
371 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
372 rn
= bgp_route_next(rn
)) {
374 continue; /* XXX json TODO */
376 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
379 if ((table
= rn
->info
) != NULL
) {
382 for (rm
= bgp_table_top(table
); rm
;
383 rm
= bgp_route_next(rm
))
384 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
386 if (type
== bgp_show_type_neighbor
) {
387 union sockunion
*su
=
390 if (ri
->peer
->su_remote
== NULL
399 == SHOW_DISPLAY_TAGS
) {
404 json_object_string_add(
409 json_object_object_add(
413 json_object_object_add(
420 == SHOW_DISPLAY_TAGS
)
425 == SHOW_DISPLAY_OVERLAY
)
430 "BGP table version is 0, local router ID is %s\n",
434 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
436 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
451 /* Decode RD type. */
452 type
= decode_rd_type(pnt
);
453 /* Decode RD value. */
454 if (type
== RD_TYPE_AS
)
455 decode_rd_as(pnt
+ 2,
457 else if (type
== RD_TYPE_AS4
)
458 decode_rd_as4(pnt
+ 2,
460 else if (type
== RD_TYPE_IP
)
461 decode_rd_ip(pnt
+ 2,
465 if (type
== RD_TYPE_AS
466 || type
== RD_TYPE_AS4
)
478 json_object_string_add(
480 "routeDistinguisher",
484 "Route Distinguisher: ");
485 if (type
== RD_TYPE_AS
)
503 vty_out(vty
, "\n\n");
509 json_object_new_array();
512 if (option
== SHOW_DISPLAY_TAGS
)
515 SAFI_EVPN
, json_array
);
516 else if (option
== SHOW_DISPLAY_OVERLAY
)
517 route_vty_out_overlay(
521 route_vty_out(vty
, &rm
->p
, ri
,
529 if (output_count
== 0)
530 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
532 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
533 output_count
, total_count
);
537 DEFUN(show_ip_bgp_l2vpn_evpn
,
538 show_ip_bgp_l2vpn_evpn_cmd
,
539 "show [ip] bgp l2vpn evpn [json]",
540 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
542 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
543 use_json(argc
, argv
));
546 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
547 show_ip_bgp_l2vpn_evpn_rd_cmd
,
548 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
554 "Display information for a route distinguisher\n"
555 "VPN Route Distinguisher\n" JSON_STR
)
557 int idx_ext_community
= 0;
559 struct prefix_rd prd
;
561 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
563 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
565 vty_out(vty
, "%% Malformed Route Distinguisher\n");
568 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
569 use_json(argc
, argv
));
572 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
573 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
574 "show [ip] bgp l2vpn evpn all tags",
580 "Display information about all EVPN NLRIs\n"
581 "Display BGP tags for prefixes\n")
583 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
587 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
588 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
589 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
595 "Display information for a route distinguisher\n"
596 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
598 int idx_ext_community
= 0;
600 struct prefix_rd prd
;
602 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
604 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
606 vty_out(vty
, "%% Malformed Route Distinguisher\n");
609 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
613 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
614 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
615 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
621 "Display information about all EVPN NLRIs\n"
622 "Detailed information on TCP and BGP neighbor connections\n"
623 "Neighbor to display information about\n"
624 "Display routes learned from neighbor\n" JSON_STR
)
630 u_char uj
= use_json(argc
, argv
);
632 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
634 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
637 json_object
*json_no
= NULL
;
638 json_no
= json_object_new_object();
639 json_object_string_add(json_no
, "warning",
640 "Malformed address");
642 json_object_to_json_string(json_no
));
643 json_object_free(json_no
);
645 vty_out(vty
, "Malformed address: %s\n",
646 argv
[idx_ipv4
]->arg
);
650 peer
= peer_lookup(NULL
, &su
);
651 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
653 json_object
*json_no
= NULL
;
654 json_no
= json_object_new_object();
655 json_object_string_add(
657 "No such neighbor or address family");
659 json_object_to_json_string(json_no
));
660 json_object_free(json_no
);
662 vty_out(vty
, "%% No such neighbor or address family\n");
666 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
670 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
671 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
672 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
678 "Display information for a route distinguisher\n"
679 "VPN Route Distinguisher\n"
680 "Detailed information on TCP and BGP neighbor connections\n"
681 "Neighbor to display information about\n"
682 "Display routes learned from neighbor\n" JSON_STR
)
684 int idx_ext_community
= 0;
689 struct prefix_rd prd
;
690 u_char uj
= use_json(argc
, argv
);
692 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
693 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
695 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
698 json_object
*json_no
= NULL
;
699 json_no
= json_object_new_object();
700 json_object_string_add(json_no
, "warning",
701 "Malformed Route Distinguisher");
703 json_object_to_json_string(json_no
));
704 json_object_free(json_no
);
706 vty_out(vty
, "%% Malformed Route Distinguisher\n");
710 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
713 json_object
*json_no
= NULL
;
714 json_no
= json_object_new_object();
715 json_object_string_add(json_no
, "warning",
716 "Malformed address");
718 json_object_to_json_string(json_no
));
719 json_object_free(json_no
);
721 vty_out(vty
, "Malformed address: %s\n",
722 argv
[idx_ext_community
]->arg
);
726 peer
= peer_lookup(NULL
, &su
);
727 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
729 json_object
*json_no
= NULL
;
730 json_no
= json_object_new_object();
731 json_object_string_add(
733 "No such neighbor or address family");
735 json_object_to_json_string(json_no
));
736 json_object_free(json_no
);
738 vty_out(vty
, "%% No such neighbor or address family\n");
742 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
746 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
747 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
748 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
754 "Display information about all EVPN NLRIs\n"
755 "Detailed information on TCP and BGP neighbor connections\n"
756 "Neighbor to display information about\n"
757 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
763 u_char uj
= use_json(argc
, argv
);
765 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
767 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
770 json_object
*json_no
= NULL
;
771 json_no
= json_object_new_object();
772 json_object_string_add(json_no
, "warning",
773 "Malformed address");
775 json_object_to_json_string(json_no
));
776 json_object_free(json_no
);
778 vty_out(vty
, "Malformed address: %s\n",
779 argv
[idx_ipv4
]->arg
);
782 peer
= peer_lookup(NULL
, &su
);
783 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
785 json_object
*json_no
= NULL
;
786 json_no
= json_object_new_object();
787 json_object_string_add(
789 "No such neighbor or address family");
791 json_object_to_json_string(json_no
));
792 json_object_free(json_no
);
794 vty_out(vty
, "%% No such neighbor or address family\n");
798 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
801 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
802 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
803 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
809 "Display information for a route distinguisher\n"
810 "VPN Route Distinguisher\n"
811 "Detailed information on TCP and BGP neighbor connections\n"
812 "Neighbor to display information about\n"
813 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
815 int idx_ext_community
= 0;
819 struct prefix_rd prd
;
821 u_char uj
= use_json(argc
, argv
);
823 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
824 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
826 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
829 json_object
*json_no
= NULL
;
830 json_no
= json_object_new_object();
831 json_object_string_add(json_no
, "warning",
832 "Malformed address");
834 json_object_to_json_string(json_no
));
835 json_object_free(json_no
);
837 vty_out(vty
, "Malformed address: %s\n",
838 argv
[idx_ext_community
]->arg
);
841 peer
= peer_lookup(NULL
, &su
);
842 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
844 json_object
*json_no
= NULL
;
845 json_no
= json_object_new_object();
846 json_object_string_add(
848 "No such neighbor or address family");
850 json_object_to_json_string(json_no
));
851 json_object_free(json_no
);
853 vty_out(vty
, "%% No such neighbor or address family\n");
857 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
860 json_object
*json_no
= NULL
;
861 json_no
= json_object_new_object();
862 json_object_string_add(json_no
, "warning",
863 "Malformed Route Distinguisher");
865 json_object_to_json_string(json_no
));
866 json_object_free(json_no
);
868 vty_out(vty
, "%% Malformed Route Distinguisher\n");
872 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
875 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
876 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
877 "show [ip] bgp l2vpn evpn all overlay",
883 "Display information about all EVPN NLRIs\n"
884 "Display BGP Overlay Information for prefixes\n")
886 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
887 SHOW_DISPLAY_OVERLAY
,
888 use_json(argc
, argv
));
891 DEFUN(show_ip_bgp_evpn_rd_overlay
,
892 show_ip_bgp_evpn_rd_overlay_cmd
,
893 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
899 "Display information for a route distinguisher\n"
900 "VPN Route Distinguisher\n"
901 "Display BGP Overlay Information for prefixes\n")
903 int idx_ext_community
= 0;
905 struct prefix_rd prd
;
907 argv_find(argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
909 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
911 vty_out(vty
, "%% Malformed Route Distinguisher\n");
914 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
915 SHOW_DISPLAY_OVERLAY
,
916 use_json(argc
, argv
));
919 /* For testing purpose, static route of MPLS-VPN. */
920 DEFUN(evpnrt5_network
,
922 "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]",
923 "Specify a network to announce via BGP\n"
926 "Specify Route Distinguisher\n"
927 "VPN Route Distinguisher\n"
929 "Ethernet Tag Value\n"
932 "Ethernet Segment Identifier\n"
933 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
935 "Gateway IP ( A.B.C.D )\n"
936 "Gateway IPv6 ( X:X::X:X )\n"
937 "Router Mac Ext Comm\n"
938 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
939 "Route-map to modify the attributes\n"
940 "Name of the route map\n")
942 int idx_ipv4_prefixlen
= 1;
943 int idx_ext_community
= 3;
948 int idx_routermac
= 13;
950 return bgp_static_set_safi(
951 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
952 argv
[idx_ext_community
]->arg
, argv
[idx_word
]->arg
,
953 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
954 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
955 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
956 argv
[idx_routermac
]->arg
);
959 /* For testing purpose, static route of MPLS-VPN. */
960 DEFUN(no_evpnrt5_network
,
961 no_evpnrt5_network_cmd
,
962 "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>",
964 "Specify a network to announce via BGP\n"
967 "Specify Route Distinguisher\n"
968 "VPN Route Distinguisher\n"
970 "Ethernet Tag Value\n"
973 "Ethernet Segment Identifier\n"
974 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
975 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
977 int idx_ipv4_prefixlen
= 2;
978 int idx_ext_community
= 4;
983 return bgp_static_unset_safi(
984 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
985 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
986 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
987 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
990 #if defined(HAVE_CUMULUS)
991 static void evpn_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
,
994 struct listnode
*node
, *nnode
, *node_to_del
;
995 struct ecommunity
*ecom
, *ecom_auto
;
996 struct ecommunity_val eval
;
998 encode_route_target_as((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
1000 ecom_auto
= ecommunity_new();
1001 ecommunity_add_val(ecom_auto
, &eval
);
1004 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
1005 if (ecommunity_match(ecom
, ecom_auto
)) {
1006 ecommunity_free(&ecom
);
1012 list_delete_node(rtl
, node_to_del
);
1014 ecommunity_free(&ecom_auto
);
1017 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1019 evpn_rt_delete_auto(bgp
, vpn
, vpn
->import_rtl
);
1022 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1024 evpn_rt_delete_auto(bgp
, vpn
, vpn
->export_rtl
);
1028 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1029 * check that this is a change.
1031 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1032 struct ecommunity
*ecomadd
)
1034 /* If the VNI is "live", we need to uninstall routes using the current
1035 * import RT(s) first before we update the import RT, and subsequently
1038 if (is_vni_live(vpn
))
1039 bgp_evpn_uninstall_routes(bgp
, vpn
);
1041 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1042 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1044 /* If the auto route-target is in use we must remove it */
1045 evpn_import_rt_delete_auto(bgp
, vpn
);
1047 /* Add new RT and rebuild the RT to VNI mapping */
1048 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1050 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1051 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1053 /* Install routes that match new import RT */
1054 if (is_vni_live(vpn
))
1055 bgp_evpn_install_routes(bgp
, vpn
);
1059 * Unconfigure Import RT(s) for a VNI (vty handler).
1061 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1062 struct ecommunity
*ecomdel
)
1064 struct listnode
*node
, *nnode
, *node_to_del
;
1065 struct ecommunity
*ecom
;
1067 /* Along the lines of "configure" except we have to reset to the
1070 if (is_vni_live(vpn
))
1071 bgp_evpn_uninstall_routes(bgp
, vpn
);
1073 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1074 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1076 /* Delete all import RTs */
1077 if (ecomdel
== NULL
) {
1078 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1079 ecommunity_free(&ecom
);
1081 list_delete_all_node(vpn
->import_rtl
);
1084 /* Delete a specific import RT */
1088 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1089 if (ecommunity_match(ecom
, ecomdel
)) {
1090 ecommunity_free(&ecom
);
1097 list_delete_node(vpn
->import_rtl
, node_to_del
);
1100 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1101 if (list_isempty(vpn
->import_rtl
)) {
1102 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1103 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1105 /* Rebuild the RT to VNI mapping */
1107 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1109 /* Install routes that match new import RT */
1110 if (is_vni_live(vpn
))
1111 bgp_evpn_install_routes(bgp
, vpn
);
1115 * Configure the Export RT for a VNI (vty handler). Caller expected to
1116 * check that this is a change. Note that only a single export RT is
1117 * allowed for a VNI and any change to configuration is implemented as
1118 * a "replace" (similar to other configuration).
1120 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1121 struct ecommunity
*ecomadd
)
1123 /* If the auto route-target is in use we must remove it */
1124 evpn_export_rt_delete_auto(bgp
, vpn
);
1126 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1127 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1129 if (is_vni_live(vpn
))
1130 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1134 * Unconfigure the Export RT for a VNI (vty handler)
1136 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1137 struct ecommunity
*ecomdel
)
1139 struct listnode
*node
, *nnode
, *node_to_del
;
1140 struct ecommunity
*ecom
;
1142 /* Delete all export RTs */
1143 if (ecomdel
== NULL
) {
1144 /* Reset to default and process all routes. */
1145 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1146 ecommunity_free(&ecom
);
1148 list_delete_all_node(vpn
->export_rtl
);
1151 /* Delete a specific export RT */
1155 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1156 if (ecommunity_match(ecom
, ecomdel
)) {
1157 ecommunity_free(&ecom
);
1164 list_delete_node(vpn
->export_rtl
, node_to_del
);
1167 if (list_isempty(vpn
->export_rtl
)) {
1168 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1169 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1172 if (is_vni_live(vpn
))
1173 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1177 * Configure RD for a VNI (vty handler)
1179 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1180 struct prefix_rd
*rd
)
1182 /* If the VNI is "live", we need to delete and withdraw this VNI's
1183 * local routes with the prior RD first. Then, after updating RD,
1184 * need to re-advertise.
1186 if (is_vni_live(vpn
))
1187 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1190 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1191 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1193 if (is_vni_live(vpn
))
1194 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1198 * Unconfigure RD for a VNI (vty handler)
1200 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1202 /* If the VNI is "live", we need to delete and withdraw this VNI's
1203 * local routes with the prior RD first. Then, after resetting RD
1204 * to automatic value, need to re-advertise.
1206 if (is_vni_live(vpn
))
1207 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1209 /* reset RD to default */
1210 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1212 if (is_vni_live(vpn
))
1213 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1217 * Create VNI, if not already present (VTY handler). Mark as configured.
1219 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1221 struct bgpevpn
*vpn
;
1226 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1228 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
);
1231 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1237 /* Mark as configured. */
1238 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1243 * Delete VNI. If VNI does not exist in the system (i.e., just
1244 * configuration), all that is needed is to free it. Otherwise,
1245 * any parameters configured for the VNI need to be reset (with
1246 * appropriate action) and the VNI marked as unconfigured; the
1247 * VNI will continue to exist, purely as a "learnt" entity.
1249 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1251 assert(bgp
->vnihash
);
1253 if (!is_vni_live(vpn
)) {
1254 bgp_evpn_free(bgp
, vpn
);
1258 /* We need to take the unconfigure action for each parameter of this VNI
1259 * that is configured. Some optimization is possible, but not worth the
1260 * additional code for an operation that should be pretty rare.
1262 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1264 /* First, deal with the export side - RD and export RT changes. */
1265 if (is_rd_configured(vpn
))
1266 evpn_unconfigure_rd(bgp
, vpn
);
1267 if (is_export_rt_configured(vpn
))
1268 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1270 /* Next, deal with the import side. */
1271 if (is_import_rt_configured(vpn
))
1272 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1278 * Display import RT mapping to VNIs (vty handler)
1280 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
)
1283 bgp
->import_rt_hash
,
1284 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1289 * Display EVPN routes for all VNIs - vty handler.
1291 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1292 struct in_addr vtep_ip
)
1295 struct vni_walk_ctx wctx
;
1297 num_vnis
= hashcount(bgp
->vnihash
);
1300 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1303 wctx
.vtep_ip
= vtep_ip
;
1306 (void (*)(struct hash_backet
*, void *))show_vni_routes_hash
,
1311 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1313 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1314 vni_t vni
, struct in_addr orig_ip
)
1316 struct bgpevpn
*vpn
;
1317 struct prefix_evpn p
;
1318 struct bgp_node
*rn
;
1319 struct bgp_info
*ri
;
1320 u_int32_t path_cnt
= 0;
1328 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1330 vty_out(vty
, "VNI not found\n");
1334 /* See if route exists. */
1335 build_evpn_type3_prefix(&p
, orig_ip
);
1336 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1337 if (!rn
|| !rn
->info
) {
1338 vty_out(vty
, "%% Network not in table\n");
1342 /* Prefix and num paths displayed once per prefix. */
1343 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1345 /* Display each path for this prefix. */
1346 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1347 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1351 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1355 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1356 * By definition, only matching type-2 route will be displayed.
1358 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1359 vni_t vni
, struct ethaddr
*mac
,
1362 struct bgpevpn
*vpn
;
1363 struct prefix_evpn p
;
1364 struct bgp_node
*rn
;
1365 struct bgp_info
*ri
;
1366 u_int32_t path_cnt
= 0;
1374 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1376 vty_out(vty
, "VNI not found\n");
1380 /* See if route exists. Look for both non-sticky and sticky. */
1381 build_evpn_type2_prefix(&p
, mac
, ip
);
1382 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1383 if (!rn
|| !rn
->info
) {
1384 vty_out(vty
, "%% Network not in table\n");
1388 /* Prefix and num paths displayed once per prefix. */
1389 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1391 /* Display each path for this prefix. */
1392 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1393 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1397 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1401 * Display EVPN routes for a VNI - vty handler.
1402 * If 'type' is non-zero, only routes matching that type are shown.
1403 * If the vtep_ip is non zero, only routes behind that vtep are shown
1405 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1406 int type
, struct in_addr vtep_ip
)
1408 struct bgpevpn
*vpn
;
1411 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1413 vty_out(vty
, "VNI not found\n");
1417 /* Walk this VNI's route table and display appropriate routes. */
1418 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
);
1422 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1423 * IP (vty handler). By definition, only matching type-2 route will be
1426 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1427 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1430 struct prefix_evpn p
;
1431 struct bgp_node
*rn
;
1432 struct bgp_info
*ri
;
1435 u_int32_t path_cnt
= 0;
1440 /* See if route exists. Look for both non-sticky and sticky. */
1441 build_evpn_type2_prefix(&p
, mac
, ip
);
1442 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1443 (struct prefix
*)&p
, prd
);
1444 if (!rn
|| !rn
->info
) {
1445 vty_out(vty
, "%% Network not in table\n");
1449 /* Prefix and num paths displayed once per prefix. */
1450 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, NULL
);
1452 /* Display each path for this prefix. */
1453 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1454 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1458 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1462 * Display BGP EVPN routing table -- for specific RD (vty handler)
1463 * If 'type' is non-zero, only routes matching that type are shown.
1465 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
1466 struct prefix_rd
*prd
, int type
)
1468 struct bgp_node
*rd_rn
;
1469 struct bgp_table
*table
;
1470 struct bgp_node
*rn
;
1471 struct bgp_info
*ri
;
1475 u_int32_t prefix_cnt
, path_cnt
;
1479 prefix_cnt
= path_cnt
= 0;
1481 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1484 table
= (struct bgp_table
*)rd_rn
->info
;
1488 /* Display all prefixes with this RD. */
1489 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1490 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1492 if (type
&& evp
->prefix
.route_type
!= type
)
1496 /* RD header and legend - once overall. */
1499 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1502 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1507 /* Prefix and num paths displayed once per prefix. */
1508 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
1514 /* Display each path for this prefix. */
1515 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1516 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1522 if (prefix_cnt
== 0)
1523 vty_out(vty
, "No prefixes exist with this RD%s\n",
1524 type
? " (of requested type)" : "");
1527 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
1528 prefix_cnt
, path_cnt
,
1529 type
? " (of requested type)" : "");
1533 * Display BGP EVPN routing table - all routes (vty handler).
1534 * If 'type' is non-zero, only routes matching that type are shown.
1536 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
)
1538 struct bgp_node
*rd_rn
;
1539 struct bgp_table
*table
;
1540 struct bgp_node
*rn
;
1541 struct bgp_info
*ri
;
1546 u_int32_t prefix_cnt
, path_cnt
;
1550 prefix_cnt
= path_cnt
= 0;
1552 /* EVPN routing table is a 2-level table with the first level being
1555 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1556 rd_rn
= bgp_route_next(rd_rn
)) {
1557 table
= (struct bgp_table
*)rd_rn
->info
;
1563 /* Display all prefixes for an RD */
1564 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1565 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1567 if (type
&& evp
->prefix
.route_type
!= type
)
1571 /* Overall header/legend displayed once. */
1573 bgp_evpn_show_route_header(vty
, bgp
);
1577 /* RD header - per RD. */
1579 bgp_evpn_show_route_rd_header(vty
,
1587 /* For EVPN, the prefix is displayed for each path (to
1589 * with code that already exists).
1591 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1593 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
1599 if (prefix_cnt
== 0)
1600 vty_out(vty
, "No EVPN prefixes %sexist\n",
1601 type
? "(of requested type) " : "");
1603 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
1604 prefix_cnt
, path_cnt
,
1605 type
? " (of requested type)" : "");
1609 * Display specified VNI (vty handler)
1611 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
)
1613 struct bgpevpn
*vpn
;
1615 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1617 vty_out(vty
, "VNI not found\n");
1621 display_vni(vty
, vpn
);
1625 * Display a VNI (upon user query).
1627 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
)
1631 num_vnis
= hashcount(bgp
->vnihash
);
1634 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
1635 vty_out(vty
, "Flags: * - Kernel \n");
1636 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s\n", "VNI", "Orig IP",
1637 "RD", "Import RT", "Export RT");
1638 hash_iterate(bgp
->vnihash
,
1639 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
1644 * EVPN (VNI advertisement) enabled. Register with zebra.
1646 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
1648 bgp
->advertise_all_vni
= 1;
1649 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
1653 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
1654 * cache, EVPN routes (delete and withdraw from peers).
1656 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
1658 bgp
->advertise_all_vni
= 0;
1659 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
1660 bgp_evpn_cleanup_on_disable(bgp
);
1662 #endif /* HAVE_CUMULUS */
1664 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
, int *write
)
1666 char buf1
[INET6_ADDRSTRLEN
];
1667 afi_t afi
= AFI_L2VPN
;
1668 safi_t safi
= SAFI_EVPN
;
1670 struct listnode
*node
, *nnode
;
1671 struct ecommunity
*ecom
;
1673 if (is_vni_configured(vpn
)) {
1674 bgp_config_write_family_header(vty
, afi
, safi
, write
);
1675 vty_out(vty
, " vni %d\n", vpn
->vni
);
1676 if (is_rd_configured(vpn
))
1677 vty_out(vty
, " rd %s\n",
1678 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
1680 if (is_import_rt_configured(vpn
)) {
1681 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
1683 ecom_str
= ecommunity_ecom2str(
1684 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1685 vty_out(vty
, " route-target import %s\n",
1687 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1691 if (is_export_rt_configured(vpn
)) {
1692 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
1694 ecom_str
= ecommunity_ecom2str(
1695 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1696 vty_out(vty
, " route-target export %s\n",
1698 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1702 vty_out(vty
, " exit-vni\n");
1706 static void write_vni_config_for_entry(struct hash_backet
*backet
,
1707 struct evpn_config_write
*cfg
)
1709 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
1710 write_vni_config(cfg
->vty
, vpn
, &cfg
->write
);
1713 #if defined(HAVE_CUMULUS)
1714 DEFUN (bgp_evpn_advertise_all_vni
,
1715 bgp_evpn_advertise_all_vni_cmd
,
1716 "advertise-all-vni",
1717 "Advertise All local VNIs\n")
1719 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1723 evpn_set_advertise_all_vni(bgp
);
1727 DEFUN (no_bgp_evpn_advertise_all_vni
,
1728 no_bgp_evpn_advertise_all_vni_cmd
,
1729 "no advertise-all-vni",
1731 "Advertise All local VNIs\n")
1733 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1737 evpn_unset_advertise_all_vni(bgp
);
1741 DEFUN (show_bgp_evpn_vni
,
1742 show_bgp_evpn_vni_cmd
,
1743 "show bgp evpn vni",
1751 bgp
= bgp_get_default();
1755 vty_out(vty
, "Advertise All VNI flag: %s\n",
1756 bgp
->advertise_all_vni
? "Enabled" : "Disabled");
1758 evpn_show_all_vnis(vty
, bgp
);
1762 DEFUN (show_bgp_evpn_vni_num
,
1763 show_bgp_evpn_vni_num_cmd
,
1764 "show bgp evpn vni (1-16777215)",
1767 "Address family modifier\n"
1774 bgp
= bgp_get_default();
1778 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
1780 evpn_show_vni(vty
, bgp
, vni
);
1784 /* `show bgp evpn summary' commands. */
1785 DEFUN (show_bgp_evpn_summary
,
1786 show_bgp_evpn_summary_cmd
,
1787 "show bgp evpn summary [json]",
1791 "Summary of BGP neighbor status\n"
1792 "JavaScript Object Notation\n")
1794 u_char uj
= use_json(argc
, argv
);
1795 return bgp_show_summary_vty(vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1798 /* Show bgp evpn route */
1799 DEFUN (show_bgp_evpn_route
,
1800 show_bgp_evpn_route_cmd
,
1801 "show bgp evpn route [type <macip|multicast>]",
1804 "Address Family Modifier\n"
1805 "Display EVPN route information\n"
1806 "Specify Route type\n"
1807 "MAC-IP (Type-2) route\n"
1808 "Multicast (Type-3) route\n")
1813 bgp
= bgp_get_default();
1818 if (strncmp(argv
[5]->arg
, "ma", 2) == 0)
1819 type
= BGP_EVPN_MAC_IP_ROUTE
;
1820 else if (strncmp(argv
[5]->arg
, "mu", 2) == 0)
1821 type
= BGP_EVPN_IMET_ROUTE
;
1826 evpn_show_all_routes(vty
, bgp
, type
);
1830 DEFUN (show_bgp_evpn_route_rd
,
1831 show_bgp_evpn_route_rd_cmd
,
1832 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
1835 "Address Family Modifier\n"
1836 "Display EVPN route information\n"
1837 "Route Distinguisher\n"
1838 "ASN:XX or A.B.C.D:XX\n"
1839 "Specify Route type\n"
1840 "MAC-IP (Type-2) route\n"
1841 "Multicast (Type-3) route\n")
1845 struct prefix_rd prd
;
1848 bgp
= bgp_get_default();
1852 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
1854 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1859 if (strncmp(argv
[7]->arg
, "ma", 2) == 0)
1860 type
= BGP_EVPN_MAC_IP_ROUTE
;
1861 else if (strncmp(argv
[7]->arg
, "mu", 2) == 0)
1862 type
= BGP_EVPN_IMET_ROUTE
;
1867 evpn_show_route_rd(vty
, bgp
, &prd
, type
);
1871 DEFUN (show_bgp_evpn_route_rd_macip
,
1872 show_bgp_evpn_route_rd_macip_cmd
,
1873 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
1876 "Address Family Modifier\n"
1877 "Display EVPN route information\n"
1878 "Route Distinguisher\n"
1879 "ASN:XX or A.B.C.D:XX\n"
1881 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
1883 "IP address (IPv4 or IPv6)\n")
1887 struct prefix_rd prd
;
1891 bgp
= bgp_get_default();
1895 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
1897 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1900 if (!prefix_str2mac(argv
[7]->arg
, &mac
)) {
1901 vty_out(vty
, "%% Malformed MAC address\n");
1904 memset(&ip
, 0, sizeof(ip
));
1905 if (argc
== 10 && argv
[9]->arg
!= NULL
) {
1906 if (str2ipaddr(argv
[9]->arg
, &ip
) != 0) {
1907 vty_out(vty
, "%% Malformed IP address\n");
1912 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
);
1916 DEFUN (show_bgp_evpn_route_vni
,
1917 show_bgp_evpn_route_vni_cmd
,
1918 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
1921 "Address Family Modifier\n"
1922 "Display EVPN route information\n"
1923 "VXLAN Network Identifier\n"
1925 "Specify Route type\n"
1926 "MAC-IP (Type-2) route\n"
1927 "Multicast (Type-3) route\n"
1929 "Remote VTEP IP address\n")
1933 struct in_addr vtep_ip
;
1936 bgp
= bgp_get_default();
1942 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
1944 if (argc
== 8 && argv
[6]->arg
) {
1945 if (strncmp(argv
[6]->arg
, "type", 4) == 0) {
1946 if (strncmp(argv
[7]->arg
, "ma", 2) == 0)
1947 type
= BGP_EVPN_MAC_IP_ROUTE
;
1948 else if (strncmp(argv
[7]->arg
, "mu", 2) == 0)
1949 type
= BGP_EVPN_IMET_ROUTE
;
1952 } else if (strncmp(argv
[6]->arg
, "vtep", 4) == 0) {
1953 if (!inet_aton(argv
[7]->arg
, &vtep_ip
)) {
1954 vty_out(vty
, "%% Malformed VTEP IP address\n");
1961 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
);
1965 DEFUN (show_bgp_evpn_route_vni_macip
,
1966 show_bgp_evpn_route_vni_macip_cmd
,
1967 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
1970 "Address Family Modifier\n"
1971 "Display EVPN route information\n"
1972 "VXLAN Network Identifier\n"
1975 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
1977 "IP address (IPv4 or IPv6)\n")
1984 bgp
= bgp_get_default();
1988 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
1989 if (!prefix_str2mac(argv
[7]->arg
, &mac
)) {
1990 vty_out(vty
, "%% Malformed MAC address\n");
1993 memset(&ip
, 0, sizeof(ip
));
1994 if (argc
== 10 && argv
[9]->arg
!= NULL
) {
1995 if (str2ipaddr(argv
[9]->arg
, &ip
) != 0) {
1996 vty_out(vty
, "%% Malformed IP address\n");
2001 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
);
2005 DEFUN (show_bgp_evpn_route_vni_multicast
,
2006 show_bgp_evpn_route_vni_multicast_cmd
,
2007 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2010 "Address Family Modifier\n"
2011 "Display EVPN route information\n"
2012 "VXLAN Network Identifier\n"
2014 "Multicast (Type-3) route\n"
2015 "Originating Router IP address\n")
2020 struct in_addr orig_ip
;
2022 bgp
= bgp_get_default();
2026 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
2027 ret
= inet_aton(argv
[7]->arg
, &orig_ip
);
2029 vty_out(vty
, "%% Malformed Originating Router IP address\n");
2033 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
);
2037 DEFUN (show_bgp_evpn_route_vni_all
,
2038 show_bgp_evpn_route_vni_all_cmd
,
2039 "show bgp evpn route vni all [vtep A.B.C.D]",
2042 "Address Family Modifier\n"
2043 "Display EVPN route information\n"
2044 "VXLAN Network Identifier\n"
2047 "Remote VTEP IP address\n")
2050 struct in_addr vtep_ip
;
2052 bgp
= bgp_get_default();
2057 if (argc
== 8 && argv
[7]->arg
) {
2058 if (!inet_aton(argv
[7]->arg
, &vtep_ip
)) {
2059 vty_out(vty
, "%% Malformed VTEP IP address\n");
2064 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
);
2068 DEFUN (show_bgp_evpn_import_rt
,
2069 show_bgp_evpn_import_rt_cmd
,
2070 "show bgp evpn import-rt",
2073 "Address family modifier\n"
2074 "Show import route target\n")
2078 bgp
= bgp_get_default();
2082 evpn_show_import_rts(vty
, bgp
);
2086 DEFUN_NOSH (bgp_evpn_vni
,
2089 "VXLAN Network Identifier\n"
2093 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2094 struct bgpevpn
*vpn
;
2099 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2101 /* Create VNI, or mark as configured. */
2102 vpn
= evpn_create_update_vni(bgp
, vni
);
2104 vty_out(vty
, "%% Failed to create VNI \n");
2108 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
2112 DEFUN (no_bgp_evpn_vni
,
2113 no_bgp_evpn_vni_cmd
,
2114 "no vni (1-16777215)",
2116 "VXLAN Network Identifier\n"
2120 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2121 struct bgpevpn
*vpn
;
2126 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2128 /* Check if we should disallow. */
2129 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2131 vty_out(vty
, "%% Specified VNI does not exist\n");
2134 if (!is_vni_configured(vpn
)) {
2135 vty_out(vty
, "%% Specified VNI is not configured\n");
2139 evpn_delete_vni(bgp
, vpn
);
2143 DEFUN_NOSH (exit_vni
,
2146 "Exit from VNI mode\n")
2148 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2149 vty
->node
= BGP_EVPN_NODE
;
2153 DEFUN (bgp_evpn_vni_rd
,
2154 bgp_evpn_vni_rd_cmd
,
2155 "rd ASN:nn_or_IP-address:nn",
2156 "Route Distinguisher\n"
2157 "ASN:XX or A.B.C.D:XX\n")
2159 struct prefix_rd prd
;
2160 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2161 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2167 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
2169 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2173 /* If same as existing value, there is nothing more to do. */
2174 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
2177 /* Configure or update the RD. */
2178 evpn_configure_rd(bgp
, vpn
, &prd
);
2182 DEFUN (no_bgp_evpn_vni_rd
,
2183 no_bgp_evpn_vni_rd_cmd
,
2184 "no rd ASN:nn_or_IP-address:nn",
2186 "Route Distinguisher\n"
2187 "ASN:XX or A.B.C.D:XX\n")
2189 struct prefix_rd prd
;
2190 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2191 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2197 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
2199 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2203 /* Check if we should disallow. */
2204 if (!is_rd_configured(vpn
)) {
2205 vty_out(vty
, "%% RD is not configured for this VNI\n");
2209 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
2211 "%% RD specified does not match configuration for this VNI\n");
2215 evpn_unconfigure_rd(bgp
, vpn
);
2219 DEFUN (no_bgp_evpn_vni_rd_without_val
,
2220 no_bgp_evpn_vni_rd_without_val_cmd
,
2223 "Route Distinguisher\n")
2225 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2226 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2231 /* Check if we should disallow. */
2232 if (!is_rd_configured(vpn
)) {
2233 vty_out(vty
, "%% RD is not configured for this VNI\n");
2237 evpn_unconfigure_rd(bgp
, vpn
);
2242 * Loop over all extended-communities in the route-target list rtl and
2243 * return 1 if we find ecomtarget
2245 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
2246 struct ecommunity
*ecomtarget
)
2248 struct listnode
*node
, *nnode
;
2249 struct ecommunity
*ecom
;
2251 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
2252 if (ecommunity_match(ecom
, ecomtarget
))
2260 DEFUN (bgp_evpn_vni_rt
,
2261 bgp_evpn_vni_rt_cmd
,
2262 "route-target <both|import|export> RT",
2264 "import and export\n"
2267 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
2269 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2270 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2272 struct ecommunity
*ecomadd
= NULL
;
2277 if (!strcmp(argv
[1]->arg
, "import"))
2278 rt_type
= RT_TYPE_IMPORT
;
2279 else if (!strcmp(argv
[1]->arg
, "export"))
2280 rt_type
= RT_TYPE_EXPORT
;
2281 else if (!strcmp(argv
[1]->arg
, "both"))
2282 rt_type
= RT_TYPE_BOTH
;
2284 vty_out(vty
, "%% Invalid Route Target type\n");
2288 /* Add/update the import route-target */
2289 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
2290 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
2291 ECOMMUNITY_ROUTE_TARGET
, 0);
2292 ecommunity_str(ecomadd
);
2294 vty_out(vty
, "%% Malformed Route Target list\n");
2298 /* Do nothing if we already have this import route-target */
2299 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
2300 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
2303 /* Add/update the export route-target */
2304 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
2305 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
2306 ECOMMUNITY_ROUTE_TARGET
, 0);
2307 ecommunity_str(ecomadd
);
2309 vty_out(vty
, "%% Malformed Route Target list\n");
2313 /* Do nothing if we already have this export route-target */
2314 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
2315 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
2321 DEFUN (no_bgp_evpn_vni_rt
,
2322 no_bgp_evpn_vni_rt_cmd
,
2323 "no route-target <both|import|export> RT",
2326 "import and export\n"
2329 "ASN:XX or A.B.C.D:XX\n")
2331 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2332 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2333 int rt_type
, found_ecomdel
;
2334 struct ecommunity
*ecomdel
= NULL
;
2339 if (!strcmp(argv
[2]->arg
, "import"))
2340 rt_type
= RT_TYPE_IMPORT
;
2341 else if (!strcmp(argv
[2]->arg
, "export"))
2342 rt_type
= RT_TYPE_EXPORT
;
2343 else if (!strcmp(argv
[2]->arg
, "both"))
2344 rt_type
= RT_TYPE_BOTH
;
2346 vty_out(vty
, "%% Invalid Route Target type\n");
2350 /* The user did "no route-target import", check to see if there are any
2351 * import route-targets configured. */
2352 if (rt_type
== RT_TYPE_IMPORT
) {
2353 if (!is_import_rt_configured(vpn
)) {
2355 "%% Import RT is not configured for this VNI\n");
2358 } else if (rt_type
== RT_TYPE_EXPORT
) {
2359 if (!is_export_rt_configured(vpn
)) {
2361 "%% Export RT is not configured for this VNI\n");
2364 } else if (rt_type
== RT_TYPE_BOTH
) {
2365 if (!is_import_rt_configured(vpn
)
2366 && !is_export_rt_configured(vpn
)) {
2368 "%% Import/Export RT is not configured for this VNI\n");
2373 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
2374 ecommunity_str(ecomdel
);
2376 vty_out(vty
, "%% Malformed Route Target list\n");
2380 if (rt_type
== RT_TYPE_IMPORT
) {
2381 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
2383 "%% RT specified does not match configuration for this VNI\n");
2386 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
2387 } else if (rt_type
== RT_TYPE_EXPORT
) {
2388 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
2390 "%% RT specified does not match configuration for this VNI\n");
2393 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
2394 } else if (rt_type
== RT_TYPE_BOTH
) {
2397 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
2398 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
2402 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
2403 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
2407 if (!found_ecomdel
) {
2409 "%% RT specified does not match configuration for this VNI\n");
2417 DEFUN (no_bgp_evpn_vni_rt_without_val
,
2418 no_bgp_evpn_vni_rt_without_val_cmd
,
2419 "no route-target <import|export>",
2425 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2426 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2432 if (!strcmp(argv
[2]->arg
, "import")) {
2433 rt_type
= RT_TYPE_IMPORT
;
2434 } else if (!strcmp(argv
[2]->arg
, "export")) {
2435 rt_type
= RT_TYPE_EXPORT
;
2437 vty_out(vty
, "%% Invalid Route Target type\n");
2441 /* Check if we should disallow. */
2442 if (rt_type
== RT_TYPE_IMPORT
) {
2443 if (!is_import_rt_configured(vpn
)) {
2445 "%% Import RT is not configured for this VNI\n");
2449 if (!is_export_rt_configured(vpn
)) {
2451 "%% Export RT is not configured for this VNI\n");
2456 /* Unconfigure the RT. */
2457 if (rt_type
== RT_TYPE_IMPORT
)
2458 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2460 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2465 * Output EVPN configuration information.
2467 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
2468 safi_t safi
, int *write
)
2470 struct evpn_config_write cfg
;
2475 hash_iterate(bgp
->vnihash
,
2476 (void (*)(struct hash_backet
*,
2477 void *))write_vni_config_for_entry
,
2482 if (bgp
->advertise_all_vni
) {
2483 bgp_config_write_family_header(vty
, afi
, safi
, write
);
2484 vty_out(vty
, " advertise-all-vni\n");
2488 void bgp_ethernetvpn_init(void)
2490 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
2491 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
2492 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
2493 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
2494 install_element(VIEW_NODE
,
2495 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
2496 install_element(VIEW_NODE
,
2497 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
2500 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
2503 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
2504 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
2505 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
2506 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
2507 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
2508 #if defined(HAVE_CUMULUS)
2509 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
2510 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
2512 /* "show bgp evpn" commands. */
2513 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
2514 install_element(VIEW_NODE
, &show_bgp_evpn_vni_num_cmd
);
2515 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
2516 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
2517 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
2518 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
2519 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
2520 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
2521 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
2522 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
2523 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
2525 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
2526 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
2527 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
2528 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
2529 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
2530 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
2531 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
2532 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
2533 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);