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 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
59 uint8_t type
, sub_type
;
60 struct ecommunity_as eas
;
61 struct ecommunity_ip eip
;
62 struct listnode
*node
, *nnode
;
63 struct bgp
*tmp_bgp_vrf
= NULL
;
64 json_object
*json_rt
= NULL
;
65 json_object
*json_vrfs
= NULL
;
66 char rt_buf
[RT_ADDRSTRLEN
];
69 json_rt
= json_object_new_object();
70 json_vrfs
= json_object_new_array();
73 pnt
= (uint8_t *)&irt
->rt
.val
;
76 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
79 memset(&eas
, 0, sizeof(eas
));
81 case ECOMMUNITY_ENCODE_AS
:
82 eas
.as
= (*pnt
++ << 8);
84 ptr_get_be32(pnt
, &eas
.val
);
86 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
89 json_object_string_add(json_rt
, "rt", rt_buf
);
91 vty_out(vty
, "Route-target: %s", rt_buf
);
95 case ECOMMUNITY_ENCODE_IP
:
96 memcpy(&eip
.ip
, pnt
, 4);
98 eip
.val
= (*pnt
++ << 8);
101 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
105 json_object_string_add(json_rt
, "rt", rt_buf
);
107 vty_out(vty
, "Route-target: %s", rt_buf
);
111 case ECOMMUNITY_ENCODE_AS4
:
112 pnt
= ptr_get_be32(pnt
, &eas
.val
);
113 eas
.val
= (*pnt
++ << 8);
116 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
119 json_object_string_add(json_rt
, "rt", rt_buf
);
121 vty_out(vty
, "Route-target: %s", rt_buf
);
131 "\nList of VRFs importing routes with this route-target:\n");
134 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
136 json_object_array_add(
138 json_object_new_string(
139 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
141 vty_out(vty
, " %s\n",
142 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
146 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
147 json_object_object_add(json
, rt_buf
, json_rt
);
151 static void show_vrf_import_rt_entry(struct hash_backet
*backet
, void *args
[])
153 json_object
*json
= NULL
;
154 struct vty
*vty
= NULL
;
155 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)backet
->data
;
157 vty
= (struct vty
*)args
[0];
158 json
= (struct json_object
*)args
[1];
160 display_vrf_import_rt(vty
, irt
, json
);
163 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
167 uint8_t type
, sub_type
;
168 struct ecommunity_as eas
;
169 struct ecommunity_ip eip
;
170 struct listnode
*node
, *nnode
;
171 struct bgpevpn
*tmp_vpn
;
172 json_object
*json_rt
= NULL
;
173 json_object
*json_vnis
= NULL
;
174 char rt_buf
[RT_ADDRSTRLEN
];
177 json_rt
= json_object_new_object();
178 json_vnis
= json_object_new_array();
181 /* TODO: This needs to go into a function */
183 pnt
= (uint8_t *)&irt
->rt
.val
;
186 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
189 memset(&eas
, 0, sizeof(eas
));
191 case ECOMMUNITY_ENCODE_AS
:
192 eas
.as
= (*pnt
++ << 8);
194 ptr_get_be32(pnt
, &eas
.val
);
196 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
199 json_object_string_add(json_rt
, "rt", rt_buf
);
201 vty_out(vty
, "Route-target: %s", rt_buf
);
205 case ECOMMUNITY_ENCODE_IP
:
206 memcpy(&eip
.ip
, pnt
, 4);
208 eip
.val
= (*pnt
++ << 8);
211 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
215 json_object_string_add(json_rt
, "rt", rt_buf
);
217 vty_out(vty
, "Route-target: %s", rt_buf
);
221 case ECOMMUNITY_ENCODE_AS4
:
222 pnt
= ptr_get_be32(pnt
, &eas
.val
);
223 eas
.val
= (*pnt
++ << 8);
226 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
229 json_object_string_add(json_rt
, "rt", rt_buf
);
231 vty_out(vty
, "Route-target: %s", rt_buf
);
241 "\nList of VNIs importing routes with this route-target:\n");
244 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
246 json_object_array_add(
247 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
249 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
253 json_object_object_add(json_rt
, "vnis", json_vnis
);
254 json_object_object_add(json
, rt_buf
, json_rt
);
258 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
260 json_object
*json
= NULL
;
261 struct vty
*vty
= NULL
;
262 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
267 display_import_rt(vty
, irt
, json
);
272 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
273 struct bgp_node
*rd_rn
,
280 char rd_str
[RD_ADDRSTRLEN
];
282 pnt
= rd_rn
->p
.u
.val
;
284 /* Decode RD type. */
285 type
= decode_rd_type(pnt
);
290 vty_out(vty
, "Route Distinguisher: ");
294 decode_rd_as(pnt
+ 2, &rd_as
);
295 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
299 decode_rd_ip(pnt
+ 2, &rd_ip
);
300 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
305 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
309 vty_out(vty
, "%s\n", rd_str
);
312 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
313 uint64_t tbl_ver
, json_object
*json
)
316 " Network Next Hop Metric LocPrf Weight Path\n";
321 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
322 tbl_ver
, inet_ntoa(bgp
->router_id
));
324 "Status codes: s suppressed, d damped, h history, "
325 "* valid, > best, i - internal\n");
326 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
328 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
329 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
330 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
331 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
332 vty_out(vty
, "%s", ri_header
);
335 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
338 char buf1
[INET6_ADDRSTRLEN
];
340 struct listnode
*node
, *nnode
;
341 struct ecommunity
*ecom
;
342 json_object
*json_import_rtl
= NULL
;
343 json_object
*json_export_rtl
= NULL
;
345 json_import_rtl
= json_export_rtl
= 0;
348 json_import_rtl
= json_object_new_array();
349 json_export_rtl
= json_object_new_array();
350 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
351 json_object_string_add(json
, "type", "L3");
352 json_object_string_add(json
, "kernelFlag", "Yes");
353 json_object_string_add(
355 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
356 json_object_string_add(json
, "originatorIp",
357 inet_ntoa(bgp_vrf
->originator_ip
));
358 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
360 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
361 vty_out(vty
, " (known to the kernel)");
364 vty_out(vty
, " Type: %s\n", "L3");
365 vty_out(vty
, " Tenant VRF: %s\n",
366 vrf_id_to_name(bgp_vrf
->vrf_id
));
367 vty_out(vty
, " RD: %s\n",
368 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
369 vty_out(vty
, " Originator IP: %s\n",
370 inet_ntoa(bgp_vrf
->originator_ip
));
371 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
375 vty_out(vty
, " Import Route Target:\n");
377 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
378 ecom_str
= ecommunity_ecom2str(ecom
,
379 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
382 json_object_array_add(json_import_rtl
,
383 json_object_new_string(ecom_str
));
385 vty_out(vty
, " %s\n", ecom_str
);
387 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
391 json_object_object_add(json
, "importRts", json_import_rtl
);
393 vty_out(vty
, " Export Route Target:\n");
395 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
396 ecom_str
= ecommunity_ecom2str(ecom
,
397 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
400 json_object_array_add(json_export_rtl
,
401 json_object_new_string(ecom_str
));
403 vty_out(vty
, " %s\n", ecom_str
);
405 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
409 json_object_object_add(json
, "exportRts", json_export_rtl
);
412 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
414 struct in_addr
*vtep
;
415 char buf
[ESI_STR_LEN
];
416 char buf1
[RD_ADDRSTRLEN
];
417 char buf2
[INET6_ADDRSTRLEN
];
418 struct listnode
*node
= NULL
;
419 json_object
*json_vteps
= NULL
;
422 json_vteps
= json_object_new_array();
423 json_object_string_add(json
, "esi",
424 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
425 json_object_string_add(json
, "rd",
426 prefix_rd2str(&es
->prd
, buf1
,
428 json_object_string_add(
429 json
, "originatorIp",
430 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
432 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
433 json_object_array_add(
434 json_vteps
, json_object_new_string(
437 json_object_object_add(json
, "vteps", json_vteps
);
439 vty_out(vty
, "ESI: %s\n",
440 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
441 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
443 vty_out(vty
, " Originator-IP: %s\n",
444 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
446 vty_out(vty
, " VTEP List:\n");
447 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
448 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
453 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
455 char buf1
[RD_ADDRSTRLEN
];
457 struct listnode
*node
, *nnode
;
458 struct ecommunity
*ecom
;
459 json_object
*json_import_rtl
= NULL
;
460 json_object
*json_export_rtl
= NULL
;
463 json_import_rtl
= json_object_new_array();
464 json_export_rtl
= json_object_new_array();
465 json_object_int_add(json
, "vni", vpn
->vni
);
466 json_object_string_add(json
, "type", "L2");
467 json_object_string_add(json
, "kernelFlag",
468 is_vni_live(vpn
) ? "Yes" : "No");
469 json_object_string_add(
471 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
472 json_object_string_add(json
, "originatorIp",
473 inet_ntoa(vpn
->originator_ip
));
474 json_object_string_add(json
, "advertiseGatewayMacip",
475 vpn
->advertise_gw_macip
? "Yes" : "No");
477 vty_out(vty
, "VNI: %d", vpn
->vni
);
478 if (is_vni_live(vpn
))
479 vty_out(vty
, " (known to the kernel)");
482 vty_out(vty
, " Type: %s\n", "L2");
483 vty_out(vty
, " Tenant-Vrf: %s\n",
484 vrf_id_to_name(vpn
->tenant_vrf_id
));
485 vty_out(vty
, " RD: %s\n",
486 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
487 vty_out(vty
, " Originator IP: %s\n",
488 inet_ntoa(vpn
->originator_ip
));
489 vty_out(vty
, " Advertise-gw-macip : %s\n",
490 vpn
->advertise_gw_macip
? "Yes" : "No");
494 vty_out(vty
, " Import Route Target:\n");
496 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
497 ecom_str
= ecommunity_ecom2str(ecom
,
498 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
501 json_object_array_add(json_import_rtl
,
502 json_object_new_string(ecom_str
));
504 vty_out(vty
, " %s\n", ecom_str
);
506 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
510 json_object_object_add(json
, "importRts", json_import_rtl
);
512 vty_out(vty
, " Export Route Target:\n");
514 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
515 ecom_str
= ecommunity_ecom2str(ecom
,
516 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
519 json_object_array_add(json_export_rtl
,
520 json_object_new_string(ecom_str
));
522 vty_out(vty
, " %s\n", ecom_str
);
524 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
528 json_object_object_add(json
, "exportRts", json_export_rtl
);
531 static void show_esi_routes(struct bgp
*bgp
,
539 uint32_t prefix_cnt
, path_cnt
;
542 prefix_cnt
= path_cnt
= 0;
544 tbl_ver
= es
->route_table
->version
;
545 for (rn
= bgp_table_top(es
->route_table
); rn
;
546 rn
= bgp_route_next(rn
)) {
547 int add_prefix_to_json
= 0;
548 char prefix_str
[BUFSIZ
];
549 json_object
*json_paths
= NULL
;
550 json_object
*json_prefix
= NULL
;
552 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
556 json_prefix
= json_object_new_object();
559 /* Overall header/legend displayed once. */
561 bgp_evpn_show_route_header(vty
, bgp
,
570 json_paths
= json_object_new_array();
572 /* For EVPN, the prefix is displayed for each path (to fit in
573 * with code that already exists).
575 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
576 json_object
*json_path
= NULL
;
579 json_path
= json_object_new_array();
581 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
584 json_object_array_add(json_paths
, json_path
);
587 add_prefix_to_json
= 1;
590 if (json
&& add_prefix_to_json
) {
591 json_object_string_add(json_prefix
, "prefix",
593 json_object_int_add(json_prefix
, "prefixLen",
595 json_object_object_add(json_prefix
, "paths",
597 json_object_object_add(json
, prefix_str
, json_prefix
);
602 json_object_int_add(json
, "numPrefix", prefix_cnt
);
603 json_object_int_add(json
, "numPaths", path_cnt
);
606 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
608 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
609 prefix_cnt
, path_cnt
);
613 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
614 struct vty
*vty
, struct in_addr vtep_ip
,
619 struct bgp_table
*table
;
622 uint32_t prefix_cnt
, path_cnt
;
624 prefix_cnt
= path_cnt
= 0;
626 table
= vpn
->route_table
;
627 tbl_ver
= table
->version
;
628 for (rn
= bgp_table_top(table
); rn
;
629 rn
= bgp_route_next(rn
)) {
630 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
631 int add_prefix_to_json
= 0;
632 char prefix_str
[BUFSIZ
];
633 json_object
*json_paths
= NULL
;
634 json_object
*json_prefix
= NULL
;
636 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
639 if (type
&& evp
->prefix
.route_type
!= type
)
643 json_prefix
= json_object_new_object();
646 /* Overall header/legend displayed once. */
648 bgp_evpn_show_route_header(vty
, bgp
,
657 json_paths
= json_object_new_array();
659 /* For EVPN, the prefix is displayed for each path (to fit in
660 * with code that already exists).
662 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
663 json_object
*json_path
= NULL
;
666 && !IPV4_ADDR_SAME(&(vtep_ip
),
667 &(ri
->attr
->nexthop
)))
671 json_path
= json_object_new_array();
673 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
676 json_object_array_add(json_paths
, json_path
);
679 add_prefix_to_json
= 1;
682 if (json
&& add_prefix_to_json
) {
683 json_object_string_add(json_prefix
, "prefix",
685 json_object_int_add(json_prefix
, "prefixLen",
687 json_object_object_add(json_prefix
, "paths",
689 json_object_object_add(json
, prefix_str
, json_prefix
);
694 json_object_int_add(json
, "numPrefix", prefix_cnt
);
695 json_object_int_add(json
, "numPaths", path_cnt
);
698 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
699 type
? "(of requested type) " : "");
701 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
702 prefix_cnt
, path_cnt
,
703 type
? " (of requested type)" : "");
707 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
709 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
710 struct vni_walk_ctx
*wctx
= arg
;
711 struct vty
*vty
= wctx
->vty
;
712 json_object
*json
= wctx
->json
;
713 json_object
*json_vni
= NULL
;
714 char vni_str
[VNI_STR_LEN
];
716 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
718 json_vni
= json_object_new_object();
719 json_object_int_add(json_vni
, "vni", vpn
->vni
);
721 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
724 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
727 json_object_object_add(json
, vni_str
, json_vni
);
730 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
733 json_object
*json_vni
= NULL
;
734 json_object
*json_import_rtl
= NULL
;
735 json_object
*json_export_rtl
= NULL
;
737 char buf2
[INET6_ADDRSTRLEN
];
740 struct listnode
*node
, *nnode
;
741 struct ecommunity
*ecom
;
747 json_vni
= json_object_new_object();
748 json_import_rtl
= json_object_new_array();
749 json_export_rtl
= json_object_new_array();
752 /* if an l3vni is present in bgp it is live */
757 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
758 json_object_string_add(json_vni
, "type", "L3");
759 json_object_string_add(json_vni
, "inKernel", "True");
760 json_object_string_add(json_vni
, "originatorIp",
761 inet_ntoa(bgp
->originator_ip
));
762 json_object_string_add(
764 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
766 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
767 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
770 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
771 ecom_str
= ecommunity_ecom2str(ecom
,
772 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
775 json_object_array_add(json_import_rtl
,
776 json_object_new_string(ecom_str
));
778 if (listcount(bgp
->vrf_import_rtl
) > 1)
779 sprintf(rt_buf
, "%s, ...", ecom_str
);
781 sprintf(rt_buf
, "%s", ecom_str
);
782 vty_out(vty
, " %-25s", rt_buf
);
785 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
787 /* If there are multiple import RTs we break here and show only
794 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
796 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
797 ecom_str
= ecommunity_ecom2str(ecom
,
798 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
801 json_object_array_add(json_export_rtl
,
802 json_object_new_string(ecom_str
));
804 if (listcount(bgp
->vrf_export_rtl
) > 1)
805 sprintf(rt_buf
, "%s, ...", ecom_str
);
807 sprintf(rt_buf
, "%s", ecom_str
);
808 vty_out(vty
, " %-25s", rt_buf
);
811 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
813 /* If there are multiple export RTs we break here and show only
820 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
823 char vni_str
[VNI_STR_LEN
];
825 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
826 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
827 json_object_object_add(json
, vni_str
, json_vni
);
833 static void show_es_entry(struct hash_backet
*backet
, void *args
[])
835 char buf
[ESI_STR_LEN
];
836 char buf1
[RD_ADDRSTRLEN
];
837 char buf2
[INET6_ADDRSTRLEN
];
838 struct in_addr
*vtep
= NULL
;
839 struct vty
*vty
= args
[0];
840 json_object
*json
= args
[1];
841 json_object
*json_vteps
= NULL
;
842 struct listnode
*node
= NULL
;
843 struct evpnes
*es
= (struct evpnes
*)backet
->data
;
846 json_vteps
= json_object_new_array();
847 json_object_string_add(json
, "esi",
848 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
849 json_object_string_add(json
, "type",
850 is_es_local(es
) ? "Local" : "Remote");
851 json_object_string_add(json
, "rd",
852 prefix_rd2str(&es
->prd
, buf1
,
854 json_object_string_add(
855 json
, "originatorIp",
856 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
858 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
859 json_object_array_add(json_vteps
,
860 json_object_new_string(
863 json_object_object_add(json
, "vteps", json_vteps
);
865 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
866 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
867 is_es_local(es
) ? "Local" : "Remote",
868 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
869 ipaddr2str(&es
->originator_ip
, buf2
,
871 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
875 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
879 json_object
*json_vni
= NULL
;
880 json_object
*json_import_rtl
= NULL
;
881 json_object
*json_export_rtl
= NULL
;
882 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
884 char buf2
[RD_ADDRSTRLEN
];
887 struct listnode
*node
, *nnode
;
888 struct ecommunity
*ecom
;
894 json_vni
= json_object_new_object();
895 json_import_rtl
= json_object_new_array();
896 json_export_rtl
= json_object_new_array();
900 if (is_vni_live(vpn
))
904 json_object_int_add(json_vni
, "vni", vpn
->vni
);
905 json_object_string_add(json_vni
, "type", "L2");
906 json_object_string_add(json_vni
, "inKernel",
907 is_vni_live(vpn
) ? "True" : "False");
908 json_object_string_add(json_vni
, "originatorIp",
909 inet_ntoa(vpn
->originator_ip
));
910 json_object_string_add(json_vni
, "originatorIp",
911 inet_ntoa(vpn
->originator_ip
));
912 json_object_string_add(
914 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
916 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
917 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
920 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
921 ecom_str
= ecommunity_ecom2str(ecom
,
922 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
925 json_object_array_add(json_import_rtl
,
926 json_object_new_string(ecom_str
));
928 if (listcount(vpn
->import_rtl
) > 1)
929 sprintf(rt_buf
, "%s, ...", ecom_str
);
931 sprintf(rt_buf
, "%s", ecom_str
);
932 vty_out(vty
, " %-25s", rt_buf
);
935 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
937 /* If there are multiple import RTs we break here and show only
944 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
946 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
947 ecom_str
= ecommunity_ecom2str(ecom
,
948 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
951 json_object_array_add(json_export_rtl
,
952 json_object_new_string(ecom_str
));
954 if (listcount(vpn
->export_rtl
) > 1)
955 sprintf(rt_buf
, "%s, ...", ecom_str
);
957 sprintf(rt_buf
, "%s", ecom_str
);
958 vty_out(vty
, " %-25s", rt_buf
);
961 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
963 /* If there are multiple export RTs we break here and show only
970 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
973 char vni_str
[VNI_STR_LEN
];
975 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
976 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
977 json_object_object_add(json
, vni_str
, json_vni
);
983 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
984 enum bgp_show_type type
, void *output_arg
,
985 int option
, uint8_t use_json
)
987 afi_t afi
= AFI_L2VPN
;
989 struct bgp_table
*table
;
996 unsigned long output_count
= 0;
997 unsigned long total_count
= 0;
998 json_object
*json
= NULL
;
999 json_object
*json_nroute
= NULL
;
1000 json_object
*json_array
= NULL
;
1001 json_object
*json_scode
= NULL
;
1002 json_object
*json_ocode
= NULL
;
1004 bgp
= bgp_get_default();
1007 vty_out(vty
, "No BGP process is configured\n");
1009 vty_out(vty
, "{}\n");
1014 json_scode
= json_object_new_object();
1015 json_ocode
= json_object_new_object();
1016 json
= json_object_new_object();
1017 json_nroute
= json_object_new_object();
1019 json_object_string_add(json_scode
, "suppressed", "s");
1020 json_object_string_add(json_scode
, "damped", "d");
1021 json_object_string_add(json_scode
, "history", "h");
1022 json_object_string_add(json_scode
, "valid", "*");
1023 json_object_string_add(json_scode
, "best", ">");
1024 json_object_string_add(json_scode
, "internal", "i");
1026 json_object_string_add(json_ocode
, "igp", "i");
1027 json_object_string_add(json_ocode
, "egp", "e");
1028 json_object_string_add(json_ocode
, "incomplete", "?");
1031 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1032 rn
= bgp_route_next(rn
)) {
1036 continue; /* XXX json TODO */
1038 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1041 if ((table
= rn
->info
) == NULL
)
1045 tbl_ver
= table
->version
;
1047 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1048 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
1050 if (type
== bgp_show_type_neighbor
) {
1051 union sockunion
*su
= output_arg
;
1053 if (ri
->peer
->su_remote
== NULL
1055 ri
->peer
->su_remote
, su
))
1061 == SHOW_DISPLAY_TAGS
) {
1062 json_object_int_add(
1066 json_object_string_add(
1071 json_object_object_add(
1075 json_object_object_add(
1081 if (option
== SHOW_DISPLAY_TAGS
)
1086 == SHOW_DISPLAY_OVERLAY
)
1091 "BGP table version is %" PRIu64
", local router ID is %s\n",
1096 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1098 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1099 vty_out(vty
, V4_HEADER
);
1112 /* Decode RD type. */
1113 type
= decode_rd_type(pnt
);
1114 /* Decode RD value. */
1115 if (type
== RD_TYPE_AS
)
1116 decode_rd_as(pnt
+ 2, &rd_as
);
1117 else if (type
== RD_TYPE_AS4
)
1118 decode_rd_as4(pnt
+ 2, &rd_as
);
1119 else if (type
== RD_TYPE_IP
)
1120 decode_rd_ip(pnt
+ 2, &rd_ip
);
1122 char buffer
[BUFSIZ
];
1123 if (type
== RD_TYPE_AS
1124 || type
== RD_TYPE_AS4
)
1125 sprintf(buffer
, "%u:%d",
1128 else if (type
== RD_TYPE_IP
)
1129 sprintf(buffer
, "%s:%d",
1133 json_object_string_add(
1135 "routeDistinguisher",
1139 "Route Distinguisher: ");
1140 if (type
== RD_TYPE_AS
)
1145 else if (type
== RD_TYPE_AS4
)
1150 else if (type
== RD_TYPE_IP
)
1151 vty_out(vty
, "ip %s:%d",
1155 vty_out(vty
, "\n\n");
1160 json_array
= json_object_new_array();
1163 if (option
== SHOW_DISPLAY_TAGS
)
1164 route_vty_out_tag(vty
, &rm
->p
, ri
, 0,
1167 else if (option
== SHOW_DISPLAY_OVERLAY
)
1168 route_vty_out_overlay(vty
, &rm
->p
, ri
,
1171 route_vty_out(vty
, &rm
->p
, ri
, 0,
1172 SAFI_EVPN
, json_array
);
1177 if (output_count
== 0)
1178 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1180 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1181 output_count
, total_count
);
1185 DEFUN(show_ip_bgp_l2vpn_evpn
,
1186 show_ip_bgp_l2vpn_evpn_cmd
,
1187 "show [ip] bgp l2vpn evpn [json]",
1188 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1190 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1191 use_json(argc
, argv
));
1194 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1195 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1196 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1202 "Display information for a route distinguisher\n"
1203 "VPN Route Distinguisher\n" JSON_STR
)
1205 int idx_ext_community
= 0;
1207 struct prefix_rd prd
;
1209 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1211 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1213 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1216 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1217 use_json(argc
, argv
));
1220 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1221 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1222 "show [ip] bgp l2vpn evpn all tags",
1228 "Display information about all EVPN NLRIs\n"
1229 "Display BGP tags for prefixes\n")
1231 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1235 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1236 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1237 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1243 "Display information for a route distinguisher\n"
1244 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1246 int idx_ext_community
= 0;
1248 struct prefix_rd prd
;
1250 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1252 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1254 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1257 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1261 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1262 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1263 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1269 "Display information about all EVPN NLRIs\n"
1270 "Detailed information on TCP and BGP neighbor connections\n"
1271 "Neighbor to display information about\n"
1272 "Display routes learned from neighbor\n" JSON_STR
)
1278 uint8_t uj
= use_json(argc
, argv
);
1280 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1282 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1285 json_object
*json_no
= NULL
;
1286 json_no
= json_object_new_object();
1287 json_object_string_add(json_no
, "warning",
1288 "Malformed address");
1289 vty_out(vty
, "%s\n",
1290 json_object_to_json_string(json_no
));
1291 json_object_free(json_no
);
1293 vty_out(vty
, "Malformed address: %s\n",
1294 argv
[idx_ipv4
]->arg
);
1298 peer
= peer_lookup(NULL
, &su
);
1299 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1301 json_object
*json_no
= NULL
;
1302 json_no
= json_object_new_object();
1303 json_object_string_add(
1305 "No such neighbor or address family");
1306 vty_out(vty
, "%s\n",
1307 json_object_to_json_string(json_no
));
1308 json_object_free(json_no
);
1310 vty_out(vty
, "%% No such neighbor or address family\n");
1314 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1318 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1319 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1320 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1326 "Display information for a route distinguisher\n"
1327 "VPN Route Distinguisher\n"
1328 "Detailed information on TCP and BGP neighbor connections\n"
1329 "Neighbor to display information about\n"
1330 "Display routes learned from neighbor\n" JSON_STR
)
1332 int idx_ext_community
= 0;
1337 struct prefix_rd prd
;
1338 uint8_t uj
= use_json(argc
, argv
);
1340 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1341 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1343 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1346 json_object
*json_no
= NULL
;
1347 json_no
= json_object_new_object();
1348 json_object_string_add(json_no
, "warning",
1349 "Malformed Route Distinguisher");
1350 vty_out(vty
, "%s\n",
1351 json_object_to_json_string(json_no
));
1352 json_object_free(json_no
);
1354 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1358 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1361 json_object
*json_no
= NULL
;
1362 json_no
= json_object_new_object();
1363 json_object_string_add(json_no
, "warning",
1364 "Malformed address");
1365 vty_out(vty
, "%s\n",
1366 json_object_to_json_string(json_no
));
1367 json_object_free(json_no
);
1369 vty_out(vty
, "Malformed address: %s\n",
1370 argv
[idx_ext_community
]->arg
);
1374 peer
= peer_lookup(NULL
, &su
);
1375 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1377 json_object
*json_no
= NULL
;
1378 json_no
= json_object_new_object();
1379 json_object_string_add(
1381 "No such neighbor or address family");
1382 vty_out(vty
, "%s\n",
1383 json_object_to_json_string(json_no
));
1384 json_object_free(json_no
);
1386 vty_out(vty
, "%% No such neighbor or address family\n");
1390 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1394 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1395 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1396 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1402 "Display information about all EVPN NLRIs\n"
1403 "Detailed information on TCP and BGP neighbor connections\n"
1404 "Neighbor to display information about\n"
1405 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1411 uint8_t uj
= use_json(argc
, argv
);
1413 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1415 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1418 json_object
*json_no
= NULL
;
1419 json_no
= json_object_new_object();
1420 json_object_string_add(json_no
, "warning",
1421 "Malformed address");
1422 vty_out(vty
, "%s\n",
1423 json_object_to_json_string(json_no
));
1424 json_object_free(json_no
);
1426 vty_out(vty
, "Malformed address: %s\n",
1427 argv
[idx_ipv4
]->arg
);
1430 peer
= peer_lookup(NULL
, &su
);
1431 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1433 json_object
*json_no
= NULL
;
1434 json_no
= json_object_new_object();
1435 json_object_string_add(
1437 "No such neighbor or address family");
1438 vty_out(vty
, "%s\n",
1439 json_object_to_json_string(json_no
));
1440 json_object_free(json_no
);
1442 vty_out(vty
, "%% No such neighbor or address family\n");
1446 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1449 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1450 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1451 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1457 "Display information for a route distinguisher\n"
1458 "VPN Route Distinguisher\n"
1459 "Detailed information on TCP and BGP neighbor connections\n"
1460 "Neighbor to display information about\n"
1461 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1463 int idx_ext_community
= 0;
1467 struct prefix_rd prd
;
1469 uint8_t uj
= use_json(argc
, argv
);
1471 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1472 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1474 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1477 json_object
*json_no
= NULL
;
1478 json_no
= json_object_new_object();
1479 json_object_string_add(json_no
, "warning",
1480 "Malformed address");
1481 vty_out(vty
, "%s\n",
1482 json_object_to_json_string(json_no
));
1483 json_object_free(json_no
);
1485 vty_out(vty
, "Malformed address: %s\n",
1486 argv
[idx_ext_community
]->arg
);
1489 peer
= peer_lookup(NULL
, &su
);
1490 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1492 json_object
*json_no
= NULL
;
1493 json_no
= json_object_new_object();
1494 json_object_string_add(
1496 "No such neighbor or address family");
1497 vty_out(vty
, "%s\n",
1498 json_object_to_json_string(json_no
));
1499 json_object_free(json_no
);
1501 vty_out(vty
, "%% No such neighbor or address family\n");
1505 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1508 json_object
*json_no
= NULL
;
1509 json_no
= json_object_new_object();
1510 json_object_string_add(json_no
, "warning",
1511 "Malformed Route Distinguisher");
1512 vty_out(vty
, "%s\n",
1513 json_object_to_json_string(json_no
));
1514 json_object_free(json_no
);
1516 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1520 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1523 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1524 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1525 "show [ip] bgp l2vpn evpn all overlay",
1531 "Display information about all EVPN NLRIs\n"
1532 "Display BGP Overlay Information for prefixes\n")
1534 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1535 SHOW_DISPLAY_OVERLAY
,
1536 use_json(argc
, argv
));
1539 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1540 show_ip_bgp_evpn_rd_overlay_cmd
,
1541 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1547 "Display information for a route distinguisher\n"
1548 "VPN Route Distinguisher\n"
1549 "Display BGP Overlay Information for prefixes\n")
1551 int idx_ext_community
= 0;
1553 struct prefix_rd prd
;
1555 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1557 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1559 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1562 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1563 SHOW_DISPLAY_OVERLAY
,
1564 use_json(argc
, argv
));
1567 /* For testing purpose, static route of MPLS-VPN. */
1568 DEFUN(evpnrt5_network
,
1569 evpnrt5_network_cmd
,
1570 "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]",
1571 "Specify a network to announce via BGP\n"
1574 "Specify Route Distinguisher\n"
1575 "VPN Route Distinguisher\n"
1577 "Ethernet Tag Value\n"
1580 "Ethernet Segment Identifier\n"
1581 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1583 "Gateway IP ( A.B.C.D )\n"
1584 "Gateway IPv6 ( X:X::X:X )\n"
1585 "Router Mac Ext Comm\n"
1586 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1587 "Route-map to modify the attributes\n"
1588 "Name of the route map\n")
1590 int idx_ipv4_prefixlen
= 1;
1591 int idx_route_distinguisher
= 3;
1596 int idx_routermac
= 13;
1598 return bgp_static_set_safi(
1599 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1600 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1601 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1602 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1603 argv
[idx_routermac
]->arg
);
1606 /* For testing purpose, static route of MPLS-VPN. */
1607 DEFUN(no_evpnrt5_network
,
1608 no_evpnrt5_network_cmd
,
1609 "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>",
1611 "Specify a network to announce via BGP\n"
1614 "Specify Route Distinguisher\n"
1615 "VPN Route Distinguisher\n"
1617 "Ethernet Tag Value\n"
1620 "Ethernet Segment Identifier\n"
1621 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1622 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1624 int idx_ipv4_prefixlen
= 2;
1625 int idx_ext_community
= 4;
1630 return bgp_static_unset_safi(
1631 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1632 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1633 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1634 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1637 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1639 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1642 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1644 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1648 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1649 * check that this is a change.
1651 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1652 struct ecommunity
*ecomadd
)
1654 /* If the VNI is "live", we need to uninstall routes using the current
1655 * import RT(s) first before we update the import RT, and subsequently
1658 if (is_vni_live(vpn
))
1659 bgp_evpn_uninstall_routes(bgp
, vpn
);
1661 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1662 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1664 /* If the auto route-target is in use we must remove it */
1665 evpn_import_rt_delete_auto(bgp
, vpn
);
1667 /* Add new RT and rebuild the RT to VNI mapping */
1668 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1670 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1671 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1673 /* Install routes that match new import RT */
1674 if (is_vni_live(vpn
))
1675 bgp_evpn_install_routes(bgp
, vpn
);
1679 * Unconfigure Import RT(s) for a VNI (vty handler).
1681 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1682 struct ecommunity
*ecomdel
)
1684 struct listnode
*node
, *nnode
, *node_to_del
;
1685 struct ecommunity
*ecom
;
1687 /* Along the lines of "configure" except we have to reset to the
1690 if (is_vni_live(vpn
))
1691 bgp_evpn_uninstall_routes(bgp
, vpn
);
1693 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1694 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1696 /* Delete all import RTs */
1697 if (ecomdel
== NULL
) {
1698 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1699 ecommunity_free(&ecom
);
1701 list_delete_all_node(vpn
->import_rtl
);
1704 /* Delete a specific import RT */
1708 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1709 if (ecommunity_match(ecom
, ecomdel
)) {
1710 ecommunity_free(&ecom
);
1717 list_delete_node(vpn
->import_rtl
, node_to_del
);
1720 assert(vpn
->import_rtl
);
1721 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1722 if (list_isempty(vpn
->import_rtl
)) {
1723 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1724 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1726 /* Rebuild the RT to VNI mapping */
1728 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1730 /* Install routes that match new import RT */
1731 if (is_vni_live(vpn
))
1732 bgp_evpn_install_routes(bgp
, vpn
);
1736 * Configure the Export RT for a VNI (vty handler). Caller expected to
1737 * check that this is a change. Note that only a single export RT is
1738 * allowed for a VNI and any change to configuration is implemented as
1739 * a "replace" (similar to other configuration).
1741 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1742 struct ecommunity
*ecomadd
)
1744 /* If the auto route-target is in use we must remove it */
1745 evpn_export_rt_delete_auto(bgp
, vpn
);
1747 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1748 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1750 if (is_vni_live(vpn
))
1751 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1755 * Unconfigure the Export RT for a VNI (vty handler)
1757 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1758 struct ecommunity
*ecomdel
)
1760 struct listnode
*node
, *nnode
, *node_to_del
;
1761 struct ecommunity
*ecom
;
1763 /* Delete all export RTs */
1764 if (ecomdel
== NULL
) {
1765 /* Reset to default and process all routes. */
1766 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1767 ecommunity_free(&ecom
);
1769 list_delete_all_node(vpn
->export_rtl
);
1772 /* Delete a specific export RT */
1776 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1777 if (ecommunity_match(ecom
, ecomdel
)) {
1778 ecommunity_free(&ecom
);
1785 list_delete_node(vpn
->export_rtl
, node_to_del
);
1788 assert(vpn
->export_rtl
);
1789 if (list_isempty(vpn
->export_rtl
)) {
1790 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1791 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1794 if (is_vni_live(vpn
))
1795 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1799 * Configure RD for VRF
1801 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1803 /* If we have already advertise type-5 routes with a diffrent RD, we
1804 * have to delete and withdraw them firs
1806 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1809 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1810 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1812 /* We have a new RD for VRF.
1813 * Advertise all type-5 routes again with the new RD
1815 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1819 * Unconfigure RD for VRF
1821 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1823 /* If we have already advertise type-5 routes with a diffrent RD, we
1824 * have to delete and withdraw them firs
1826 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1828 /* fall back to default RD */
1829 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1830 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1832 /* We have a new RD for VRF.
1833 * Advertise all type-5 routes again with the new RD
1835 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1839 * Configure RD for a VNI (vty handler)
1841 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1842 struct prefix_rd
*rd
)
1844 /* If the VNI is "live", we need to delete and withdraw this VNI's
1845 * local routes with the prior RD first. Then, after updating RD,
1846 * need to re-advertise.
1848 if (is_vni_live(vpn
))
1849 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1852 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1853 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1855 if (is_vni_live(vpn
))
1856 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1860 * Unconfigure RD for a VNI (vty handler)
1862 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1864 /* If the VNI is "live", we need to delete and withdraw this VNI's
1865 * local routes with the prior RD first. Then, after resetting RD
1866 * to automatic value, need to re-advertise.
1868 if (is_vni_live(vpn
))
1869 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1871 /* reset RD to default */
1872 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1874 if (is_vni_live(vpn
))
1875 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1879 * Create VNI, if not already present (VTY handler). Mark as configured.
1881 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1883 struct bgpevpn
*vpn
;
1888 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1890 /* tenant vrf will be updated when we get local_vni_add from
1893 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1896 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1902 /* Mark as configured. */
1903 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1908 * Delete VNI. If VNI does not exist in the system (i.e., just
1909 * configuration), all that is needed is to free it. Otherwise,
1910 * any parameters configured for the VNI need to be reset (with
1911 * appropriate action) and the VNI marked as unconfigured; the
1912 * VNI will continue to exist, purely as a "learnt" entity.
1914 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1916 assert(bgp
->vnihash
);
1918 if (!is_vni_live(vpn
)) {
1919 bgp_evpn_free(bgp
, vpn
);
1923 /* We need to take the unconfigure action for each parameter of this VNI
1924 * that is configured. Some optimization is possible, but not worth the
1925 * additional code for an operation that should be pretty rare.
1927 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1929 /* First, deal with the export side - RD and export RT changes. */
1930 if (is_rd_configured(vpn
))
1931 evpn_unconfigure_rd(bgp
, vpn
);
1932 if (is_export_rt_configured(vpn
))
1933 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1935 /* Next, deal with the import side. */
1936 if (is_import_rt_configured(vpn
))
1937 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1943 * Display import RT mapping to VRFs (vty handler)
1944 * bgp_def: default bgp instance
1946 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1954 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1955 (void (*)(struct hash_backet
*,
1956 void *))show_vrf_import_rt_entry
,
1961 * Display import RT mapping to VNIs (vty handler)
1963 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1972 bgp
->import_rt_hash
,
1973 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1978 * Display EVPN routes for all VNIs - vty handler.
1980 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1981 struct in_addr vtep_ip
, json_object
*json
)
1984 struct vni_walk_ctx wctx
;
1986 num_vnis
= hashcount(bgp
->vnihash
);
1989 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1992 wctx
.vtep_ip
= vtep_ip
;
1994 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1995 void *))show_vni_routes_hash
,
2000 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2002 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2003 vni_t vni
, struct in_addr orig_ip
,
2006 struct bgpevpn
*vpn
;
2007 struct prefix_evpn p
;
2008 struct bgp_node
*rn
;
2009 struct bgp_info
*ri
;
2010 uint32_t path_cnt
= 0;
2013 json_object
*json_paths
= NULL
;
2019 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2021 vty_out(vty
, "VNI not found\n");
2025 /* See if route exists. */
2026 build_evpn_type3_prefix(&p
, orig_ip
);
2027 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2028 if (!rn
|| !rn
->info
) {
2030 vty_out(vty
, "%% Network not in table\n");
2035 json_paths
= json_object_new_array();
2037 /* Prefix and num paths displayed once per prefix. */
2038 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2040 /* Display each path for this prefix. */
2041 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2042 json_object
*json_path
= NULL
;
2045 json_path
= json_object_new_array();
2047 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2051 json_object_array_add(json_paths
, json_path
);
2058 json_object_object_add(json
, "paths", json_paths
);
2060 json_object_int_add(json
, "numPaths", path_cnt
);
2062 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2068 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2069 * By definition, only matching type-2 route will be displayed.
2071 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2072 vni_t vni
, struct ethaddr
*mac
,
2073 struct ipaddr
*ip
, json_object
*json
)
2075 struct bgpevpn
*vpn
;
2076 struct prefix_evpn p
;
2077 struct bgp_node
*rn
;
2078 struct bgp_info
*ri
;
2079 uint32_t path_cnt
= 0;
2082 json_object
*json_paths
= NULL
;
2088 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2091 vty_out(vty
, "VNI not found\n");
2095 /* See if route exists. Look for both non-sticky and sticky. */
2096 build_evpn_type2_prefix(&p
, mac
, ip
);
2097 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2098 if (!rn
|| !rn
->info
) {
2100 vty_out(vty
, "%% Network not in table\n");
2105 json_paths
= json_object_new_array();
2107 /* Prefix and num paths displayed once per prefix. */
2108 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2110 /* Display each path for this prefix. */
2111 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2112 json_object
*json_path
= NULL
;
2115 json_path
= json_object_new_array();
2117 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2121 json_object_array_add(json_paths
, json_path
);
2128 json_object_object_add(json
, "paths", json_paths
);
2130 json_object_int_add(json
, "numPaths", path_cnt
);
2132 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2137 /* Disaplay EVPN routes for a ESI - VTY handler */
2138 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2139 esi_t
*esi
, json_object
*json
)
2141 struct evpnes
*es
= NULL
;
2144 es
= bgp_evpn_lookup_es(bgp
, esi
);
2147 vty_out(vty
, "ESI not found\n");
2151 show_esi_routes(bgp
, es
, vty
, json
);
2155 * Display EVPN routes for a VNI - vty handler.
2156 * If 'type' is non-zero, only routes matching that type are shown.
2157 * If the vtep_ip is non zero, only routes behind that vtep are shown
2159 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2160 int type
, struct in_addr vtep_ip
,
2163 struct bgpevpn
*vpn
;
2166 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2169 vty_out(vty
, "VNI not found\n");
2173 /* Walk this VNI's route table and display appropriate routes. */
2174 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2178 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2179 * IP (vty handler). By definition, only matching type-2 route will be
2182 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2183 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2184 struct ipaddr
*ip
, json_object
*json
)
2186 struct prefix_evpn p
;
2187 struct bgp_node
*rn
;
2188 struct bgp_info
*ri
;
2191 uint32_t path_cnt
= 0;
2192 json_object
*json_paths
= NULL
;
2193 char prefix_str
[BUFSIZ
];
2198 /* See if route exists. Look for both non-sticky and sticky. */
2199 build_evpn_type2_prefix(&p
, mac
, ip
);
2200 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2201 (struct prefix
*)&p
, prd
);
2202 if (!rn
|| !rn
->info
) {
2204 vty_out(vty
, "%% Network not in table\n");
2208 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2209 sizeof(prefix_str
));
2211 /* Prefix and num paths displayed once per prefix. */
2212 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2215 json_paths
= json_object_new_array();
2217 /* Display each path for this prefix. */
2218 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2219 json_object
*json_path
= NULL
;
2222 json_path
= json_object_new_array();
2224 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2228 json_object_array_add(json_paths
, json_path
);
2233 if (json
&& path_cnt
) {
2235 json_object_object_add(json
, prefix_str
, json_paths
);
2236 json_object_int_add(json
, "numPaths", path_cnt
);
2238 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2244 * Display BGP EVPN routing table -- for specific RD (vty handler)
2245 * If 'type' is non-zero, only routes matching that type are shown.
2247 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2248 struct prefix_rd
*prd
, int type
,
2251 struct bgp_node
*rd_rn
;
2252 struct bgp_table
*table
;
2253 struct bgp_node
*rn
;
2254 struct bgp_info
*ri
;
2258 uint32_t prefix_cnt
, path_cnt
;
2259 char rd_str
[RD_ADDRSTRLEN
];
2260 json_object
*json_rd
= NULL
;
2261 int add_rd_to_json
= 0;
2265 prefix_cnt
= path_cnt
= 0;
2267 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2269 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2273 table
= (struct bgp_table
*)rd_rn
->info
;
2278 json_rd
= json_object_new_object();
2279 json_object_string_add(json_rd
, "rd", rd_str
);
2282 /* Display all prefixes with this RD. */
2283 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2284 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2285 json_object
*json_prefix
= NULL
;
2286 json_object
*json_paths
= NULL
;
2287 char prefix_str
[BUFSIZ
];
2288 int add_prefix_to_json
= 0;
2290 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2291 sizeof(prefix_str
));
2293 if (type
&& evp
->prefix
.route_type
!= type
)
2297 json_prefix
= json_object_new_object();
2300 /* RD header and legend - once overall. */
2301 if (rd_header
&& !json
) {
2303 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2305 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2307 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2311 /* Prefix and num paths displayed once per prefix. */
2312 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2319 json_paths
= json_object_new_array();
2321 /* Display each path for this prefix. */
2322 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2323 json_object
*json_path
= NULL
;
2326 json_path
= json_object_new_array();
2328 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2332 json_object_array_add(json_paths
, json_path
);
2335 add_prefix_to_json
= 1;
2339 if (json
&& add_prefix_to_json
) {
2340 json_object_object_add(json_prefix
, "paths",
2342 json_object_object_add(json_rd
, prefix_str
,
2347 if (json
&& add_rd_to_json
)
2348 json_object_object_add(json
, rd_str
, json_rd
);
2351 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2352 json_object_int_add(json
, "numPaths", path_cnt
);
2354 if (prefix_cnt
== 0)
2355 vty_out(vty
, "No prefixes exist with this RD%s\n",
2356 type
? " (of requested type)" : "");
2359 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2360 prefix_cnt
, path_cnt
,
2361 type
? " (of requested type)" : "");
2366 * Display BGP EVPN routing table - all routes (vty handler).
2367 * If 'type' is non-zero, only routes matching that type are shown.
2369 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2372 struct bgp_node
*rd_rn
;
2373 struct bgp_table
*table
;
2374 struct bgp_node
*rn
;
2375 struct bgp_info
*ri
;
2380 uint32_t prefix_cnt
, path_cnt
;
2384 prefix_cnt
= path_cnt
= 0;
2386 /* EVPN routing table is a 2-level table with the first level being
2389 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2390 rd_rn
= bgp_route_next(rd_rn
)) {
2391 char rd_str
[RD_ADDRSTRLEN
];
2392 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2393 int add_rd_to_json
= 0;
2396 table
= (struct bgp_table
*)rd_rn
->info
;
2400 tbl_ver
= table
->version
;
2401 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2405 json_rd
= json_object_new_object();
2406 json_object_string_add(json_rd
, "rd", rd_str
);
2411 /* Display all prefixes for an RD */
2412 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2413 json_object
*json_prefix
=
2414 NULL
; /* contains prefix under a RD */
2415 json_object
*json_paths
=
2416 NULL
; /* array of paths under a prefix*/
2417 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2418 char prefix_str
[BUFSIZ
];
2419 int add_prefix_to_json
= 0;
2421 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2422 prefix_str
, sizeof(prefix_str
));
2424 if (type
&& evp
->prefix
.route_type
!= type
)
2428 /* Overall header/legend displayed once. */
2430 bgp_evpn_show_route_header(vty
, bgp
,
2436 /* RD header - per RD. */
2438 bgp_evpn_show_route_rd_header(
2447 json_prefix
= json_object_new_object();
2448 json_paths
= json_object_new_array();
2449 json_object_string_add(json_prefix
, "prefix",
2451 json_object_int_add(json_prefix
, "prefixLen",
2455 /* For EVPN, the prefix is displayed for each path (to
2457 * with code that already exists).
2459 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2460 json_object
*json_path
= NULL
;
2462 add_prefix_to_json
= 1;
2466 json_path
= json_object_new_array();
2468 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
2472 json_object_array_add(json_paths
,
2476 if (json
&& add_prefix_to_json
) {
2477 json_object_object_add(json_prefix
, "paths",
2479 json_object_object_add(json_rd
, prefix_str
,
2484 if (json
&& add_rd_to_json
)
2485 json_object_object_add(json
, rd_str
, json_rd
);
2489 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2490 json_object_int_add(json
, "numPaths", path_cnt
);
2492 if (prefix_cnt
== 0) {
2493 vty_out(vty
, "No EVPN prefixes %sexist\n",
2494 type
? "(of requested type) " : "");
2496 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2497 prefix_cnt
, path_cnt
,
2498 type
? " (of requested type)" : "");
2503 /* Display specific ES */
2504 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2507 struct evpnes
*es
= NULL
;
2509 es
= bgp_evpn_lookup_es(bgp
, esi
);
2511 display_es(vty
, es
, json
);
2514 vty_out(vty
, "{}\n");
2516 vty_out(vty
, "ESI not found\n");
2522 /* Display all ESs */
2523 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2529 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2530 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2535 hash_iterate(bgp
->esihash
,
2536 (void (*)(struct hash_backet
*, void *))show_es_entry
,
2541 * Display specified VNI (vty handler)
2543 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2547 struct bgpevpn
*vpn
;
2549 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2552 display_vni(vty
, vpn
, json
);
2554 struct bgp
*bgp_temp
;
2555 struct listnode
*node
= NULL
;
2557 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2558 if (bgp_temp
->l3vni
== vni
) {
2560 display_l3vni(vty
, bgp_temp
, json
);
2567 vty_out(vty
, "{}\n");
2569 vty_out(vty
, "VNI not found\n");
2576 * Display a VNI (upon user query).
2578 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2582 struct bgp
*bgp_temp
= NULL
;
2583 struct listnode
*node
;
2587 vty_out(vty
, "Flags: * - Kernel\n");
2588 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2589 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2592 /* print all L2 VNIS */
2595 hash_iterate(bgp
->vnihash
,
2596 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2599 /* print all L3 VNIs */
2600 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2601 show_l3vni_entry(vty
, bgp_temp
, json
);
2605 * evpn - enable advertisement of default g/w
2607 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2610 if (bgp
->advertise_gw_macip
)
2613 bgp
->advertise_gw_macip
= 1;
2614 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2616 if (vpn
->advertise_gw_macip
)
2619 vpn
->advertise_gw_macip
= 1;
2620 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2627 * evpn - disable advertisement of default g/w
2629 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2630 struct bgpevpn
*vpn
)
2633 if (!bgp
->advertise_gw_macip
)
2636 bgp
->advertise_gw_macip
= 0;
2637 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2639 if (!vpn
->advertise_gw_macip
)
2642 vpn
->advertise_gw_macip
= 0;
2643 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2650 * evpn - enable advertisement of default g/w
2652 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2655 struct prefix ip_prefix
;
2656 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2658 /* form the default prefix 0.0.0.0/0 */
2659 memset(&ip_prefix
, 0, sizeof(struct prefix
));
2660 ip_prefix
.family
= afi2family(afi
);
2661 ip_prefix
.prefixlen
= 0;
2664 /* bail if we are already advertising default route */
2665 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2669 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2670 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2671 else if (afi
== AFI_IP6
)
2672 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2673 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2674 bgp_evpn_advertise_type5_route(bgp_vrf
, &ip_prefix
,
2677 /* bail out if we havent advertised the default route */
2678 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2681 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2682 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2683 else if (afi
== AFI_IP6
)
2684 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2685 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2686 bgp_evpn_withdraw_type5_route(bgp_vrf
, &ip_prefix
,
2692 * evpn - enable advertisement of default g/w
2694 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2695 struct bgpevpn
*vpn
)
2697 if (vpn
->advertise_subnet
)
2700 vpn
->advertise_subnet
= 1;
2701 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2705 * evpn - disable advertisement of default g/w
2707 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2709 if (!vpn
->advertise_subnet
)
2712 vpn
->advertise_subnet
= 0;
2713 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2717 * EVPN (VNI advertisement) enabled. Register with zebra.
2719 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2721 bgp
->advertise_all_vni
= 1;
2722 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2726 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2727 * cache, EVPN routes (delete and withdraw from peers).
2729 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2731 bgp
->advertise_all_vni
= 0;
2732 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2733 bgp_evpn_cleanup_on_disable(bgp
);
2737 * EVPN - use RFC8365 to auto-derive RT
2739 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2741 bgp
->advertise_autort_rfc8365
= 1;
2742 bgp_evpn_handle_autort_change(bgp
);
2746 * EVPN - don't use RFC8365 to auto-derive RT
2748 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2750 bgp
->advertise_autort_rfc8365
= 0;
2751 bgp_evpn_handle_autort_change(bgp
);
2754 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2756 char buf1
[RD_ADDRSTRLEN
];
2758 struct listnode
*node
, *nnode
;
2759 struct ecommunity
*ecom
;
2761 if (is_vni_configured(vpn
)) {
2762 vty_out(vty
, " vni %d\n", vpn
->vni
);
2763 if (is_rd_configured(vpn
))
2764 vty_out(vty
, " rd %s\n",
2765 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2767 if (is_import_rt_configured(vpn
)) {
2768 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2770 ecom_str
= ecommunity_ecom2str(
2771 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2772 vty_out(vty
, " route-target import %s\n",
2774 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2778 if (is_export_rt_configured(vpn
)) {
2779 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2781 ecom_str
= ecommunity_ecom2str(
2782 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2783 vty_out(vty
, " route-target export %s\n",
2785 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2789 if (vpn
->advertise_gw_macip
)
2790 vty_out(vty
, " advertise-default-gw\n");
2792 if (vpn
->advertise_subnet
)
2793 vty_out(vty
, " advertise-subnet\n");
2795 vty_out(vty
, " exit-vni\n");
2799 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2800 bgp_evpn_advertise_default_gw_vni_cmd
,
2801 "advertise-default-gw",
2802 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2804 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2805 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2810 evpn_set_advertise_default_gw(bgp
, vpn
);
2815 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2816 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2817 "no advertise-default-gw",
2819 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2821 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2822 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2827 evpn_unset_advertise_default_gw(bgp
, vpn
);
2833 DEFUN (bgp_evpn_advertise_default_gw
,
2834 bgp_evpn_advertise_default_gw_cmd
,
2835 "advertise-default-gw",
2836 "Advertise All default g/w mac-ip routes in EVPN\n")
2838 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2843 evpn_set_advertise_default_gw(bgp
, NULL
);
2848 DEFUN (no_bgp_evpn_advertise_default_gw
,
2849 no_bgp_evpn_advertise_default_gw_cmd
,
2850 "no advertise-default-gw",
2852 "Withdraw All default g/w mac-ip routes from EVPN\n")
2854 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2859 evpn_unset_advertise_default_gw(bgp
, NULL
);
2864 DEFUN (bgp_evpn_advertise_all_vni
,
2865 bgp_evpn_advertise_all_vni_cmd
,
2866 "advertise-all-vni",
2867 "Advertise All local VNIs\n")
2869 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2873 evpn_set_advertise_all_vni(bgp
);
2877 DEFUN (no_bgp_evpn_advertise_all_vni
,
2878 no_bgp_evpn_advertise_all_vni_cmd
,
2879 "no advertise-all-vni",
2881 "Advertise All local VNIs\n")
2883 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2887 evpn_unset_advertise_all_vni(bgp
);
2891 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2892 bgp_evpn_advertise_autort_rfc8365_cmd
,
2893 "autort rfc8365-compatible",
2894 "Auto-derivation of RT\n"
2895 "Auto-derivation of RT using RFC8365\n")
2897 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2901 evpn_set_advertise_autort_rfc8365(bgp
);
2905 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
2906 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
2907 "no autort rfc8365-compatible",
2909 "Auto-derivation of RT\n"
2910 "Auto-derivation of RT using RFC8365\n")
2912 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2916 evpn_unset_advertise_autort_rfc8365(bgp
);
2920 DEFUN (bgp_evpn_default_originate
,
2921 bgp_evpn_default_originate_cmd
,
2922 "default-originate <ipv4 | ipv6>",
2923 "originate a default route\n"
2924 "ipv4 address family\n"
2925 "ipv6 address family\n")
2929 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2933 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2934 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 1);
2938 DEFUN (no_bgp_evpn_default_originate
,
2939 no_bgp_evpn_default_originate_cmd
,
2940 "no default-originate <ipv4 | ipv6>",
2942 "withdraw a default route\n"
2943 "ipv4 address family\n"
2944 "ipv6 address family\n")
2948 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2952 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2953 evpn_process_default_originate_cmd(bgp_vrf
, afi
, 0);
2957 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
2958 bgp_evpn_advertise_vni_subnet_cmd
,
2960 "Advertise the subnet corresponding to VNI\n")
2962 struct bgp
*bgp_vrf
= NULL
;
2963 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2964 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2969 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
2973 evpn_set_advertise_subnet(bgp
, vpn
);
2977 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
2978 no_bgp_evpn_advertise_vni_subnet_cmd
,
2979 "no advertise-subnet",
2981 "Advertise All local VNIs\n")
2983 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2984 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2989 evpn_unset_advertise_subnet(bgp
, vpn
);
2993 DEFUN (bgp_evpn_advertise_type5
,
2994 bgp_evpn_advertise_type5_cmd
,
2995 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
2996 "Advertise prefix routes\n"
2999 "route-map for filtering specific routes\n"
3000 "Name of the route map\n")
3002 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3009 int rmap_changed
= 0;
3011 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3012 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3013 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3015 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3017 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3018 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3021 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3025 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3027 "%%only ipv4 or ipv6 address families are supported");
3031 if (safi
!= SAFI_UNICAST
) {
3033 "%%only ipv4 unicast or ipv6 unicast are supported");
3037 if (afi
== AFI_IP
) {
3039 /* if we are already advertising ipv4 prefix as type-5
3042 if (!rmap_changed
&&
3043 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3044 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3046 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3047 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3050 /* if we are already advertising ipv6 prefix as type-5
3053 if (!rmap_changed
&&
3054 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3055 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3057 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3058 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3062 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3063 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3064 XFREE(MTYPE_ROUTE_MAP_NAME
,
3065 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3066 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3067 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3071 /* set the route-map for advertise command */
3072 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3073 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3074 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3075 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3076 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3079 /* advertise type-5 routes */
3080 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3084 DEFUN (no_bgp_evpn_advertise_type5
,
3085 no_bgp_evpn_advertise_type5_cmd
,
3086 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3088 "Advertise prefix routes\n"
3092 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3098 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3099 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3101 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3103 "%%only ipv4 or ipv6 address families are supported");
3107 if (safi
!= SAFI_UNICAST
) {
3109 "%%only ipv4 unicast or ipv6 unicast are supported");
3113 if (afi
== AFI_IP
) {
3115 /* if we are not advertising ipv4 prefix as type-5
3118 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3119 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3120 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3121 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3122 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3126 /* if we are not advertising ipv6 prefix as type-5
3129 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3130 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3131 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3132 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3133 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3137 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3138 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3139 XFREE(MTYPE_ROUTE_MAP_NAME
,
3140 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3141 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3142 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3149 * Display VNI information - for all or a specific VNI
3151 DEFUN(show_bgp_l2vpn_evpn_vni
,
3152 show_bgp_l2vpn_evpn_vni_cmd
,
3153 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
3162 struct bgp
*bgp_def
;
3166 json_object
*json
= NULL
;
3167 uint32_t num_l2vnis
= 0;
3168 uint32_t num_l3vnis
= 0;
3169 uint32_t num_vnis
= 0;
3170 struct listnode
*node
= NULL
;
3171 struct bgp
*bgp_temp
= NULL
;
3173 uj
= use_json(argc
, argv
);
3175 bgp_def
= bgp_get_default();
3179 if (!argv_find(argv
, argc
, "evpn", &idx
))
3183 json
= json_object_new_object();
3185 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3187 num_l2vnis
= hashcount(bgp_def
->vnihash
);
3189 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3190 if (bgp_temp
->l3vni
)
3193 num_vnis
= num_l2vnis
+ num_l3vnis
;
3195 json_object_string_add(json
, "advertiseGatewayMacip",
3196 bgp_def
->advertise_gw_macip
3199 json_object_string_add(json
, "advertiseAllVnis",
3200 is_evpn_enabled() ? "Enabled"
3202 json_object_int_add(json
, "numVnis", num_vnis
);
3203 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3204 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3206 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3207 bgp_def
->advertise_gw_macip
? "Enabled"
3209 vty_out(vty
, "Advertise All VNI flag: %s\n",
3210 is_evpn_enabled() ? "Enabled" : "Disabled");
3211 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3212 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3214 evpn_show_all_vnis(vty
, bgp_def
, json
);
3218 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3221 /* Display specific VNI */
3222 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3223 evpn_show_vni(vty
, bgp_def
, vni
, json
);
3227 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3228 json
, JSON_C_TO_STRING_PRETTY
));
3229 json_object_free(json
);
3236 DEFUN(show_bgp_l2vpn_evpn_es
,
3237 show_bgp_l2vpn_evpn_es_cmd
,
3238 "show bgp l2vpn evpn es [ESI] [json]",
3243 "ethernet-Segment\n"
3244 "Ethernet-Segment Identifier\n"
3250 json_object
*json
= NULL
;
3251 struct bgp
*bgp
= NULL
;
3253 memset(&esi
, 0, sizeof(esi
));
3254 uj
= use_json(argc
, argv
);
3256 bgp
= bgp_get_default();
3260 if (!argv_find(argv
, argc
, "evpn", &idx
))
3263 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3264 (!uj
&& argc
== (idx
+ 1) + 1)) {
3267 evpn_show_all_es(vty
, bgp
, json
);
3270 /* show a specific ES */
3272 /* get the ESI - ESI-ID is at argv[5] */
3273 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3274 vty_out(vty
, "%% Malformed ESI\n");
3277 evpn_show_es(vty
, bgp
, &esi
, json
);
3281 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3282 json
, JSON_C_TO_STRING_PRETTY
));
3283 json_object_free(json
);
3290 * Display EVPN neighbor summary.
3292 DEFUN(show_bgp_l2vpn_evpn_summary
,
3293 show_bgp_l2vpn_evpn_summary_cmd
,
3294 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3301 "Summary of BGP neighbor status\n"
3305 uint8_t uj
= use_json(argc
, argv
);
3308 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3309 vrf
= argv
[++idx_vrf
]->arg
;
3310 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3314 * Display global EVPN routing table.
3316 DEFUN(show_bgp_l2vpn_evpn_route
,
3317 show_bgp_l2vpn_evpn_route_cmd
,
3318 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3323 "EVPN route information\n"
3324 "Specify Route type\n"
3325 "MAC-IP (Type-2) route\n"
3326 "Multicast (Type-3) route\n"
3327 "Ethernet Segment (type-4) route \n"
3328 "Prefix (type-5 )route\n"
3335 json_object
*json
= NULL
;
3337 uj
= use_json(argc
, argv
);
3339 bgp
= bgp_get_default();
3344 json
= json_object_new_object();
3347 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3348 /* Specific type is requested */
3349 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3350 type
= BGP_EVPN_MAC_IP_ROUTE
;
3351 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3352 type
= BGP_EVPN_IMET_ROUTE
;
3353 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3354 type
= BGP_EVPN_ES_ROUTE
;
3355 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3356 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3361 evpn_show_all_routes(vty
, bgp
, type
, json
);
3364 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3365 json
, JSON_C_TO_STRING_PRETTY
));
3366 json_object_free(json
);
3372 * Display global EVPN routing table for specific RD.
3374 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3375 show_bgp_l2vpn_evpn_route_rd_cmd
,
3376 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3381 "EVPN route information\n"
3382 "Route Distinguisher\n"
3383 "ASN:XX or A.B.C.D:XX\n"
3384 "Specify Route type\n"
3385 "MAC-IP (Type-2) route\n"
3386 "Multicast (Type-3) route\n"
3387 "Ethernet Segment route\n"
3393 struct prefix_rd prd
;
3398 json_object
*json
= NULL
;
3400 bgp
= bgp_get_default();
3404 /* check if we need json output */
3405 uj
= use_json(argc
, argv
);
3407 json
= json_object_new_object();
3410 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3411 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3414 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3420 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3421 /* Specific type is requested */
3422 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3423 type
= BGP_EVPN_MAC_IP_ROUTE
;
3424 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3425 type
= BGP_EVPN_IMET_ROUTE
;
3426 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3427 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3432 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3435 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3436 json
, JSON_C_TO_STRING_PRETTY
));
3437 json_object_free(json
);
3444 * Display global EVPN routing table for specific RD and MACIP.
3446 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3447 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3448 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3453 "EVPN route information\n"
3454 "Route Distinguisher\n"
3455 "ASN:XX or A.B.C.D:XX\n"
3457 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3459 "IP address (IPv4 or IPv6)\n"
3464 struct prefix_rd prd
;
3471 json_object
*json
= NULL
;
3473 memset(&mac
, 0, sizeof(struct ethaddr
));
3474 memset(&ip
, 0, sizeof(struct ipaddr
));
3476 bgp
= bgp_get_default();
3480 /* check if we need json output */
3481 uj
= use_json(argc
, argv
);
3483 json
= json_object_new_object();
3486 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3487 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3489 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3495 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3496 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3497 vty_out(vty
, "%% Malformed MAC address\n");
3502 /* get the ip if specified */
3503 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3504 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3505 vty_out(vty
, "%% Malformed IP address\n");
3510 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3513 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3514 json
, JSON_C_TO_STRING_PRETTY
));
3515 json_object_free(json
);
3521 /* Display per ESI routing table */
3522 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3523 show_bgp_l2vpn_evpn_route_esi_cmd
,
3524 "show bgp l2vpn evpn route esi ESI [json]",
3529 "EVPN route information\n"
3530 "Ethernet Segment Identifier\n"
3536 struct bgp
*bgp
= NULL
;
3537 json_object
*json
= NULL
;
3539 memset(&esi
, 0, sizeof(esi
));
3540 bgp
= bgp_get_default();
3544 uj
= use_json(argc
, argv
);
3546 json
= json_object_new_object();
3548 /* get the ESI - ESI-ID is at argv[6] */
3549 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3550 vty_out(vty
, "%% Malformed ESI\n");
3554 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3557 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3558 json
, JSON_C_TO_STRING_PRETTY
));
3559 json_object_free(json
);
3567 * Display per-VNI EVPN routing table.
3569 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3570 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3575 "EVPN route information\n"
3576 "VXLAN Network Identifier\n"
3578 "Specify Route type\n"
3579 "MAC-IP (Type-2) route\n"
3580 "Multicast (Type-3) route\n"
3582 "Remote VTEP IP address\n"
3587 struct in_addr vtep_ip
;
3591 json_object
*json
= NULL
;
3593 bgp
= bgp_get_default();
3597 /* check if we need json output */
3598 uj
= use_json(argc
, argv
);
3600 json
= json_object_new_object();
3602 if (!argv_find(argv
, argc
, "evpn", &idx
))
3607 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3609 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3610 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3611 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3612 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3613 type
= BGP_EVPN_MAC_IP_ROUTE
;
3614 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3615 type
= BGP_EVPN_IMET_ROUTE
;
3618 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3619 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3620 vty_out(vty
, "%% Malformed VTEP IP address\n");
3627 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3630 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3631 json
, JSON_C_TO_STRING_PRETTY
));
3632 json_object_free(json
);
3639 * Display per-VNI EVPN routing table for specific MACIP.
3641 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3642 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3643 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3648 "EVPN route information\n"
3649 "VXLAN Network Identifier\n"
3652 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3654 "IP address (IPv4 or IPv6)\n"
3663 json_object
*json
= NULL
;
3665 bgp
= bgp_get_default();
3669 /* check if we need json output */
3670 uj
= use_json(argc
, argv
);
3672 json
= json_object_new_object();
3674 if (!argv_find(argv
, argc
, "evpn", &idx
))
3678 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3681 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3682 vty_out(vty
, "%% Malformed MAC address\n");
3687 memset(&ip
, 0, sizeof(ip
));
3688 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3690 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3691 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3692 vty_out(vty
, "%% Malformed IP address\n");
3697 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3700 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3701 json
, JSON_C_TO_STRING_PRETTY
));
3702 json_object_free(json
);
3709 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3711 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3712 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3713 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3718 "EVPN route information\n"
3719 "VXLAN Network Identifier\n"
3721 "Multicast (Type-3) route\n"
3722 "Originating Router IP address\n"
3728 struct in_addr orig_ip
;
3731 json_object
*json
= NULL
;
3733 bgp
= bgp_get_default();
3737 /* check if we need json output */
3738 uj
= use_json(argc
, argv
);
3740 json
= json_object_new_object();
3742 if (!argv_find(argv
, argc
, "evpn", &idx
))
3746 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3749 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3751 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3755 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3758 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3759 json
, JSON_C_TO_STRING_PRETTY
));
3760 json_object_free(json
);
3767 * Display per-VNI EVPN routing table - for all VNIs.
3769 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3770 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3771 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3776 "EVPN route information\n"
3777 "VXLAN Network Identifier\n"
3780 "Remote VTEP IP address\n"
3784 struct in_addr vtep_ip
;
3787 json_object
*json
= NULL
;
3789 bgp
= bgp_get_default();
3793 /* check if we need json output */
3794 uj
= use_json(argc
, argv
);
3796 json
= json_object_new_object();
3798 if (!argv_find(argv
, argc
, "evpn", &idx
))
3802 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3803 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3804 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3805 vty_out(vty
, "%% Malformed VTEP IP address\n");
3810 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3813 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3814 json
, JSON_C_TO_STRING_PRETTY
));
3815 json_object_free(json
);
3822 * Display EVPN import route-target hash table
3824 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3825 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3826 "show bgp l2vpn evpn vrf-import-rt [json]",
3831 "Show vrf import route target\n"
3835 struct bgp
*bgp_def
= NULL
;
3836 json_object
*json
= NULL
;
3838 bgp_def
= bgp_get_default();
3842 uj
= use_json(argc
, argv
);
3844 json
= json_object_new_object();
3846 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
3849 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3850 json
, JSON_C_TO_STRING_PRETTY
));
3851 json_object_free(json
);
3858 * Display EVPN import route-target hash table
3860 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
3861 show_bgp_l2vpn_evpn_import_rt_cmd
,
3862 "show bgp l2vpn evpn import-rt [json]",
3867 "Show import route target\n"
3872 json_object
*json
= NULL
;
3874 bgp
= bgp_get_default();
3878 uj
= use_json(argc
, argv
);
3880 json
= json_object_new_object();
3882 evpn_show_import_rts(vty
, bgp
, json
);
3885 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3886 json
, JSON_C_TO_STRING_PRETTY
));
3887 json_object_free(json
);
3893 DEFUN(test_adv_evpn_type4_route
,
3894 test_adv_evpn_type4_route_cmd
,
3896 "Advertise EVPN ES route\n"
3897 "Ethernet-segment\n"
3898 "Ethernet-Segment Identifier\n")
3903 struct ipaddr vtep_ip
;
3905 bgp
= bgp_get_default();
3907 vty_out(vty
, "%%Default BGP instance not yet created\n");
3911 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
3912 vty_out(vty
, "%%Malformed ESI\n");
3916 vtep_ip
.ipa_type
= IPADDR_V4
;
3917 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3919 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
3921 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
3927 DEFUN(test_withdraw_evpn_type4_route
,
3928 test_withdraw_evpn_type4_route_cmd
,
3930 "Advertise EVPN ES route\n"
3931 "Ethernet-segment\n"
3932 "Ethernet-Segment Identifier\n")
3937 struct ipaddr vtep_ip
;
3939 bgp
= bgp_get_default();
3941 vty_out(vty
, "%%Default BGP instance not yet created\n");
3945 if (!bgp
->peer_self
) {
3946 vty_out(vty
, "%%BGP instance doesnt have self peer\n");
3950 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
3951 vty_out(vty
, "%%Malformed ESI\n");
3955 vtep_ip
.ipa_type
= IPADDR_V4
;
3956 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
3957 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
3959 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
3965 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
3966 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3970 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
3971 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3972 "Summary of BGP neighbor status\n" JSON_STR
)
3974 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
3975 "show bgp evpn route [type <macip|multicast>]",
3976 SHOW_STR BGP_STR EVPN_HELP_STR
3977 "EVPN route information\n"
3978 "Specify Route type\n"
3979 "MAC-IP (Type-2) route\n"
3980 "Multicast (Type-3) route\n")
3983 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
3984 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3985 SHOW_STR BGP_STR EVPN_HELP_STR
3986 "EVPN route information\n"
3987 "Route Distinguisher\n"
3988 "ASN:XX or A.B.C.D:XX\n"
3989 "Specify Route type\n"
3990 "MAC-IP (Type-2) route\n"
3991 "Multicast (Type-3) route\n")
3994 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
3995 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
3996 SHOW_STR BGP_STR EVPN_HELP_STR
3997 "EVPN route information\n"
3998 "Route Distinguisher\n"
3999 "ASN:XX or A.B.C.D:XX\n"
4001 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4003 "IP address (IPv4 or IPv6)\n")
4006 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4007 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
4008 SHOW_STR BGP_STR EVPN_HELP_STR
4009 "EVPN route information\n"
4010 "VXLAN Network Identifier\n"
4012 "Specify Route type\n"
4013 "MAC-IP (Type-2) route\n"
4014 "Multicast (Type-3) route\n"
4016 "Remote VTEP IP address\n")
4018 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4019 show_bgp_evpn_route_vni_macip_cmd
,
4020 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
4021 SHOW_STR BGP_STR EVPN_HELP_STR
4022 "EVPN route information\n"
4023 "VXLAN Network Identifier\n"
4026 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4028 "IP address (IPv4 or IPv6)\n")
4030 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4031 show_bgp_evpn_route_vni_multicast_cmd
,
4032 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
4033 SHOW_STR BGP_STR EVPN_HELP_STR
4034 "EVPN route information\n"
4035 "VXLAN Network Identifier\n"
4037 "Multicast (Type-3) route\n"
4038 "Originating Router IP address\n")
4040 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4041 "show bgp evpn route vni all [vtep A.B.C.D]",
4042 SHOW_STR BGP_STR EVPN_HELP_STR
4043 "EVPN route information\n"
4044 "VXLAN Network Identifier\n"
4047 "Remote VTEP IP address\n")
4049 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4050 "show bgp evpn import-rt",
4051 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4053 DEFUN_NOSH (bgp_evpn_vni
,
4056 "VXLAN Network Identifier\n"
4060 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4061 struct bgpevpn
*vpn
;
4066 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4068 /* Create VNI, or mark as configured. */
4069 vpn
= evpn_create_update_vni(bgp
, vni
);
4071 vty_out(vty
, "%% Failed to create VNI \n");
4075 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4079 DEFUN (no_bgp_evpn_vni
,
4080 no_bgp_evpn_vni_cmd
,
4081 "no vni (1-16777215)",
4083 "VXLAN Network Identifier\n"
4087 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4088 struct bgpevpn
*vpn
;
4093 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4095 /* Check if we should disallow. */
4096 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4098 vty_out(vty
, "%% Specified VNI does not exist\n");
4101 if (!is_vni_configured(vpn
)) {
4102 vty_out(vty
, "%% Specified VNI is not configured\n");
4106 evpn_delete_vni(bgp
, vpn
);
4110 DEFUN_NOSH (exit_vni
,
4113 "Exit from VNI mode\n")
4115 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4116 vty
->node
= BGP_EVPN_NODE
;
4120 DEFUN (bgp_evpn_vrf_rd
,
4121 bgp_evpn_vrf_rd_cmd
,
4122 "rd ASN:NN_OR_IP-ADDRESS:NN",
4123 "Route Distinguisher\n"
4124 "ASN:XX or A.B.C.D:XX\n")
4127 struct prefix_rd prd
;
4128 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4133 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4135 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4139 /* If same as existing value, there is nothing more to do. */
4140 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4143 /* Configure or update the RD. */
4144 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4148 DEFUN (no_bgp_evpn_vrf_rd
,
4149 no_bgp_evpn_vrf_rd_cmd
,
4150 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4152 "Route Distinguisher\n"
4153 "ASN:XX or A.B.C.D:XX\n")
4156 struct prefix_rd prd
;
4157 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4162 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4164 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4168 /* Check if we should disallow. */
4169 if (!is_vrf_rd_configured(bgp_vrf
)) {
4170 vty_out(vty
, "%% RD is not configured for this VRF\n");
4174 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4176 "%% RD specified does not match configuration for this VRF\n");
4180 evpn_unconfigure_vrf_rd(bgp_vrf
);
4184 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4185 no_bgp_evpn_vrf_rd_without_val_cmd
,
4188 "Route Distinguisher\n")
4190 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4195 /* Check if we should disallow. */
4196 if (!is_vrf_rd_configured(bgp_vrf
)) {
4197 vty_out(vty
, "%% RD is not configured for this VRF\n");
4201 evpn_unconfigure_vrf_rd(bgp_vrf
);
4205 DEFUN (bgp_evpn_vni_rd
,
4206 bgp_evpn_vni_rd_cmd
,
4207 "rd ASN:NN_OR_IP-ADDRESS:NN",
4208 "Route Distinguisher\n"
4209 "ASN:XX or A.B.C.D:XX\n")
4211 struct prefix_rd prd
;
4212 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4213 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4219 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4221 "This command is only supported under Default VRF\n");
4225 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4227 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4231 /* If same as existing value, there is nothing more to do. */
4232 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4235 /* Configure or update the RD. */
4236 evpn_configure_rd(bgp
, vpn
, &prd
);
4240 DEFUN (no_bgp_evpn_vni_rd
,
4241 no_bgp_evpn_vni_rd_cmd
,
4242 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4244 "Route Distinguisher\n"
4245 "ASN:XX or A.B.C.D:XX\n")
4247 struct prefix_rd prd
;
4248 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4249 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4255 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4257 "This command is only supported under Default VRF\n");
4261 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4263 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4267 /* Check if we should disallow. */
4268 if (!is_rd_configured(vpn
)) {
4269 vty_out(vty
, "%% RD is not configured for this VNI\n");
4273 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4275 "%% RD specified does not match configuration for this VNI\n");
4279 evpn_unconfigure_rd(bgp
, vpn
);
4283 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4284 no_bgp_evpn_vni_rd_without_val_cmd
,
4287 "Route Distinguisher\n")
4289 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4290 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4295 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4297 "This command is only supported under Default VRF\n");
4301 /* Check if we should disallow. */
4302 if (!is_rd_configured(vpn
)) {
4303 vty_out(vty
, "%% RD is not configured for this VNI\n");
4307 evpn_unconfigure_rd(bgp
, vpn
);
4312 * Loop over all extended-communities in the route-target list rtl and
4313 * return 1 if we find ecomtarget
4315 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4316 struct ecommunity
*ecomtarget
)
4318 struct listnode
*node
, *nnode
;
4319 struct ecommunity
*ecom
;
4321 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4322 if (ecommunity_match(ecom
, ecomtarget
))
4329 /* display L3VNI related info for a VRF instance */
4330 DEFUN (show_bgp_vrf_l3vni_info
,
4331 show_bgp_vrf_l3vni_info_cmd
,
4332 "show bgp vrf VRFNAME vni [json]",
4340 char buf
[ETHER_ADDR_STRLEN
];
4341 char buf1
[INET6_ADDRSTRLEN
];
4343 const char *name
= NULL
;
4344 struct bgp
*bgp
= NULL
;
4345 struct listnode
*node
= NULL
;
4346 struct bgpevpn
*vpn
= NULL
;
4347 struct ecommunity
*ecom
= NULL
;
4348 json_object
*json
= NULL
;
4349 json_object
*json_vnis
= NULL
;
4350 json_object
*json_export_rts
= NULL
;
4351 json_object
*json_import_rts
= NULL
;
4352 uint8_t uj
= use_json(argc
, argv
);
4355 json
= json_object_new_object();
4356 json_vnis
= json_object_new_array();
4357 json_export_rts
= json_object_new_array();
4358 json_import_rts
= json_object_new_array();
4361 name
= argv
[idx_vrf
]->arg
;
4362 bgp
= bgp_lookup_by_name(name
);
4365 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4367 json_object_string_add(json
, "warning",
4368 "BGP instance not found");
4369 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4370 json_object_free(json
);
4376 vty_out(vty
, "BGP VRF: %s\n", name
);
4377 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4378 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4379 vty_out(vty
, " Rmac: %s\n",
4380 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4381 vty_out(vty
, " VNI Filter: %s\n",
4382 CHECK_FLAG(bgp
->vrf_flags
,
4383 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4384 ? "prefix-routes-only"
4386 vty_out(vty
, " L2-VNI List:\n");
4388 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4389 vty_out(vty
, "%u ", vpn
->vni
);
4391 vty_out(vty
, " Export-RTs:\n");
4393 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4394 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4396 vty_out(vty
, " Import-RTs:\n");
4398 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4399 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4401 vty_out(vty
, " RD: %s\n",
4402 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4404 json_object_string_add(json
, "vrf", name
);
4405 json_object_string_add(json
, "local-ip",
4406 inet_ntoa(bgp
->originator_ip
));
4407 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4408 json_object_string_add(
4410 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4411 json_object_string_add(
4413 CHECK_FLAG(bgp
->vrf_flags
,
4414 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4415 ? "prefix-routes-only"
4417 /* list of l2vnis */
4418 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4419 json_object_array_add(json_vnis
,
4420 json_object_new_int(vpn
->vni
));
4421 json_object_object_add(json
, "l2vnis", json_vnis
);
4424 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4425 json_object_array_add(
4427 json_object_new_string(ecommunity_str(ecom
)));
4428 json_object_object_add(json
, "export-rts", json_export_rts
);
4431 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4432 json_object_array_add(
4434 json_object_new_string(ecommunity_str(ecom
)));
4435 json_object_object_add(json
, "import-rts", json_import_rts
);
4436 json_object_string_add(
4438 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4442 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4443 json
, JSON_C_TO_STRING_PRETTY
));
4444 json_object_free(json
);
4449 /* import/export rt for l3vni-vrf */
4450 DEFUN (bgp_evpn_vrf_rt
,
4451 bgp_evpn_vrf_rt_cmd
,
4452 "route-target <both|import|export> RT",
4454 "import and export\n"
4457 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4460 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4461 struct ecommunity
*ecomadd
= NULL
;
4466 if (!strcmp(argv
[1]->arg
, "import"))
4467 rt_type
= RT_TYPE_IMPORT
;
4468 else if (!strcmp(argv
[1]->arg
, "export"))
4469 rt_type
= RT_TYPE_EXPORT
;
4470 else if (!strcmp(argv
[1]->arg
, "both"))
4471 rt_type
= RT_TYPE_BOTH
;
4473 vty_out(vty
, "%% Invalid Route Target type\n");
4477 /* Add/update the import route-target */
4478 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4479 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4480 ECOMMUNITY_ROUTE_TARGET
, 0);
4482 vty_out(vty
, "%% Malformed Route Target list\n");
4485 ecommunity_str(ecomadd
);
4487 /* Do nothing if we already have this import route-target */
4488 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4489 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4492 /* Add/update the export route-target */
4493 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4494 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4495 ECOMMUNITY_ROUTE_TARGET
, 0);
4497 vty_out(vty
, "%% Malformed Route Target list\n");
4500 ecommunity_str(ecomadd
);
4502 /* Do nothing if we already have this export route-target */
4503 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4504 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4510 DEFUN (no_bgp_evpn_vrf_rt
,
4511 no_bgp_evpn_vrf_rt_cmd
,
4512 "no route-target <both|import|export> RT",
4515 "import and export\n"
4518 "ASN:XX or A.B.C.D:XX\n")
4520 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4521 int rt_type
, found_ecomdel
;
4522 struct ecommunity
*ecomdel
= NULL
;
4527 if (!strcmp(argv
[2]->arg
, "import"))
4528 rt_type
= RT_TYPE_IMPORT
;
4529 else if (!strcmp(argv
[2]->arg
, "export"))
4530 rt_type
= RT_TYPE_EXPORT
;
4531 else if (!strcmp(argv
[2]->arg
, "both"))
4532 rt_type
= RT_TYPE_BOTH
;
4534 vty_out(vty
, "%% Invalid Route Target type\n");
4538 if (rt_type
== RT_TYPE_IMPORT
) {
4539 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4541 "%% Import RT is not configured for this VRF\n");
4544 } else if (rt_type
== RT_TYPE_EXPORT
) {
4545 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4547 "%% Export RT is not configured for this VRF\n");
4550 } else if (rt_type
== RT_TYPE_BOTH
) {
4551 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4552 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4554 "%% Import/Export RT is not configured for this VRF\n");
4559 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4561 vty_out(vty
, "%% Malformed Route Target list\n");
4564 ecommunity_str(ecomdel
);
4566 if (rt_type
== RT_TYPE_IMPORT
) {
4567 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4570 "%% RT specified does not match configuration for this VRF\n");
4573 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4574 } else if (rt_type
== RT_TYPE_EXPORT
) {
4575 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4578 "%% RT specified does not match configuration for this VRF\n");
4581 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4582 } else if (rt_type
== RT_TYPE_BOTH
) {
4585 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4587 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4591 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4593 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4597 if (!found_ecomdel
) {
4599 "%% RT specified does not match configuration for this VRF\n");
4607 DEFUN (bgp_evpn_vni_rt
,
4608 bgp_evpn_vni_rt_cmd
,
4609 "route-target <both|import|export> RT",
4611 "import and export\n"
4614 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4616 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4617 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4619 struct ecommunity
*ecomadd
= NULL
;
4624 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4626 "This command is only supported under Default VRF\n");
4630 if (!strcmp(argv
[1]->text
, "import"))
4631 rt_type
= RT_TYPE_IMPORT
;
4632 else if (!strcmp(argv
[1]->text
, "export"))
4633 rt_type
= RT_TYPE_EXPORT
;
4634 else if (!strcmp(argv
[1]->text
, "both"))
4635 rt_type
= RT_TYPE_BOTH
;
4637 vty_out(vty
, "%% Invalid Route Target type\n");
4641 /* Add/update the import route-target */
4642 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4643 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4644 ECOMMUNITY_ROUTE_TARGET
, 0);
4646 vty_out(vty
, "%% Malformed Route Target list\n");
4649 ecommunity_str(ecomadd
);
4651 /* Do nothing if we already have this import route-target */
4652 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4653 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4656 /* Add/update the export route-target */
4657 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4658 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4659 ECOMMUNITY_ROUTE_TARGET
, 0);
4661 vty_out(vty
, "%% Malformed Route Target list\n");
4664 ecommunity_str(ecomadd
);
4666 /* Do nothing if we already have this export route-target */
4667 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4668 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4674 DEFUN (no_bgp_evpn_vni_rt
,
4675 no_bgp_evpn_vni_rt_cmd
,
4676 "no route-target <both|import|export> RT",
4679 "import and export\n"
4682 "ASN:XX or A.B.C.D:XX\n")
4684 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4685 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4686 int rt_type
, found_ecomdel
;
4687 struct ecommunity
*ecomdel
= NULL
;
4692 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4694 "This command is only supported under Default VRF\n");
4698 if (!strcmp(argv
[2]->text
, "import"))
4699 rt_type
= RT_TYPE_IMPORT
;
4700 else if (!strcmp(argv
[2]->text
, "export"))
4701 rt_type
= RT_TYPE_EXPORT
;
4702 else if (!strcmp(argv
[2]->text
, "both"))
4703 rt_type
= RT_TYPE_BOTH
;
4705 vty_out(vty
, "%% Invalid Route Target type\n");
4709 /* The user did "no route-target import", check to see if there are any
4710 * import route-targets configured. */
4711 if (rt_type
== RT_TYPE_IMPORT
) {
4712 if (!is_import_rt_configured(vpn
)) {
4714 "%% Import RT is not configured for this VNI\n");
4717 } else if (rt_type
== RT_TYPE_EXPORT
) {
4718 if (!is_export_rt_configured(vpn
)) {
4720 "%% Export RT is not configured for this VNI\n");
4723 } else if (rt_type
== RT_TYPE_BOTH
) {
4724 if (!is_import_rt_configured(vpn
)
4725 && !is_export_rt_configured(vpn
)) {
4727 "%% Import/Export RT is not configured for this VNI\n");
4732 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4734 vty_out(vty
, "%% Malformed Route Target list\n");
4737 ecommunity_str(ecomdel
);
4739 if (rt_type
== RT_TYPE_IMPORT
) {
4740 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4742 "%% RT specified does not match configuration for this VNI\n");
4745 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4746 } else if (rt_type
== RT_TYPE_EXPORT
) {
4747 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4749 "%% RT specified does not match configuration for this VNI\n");
4752 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4753 } else if (rt_type
== RT_TYPE_BOTH
) {
4756 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4757 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4761 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4762 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4766 if (!found_ecomdel
) {
4768 "%% RT specified does not match configuration for this VNI\n");
4776 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4777 no_bgp_evpn_vni_rt_without_val_cmd
,
4778 "no route-target <import|export>",
4784 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4785 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4791 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4793 "This command is only supported under Default VRF\n");
4797 if (!strcmp(argv
[2]->text
, "import")) {
4798 rt_type
= RT_TYPE_IMPORT
;
4799 } else if (!strcmp(argv
[2]->text
, "export")) {
4800 rt_type
= RT_TYPE_EXPORT
;
4802 vty_out(vty
, "%% Invalid Route Target type\n");
4806 /* Check if we should disallow. */
4807 if (rt_type
== RT_TYPE_IMPORT
) {
4808 if (!is_import_rt_configured(vpn
)) {
4810 "%% Import RT is not configured for this VNI\n");
4814 if (!is_export_rt_configured(vpn
)) {
4816 "%% Export RT is not configured for this VNI\n");
4821 /* Unconfigure the RT. */
4822 if (rt_type
== RT_TYPE_IMPORT
)
4823 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4825 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
4829 static int vni_cmp(const void **a
, const void **b
)
4831 const struct bgpevpn
*first
= *a
;
4832 const struct bgpevpn
*secnd
= *b
;
4834 return secnd
->vni
- first
->vni
;
4838 * Output EVPN configuration information.
4840 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4843 char buf1
[RD_ADDRSTRLEN
];
4846 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
4847 struct listnode
*ln
;
4848 struct bgpevpn
*data
;
4850 list_sort(vnilist
, vni_cmp
);
4851 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
4852 write_vni_config(vty
, data
);
4854 list_delete_and_null(&vnilist
);
4857 if (bgp
->advertise_all_vni
)
4858 vty_out(vty
, " advertise-all-vni\n");
4860 if (bgp
->advertise_autort_rfc8365
)
4861 vty_out(vty
, " autort rfc8365-compatible\n");
4863 if (bgp
->advertise_gw_macip
)
4864 vty_out(vty
, " advertise-default-gw\n");
4866 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4867 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
4868 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
4869 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
4870 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
4872 vty_out(vty
, " advertise ipv4 unicast\n");
4875 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4876 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
4877 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
4878 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
4879 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
4881 vty_out(vty
, " advertise ipv6 unicast\n");
4884 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4885 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
4886 vty_out(vty
, " default-originate ipv4\n");
4888 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4889 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
4890 vty_out(vty
, " default-originate ipv6\n");
4892 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
4893 vty_out(vty
, " rd %s\n",
4894 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
4896 /* import route-target */
4897 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4899 struct listnode
*node
, *nnode
;
4900 struct ecommunity
*ecom
;
4902 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
4904 ecom_str
= ecommunity_ecom2str(
4905 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4906 vty_out(vty
, " route-target import %s\n", ecom_str
);
4907 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4911 /* export route-target */
4912 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4914 struct listnode
*node
, *nnode
;
4915 struct ecommunity
*ecom
;
4917 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
4919 ecom_str
= ecommunity_ecom2str(
4920 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4921 vty_out(vty
, " route-target export %s\n", ecom_str
);
4922 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4927 void bgp_ethernetvpn_init(void)
4929 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
4930 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
4931 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
4932 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
4933 install_element(VIEW_NODE
,
4934 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
4935 install_element(VIEW_NODE
,
4936 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
4939 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
4942 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
4943 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
4944 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
4945 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
4946 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
4947 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
4948 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
4949 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
4950 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
4951 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
4952 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
4953 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
4954 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
4955 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
4956 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
4959 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
4960 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
4962 /* "show bgp l2vpn evpn" commands. */
4963 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
4964 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
4965 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
4966 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
4967 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
4968 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
4969 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
4970 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
4971 install_element(VIEW_NODE
,
4972 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
4973 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
4974 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
4975 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
4976 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
4978 /* "show bgp evpn" commands. */
4979 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
4980 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
4981 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
4982 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
4983 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
4984 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
4985 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
4986 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
4987 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
4988 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
4989 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
4991 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4992 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
4993 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4994 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
4995 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
4996 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
4997 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
4998 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
4999 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5000 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5001 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5002 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5003 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5004 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5005 install_element(BGP_EVPN_VNI_NODE
,
5006 &bgp_evpn_advertise_default_gw_vni_cmd
);
5007 install_element(BGP_EVPN_VNI_NODE
,
5008 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5009 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5010 install_element(BGP_EVPN_VNI_NODE
,
5011 &no_bgp_evpn_advertise_vni_subnet_cmd
);