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
;
1304 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1305 void *))show_vni_routes_hash
,
1310 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1312 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1313 vni_t vni
, struct in_addr orig_ip
)
1315 struct bgpevpn
*vpn
;
1316 struct prefix_evpn p
;
1317 struct bgp_node
*rn
;
1318 struct bgp_info
*ri
;
1319 u_int32_t path_cnt
= 0;
1327 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1329 vty_out(vty
, "VNI not found\n");
1333 /* See if route exists. */
1334 build_evpn_type3_prefix(&p
, orig_ip
);
1335 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1336 if (!rn
|| !rn
->info
) {
1337 vty_out(vty
, "%% Network not in table\n");
1341 /* Prefix and num paths displayed once per prefix. */
1342 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1344 /* Display each path for this prefix. */
1345 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1346 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1350 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1354 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1355 * By definition, only matching type-2 route will be displayed.
1357 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1358 vni_t vni
, struct ethaddr
*mac
,
1361 struct bgpevpn
*vpn
;
1362 struct prefix_evpn p
;
1363 struct bgp_node
*rn
;
1364 struct bgp_info
*ri
;
1365 u_int32_t path_cnt
= 0;
1373 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1375 vty_out(vty
, "VNI not found\n");
1379 /* See if route exists. Look for both non-sticky and sticky. */
1380 build_evpn_type2_prefix(&p
, mac
, ip
);
1381 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1382 if (!rn
|| !rn
->info
) {
1383 vty_out(vty
, "%% Network not in table\n");
1387 /* Prefix and num paths displayed once per prefix. */
1388 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1390 /* Display each path for this prefix. */
1391 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1392 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1396 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1400 * Display EVPN routes for a VNI - vty handler.
1401 * If 'type' is non-zero, only routes matching that type are shown.
1402 * If the vtep_ip is non zero, only routes behind that vtep are shown
1404 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1405 int type
, struct in_addr vtep_ip
)
1407 struct bgpevpn
*vpn
;
1410 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1412 vty_out(vty
, "VNI not found\n");
1416 /* Walk this VNI's route table and display appropriate routes. */
1417 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
);
1421 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1422 * IP (vty handler). By definition, only matching type-2 route will be
1425 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1426 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1429 struct prefix_evpn p
;
1430 struct bgp_node
*rn
;
1431 struct bgp_info
*ri
;
1434 u_int32_t path_cnt
= 0;
1439 /* See if route exists. Look for both non-sticky and sticky. */
1440 build_evpn_type2_prefix(&p
, mac
, ip
);
1441 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1442 (struct prefix
*)&p
, prd
);
1443 if (!rn
|| !rn
->info
) {
1444 vty_out(vty
, "%% Network not in table\n");
1448 /* Prefix and num paths displayed once per prefix. */
1449 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, NULL
);
1451 /* Display each path for this prefix. */
1452 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1453 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1457 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n", path_cnt
);
1461 * Display BGP EVPN routing table -- for specific RD (vty handler)
1462 * If 'type' is non-zero, only routes matching that type are shown.
1464 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
1465 struct prefix_rd
*prd
, int type
)
1467 struct bgp_node
*rd_rn
;
1468 struct bgp_table
*table
;
1469 struct bgp_node
*rn
;
1470 struct bgp_info
*ri
;
1474 u_int32_t prefix_cnt
, path_cnt
;
1478 prefix_cnt
= path_cnt
= 0;
1480 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1483 table
= (struct bgp_table
*)rd_rn
->info
;
1487 /* Display all prefixes with this RD. */
1488 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1489 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1491 if (type
&& evp
->prefix
.route_type
!= type
)
1495 /* RD header and legend - once overall. */
1498 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1501 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1506 /* Prefix and num paths displayed once per prefix. */
1507 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
1513 /* Display each path for this prefix. */
1514 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1515 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1521 if (prefix_cnt
== 0)
1522 vty_out(vty
, "No prefixes exist with this RD%s\n",
1523 type
? " (of requested type)" : "");
1526 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
1527 prefix_cnt
, path_cnt
,
1528 type
? " (of requested type)" : "");
1532 * Display BGP EVPN routing table - all routes (vty handler).
1533 * If 'type' is non-zero, only routes matching that type are shown.
1535 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
)
1537 struct bgp_node
*rd_rn
;
1538 struct bgp_table
*table
;
1539 struct bgp_node
*rn
;
1540 struct bgp_info
*ri
;
1545 u_int32_t prefix_cnt
, path_cnt
;
1549 prefix_cnt
= path_cnt
= 0;
1551 /* EVPN routing table is a 2-level table with the first level being
1554 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
1555 rd_rn
= bgp_route_next(rd_rn
)) {
1556 table
= (struct bgp_table
*)rd_rn
->info
;
1562 /* Display all prefixes for an RD */
1563 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1564 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1566 if (type
&& evp
->prefix
.route_type
!= type
)
1570 /* Overall header/legend displayed once. */
1572 bgp_evpn_show_route_header(vty
, bgp
);
1576 /* RD header - per RD. */
1578 bgp_evpn_show_route_rd_header(vty
,
1586 /* For EVPN, the prefix is displayed for each path (to
1588 * with code that already exists).
1590 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1592 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
1598 if (prefix_cnt
== 0)
1599 vty_out(vty
, "No EVPN prefixes %sexist\n",
1600 type
? "(of requested type) " : "");
1602 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
1603 prefix_cnt
, path_cnt
,
1604 type
? " (of requested type)" : "");
1608 * Display specified VNI (vty handler)
1610 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
)
1612 struct bgpevpn
*vpn
;
1614 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1616 vty_out(vty
, "VNI not found\n");
1620 display_vni(vty
, vpn
);
1624 * Display a VNI (upon user query).
1626 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
)
1630 num_vnis
= hashcount(bgp
->vnihash
);
1633 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
1634 vty_out(vty
, "Flags: * - Kernel \n");
1635 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s\n", "VNI", "Orig IP",
1636 "RD", "Import RT", "Export RT");
1637 hash_iterate(bgp
->vnihash
,
1638 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
1643 * EVPN (VNI advertisement) enabled. Register with zebra.
1645 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
1647 bgp
->advertise_all_vni
= 1;
1648 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
1652 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
1653 * cache, EVPN routes (delete and withdraw from peers).
1655 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
1657 bgp
->advertise_all_vni
= 0;
1658 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
1659 bgp_evpn_cleanup_on_disable(bgp
);
1661 #endif /* HAVE_CUMULUS */
1663 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
, int *write
)
1665 char buf1
[INET6_ADDRSTRLEN
];
1666 afi_t afi
= AFI_L2VPN
;
1667 safi_t safi
= SAFI_EVPN
;
1669 struct listnode
*node
, *nnode
;
1670 struct ecommunity
*ecom
;
1672 if (is_vni_configured(vpn
)) {
1673 bgp_config_write_family_header(vty
, afi
, safi
, write
);
1674 vty_out(vty
, " vni %d\n", vpn
->vni
);
1675 if (is_rd_configured(vpn
))
1676 vty_out(vty
, " rd %s\n",
1677 prefix_rd2str(&vpn
->prd
, buf1
, RD_ADDRSTRLEN
));
1679 if (is_import_rt_configured(vpn
)) {
1680 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
1682 ecom_str
= ecommunity_ecom2str(
1683 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1684 vty_out(vty
, " route-target import %s\n",
1686 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1690 if (is_export_rt_configured(vpn
)) {
1691 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
1693 ecom_str
= ecommunity_ecom2str(
1694 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1695 vty_out(vty
, " route-target export %s\n",
1697 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1701 vty_out(vty
, " exit-vni\n");
1705 static void write_vni_config_for_entry(struct hash_backet
*backet
,
1706 struct evpn_config_write
*cfg
)
1708 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
1709 write_vni_config(cfg
->vty
, vpn
, &cfg
->write
);
1712 #if defined(HAVE_CUMULUS)
1713 DEFUN (bgp_evpn_advertise_all_vni
,
1714 bgp_evpn_advertise_all_vni_cmd
,
1715 "advertise-all-vni",
1716 "Advertise All local VNIs\n")
1718 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1722 evpn_set_advertise_all_vni(bgp
);
1726 DEFUN (no_bgp_evpn_advertise_all_vni
,
1727 no_bgp_evpn_advertise_all_vni_cmd
,
1728 "no advertise-all-vni",
1730 "Advertise All local VNIs\n")
1732 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1736 evpn_unset_advertise_all_vni(bgp
);
1740 DEFUN (show_bgp_evpn_vni
,
1741 show_bgp_evpn_vni_cmd
,
1742 "show bgp evpn vni",
1750 bgp
= bgp_get_default();
1754 vty_out(vty
, "Advertise All VNI flag: %s\n",
1755 bgp
->advertise_all_vni
? "Enabled" : "Disabled");
1757 evpn_show_all_vnis(vty
, bgp
);
1761 DEFUN (show_bgp_evpn_vni_num
,
1762 show_bgp_evpn_vni_num_cmd
,
1763 "show bgp evpn vni (1-16777215)",
1766 "Address family modifier\n"
1773 bgp
= bgp_get_default();
1777 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
1779 evpn_show_vni(vty
, bgp
, vni
);
1783 /* `show bgp evpn summary' commands. */
1784 DEFUN (show_bgp_evpn_summary
,
1785 show_bgp_evpn_summary_cmd
,
1786 "show bgp evpn summary [json]",
1790 "Summary of BGP neighbor status\n"
1791 "JavaScript Object Notation\n")
1793 u_char uj
= use_json(argc
, argv
);
1794 return bgp_show_summary_vty(vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1797 /* Show bgp evpn route */
1798 DEFUN (show_bgp_evpn_route
,
1799 show_bgp_evpn_route_cmd
,
1800 "show bgp evpn route [type <macip|multicast>]",
1803 "Address Family Modifier\n"
1804 "Display EVPN route information\n"
1805 "Specify Route type\n"
1806 "MAC-IP (Type-2) route\n"
1807 "Multicast (Type-3) route\n")
1812 bgp
= bgp_get_default();
1817 if (strncmp(argv
[5]->arg
, "ma", 2) == 0)
1818 type
= BGP_EVPN_MAC_IP_ROUTE
;
1819 else if (strncmp(argv
[5]->arg
, "mu", 2) == 0)
1820 type
= BGP_EVPN_IMET_ROUTE
;
1825 evpn_show_all_routes(vty
, bgp
, type
);
1829 DEFUN (show_bgp_evpn_route_rd
,
1830 show_bgp_evpn_route_rd_cmd
,
1831 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
1834 "Address Family Modifier\n"
1835 "Display EVPN route information\n"
1836 "Route Distinguisher\n"
1837 "ASN:XX or A.B.C.D:XX\n"
1838 "Specify Route type\n"
1839 "MAC-IP (Type-2) route\n"
1840 "Multicast (Type-3) route\n")
1844 struct prefix_rd prd
;
1847 bgp
= bgp_get_default();
1851 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
1853 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1858 if (strncmp(argv
[7]->arg
, "ma", 2) == 0)
1859 type
= BGP_EVPN_MAC_IP_ROUTE
;
1860 else if (strncmp(argv
[7]->arg
, "mu", 2) == 0)
1861 type
= BGP_EVPN_IMET_ROUTE
;
1866 evpn_show_route_rd(vty
, bgp
, &prd
, type
);
1870 DEFUN (show_bgp_evpn_route_rd_macip
,
1871 show_bgp_evpn_route_rd_macip_cmd
,
1872 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
1875 "Address Family Modifier\n"
1876 "Display EVPN route information\n"
1877 "Route Distinguisher\n"
1878 "ASN:XX or A.B.C.D:XX\n"
1880 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
1882 "IP address (IPv4 or IPv6)\n")
1886 struct prefix_rd prd
;
1890 bgp
= bgp_get_default();
1894 ret
= str2prefix_rd(argv
[5]->arg
, &prd
);
1896 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1899 if (!prefix_str2mac(argv
[7]->arg
, &mac
)) {
1900 vty_out(vty
, "%% Malformed MAC address\n");
1903 memset(&ip
, 0, sizeof(ip
));
1904 if (argc
== 10 && argv
[9]->arg
!= NULL
) {
1905 if (str2ipaddr(argv
[9]->arg
, &ip
) != 0) {
1906 vty_out(vty
, "%% Malformed IP address\n");
1911 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
);
1915 DEFUN (show_bgp_evpn_route_vni
,
1916 show_bgp_evpn_route_vni_cmd
,
1917 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
1920 "Address Family Modifier\n"
1921 "Display EVPN route information\n"
1922 "VXLAN Network Identifier\n"
1924 "Specify Route type\n"
1925 "MAC-IP (Type-2) route\n"
1926 "Multicast (Type-3) route\n"
1928 "Remote VTEP IP address\n")
1932 struct in_addr vtep_ip
;
1935 bgp
= bgp_get_default();
1941 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
1943 if (argc
== 8 && argv
[6]->arg
) {
1944 if (strncmp(argv
[6]->arg
, "type", 4) == 0) {
1945 if (strncmp(argv
[7]->arg
, "ma", 2) == 0)
1946 type
= BGP_EVPN_MAC_IP_ROUTE
;
1947 else if (strncmp(argv
[7]->arg
, "mu", 2) == 0)
1948 type
= BGP_EVPN_IMET_ROUTE
;
1951 } else if (strncmp(argv
[6]->arg
, "vtep", 4) == 0) {
1952 if (!inet_aton(argv
[7]->arg
, &vtep_ip
)) {
1953 vty_out(vty
, "%% Malformed VTEP IP address\n");
1960 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
);
1964 DEFUN (show_bgp_evpn_route_vni_macip
,
1965 show_bgp_evpn_route_vni_macip_cmd
,
1966 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
1969 "Address Family Modifier\n"
1970 "Display EVPN route information\n"
1971 "VXLAN Network Identifier\n"
1974 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
1976 "IP address (IPv4 or IPv6)\n")
1983 bgp
= bgp_get_default();
1987 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
1988 if (!prefix_str2mac(argv
[7]->arg
, &mac
)) {
1989 vty_out(vty
, "%% Malformed MAC address\n");
1992 memset(&ip
, 0, sizeof(ip
));
1993 if (argc
== 10 && argv
[9]->arg
!= NULL
) {
1994 if (str2ipaddr(argv
[9]->arg
, &ip
) != 0) {
1995 vty_out(vty
, "%% Malformed IP address\n");
2000 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
);
2004 DEFUN (show_bgp_evpn_route_vni_multicast
,
2005 show_bgp_evpn_route_vni_multicast_cmd
,
2006 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2009 "Address Family Modifier\n"
2010 "Display EVPN route information\n"
2011 "VXLAN Network Identifier\n"
2013 "Multicast (Type-3) route\n"
2014 "Originating Router IP address\n")
2019 struct in_addr orig_ip
;
2021 bgp
= bgp_get_default();
2025 vni
= strtoul(argv
[5]->arg
, NULL
, 10);
2026 ret
= inet_aton(argv
[7]->arg
, &orig_ip
);
2028 vty_out(vty
, "%% Malformed Originating Router IP address\n");
2032 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
);
2036 DEFUN (show_bgp_evpn_route_vni_all
,
2037 show_bgp_evpn_route_vni_all_cmd
,
2038 "show bgp evpn route vni all [vtep A.B.C.D]",
2041 "Address Family Modifier\n"
2042 "Display EVPN route information\n"
2043 "VXLAN Network Identifier\n"
2046 "Remote VTEP IP address\n")
2049 struct in_addr vtep_ip
;
2051 bgp
= bgp_get_default();
2056 if (argc
== 8 && argv
[7]->arg
) {
2057 if (!inet_aton(argv
[7]->arg
, &vtep_ip
)) {
2058 vty_out(vty
, "%% Malformed VTEP IP address\n");
2063 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
);
2067 DEFUN (show_bgp_evpn_import_rt
,
2068 show_bgp_evpn_import_rt_cmd
,
2069 "show bgp evpn import-rt",
2072 "Address family modifier\n"
2073 "Show import route target\n")
2077 bgp
= bgp_get_default();
2081 evpn_show_import_rts(vty
, bgp
);
2085 DEFUN_NOSH (bgp_evpn_vni
,
2088 "VXLAN Network Identifier\n"
2092 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2093 struct bgpevpn
*vpn
;
2098 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
2100 /* Create VNI, or mark as configured. */
2101 vpn
= evpn_create_update_vni(bgp
, vni
);
2103 vty_out(vty
, "%% Failed to create VNI \n");
2107 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
2111 DEFUN (no_bgp_evpn_vni
,
2112 no_bgp_evpn_vni_cmd
,
2113 "no vni (1-16777215)",
2115 "VXLAN Network Identifier\n"
2119 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2120 struct bgpevpn
*vpn
;
2125 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2127 /* Check if we should disallow. */
2128 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2130 vty_out(vty
, "%% Specified VNI does not exist\n");
2133 if (!is_vni_configured(vpn
)) {
2134 vty_out(vty
, "%% Specified VNI is not configured\n");
2138 evpn_delete_vni(bgp
, vpn
);
2142 DEFUN_NOSH (exit_vni
,
2145 "Exit from VNI mode\n")
2147 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2148 vty
->node
= BGP_EVPN_NODE
;
2152 DEFUN (bgp_evpn_vni_rd
,
2153 bgp_evpn_vni_rd_cmd
,
2154 "rd ASN:nn_or_IP-address:nn",
2155 "Route Distinguisher\n"
2156 "ASN:XX or A.B.C.D:XX\n")
2158 struct prefix_rd prd
;
2159 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2160 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2166 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
2168 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2172 /* If same as existing value, there is nothing more to do. */
2173 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
2176 /* Configure or update the RD. */
2177 evpn_configure_rd(bgp
, vpn
, &prd
);
2181 DEFUN (no_bgp_evpn_vni_rd
,
2182 no_bgp_evpn_vni_rd_cmd
,
2183 "no rd ASN:nn_or_IP-address:nn",
2185 "Route Distinguisher\n"
2186 "ASN:XX or A.B.C.D:XX\n")
2188 struct prefix_rd prd
;
2189 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2190 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2196 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
2198 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2202 /* Check if we should disallow. */
2203 if (!is_rd_configured(vpn
)) {
2204 vty_out(vty
, "%% RD is not configured for this VNI\n");
2208 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
2210 "%% RD specified does not match configuration for this VNI\n");
2214 evpn_unconfigure_rd(bgp
, vpn
);
2218 DEFUN (no_bgp_evpn_vni_rd_without_val
,
2219 no_bgp_evpn_vni_rd_without_val_cmd
,
2222 "Route Distinguisher\n")
2224 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2225 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2230 /* Check if we should disallow. */
2231 if (!is_rd_configured(vpn
)) {
2232 vty_out(vty
, "%% RD is not configured for this VNI\n");
2236 evpn_unconfigure_rd(bgp
, vpn
);
2241 * Loop over all extended-communities in the route-target list rtl and
2242 * return 1 if we find ecomtarget
2244 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
2245 struct ecommunity
*ecomtarget
)
2247 struct listnode
*node
, *nnode
;
2248 struct ecommunity
*ecom
;
2250 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
2251 if (ecommunity_match(ecom
, ecomtarget
))
2259 DEFUN (bgp_evpn_vni_rt
,
2260 bgp_evpn_vni_rt_cmd
,
2261 "route-target <both|import|export> RT",
2263 "import and export\n"
2266 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
2268 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2269 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2271 struct ecommunity
*ecomadd
= NULL
;
2276 if (!strcmp(argv
[1]->arg
, "import"))
2277 rt_type
= RT_TYPE_IMPORT
;
2278 else if (!strcmp(argv
[1]->arg
, "export"))
2279 rt_type
= RT_TYPE_EXPORT
;
2280 else if (!strcmp(argv
[1]->arg
, "both"))
2281 rt_type
= RT_TYPE_BOTH
;
2283 vty_out(vty
, "%% Invalid Route Target type\n");
2287 /* Add/update the import route-target */
2288 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
2289 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
2290 ECOMMUNITY_ROUTE_TARGET
, 0);
2291 ecommunity_str(ecomadd
);
2293 vty_out(vty
, "%% Malformed Route Target list\n");
2297 /* Do nothing if we already have this import route-target */
2298 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
2299 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
2302 /* Add/update the export route-target */
2303 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
2304 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
2305 ECOMMUNITY_ROUTE_TARGET
, 0);
2306 ecommunity_str(ecomadd
);
2308 vty_out(vty
, "%% Malformed Route Target list\n");
2312 /* Do nothing if we already have this export route-target */
2313 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
2314 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
2320 DEFUN (no_bgp_evpn_vni_rt
,
2321 no_bgp_evpn_vni_rt_cmd
,
2322 "no route-target <both|import|export> RT",
2325 "import and export\n"
2328 "ASN:XX or A.B.C.D:XX\n")
2330 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2331 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2332 int rt_type
, found_ecomdel
;
2333 struct ecommunity
*ecomdel
= NULL
;
2338 if (!strcmp(argv
[2]->arg
, "import"))
2339 rt_type
= RT_TYPE_IMPORT
;
2340 else if (!strcmp(argv
[2]->arg
, "export"))
2341 rt_type
= RT_TYPE_EXPORT
;
2342 else if (!strcmp(argv
[2]->arg
, "both"))
2343 rt_type
= RT_TYPE_BOTH
;
2345 vty_out(vty
, "%% Invalid Route Target type\n");
2349 /* The user did "no route-target import", check to see if there are any
2350 * import route-targets configured. */
2351 if (rt_type
== RT_TYPE_IMPORT
) {
2352 if (!is_import_rt_configured(vpn
)) {
2354 "%% Import RT is not configured for this VNI\n");
2357 } else if (rt_type
== RT_TYPE_EXPORT
) {
2358 if (!is_export_rt_configured(vpn
)) {
2360 "%% Export RT is not configured for this VNI\n");
2363 } else if (rt_type
== RT_TYPE_BOTH
) {
2364 if (!is_import_rt_configured(vpn
)
2365 && !is_export_rt_configured(vpn
)) {
2367 "%% Import/Export RT is not configured for this VNI\n");
2372 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
2373 ecommunity_str(ecomdel
);
2375 vty_out(vty
, "%% Malformed Route Target list\n");
2379 if (rt_type
== RT_TYPE_IMPORT
) {
2380 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
2382 "%% RT specified does not match configuration for this VNI\n");
2385 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
2386 } else if (rt_type
== RT_TYPE_EXPORT
) {
2387 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
2389 "%% RT specified does not match configuration for this VNI\n");
2392 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
2393 } else if (rt_type
== RT_TYPE_BOTH
) {
2396 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
2397 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
2401 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
2402 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
2406 if (!found_ecomdel
) {
2408 "%% RT specified does not match configuration for this VNI\n");
2416 DEFUN (no_bgp_evpn_vni_rt_without_val
,
2417 no_bgp_evpn_vni_rt_without_val_cmd
,
2418 "no route-target <import|export>",
2424 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2425 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2431 if (!strcmp(argv
[2]->arg
, "import")) {
2432 rt_type
= RT_TYPE_IMPORT
;
2433 } else if (!strcmp(argv
[2]->arg
, "export")) {
2434 rt_type
= RT_TYPE_EXPORT
;
2436 vty_out(vty
, "%% Invalid Route Target type\n");
2440 /* Check if we should disallow. */
2441 if (rt_type
== RT_TYPE_IMPORT
) {
2442 if (!is_import_rt_configured(vpn
)) {
2444 "%% Import RT is not configured for this VNI\n");
2448 if (!is_export_rt_configured(vpn
)) {
2450 "%% Export RT is not configured for this VNI\n");
2455 /* Unconfigure the RT. */
2456 if (rt_type
== RT_TYPE_IMPORT
)
2457 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2459 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2464 * Output EVPN configuration information.
2466 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
2467 safi_t safi
, int *write
)
2469 struct evpn_config_write cfg
;
2474 hash_iterate(bgp
->vnihash
,
2475 (void (*)(struct hash_backet
*,
2476 void *))write_vni_config_for_entry
,
2481 if (bgp
->advertise_all_vni
) {
2482 bgp_config_write_family_header(vty
, afi
, safi
, write
);
2483 vty_out(vty
, " advertise-all-vni\n");
2487 void bgp_ethernetvpn_init(void)
2489 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
2490 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
2491 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
2492 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
2493 install_element(VIEW_NODE
,
2494 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
2495 install_element(VIEW_NODE
,
2496 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
2499 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
2502 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
2503 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
2504 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
2505 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
2506 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
2507 #if defined(HAVE_CUMULUS)
2508 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
2509 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
2511 /* "show bgp evpn" commands. */
2512 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
2513 install_element(VIEW_NODE
, &show_bgp_evpn_vni_num_cmd
);
2514 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
2515 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
2516 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
2517 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
2518 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
2519 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
2520 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
2521 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
2522 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
2524 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
2525 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
2526 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
2527 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
2528 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
2529 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
2530 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
2531 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
2532 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);