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.
49 struct in_addr vtep_ip
;
52 struct evpn_config_write
58 #if defined (HAVE_CUMULUS)
60 display_import_rt (struct vty
*vty
, struct irt_node
*irt
)
63 u_char type
, sub_type
;
74 struct listnode
*node
, *nnode
;
75 struct bgpevpn
*tmp_vpn
;
78 /* TODO: This needs to go into a function */
80 pnt
= (u_char
*)&irt
->rt
.val
;
83 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
88 case ECOMMUNITY_ENCODE_AS
:
89 eas
.as
= (*pnt
++ << 8);
92 eas
.val
= (*pnt
++ << 24);
93 eas
.val
|= (*pnt
++ << 16);
94 eas
.val
|= (*pnt
++ << 8);
97 vty_out (vty
, "Route-target: %u:%u", eas
.as
, eas
.val
);
100 case ECOMMUNITY_ENCODE_IP
:
101 memcpy (&eip
.ip
, pnt
, 4);
103 eip
.val
= (*pnt
++ << 8);
106 vty_out (vty
, "Route-target: %s:%u",
107 inet_ntoa (eip
.ip
), eip
.val
);
110 case ECOMMUNITY_ENCODE_AS4
:
111 eas
.as
= (*pnt
++ << 24);
112 eas
.as
|= (*pnt
++ << 16);
113 eas
.as
|= (*pnt
++ << 8);
116 eas
.val
= (*pnt
++ << 8);
119 vty_out (vty
, "Route-target: %u:%u", eas
.as
, eas
.val
);
126 vty_out (vty
, "%s", VTY_NEWLINE
);
127 vty_out (vty
, "List of VNIs importing routes with this route-target:%s",
130 for (ALL_LIST_ELEMENTS (irt
->vnis
, node
, nnode
, tmp_vpn
))
131 vty_out (vty
, " %u%s", tmp_vpn
->vni
, VTY_NEWLINE
);
135 show_import_rt_entry (struct hash_backet
*backet
, struct vty
*vty
)
137 struct irt_node
*irt
= (struct irt_node
*) backet
->data
;
138 display_import_rt (vty
, irt
);
142 bgp_evpn_show_route_rd_header (struct vty
*vty
, struct bgp_node
*rd_rn
)
149 pnt
= rd_rn
->p
.u
.val
;
151 /* Decode RD type. */
152 type
= decode_rd_type (pnt
);
154 vty_out (vty
, "Route Distinguisher: ");
159 decode_rd_as (pnt
+ 2, &rd_as
);
160 vty_out (vty
, "%u:%d", rd_as
.as
, rd_as
.val
);
164 decode_rd_ip (pnt
+ 2, &rd_ip
);
165 vty_out (vty
, "%s:%d", inet_ntoa (rd_ip
.ip
), rd_ip
.val
);
169 vty_out (vty
, "Unknown RD type");
173 vty_out (vty
, "%s", VTY_NEWLINE
);
177 bgp_evpn_show_route_header (struct vty
*vty
, struct bgp
*bgp
)
179 char ri_header
[] = " Network Next Hop Metric LocPrf Weight Path%s";
181 vty_out (vty
, "BGP table version is 0, local router ID is %s%s",
182 inet_ntoa (bgp
->router_id
), VTY_NEWLINE
);
183 vty_out (vty
, "Status codes: s suppressed, d damped, h history, "
184 "* valid, > best, i - internal%s", VTY_NEWLINE
);
185 vty_out (vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete%s",
187 vty_out (vty
, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]%s",
189 vty_out (vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]%s%s",
190 VTY_NEWLINE
, VTY_NEWLINE
);
191 vty_out (vty
, ri_header
, VTY_NEWLINE
);
195 display_vni (struct vty
*vty
, struct bgpevpn
*vpn
)
197 char buf1
[INET6_ADDRSTRLEN
];
199 struct listnode
*node
, *nnode
;
200 struct ecommunity
*ecom
;
202 vty_out (vty
, "VNI: %d", vpn
->vni
);
203 if (is_vni_live (vpn
))
204 vty_out (vty
, " (known to the kernel)");
205 vty_out (vty
, "%s", VTY_NEWLINE
);
207 vty_out (vty
, " RD: %s%s",
208 prefix_rd2str (&vpn
->prd
, buf1
, RD_ADDRSTRLEN
),
210 vty_out (vty
, " Originator IP: %s%s",
211 inet_ntoa(vpn
->originator_ip
), VTY_NEWLINE
);
213 vty_out (vty
, " Import Route Target:%s", VTY_NEWLINE
);
214 for (ALL_LIST_ELEMENTS (vpn
->import_rtl
, node
, nnode
, ecom
))
216 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
217 vty_out (vty
, " %s%s", ecom_str
, VTY_NEWLINE
);
218 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
221 vty_out (vty
, " Export Route Target:%s", VTY_NEWLINE
);
222 for (ALL_LIST_ELEMENTS (vpn
->export_rtl
, node
, nnode
, ecom
))
224 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
225 vty_out (vty
, " %s%s", ecom_str
, VTY_NEWLINE
);
226 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
231 show_vni_routes (struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
232 struct vty
*vty
, struct in_addr vtep_ip
)
237 u_int32_t prefix_cnt
, path_cnt
;
239 prefix_cnt
= path_cnt
= 0;
241 for (rn
= bgp_table_top (vpn
->route_table
); rn
; rn
= bgp_route_next (rn
))
243 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
246 evp
->prefix
.route_type
!= type
)
251 /* Overall header/legend displayed once. */
254 bgp_evpn_show_route_header (vty
, bgp
);
261 /* For EVPN, the prefix is displayed for each path (to fit in
262 * with code that already exists).
264 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
266 if (vtep_ip
.s_addr
&&
267 !IPV4_ADDR_SAME(&(vtep_ip
), &(ri
->attr
->nexthop
)))
271 route_vty_out (vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, NULL
);
276 vty_out (vty
, "No EVPN prefixes %sexist for this VNI%s",
277 type
? "(of requested type) " : "", VTY_NEWLINE
);
279 vty_out (vty
, "%sDisplayed %u prefixes (%u paths)%s%s",
280 VTY_NEWLINE
, prefix_cnt
, path_cnt
,
281 type
? " (of requested type)" : "", VTY_NEWLINE
);
285 show_vni_routes_hash (struct hash_backet
*backet
, void *arg
)
287 struct bgpevpn
*vpn
= (struct bgpevpn
*) backet
->data
;
288 struct vni_walk_ctx
*wctx
= arg
;
289 struct vty
*vty
= wctx
->vty
;
291 vty_out (vty
, "%sVNI: %d%s%s", VTY_NEWLINE
, vpn
->vni
, VTY_NEWLINE
, VTY_NEWLINE
);
292 show_vni_routes (wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
);
296 show_vni_entry (struct hash_backet
*backet
, struct vty
*vty
)
298 struct bgpevpn
*vpn
= (struct bgpevpn
*) backet
->data
;
300 char buf2
[INET6_ADDRSTRLEN
];
303 struct listnode
*node
, *nnode
;
304 struct ecommunity
*ecom
;
307 if (is_vni_live (vpn
))
310 vty_out(vty
, "%-1s %-10u %-15s %-21s",
311 buf1
, vpn
->vni
, inet_ntoa(vpn
->originator_ip
),
312 prefix_rd2str (&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
314 for (ALL_LIST_ELEMENTS (vpn
->import_rtl
, node
, nnode
, ecom
))
316 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
318 if (listcount(vpn
->import_rtl
) > 1)
319 sprintf (rt_buf
, "%s, ...", ecom_str
);
321 sprintf (rt_buf
, "%s", ecom_str
);
322 vty_out (vty
, " %-25s", rt_buf
);
324 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
328 for (ALL_LIST_ELEMENTS (vpn
->export_rtl
, node
, nnode
, ecom
))
330 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
332 if (listcount(vpn
->export_rtl
) > 1)
333 sprintf (rt_buf
, "%s, ...", ecom_str
);
335 sprintf (rt_buf
, "%s", ecom_str
);
336 vty_out (vty
, " %-25s", rt_buf
);
338 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
341 vty_out (vty
, "%s", VTY_NEWLINE
);
343 #endif /* HAVE_CUMULUS */
346 bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
347 enum bgp_show_type type
, void *output_arg
, int option
,
350 afi_t afi
= AFI_L2VPN
;
352 struct bgp_table
*table
;
359 unsigned long output_count
= 0;
360 unsigned long total_count
= 0;
361 json_object
*json
= NULL
;
362 json_object
*json_nroute
= NULL
;
363 json_object
*json_array
= NULL
;
364 json_object
*json_scode
= NULL
;
365 json_object
*json_ocode
= NULL
;
367 bgp
= bgp_get_default();
370 vty_out (vty
,"No BGP process is configured\n");
375 json_scode
= json_object_new_object();
376 json_ocode
= json_object_new_object();
377 json
= json_object_new_object();
378 json_nroute
= json_object_new_object();
380 json_object_string_add(json_scode
, "suppressed", "s");
381 json_object_string_add(json_scode
, "damped", "d");
382 json_object_string_add(json_scode
, "history", "h");
383 json_object_string_add(json_scode
, "valid", "*");
384 json_object_string_add(json_scode
, "best", ">");
385 json_object_string_add(json_scode
, "internal", "i");
387 json_object_string_add(json_ocode
, "igp", "i");
388 json_object_string_add(json_ocode
, "egp", "e");
389 json_object_string_add(json_ocode
, "incomplete", "?");
392 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
393 rn
= bgp_route_next(rn
)) {
395 continue; /* XXX json TODO */
397 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
400 if ((table
= rn
->info
) != NULL
) {
403 for (rm
= bgp_table_top(table
); rm
;
404 rm
= bgp_route_next(rm
))
405 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
407 if (type
== bgp_show_type_neighbor
) {
408 union sockunion
*su
=
411 if (ri
->peer
->su_remote
== NULL
412 || !sockunion_same(ri
->
426 json_object_string_add
432 json_object_object_add
436 json_object_object_add
444 vty_out(vty
, V4_HEADER_TAG
);
446 SHOW_DISPLAY_OVERLAY
)
447 vty_out(vty
, V4_HEADER_OVERLAY
);
450 "BGP table version is 0, local router ID is %s\n",
451 inet_ntoa(bgp
->router_id
));
453 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
455 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
456 vty_out(vty
, V4_HEADER
);
469 /* Decode RD type. */
470 type
= decode_rd_type(pnt
);
471 /* Decode RD value. */
472 if (type
== RD_TYPE_AS
)
473 decode_rd_as(pnt
+ 2,
475 else if (type
== RD_TYPE_AS4
)
476 decode_rd_as4(pnt
+ 2,
478 else if (type
== RD_TYPE_IP
)
479 decode_rd_ip(pnt
+ 2,
483 if (type
== RD_TYPE_AS
501 json_object_string_add
503 "routeDistinguisher",
507 "Route Distinguisher: ");
508 if (type
== RD_TYPE_AS
)
532 vty_out (vty
, "\n\n");
538 json_object_new_array();
541 if (option
== SHOW_DISPLAY_TAGS
)
542 route_vty_out_tag(vty
, &rm
->p
,
546 else if (option
== SHOW_DISPLAY_OVERLAY
)
547 route_vty_out_overlay(vty
,
552 route_vty_out(vty
, &rm
->p
, ri
,
560 if (output_count
== 0)
561 vty_out (vty
, "No prefixes displayed, %ld exist\n",
564 vty_out (vty
, "\nDisplayed %ld out of %ld total prefixes\n", output_count
, total_count
);
568 DEFUN(show_ip_bgp_l2vpn_evpn
,
569 show_ip_bgp_l2vpn_evpn_cmd
,
570 "show [ip] bgp l2vpn evpn [json]",
571 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
573 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
574 use_json(argc
, argv
));
577 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
578 show_ip_bgp_l2vpn_evpn_rd_cmd
,
579 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn [json]",
585 "Display information for a route distinguisher\n"
586 "VPN Route Distinguisher\n" JSON_STR
)
588 int idx_ext_community
= 0;
590 struct prefix_rd prd
;
592 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
594 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
596 vty_out (vty
, "%% Malformed Route Distinguisher\n");
599 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
600 use_json(argc
, argv
));
603 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
604 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
605 "show [ip] bgp l2vpn evpn all tags",
611 "Display information about all EVPN NLRIs\n"
612 "Display BGP tags for prefixes\n")
614 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
618 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
619 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
620 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn tags",
626 "Display information for a route distinguisher\n"
627 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
629 int idx_ext_community
= 0;
631 struct prefix_rd prd
;
633 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
635 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
637 vty_out (vty
, "%% Malformed Route Distinguisher\n");
640 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
644 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
645 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
646 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
652 "Display information about all EVPN NLRIs\n"
653 "Detailed information on TCP and BGP neighbor connections\n"
654 "Neighbor to display information about\n"
655 "Display routes learned from neighbor\n" JSON_STR
)
661 u_char uj
= use_json(argc
, argv
);
663 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
665 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
668 json_object
*json_no
= NULL
;
669 json_no
= json_object_new_object();
670 json_object_string_add(json_no
, "warning",
671 "Malformed address");
672 vty_out (vty
, "%s\n",
673 json_object_to_json_string(json_no
));
674 json_object_free(json_no
);
676 vty_out (vty
, "Malformed address: %s\n",
677 argv
[idx_ipv4
]->arg
);
681 peer
= peer_lookup(NULL
, &su
);
682 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
684 json_object
*json_no
= NULL
;
685 json_no
= json_object_new_object();
686 json_object_string_add(json_no
, "warning",
687 "No such neighbor or address family");
688 vty_out (vty
, "%s\n",
689 json_object_to_json_string(json_no
));
690 json_object_free(json_no
);
693 "%% No such neighbor or address family\n");
697 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
701 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
702 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
703 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D routes [json]",
709 "Display information for a route distinguisher\n"
710 "VPN Route Distinguisher\n"
711 "Detailed information on TCP and BGP neighbor connections\n"
712 "Neighbor to display information about\n"
713 "Display routes learned from neighbor\n" JSON_STR
)
715 int idx_ext_community
= 0;
720 struct prefix_rd prd
;
721 u_char uj
= use_json(argc
, argv
);
723 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
724 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
726 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
729 json_object
*json_no
= NULL
;
730 json_no
= json_object_new_object();
731 json_object_string_add(json_no
, "warning",
732 "Malformed Route Distinguisher");
733 vty_out (vty
, "%s\n",
734 json_object_to_json_string(json_no
));
735 json_object_free(json_no
);
737 vty_out (vty
,"%% Malformed Route Distinguisher\n");
741 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
744 json_object
*json_no
= NULL
;
745 json_no
= json_object_new_object();
746 json_object_string_add(json_no
, "warning",
747 "Malformed address");
748 vty_out (vty
, "%s\n",
749 json_object_to_json_string(json_no
));
750 json_object_free(json_no
);
752 vty_out (vty
, "Malformed address: %s\n",
753 argv
[idx_ext_community
]->arg
);
757 peer
= peer_lookup(NULL
, &su
);
758 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
760 json_object
*json_no
= NULL
;
761 json_no
= json_object_new_object();
762 json_object_string_add(json_no
, "warning",
763 "No such neighbor or address family");
764 vty_out (vty
, "%s\n",
765 json_object_to_json_string(json_no
));
766 json_object_free(json_no
);
769 "%% No such neighbor or address family\n");
773 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
777 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
778 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
779 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
785 "Display information about all EVPN NLRIs\n"
786 "Detailed information on TCP and BGP neighbor connections\n"
787 "Neighbor to display information about\n"
788 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
794 u_char uj
= use_json(argc
, argv
);
796 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
798 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
801 json_object
*json_no
= NULL
;
802 json_no
= json_object_new_object();
803 json_object_string_add(json_no
, "warning",
804 "Malformed address");
805 vty_out (vty
, "%s\n",
806 json_object_to_json_string(json_no
));
807 json_object_free(json_no
);
809 vty_out (vty
, "Malformed address: %s\n",
810 argv
[idx_ipv4
]->arg
);
813 peer
= peer_lookup(NULL
, &su
);
814 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
816 json_object
*json_no
= NULL
;
817 json_no
= json_object_new_object();
818 json_object_string_add(json_no
, "warning",
819 "No such neighbor or address family");
820 vty_out (vty
, "%s\n",
821 json_object_to_json_string(json_no
));
822 json_object_free(json_no
);
825 "%% No such neighbor or address family\n");
829 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
832 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
833 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
834 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn neighbors A.B.C.D advertised-routes [json]",
840 "Display information for a route distinguisher\n"
841 "VPN Route Distinguisher\n"
842 "Detailed information on TCP and BGP neighbor connections\n"
843 "Neighbor to display information about\n"
844 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
846 int idx_ext_community
= 0;
850 struct prefix_rd prd
;
852 u_char uj
= use_json(argc
, argv
);
854 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
855 argv_find (argv
, argc
, "A.B.C.D", &idx_ipv4
);
857 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
860 json_object
*json_no
= NULL
;
861 json_no
= json_object_new_object();
862 json_object_string_add(json_no
, "warning",
863 "Malformed address");
864 vty_out (vty
, "%s\n",
865 json_object_to_json_string(json_no
));
866 json_object_free(json_no
);
868 vty_out (vty
, "Malformed address: %s\n",
869 argv
[idx_ext_community
]->arg
);
872 peer
= peer_lookup(NULL
, &su
);
873 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
875 json_object
*json_no
= NULL
;
876 json_no
= json_object_new_object();
877 json_object_string_add(json_no
, "warning",
878 "No such neighbor or address family");
879 vty_out (vty
, "%s\n",
880 json_object_to_json_string(json_no
));
881 json_object_free(json_no
);
884 "%% No such neighbor or address family\n");
888 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
891 json_object
*json_no
= NULL
;
892 json_no
= json_object_new_object();
893 json_object_string_add(json_no
, "warning",
894 "Malformed Route Distinguisher");
895 vty_out (vty
, "%s\n",
896 json_object_to_json_string(json_no
));
897 json_object_free(json_no
);
899 vty_out (vty
,"%% Malformed Route Distinguisher\n");
903 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
906 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
907 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
908 "show [ip] bgp l2vpn evpn all overlay",
914 "Display information about all EVPN NLRIs\n"
915 "Display BGP Overlay Information for prefixes\n")
917 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
918 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
922 DEFUN(show_ip_bgp_evpn_rd_overlay
,
923 show_ip_bgp_evpn_rd_overlay_cmd
,
924 "show [ip] bgp l2vpn evpn rd ASN:nn_or_IP-address:nn overlay",
930 "Display information for a route distinguisher\n"
931 "VPN Route Distinguisher\n"
932 "Display BGP Overlay Information for prefixes\n")
934 int idx_ext_community
= 0;
936 struct prefix_rd prd
;
938 argv_find (argv
, argc
, "ASN:nn_or_IP-address:nn", &idx_ext_community
);
940 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
942 vty_out (vty
, "%% Malformed Route Distinguisher\n");
945 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
946 SHOW_DISPLAY_OVERLAY
, use_json(argc
,
950 /* For testing purpose, static route of MPLS-VPN. */
951 DEFUN(evpnrt5_network
,
953 "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]",
954 "Specify a network to announce via BGP\n"
957 "Specify Route Distinguisher\n"
958 "VPN Route Distinguisher\n"
960 "Ethernet Tag Value\n"
963 "Ethernet Segment Identifier\n"
964 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
966 "Gateway IP ( A.B.C.D )\n"
967 "Gateway IPv6 ( X:X::X:X )\n"
968 "Router Mac Ext Comm\n"
969 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
970 "Route-map to modify the attributes\n"
971 "Name of the route map\n")
973 int idx_ipv4_prefixlen
= 1;
974 int idx_ext_community
= 3;
979 int idx_routermac
= 13;
981 return bgp_static_set_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
982 argv
[idx_ipv4_prefixlen
]->arg
,
983 argv
[idx_ext_community
]->arg
,
985 argv
[idx_rmap
] ? argv
[idx_gwip
]->arg
: NULL
,
986 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
987 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
988 argv
[idx_routermac
]->arg
);
991 /* For testing purpose, static route of MPLS-VPN. */
992 DEFUN(no_evpnrt5_network
,
993 no_evpnrt5_network_cmd
,
994 "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>",
996 "Specify a network to announce via BGP\n"
999 "Specify Route Distinguisher\n"
1000 "VPN Route Distinguisher\n"
1002 "Ethernet Tag Value\n"
1005 "Ethernet Segment Identifier\n"
1006 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1007 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1009 int idx_ipv4_prefixlen
= 2;
1010 int idx_ext_community
= 4;
1015 return bgp_static_unset_safi(AFI_L2VPN
, SAFI_EVPN
, vty
,
1016 argv
[idx_ipv4_prefixlen
]->arg
,
1017 argv
[idx_ext_community
]->arg
,
1018 argv
[idx_label
]->arg
, BGP_EVPN_IP_PREFIX_ROUTE
,
1019 argv
[idx_esi
]->arg
, argv
[idx_gwip
]->arg
,
1020 argv
[idx_ethtag
]->arg
);
1023 #if defined(HAVE_CUMULUS)
1025 evpn_rt_delete_auto (struct bgp
*bgp
, struct bgpevpn
*vpn
, struct list
*rtl
)
1027 struct listnode
*node
, *nnode
, *node_to_del
;
1028 struct ecommunity
*ecom
, *ecom_auto
;
1029 struct ecommunity_val eval
;
1031 encode_route_target_as ((bgp
->as
& 0xFFFF), vpn
->vni
, &eval
);
1033 ecom_auto
= ecommunity_new ();
1034 ecommunity_add_val (ecom_auto
, &eval
);
1037 for (ALL_LIST_ELEMENTS (rtl
, node
, nnode
, ecom
))
1039 if (ecommunity_match (ecom
, ecom_auto
))
1041 ecommunity_free (&ecom
);
1047 list_delete_node(rtl
, node_to_del
);
1049 ecommunity_free(&ecom_auto
);
1053 evpn_import_rt_delete_auto (struct bgp
*bgp
, struct bgpevpn
*vpn
)
1055 evpn_rt_delete_auto (bgp
, vpn
, vpn
->import_rtl
);
1059 evpn_export_rt_delete_auto (struct bgp
*bgp
, struct bgpevpn
*vpn
)
1061 evpn_rt_delete_auto (bgp
, vpn
, vpn
->export_rtl
);
1065 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1066 * check that this is a change.
1069 evpn_configure_import_rt (struct bgp
*bgp
, struct bgpevpn
*vpn
,
1070 struct ecommunity
*ecomadd
)
1072 /* If the VNI is "live", we need to uninstall routes using the current
1073 * import RT(s) first before we update the import RT, and subsequently
1076 if (is_vni_live (vpn
))
1077 bgp_evpn_uninstall_routes (bgp
, vpn
);
1079 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1080 bgp_evpn_unmap_vni_from_its_rts (bgp
, vpn
);
1082 /* If the auto route-target is in use we must remove it */
1083 evpn_import_rt_delete_auto(bgp
, vpn
);
1085 /* Add new RT and rebuild the RT to VNI mapping */
1086 listnode_add_sort (vpn
->import_rtl
, ecomadd
);
1088 SET_FLAG (vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1089 bgp_evpn_map_vni_to_its_rts (bgp
, vpn
);
1091 /* Install routes that match new import RT */
1092 if (is_vni_live (vpn
))
1093 bgp_evpn_install_routes (bgp
, vpn
);
1097 * Unconfigure Import RT(s) for a VNI (vty handler).
1100 evpn_unconfigure_import_rt (struct bgp
*bgp
, struct bgpevpn
*vpn
,
1101 struct ecommunity
*ecomdel
)
1103 struct listnode
*node
, *nnode
, *node_to_del
;
1104 struct ecommunity
*ecom
;
1106 /* Along the lines of "configure" except we have to reset to the
1109 if (is_vni_live (vpn
))
1110 bgp_evpn_uninstall_routes (bgp
, vpn
);
1112 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1113 bgp_evpn_unmap_vni_from_its_rts (bgp
, vpn
);
1115 /* Delete all import RTs */
1116 if (ecomdel
== NULL
)
1118 for (ALL_LIST_ELEMENTS (vpn
->import_rtl
, node
, nnode
, ecom
))
1119 ecommunity_free (&ecom
);
1121 list_delete_all_node(vpn
->import_rtl
);
1124 /* Delete a specific import RT */
1129 for (ALL_LIST_ELEMENTS (vpn
->import_rtl
, node
, nnode
, ecom
))
1131 if (ecommunity_match (ecom
, ecomdel
))
1133 ecommunity_free (&ecom
);
1140 list_delete_node(vpn
->import_rtl
, node_to_del
);
1143 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1144 if (list_isempty(vpn
->import_rtl
))
1146 UNSET_FLAG (vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1147 bgp_evpn_derive_auto_rt_import (bgp
, vpn
);
1149 /* Rebuild the RT to VNI mapping */
1151 bgp_evpn_map_vni_to_its_rts (bgp
, vpn
);
1153 /* Install routes that match new import RT */
1154 if (is_vni_live (vpn
))
1155 bgp_evpn_install_routes (bgp
, vpn
);
1159 * Configure the Export RT for a VNI (vty handler). Caller expected to
1160 * check that this is a change. Note that only a single export RT is
1161 * allowed for a VNI and any change to configuration is implemented as
1162 * a "replace" (similar to other configuration).
1165 evpn_configure_export_rt (struct bgp
*bgp
, struct bgpevpn
*vpn
,
1166 struct ecommunity
*ecomadd
)
1168 /* If the auto route-target is in use we must remove it */
1169 evpn_export_rt_delete_auto (bgp
, vpn
);
1171 listnode_add_sort (vpn
->export_rtl
, ecomadd
);
1172 SET_FLAG (vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1174 if (is_vni_live (vpn
))
1175 bgp_evpn_handle_export_rt_change (bgp
, vpn
);
1179 * Unconfigure the Export RT for a VNI (vty handler)
1182 evpn_unconfigure_export_rt (struct bgp
*bgp
, struct bgpevpn
*vpn
,
1183 struct ecommunity
*ecomdel
)
1185 struct listnode
*node
, *nnode
, *node_to_del
;
1186 struct ecommunity
*ecom
;
1188 /* Delete all export RTs */
1189 if (ecomdel
== NULL
)
1191 /* Reset to default and process all routes. */
1192 for (ALL_LIST_ELEMENTS (vpn
->export_rtl
, node
, nnode
, ecom
))
1193 ecommunity_free (&ecom
);
1195 list_delete_all_node(vpn
->export_rtl
);
1198 /* Delete a specific export RT */
1203 for (ALL_LIST_ELEMENTS (vpn
->export_rtl
, node
, nnode
, ecom
))
1205 if (ecommunity_match (ecom
, ecomdel
))
1207 ecommunity_free (&ecom
);
1214 list_delete_node(vpn
->export_rtl
, node_to_del
);
1217 if (list_isempty(vpn
->export_rtl
))
1219 UNSET_FLAG (vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1220 bgp_evpn_derive_auto_rt_export (bgp
, vpn
);
1223 if (is_vni_live (vpn
))
1224 bgp_evpn_handle_export_rt_change (bgp
, vpn
);
1228 * Configure RD for a VNI (vty handler)
1231 evpn_configure_rd (struct bgp
*bgp
, struct bgpevpn
*vpn
,
1232 struct prefix_rd
*rd
)
1234 /* If the VNI is "live", we need to delete and withdraw this VNI's
1235 * local routes with the prior RD first. Then, after updating RD,
1236 * need to re-advertise.
1238 if (is_vni_live (vpn
))
1239 bgp_evpn_handle_rd_change (bgp
, vpn
, 1);
1242 memcpy(&vpn
->prd
, rd
, sizeof (struct prefix_rd
));
1243 SET_FLAG (vpn
->flags
, VNI_FLAG_RD_CFGD
);
1245 if (is_vni_live (vpn
))
1246 bgp_evpn_handle_rd_change (bgp
, vpn
, 0);
1250 * Unconfigure RD for a VNI (vty handler)
1253 evpn_unconfigure_rd (struct bgp
*bgp
, struct bgpevpn
*vpn
)
1255 /* If the VNI is "live", we need to delete and withdraw this VNI's
1256 * local routes with the prior RD first. Then, after resetting RD
1257 * to automatic value, need to re-advertise.
1259 if (is_vni_live (vpn
))
1260 bgp_evpn_handle_rd_change (bgp
, vpn
, 1);
1262 /* reset RD to default */
1263 bgp_evpn_derive_auto_rd (bgp
, vpn
);
1265 if (is_vni_live (vpn
))
1266 bgp_evpn_handle_rd_change (bgp
, vpn
, 0);
1270 * Create VNI, if not already present (VTY handler). Mark as configured.
1272 static struct bgpevpn
*
1273 evpn_create_update_vni (struct bgp
*bgp
, vni_t vni
)
1275 struct bgpevpn
*vpn
;
1280 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
1283 vpn
= bgp_evpn_new (bgp
, vni
, bgp
->router_id
);
1286 zlog_err ("%u: Failed to allocate VNI entry for VNI %u - at Config",
1292 /* Mark as configured. */
1293 SET_FLAG (vpn
->flags
, VNI_FLAG_CFGD
);
1298 * Delete VNI. If VNI does not exist in the system (i.e., just
1299 * configuration), all that is needed is to free it. Otherwise,
1300 * any parameters configured for the VNI need to be reset (with
1301 * appropriate action) and the VNI marked as unconfigured; the
1302 * VNI will continue to exist, purely as a "learnt" entity.
1305 evpn_delete_vni (struct bgp
*bgp
, struct bgpevpn
*vpn
)
1307 assert (bgp
->vnihash
);
1309 if (!is_vni_live (vpn
))
1311 bgp_evpn_free (bgp
, vpn
);
1315 /* We need to take the unconfigure action for each parameter of this VNI
1316 * that is configured. Some optimization is possible, but not worth the
1317 * additional code for an operation that should be pretty rare.
1319 UNSET_FLAG (vpn
->flags
, VNI_FLAG_CFGD
);
1321 /* First, deal with the export side - RD and export RT changes. */
1322 if (is_rd_configured (vpn
))
1323 evpn_unconfigure_rd (bgp
, vpn
);
1324 if (is_export_rt_configured (vpn
))
1325 evpn_unconfigure_export_rt (bgp
, vpn
, NULL
);
1327 /* Next, deal with the import side. */
1328 if (is_import_rt_configured (vpn
))
1329 evpn_unconfigure_import_rt (bgp
, vpn
, NULL
);
1335 * Display import RT mapping to VNIs (vty handler)
1338 evpn_show_import_rts (struct vty
*vty
, struct bgp
*bgp
)
1340 hash_iterate (bgp
->import_rt_hash
,
1341 (void (*) (struct hash_backet
*, void *))
1342 show_import_rt_entry
, vty
);
1346 * Display EVPN routes for all VNIs - vty handler.
1349 evpn_show_routes_vni_all (struct vty
*vty
, struct bgp
*bgp
, struct in_addr vtep_ip
)
1352 struct vni_walk_ctx wctx
;
1354 num_vnis
= hashcount(bgp
->vnihash
);
1357 memset (&wctx
, 0, sizeof (struct vni_walk_ctx
));
1360 wctx
.vtep_ip
= vtep_ip
;
1361 hash_iterate (bgp
->vnihash
,
1362 (void (*) (struct hash_backet
*, void *))
1363 show_vni_routes_hash
, &wctx
);
1367 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1370 evpn_show_route_vni_multicast (struct vty
*vty
, struct bgp
*bgp
,
1371 vni_t vni
, struct in_addr orig_ip
)
1373 struct bgpevpn
*vpn
;
1374 struct prefix_evpn p
;
1375 struct bgp_node
*rn
;
1376 struct bgp_info
*ri
;
1377 u_int32_t path_cnt
= 0;
1385 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
1388 vty_out (vty
, "VNI not found%s", VTY_NEWLINE
);
1392 /* See if route exists. */
1393 build_evpn_type3_prefix (&p
, orig_ip
);
1394 rn
= bgp_node_lookup (vpn
->route_table
, (struct prefix
*)&p
);
1395 if (!rn
|| !rn
->info
)
1397 vty_out (vty
, "%% Network not in table%s", VTY_NEWLINE
);
1401 /* Prefix and num paths displayed once per prefix. */
1402 route_vty_out_detail_header (vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1404 /* Display each path for this prefix. */
1405 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1407 route_vty_out_detail (vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1411 vty_out (vty
, "%sDisplayed %u paths for requested prefix%s",
1412 VTY_NEWLINE
, path_cnt
, VTY_NEWLINE
);
1416 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1417 * By definition, only matching type-2 route will be displayed.
1420 evpn_show_route_vni_macip (struct vty
*vty
, struct bgp
*bgp
,
1421 vni_t vni
, struct ethaddr
*mac
,
1424 struct bgpevpn
*vpn
;
1425 struct prefix_evpn p
;
1426 struct bgp_node
*rn
;
1427 struct bgp_info
*ri
;
1428 u_int32_t path_cnt
= 0;
1436 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
1439 vty_out (vty
, "VNI not found%s", VTY_NEWLINE
);
1443 /* See if route exists. Look for both non-sticky and sticky. */
1444 build_evpn_type2_prefix (&p
, mac
, ip
);
1445 rn
= bgp_node_lookup (vpn
->route_table
, (struct prefix
*)&p
);
1446 if (!rn
|| !rn
->info
)
1448 vty_out (vty
, "%% Network not in table%s", VTY_NEWLINE
);
1452 /* Prefix and num paths displayed once per prefix. */
1453 route_vty_out_detail_header (vty
, bgp
, rn
, NULL
, afi
, safi
, NULL
);
1455 /* Display each path for this prefix. */
1456 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1458 route_vty_out_detail (vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1462 vty_out (vty
, "%sDisplayed %u paths for requested prefix%s",
1463 VTY_NEWLINE
, path_cnt
, VTY_NEWLINE
);
1467 * Display EVPN routes for a VNI - vty handler.
1468 * If 'type' is non-zero, only routes matching that type are shown.
1469 * If the vtep_ip is non zero, only routes behind that vtep are shown
1472 evpn_show_routes_vni (struct vty
*vty
, struct bgp
*bgp
,
1473 vni_t vni
, int type
, struct in_addr vtep_ip
)
1475 struct bgpevpn
*vpn
;
1478 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
1481 vty_out (vty
, "VNI not found%s", VTY_NEWLINE
);
1485 /* Walk this VNI's route table and display appropriate routes. */
1486 show_vni_routes (bgp
, vpn
, type
, vty
, vtep_ip
);
1490 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1491 * IP (vty handler). By definition, only matching type-2 route will be
1495 evpn_show_route_rd_macip (struct vty
*vty
, struct bgp
*bgp
,
1496 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1499 struct prefix_evpn p
;
1500 struct bgp_node
*rn
;
1501 struct bgp_info
*ri
;
1504 u_int32_t path_cnt
= 0;
1509 /* See if route exists. Look for both non-sticky and sticky. */
1510 build_evpn_type2_prefix (&p
, mac
, ip
);
1511 rn
= bgp_afi_node_lookup (bgp
->rib
[afi
][safi
], afi
, safi
,
1512 (struct prefix
*)&p
, prd
);
1513 if (!rn
|| !rn
->info
)
1515 vty_out (vty
, "%% Network not in table%s", VTY_NEWLINE
);
1519 /* Prefix and num paths displayed once per prefix. */
1520 route_vty_out_detail_header (vty
, bgp
, rn
, prd
, afi
, safi
, NULL
);
1522 /* Display each path for this prefix. */
1523 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1525 route_vty_out_detail (vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1529 vty_out (vty
, "%sDisplayed %u paths for requested prefix%s",
1530 VTY_NEWLINE
, path_cnt
, VTY_NEWLINE
);
1534 * Display BGP EVPN routing table -- for specific RD (vty handler)
1535 * If 'type' is non-zero, only routes matching that type are shown.
1538 evpn_show_route_rd (struct vty
*vty
, struct bgp
*bgp
,
1539 struct prefix_rd
*prd
, int type
)
1541 struct bgp_node
*rd_rn
;
1542 struct bgp_table
*table
;
1543 struct bgp_node
*rn
;
1544 struct bgp_info
*ri
;
1548 u_int32_t prefix_cnt
, path_cnt
;
1552 prefix_cnt
= path_cnt
= 0;
1554 rd_rn
= bgp_node_lookup (bgp
->rib
[afi
][safi
], (struct prefix
*) prd
);
1557 table
= (struct bgp_table
*)rd_rn
->info
;
1561 /* Display all prefixes with this RD. */
1562 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
1564 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1567 evp
->prefix
.route_type
!= type
)
1572 /* RD header and legend - once overall. */
1575 vty_out (vty
, "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:"
1576 "[MAC]%s", VTY_NEWLINE
);
1577 vty_out (vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:"
1578 "[OrigIP]%s%s", VTY_NEWLINE
, VTY_NEWLINE
);
1582 /* Prefix and num paths displayed once per prefix. */
1583 route_vty_out_detail_header (vty
, bgp
, rn
, prd
, afi
, safi
, NULL
);
1588 /* Display each path for this prefix. */
1589 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1591 route_vty_out_detail (vty
, bgp
, &rn
->p
, ri
, afi
, safi
, NULL
);
1596 if (prefix_cnt
== 0)
1597 vty_out (vty
, "No prefixes exist with this RD%s%s",
1598 type
? " (of requested type)" : "", VTY_NEWLINE
);
1600 vty_out (vty
, "%sDisplayed %u prefixes (%u paths) with this RD%s%s",
1601 VTY_NEWLINE
, prefix_cnt
, path_cnt
,
1602 type
? " (of requested type)" : "", VTY_NEWLINE
);
1606 * Display BGP EVPN routing table - all routes (vty handler).
1607 * If 'type' is non-zero, only routes matching that type are shown.
1610 evpn_show_all_routes (struct vty
*vty
, struct bgp
*bgp
, int type
)
1612 struct bgp_node
*rd_rn
;
1613 struct bgp_table
*table
;
1614 struct bgp_node
*rn
;
1615 struct bgp_info
*ri
;
1620 u_int32_t prefix_cnt
, path_cnt
;
1624 prefix_cnt
= path_cnt
= 0;
1626 /* EVPN routing table is a 2-level table with the first level being
1629 for (rd_rn
= bgp_table_top (bgp
->rib
[afi
][safi
]); rd_rn
;
1630 rd_rn
= bgp_route_next (rd_rn
))
1632 table
= (struct bgp_table
*)rd_rn
->info
;
1638 /* Display all prefixes for an RD */
1639 for (rn
= bgp_table_top (table
); rn
; rn
= bgp_route_next (rn
))
1641 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1644 evp
->prefix
.route_type
!= type
)
1649 /* Overall header/legend displayed once. */
1652 bgp_evpn_show_route_header (vty
, bgp
);
1656 /* RD header - per RD. */
1659 bgp_evpn_show_route_rd_header (vty
, rd_rn
);
1666 /* For EVPN, the prefix is displayed for each path (to fit in
1667 * with code that already exists).
1669 for (ri
= rn
->info
; ri
; ri
= ri
->next
)
1672 route_vty_out (vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, NULL
);
1677 if (prefix_cnt
== 0)
1678 vty_out (vty
, "No EVPN prefixes %sexist%s",
1679 type
? "(of requested type) " : "", VTY_NEWLINE
);
1681 vty_out (vty
, "%sDisplayed %u prefixes (%u paths)%s%s",
1682 VTY_NEWLINE
, prefix_cnt
, path_cnt
,
1683 type
? " (of requested type)" : "", VTY_NEWLINE
);
1687 * Display specified VNI (vty handler)
1690 evpn_show_vni (struct vty
*vty
, struct bgp
*bgp
, vni_t vni
)
1692 struct bgpevpn
*vpn
;
1694 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
1697 vty_out (vty
, "VNI not found%s", VTY_NEWLINE
);
1701 display_vni (vty
, vpn
);
1705 * Display a VNI (upon user query).
1708 evpn_show_all_vnis (struct vty
*vty
, struct bgp
*bgp
)
1712 num_vnis
= hashcount(bgp
->vnihash
);
1715 vty_out(vty
, "Number of VNIs: %u%s",
1716 num_vnis
, VTY_NEWLINE
);
1717 vty_out(vty
, "Flags: * - Kernel %s", VTY_NEWLINE
);
1718 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s%s",
1719 "VNI", "Orig IP", "RD", "Import RT", "Export RT", VTY_NEWLINE
);
1720 hash_iterate (bgp
->vnihash
,
1721 (void (*) (struct hash_backet
*, void *))
1722 show_vni_entry
, vty
);
1726 * EVPN (VNI advertisement) enabled. Register with zebra.
1729 evpn_set_advertise_all_vni (struct bgp
*bgp
)
1731 bgp
->advertise_all_vni
= 1;
1732 bgp_zebra_advertise_all_vni (bgp
, bgp
->advertise_all_vni
);
1736 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
1737 * cache, EVPN routes (delete and withdraw from peers).
1740 evpn_unset_advertise_all_vni (struct bgp
*bgp
)
1742 bgp
->advertise_all_vni
= 0;
1743 bgp_zebra_advertise_all_vni (bgp
, bgp
->advertise_all_vni
);
1744 bgp_evpn_cleanup_on_disable (bgp
);
1746 #endif /* HAVE_CUMULUS */
1749 write_vni_config (struct vty
*vty
, struct bgpevpn
*vpn
, int *write
)
1751 char buf1
[INET6_ADDRSTRLEN
];
1752 afi_t afi
= AFI_L2VPN
;
1753 safi_t safi
= SAFI_EVPN
;
1755 struct listnode
*node
, *nnode
;
1756 struct ecommunity
*ecom
;
1758 if (is_vni_configured (vpn
))
1760 bgp_config_write_family_header (vty
, afi
, safi
, write
);
1761 vty_out (vty
, " vni %d%s", vpn
->vni
, VTY_NEWLINE
);
1762 if (is_rd_configured (vpn
))
1763 vty_out (vty
, " rd %s%s",
1764 prefix_rd2str (&vpn
->prd
, buf1
, RD_ADDRSTRLEN
),
1767 if (is_import_rt_configured (vpn
))
1769 for (ALL_LIST_ELEMENTS (vpn
->import_rtl
, node
, nnode
, ecom
))
1771 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1772 vty_out (vty
, " route-target import %s%s", ecom_str
, VTY_NEWLINE
);
1773 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
1777 if (is_export_rt_configured (vpn
))
1779 for (ALL_LIST_ELEMENTS (vpn
->export_rtl
, node
, nnode
, ecom
))
1781 ecom_str
= ecommunity_ecom2str (ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1782 vty_out (vty
, " route-target export %s%s", ecom_str
, VTY_NEWLINE
);
1783 XFREE (MTYPE_ECOMMUNITY_STR
, ecom_str
);
1787 vty_out (vty
, " exit-vni%s", VTY_NEWLINE
);
1792 write_vni_config_for_entry (struct hash_backet
*backet
,
1793 struct evpn_config_write
*cfg
)
1795 struct bgpevpn
*vpn
= (struct bgpevpn
*) backet
->data
;
1796 write_vni_config (cfg
->vty
, vpn
, &cfg
->write
);
1799 #if defined (HAVE_CUMULUS)
1800 DEFUN (bgp_evpn_advertise_all_vni
,
1801 bgp_evpn_advertise_all_vni_cmd
,
1802 "advertise-all-vni",
1803 "Advertise All local VNIs\n")
1805 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1809 evpn_set_advertise_all_vni (bgp
);
1813 DEFUN (no_bgp_evpn_advertise_all_vni
,
1814 no_bgp_evpn_advertise_all_vni_cmd
,
1815 "no advertise-all-vni",
1817 "Advertise All local VNIs\n")
1819 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
1823 evpn_unset_advertise_all_vni (bgp
);
1827 DEFUN (show_bgp_evpn_vni
,
1828 show_bgp_evpn_vni_cmd
,
1829 "show bgp evpn vni",
1837 bgp
= bgp_get_default();
1841 vty_out (vty
, "Advertise All VNI flag: %s%s",
1842 bgp
->advertise_all_vni
? "Enabled" : "Disabled", VTY_NEWLINE
);
1844 evpn_show_all_vnis (vty
, bgp
);
1848 DEFUN (show_bgp_evpn_vni_num
,
1849 show_bgp_evpn_vni_num_cmd
,
1850 "show bgp evpn vni (1-16777215)",
1853 "Address family modifier\n"
1860 bgp
= bgp_get_default();
1864 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[4]->arg
, 1, VNI_MAX
);
1866 evpn_show_vni (vty
, bgp
, vni
);
1870 /* `show bgp evpn summary' commands. */
1871 DEFUN (show_bgp_evpn_summary
,
1872 show_bgp_evpn_summary_cmd
,
1873 "show bgp evpn summary [json]",
1877 "Summary of BGP neighbor status\n"
1878 "JavaScript Object Notation\n")
1880 u_char uj
= use_json(argc
, argv
);
1881 return bgp_show_summary_vty (vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1884 /* Show bgp evpn route */
1885 DEFUN (show_bgp_evpn_route
,
1886 show_bgp_evpn_route_cmd
,
1887 "show bgp evpn route [type <macip|multicast>]",
1890 "Address Family Modifier\n"
1891 "Display EVPN route information\n"
1892 "Specify Route type\n"
1893 "MAC-IP (Type-2) route\n"
1894 "Multicast (Type-3) route\n")
1899 bgp
= bgp_get_default();
1905 if (strncmp (argv
[5]->arg
, "ma", 2) == 0)
1906 type
= BGP_EVPN_MAC_IP_ROUTE
;
1907 else if (strncmp (argv
[5]->arg
, "mu", 2) == 0)
1908 type
= BGP_EVPN_IMET_ROUTE
;
1913 evpn_show_all_routes (vty
, bgp
, type
);
1917 DEFUN (show_bgp_evpn_route_rd
,
1918 show_bgp_evpn_route_rd_cmd
,
1919 "show bgp evpn route rd ASN:nn_or_IP-address:nn [type <macip|multicast>]",
1922 "Address Family Modifier\n"
1923 "Display EVPN route information\n"
1924 "Route Distinguisher\n"
1925 "ASN:XX or A.B.C.D:XX\n"
1926 "Specify Route type\n"
1927 "MAC-IP (Type-2) route\n"
1928 "Multicast (Type-3) route\n")
1932 struct prefix_rd prd
;
1935 bgp
= bgp_get_default();
1939 ret
= str2prefix_rd (argv
[5]->arg
, &prd
);
1942 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
1948 if (strncmp (argv
[7]->arg
, "ma", 2) == 0)
1949 type
= BGP_EVPN_MAC_IP_ROUTE
;
1950 else if (strncmp (argv
[7]->arg
, "mu", 2) == 0)
1951 type
= BGP_EVPN_IMET_ROUTE
;
1956 evpn_show_route_rd (vty
, bgp
, &prd
, type
);
1960 DEFUN (show_bgp_evpn_route_rd_macip
,
1961 show_bgp_evpn_route_rd_macip_cmd
,
1962 "show bgp evpn route rd ASN:nn_or_IP-address:nn mac WORD [ip WORD]",
1965 "Address Family Modifier\n"
1966 "Display EVPN route information\n"
1967 "Route Distinguisher\n"
1968 "ASN:XX or A.B.C.D:XX\n"
1970 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
1972 "IP address (IPv4 or IPv6)\n")
1976 struct prefix_rd prd
;
1980 bgp
= bgp_get_default();
1984 ret
= str2prefix_rd (argv
[5]->arg
, &prd
);
1987 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
1990 if (!prefix_str2mac (argv
[7]->arg
, &mac
))
1992 vty_out (vty
, "%% Malformed MAC address%s", VTY_NEWLINE
);
1995 memset (&ip
, 0, sizeof (ip
));
1996 if (argc
== 10 && argv
[9]->arg
!= NULL
)
1998 if (str2ipaddr (argv
[9]->arg
, &ip
) != 0)
2000 vty_out (vty
, "%% Malformed IP address%s", VTY_NEWLINE
);
2005 evpn_show_route_rd_macip (vty
, bgp
, &prd
, &mac
, &ip
);
2009 DEFUN (show_bgp_evpn_route_vni
,
2010 show_bgp_evpn_route_vni_cmd
,
2011 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
2014 "Address Family Modifier\n"
2015 "Display EVPN route information\n"
2016 "VXLAN Network Identifier\n"
2018 "Specify Route type\n"
2019 "MAC-IP (Type-2) route\n"
2020 "Multicast (Type-3) route\n"
2022 "Remote VTEP IP address\n")
2026 struct in_addr vtep_ip
;
2029 bgp
= bgp_get_default();
2035 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[5]->arg
, 1, VNI_MAX
);
2037 if (argc
== 8 && argv
[6]->arg
)
2039 if (strncmp (argv
[6]->arg
, "type", 4) == 0)
2041 if (strncmp (argv
[7]->arg
, "ma", 2) == 0)
2042 type
= BGP_EVPN_MAC_IP_ROUTE
;
2043 else if (strncmp (argv
[7]->arg
, "mu", 2) == 0)
2044 type
= BGP_EVPN_IMET_ROUTE
;
2048 else if (strncmp (argv
[6]->arg
, "vtep", 4) == 0)
2050 if (!inet_aton (argv
[7]->arg
, &vtep_ip
))
2052 vty_out (vty
, "%% Malformed VTEP IP address%s", VTY_NEWLINE
);
2060 evpn_show_routes_vni (vty
, bgp
, vni
, type
, vtep_ip
);
2064 DEFUN (show_bgp_evpn_route_vni_macip
,
2065 show_bgp_evpn_route_vni_macip_cmd
,
2066 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
2069 "Address Family Modifier\n"
2070 "Display EVPN route information\n"
2071 "VXLAN Network Identifier\n"
2074 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2076 "IP address (IPv4 or IPv6)\n")
2083 bgp
= bgp_get_default();
2087 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[5]->arg
, 1, VNI_MAX
);
2088 if (!prefix_str2mac (argv
[7]->arg
, &mac
))
2090 vty_out (vty
, "%% Malformed MAC address%s", VTY_NEWLINE
);
2093 memset (&ip
, 0, sizeof (ip
));
2094 if (argc
== 10 && argv
[9]->arg
!= NULL
)
2096 if (str2ipaddr (argv
[9]->arg
, &ip
) != 0)
2098 vty_out (vty
, "%% Malformed IP address%s", VTY_NEWLINE
);
2103 evpn_show_route_vni_macip (vty
, bgp
, vni
, &mac
, &ip
);
2107 DEFUN (show_bgp_evpn_route_vni_multicast
,
2108 show_bgp_evpn_route_vni_multicast_cmd
,
2109 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
2112 "Address Family Modifier\n"
2113 "Display EVPN route information\n"
2114 "VXLAN Network Identifier\n"
2116 "Multicast (Type-3) route\n"
2117 "Originating Router IP address\n")
2122 struct in_addr orig_ip
;
2124 bgp
= bgp_get_default();
2128 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[5]->arg
, 1, VNI_MAX
);
2129 ret
= inet_aton (argv
[7]->arg
, &orig_ip
);
2132 vty_out (vty
, "%% Malformed Originating Router IP address%s", VTY_NEWLINE
);
2136 evpn_show_route_vni_multicast (vty
, bgp
, vni
, orig_ip
);
2140 DEFUN (show_bgp_evpn_route_vni_all
,
2141 show_bgp_evpn_route_vni_all_cmd
,
2142 "show bgp evpn route vni all [vtep A.B.C.D]",
2145 "Address Family Modifier\n"
2146 "Display EVPN route information\n"
2147 "VXLAN Network Identifier\n"
2150 "Remote VTEP IP address\n")
2153 struct in_addr vtep_ip
;
2155 bgp
= bgp_get_default();
2160 if (argc
== 8 && argv
[7]->arg
)
2162 if (!inet_aton (argv
[7]->arg
, &vtep_ip
))
2164 vty_out (vty
, "%% Malformed VTEP IP address%s", VTY_NEWLINE
);
2169 evpn_show_routes_vni_all (vty
, bgp
, vtep_ip
);
2173 DEFUN (show_bgp_evpn_import_rt
,
2174 show_bgp_evpn_import_rt_cmd
,
2175 "show bgp evpn import-rt",
2178 "Address family modifier\n"
2179 "Show import route target\n")
2183 bgp
= bgp_get_default();
2187 evpn_show_import_rts (vty
, bgp
);
2191 DEFUN_NOSH (bgp_evpn_vni
,
2194 "VXLAN Network Identifier\n"
2198 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2199 struct bgpevpn
*vpn
;
2204 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[1]->arg
, 1, VNI_MAX
);
2206 /* Create VNI, or mark as configured. */
2207 vpn
= evpn_create_update_vni (bgp
, vni
);
2210 vty_out (vty
, "%% Failed to create VNI %s", VTY_NEWLINE
);
2214 VTY_PUSH_CONTEXT_SUB (BGP_EVPN_VNI_NODE
, vpn
);
2218 DEFUN (no_bgp_evpn_vni
,
2219 no_bgp_evpn_vni_cmd
,
2220 "no vni (1-16777215)",
2222 "VXLAN Network Identifier\n"
2226 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2227 struct bgpevpn
*vpn
;
2232 VTY_GET_INTEGER_RANGE ("VNI", vni
, argv
[2]->arg
, 1, VNI_MAX
);
2234 /* Check if we should disallow. */
2235 vpn
= bgp_evpn_lookup_vni (bgp
, vni
);
2238 vty_out (vty
, "%% Specified VNI does not exist%s", VTY_NEWLINE
);
2241 if (!is_vni_configured (vpn
))
2243 vty_out (vty
, "%% Specified VNI is not configured%s", VTY_NEWLINE
);
2247 evpn_delete_vni (bgp
, vpn
);
2251 DEFUN_NOSH (exit_vni
,
2254 "Exit from VNI mode\n")
2256 if (vty
->node
== BGP_EVPN_VNI_NODE
)
2257 vty
->node
= BGP_EVPN_NODE
;
2261 DEFUN (bgp_evpn_vni_rd
,
2262 bgp_evpn_vni_rd_cmd
,
2263 "rd ASN:nn_or_IP-address:nn",
2264 "Route Distinguisher\n"
2265 "ASN:XX or A.B.C.D:XX\n")
2267 struct prefix_rd prd
;
2268 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2269 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2275 ret
= str2prefix_rd (argv
[1]->arg
, &prd
);
2278 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
2282 /* If same as existing value, there is nothing more to do. */
2283 if (bgp_evpn_rd_matches_existing (vpn
, &prd
))
2286 /* Configure or update the RD. */
2287 evpn_configure_rd (bgp
, vpn
, &prd
);
2291 DEFUN (no_bgp_evpn_vni_rd
,
2292 no_bgp_evpn_vni_rd_cmd
,
2293 "no rd ASN:nn_or_IP-address:nn",
2295 "Route Distinguisher\n"
2296 "ASN:XX or A.B.C.D:XX\n")
2298 struct prefix_rd prd
;
2299 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2300 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2306 ret
= str2prefix_rd (argv
[2]->arg
, &prd
);
2309 vty_out (vty
, "%% Malformed Route Distinguisher%s", VTY_NEWLINE
);
2313 /* Check if we should disallow. */
2314 if (!is_rd_configured (vpn
))
2316 vty_out (vty
, "%% RD is not configured for this VNI%s", VTY_NEWLINE
);
2320 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
))
2322 vty_out (vty
, "%% RD specified does not match configuration for this VNI%s", VTY_NEWLINE
);
2326 evpn_unconfigure_rd (bgp
, vpn
);
2330 DEFUN (no_bgp_evpn_vni_rd_without_val
,
2331 no_bgp_evpn_vni_rd_without_val_cmd
,
2334 "Route Distinguisher\n")
2336 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2337 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2342 /* Check if we should disallow. */
2343 if (!is_rd_configured (vpn
))
2345 vty_out (vty
, "%% RD is not configured for this VNI%s", VTY_NEWLINE
);
2349 evpn_unconfigure_rd (bgp
, vpn
);
2354 * Loop over all extended-communities in the route-target list rtl and
2355 * return 1 if we find ecomtarget
2358 bgp_evpn_rt_matches_existing (struct list
*rtl
,
2359 struct ecommunity
*ecomtarget
)
2361 struct listnode
*node
, *nnode
;
2362 struct ecommunity
*ecom
;
2364 for (ALL_LIST_ELEMENTS (rtl
, node
, nnode
, ecom
))
2366 if (ecommunity_match (ecom
, ecomtarget
))
2374 DEFUN (bgp_evpn_vni_rt
,
2375 bgp_evpn_vni_rt_cmd
,
2376 "route-target <both|import|export> RT",
2378 "import and export\n"
2381 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
2383 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2384 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2386 struct ecommunity
*ecomadd
= NULL
;
2391 if (!strcmp (argv
[1]->arg
, "import"))
2392 rt_type
= RT_TYPE_IMPORT
;
2393 else if (!strcmp (argv
[1]->arg
, "export"))
2394 rt_type
= RT_TYPE_EXPORT
;
2395 else if (!strcmp (argv
[1]->arg
, "both"))
2396 rt_type
= RT_TYPE_BOTH
;
2399 vty_out (vty
, "%% Invalid Route Target type%s", VTY_NEWLINE
);
2403 /* Add/update the import route-target */
2404 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
2406 ecomadd
= ecommunity_str2com (argv
[2]->arg
,
2407 ECOMMUNITY_ROUTE_TARGET
, 0);
2408 ecommunity_str(ecomadd
);
2411 vty_out (vty
, "%% Malformed Route Target list%s", VTY_NEWLINE
);
2415 /* Do nothing if we already have this import route-target */
2416 if (! bgp_evpn_rt_matches_existing (vpn
->import_rtl
, ecomadd
))
2417 evpn_configure_import_rt (bgp
, vpn
, ecomadd
);
2420 /* Add/update the export route-target */
2421 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
2423 ecomadd
= ecommunity_str2com (argv
[2]->arg
,
2424 ECOMMUNITY_ROUTE_TARGET
, 0);
2425 ecommunity_str(ecomadd
);
2428 vty_out (vty
, "%% Malformed Route Target list%s", VTY_NEWLINE
);
2432 /* Do nothing if we already have this export route-target */
2433 if (! bgp_evpn_rt_matches_existing (vpn
->export_rtl
, ecomadd
))
2434 evpn_configure_export_rt (bgp
, vpn
, ecomadd
);
2440 DEFUN (no_bgp_evpn_vni_rt
,
2441 no_bgp_evpn_vni_rt_cmd
,
2442 "no route-target <both|import|export> RT",
2445 "import and export\n"
2448 "ASN:XX or A.B.C.D:XX\n")
2450 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2451 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2452 int rt_type
, found_ecomdel
;
2453 struct ecommunity
*ecomdel
= NULL
;
2458 if (!strcmp (argv
[2]->arg
, "import"))
2459 rt_type
= RT_TYPE_IMPORT
;
2460 else if (!strcmp (argv
[2]->arg
, "export"))
2461 rt_type
= RT_TYPE_EXPORT
;
2462 else if (!strcmp (argv
[2]->arg
, "both"))
2463 rt_type
= RT_TYPE_BOTH
;
2466 vty_out (vty
, "%% Invalid Route Target type%s", VTY_NEWLINE
);
2470 /* The user did "no route-target import", check to see if there are any
2471 * import route-targets configured. */
2472 if (rt_type
== RT_TYPE_IMPORT
)
2474 if (!is_import_rt_configured (vpn
))
2476 vty_out (vty
, "%% Import RT is not configured for this VNI%s", VTY_NEWLINE
);
2480 else if (rt_type
== RT_TYPE_EXPORT
)
2482 if (!is_export_rt_configured (vpn
))
2484 vty_out (vty
, "%% Export RT is not configured for this VNI%s", VTY_NEWLINE
);
2488 else if (rt_type
== RT_TYPE_BOTH
)
2490 if (!is_import_rt_configured (vpn
) && !is_export_rt_configured (vpn
))
2492 vty_out (vty
, "%% Import/Export RT is not configured for this VNI%s", VTY_NEWLINE
);
2497 ecomdel
= ecommunity_str2com (argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
2498 ecommunity_str(ecomdel
);
2501 vty_out (vty
, "%% Malformed Route Target list%s", VTY_NEWLINE
);
2505 if (rt_type
== RT_TYPE_IMPORT
)
2507 if (!bgp_evpn_rt_matches_existing (vpn
->import_rtl
, ecomdel
))
2509 vty_out (vty
, "%% RT specified does not match configuration for this VNI%s", VTY_NEWLINE
);
2512 evpn_unconfigure_import_rt (bgp
, vpn
, ecomdel
);
2514 else if (rt_type
== RT_TYPE_EXPORT
)
2516 if (!bgp_evpn_rt_matches_existing (vpn
->export_rtl
, ecomdel
))
2518 vty_out (vty
, "%% RT specified does not match configuration for this VNI%s", VTY_NEWLINE
);
2521 evpn_unconfigure_export_rt (bgp
, vpn
, ecomdel
);
2523 else if (rt_type
== RT_TYPE_BOTH
)
2527 if (bgp_evpn_rt_matches_existing (vpn
->import_rtl
, ecomdel
))
2529 evpn_unconfigure_import_rt (bgp
, vpn
, ecomdel
);
2533 if (bgp_evpn_rt_matches_existing (vpn
->export_rtl
, ecomdel
))
2535 evpn_unconfigure_export_rt (bgp
, vpn
, ecomdel
);
2539 if (! found_ecomdel
)
2541 vty_out (vty
, "%% RT specified does not match configuration for this VNI%s", VTY_NEWLINE
);
2549 DEFUN (no_bgp_evpn_vni_rt_without_val
,
2550 no_bgp_evpn_vni_rt_without_val_cmd
,
2551 "no route-target <import|export>",
2557 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2558 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2564 if (!strcmp (argv
[2]->arg
, "import"))
2566 rt_type
= RT_TYPE_IMPORT
;
2568 else if (!strcmp (argv
[2]->arg
, "export"))
2570 rt_type
= RT_TYPE_EXPORT
;
2574 vty_out (vty
, "%% Invalid Route Target type%s", VTY_NEWLINE
);
2578 /* Check if we should disallow. */
2579 if (rt_type
== RT_TYPE_IMPORT
)
2581 if (!is_import_rt_configured (vpn
))
2583 vty_out (vty
, "%% Import RT is not configured for this VNI%s", VTY_NEWLINE
);
2589 if (!is_export_rt_configured (vpn
))
2591 vty_out (vty
, "%% Export RT is not configured for this VNI%s", VTY_NEWLINE
);
2596 /* Unconfigure the RT. */
2597 if (rt_type
== RT_TYPE_IMPORT
)
2598 evpn_unconfigure_import_rt (bgp
, vpn
, NULL
);
2600 evpn_unconfigure_export_rt (bgp
, vpn
, NULL
);
2605 * Output EVPN configuration information.
2608 bgp_config_write_evpn_info (struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
2609 safi_t safi
, int *write
)
2611 struct evpn_config_write cfg
;
2617 hash_iterate (bgp
->vnihash
,
2618 (void (*) (struct hash_backet
*, void *))
2619 write_vni_config_for_entry
, &cfg
);
2623 if (bgp
->advertise_all_vni
)
2625 bgp_config_write_family_header (vty
, afi
, safi
, write
);
2626 vty_out (vty
, " advertise-all-vni%s", VTY_NEWLINE
);
2630 void bgp_ethernetvpn_init(void)
2632 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
2633 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
2634 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
2635 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
2636 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
2637 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
2638 install_element(VIEW_NODE
,
2639 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
2640 install_element(VIEW_NODE
,
2641 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
2642 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
2643 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
2644 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
2645 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
2646 #if defined(HAVE_CUMULUS)
2647 install_element (BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
2648 install_element (BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
2650 /* "show bgp evpn" commands. */
2651 install_element (VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
2652 install_element (VIEW_NODE
, &show_bgp_evpn_vni_num_cmd
);
2653 install_element (VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
2654 install_element (VIEW_NODE
, &show_bgp_evpn_route_cmd
);
2655 install_element (VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
2656 install_element (VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
2657 install_element (VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
2658 install_element (VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
2659 install_element (VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
2660 install_element (VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
2661 install_element (VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
2663 install_element (BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
2664 install_element (BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
2665 install_element (BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
2666 install_element (BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
2667 install_element (BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
2668 install_element (BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
2669 install_element (BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
2670 install_element (BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
2671 install_element (BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);