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
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_ecommunity.h"
40 #define SHOW_DISPLAY_STANDARD 0
41 #define SHOW_DISPLAY_TAGS 1
42 #define SHOW_DISPLAY_OVERLAY 2
43 #define VNI_STR_LEN 32
46 * Context for VNI hash walk - used by callbacks.
51 struct in_addr vtep_ip
;
55 #if defined(HAVE_CUMULUS)
56 static void display_vrf_import_rt(struct vty
*vty
,
57 struct vrf_irt_node
*irt
,
61 u_char type
, sub_type
;
62 struct ecommunity_as eas
;
63 struct ecommunity_ip eip
;
64 struct listnode
*node
, *nnode
;
65 struct bgp
*tmp_bgp_vrf
= NULL
;
66 json_object
*json_rt
= NULL
;
67 json_object
*json_vrfs
= NULL
;
68 char rt_buf
[RT_ADDRSTRLEN
];
71 json_rt
= json_object_new_object();
72 json_vrfs
= json_object_new_array();
75 pnt
= (u_char
*)&irt
->rt
.val
;
78 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
81 memset(&eas
, 0, sizeof(eas
));
83 case ECOMMUNITY_ENCODE_AS
:
84 eas
.as
= (*pnt
++ << 8);
86 pnt
= ptr_get_be32(pnt
, &eas
.val
);
88 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
91 json_object_string_add(json_rt
, "rt", rt_buf
);
93 vty_out(vty
, "Route-target: %s", rt_buf
);
97 case ECOMMUNITY_ENCODE_IP
:
98 memcpy(&eip
.ip
, pnt
, 4);
100 eip
.val
= (*pnt
++ << 8);
103 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
107 json_object_string_add(json_rt
, "rt", rt_buf
);
109 vty_out(vty
, "Route-target: %s", rt_buf
);
113 case ECOMMUNITY_ENCODE_AS4
:
114 pnt
= ptr_get_be32(pnt
, &eas
.val
);
115 eas
.val
= (*pnt
++ << 8);
118 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
121 json_object_string_add(json_rt
, "rt", rt_buf
);
123 vty_out(vty
, "Route-target: %s", rt_buf
);
133 "\nList of VRFs importing routes with this route-target:\n");
136 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
138 json_object_array_add(
140 json_object_new_string(
142 tmp_bgp_vrf
->vrf_id
)));
144 vty_out(vty
, " %s\n",
145 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
149 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
150 json_object_object_add(json
, rt_buf
, json_rt
);
154 static void show_vrf_import_rt_entry(struct hash_backet
*backet
,
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)backet
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 u_char type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (u_char
*)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 pnt
= ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
219 json_object_string_add(json_rt
, "rt", rt_buf
);
221 vty_out(vty
, "Route-target: %s", rt_buf
);
225 case ECOMMUNITY_ENCODE_AS4
:
226 pnt
= ptr_get_be32(pnt
, &eas
.val
);
227 eas
.val
= (*pnt
++ << 8);
230 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
233 json_object_string_add(json_rt
, "rt", rt_buf
);
235 vty_out(vty
, "Route-target: %s", rt_buf
);
245 "\nList of VNIs importing routes with this route-target:\n");
248 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
250 json_object_array_add(
251 json_vnis
, json_object_new_int64(tmp_vpn
->vni
));
253 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
257 json_object_object_add(json_rt
, "vnis", json_vnis
);
258 json_object_object_add(json
, rt_buf
, json_rt
);
262 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
264 json_object
*json
= NULL
;
265 struct vty
*vty
= NULL
;
266 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
271 display_import_rt(vty
, irt
, json
);
276 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
277 struct bgp_node
*rd_rn
,
284 char rd_str
[RD_ADDRSTRLEN
];
286 pnt
= rd_rn
->p
.u
.val
;
288 /* Decode RD type. */
289 type
= decode_rd_type(pnt
);
294 vty_out(vty
, "Route Distinguisher: ");
298 decode_rd_as(pnt
+ 2, &rd_as
);
299 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
303 decode_rd_ip(pnt
+ 2, &rd_ip
);
304 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
309 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
313 vty_out(vty
, "%s\n", rd_str
);
316 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
320 " Network Next Hop Metric LocPrf Weight Path\n";
326 vty_out(vty
, "BGP table version is 0, local router ID is %s\n",
327 inet_ntoa(bgp
->router_id
));
329 "Status codes: s suppressed, d damped, h history, "
330 "* valid, > best, i - internal\n");
331 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
333 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
334 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n\n");
335 vty_out(vty
, "%s", ri_header
);
338 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
340 char buf1
[RD_ADDRSTRLEN
];
342 struct listnode
*node
, *nnode
;
343 struct ecommunity
*ecom
;
344 json_object
*json_import_rtl
= NULL
;
345 json_object
*json_export_rtl
= NULL
;
348 json_import_rtl
= json_object_new_array();
349 json_export_rtl
= json_object_new_array();
350 json_object_int_add(json
, "vni", vpn
->vni
);
351 json_object_string_add(json
, "kernelFlag",
352 is_vni_live(vpn
) ? "Yes" : "No");
353 json_object_string_add(
355 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
356 json_object_string_add(json
, "originatorIp",
357 inet_ntoa(vpn
->originator_ip
));
358 json_object_string_add(json
, "advertiseGatewayMacip",
359 vpn
->advertise_gw_macip
? "Yes" : "No");
361 vty_out(vty
, "VNI: %d", vpn
->vni
);
362 if (is_vni_live(vpn
))
363 vty_out(vty
, " (known to the kernel)");
366 vty_out(vty
, " Tenant-Vrf: %s\n",
367 vrf_id_to_name(vpn
->tenant_vrf_id
));
368 vty_out(vty
, " RD: %s\n",
369 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
370 vty_out(vty
, " Originator IP: %s\n",
371 inet_ntoa(vpn
->originator_ip
));
372 vty_out(vty
, " Advertise-gw-macip : %s\n",
373 vpn
->advertise_gw_macip
? "Yes" : "No");
377 vty_out(vty
, " Import Route Target:\n");
379 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
380 ecom_str
= ecommunity_ecom2str(ecom
,
381 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
384 json_object_array_add(json_import_rtl
,
385 json_object_new_string(ecom_str
));
387 vty_out(vty
, " %s\n", ecom_str
);
389 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
393 json_object_object_add(json
, "importRts", json_import_rtl
);
395 vty_out(vty
, " Export Route Target:\n");
397 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
398 ecom_str
= ecommunity_ecom2str(ecom
,
399 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
402 json_object_array_add(json_export_rtl
,
403 json_object_new_string(ecom_str
));
405 vty_out(vty
, " %s\n", ecom_str
);
407 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
411 json_object_object_add(json
, "exportRts", json_export_rtl
);
414 static void evpn_show_vrf_routes(struct vty
*vty
,
417 struct bgp
*bgp_def
= NULL
;
421 u_int32_t prefix_cnt
, path_cnt
;
422 struct bgp_table
*table
;
424 prefix_cnt
= path_cnt
= 0;
425 bgp_def
= bgp_get_default();
429 table
= (struct bgp_table
*)bgp_vrf
->rib
[AFI_L2VPN
][SAFI_EVPN
];
430 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
431 char prefix_str
[BUFSIZ
];
433 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
437 /* Overall header/legend displayed once. */
439 bgp_evpn_show_route_header(vty
, bgp_def
, NULL
);
445 /* For EVPN, the prefix is displayed for each path (to fit in
446 * with code that already exists).
448 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
449 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, NULL
);
455 vty_out(vty
, "No EVPN prefixes exist for this VRF");
457 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)",
458 prefix_cnt
, path_cnt
);
461 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
462 struct vty
*vty
, struct in_addr vtep_ip
,
468 u_int32_t prefix_cnt
, path_cnt
;
470 prefix_cnt
= path_cnt
= 0;
472 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
473 rn
= bgp_route_next(rn
)) {
474 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
475 int add_prefix_to_json
= 0;
476 char prefix_str
[BUFSIZ
];
477 json_object
*json_paths
= NULL
;
478 json_object
*json_prefix
= NULL
;
480 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
483 if (type
&& evp
->prefix
.route_type
!= type
)
487 json_prefix
= json_object_new_object();
490 /* Overall header/legend displayed once. */
492 bgp_evpn_show_route_header(vty
, bgp
, json
);
500 json_paths
= json_object_new_array();
502 /* For EVPN, the prefix is displayed for each path (to fit in
503 * with code that already exists).
505 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
506 json_object
*json_path
= NULL
;
509 && !IPV4_ADDR_SAME(&(vtep_ip
),
510 &(ri
->attr
->nexthop
)))
514 json_path
= json_object_new_array();
516 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
519 json_object_array_add(json_paths
, json_path
);
522 add_prefix_to_json
= 1;
525 if (json
&& add_prefix_to_json
) {
526 json_object_string_add(json_prefix
, "prefix",
528 json_object_int_add(json_prefix
, "prefixLen",
530 json_object_object_add(json_prefix
, "paths",
532 json_object_object_add(json
, prefix_str
, json_prefix
);
537 json_object_int_add(json
, "numPrefix", prefix_cnt
);
538 json_object_int_add(json
, "numPaths", path_cnt
);
541 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
542 type
? "(of requested type) " : "");
544 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s",
545 prefix_cnt
, path_cnt
,
546 type
? " (of requested type)" : "");
550 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
552 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
553 struct vni_walk_ctx
*wctx
= arg
;
554 struct vty
*vty
= wctx
->vty
;
555 json_object
*json
= wctx
->json
;
556 json_object
*json_vni
= NULL
;
557 char vni_str
[VNI_STR_LEN
];
559 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
561 json_vni
= json_object_new_object();
562 json_object_int_add(json_vni
, "vni", vpn
->vni
);
564 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
567 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
570 json_object_object_add(json
, vni_str
, json_vni
);
573 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
577 json_object
*json_vni
;
578 json_object
*json_import_rtl
;
579 json_object
*json_export_rtl
;
580 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
582 char buf2
[RD_ADDRSTRLEN
];
585 struct listnode
*node
, *nnode
;
586 struct ecommunity
*ecom
;
592 json_vni
= json_object_new_object();
593 json_import_rtl
= json_object_new_array();
594 json_export_rtl
= json_object_new_array();
598 if (is_vni_live(vpn
))
602 json_object_int_add(json_vni
, "vni", vpn
->vni
);
603 json_object_string_add(json_vni
, "inKernel",
604 is_vni_live(vpn
) ? "True" : "False");
605 json_object_string_add(json_vni
, "originatorIp",
606 inet_ntoa(vpn
->originator_ip
));
607 json_object_string_add(
609 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
611 vty_out(vty
, "%-1s %-10u %-15s %-21s", buf1
, vpn
->vni
,
612 inet_ntoa(vpn
->originator_ip
),
613 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
616 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
617 ecom_str
= ecommunity_ecom2str(ecom
,
618 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
621 json_object_array_add(json_import_rtl
,
622 json_object_new_string(ecom_str
));
624 if (listcount(vpn
->import_rtl
) > 1)
625 sprintf(rt_buf
, "%s, ...", ecom_str
);
627 sprintf(rt_buf
, "%s", ecom_str
);
628 vty_out(vty
, " %-25s", rt_buf
);
631 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
633 /* If there are multiple import RTs we break here and show only
640 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
642 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
643 ecom_str
= ecommunity_ecom2str(ecom
,
644 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
647 json_object_array_add(json_export_rtl
,
648 json_object_new_string(ecom_str
));
650 if (listcount(vpn
->export_rtl
) > 1)
651 sprintf(rt_buf
, "%s, ...", ecom_str
);
653 sprintf(rt_buf
, "%s", ecom_str
);
654 vty_out(vty
, " %-25s", rt_buf
);
657 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
659 /* If there are multiple export RTs we break here and show only
666 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
669 char vni_str
[VNI_STR_LEN
];
671 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
672 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
673 json_object_object_add(json
, vni_str
, json_vni
);
678 #endif /* HAVE_CUMULUS */
680 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
681 enum bgp_show_type type
, void *output_arg
,
682 int option
, u_char use_json
)
684 afi_t afi
= AFI_L2VPN
;
686 struct bgp_table
*table
;
693 unsigned long output_count
= 0;
694 unsigned long total_count
= 0;
695 json_object
*json
= NULL
;
696 json_object
*json_nroute
= NULL
;
697 json_object
*json_array
= NULL
;
698 json_object
*json_scode
= NULL
;
699 json_object
*json_ocode
= NULL
;
701 bgp
= bgp_get_default();
704 vty_out(vty
, "No BGP process is configured\n");
706 vty_out(vty
, "{}\n");
711 json_scode
= json_object_new_object();
712 json_ocode
= json_object_new_object();
713 json
= json_object_new_object();
714 json_nroute
= json_object_new_object();
716 json_object_string_add(json_scode
, "suppressed", "s");
717 json_object_string_add(json_scode
, "damped", "d");
718 json_object_string_add(json_scode
, "history", "h");
719 json_object_string_add(json_scode
, "valid", "*");
720 json_object_string_add(json_scode
, "best", ">");
721 json_object_string_add(json_scode
, "internal", "i");
723 json_object_string_add(json_ocode
, "igp", "i");
724 json_object_string_add(json_ocode
, "egp", "e");
725 json_object_string_add(json_ocode
, "incomplete", "?");
728 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
729 rn
= bgp_route_next(rn
)) {
731 continue; /* XXX json TODO */
733 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
736 if ((table
= rn
->info
) == NULL
)
741 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
742 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
744 if (type
== bgp_show_type_neighbor
) {
745 union sockunion
*su
= output_arg
;
747 if (ri
->peer
->su_remote
== NULL
749 ri
->peer
->su_remote
, su
))
755 == SHOW_DISPLAY_TAGS
) {
760 json_object_string_add(
765 json_object_object_add(
769 json_object_object_add(
775 if (option
== SHOW_DISPLAY_TAGS
)
780 == SHOW_DISPLAY_OVERLAY
)
785 "BGP table version is 0, local router ID is %s\n",
789 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
791 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
792 vty_out(vty
, V4_HEADER
);
805 /* Decode RD type. */
806 type
= decode_rd_type(pnt
);
807 /* Decode RD value. */
808 if (type
== RD_TYPE_AS
)
809 decode_rd_as(pnt
+ 2, &rd_as
);
810 else if (type
== RD_TYPE_AS4
)
811 decode_rd_as4(pnt
+ 2, &rd_as
);
812 else if (type
== RD_TYPE_IP
)
813 decode_rd_ip(pnt
+ 2, &rd_ip
);
816 if (type
== RD_TYPE_AS
817 || type
== RD_TYPE_AS4
)
818 sprintf(buffer
, "%u:%d",
821 else if (type
== RD_TYPE_IP
)
822 sprintf(buffer
, "%s:%d",
826 json_object_string_add(
828 "routeDistinguisher",
832 "Route Distinguisher: ");
833 if (type
== RD_TYPE_AS
)
838 else if (type
== RD_TYPE_AS4
)
843 else if (type
== RD_TYPE_IP
)
844 vty_out(vty
, "ip %s:%d",
848 vty_out(vty
, "\n\n");
853 json_array
= json_object_new_array();
856 if (option
== SHOW_DISPLAY_TAGS
)
857 route_vty_out_tag(vty
, &rm
->p
, ri
, 0,
860 else if (option
== SHOW_DISPLAY_OVERLAY
)
861 route_vty_out_overlay(vty
, &rm
->p
, ri
,
864 route_vty_out(vty
, &rm
->p
, ri
, 0,
865 SAFI_EVPN
, json_array
);
870 if (output_count
== 0)
871 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
873 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
874 output_count
, total_count
);
878 DEFUN(show_ip_bgp_l2vpn_evpn
,
879 show_ip_bgp_l2vpn_evpn_cmd
,
880 "show [ip] bgp l2vpn evpn [json]",
881 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
883 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
884 use_json(argc
, argv
));
887 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
888 show_ip_bgp_l2vpn_evpn_rd_cmd
,
889 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
895 "Display information for a route distinguisher\n"
896 "VPN Route Distinguisher\n" JSON_STR
)
898 int idx_ext_community
= 0;
900 struct prefix_rd prd
;
902 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
904 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
906 vty_out(vty
, "%% Malformed Route Distinguisher\n");
909 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
910 use_json(argc
, argv
));
913 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
914 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
915 "show [ip] bgp l2vpn evpn all tags",
921 "Display information about all EVPN NLRIs\n"
922 "Display BGP tags for prefixes\n")
924 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
928 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
929 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
930 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
936 "Display information for a route distinguisher\n"
937 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
939 int idx_ext_community
= 0;
941 struct prefix_rd prd
;
943 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
945 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
947 vty_out(vty
, "%% Malformed Route Distinguisher\n");
950 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
954 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
955 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
956 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
962 "Display information about all EVPN NLRIs\n"
963 "Detailed information on TCP and BGP neighbor connections\n"
964 "Neighbor to display information about\n"
965 "Display routes learned from neighbor\n" JSON_STR
)
971 u_char uj
= use_json(argc
, argv
);
973 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
975 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
978 json_object
*json_no
= NULL
;
979 json_no
= json_object_new_object();
980 json_object_string_add(json_no
, "warning",
981 "Malformed address");
983 json_object_to_json_string(json_no
));
984 json_object_free(json_no
);
986 vty_out(vty
, "Malformed address: %s\n",
987 argv
[idx_ipv4
]->arg
);
991 peer
= peer_lookup(NULL
, &su
);
992 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
994 json_object
*json_no
= NULL
;
995 json_no
= json_object_new_object();
996 json_object_string_add(
998 "No such neighbor or address family");
1000 json_object_to_json_string(json_no
));
1001 json_object_free(json_no
);
1003 vty_out(vty
, "%% No such neighbor or address family\n");
1007 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1011 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1012 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1013 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1019 "Display information for a route distinguisher\n"
1020 "VPN Route Distinguisher\n"
1021 "Detailed information on TCP and BGP neighbor connections\n"
1022 "Neighbor to display information about\n"
1023 "Display routes learned from neighbor\n" JSON_STR
)
1025 int idx_ext_community
= 0;
1030 struct prefix_rd prd
;
1031 u_char uj
= use_json(argc
, argv
);
1033 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1034 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1036 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1039 json_object
*json_no
= NULL
;
1040 json_no
= json_object_new_object();
1041 json_object_string_add(json_no
, "warning",
1042 "Malformed Route Distinguisher");
1043 vty_out(vty
, "%s\n",
1044 json_object_to_json_string(json_no
));
1045 json_object_free(json_no
);
1047 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1051 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1054 json_object
*json_no
= NULL
;
1055 json_no
= json_object_new_object();
1056 json_object_string_add(json_no
, "warning",
1057 "Malformed address");
1058 vty_out(vty
, "%s\n",
1059 json_object_to_json_string(json_no
));
1060 json_object_free(json_no
);
1062 vty_out(vty
, "Malformed address: %s\n",
1063 argv
[idx_ext_community
]->arg
);
1067 peer
= peer_lookup(NULL
, &su
);
1068 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1070 json_object
*json_no
= NULL
;
1071 json_no
= json_object_new_object();
1072 json_object_string_add(
1074 "No such neighbor or address family");
1075 vty_out(vty
, "%s\n",
1076 json_object_to_json_string(json_no
));
1077 json_object_free(json_no
);
1079 vty_out(vty
, "%% No such neighbor or address family\n");
1083 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1087 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1088 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1089 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1095 "Display information about all EVPN NLRIs\n"
1096 "Detailed information on TCP and BGP neighbor connections\n"
1097 "Neighbor to display information about\n"
1098 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1104 u_char uj
= use_json(argc
, argv
);
1106 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1108 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1111 json_object
*json_no
= NULL
;
1112 json_no
= json_object_new_object();
1113 json_object_string_add(json_no
, "warning",
1114 "Malformed address");
1115 vty_out(vty
, "%s\n",
1116 json_object_to_json_string(json_no
));
1117 json_object_free(json_no
);
1119 vty_out(vty
, "Malformed address: %s\n",
1120 argv
[idx_ipv4
]->arg
);
1123 peer
= peer_lookup(NULL
, &su
);
1124 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1126 json_object
*json_no
= NULL
;
1127 json_no
= json_object_new_object();
1128 json_object_string_add(
1130 "No such neighbor or address family");
1131 vty_out(vty
, "%s\n",
1132 json_object_to_json_string(json_no
));
1133 json_object_free(json_no
);
1135 vty_out(vty
, "%% No such neighbor or address family\n");
1139 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1142 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1143 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1144 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1150 "Display information for a route distinguisher\n"
1151 "VPN Route Distinguisher\n"
1152 "Detailed information on TCP and BGP neighbor connections\n"
1153 "Neighbor to display information about\n"
1154 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1156 int idx_ext_community
= 0;
1160 struct prefix_rd prd
;
1162 u_char uj
= use_json(argc
, argv
);
1164 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1165 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1167 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1170 json_object
*json_no
= NULL
;
1171 json_no
= json_object_new_object();
1172 json_object_string_add(json_no
, "warning",
1173 "Malformed address");
1174 vty_out(vty
, "%s\n",
1175 json_object_to_json_string(json_no
));
1176 json_object_free(json_no
);
1178 vty_out(vty
, "Malformed address: %s\n",
1179 argv
[idx_ext_community
]->arg
);
1182 peer
= peer_lookup(NULL
, &su
);
1183 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1185 json_object
*json_no
= NULL
;
1186 json_no
= json_object_new_object();
1187 json_object_string_add(
1189 "No such neighbor or address family");
1190 vty_out(vty
, "%s\n",
1191 json_object_to_json_string(json_no
));
1192 json_object_free(json_no
);
1194 vty_out(vty
, "%% No such neighbor or address family\n");
1198 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1201 json_object
*json_no
= NULL
;
1202 json_no
= json_object_new_object();
1203 json_object_string_add(json_no
, "warning",
1204 "Malformed Route Distinguisher");
1205 vty_out(vty
, "%s\n",
1206 json_object_to_json_string(json_no
));
1207 json_object_free(json_no
);
1209 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1213 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1216 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1217 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1218 "show [ip] bgp l2vpn evpn all overlay",
1224 "Display information about all EVPN NLRIs\n"
1225 "Display BGP Overlay Information for prefixes\n")
1227 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1228 SHOW_DISPLAY_OVERLAY
,
1229 use_json(argc
, argv
));
1232 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1233 show_ip_bgp_evpn_rd_overlay_cmd
,
1234 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1240 "Display information for a route distinguisher\n"
1241 "VPN Route Distinguisher\n"
1242 "Display BGP Overlay Information for prefixes\n")
1244 int idx_ext_community
= 0;
1246 struct prefix_rd prd
;
1248 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1250 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1252 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1255 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1256 SHOW_DISPLAY_OVERLAY
,
1257 use_json(argc
, argv
));
1260 /* For testing purpose, static route of MPLS-VPN. */
1261 DEFUN(evpnrt5_network
,
1262 evpnrt5_network_cmd
,
1263 "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]",
1264 "Specify a network to announce via BGP\n"
1267 "Specify Route Distinguisher\n"
1268 "VPN Route Distinguisher\n"
1270 "Ethernet Tag Value\n"
1273 "Ethernet Segment Identifier\n"
1274 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1276 "Gateway IP ( A.B.C.D )\n"
1277 "Gateway IPv6 ( X:X::X:X )\n"
1278 "Router Mac Ext Comm\n"
1279 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1280 "Route-map to modify the attributes\n"
1281 "Name of the route map\n")
1283 int idx_ipv4_prefixlen
= 1;
1284 int idx_route_distinguisher
= 3;
1289 int idx_routermac
= 13;
1291 return bgp_static_set_safi(
1292 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1293 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
,
1295 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1296 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1297 argv
[idx_routermac
]->arg
);
1300 /* For testing purpose, static route of MPLS-VPN. */
1301 DEFUN(no_evpnrt5_network
,
1302 no_evpnrt5_network_cmd
,
1303 "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>",
1305 "Specify a network to announce via BGP\n"
1308 "Specify Route Distinguisher\n"
1309 "VPN Route Distinguisher\n"
1311 "Ethernet Tag Value\n"
1314 "Ethernet Segment Identifier\n"
1315 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1316 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1318 int idx_ipv4_prefixlen
= 2;
1319 int idx_ext_community
= 4;
1324 return bgp_static_unset_safi(
1325 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1326 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1327 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1328 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1331 #if defined(HAVE_CUMULUS)
1333 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1335 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1338 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1340 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1344 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1345 * check that this is a change.
1347 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1348 struct ecommunity
*ecomadd
)
1350 /* If the VNI is "live", we need to uninstall routes using the current
1351 * import RT(s) first before we update the import RT, and subsequently
1354 if (is_vni_live(vpn
))
1355 bgp_evpn_uninstall_routes(bgp
, vpn
);
1357 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1358 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1360 /* If the auto route-target is in use we must remove it */
1361 evpn_import_rt_delete_auto(bgp
, vpn
);
1363 /* Add new RT and rebuild the RT to VNI mapping */
1364 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1366 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1367 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1369 /* Install routes that match new import RT */
1370 if (is_vni_live(vpn
))
1371 bgp_evpn_install_routes(bgp
, vpn
);
1375 * Unconfigure Import RT(s) for a VNI (vty handler).
1377 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1378 struct ecommunity
*ecomdel
)
1380 struct listnode
*node
, *nnode
, *node_to_del
;
1381 struct ecommunity
*ecom
;
1383 /* Along the lines of "configure" except we have to reset to the
1386 if (is_vni_live(vpn
))
1387 bgp_evpn_uninstall_routes(bgp
, vpn
);
1389 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1390 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1392 /* Delete all import RTs */
1393 if (ecomdel
== NULL
) {
1394 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1395 ecommunity_free(&ecom
);
1397 list_delete_all_node(vpn
->import_rtl
);
1400 /* Delete a specific import RT */
1404 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1405 if (ecommunity_match(ecom
, ecomdel
)) {
1406 ecommunity_free(&ecom
);
1413 list_delete_node(vpn
->import_rtl
, node_to_del
);
1416 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1417 if (list_isempty(vpn
->import_rtl
)) {
1418 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1419 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1421 /* Rebuild the RT to VNI mapping */
1423 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1425 /* Install routes that match new import RT */
1426 if (is_vni_live(vpn
))
1427 bgp_evpn_install_routes(bgp
, vpn
);
1431 * Configure the Export RT for a VNI (vty handler). Caller expected to
1432 * check that this is a change. Note that only a single export RT is
1433 * allowed for a VNI and any change to configuration is implemented as
1434 * a "replace" (similar to other configuration).
1436 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1437 struct ecommunity
*ecomadd
)
1439 /* If the auto route-target is in use we must remove it */
1440 evpn_export_rt_delete_auto(bgp
, vpn
);
1442 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1443 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1445 if (is_vni_live(vpn
))
1446 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1450 * Unconfigure the Export RT for a VNI (vty handler)
1452 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1453 struct ecommunity
*ecomdel
)
1455 struct listnode
*node
, *nnode
, *node_to_del
;
1456 struct ecommunity
*ecom
;
1458 /* Delete all export RTs */
1459 if (ecomdel
== NULL
) {
1460 /* Reset to default and process all routes. */
1461 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1462 ecommunity_free(&ecom
);
1464 list_delete_all_node(vpn
->export_rtl
);
1467 /* Delete a specific export RT */
1471 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1472 if (ecommunity_match(ecom
, ecomdel
)) {
1473 ecommunity_free(&ecom
);
1480 list_delete_node(vpn
->export_rtl
, node_to_del
);
1483 if (list_isempty(vpn
->export_rtl
)) {
1484 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1485 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1488 if (is_vni_live(vpn
))
1489 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1493 * Configure RD for VRF
1495 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
,
1496 struct prefix_rd
*rd
)
1498 /* If we have already advertise type-5 routes with a diffrent RD, we
1499 * have to delete and withdraw them firs
1501 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1504 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1505 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1507 /* We have a new RD for VRF.
1508 * Advertise all type-5 routes again with the new RD
1510 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1514 * Unconfigure RD for VRF
1516 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1518 /* If we have already advertise type-5 routes with a diffrent RD, we
1519 * have to delete and withdraw them firs
1521 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1523 /* fall back to default RD */
1524 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1526 /* We have a new RD for VRF.
1527 * Advertise all type-5 routes again with the new RD
1529 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1533 * Configure RD for a VNI (vty handler)
1535 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1536 struct prefix_rd
*rd
)
1538 /* If the VNI is "live", we need to delete and withdraw this VNI's
1539 * local routes with the prior RD first. Then, after updating RD,
1540 * need to re-advertise.
1542 if (is_vni_live(vpn
))
1543 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1546 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1547 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1549 if (is_vni_live(vpn
))
1550 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1554 * Unconfigure RD for a VNI (vty handler)
1556 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1558 /* If the VNI is "live", we need to delete and withdraw this VNI's
1559 * local routes with the prior RD first. Then, after resetting RD
1560 * to automatic value, need to re-advertise.
1562 if (is_vni_live(vpn
))
1563 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1565 /* reset RD to default */
1566 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1568 if (is_vni_live(vpn
))
1569 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1573 * Create VNI, if not already present (VTY handler). Mark as configured.
1575 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1577 struct bgpevpn
*vpn
;
1582 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1584 /* tenant vrf will be updated when we get local_vni_add from
1587 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1590 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1596 /* Mark as configured. */
1597 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1602 * Delete VNI. If VNI does not exist in the system (i.e., just
1603 * configuration), all that is needed is to free it. Otherwise,
1604 * any parameters configured for the VNI need to be reset (with
1605 * appropriate action) and the VNI marked as unconfigured; the
1606 * VNI will continue to exist, purely as a "learnt" entity.
1608 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1610 assert(bgp
->vnihash
);
1612 if (!is_vni_live(vpn
)) {
1613 bgp_evpn_free(bgp
, vpn
);
1617 /* We need to take the unconfigure action for each parameter of this VNI
1618 * that is configured. Some optimization is possible, but not worth the
1619 * additional code for an operation that should be pretty rare.
1621 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1623 /* First, deal with the export side - RD and export RT changes. */
1624 if (is_rd_configured(vpn
))
1625 evpn_unconfigure_rd(bgp
, vpn
);
1626 if (is_export_rt_configured(vpn
))
1627 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1629 /* Next, deal with the import side. */
1630 if (is_import_rt_configured(vpn
))
1631 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1637 * Display import RT mapping to VRFs (vty handler)
1638 * bgp_def: default bgp instance
1640 static void evpn_show_vrf_import_rts(struct vty
*vty
,
1641 struct bgp
*bgp_def
,
1649 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1650 (void (*)(struct hash_backet
*, void *))
1651 show_vrf_import_rt_entry
,
1656 * Display import RT mapping to VNIs (vty handler)
1658 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1667 bgp
->import_rt_hash
,
1668 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1673 * Display EVPN routes for all VNIs - vty handler.
1675 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1676 struct in_addr vtep_ip
, json_object
*json
)
1679 struct vni_walk_ctx wctx
;
1681 num_vnis
= hashcount(bgp
->vnihash
);
1684 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1687 wctx
.vtep_ip
= vtep_ip
;
1689 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1690 void *))show_vni_routes_hash
,
1695 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1697 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1698 vni_t vni
, struct in_addr orig_ip
,
1701 struct bgpevpn
*vpn
;
1702 struct prefix_evpn p
;
1703 struct bgp_node
*rn
;
1704 struct bgp_info
*ri
;
1705 u_int32_t path_cnt
= 0;
1708 json_object
*json_paths
= NULL
;
1714 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1716 vty_out(vty
, "VNI not found\n");
1720 /* See if route exists. */
1721 build_evpn_type3_prefix(&p
, orig_ip
);
1722 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1723 if (!rn
|| !rn
->info
) {
1725 vty_out(vty
, "%% Network not in table\n");
1730 json_paths
= json_object_new_array();
1732 /* Prefix and num paths displayed once per prefix. */
1733 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1735 /* Display each path for this prefix. */
1736 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1737 json_object
*json_path
= NULL
;
1740 json_path
= json_object_new_array();
1742 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1746 json_object_array_add(json_paths
, json_path
);
1753 json_object_object_add(json
, "paths", json_paths
);
1755 json_object_int_add(json
, "numPaths", path_cnt
);
1757 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1763 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1764 * By definition, only matching type-2 route will be displayed.
1766 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1767 vni_t vni
, struct ethaddr
*mac
,
1768 struct ipaddr
*ip
, json_object
*json
)
1770 struct bgpevpn
*vpn
;
1771 struct prefix_evpn p
;
1772 struct bgp_node
*rn
;
1773 struct bgp_info
*ri
;
1774 u_int32_t path_cnt
= 0;
1777 json_object
*json_paths
= NULL
;
1783 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1786 vty_out(vty
, "VNI not found\n");
1790 /* See if route exists. Look for both non-sticky and sticky. */
1791 build_evpn_type2_prefix(&p
, mac
, ip
);
1792 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1793 if (!rn
|| !rn
->info
) {
1795 vty_out(vty
, "%% Network not in table\n");
1800 json_paths
= json_object_new_array();
1802 /* Prefix and num paths displayed once per prefix. */
1803 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1805 /* Display each path for this prefix. */
1806 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1807 json_object
*json_path
= NULL
;
1810 json_path
= json_object_new_array();
1812 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1816 json_object_array_add(json_paths
, json_path
);
1823 json_object_object_add(json
, "paths", json_paths
);
1825 json_object_int_add(json
, "numPaths", path_cnt
);
1827 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1833 * Display EVPN routes for a VNI - vty handler.
1834 * If 'type' is non-zero, only routes matching that type are shown.
1835 * If the vtep_ip is non zero, only routes behind that vtep are shown
1837 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1838 int type
, struct in_addr vtep_ip
,
1841 struct bgpevpn
*vpn
;
1844 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1847 vty_out(vty
, "VNI not found\n");
1851 /* Walk this VNI's route table and display appropriate routes. */
1852 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
1856 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1857 * IP (vty handler). By definition, only matching type-2 route will be
1860 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1861 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1862 struct ipaddr
*ip
, json_object
*json
)
1864 struct prefix_evpn p
;
1865 struct bgp_node
*rn
;
1866 struct bgp_info
*ri
;
1869 u_int32_t path_cnt
= 0;
1870 json_object
*json_paths
= NULL
;
1871 char prefix_str
[BUFSIZ
];
1876 /* See if route exists. Look for both non-sticky and sticky. */
1877 build_evpn_type2_prefix(&p
, mac
, ip
);
1878 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
1879 (struct prefix
*)&p
, prd
);
1880 if (!rn
|| !rn
->info
) {
1882 vty_out(vty
, "%% Network not in table\n");
1886 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
1887 sizeof(prefix_str
));
1889 /* Prefix and num paths displayed once per prefix. */
1890 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
1893 json_paths
= json_object_new_array();
1895 /* Display each path for this prefix. */
1896 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1897 json_object
*json_path
= NULL
;
1900 json_path
= json_object_new_array();
1902 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1906 json_object_array_add(json_paths
, json_path
);
1911 if (json
&& path_cnt
) {
1913 json_object_object_add(json
, prefix_str
, json_paths
);
1914 json_object_int_add(json
, "numPaths", path_cnt
);
1916 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1922 * Display BGP EVPN routing table -- for specific RD (vty handler)
1923 * If 'type' is non-zero, only routes matching that type are shown.
1925 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
1926 struct prefix_rd
*prd
, int type
,
1929 struct bgp_node
*rd_rn
;
1930 struct bgp_table
*table
;
1931 struct bgp_node
*rn
;
1932 struct bgp_info
*ri
;
1936 u_int32_t prefix_cnt
, path_cnt
;
1937 char rd_str
[RD_ADDRSTRLEN
];
1938 json_object
*json_rd
= NULL
;
1939 int add_rd_to_json
= 0;
1943 prefix_cnt
= path_cnt
= 0;
1945 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
1947 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
1951 table
= (struct bgp_table
*)rd_rn
->info
;
1956 json_rd
= json_object_new_object();
1957 json_object_string_add(json_rd
, "rd", rd_str
);
1960 /* Display all prefixes with this RD. */
1961 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
1962 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
1963 json_object
*json_prefix
= NULL
;
1964 json_object
*json_paths
= NULL
;
1965 char prefix_str
[BUFSIZ
];
1966 int add_prefix_to_json
= 0;
1968 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
1969 sizeof(prefix_str
));
1971 if (type
&& evp
->prefix
.route_type
!= type
)
1975 json_prefix
= json_object_new_object();
1978 /* RD header and legend - once overall. */
1979 if (rd_header
&& !json
) {
1981 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]\n");
1983 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
1985 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
1989 /* Prefix and num paths displayed once per prefix. */
1990 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
1997 json_paths
= json_object_new_array();
1999 /* Display each path for this prefix. */
2000 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2001 json_object
*json_path
= NULL
;
2004 json_path
= json_object_new_array();
2006 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2010 json_object_array_add(json_paths
, json_path
);
2013 add_prefix_to_json
= 1;
2017 if (json
&& add_prefix_to_json
) {
2018 json_object_object_add(json_prefix
, "paths",
2020 json_object_object_add(json_rd
, prefix_str
,
2025 if (json
&& add_rd_to_json
)
2026 json_object_object_add(json
, rd_str
, json_rd
);
2029 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2030 json_object_int_add(json
, "numPaths", path_cnt
);
2032 if (prefix_cnt
== 0)
2033 vty_out(vty
, "No prefixes exist with this RD%s\n",
2034 type
? " (of requested type)" : "");
2037 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2038 prefix_cnt
, path_cnt
,
2039 type
? " (of requested type)" : "");
2044 * Display BGP EVPN routing table - all routes (vty handler).
2045 * If 'type' is non-zero, only routes matching that type are shown.
2047 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2050 struct bgp_node
*rd_rn
;
2051 struct bgp_table
*table
;
2052 struct bgp_node
*rn
;
2053 struct bgp_info
*ri
;
2058 u_int32_t prefix_cnt
, path_cnt
;
2062 prefix_cnt
= path_cnt
= 0;
2064 /* EVPN routing table is a 2-level table with the first level being
2067 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2068 rd_rn
= bgp_route_next(rd_rn
)) {
2069 char rd_str
[RD_ADDRSTRLEN
];
2070 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2071 int add_rd_to_json
= 0;
2073 table
= (struct bgp_table
*)rd_rn
->info
;
2077 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2081 json_rd
= json_object_new_object();
2082 json_object_string_add(json_rd
, "rd", rd_str
);
2087 /* Display all prefixes for an RD */
2088 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2089 json_object
*json_prefix
=
2090 NULL
; /* contains prefix under a RD */
2091 json_object
*json_paths
=
2092 NULL
; /* array of paths under a prefix*/
2093 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2094 char prefix_str
[BUFSIZ
];
2095 int add_prefix_to_json
= 0;
2097 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2098 prefix_str
, sizeof(prefix_str
));
2100 if (type
&& evp
->prefix
.route_type
!= type
)
2104 /* Overall header/legend displayed once. */
2106 bgp_evpn_show_route_header(vty
, bgp
,
2111 /* RD header - per RD. */
2113 bgp_evpn_show_route_rd_header(
2122 json_prefix
= json_object_new_object();
2123 json_paths
= json_object_new_array();
2124 json_object_string_add(json_prefix
, "prefix",
2126 json_object_int_add(json_prefix
, "prefixLen",
2130 /* For EVPN, the prefix is displayed for each path (to
2132 * with code that already exists).
2134 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2135 json_object
*json_path
= NULL
;
2137 add_prefix_to_json
= 1;
2141 json_path
= json_object_new_array();
2143 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
2147 json_object_array_add(json_paths
,
2151 if (json
&& add_prefix_to_json
) {
2152 json_object_object_add(json_prefix
, "paths",
2154 json_object_object_add(json_rd
, prefix_str
,
2159 if (json
&& add_rd_to_json
)
2160 json_object_object_add(json
, rd_str
, json_rd
);
2164 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2165 json_object_int_add(json
, "numPaths", path_cnt
);
2167 if (prefix_cnt
== 0) {
2168 vty_out(vty
, "No EVPN prefixes %sexist\n",
2169 type
? "(of requested type) " : "");
2171 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2172 prefix_cnt
, path_cnt
,
2173 type
? " (of requested type)" : "");
2179 * Display specified VNI (vty handler)
2181 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2184 struct bgpevpn
*vpn
;
2186 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2189 vty_out(vty
, "{}\n");
2191 vty_out(vty
, "VNI not found\n");
2196 display_vni(vty
, vpn
, json
);
2200 * Display a VNI (upon user query).
2202 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2208 num_vnis
= hashcount(bgp
->vnihash
);
2213 json_object_int_add(json
, "numVnis", num_vnis
);
2215 vty_out(vty
, "Number of VNIs: %u\n", num_vnis
);
2216 vty_out(vty
, "Flags: * - Kernel\n");
2217 vty_out(vty
, " %-10s %-15s %-21s %-25s %-25s %-37s\n", "VNI",
2218 "Orig IP", "RD", "Import RT",
2219 "Export RT", "Tenant-Vrf");
2224 hash_iterate(bgp
->vnihash
,
2225 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2230 * evpn - enable advertisement of default g/w
2232 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2235 if (bgp
->advertise_gw_macip
)
2238 bgp
->advertise_gw_macip
= 1;
2239 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2241 if (vpn
->advertise_gw_macip
)
2244 vpn
->advertise_gw_macip
= 1;
2245 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2252 * evpn - disable advertisement of default g/w
2254 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2255 struct bgpevpn
*vpn
)
2258 if (!bgp
->advertise_gw_macip
)
2261 bgp
->advertise_gw_macip
= 0;
2262 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2264 if (!vpn
->advertise_gw_macip
)
2267 vpn
->advertise_gw_macip
= 0;
2268 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2275 * EVPN (VNI advertisement) enabled. Register with zebra.
2277 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2279 bgp
->advertise_all_vni
= 1;
2280 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2284 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2285 * cache, EVPN routes (delete and withdraw from peers).
2287 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2289 bgp
->advertise_all_vni
= 0;
2290 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2291 bgp_evpn_cleanup_on_disable(bgp
);
2293 #endif /* HAVE_CUMULUS */
2295 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2297 char buf1
[RD_ADDRSTRLEN
];
2299 struct listnode
*node
, *nnode
;
2300 struct ecommunity
*ecom
;
2302 if (is_vni_configured(vpn
)) {
2303 vty_out(vty
, " vni %d\n", vpn
->vni
);
2304 if (is_rd_configured(vpn
))
2305 vty_out(vty
, " rd %s\n",
2306 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2308 if (is_import_rt_configured(vpn
)) {
2309 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2311 ecom_str
= ecommunity_ecom2str(
2312 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2313 vty_out(vty
, " route-target import %s\n",
2315 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2319 if (is_export_rt_configured(vpn
)) {
2320 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2322 ecom_str
= ecommunity_ecom2str(
2323 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2324 vty_out(vty
, " route-target export %s\n",
2326 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2330 if (vpn
->advertise_gw_macip
)
2331 vty_out(vty
, " advertise-default-gw\n");
2333 vty_out(vty
, " exit-vni\n");
2337 static void write_vni_config_for_entry(struct hash_backet
*backet
,
2340 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2341 write_vni_config(vty
, vpn
);
2344 #if defined(HAVE_CUMULUS)
2345 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2346 bgp_evpn_advertise_default_gw_vni_cmd
,
2347 "advertise-default-gw",
2348 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2350 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2351 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2359 evpn_set_advertise_default_gw(bgp
, vpn
);
2364 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2365 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2366 "no advertise-default-gw",
2368 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2370 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2371 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2379 evpn_unset_advertise_default_gw(bgp
, vpn
);
2385 DEFUN (bgp_evpn_advertise_default_gw
,
2386 bgp_evpn_advertise_default_gw_cmd
,
2387 "advertise-default-gw",
2388 "Advertise All default g/w mac-ip routes in EVPN\n")
2390 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2395 evpn_set_advertise_default_gw(bgp
, NULL
);
2400 DEFUN (no_bgp_evpn_advertise_default_gw
,
2401 no_bgp_evpn_advertise_default_gw_cmd
,
2402 "no advertise-default-gw",
2404 "Withdraw All default g/w mac-ip routes from EVPN\n")
2406 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2411 evpn_unset_advertise_default_gw(bgp
, NULL
);
2416 DEFUN (bgp_evpn_advertise_all_vni
,
2417 bgp_evpn_advertise_all_vni_cmd
,
2418 "advertise-all-vni",
2419 "Advertise All local VNIs\n")
2421 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2425 evpn_set_advertise_all_vni(bgp
);
2429 DEFUN (no_bgp_evpn_advertise_all_vni
,
2430 no_bgp_evpn_advertise_all_vni_cmd
,
2431 "no advertise-all-vni",
2433 "Advertise All local VNIs\n")
2435 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2439 evpn_unset_advertise_all_vni(bgp
);
2443 DEFUN (bgp_evpn_advertise_type5
,
2444 bgp_evpn_advertise_type5_cmd
,
2445 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
2446 "Advertise prefix routes\n"
2450 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
2456 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2457 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
2459 if (!(afi
== AFI_IP
) || (afi
== AFI_IP6
)) {
2461 "%%only ipv4 or ipv6 address families are supported");
2465 if (safi
!= SAFI_UNICAST
) {
2467 "%%only ipv4 unicast or ipv6 unicast are supported");
2471 if (afi
== AFI_IP
) {
2473 /* if we are already advertising ipv4 prefix as type-5
2476 if (!CHECK_FLAG(bgp_vrf
->vrf_flags
,
2477 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
)) {
2478 SET_FLAG(bgp_vrf
->vrf_flags
,
2479 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
);
2480 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
2484 /* if we are already advertising ipv6 prefix as type-5
2487 if (!CHECK_FLAG(bgp_vrf
->vrf_flags
,
2488 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
)) {
2489 SET_FLAG(bgp_vrf
->vrf_flags
,
2490 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
);
2491 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
2497 DEFUN (no_bgp_evpn_advertise_type5
,
2498 no_bgp_evpn_advertise_type5_cmd
,
2499 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
2501 "Advertise prefix routes\n"
2505 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
2511 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2512 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
2514 if (!(afi
== AFI_IP
) || (afi
== AFI_IP6
)) {
2516 "%%only ipv4 or ipv6 address families are supported");
2520 if (safi
!= SAFI_UNICAST
) {
2522 "%%only ipv4 unicast or ipv6 unicast are supported");
2526 if (afi
== AFI_IP
) {
2528 /* if we are already advertising ipv4 prefix as type-5
2531 if (CHECK_FLAG(bgp_vrf
->vrf_flags
,
2532 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
)) {
2533 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
2534 UNSET_FLAG(bgp_vrf
->vrf_flags
,
2535 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
);
2539 /* if we are already advertising ipv6 prefix as type-5
2542 if (CHECK_FLAG(bgp_vrf
->vrf_flags
,
2543 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
)) {
2544 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
2545 UNSET_FLAG(bgp_vrf
->vrf_flags
,
2546 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
);
2553 * Display VNI information - for all or a specific VNI
2555 DEFUN(show_bgp_l2vpn_evpn_vni
,
2556 show_bgp_l2vpn_evpn_vni_cmd
,
2557 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2570 json_object
*json
= NULL
;
2572 uj
= use_json(argc
, argv
);
2574 bgp
= bgp_get_default();
2578 if (!argv_find(argv
, argc
, "evpn", &idx
))
2582 json
= json_object_new_object();
2584 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
2586 json_object_string_add(json
, "advertiseGatewayMacip",
2587 bgp
->advertise_gw_macip
2590 json_object_string_add(json
, "advertiseAllVnis",
2595 vty_out(vty
, "Advertise Gateway Macip: %s\n",
2596 bgp
->advertise_gw_macip
? "Enabled"
2599 /* Display all VNIs */
2600 vty_out(vty
, "Advertise All VNI flag: %s\n",
2601 is_evpn_enabled() ? "Enabled" : "Disabled");
2604 evpn_show_all_vnis(vty
, bgp
, json
);
2608 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
2611 /* Display specific VNI */
2612 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
2613 evpn_show_vni(vty
, bgp
, vni
, json
);
2617 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2618 json
, JSON_C_TO_STRING_PRETTY
));
2619 json_object_free(json
);
2626 * Display EVPN neighbor summary.
2628 DEFUN(show_bgp_l2vpn_evpn_summary
,
2629 show_bgp_l2vpn_evpn_summary_cmd
,
2630 "show bgp l2vpn evpn summary [json]",
2635 "Summary of BGP neighbor status\n"
2638 u_char uj
= use_json(argc
, argv
);
2639 return bgp_show_summary_vty(vty
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
2643 * Display global EVPN routing table.
2645 DEFUN(show_bgp_l2vpn_evpn_route
,
2646 show_bgp_l2vpn_evpn_route_cmd
,
2647 "show bgp l2vpn evpn route [type <macip|multicast>] [json]",
2652 "EVPN route information\n"
2653 "Specify Route type\n"
2654 "MAC-IP (Type-2) route\n"
2655 "Multicast (Type-3) route\n"
2662 json_object
*json
= NULL
;
2664 uj
= use_json(argc
, argv
);
2666 bgp
= bgp_get_default();
2671 json
= json_object_new_object();
2674 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2675 /* Specific type is requested */
2676 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2677 type
= BGP_EVPN_MAC_IP_ROUTE
;
2678 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2679 type
= BGP_EVPN_IMET_ROUTE
;
2684 evpn_show_all_routes(vty
, bgp
, type
, json
);
2687 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2688 json
, JSON_C_TO_STRING_PRETTY
));
2689 json_object_free(json
);
2696 * Display global EVPN routing table for specific RD.
2698 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
2699 show_bgp_l2vpn_evpn_route_rd_cmd
,
2700 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>] [json]",
2705 "EVPN route information\n"
2706 "Route Distinguisher\n"
2707 "ASN:XX or A.B.C.D:XX\n"
2708 "Specify Route type\n"
2709 "MAC-IP (Type-2) route\n"
2710 "Multicast (Type-3) route\n"
2715 struct prefix_rd prd
;
2720 json_object
*json
= NULL
;
2722 bgp
= bgp_get_default();
2726 /* check if we need json output */
2727 uj
= use_json(argc
, argv
);
2729 json
= json_object_new_object();
2732 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2733 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2736 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2742 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2743 /* Specific type is requested */
2744 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2745 type
= BGP_EVPN_MAC_IP_ROUTE
;
2746 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2747 type
= BGP_EVPN_IMET_ROUTE
;
2752 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
2755 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2756 json
, JSON_C_TO_STRING_PRETTY
));
2757 json_object_free(json
);
2764 * Display global EVPN routing table for specific RD and MACIP.
2766 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
2767 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
2768 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
2773 "EVPN route information\n"
2774 "Route Distinguisher\n"
2775 "ASN:XX or A.B.C.D:XX\n"
2777 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2779 "IP address (IPv4 or IPv6)\n"
2784 struct prefix_rd prd
;
2791 json_object
*json
= NULL
;
2793 memset(&mac
, 0, sizeof(struct ethaddr
));
2794 memset(&ip
, 0, sizeof(struct ipaddr
));
2796 bgp
= bgp_get_default();
2800 /* check if we need json output */
2801 uj
= use_json(argc
, argv
);
2803 json
= json_object_new_object();
2806 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
2807 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
2809 vty_out(vty
, "%% Malformed Route Distinguisher\n");
2815 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
2816 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
2817 vty_out(vty
, "%% Malformed MAC address\n");
2822 /* get the ip if specified */
2823 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
2824 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
2825 vty_out(vty
, "%% Malformed IP address\n");
2830 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
2833 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2834 json
, JSON_C_TO_STRING_PRETTY
));
2835 json_object_free(json
);
2842 * Display per-VRF EVPN routing table.
2844 DEFUN(show_bgp_l2vpn_evpn_route_vrf
, show_bgp_l2vpn_evpn_route_vrf_cmd
,
2845 "show bgp l2vpn evpn route vrf VRFNAME",
2850 "EVPN route information\n"
2855 char *vrf_name
= NULL
;
2856 struct bgp
*bgp_vrf
= NULL
;
2858 vrf_name
= argv
[vrf_idx
]->arg
;
2859 bgp_vrf
= bgp_lookup_by_name(vrf_name
);
2863 evpn_show_vrf_routes(vty
, bgp_vrf
);
2869 * Display per-VNI EVPN routing table.
2871 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
2872 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
2877 "EVPN route information\n"
2878 "VXLAN Network Identifier\n"
2880 "Specify Route type\n"
2881 "MAC-IP (Type-2) route\n"
2882 "Multicast (Type-3) route\n"
2884 "Remote VTEP IP address\n"
2889 struct in_addr vtep_ip
;
2893 json_object
*json
= NULL
;
2895 bgp
= bgp_get_default();
2899 /* check if we need json output */
2900 uj
= use_json(argc
, argv
);
2902 json
= json_object_new_object();
2904 if (!argv_find(argv
, argc
, "evpn", &idx
))
2909 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2911 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
2912 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
2913 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
2914 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
2915 type
= BGP_EVPN_MAC_IP_ROUTE
;
2916 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
2917 type
= BGP_EVPN_IMET_ROUTE
;
2920 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
2921 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
2922 vty_out(vty
, "%% Malformed VTEP IP address\n");
2929 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
2932 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2933 json
, JSON_C_TO_STRING_PRETTY
));
2934 json_object_free(json
);
2941 * Display per-VNI EVPN routing table for specific MACIP.
2943 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
2944 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
2945 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
2950 "EVPN route information\n"
2951 "VXLAN Network Identifier\n"
2954 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
2956 "IP address (IPv4 or IPv6)\n"
2965 json_object
*json
= NULL
;
2967 bgp
= bgp_get_default();
2971 /* check if we need json output */
2972 uj
= use_json(argc
, argv
);
2974 json
= json_object_new_object();
2976 if (!argv_find(argv
, argc
, "evpn", &idx
))
2980 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
2983 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
2984 vty_out(vty
, "%% Malformed MAC address\n");
2989 memset(&ip
, 0, sizeof(ip
));
2990 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
2992 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
2993 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
2994 vty_out(vty
, "%% Malformed IP address\n");
2999 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3002 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3003 json
, JSON_C_TO_STRING_PRETTY
));
3004 json_object_free(json
);
3011 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3013 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3014 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3015 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3020 "EVPN route information\n"
3021 "VXLAN Network Identifier\n"
3023 "Multicast (Type-3) route\n"
3024 "Originating Router IP address\n"
3030 struct in_addr orig_ip
;
3033 json_object
*json
= NULL
;
3035 bgp
= bgp_get_default();
3039 /* check if we need json output */
3040 uj
= use_json(argc
, argv
);
3042 json
= json_object_new_object();
3044 if (!argv_find(argv
, argc
, "evpn", &idx
))
3048 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3051 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3053 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3057 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3060 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3061 json
, JSON_C_TO_STRING_PRETTY
));
3062 json_object_free(json
);
3069 * Display per-VNI EVPN routing table - for all VNIs.
3071 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3072 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3073 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3078 "EVPN route information\n"
3079 "VXLAN Network Identifier\n"
3082 "Remote VTEP IP address\n"
3086 struct in_addr vtep_ip
;
3089 json_object
*json
= NULL
;
3091 bgp
= bgp_get_default();
3095 /* check if we need json output */
3096 uj
= use_json(argc
, argv
);
3098 json
= json_object_new_object();
3100 if (!argv_find(argv
, argc
, "evpn", &idx
))
3104 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3105 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3106 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3107 vty_out(vty
, "%% Malformed VTEP IP address\n");
3112 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3115 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3116 json
, JSON_C_TO_STRING_PRETTY
));
3117 json_object_free(json
);
3124 * Display EVPN import route-target hash table
3126 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3127 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3128 "show bgp l2vpn evpn vrf-import-rt [json]",
3133 "Show vrf import route target\n"
3137 struct bgp
*bgp_def
= NULL
;
3138 json_object
*json
= NULL
;
3140 bgp_def
= bgp_get_default();
3144 uj
= use_json(argc
, argv
);
3146 json
= json_object_new_object();
3148 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
3151 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3152 json
, JSON_C_TO_STRING_PRETTY
));
3153 json_object_free(json
);
3160 * Display EVPN import route-target hash table
3162 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
3163 show_bgp_l2vpn_evpn_import_rt_cmd
,
3164 "show bgp l2vpn evpn import-rt [json]",
3169 "Show import route target\n"
3174 json_object
*json
= NULL
;
3176 bgp
= bgp_get_default();
3180 uj
= use_json(argc
, argv
);
3182 json
= json_object_new_object();
3184 evpn_show_import_rts(vty
, bgp
, json
);
3187 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3188 json
, JSON_C_TO_STRING_PRETTY
));
3189 json_object_free(json
);
3195 #if defined(HAVE_CUMULUS)
3196 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
3197 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3201 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
3202 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3203 "Summary of BGP neighbor status\n"
3206 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
3207 "show bgp evpn route [type <macip|multicast>]",
3208 SHOW_STR BGP_STR EVPN_HELP_STR
3209 "EVPN route information\n"
3210 "Specify Route type\n"
3211 "MAC-IP (Type-2) route\n"
3212 "Multicast (Type-3) route\n")
3215 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
3216 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3217 SHOW_STR BGP_STR EVPN_HELP_STR
3218 "EVPN route information\n"
3219 "Route Distinguisher\n"
3220 "ASN:XX or A.B.C.D:XX\n"
3221 "Specify Route type\n"
3222 "MAC-IP (Type-2) route\n"
3223 "Multicast (Type-3) route\n")
3226 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
3227 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
3228 SHOW_STR BGP_STR EVPN_HELP_STR
3229 "EVPN route information\n"
3230 "Route Distinguisher\n"
3231 "ASN:XX or A.B.C.D:XX\n"
3233 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3235 "IP address (IPv4 or IPv6)\n")
3238 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
3239 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3240 SHOW_STR BGP_STR EVPN_HELP_STR
3241 "EVPN route information\n"
3242 "VXLAN Network Identifier\n"
3244 "Specify Route type\n"
3245 "MAC-IP (Type-2) route\n"
3246 "Multicast (Type-3) route\n"
3248 "Remote VTEP IP address\n")
3250 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
3251 show_bgp_evpn_route_vni_macip_cmd
,
3252 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3253 SHOW_STR BGP_STR EVPN_HELP_STR
3254 "EVPN route information\n"
3255 "VXLAN Network Identifier\n"
3258 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3260 "IP address (IPv4 or IPv6)\n")
3262 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3263 show_bgp_evpn_route_vni_multicast_cmd
,
3264 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3265 SHOW_STR BGP_STR EVPN_HELP_STR
3266 "EVPN route information\n"
3267 "VXLAN Network Identifier\n"
3269 "Multicast (Type-3) route\n"
3270 "Originating Router IP address\n")
3272 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
3273 "show bgp evpn route vni all [vtep A.B.C.D]",
3274 SHOW_STR BGP_STR EVPN_HELP_STR
3275 "EVPN route information\n"
3276 "VXLAN Network Identifier\n"
3279 "Remote VTEP IP address\n")
3281 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
3282 "show bgp evpn import-rt",
3283 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
3286 DEFUN_NOSH (bgp_evpn_vni
,
3289 "VXLAN Network Identifier\n"
3293 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3294 struct bgpevpn
*vpn
;
3299 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
3301 /* Create VNI, or mark as configured. */
3302 vpn
= evpn_create_update_vni(bgp
, vni
);
3304 vty_out(vty
, "%% Failed to create VNI \n");
3308 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
3312 DEFUN (no_bgp_evpn_vni
,
3313 no_bgp_evpn_vni_cmd
,
3314 "no vni (1-16777215)",
3316 "VXLAN Network Identifier\n"
3320 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3321 struct bgpevpn
*vpn
;
3326 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3328 /* Check if we should disallow. */
3329 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3331 vty_out(vty
, "%% Specified VNI does not exist\n");
3334 if (!is_vni_configured(vpn
)) {
3335 vty_out(vty
, "%% Specified VNI is not configured\n");
3339 evpn_delete_vni(bgp
, vpn
);
3343 DEFUN_NOSH (exit_vni
,
3346 "Exit from VNI mode\n")
3348 if (vty
->node
== BGP_EVPN_VNI_NODE
)
3349 vty
->node
= BGP_EVPN_NODE
;
3353 DEFUN (bgp_evpn_vrf_rd
,
3354 bgp_evpn_vrf_rd_cmd
,
3355 "rd ASN:NN_OR_IP-ADDRESS:NN",
3356 "Route Distinguisher\n"
3357 "ASN:XX or A.B.C.D:XX\n")
3360 struct prefix_rd prd
;
3361 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3366 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3368 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3372 /* If same as existing value, there is nothing more to do. */
3373 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
3376 /* Configure or update the RD. */
3377 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
3381 DEFUN (no_bgp_evpn_vrf_rd
,
3382 no_bgp_evpn_vrf_rd_cmd
,
3383 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3385 "Route Distinguisher\n"
3386 "ASN:XX or A.B.C.D:XX\n")
3389 struct prefix_rd prd
;
3390 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3395 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3397 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3401 /* Check if we should disallow. */
3402 if (!is_vrf_rd_configured(bgp_vrf
)) {
3403 vty_out(vty
, "%% RD is not configured for this VRF\n");
3407 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
3409 "%% RD specified does not match configuration for this VRF\n");
3413 evpn_unconfigure_vrf_rd(bgp_vrf
);
3417 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
3418 no_bgp_evpn_vrf_rd_without_val_cmd
,
3421 "Route Distinguisher\n")
3423 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3428 /* Check if we should disallow. */
3429 if (!is_vrf_rd_configured(bgp_vrf
)) {
3430 vty_out(vty
, "%% RD is not configured for this VRF\n");
3434 evpn_unconfigure_vrf_rd(bgp_vrf
);
3438 DEFUN (bgp_evpn_vni_rd
,
3439 bgp_evpn_vni_rd_cmd
,
3440 "rd ASN:NN_OR_IP-ADDRESS:NN",
3441 "Route Distinguisher\n"
3442 "ASN:XX or A.B.C.D:XX\n")
3444 struct prefix_rd prd
;
3445 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3446 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3452 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3454 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3458 /* If same as existing value, there is nothing more to do. */
3459 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
3462 /* Configure or update the RD. */
3463 evpn_configure_rd(bgp
, vpn
, &prd
);
3467 DEFUN (no_bgp_evpn_vni_rd
,
3468 no_bgp_evpn_vni_rd_cmd
,
3469 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3471 "Route Distinguisher\n"
3472 "ASN:XX or A.B.C.D:XX\n")
3474 struct prefix_rd prd
;
3475 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3476 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3482 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3484 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3488 /* Check if we should disallow. */
3489 if (!is_rd_configured(vpn
)) {
3490 vty_out(vty
, "%% RD is not configured for this VNI\n");
3494 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
3496 "%% RD specified does not match configuration for this VNI\n");
3500 evpn_unconfigure_rd(bgp
, vpn
);
3504 DEFUN (no_bgp_evpn_vni_rd_without_val
,
3505 no_bgp_evpn_vni_rd_without_val_cmd
,
3508 "Route Distinguisher\n")
3510 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3511 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3516 /* Check if we should disallow. */
3517 if (!is_rd_configured(vpn
)) {
3518 vty_out(vty
, "%% RD is not configured for this VNI\n");
3522 evpn_unconfigure_rd(bgp
, vpn
);
3527 * Loop over all extended-communities in the route-target list rtl and
3528 * return 1 if we find ecomtarget
3530 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
3531 struct ecommunity
*ecomtarget
)
3533 struct listnode
*node
, *nnode
;
3534 struct ecommunity
*ecom
;
3536 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
3537 if (ecommunity_match(ecom
, ecomtarget
))
3544 /* display L3VNI related info for a VRF instance */
3545 DEFUN (show_bgp_vrf_l3vni_info
,
3546 show_bgp_vrf_l3vni_info_cmd
,
3547 "show bgp vrf VRFNAME l3vni info [json]",
3556 char buf
[ETHER_ADDR_STRLEN
];
3557 char buf1
[INET6_ADDRSTRLEN
];
3559 const char *name
= NULL
;
3560 struct bgp
*bgp
= NULL
;
3561 struct listnode
*node
= NULL
;
3562 struct bgpevpn
*vpn
= NULL
;
3563 struct ecommunity
*ecom
= NULL
;
3564 json_object
*json
= NULL
;
3565 json_object
*json_vnis
= NULL
;
3566 json_object
*json_export_rts
= NULL
;
3567 json_object
*json_import_rts
= NULL
;
3568 u_char uj
= use_json(argc
, argv
);
3571 json
= json_object_new_object();
3572 json_vnis
= json_object_new_array();
3573 json_export_rts
= json_object_new_array();
3574 json_import_rts
= json_object_new_array();
3577 name
= argv
[idx_vrf
]->arg
;
3578 bgp
= bgp_lookup_by_name(name
);
3581 vty_out(vty
, "BGP instance for VRF %s not found",
3584 json_object_string_add(json
, "warning",
3585 "BGP instance not found");
3586 vty_out(vty
, "%s\n",
3587 json_object_to_json_string(json
));
3588 json_object_free(json
);
3594 vty_out(vty
, "BGP VRF: %s\n", name
);
3595 vty_out(vty
, " Local-Ip: %s\n",
3596 inet_ntoa(bgp
->originator_ip
));
3597 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
3598 vty_out(vty
, " Rmac: %s\n",
3599 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
3600 vty_out(vty
, " L2-VNI List:\n");
3602 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
3603 vty_out(vty
, "%u ", vpn
->vni
);
3605 vty_out(vty
, " Export-RTs:\n");
3607 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
3608 vty_out(vty
, "%s ", ecommunity_str(ecom
));
3610 vty_out(vty
, " Import-RTs:\n");
3612 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
3613 vty_out(vty
, "%s ", ecommunity_str(ecom
));
3615 vty_out(vty
, " RD: %s\n",
3616 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
3618 json_object_string_add(json
, "vrf", name
);
3619 json_object_string_add(json
, "local-ip",
3620 inet_ntoa(bgp
->originator_ip
));
3621 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
3622 json_object_string_add(json
, "rmac",
3623 prefix_mac2str(&bgp
->rmac
, buf
,
3625 /* list of l2vnis */
3626 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
3627 json_object_array_add(json_vnis
,
3628 json_object_new_int(vpn
->vni
));
3629 json_object_object_add(json
, "l2vnis", json_vnis
);
3632 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
3633 json_object_array_add(json_export_rts
,
3634 json_object_new_string(
3635 ecommunity_str(ecom
)));
3636 json_object_object_add(json
, "export-rts", json_export_rts
);
3639 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
3640 json_object_array_add(json_import_rts
,
3641 json_object_new_string(
3642 ecommunity_str(ecom
)));
3643 json_object_object_add(json
, "import-rts", json_import_rts
);
3644 json_object_string_add(
3646 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
3651 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3652 json
, JSON_C_TO_STRING_PRETTY
));
3653 json_object_free(json
);
3658 /* import/export rt for l3vni-vrf */
3659 DEFUN (bgp_evpn_vrf_rt
,
3660 bgp_evpn_vrf_rt_cmd
,
3661 "route-target <both|import|export> RT",
3663 "import and export\n"
3666 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3669 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3670 struct ecommunity
*ecomadd
= NULL
;
3675 if (!strcmp(argv
[1]->arg
, "import"))
3676 rt_type
= RT_TYPE_IMPORT
;
3677 else if (!strcmp(argv
[1]->arg
, "export"))
3678 rt_type
= RT_TYPE_EXPORT
;
3679 else if (!strcmp(argv
[1]->arg
, "both"))
3680 rt_type
= RT_TYPE_BOTH
;
3682 vty_out(vty
, "%% Invalid Route Target type\n");
3686 /* Add/update the import route-target */
3687 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
3688 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3689 ECOMMUNITY_ROUTE_TARGET
, 0);
3691 vty_out(vty
, "%% Malformed Route Target list\n");
3694 ecommunity_str(ecomadd
);
3696 /* Do nothing if we already have this import route-target */
3697 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
3699 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
3702 /* Add/update the export route-target */
3703 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
3704 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3705 ECOMMUNITY_ROUTE_TARGET
, 0);
3707 vty_out(vty
, "%% Malformed Route Target list\n");
3710 ecommunity_str(ecomadd
);
3712 /* Do nothing if we already have this export route-target */
3713 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
3715 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
3721 DEFUN (no_bgp_evpn_vrf_rt
,
3722 no_bgp_evpn_vrf_rt_cmd
,
3723 "no route-target <both|import|export> RT",
3726 "import and export\n"
3729 "ASN:XX or A.B.C.D:XX\n")
3731 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3732 int rt_type
, found_ecomdel
;
3733 struct ecommunity
*ecomdel
= NULL
;
3738 if (!strcmp(argv
[2]->arg
, "import"))
3739 rt_type
= RT_TYPE_IMPORT
;
3740 else if (!strcmp(argv
[2]->arg
, "export"))
3741 rt_type
= RT_TYPE_EXPORT
;
3742 else if (!strcmp(argv
[2]->arg
, "both"))
3743 rt_type
= RT_TYPE_BOTH
;
3745 vty_out(vty
, "%% Invalid Route Target type\n");
3749 if (rt_type
== RT_TYPE_IMPORT
) {
3750 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
3752 "%% Import RT is not configured for this VRF\n");
3755 } else if (rt_type
== RT_TYPE_EXPORT
) {
3756 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
3758 "%% Export RT is not configured for this VRF\n");
3761 } else if (rt_type
== RT_TYPE_BOTH
) {
3762 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
3763 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
3765 "%% Import/Export RT is not configured for this VRF\n");
3770 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
3772 vty_out(vty
, "%% Malformed Route Target list\n");
3775 ecommunity_str(ecomdel
);
3777 if (rt_type
== RT_TYPE_IMPORT
) {
3778 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
3781 "%% RT specified does not match configuration for this VRF\n");
3784 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
3785 } else if (rt_type
== RT_TYPE_EXPORT
) {
3786 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
3789 "%% RT specified does not match configuration for this VRF\n");
3792 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
3793 } else if (rt_type
== RT_TYPE_BOTH
) {
3796 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
3798 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
3802 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
3804 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
3808 if (!found_ecomdel
) {
3810 "%% RT specified does not match configuration for this VRF\n");
3818 DEFUN (bgp_evpn_vni_rt
,
3819 bgp_evpn_vni_rt_cmd
,
3820 "route-target <both|import|export> RT",
3822 "import and export\n"
3825 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3827 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3828 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3830 struct ecommunity
*ecomadd
= NULL
;
3835 if (!strcmp(argv
[1]->text
, "import"))
3836 rt_type
= RT_TYPE_IMPORT
;
3837 else if (!strcmp(argv
[1]->text
, "export"))
3838 rt_type
= RT_TYPE_EXPORT
;
3839 else if (!strcmp(argv
[1]->text
, "both"))
3840 rt_type
= RT_TYPE_BOTH
;
3842 vty_out(vty
, "%% Invalid Route Target type\n");
3846 /* Add/update the import route-target */
3847 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
3848 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3849 ECOMMUNITY_ROUTE_TARGET
, 0);
3851 vty_out(vty
, "%% Malformed Route Target list\n");
3854 ecommunity_str(ecomadd
);
3856 /* Do nothing if we already have this import route-target */
3857 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
3858 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
3861 /* Add/update the export route-target */
3862 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
3863 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3864 ECOMMUNITY_ROUTE_TARGET
, 0);
3866 vty_out(vty
, "%% Malformed Route Target list\n");
3869 ecommunity_str(ecomadd
);
3871 /* Do nothing if we already have this export route-target */
3872 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
3873 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
3879 DEFUN (no_bgp_evpn_vni_rt
,
3880 no_bgp_evpn_vni_rt_cmd
,
3881 "no route-target <both|import|export> RT",
3884 "import and export\n"
3887 "ASN:XX or A.B.C.D:XX\n")
3889 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3890 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3891 int rt_type
, found_ecomdel
;
3892 struct ecommunity
*ecomdel
= NULL
;
3897 if (!strcmp(argv
[2]->text
, "import"))
3898 rt_type
= RT_TYPE_IMPORT
;
3899 else if (!strcmp(argv
[2]->text
, "export"))
3900 rt_type
= RT_TYPE_EXPORT
;
3901 else if (!strcmp(argv
[2]->text
, "both"))
3902 rt_type
= RT_TYPE_BOTH
;
3904 vty_out(vty
, "%% Invalid Route Target type\n");
3908 /* The user did "no route-target import", check to see if there are any
3909 * import route-targets configured. */
3910 if (rt_type
== RT_TYPE_IMPORT
) {
3911 if (!is_import_rt_configured(vpn
)) {
3913 "%% Import RT is not configured for this VNI\n");
3916 } else if (rt_type
== RT_TYPE_EXPORT
) {
3917 if (!is_export_rt_configured(vpn
)) {
3919 "%% Export RT is not configured for this VNI\n");
3922 } else if (rt_type
== RT_TYPE_BOTH
) {
3923 if (!is_import_rt_configured(vpn
)
3924 && !is_export_rt_configured(vpn
)) {
3926 "%% Import/Export RT is not configured for this VNI\n");
3931 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
3933 vty_out(vty
, "%% Malformed Route Target list\n");
3936 ecommunity_str(ecomdel
);
3938 if (rt_type
== RT_TYPE_IMPORT
) {
3939 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3941 "%% RT specified does not match configuration for this VNI\n");
3944 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3945 } else if (rt_type
== RT_TYPE_EXPORT
) {
3946 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3948 "%% RT specified does not match configuration for this VNI\n");
3951 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3952 } else if (rt_type
== RT_TYPE_BOTH
) {
3955 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
3956 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
3960 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
3961 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
3965 if (!found_ecomdel
) {
3967 "%% RT specified does not match configuration for this VNI\n");
3975 DEFUN (no_bgp_evpn_vni_rt_without_val
,
3976 no_bgp_evpn_vni_rt_without_val_cmd
,
3977 "no route-target <import|export>",
3983 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3984 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3990 if (!strcmp(argv
[2]->text
, "import")) {
3991 rt_type
= RT_TYPE_IMPORT
;
3992 } else if (!strcmp(argv
[2]->text
, "export")) {
3993 rt_type
= RT_TYPE_EXPORT
;
3995 vty_out(vty
, "%% Invalid Route Target type\n");
3999 /* Check if we should disallow. */
4000 if (rt_type
== RT_TYPE_IMPORT
) {
4001 if (!is_import_rt_configured(vpn
)) {
4003 "%% Import RT is not configured for this VNI\n");
4007 if (!is_export_rt_configured(vpn
)) {
4009 "%% Export RT is not configured for this VNI\n");
4014 /* Unconfigure the RT. */
4015 if (rt_type
== RT_TYPE_IMPORT
)
4016 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4018 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
4023 * Output EVPN configuration information.
4025 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4029 hash_iterate(bgp
->vnihash
,
4030 (void (*)(struct hash_backet
*,
4031 void *))write_vni_config_for_entry
,
4034 if (bgp
->advertise_all_vni
)
4035 vty_out(vty
, " advertise-all-vni\n");
4037 if (bgp
->advertise_gw_macip
)
4038 vty_out(vty
, " advertise-default-gw\n");
4040 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_ADVERTISE_IPV4_IN_EVPN
))
4041 vty_out(vty
, " advertise ipv4 unicast\n");
4043 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_ADVERTISE_IPV6_IN_EVPN
))
4044 vty_out(vty
, " advertise ipv6 unicast\n");
4047 void bgp_ethernetvpn_init(void)
4049 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
4050 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
4051 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
4052 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
4053 install_element(VIEW_NODE
,
4054 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
4055 install_element(VIEW_NODE
,
4056 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
4059 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
4062 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
4063 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
4064 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
4065 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
4066 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
4067 #if defined(HAVE_CUMULUS)
4068 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
4069 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
4070 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
4071 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
4072 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
4073 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
4075 /* "show bgp l2vpn evpn" commands. */
4076 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
4077 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
4078 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
4079 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
4080 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
4081 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
4082 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vrf_cmd
);
4083 install_element(VIEW_NODE
,
4084 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
4085 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
4086 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
4087 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
4088 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
4090 /* "show bgp evpn" commands. */
4091 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
4092 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
4093 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
4094 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
4095 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
4096 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
4097 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
4098 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
4099 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
4100 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
4101 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
4103 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4104 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
4105 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4106 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
4107 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
4108 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
4109 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
4110 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
4111 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
4112 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
4113 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
4114 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
4115 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
4116 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
4117 install_element(BGP_EVPN_VNI_NODE
,
4118 &bgp_evpn_advertise_default_gw_vni_cmd
);
4119 install_element(BGP_EVPN_VNI_NODE
,
4120 &no_bgp_evpn_advertise_default_gw_vni_cmd
);