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_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
41 #define SHOW_DISPLAY_STANDARD 0
42 #define SHOW_DISPLAY_TAGS 1
43 #define SHOW_DISPLAY_OVERLAY 2
44 #define VNI_STR_LEN 32
47 * Context for VNI hash walk - used by callbacks.
52 struct in_addr vtep_ip
;
56 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
60 uint8_t type
, sub_type
;
61 struct ecommunity_as eas
;
62 struct ecommunity_ip eip
;
63 struct listnode
*node
, *nnode
;
64 struct bgp
*tmp_bgp_vrf
= NULL
;
65 json_object
*json_rt
= NULL
;
66 json_object
*json_vrfs
= NULL
;
67 char rt_buf
[RT_ADDRSTRLEN
];
70 json_rt
= json_object_new_object();
71 json_vrfs
= json_object_new_array();
74 pnt
= (uint8_t *)&irt
->rt
.val
;
77 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
80 memset(&eas
, 0, sizeof(eas
));
82 case ECOMMUNITY_ENCODE_AS
:
83 eas
.as
= (*pnt
++ << 8);
85 ptr_get_be32(pnt
, &eas
.val
);
87 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
90 json_object_string_add(json_rt
, "rt", rt_buf
);
92 vty_out(vty
, "Route-target: %s", rt_buf
);
96 case ECOMMUNITY_ENCODE_IP
:
97 memcpy(&eip
.ip
, pnt
, 4);
99 eip
.val
= (*pnt
++ << 8);
102 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
106 json_object_string_add(json_rt
, "rt", rt_buf
);
108 vty_out(vty
, "Route-target: %s", rt_buf
);
112 case ECOMMUNITY_ENCODE_AS4
:
113 pnt
= ptr_get_be32(pnt
, &eas
.val
);
114 eas
.val
= (*pnt
++ << 8);
117 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
132 "\nList of VRFs importing routes with this route-target:\n");
135 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
137 json_object_array_add(
139 json_object_new_string(
140 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
142 vty_out(vty
, " %s\n",
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
147 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
148 json_object_object_add(json
, rt_buf
, json_rt
);
152 static void show_vrf_import_rt_entry(struct hash_backet
*backet
, void *args
[])
154 json_object
*json
= NULL
;
155 struct vty
*vty
= NULL
;
156 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)backet
->data
;
158 vty
= (struct vty
*)args
[0];
159 json
= (struct json_object
*)args
[1];
161 display_vrf_import_rt(vty
, irt
, json
);
164 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
168 uint8_t type
, sub_type
;
169 struct ecommunity_as eas
;
170 struct ecommunity_ip eip
;
171 struct listnode
*node
, *nnode
;
172 struct bgpevpn
*tmp_vpn
;
173 json_object
*json_rt
= NULL
;
174 json_object
*json_vnis
= NULL
;
175 char rt_buf
[RT_ADDRSTRLEN
];
178 json_rt
= json_object_new_object();
179 json_vnis
= json_object_new_array();
182 /* TODO: This needs to go into a function */
184 pnt
= (uint8_t *)&irt
->rt
.val
;
187 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
190 memset(&eas
, 0, sizeof(eas
));
192 case ECOMMUNITY_ENCODE_AS
:
193 eas
.as
= (*pnt
++ << 8);
195 ptr_get_be32(pnt
, &eas
.val
);
197 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
200 json_object_string_add(json_rt
, "rt", rt_buf
);
202 vty_out(vty
, "Route-target: %s", rt_buf
);
206 case ECOMMUNITY_ENCODE_IP
:
207 memcpy(&eip
.ip
, pnt
, 4);
209 eip
.val
= (*pnt
++ << 8);
212 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
216 json_object_string_add(json_rt
, "rt", rt_buf
);
218 vty_out(vty
, "Route-target: %s", rt_buf
);
222 case ECOMMUNITY_ENCODE_AS4
:
223 pnt
= ptr_get_be32(pnt
, &eas
.val
);
224 eas
.val
= (*pnt
++ << 8);
227 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
230 json_object_string_add(json_rt
, "rt", rt_buf
);
232 vty_out(vty
, "Route-target: %s", rt_buf
);
242 "\nList of VNIs importing routes with this route-target:\n");
245 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
247 json_object_array_add(
248 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
250 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
254 json_object_object_add(json_rt
, "vnis", json_vnis
);
255 json_object_object_add(json
, rt_buf
, json_rt
);
259 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
261 json_object
*json
= NULL
;
262 struct vty
*vty
= NULL
;
263 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
268 display_import_rt(vty
, irt
, json
);
273 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
274 struct bgp_node
*rd_rn
,
281 char rd_str
[RD_ADDRSTRLEN
];
283 pnt
= rd_rn
->p
.u
.val
;
285 /* Decode RD type. */
286 type
= decode_rd_type(pnt
);
291 vty_out(vty
, "Route Distinguisher: ");
295 decode_rd_as(pnt
+ 2, &rd_as
);
296 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
300 decode_rd_ip(pnt
+ 2, &rd_ip
);
301 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
306 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
310 vty_out(vty
, "%s\n", rd_str
);
313 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
314 uint64_t tbl_ver
, json_object
*json
)
317 " Network Next Hop Metric LocPrf Weight Path\n";
322 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
323 tbl_ver
, inet_ntoa(bgp
->router_id
));
325 "Status codes: s suppressed, d damped, h history, "
326 "* valid, > best, i - internal\n");
327 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
329 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
330 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
331 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
332 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
333 vty_out(vty
, "%s", ri_header
);
336 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
339 char buf1
[INET6_ADDRSTRLEN
];
341 struct listnode
*node
, *nnode
;
342 struct ecommunity
*ecom
;
343 json_object
*json_import_rtl
= NULL
;
344 json_object
*json_export_rtl
= NULL
;
346 json_import_rtl
= json_export_rtl
= 0;
349 json_import_rtl
= json_object_new_array();
350 json_export_rtl
= json_object_new_array();
351 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
352 json_object_string_add(json
, "type", "L3");
353 json_object_string_add(json
, "kernelFlag", "Yes");
354 json_object_string_add(
356 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
357 json_object_string_add(json
, "originatorIp",
358 inet_ntoa(bgp_vrf
->originator_ip
));
359 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
361 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
362 vty_out(vty
, " (known to the kernel)");
365 vty_out(vty
, " Type: %s\n", "L3");
366 vty_out(vty
, " Tenant VRF: %s\n",
367 vrf_id_to_name(bgp_vrf
->vrf_id
));
368 vty_out(vty
, " RD: %s\n",
369 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
370 vty_out(vty
, " Originator IP: %s\n",
371 inet_ntoa(bgp_vrf
->originator_ip
));
372 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
376 vty_out(vty
, " Import Route Target:\n");
378 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
379 ecom_str
= ecommunity_ecom2str(ecom
,
380 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
383 json_object_array_add(json_import_rtl
,
384 json_object_new_string(ecom_str
));
386 vty_out(vty
, " %s\n", ecom_str
);
388 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
392 json_object_object_add(json
, "importRts", json_import_rtl
);
394 vty_out(vty
, " Export Route Target:\n");
396 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
397 ecom_str
= ecommunity_ecom2str(ecom
,
398 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
401 json_object_array_add(json_export_rtl
,
402 json_object_new_string(ecom_str
));
404 vty_out(vty
, " %s\n", ecom_str
);
406 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
410 json_object_object_add(json
, "exportRts", json_export_rtl
);
413 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
415 struct in_addr
*vtep
;
416 char buf
[ESI_STR_LEN
];
417 char buf1
[RD_ADDRSTRLEN
];
418 char buf2
[INET6_ADDRSTRLEN
];
419 struct listnode
*node
= NULL
;
420 json_object
*json_vteps
= NULL
;
423 json_vteps
= json_object_new_array();
424 json_object_string_add(json
, "esi",
425 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
426 json_object_string_add(json
, "rd",
427 prefix_rd2str(&es
->prd
, buf1
,
429 json_object_string_add(
430 json
, "originatorIp",
431 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
433 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
434 json_object_array_add(
435 json_vteps
, json_object_new_string(
438 json_object_object_add(json
, "vteps", json_vteps
);
440 vty_out(vty
, "ESI: %s\n",
441 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
442 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
444 vty_out(vty
, " Originator-IP: %s\n",
445 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
447 vty_out(vty
, " VTEP List:\n");
448 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
449 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
454 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
456 char buf1
[RD_ADDRSTRLEN
];
458 struct listnode
*node
, *nnode
;
459 struct ecommunity
*ecom
;
460 json_object
*json_import_rtl
= NULL
;
461 json_object
*json_export_rtl
= NULL
;
464 json_import_rtl
= json_object_new_array();
465 json_export_rtl
= json_object_new_array();
466 json_object_int_add(json
, "vni", vpn
->vni
);
467 json_object_string_add(json
, "type", "L2");
468 json_object_string_add(json
, "kernelFlag",
469 is_vni_live(vpn
) ? "Yes" : "No");
470 json_object_string_add(
472 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
473 json_object_string_add(json
, "originatorIp",
474 inet_ntoa(vpn
->originator_ip
));
475 json_object_string_add(json
, "advertiseGatewayMacip",
476 vpn
->advertise_gw_macip
? "Yes" : "No");
478 vty_out(vty
, "VNI: %d", vpn
->vni
);
479 if (is_vni_live(vpn
))
480 vty_out(vty
, " (known to the kernel)");
483 vty_out(vty
, " Type: %s\n", "L2");
484 vty_out(vty
, " Tenant-Vrf: %s\n",
485 vrf_id_to_name(vpn
->tenant_vrf_id
));
486 vty_out(vty
, " RD: %s\n",
487 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
488 vty_out(vty
, " Originator IP: %s\n",
489 inet_ntoa(vpn
->originator_ip
));
490 vty_out(vty
, " Advertise-gw-macip : %s\n",
491 vpn
->advertise_gw_macip
? "Yes" : "No");
495 vty_out(vty
, " Import Route Target:\n");
497 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
498 ecom_str
= ecommunity_ecom2str(ecom
,
499 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
502 json_object_array_add(json_import_rtl
,
503 json_object_new_string(ecom_str
));
505 vty_out(vty
, " %s\n", ecom_str
);
507 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
511 json_object_object_add(json
, "importRts", json_import_rtl
);
513 vty_out(vty
, " Export Route Target:\n");
515 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
516 ecom_str
= ecommunity_ecom2str(ecom
,
517 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
520 json_object_array_add(json_export_rtl
,
521 json_object_new_string(ecom_str
));
523 vty_out(vty
, " %s\n", ecom_str
);
525 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
529 json_object_object_add(json
, "exportRts", json_export_rtl
);
532 static void show_esi_routes(struct bgp
*bgp
,
539 struct bgp_path_info
*pi
;
540 uint32_t prefix_cnt
, path_cnt
;
543 prefix_cnt
= path_cnt
= 0;
545 tbl_ver
= es
->route_table
->version
;
546 for (rn
= bgp_table_top(es
->route_table
); rn
;
547 rn
= bgp_route_next(rn
)) {
548 int add_prefix_to_json
= 0;
549 char prefix_str
[BUFSIZ
];
550 json_object
*json_paths
= NULL
;
551 json_object
*json_prefix
= NULL
;
553 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
557 json_prefix
= json_object_new_object();
560 /* Overall header/legend displayed once. */
562 bgp_evpn_show_route_header(vty
, bgp
,
571 json_paths
= json_object_new_array();
573 /* For EVPN, the prefix is displayed for each path (to fit in
574 * with code that already exists).
576 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
577 json_object
*json_path
= NULL
;
580 json_path
= json_object_new_array();
582 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
585 json_object_array_add(json_paths
, json_path
);
588 add_prefix_to_json
= 1;
591 if (json
&& add_prefix_to_json
) {
592 json_object_string_add(json_prefix
, "prefix",
594 json_object_int_add(json_prefix
, "prefixLen",
596 json_object_object_add(json_prefix
, "paths",
598 json_object_object_add(json
, prefix_str
, json_prefix
);
603 json_object_int_add(json
, "numPrefix", prefix_cnt
);
604 json_object_int_add(json
, "numPaths", path_cnt
);
607 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
609 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
610 prefix_cnt
, path_cnt
);
614 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
615 struct vty
*vty
, struct in_addr vtep_ip
,
619 struct bgp_path_info
*pi
;
620 struct bgp_table
*table
;
623 uint32_t prefix_cnt
, path_cnt
;
625 prefix_cnt
= path_cnt
= 0;
627 table
= vpn
->route_table
;
628 tbl_ver
= table
->version
;
629 for (rn
= bgp_table_top(table
); rn
;
630 rn
= bgp_route_next(rn
)) {
631 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
632 int add_prefix_to_json
= 0;
633 char prefix_str
[BUFSIZ
];
634 json_object
*json_paths
= NULL
;
635 json_object
*json_prefix
= NULL
;
637 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
640 if (type
&& evp
->prefix
.route_type
!= type
)
644 json_prefix
= json_object_new_object();
647 /* Overall header/legend displayed once. */
649 bgp_evpn_show_route_header(vty
, bgp
,
658 json_paths
= json_object_new_array();
660 /* For EVPN, the prefix is displayed for each path (to fit in
661 * with code that already exists).
663 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
664 json_object
*json_path
= NULL
;
667 && !IPV4_ADDR_SAME(&(vtep_ip
),
668 &(pi
->attr
->nexthop
)))
672 json_path
= json_object_new_array();
674 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
677 json_object_array_add(json_paths
, json_path
);
680 add_prefix_to_json
= 1;
683 if (json
&& add_prefix_to_json
) {
684 json_object_string_add(json_prefix
, "prefix",
686 json_object_int_add(json_prefix
, "prefixLen",
688 json_object_object_add(json_prefix
, "paths",
690 json_object_object_add(json
, prefix_str
, json_prefix
);
695 json_object_int_add(json
, "numPrefix", prefix_cnt
);
696 json_object_int_add(json
, "numPaths", path_cnt
);
699 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
700 type
? "(of requested type) " : "");
702 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
703 prefix_cnt
, path_cnt
,
704 type
? " (of requested type)" : "");
708 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
710 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
711 struct vni_walk_ctx
*wctx
= arg
;
712 struct vty
*vty
= wctx
->vty
;
713 json_object
*json
= wctx
->json
;
714 json_object
*json_vni
= NULL
;
715 char vni_str
[VNI_STR_LEN
];
717 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
719 json_vni
= json_object_new_object();
720 json_object_int_add(json_vni
, "vni", vpn
->vni
);
722 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
725 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
728 json_object_object_add(json
, vni_str
, json_vni
);
731 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
734 json_object
*json_vni
= NULL
;
735 json_object
*json_import_rtl
= NULL
;
736 json_object
*json_export_rtl
= NULL
;
738 char buf2
[INET6_ADDRSTRLEN
];
741 struct listnode
*node
, *nnode
;
742 struct ecommunity
*ecom
;
748 json_vni
= json_object_new_object();
749 json_import_rtl
= json_object_new_array();
750 json_export_rtl
= json_object_new_array();
753 /* if an l3vni is present in bgp it is live */
758 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
759 json_object_string_add(json_vni
, "type", "L3");
760 json_object_string_add(json_vni
, "inKernel", "True");
761 json_object_string_add(json_vni
, "originatorIp",
762 inet_ntoa(bgp
->originator_ip
));
763 json_object_string_add(
765 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
767 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
768 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
771 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
772 ecom_str
= ecommunity_ecom2str(ecom
,
773 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
776 json_object_array_add(json_import_rtl
,
777 json_object_new_string(ecom_str
));
779 if (listcount(bgp
->vrf_import_rtl
) > 1)
780 sprintf(rt_buf
, "%s, ...", ecom_str
);
782 sprintf(rt_buf
, "%s", ecom_str
);
783 vty_out(vty
, " %-25s", rt_buf
);
786 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
788 /* If there are multiple import RTs we break here and show only
795 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
797 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
798 ecom_str
= ecommunity_ecom2str(ecom
,
799 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
802 json_object_array_add(json_export_rtl
,
803 json_object_new_string(ecom_str
));
805 if (listcount(bgp
->vrf_export_rtl
) > 1)
806 sprintf(rt_buf
, "%s, ...", ecom_str
);
808 sprintf(rt_buf
, "%s", ecom_str
);
809 vty_out(vty
, " %-25s", rt_buf
);
812 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
814 /* If there are multiple export RTs we break here and show only
821 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
824 char vni_str
[VNI_STR_LEN
];
826 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
827 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
828 json_object_object_add(json
, vni_str
, json_vni
);
834 static void show_es_entry(struct hash_backet
*backet
, void *args
[])
836 char buf
[ESI_STR_LEN
];
837 char buf1
[RD_ADDRSTRLEN
];
838 char buf2
[INET6_ADDRSTRLEN
];
839 struct in_addr
*vtep
= NULL
;
840 struct vty
*vty
= args
[0];
841 json_object
*json
= args
[1];
842 json_object
*json_vteps
= NULL
;
843 struct listnode
*node
= NULL
;
844 struct evpnes
*es
= (struct evpnes
*)backet
->data
;
847 json_vteps
= json_object_new_array();
848 json_object_string_add(json
, "esi",
849 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
850 json_object_string_add(json
, "type",
851 is_es_local(es
) ? "Local" : "Remote");
852 json_object_string_add(json
, "rd",
853 prefix_rd2str(&es
->prd
, buf1
,
855 json_object_string_add(
856 json
, "originatorIp",
857 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
859 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
860 json_object_array_add(json_vteps
,
861 json_object_new_string(
864 json_object_object_add(json
, "vteps", json_vteps
);
866 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
867 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
868 is_es_local(es
) ? "Local" : "Remote",
869 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
870 ipaddr2str(&es
->originator_ip
, buf2
,
872 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
876 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
880 json_object
*json_vni
= NULL
;
881 json_object
*json_import_rtl
= NULL
;
882 json_object
*json_export_rtl
= NULL
;
883 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
885 char buf2
[RD_ADDRSTRLEN
];
888 struct listnode
*node
, *nnode
;
889 struct ecommunity
*ecom
;
895 json_vni
= json_object_new_object();
896 json_import_rtl
= json_object_new_array();
897 json_export_rtl
= json_object_new_array();
901 if (is_vni_live(vpn
))
905 json_object_int_add(json_vni
, "vni", vpn
->vni
);
906 json_object_string_add(json_vni
, "type", "L2");
907 json_object_string_add(json_vni
, "inKernel",
908 is_vni_live(vpn
) ? "True" : "False");
909 json_object_string_add(json_vni
, "originatorIp",
910 inet_ntoa(vpn
->originator_ip
));
911 json_object_string_add(json_vni
, "originatorIp",
912 inet_ntoa(vpn
->originator_ip
));
913 json_object_string_add(
915 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
917 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
918 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
921 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
922 ecom_str
= ecommunity_ecom2str(ecom
,
923 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
926 json_object_array_add(json_import_rtl
,
927 json_object_new_string(ecom_str
));
929 if (listcount(vpn
->import_rtl
) > 1)
930 sprintf(rt_buf
, "%s, ...", ecom_str
);
932 sprintf(rt_buf
, "%s", ecom_str
);
933 vty_out(vty
, " %-25s", rt_buf
);
936 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
938 /* If there are multiple import RTs we break here and show only
945 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
947 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
948 ecom_str
= ecommunity_ecom2str(ecom
,
949 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
952 json_object_array_add(json_export_rtl
,
953 json_object_new_string(ecom_str
));
955 if (listcount(vpn
->export_rtl
) > 1)
956 sprintf(rt_buf
, "%s, ...", ecom_str
);
958 sprintf(rt_buf
, "%s", ecom_str
);
959 vty_out(vty
, " %-25s", rt_buf
);
962 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
964 /* If there are multiple export RTs we break here and show only
971 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
974 char vni_str
[VNI_STR_LEN
];
976 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
977 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
978 json_object_object_add(json
, vni_str
, json_vni
);
984 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
985 enum bgp_show_type type
, void *output_arg
,
986 int option
, bool use_json
)
988 afi_t afi
= AFI_L2VPN
;
990 struct bgp_table
*table
;
993 struct bgp_path_info
*pi
;
997 unsigned long output_count
= 0;
998 unsigned long total_count
= 0;
999 json_object
*json
= NULL
;
1000 json_object
*json_nroute
= NULL
;
1001 json_object
*json_array
= NULL
;
1002 json_object
*json_scode
= NULL
;
1003 json_object
*json_ocode
= NULL
;
1005 bgp
= bgp_get_default();
1008 vty_out(vty
, "No BGP process is configured\n");
1010 vty_out(vty
, "{}\n");
1015 json_scode
= json_object_new_object();
1016 json_ocode
= json_object_new_object();
1017 json
= json_object_new_object();
1018 json_nroute
= json_object_new_object();
1020 json_object_string_add(json_scode
, "suppressed", "s");
1021 json_object_string_add(json_scode
, "damped", "d");
1022 json_object_string_add(json_scode
, "history", "h");
1023 json_object_string_add(json_scode
, "valid", "*");
1024 json_object_string_add(json_scode
, "best", ">");
1025 json_object_string_add(json_scode
, "internal", "i");
1027 json_object_string_add(json_ocode
, "igp", "i");
1028 json_object_string_add(json_ocode
, "egp", "e");
1029 json_object_string_add(json_ocode
, "incomplete", "?");
1032 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1033 rn
= bgp_route_next(rn
)) {
1037 continue; /* XXX json TODO */
1039 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1042 if ((table
= rn
->info
) == NULL
)
1046 tbl_ver
= table
->version
;
1048 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1049 for (pi
= rm
->info
; pi
; pi
= pi
->next
) {
1051 if (type
== bgp_show_type_neighbor
) {
1052 union sockunion
*su
= output_arg
;
1054 if (pi
->peer
->su_remote
== NULL
1056 pi
->peer
->su_remote
, su
))
1062 == SHOW_DISPLAY_TAGS
) {
1063 json_object_int_add(
1067 json_object_string_add(
1072 json_object_object_add(
1076 json_object_object_add(
1082 if (option
== SHOW_DISPLAY_TAGS
)
1087 == SHOW_DISPLAY_OVERLAY
)
1092 "BGP table version is %" PRIu64
", local router ID is %s\n",
1097 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1099 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1100 vty_out(vty
, V4_HEADER
);
1113 /* Decode RD type. */
1114 type
= decode_rd_type(pnt
);
1115 /* Decode RD value. */
1116 if (type
== RD_TYPE_AS
)
1117 decode_rd_as(pnt
+ 2, &rd_as
);
1118 else if (type
== RD_TYPE_AS4
)
1119 decode_rd_as4(pnt
+ 2, &rd_as
);
1120 else if (type
== RD_TYPE_IP
)
1121 decode_rd_ip(pnt
+ 2, &rd_ip
);
1123 char buffer
[BUFSIZ
];
1124 if (type
== RD_TYPE_AS
1125 || type
== RD_TYPE_AS4
)
1126 sprintf(buffer
, "%u:%d",
1129 else if (type
== RD_TYPE_IP
)
1130 sprintf(buffer
, "%s:%d",
1134 json_object_string_add(
1136 "routeDistinguisher",
1140 "Route Distinguisher: ");
1141 if (type
== RD_TYPE_AS
)
1146 else if (type
== RD_TYPE_AS4
)
1151 else if (type
== RD_TYPE_IP
)
1152 vty_out(vty
, "ip %s:%d",
1156 vty_out(vty
, "\n\n");
1161 json_array
= json_object_new_array();
1164 if (option
== SHOW_DISPLAY_TAGS
)
1165 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1168 else if (option
== SHOW_DISPLAY_OVERLAY
)
1169 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1172 route_vty_out(vty
, &rm
->p
, pi
, 0,
1173 SAFI_EVPN
, json_array
);
1178 if (output_count
== 0)
1179 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1181 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1182 output_count
, total_count
);
1186 DEFUN(show_ip_bgp_l2vpn_evpn
,
1187 show_ip_bgp_l2vpn_evpn_cmd
,
1188 "show [ip] bgp l2vpn evpn [json]",
1189 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1191 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1192 use_json(argc
, argv
));
1195 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1196 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1197 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1203 "Display information for a route distinguisher\n"
1204 "VPN Route Distinguisher\n" JSON_STR
)
1206 int idx_ext_community
= 0;
1208 struct prefix_rd prd
;
1210 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1212 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1214 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1217 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1218 use_json(argc
, argv
));
1221 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1222 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1223 "show [ip] bgp l2vpn evpn all tags",
1229 "Display information about all EVPN NLRIs\n"
1230 "Display BGP tags for prefixes\n")
1232 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1236 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1237 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1238 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1244 "Display information for a route distinguisher\n"
1245 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1247 int idx_ext_community
= 0;
1249 struct prefix_rd prd
;
1251 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1253 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1255 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1258 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1262 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1263 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1264 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1270 "Display information about all EVPN NLRIs\n"
1271 "Detailed information on TCP and BGP neighbor connections\n"
1272 "Neighbor to display information about\n"
1273 "Display routes learned from neighbor\n" JSON_STR
)
1279 bool uj
= use_json(argc
, argv
);
1281 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1283 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1286 json_object
*json_no
= NULL
;
1287 json_no
= json_object_new_object();
1288 json_object_string_add(json_no
, "warning",
1289 "Malformed address");
1290 vty_out(vty
, "%s\n",
1291 json_object_to_json_string(json_no
));
1292 json_object_free(json_no
);
1294 vty_out(vty
, "Malformed address: %s\n",
1295 argv
[idx_ipv4
]->arg
);
1299 peer
= peer_lookup(NULL
, &su
);
1300 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1302 json_object
*json_no
= NULL
;
1303 json_no
= json_object_new_object();
1304 json_object_string_add(
1306 "No such neighbor or address family");
1307 vty_out(vty
, "%s\n",
1308 json_object_to_json_string(json_no
));
1309 json_object_free(json_no
);
1311 vty_out(vty
, "%% No such neighbor or address family\n");
1315 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1319 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1320 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1321 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1327 "Display information for a route distinguisher\n"
1328 "VPN Route Distinguisher\n"
1329 "Detailed information on TCP and BGP neighbor connections\n"
1330 "Neighbor to display information about\n"
1331 "Display routes learned from neighbor\n" JSON_STR
)
1333 int idx_ext_community
= 0;
1338 struct prefix_rd prd
;
1339 bool uj
= use_json(argc
, argv
);
1341 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1342 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1344 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1347 json_object
*json_no
= NULL
;
1348 json_no
= json_object_new_object();
1349 json_object_string_add(json_no
, "warning",
1350 "Malformed Route Distinguisher");
1351 vty_out(vty
, "%s\n",
1352 json_object_to_json_string(json_no
));
1353 json_object_free(json_no
);
1355 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1359 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1362 json_object
*json_no
= NULL
;
1363 json_no
= json_object_new_object();
1364 json_object_string_add(json_no
, "warning",
1365 "Malformed address");
1366 vty_out(vty
, "%s\n",
1367 json_object_to_json_string(json_no
));
1368 json_object_free(json_no
);
1370 vty_out(vty
, "Malformed address: %s\n",
1371 argv
[idx_ext_community
]->arg
);
1375 peer
= peer_lookup(NULL
, &su
);
1376 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1378 json_object
*json_no
= NULL
;
1379 json_no
= json_object_new_object();
1380 json_object_string_add(
1382 "No such neighbor or address family");
1383 vty_out(vty
, "%s\n",
1384 json_object_to_json_string(json_no
));
1385 json_object_free(json_no
);
1387 vty_out(vty
, "%% No such neighbor or address family\n");
1391 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1395 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1396 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1397 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1403 "Display information about all EVPN NLRIs\n"
1404 "Detailed information on TCP and BGP neighbor connections\n"
1405 "Neighbor to display information about\n"
1406 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1412 bool uj
= use_json(argc
, argv
);
1414 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1416 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1419 json_object
*json_no
= NULL
;
1420 json_no
= json_object_new_object();
1421 json_object_string_add(json_no
, "warning",
1422 "Malformed address");
1423 vty_out(vty
, "%s\n",
1424 json_object_to_json_string(json_no
));
1425 json_object_free(json_no
);
1427 vty_out(vty
, "Malformed address: %s\n",
1428 argv
[idx_ipv4
]->arg
);
1431 peer
= peer_lookup(NULL
, &su
);
1432 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1434 json_object
*json_no
= NULL
;
1435 json_no
= json_object_new_object();
1436 json_object_string_add(
1438 "No such neighbor or address family");
1439 vty_out(vty
, "%s\n",
1440 json_object_to_json_string(json_no
));
1441 json_object_free(json_no
);
1443 vty_out(vty
, "%% No such neighbor or address family\n");
1447 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1450 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1451 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1452 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1458 "Display information for a route distinguisher\n"
1459 "VPN Route Distinguisher\n"
1460 "Detailed information on TCP and BGP neighbor connections\n"
1461 "Neighbor to display information about\n"
1462 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1464 int idx_ext_community
= 0;
1468 struct prefix_rd prd
;
1470 bool uj
= use_json(argc
, argv
);
1472 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1473 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1475 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1478 json_object
*json_no
= NULL
;
1479 json_no
= json_object_new_object();
1480 json_object_string_add(json_no
, "warning",
1481 "Malformed address");
1482 vty_out(vty
, "%s\n",
1483 json_object_to_json_string(json_no
));
1484 json_object_free(json_no
);
1486 vty_out(vty
, "Malformed address: %s\n",
1487 argv
[idx_ext_community
]->arg
);
1490 peer
= peer_lookup(NULL
, &su
);
1491 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1493 json_object
*json_no
= NULL
;
1494 json_no
= json_object_new_object();
1495 json_object_string_add(
1497 "No such neighbor or address family");
1498 vty_out(vty
, "%s\n",
1499 json_object_to_json_string(json_no
));
1500 json_object_free(json_no
);
1502 vty_out(vty
, "%% No such neighbor or address family\n");
1506 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1509 json_object
*json_no
= NULL
;
1510 json_no
= json_object_new_object();
1511 json_object_string_add(json_no
, "warning",
1512 "Malformed Route Distinguisher");
1513 vty_out(vty
, "%s\n",
1514 json_object_to_json_string(json_no
));
1515 json_object_free(json_no
);
1517 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1521 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1524 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1525 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1526 "show [ip] bgp l2vpn evpn all overlay",
1532 "Display information about all EVPN NLRIs\n"
1533 "Display BGP Overlay Information for prefixes\n")
1535 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1536 SHOW_DISPLAY_OVERLAY
,
1537 use_json(argc
, argv
));
1540 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1541 show_ip_bgp_evpn_rd_overlay_cmd
,
1542 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1548 "Display information for a route distinguisher\n"
1549 "VPN Route Distinguisher\n"
1550 "Display BGP Overlay Information for prefixes\n")
1552 int idx_ext_community
= 0;
1554 struct prefix_rd prd
;
1556 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1558 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1560 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1563 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1564 SHOW_DISPLAY_OVERLAY
,
1565 use_json(argc
, argv
));
1568 /* For testing purpose, static route of MPLS-VPN. */
1569 DEFUN(evpnrt5_network
,
1570 evpnrt5_network_cmd
,
1571 "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]",
1572 "Specify a network to announce via BGP\n"
1575 "Specify Route Distinguisher\n"
1576 "VPN Route Distinguisher\n"
1578 "Ethernet Tag Value\n"
1581 "Ethernet Segment Identifier\n"
1582 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1584 "Gateway IP ( A.B.C.D )\n"
1585 "Gateway IPv6 ( X:X::X:X )\n"
1586 "Router Mac Ext Comm\n"
1587 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1588 "Route-map to modify the attributes\n"
1589 "Name of the route map\n")
1591 int idx_ipv4_prefixlen
= 1;
1592 int idx_route_distinguisher
= 3;
1597 int idx_routermac
= 13;
1599 return bgp_static_set_safi(
1600 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1601 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1602 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1603 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1604 argv
[idx_routermac
]->arg
);
1607 /* For testing purpose, static route of MPLS-VPN. */
1608 DEFUN(no_evpnrt5_network
,
1609 no_evpnrt5_network_cmd
,
1610 "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>",
1612 "Specify a network to announce via BGP\n"
1615 "Specify Route Distinguisher\n"
1616 "VPN Route Distinguisher\n"
1618 "Ethernet Tag Value\n"
1621 "Ethernet Segment Identifier\n"
1622 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1623 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1625 int idx_ipv4_prefixlen
= 2;
1626 int idx_ext_community
= 4;
1631 return bgp_static_unset_safi(
1632 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1633 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1634 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1635 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1638 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1640 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1643 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1645 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1649 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1650 * check that this is a change.
1652 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1653 struct ecommunity
*ecomadd
)
1655 /* If the VNI is "live", we need to uninstall routes using the current
1656 * import RT(s) first before we update the import RT, and subsequently
1659 if (is_vni_live(vpn
))
1660 bgp_evpn_uninstall_routes(bgp
, vpn
);
1662 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1663 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1665 /* If the auto route-target is in use we must remove it */
1666 evpn_import_rt_delete_auto(bgp
, vpn
);
1668 /* Add new RT and rebuild the RT to VNI mapping */
1669 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1671 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1672 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1674 /* Install routes that match new import RT */
1675 if (is_vni_live(vpn
))
1676 bgp_evpn_install_routes(bgp
, vpn
);
1680 * Unconfigure Import RT(s) for a VNI (vty handler).
1682 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1683 struct ecommunity
*ecomdel
)
1685 struct listnode
*node
, *nnode
, *node_to_del
;
1686 struct ecommunity
*ecom
;
1688 /* Along the lines of "configure" except we have to reset to the
1691 if (is_vni_live(vpn
))
1692 bgp_evpn_uninstall_routes(bgp
, vpn
);
1694 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1695 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1697 /* Delete all import RTs */
1698 if (ecomdel
== NULL
) {
1699 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1700 ecommunity_free(&ecom
);
1701 list_delete_node(vpn
->import_rtl
, node
);
1705 /* Delete a specific import RT */
1709 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1710 if (ecommunity_match(ecom
, ecomdel
)) {
1711 ecommunity_free(&ecom
);
1718 list_delete_node(vpn
->import_rtl
, node_to_del
);
1721 assert(vpn
->import_rtl
);
1722 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1723 if (list_isempty(vpn
->import_rtl
)) {
1724 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1725 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1727 /* Rebuild the RT to VNI mapping */
1729 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1731 /* Install routes that match new import RT */
1732 if (is_vni_live(vpn
))
1733 bgp_evpn_install_routes(bgp
, vpn
);
1737 * Configure the Export RT for a VNI (vty handler). Caller expected to
1738 * check that this is a change. Note that only a single export RT is
1739 * allowed for a VNI and any change to configuration is implemented as
1740 * a "replace" (similar to other configuration).
1742 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1743 struct ecommunity
*ecomadd
)
1745 /* If the auto route-target is in use we must remove it */
1746 evpn_export_rt_delete_auto(bgp
, vpn
);
1748 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1749 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1751 if (is_vni_live(vpn
))
1752 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1756 * Unconfigure the Export RT for a VNI (vty handler)
1758 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1759 struct ecommunity
*ecomdel
)
1761 struct listnode
*node
, *nnode
, *node_to_del
;
1762 struct ecommunity
*ecom
;
1764 /* Delete all export RTs */
1765 if (ecomdel
== NULL
) {
1766 /* Reset to default and process all routes. */
1767 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1768 ecommunity_free(&ecom
);
1769 list_delete_node(vpn
->export_rtl
, node
);
1773 /* Delete a specific export RT */
1777 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1778 if (ecommunity_match(ecom
, ecomdel
)) {
1779 ecommunity_free(&ecom
);
1786 list_delete_node(vpn
->export_rtl
, node_to_del
);
1789 assert(vpn
->export_rtl
);
1790 if (list_isempty(vpn
->export_rtl
)) {
1791 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1792 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1795 if (is_vni_live(vpn
))
1796 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1800 * Configure RD for VRF
1802 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1804 /* If we have already advertise type-5 routes with a diffrent RD, we
1805 * have to delete and withdraw them firs
1807 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1810 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1811 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1813 /* We have a new RD for VRF.
1814 * Advertise all type-5 routes again with the new RD
1816 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1820 * Unconfigure RD for VRF
1822 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1824 /* If we have already advertise type-5 routes with a diffrent RD, we
1825 * have to delete and withdraw them firs
1827 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1829 /* fall back to default RD */
1830 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1831 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1833 /* We have a new RD for VRF.
1834 * Advertise all type-5 routes again with the new RD
1836 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1840 * Configure RD for a VNI (vty handler)
1842 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1843 struct prefix_rd
*rd
)
1845 /* If the VNI is "live", we need to delete and withdraw this VNI's
1846 * local routes with the prior RD first. Then, after updating RD,
1847 * need to re-advertise.
1849 if (is_vni_live(vpn
))
1850 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1853 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1854 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1856 if (is_vni_live(vpn
))
1857 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1861 * Unconfigure RD for a VNI (vty handler)
1863 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1865 /* If the VNI is "live", we need to delete and withdraw this VNI's
1866 * local routes with the prior RD first. Then, after resetting RD
1867 * to automatic value, need to re-advertise.
1869 if (is_vni_live(vpn
))
1870 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1872 /* reset RD to default */
1873 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1875 if (is_vni_live(vpn
))
1876 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1880 * Create VNI, if not already present (VTY handler). Mark as configured.
1882 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1884 struct bgpevpn
*vpn
;
1889 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1891 /* Check if this L2VNI is already configured as L3VNI */
1892 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
1895 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1900 /* tenant vrf will be updated when we get local_vni_add from
1903 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1907 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1913 /* Mark as configured. */
1914 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1919 * Delete VNI. If VNI does not exist in the system (i.e., just
1920 * configuration), all that is needed is to free it. Otherwise,
1921 * any parameters configured for the VNI need to be reset (with
1922 * appropriate action) and the VNI marked as unconfigured; the
1923 * VNI will continue to exist, purely as a "learnt" entity.
1925 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1927 assert(bgp
->vnihash
);
1929 if (!is_vni_live(vpn
)) {
1930 bgp_evpn_free(bgp
, vpn
);
1934 /* We need to take the unconfigure action for each parameter of this VNI
1935 * that is configured. Some optimization is possible, but not worth the
1936 * additional code for an operation that should be pretty rare.
1938 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1940 /* First, deal with the export side - RD and export RT changes. */
1941 if (is_rd_configured(vpn
))
1942 evpn_unconfigure_rd(bgp
, vpn
);
1943 if (is_export_rt_configured(vpn
))
1944 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1946 /* Next, deal with the import side. */
1947 if (is_import_rt_configured(vpn
))
1948 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1954 * Display import RT mapping to VRFs (vty handler)
1955 * bgp_def: default bgp instance
1957 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1965 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1966 (void (*)(struct hash_backet
*,
1967 void *))show_vrf_import_rt_entry
,
1972 * Display import RT mapping to VNIs (vty handler)
1974 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1983 bgp
->import_rt_hash
,
1984 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1989 * Display EVPN routes for all VNIs - vty handler.
1991 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1992 struct in_addr vtep_ip
, json_object
*json
)
1995 struct vni_walk_ctx wctx
;
1997 num_vnis
= hashcount(bgp
->vnihash
);
2000 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2003 wctx
.vtep_ip
= vtep_ip
;
2005 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
2006 void *))show_vni_routes_hash
,
2011 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2013 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2014 vni_t vni
, struct in_addr orig_ip
,
2017 struct bgpevpn
*vpn
;
2018 struct prefix_evpn p
;
2019 struct bgp_node
*rn
;
2020 struct bgp_path_info
*pi
;
2021 uint32_t path_cnt
= 0;
2024 json_object
*json_paths
= NULL
;
2030 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2032 vty_out(vty
, "VNI not found\n");
2036 /* See if route exists. */
2037 build_evpn_type3_prefix(&p
, orig_ip
);
2038 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2039 if (!rn
|| !rn
->info
) {
2041 vty_out(vty
, "%% Network not in table\n");
2046 json_paths
= json_object_new_array();
2048 /* Prefix and num paths displayed once per prefix. */
2049 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2051 /* Display each path for this prefix. */
2052 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2053 json_object
*json_path
= NULL
;
2056 json_path
= json_object_new_array();
2058 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2062 json_object_array_add(json_paths
, json_path
);
2069 json_object_object_add(json
, "paths", json_paths
);
2071 json_object_int_add(json
, "numPaths", path_cnt
);
2073 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2079 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2080 * By definition, only matching type-2 route will be displayed.
2082 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2083 vni_t vni
, struct ethaddr
*mac
,
2084 struct ipaddr
*ip
, json_object
*json
)
2086 struct bgpevpn
*vpn
;
2087 struct prefix_evpn p
;
2088 struct bgp_node
*rn
;
2089 struct bgp_path_info
*pi
;
2090 uint32_t path_cnt
= 0;
2093 json_object
*json_paths
= NULL
;
2099 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2102 vty_out(vty
, "VNI not found\n");
2106 /* See if route exists. Look for both non-sticky and sticky. */
2107 build_evpn_type2_prefix(&p
, mac
, ip
);
2108 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2109 if (!rn
|| !rn
->info
) {
2111 vty_out(vty
, "%% Network not in table\n");
2116 json_paths
= json_object_new_array();
2118 /* Prefix and num paths displayed once per prefix. */
2119 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2121 /* Display each path for this prefix. */
2122 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2123 json_object
*json_path
= NULL
;
2126 json_path
= json_object_new_array();
2128 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2132 json_object_array_add(json_paths
, json_path
);
2139 json_object_object_add(json
, "paths", json_paths
);
2141 json_object_int_add(json
, "numPaths", path_cnt
);
2143 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2148 /* Disaplay EVPN routes for a ESI - VTY handler */
2149 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2150 esi_t
*esi
, json_object
*json
)
2152 struct evpnes
*es
= NULL
;
2155 es
= bgp_evpn_lookup_es(bgp
, esi
);
2158 vty_out(vty
, "ESI not found\n");
2162 show_esi_routes(bgp
, es
, vty
, json
);
2166 * Display EVPN routes for a VNI - vty handler.
2167 * If 'type' is non-zero, only routes matching that type are shown.
2168 * If the vtep_ip is non zero, only routes behind that vtep are shown
2170 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2171 int type
, struct in_addr vtep_ip
,
2174 struct bgpevpn
*vpn
;
2177 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2180 vty_out(vty
, "VNI not found\n");
2184 /* Walk this VNI's route table and display appropriate routes. */
2185 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2189 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2190 * IP (vty handler). By definition, only matching type-2 route will be
2193 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2194 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2195 struct ipaddr
*ip
, json_object
*json
)
2197 struct prefix_evpn p
;
2198 struct bgp_node
*rn
;
2199 struct bgp_path_info
*pi
;
2202 uint32_t path_cnt
= 0;
2203 json_object
*json_paths
= NULL
;
2204 char prefix_str
[BUFSIZ
];
2209 /* See if route exists. Look for both non-sticky and sticky. */
2210 build_evpn_type2_prefix(&p
, mac
, ip
);
2211 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2212 (struct prefix
*)&p
, prd
);
2213 if (!rn
|| !rn
->info
) {
2215 vty_out(vty
, "%% Network not in table\n");
2219 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2220 sizeof(prefix_str
));
2222 /* Prefix and num paths displayed once per prefix. */
2223 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2226 json_paths
= json_object_new_array();
2228 /* Display each path for this prefix. */
2229 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2230 json_object
*json_path
= NULL
;
2233 json_path
= json_object_new_array();
2235 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2239 json_object_array_add(json_paths
, json_path
);
2244 if (json
&& path_cnt
) {
2246 json_object_object_add(json
, prefix_str
, json_paths
);
2247 json_object_int_add(json
, "numPaths", path_cnt
);
2249 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2255 * Display BGP EVPN routing table -- for specific RD (vty handler)
2256 * If 'type' is non-zero, only routes matching that type are shown.
2258 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2259 struct prefix_rd
*prd
, int type
,
2262 struct bgp_node
*rd_rn
;
2263 struct bgp_table
*table
;
2264 struct bgp_node
*rn
;
2265 struct bgp_path_info
*pi
;
2269 uint32_t prefix_cnt
, path_cnt
;
2270 char rd_str
[RD_ADDRSTRLEN
];
2271 json_object
*json_rd
= NULL
;
2272 int add_rd_to_json
= 0;
2276 prefix_cnt
= path_cnt
= 0;
2278 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2280 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2284 table
= (struct bgp_table
*)rd_rn
->info
;
2289 json_rd
= json_object_new_object();
2290 json_object_string_add(json_rd
, "rd", rd_str
);
2293 /* Display all prefixes with this RD. */
2294 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2295 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2296 json_object
*json_prefix
= NULL
;
2297 json_object
*json_paths
= NULL
;
2298 char prefix_str
[BUFSIZ
];
2299 int add_prefix_to_json
= 0;
2301 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2302 sizeof(prefix_str
));
2304 if (type
&& evp
->prefix
.route_type
!= type
)
2308 json_prefix
= json_object_new_object();
2311 /* RD header and legend - once overall. */
2312 if (rd_header
&& !json
) {
2314 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2316 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2318 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2322 /* Prefix and num paths displayed once per prefix. */
2323 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2330 json_paths
= json_object_new_array();
2332 /* Display each path for this prefix. */
2333 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2334 json_object
*json_path
= NULL
;
2337 json_path
= json_object_new_array();
2339 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2343 json_object_array_add(json_paths
, json_path
);
2346 add_prefix_to_json
= 1;
2350 if (json
&& add_prefix_to_json
) {
2351 json_object_object_add(json_prefix
, "paths",
2353 json_object_object_add(json_rd
, prefix_str
,
2358 if (json
&& add_rd_to_json
)
2359 json_object_object_add(json
, rd_str
, json_rd
);
2362 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2363 json_object_int_add(json
, "numPaths", path_cnt
);
2365 if (prefix_cnt
== 0)
2366 vty_out(vty
, "No prefixes exist with this RD%s\n",
2367 type
? " (of requested type)" : "");
2370 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2371 prefix_cnt
, path_cnt
,
2372 type
? " (of requested type)" : "");
2377 * Display BGP EVPN routing table - all routes (vty handler).
2378 * If 'type' is non-zero, only routes matching that type are shown.
2380 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2383 struct bgp_node
*rd_rn
;
2384 struct bgp_table
*table
;
2385 struct bgp_node
*rn
;
2386 struct bgp_path_info
*pi
;
2391 uint32_t prefix_cnt
, path_cnt
;
2395 prefix_cnt
= path_cnt
= 0;
2397 /* EVPN routing table is a 2-level table with the first level being
2400 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2401 rd_rn
= bgp_route_next(rd_rn
)) {
2402 char rd_str
[RD_ADDRSTRLEN
];
2403 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2404 int add_rd_to_json
= 0;
2407 table
= (struct bgp_table
*)rd_rn
->info
;
2411 tbl_ver
= table
->version
;
2412 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2416 json_rd
= json_object_new_object();
2417 json_object_string_add(json_rd
, "rd", rd_str
);
2422 /* Display all prefixes for an RD */
2423 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2424 json_object
*json_prefix
=
2425 NULL
; /* contains prefix under a RD */
2426 json_object
*json_paths
=
2427 NULL
; /* array of paths under a prefix*/
2428 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2429 char prefix_str
[BUFSIZ
];
2430 int add_prefix_to_json
= 0;
2432 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2433 prefix_str
, sizeof(prefix_str
));
2435 if (type
&& evp
->prefix
.route_type
!= type
)
2439 /* Overall header/legend displayed once. */
2441 bgp_evpn_show_route_header(vty
, bgp
,
2447 /* RD header - per RD. */
2449 bgp_evpn_show_route_rd_header(
2458 json_prefix
= json_object_new_object();
2459 json_paths
= json_object_new_array();
2460 json_object_string_add(json_prefix
, "prefix",
2462 json_object_int_add(json_prefix
, "prefixLen",
2466 /* For EVPN, the prefix is displayed for each path (to
2468 * with code that already exists).
2470 for (pi
= rn
->info
; pi
; pi
= pi
->next
) {
2471 json_object
*json_path
= NULL
;
2473 add_prefix_to_json
= 1;
2477 json_path
= json_object_new_array();
2479 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
2483 json_object_array_add(json_paths
,
2487 if (json
&& add_prefix_to_json
) {
2488 json_object_object_add(json_prefix
, "paths",
2490 json_object_object_add(json_rd
, prefix_str
,
2495 if (json
&& add_rd_to_json
)
2496 json_object_object_add(json
, rd_str
, json_rd
);
2500 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2501 json_object_int_add(json
, "numPaths", path_cnt
);
2503 if (prefix_cnt
== 0) {
2504 vty_out(vty
, "No EVPN prefixes %sexist\n",
2505 type
? "(of requested type) " : "");
2507 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2508 prefix_cnt
, path_cnt
,
2509 type
? " (of requested type)" : "");
2514 /* Display specific ES */
2515 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2518 struct evpnes
*es
= NULL
;
2520 es
= bgp_evpn_lookup_es(bgp
, esi
);
2522 display_es(vty
, es
, json
);
2525 vty_out(vty
, "{}\n");
2527 vty_out(vty
, "ESI not found\n");
2533 /* Display all ESs */
2534 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2540 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2541 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2546 hash_iterate(bgp
->esihash
,
2547 (void (*)(struct hash_backet
*, void *))show_es_entry
,
2552 * Display specified VNI (vty handler)
2554 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2558 struct bgpevpn
*vpn
;
2560 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2563 display_vni(vty
, vpn
, json
);
2565 struct bgp
*bgp_temp
;
2566 struct listnode
*node
= NULL
;
2568 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2569 if (bgp_temp
->l3vni
== vni
) {
2571 display_l3vni(vty
, bgp_temp
, json
);
2578 vty_out(vty
, "{}\n");
2580 vty_out(vty
, "VNI not found\n");
2587 * Display a VNI (upon user query).
2589 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2593 struct bgp
*bgp_temp
= NULL
;
2594 struct listnode
*node
;
2598 vty_out(vty
, "Flags: * - Kernel\n");
2599 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2600 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2603 /* print all L2 VNIS */
2606 hash_iterate(bgp
->vnihash
,
2607 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2610 /* print all L3 VNIs */
2611 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2612 show_l3vni_entry(vty
, bgp_temp
, json
);
2616 * evpn - enable advertisement of default g/w
2618 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2621 if (bgp
->advertise_gw_macip
)
2624 bgp
->advertise_gw_macip
= 1;
2625 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2627 if (vpn
->advertise_gw_macip
)
2630 vpn
->advertise_gw_macip
= 1;
2631 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2638 * evpn - disable advertisement of default g/w
2640 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2641 struct bgpevpn
*vpn
)
2644 if (!bgp
->advertise_gw_macip
)
2647 bgp
->advertise_gw_macip
= 0;
2648 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2650 if (!vpn
->advertise_gw_macip
)
2653 vpn
->advertise_gw_macip
= 0;
2654 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2661 * evpn - enable advertisement of default g/w
2663 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2664 afi_t afi
, bool add
)
2666 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2669 /* bail if we are already advertising default route */
2670 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2674 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2675 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2676 else if (afi
== AFI_IP6
)
2677 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2678 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2680 /* bail out if we havent advertised the default route */
2681 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2684 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2685 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2686 else if (afi
== AFI_IP6
)
2687 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2688 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2691 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2695 * evpn - enable advertisement of default g/w
2697 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2698 struct bgpevpn
*vpn
)
2700 if (vpn
->advertise_subnet
)
2703 vpn
->advertise_subnet
= 1;
2704 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2708 * evpn - disable advertisement of default g/w
2710 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2712 if (!vpn
->advertise_subnet
)
2715 vpn
->advertise_subnet
= 0;
2716 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2720 * EVPN (VNI advertisement) enabled. Register with zebra.
2722 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2724 bgp
->advertise_all_vni
= 1;
2725 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2729 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2730 * cache, EVPN routes (delete and withdraw from peers).
2732 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2734 bgp
->advertise_all_vni
= 0;
2735 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2736 bgp_evpn_cleanup_on_disable(bgp
);
2740 * EVPN - use RFC8365 to auto-derive RT
2742 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2744 bgp
->advertise_autort_rfc8365
= 1;
2745 bgp_evpn_handle_autort_change(bgp
);
2749 * EVPN - don't use RFC8365 to auto-derive RT
2751 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2753 bgp
->advertise_autort_rfc8365
= 0;
2754 bgp_evpn_handle_autort_change(bgp
);
2757 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2759 char buf1
[RD_ADDRSTRLEN
];
2761 struct listnode
*node
, *nnode
;
2762 struct ecommunity
*ecom
;
2764 if (is_vni_configured(vpn
)) {
2765 vty_out(vty
, " vni %d\n", vpn
->vni
);
2766 if (is_rd_configured(vpn
))
2767 vty_out(vty
, " rd %s\n",
2768 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2770 if (is_import_rt_configured(vpn
)) {
2771 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2773 ecom_str
= ecommunity_ecom2str(
2774 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2775 vty_out(vty
, " route-target import %s\n",
2777 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2781 if (is_export_rt_configured(vpn
)) {
2782 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2784 ecom_str
= ecommunity_ecom2str(
2785 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2786 vty_out(vty
, " route-target export %s\n",
2788 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2792 if (vpn
->advertise_gw_macip
)
2793 vty_out(vty
, " advertise-default-gw\n");
2795 if (vpn
->advertise_subnet
)
2796 vty_out(vty
, " advertise-subnet\n");
2798 vty_out(vty
, " exit-vni\n");
2802 #ifndef VTYSH_EXTRACT_PL
2803 #include "bgpd/bgp_evpn_vty_clippy.c"
2806 DEFPY(bgp_evpn_flood_control
,
2807 bgp_evpn_flood_control_cmd
,
2808 "[no$no] flooding <disable$disable|head-end-replication$her>",
2810 "Specify handling for BUM packets\n"
2811 "Do not flood any BUM packets\n"
2812 "Flood BUM packets using head-end replication\n")
2814 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2815 enum vxlan_flood_control flood_ctrl
;
2821 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
2823 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
2827 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
2830 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
2831 bgp_evpn_flood_control_change(bgp
);
2836 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2837 bgp_evpn_advertise_default_gw_vni_cmd
,
2838 "advertise-default-gw",
2839 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2841 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2842 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2847 evpn_set_advertise_default_gw(bgp
, vpn
);
2852 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2853 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2854 "no advertise-default-gw",
2856 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2858 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2859 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2864 evpn_unset_advertise_default_gw(bgp
, vpn
);
2870 DEFUN (bgp_evpn_advertise_default_gw
,
2871 bgp_evpn_advertise_default_gw_cmd
,
2872 "advertise-default-gw",
2873 "Advertise All default g/w mac-ip routes in EVPN\n")
2875 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2880 evpn_set_advertise_default_gw(bgp
, NULL
);
2885 DEFUN (no_bgp_evpn_advertise_default_gw
,
2886 no_bgp_evpn_advertise_default_gw_cmd
,
2887 "no advertise-default-gw",
2889 "Withdraw All default g/w mac-ip routes from EVPN\n")
2891 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2896 evpn_unset_advertise_default_gw(bgp
, NULL
);
2901 DEFUN (bgp_evpn_advertise_all_vni
,
2902 bgp_evpn_advertise_all_vni_cmd
,
2903 "advertise-all-vni",
2904 "Advertise All local VNIs\n")
2906 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2910 evpn_set_advertise_all_vni(bgp
);
2914 DEFUN (no_bgp_evpn_advertise_all_vni
,
2915 no_bgp_evpn_advertise_all_vni_cmd
,
2916 "no advertise-all-vni",
2918 "Advertise All local VNIs\n")
2920 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2924 evpn_unset_advertise_all_vni(bgp
);
2928 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2929 bgp_evpn_advertise_autort_rfc8365_cmd
,
2930 "autort rfc8365-compatible",
2931 "Auto-derivation of RT\n"
2932 "Auto-derivation of RT using RFC8365\n")
2934 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2938 evpn_set_advertise_autort_rfc8365(bgp
);
2942 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
2943 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
2944 "no autort rfc8365-compatible",
2946 "Auto-derivation of RT\n"
2947 "Auto-derivation of RT using RFC8365\n")
2949 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2953 evpn_unset_advertise_autort_rfc8365(bgp
);
2957 DEFUN (bgp_evpn_default_originate
,
2958 bgp_evpn_default_originate_cmd
,
2959 "default-originate <ipv4 | ipv6>",
2960 "originate a default route\n"
2961 "ipv4 address family\n"
2962 "ipv6 address family\n")
2966 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2970 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2971 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
2975 DEFUN (no_bgp_evpn_default_originate
,
2976 no_bgp_evpn_default_originate_cmd
,
2977 "no default-originate <ipv4 | ipv6>",
2979 "withdraw a default route\n"
2980 "ipv4 address family\n"
2981 "ipv6 address family\n")
2985 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
2989 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2990 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
2994 DEFPY (dup_addr_detection
,
2995 dup_addr_detection_cmd
,
2996 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
2997 "Duplicate address detection\n"
2998 "Max allowed moves before address detected as duplicate\n"
2999 "Num of max allowed moves (2-1000) default 5\n"
3000 "Duplicate address detection time\n"
3001 "Time in seconds (2-1800) default 180\n")
3003 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3008 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3011 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3013 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3015 bgp_zebra_dup_addr_detection(bgp_vrf
);
3020 DEFPY (dup_addr_detection_auto_recovery
,
3021 dup_addr_detection_auto_recovery_cmd
,
3022 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3023 "Duplicate address detection\n"
3024 "Duplicate address detection freeze\n"
3025 "Duplicate address detection permanent freeze\n"
3026 "Duplicate address detection freeze time (30-3600)\n")
3028 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3029 uint32_t freeze_time
= freeze_time_val
;
3034 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3035 bgp_vrf
->evpn_info
->dad_freeze
= true;
3036 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3038 bgp_zebra_dup_addr_detection(bgp_vrf
);
3043 DEFPY (no_dup_addr_detection
,
3044 no_dup_addr_detection_cmd
,
3045 "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3047 "Duplicate address detection\n"
3048 "Max allowed moves before address detected as duplicate\n"
3049 "Num of max allowed moves (2-1000) default 5\n"
3050 "Duplicate address detection time\n"
3051 "Time in seconds (2-1800) default 180\n"
3052 "Duplicate address detection freeze\n"
3053 "Duplicate address detection permanent freeze\n"
3054 "Duplicate address detection freeze time (30-3600)\n")
3056 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3057 uint32_t max_moves
= (uint32_t)max_moves_val
;
3058 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3064 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3066 /* Reset all parameters to default. */
3067 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3068 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3069 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3070 bgp_vrf
->evpn_info
->dad_freeze
= false;
3071 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3074 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3076 "%% Value does not match with config\n");
3079 bgp_vrf
->evpn_info
->dad_max_moves
=
3080 EVPN_DAD_DEFAULT_MAX_MOVES
;
3084 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3086 "%% Value does not match with config\n");
3089 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3093 if (bgp_vrf
->evpn_info
->dad_freeze_time
3096 "%% Value does not match with config\n");
3099 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3100 bgp_vrf
->evpn_info
->dad_freeze
= false;
3103 if (permanent_val
) {
3104 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3106 "%% Value does not match with config\n");
3109 bgp_vrf
->evpn_info
->dad_freeze
= false;
3113 bgp_zebra_dup_addr_detection(bgp_vrf
);
3118 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3119 bgp_evpn_advertise_vni_subnet_cmd
,
3121 "Advertise the subnet corresponding to VNI\n")
3123 struct bgp
*bgp_vrf
= NULL
;
3124 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3125 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3130 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3134 evpn_set_advertise_subnet(bgp
, vpn
);
3138 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3139 no_bgp_evpn_advertise_vni_subnet_cmd
,
3140 "no advertise-subnet",
3142 "Advertise All local VNIs\n")
3144 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3145 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3150 evpn_unset_advertise_subnet(bgp
, vpn
);
3154 DEFUN (bgp_evpn_advertise_type5
,
3155 bgp_evpn_advertise_type5_cmd
,
3156 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3157 "Advertise prefix routes\n"
3160 "route-map for filtering specific routes\n"
3161 "Name of the route map\n")
3163 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3170 int rmap_changed
= 0;
3172 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3173 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3174 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3176 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3178 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3179 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3182 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3186 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3188 "%%only ipv4 or ipv6 address families are supported");
3192 if (safi
!= SAFI_UNICAST
) {
3194 "%%only ipv4 unicast or ipv6 unicast are supported");
3198 if (afi
== AFI_IP
) {
3200 /* if we are already advertising ipv4 prefix as type-5
3203 if (!rmap_changed
&&
3204 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3205 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3207 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3208 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3211 /* if we are already advertising ipv6 prefix as type-5
3214 if (!rmap_changed
&&
3215 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3216 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3218 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3219 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3223 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3224 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3225 XFREE(MTYPE_ROUTE_MAP_NAME
,
3226 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3227 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3228 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3232 /* set the route-map for advertise command */
3233 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3234 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3235 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3236 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3237 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3240 /* advertise type-5 routes */
3241 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3245 DEFUN (no_bgp_evpn_advertise_type5
,
3246 no_bgp_evpn_advertise_type5_cmd
,
3247 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3249 "Advertise prefix routes\n"
3253 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3259 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3260 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3262 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3264 "%%only ipv4 or ipv6 address families are supported");
3268 if (safi
!= SAFI_UNICAST
) {
3270 "%%only ipv4 unicast or ipv6 unicast are supported");
3274 if (afi
== AFI_IP
) {
3276 /* if we are not advertising ipv4 prefix as type-5
3279 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3280 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3281 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3282 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3283 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3287 /* if we are not advertising ipv6 prefix as type-5
3290 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3291 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3292 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3293 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3294 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3298 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3299 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3300 XFREE(MTYPE_ROUTE_MAP_NAME
,
3301 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3302 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3303 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3310 * Display VNI information - for all or a specific VNI
3312 DEFUN(show_bgp_l2vpn_evpn_vni
,
3313 show_bgp_l2vpn_evpn_vni_cmd
,
3314 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3323 struct bgp
*bgp_def
;
3327 json_object
*json
= NULL
;
3328 uint32_t num_l2vnis
= 0;
3329 uint32_t num_l3vnis
= 0;
3330 uint32_t num_vnis
= 0;
3331 struct listnode
*node
= NULL
;
3332 struct bgp
*bgp_temp
= NULL
;
3334 uj
= use_json(argc
, argv
);
3336 bgp_def
= bgp_get_default();
3340 if (!argv_find(argv
, argc
, "evpn", &idx
))
3344 json
= json_object_new_object();
3346 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3348 num_l2vnis
= hashcount(bgp_def
->vnihash
);
3350 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3351 if (bgp_temp
->l3vni
)
3354 num_vnis
= num_l2vnis
+ num_l3vnis
;
3356 json_object_string_add(json
, "advertiseGatewayMacip",
3357 bgp_def
->advertise_gw_macip
3360 json_object_string_add(json
, "advertiseAllVnis",
3361 is_evpn_enabled() ? "Enabled"
3363 json_object_string_add(
3365 bgp_def
->vxlan_flood_ctrl
3366 == VXLAN_FLOOD_HEAD_END_REPL
3367 ? "Head-end replication"
3369 json_object_int_add(json
, "numVnis", num_vnis
);
3370 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3371 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3373 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3374 bgp_def
->advertise_gw_macip
? "Enabled"
3376 vty_out(vty
, "Advertise All VNI flag: %s\n",
3377 is_evpn_enabled() ? "Enabled" : "Disabled");
3378 vty_out(vty
, "BUM flooding: %s\n",
3379 bgp_def
->vxlan_flood_ctrl
3380 == VXLAN_FLOOD_HEAD_END_REPL
3381 ? "Head-end replication"
3383 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3384 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3386 evpn_show_all_vnis(vty
, bgp_def
, json
);
3390 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3393 /* Display specific VNI */
3394 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3395 evpn_show_vni(vty
, bgp_def
, vni
, json
);
3399 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3400 json
, JSON_C_TO_STRING_PRETTY
));
3401 json_object_free(json
);
3408 DEFUN(show_bgp_l2vpn_evpn_es
,
3409 show_bgp_l2vpn_evpn_es_cmd
,
3410 "show bgp l2vpn evpn es [ESI] [json]",
3415 "ethernet-Segment\n"
3416 "Ethernet-Segment Identifier\n"
3422 json_object
*json
= NULL
;
3423 struct bgp
*bgp
= NULL
;
3425 memset(&esi
, 0, sizeof(esi
));
3426 uj
= use_json(argc
, argv
);
3428 bgp
= bgp_get_default();
3432 if (!argv_find(argv
, argc
, "evpn", &idx
))
3435 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3436 (!uj
&& argc
== (idx
+ 1) + 1)) {
3439 evpn_show_all_es(vty
, bgp
, json
);
3442 /* show a specific ES */
3444 /* get the ESI - ESI-ID is at argv[5] */
3445 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3446 vty_out(vty
, "%% Malformed ESI\n");
3449 evpn_show_es(vty
, bgp
, &esi
, json
);
3453 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3454 json
, JSON_C_TO_STRING_PRETTY
));
3455 json_object_free(json
);
3462 * Display EVPN neighbor summary.
3464 DEFUN(show_bgp_l2vpn_evpn_summary
,
3465 show_bgp_l2vpn_evpn_summary_cmd
,
3466 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3473 "Summary of BGP neighbor status\n"
3477 bool uj
= use_json(argc
, argv
);
3480 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3481 vrf
= argv
[++idx_vrf
]->arg
;
3482 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3486 * Display global EVPN routing table.
3488 DEFUN(show_bgp_l2vpn_evpn_route
,
3489 show_bgp_l2vpn_evpn_route_cmd
,
3490 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3495 "EVPN route information\n"
3496 "Specify Route type\n"
3497 "MAC-IP (Type-2) route\n"
3498 "Multicast (Type-3) route\n"
3499 "Ethernet Segment (type-4) route \n"
3500 "Prefix (type-5 )route\n"
3507 json_object
*json
= NULL
;
3509 uj
= use_json(argc
, argv
);
3511 bgp
= bgp_get_default();
3516 json
= json_object_new_object();
3519 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3520 /* Specific type is requested */
3521 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3522 type
= BGP_EVPN_MAC_IP_ROUTE
;
3523 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3524 type
= BGP_EVPN_IMET_ROUTE
;
3525 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3526 type
= BGP_EVPN_ES_ROUTE
;
3527 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3528 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3533 evpn_show_all_routes(vty
, bgp
, type
, json
);
3536 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3537 json
, JSON_C_TO_STRING_PRETTY
));
3538 json_object_free(json
);
3544 * Display global EVPN routing table for specific RD.
3546 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3547 show_bgp_l2vpn_evpn_route_rd_cmd
,
3548 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3553 "EVPN route information\n"
3554 "Route Distinguisher\n"
3555 "ASN:XX or A.B.C.D:XX\n"
3556 "Specify Route type\n"
3557 "MAC-IP (Type-2) route\n"
3558 "Multicast (Type-3) route\n"
3559 "Ethernet Segment route\n"
3565 struct prefix_rd prd
;
3570 json_object
*json
= NULL
;
3572 bgp
= bgp_get_default();
3576 /* check if we need json output */
3577 uj
= use_json(argc
, argv
);
3579 json
= json_object_new_object();
3582 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3583 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3586 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3592 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3593 /* Specific type is requested */
3594 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3595 type
= BGP_EVPN_MAC_IP_ROUTE
;
3596 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3597 type
= BGP_EVPN_IMET_ROUTE
;
3598 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3599 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3604 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3607 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3608 json
, JSON_C_TO_STRING_PRETTY
));
3609 json_object_free(json
);
3616 * Display global EVPN routing table for specific RD and MACIP.
3618 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3619 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3620 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3625 "EVPN route information\n"
3626 "Route Distinguisher\n"
3627 "ASN:XX or A.B.C.D:XX\n"
3629 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3631 "IP address (IPv4 or IPv6)\n"
3636 struct prefix_rd prd
;
3643 json_object
*json
= NULL
;
3645 memset(&mac
, 0, sizeof(struct ethaddr
));
3646 memset(&ip
, 0, sizeof(struct ipaddr
));
3648 bgp
= bgp_get_default();
3652 /* check if we need json output */
3653 uj
= use_json(argc
, argv
);
3655 json
= json_object_new_object();
3658 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3659 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3661 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3667 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3668 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3669 vty_out(vty
, "%% Malformed MAC address\n");
3674 /* get the ip if specified */
3675 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3676 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3677 vty_out(vty
, "%% Malformed IP address\n");
3682 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3685 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3686 json
, JSON_C_TO_STRING_PRETTY
));
3687 json_object_free(json
);
3693 /* Display per ESI routing table */
3694 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3695 show_bgp_l2vpn_evpn_route_esi_cmd
,
3696 "show bgp l2vpn evpn route esi ESI [json]",
3701 "EVPN route information\n"
3702 "Ethernet Segment Identifier\n"
3708 struct bgp
*bgp
= NULL
;
3709 json_object
*json
= NULL
;
3711 memset(&esi
, 0, sizeof(esi
));
3712 bgp
= bgp_get_default();
3716 uj
= use_json(argc
, argv
);
3718 json
= json_object_new_object();
3720 /* get the ESI - ESI-ID is at argv[6] */
3721 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3722 vty_out(vty
, "%% Malformed ESI\n");
3726 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3729 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3730 json
, JSON_C_TO_STRING_PRETTY
));
3731 json_object_free(json
);
3739 * Display per-VNI EVPN routing table.
3741 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3742 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3747 "EVPN route information\n"
3748 "VXLAN Network Identifier\n"
3750 "Specify Route type\n"
3751 "MAC-IP (Type-2) route\n"
3752 "Multicast (Type-3) route\n"
3754 "Remote VTEP IP address\n"
3759 struct in_addr vtep_ip
;
3763 json_object
*json
= NULL
;
3765 bgp
= bgp_get_default();
3769 /* check if we need json output */
3770 uj
= use_json(argc
, argv
);
3772 json
= json_object_new_object();
3774 if (!argv_find(argv
, argc
, "evpn", &idx
))
3779 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3781 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3782 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3783 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3784 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3785 type
= BGP_EVPN_MAC_IP_ROUTE
;
3786 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3787 type
= BGP_EVPN_IMET_ROUTE
;
3790 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3791 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3792 vty_out(vty
, "%% Malformed VTEP IP address\n");
3799 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3802 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3803 json
, JSON_C_TO_STRING_PRETTY
));
3804 json_object_free(json
);
3811 * Display per-VNI EVPN routing table for specific MACIP.
3813 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3814 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3815 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
3820 "EVPN route information\n"
3821 "VXLAN Network Identifier\n"
3824 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3826 "IP address (IPv4 or IPv6)\n"
3835 json_object
*json
= NULL
;
3837 bgp
= bgp_get_default();
3841 /* check if we need json output */
3842 uj
= use_json(argc
, argv
);
3844 json
= json_object_new_object();
3846 if (!argv_find(argv
, argc
, "evpn", &idx
))
3850 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3853 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3854 vty_out(vty
, "%% Malformed MAC address\n");
3859 memset(&ip
, 0, sizeof(ip
));
3860 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3862 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3863 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3864 vty_out(vty
, "%% Malformed IP address\n");
3869 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3872 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3873 json
, JSON_C_TO_STRING_PRETTY
));
3874 json_object_free(json
);
3881 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3883 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3884 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3885 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
3890 "EVPN route information\n"
3891 "VXLAN Network Identifier\n"
3893 "Multicast (Type-3) route\n"
3894 "Originating Router IP address\n"
3900 struct in_addr orig_ip
;
3903 json_object
*json
= NULL
;
3905 bgp
= bgp_get_default();
3909 /* check if we need json output */
3910 uj
= use_json(argc
, argv
);
3912 json
= json_object_new_object();
3914 if (!argv_find(argv
, argc
, "evpn", &idx
))
3918 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3921 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3923 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3927 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3930 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3931 json
, JSON_C_TO_STRING_PRETTY
));
3932 json_object_free(json
);
3939 * Display per-VNI EVPN routing table - for all VNIs.
3941 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3942 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3943 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3948 "EVPN route information\n"
3949 "VXLAN Network Identifier\n"
3952 "Remote VTEP IP address\n"
3956 struct in_addr vtep_ip
;
3959 json_object
*json
= NULL
;
3961 bgp
= bgp_get_default();
3965 /* check if we need json output */
3966 uj
= use_json(argc
, argv
);
3968 json
= json_object_new_object();
3970 if (!argv_find(argv
, argc
, "evpn", &idx
))
3974 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3975 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3976 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3977 vty_out(vty
, "%% Malformed VTEP IP address\n");
3982 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3985 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3986 json
, JSON_C_TO_STRING_PRETTY
));
3987 json_object_free(json
);
3994 * Display EVPN import route-target hash table
3996 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3997 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3998 "show bgp l2vpn evpn vrf-import-rt [json]",
4003 "Show vrf import route target\n"
4007 struct bgp
*bgp_def
= NULL
;
4008 json_object
*json
= NULL
;
4010 bgp_def
= bgp_get_default();
4014 uj
= use_json(argc
, argv
);
4016 json
= json_object_new_object();
4018 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
4021 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4022 json
, JSON_C_TO_STRING_PRETTY
));
4023 json_object_free(json
);
4030 * Display EVPN import route-target hash table
4032 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4033 show_bgp_l2vpn_evpn_import_rt_cmd
,
4034 "show bgp l2vpn evpn import-rt [json]",
4039 "Show import route target\n"
4044 json_object
*json
= NULL
;
4046 bgp
= bgp_get_default();
4050 uj
= use_json(argc
, argv
);
4052 json
= json_object_new_object();
4054 evpn_show_import_rts(vty
, bgp
, json
);
4057 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4058 json
, JSON_C_TO_STRING_PRETTY
));
4059 json_object_free(json
);
4065 DEFUN(test_adv_evpn_type4_route
,
4066 test_adv_evpn_type4_route_cmd
,
4068 "Advertise EVPN ES route\n"
4069 "Ethernet-segment\n"
4070 "Ethernet-Segment Identifier\n")
4075 struct ipaddr vtep_ip
;
4077 bgp
= bgp_get_default();
4079 vty_out(vty
, "%%Default BGP instance not yet created\n");
4083 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4084 vty_out(vty
, "%%Malformed ESI\n");
4088 vtep_ip
.ipa_type
= IPADDR_V4
;
4089 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4091 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4093 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4099 DEFUN(test_withdraw_evpn_type4_route
,
4100 test_withdraw_evpn_type4_route_cmd
,
4102 "Advertise EVPN ES route\n"
4103 "Ethernet-segment\n"
4104 "Ethernet-Segment Identifier\n")
4109 struct ipaddr vtep_ip
;
4111 bgp
= bgp_get_default();
4113 vty_out(vty
, "%%Default BGP instance not yet created\n");
4117 if (!bgp
->peer_self
) {
4118 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4122 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4123 vty_out(vty
, "%%Malformed ESI\n");
4127 vtep_ip
.ipa_type
= IPADDR_V4
;
4128 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4129 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4131 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4137 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4138 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4142 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4143 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4144 "Summary of BGP neighbor status\n" JSON_STR
)
4146 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4147 "show bgp evpn route [type <macip|multicast>]",
4148 SHOW_STR BGP_STR EVPN_HELP_STR
4149 "EVPN route information\n"
4150 "Specify Route type\n"
4151 "MAC-IP (Type-2) route\n"
4152 "Multicast (Type-3) route\n")
4155 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4156 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4157 SHOW_STR BGP_STR EVPN_HELP_STR
4158 "EVPN route information\n"
4159 "Route Distinguisher\n"
4160 "ASN:XX or A.B.C.D:XX\n"
4161 "Specify Route type\n"
4162 "MAC-IP (Type-2) route\n"
4163 "Multicast (Type-3) route\n")
4166 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4167 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4168 SHOW_STR BGP_STR EVPN_HELP_STR
4169 "EVPN route information\n"
4170 "Route Distinguisher\n"
4171 "ASN:XX or A.B.C.D:XX\n"
4173 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4175 "IP address (IPv4 or IPv6)\n")
4178 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4179 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4180 SHOW_STR BGP_STR EVPN_HELP_STR
4181 "EVPN route information\n"
4182 "VXLAN Network Identifier\n"
4184 "Specify Route type\n"
4185 "MAC-IP (Type-2) route\n"
4186 "Multicast (Type-3) route\n"
4188 "Remote VTEP IP address\n")
4190 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4191 show_bgp_evpn_route_vni_macip_cmd
,
4192 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4193 SHOW_STR BGP_STR EVPN_HELP_STR
4194 "EVPN route information\n"
4195 "VXLAN Network Identifier\n"
4198 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4200 "IP address (IPv4 or IPv6)\n")
4202 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4203 show_bgp_evpn_route_vni_multicast_cmd
,
4204 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4205 SHOW_STR BGP_STR EVPN_HELP_STR
4206 "EVPN route information\n"
4207 "VXLAN Network Identifier\n"
4209 "Multicast (Type-3) route\n"
4210 "Originating Router IP address\n")
4212 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4213 "show bgp evpn route vni all [vtep A.B.C.D]",
4214 SHOW_STR BGP_STR EVPN_HELP_STR
4215 "EVPN route information\n"
4216 "VXLAN Network Identifier\n"
4219 "Remote VTEP IP address\n")
4221 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4222 "show bgp evpn import-rt",
4223 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4225 DEFUN_NOSH (bgp_evpn_vni
,
4227 "vni " CMD_VNI_RANGE
,
4228 "VXLAN Network Identifier\n"
4232 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4233 struct bgpevpn
*vpn
;
4238 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4240 /* Create VNI, or mark as configured. */
4241 vpn
= evpn_create_update_vni(bgp
, vni
);
4243 vty_out(vty
, "%% Failed to create VNI \n");
4247 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4251 DEFUN (no_bgp_evpn_vni
,
4252 no_bgp_evpn_vni_cmd
,
4253 "no vni " CMD_VNI_RANGE
,
4255 "VXLAN Network Identifier\n"
4259 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4260 struct bgpevpn
*vpn
;
4265 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4267 /* Check if we should disallow. */
4268 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4270 vty_out(vty
, "%% Specified VNI does not exist\n");
4273 if (!is_vni_configured(vpn
)) {
4274 vty_out(vty
, "%% Specified VNI is not configured\n");
4278 evpn_delete_vni(bgp
, vpn
);
4282 DEFUN_NOSH (exit_vni
,
4285 "Exit from VNI mode\n")
4287 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4288 vty
->node
= BGP_EVPN_NODE
;
4292 DEFUN (bgp_evpn_vrf_rd
,
4293 bgp_evpn_vrf_rd_cmd
,
4294 "rd ASN:NN_OR_IP-ADDRESS:NN",
4295 "Route Distinguisher\n"
4296 "ASN:XX or A.B.C.D:XX\n")
4299 struct prefix_rd prd
;
4300 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4305 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4307 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4311 /* If same as existing value, there is nothing more to do. */
4312 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4315 /* Configure or update the RD. */
4316 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4320 DEFUN (no_bgp_evpn_vrf_rd
,
4321 no_bgp_evpn_vrf_rd_cmd
,
4322 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4324 "Route Distinguisher\n"
4325 "ASN:XX or A.B.C.D:XX\n")
4328 struct prefix_rd prd
;
4329 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4334 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4336 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4340 /* Check if we should disallow. */
4341 if (!is_vrf_rd_configured(bgp_vrf
)) {
4342 vty_out(vty
, "%% RD is not configured for this VRF\n");
4346 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4348 "%% RD specified does not match configuration for this VRF\n");
4352 evpn_unconfigure_vrf_rd(bgp_vrf
);
4356 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4357 no_bgp_evpn_vrf_rd_without_val_cmd
,
4360 "Route Distinguisher\n")
4362 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4367 /* Check if we should disallow. */
4368 if (!is_vrf_rd_configured(bgp_vrf
)) {
4369 vty_out(vty
, "%% RD is not configured for this VRF\n");
4373 evpn_unconfigure_vrf_rd(bgp_vrf
);
4377 DEFUN (bgp_evpn_vni_rd
,
4378 bgp_evpn_vni_rd_cmd
,
4379 "rd ASN:NN_OR_IP-ADDRESS:NN",
4380 "Route Distinguisher\n"
4381 "ASN:XX or A.B.C.D:XX\n")
4383 struct prefix_rd prd
;
4384 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4385 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4391 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4393 "This command is only supported under Default VRF\n");
4397 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4399 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4403 /* If same as existing value, there is nothing more to do. */
4404 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4407 /* Configure or update the RD. */
4408 evpn_configure_rd(bgp
, vpn
, &prd
);
4412 DEFUN (no_bgp_evpn_vni_rd
,
4413 no_bgp_evpn_vni_rd_cmd
,
4414 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4416 "Route Distinguisher\n"
4417 "ASN:XX or A.B.C.D:XX\n")
4419 struct prefix_rd prd
;
4420 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4421 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4427 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4429 "This command is only supported under Default VRF\n");
4433 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4435 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4439 /* Check if we should disallow. */
4440 if (!is_rd_configured(vpn
)) {
4441 vty_out(vty
, "%% RD is not configured for this VNI\n");
4445 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4447 "%% RD specified does not match configuration for this VNI\n");
4451 evpn_unconfigure_rd(bgp
, vpn
);
4455 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4456 no_bgp_evpn_vni_rd_without_val_cmd
,
4459 "Route Distinguisher\n")
4461 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4462 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4467 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4469 "This command is only supported under Default VRF\n");
4473 /* Check if we should disallow. */
4474 if (!is_rd_configured(vpn
)) {
4475 vty_out(vty
, "%% RD is not configured for this VNI\n");
4479 evpn_unconfigure_rd(bgp
, vpn
);
4484 * Loop over all extended-communities in the route-target list rtl and
4485 * return 1 if we find ecomtarget
4487 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4488 struct ecommunity
*ecomtarget
)
4490 struct listnode
*node
, *nnode
;
4491 struct ecommunity
*ecom
;
4493 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4494 if (ecommunity_match(ecom
, ecomtarget
))
4501 /* display L3VNI related info for a VRF instance */
4502 DEFUN (show_bgp_vrf_l3vni_info
,
4503 show_bgp_vrf_l3vni_info_cmd
,
4504 "show bgp vrf VRFNAME vni [json]",
4512 char buf
[ETHER_ADDR_STRLEN
];
4513 char buf1
[INET6_ADDRSTRLEN
];
4515 const char *name
= NULL
;
4516 struct bgp
*bgp
= NULL
;
4517 struct listnode
*node
= NULL
;
4518 struct bgpevpn
*vpn
= NULL
;
4519 struct ecommunity
*ecom
= NULL
;
4520 json_object
*json
= NULL
;
4521 json_object
*json_vnis
= NULL
;
4522 json_object
*json_export_rts
= NULL
;
4523 json_object
*json_import_rts
= NULL
;
4524 bool uj
= use_json(argc
, argv
);
4527 json
= json_object_new_object();
4528 json_vnis
= json_object_new_array();
4529 json_export_rts
= json_object_new_array();
4530 json_import_rts
= json_object_new_array();
4533 name
= argv
[idx_vrf
]->arg
;
4534 bgp
= bgp_lookup_by_name(name
);
4537 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4539 json_object_string_add(json
, "warning",
4540 "BGP instance not found");
4541 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4542 json_object_free(json
);
4548 vty_out(vty
, "BGP VRF: %s\n", name
);
4549 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4550 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4551 vty_out(vty
, " Rmac: %s\n",
4552 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4553 vty_out(vty
, " VNI Filter: %s\n",
4554 CHECK_FLAG(bgp
->vrf_flags
,
4555 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4556 ? "prefix-routes-only"
4558 vty_out(vty
, " L2-VNI List:\n");
4560 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4561 vty_out(vty
, "%u ", vpn
->vni
);
4563 vty_out(vty
, " Export-RTs:\n");
4565 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4566 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4568 vty_out(vty
, " Import-RTs:\n");
4570 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4571 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4573 vty_out(vty
, " RD: %s\n",
4574 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4576 json_object_string_add(json
, "vrf", name
);
4577 json_object_string_add(json
, "local-ip",
4578 inet_ntoa(bgp
->originator_ip
));
4579 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4580 json_object_string_add(
4582 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4583 json_object_string_add(
4585 CHECK_FLAG(bgp
->vrf_flags
,
4586 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4587 ? "prefix-routes-only"
4589 /* list of l2vnis */
4590 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4591 json_object_array_add(json_vnis
,
4592 json_object_new_int(vpn
->vni
));
4593 json_object_object_add(json
, "l2vnis", json_vnis
);
4596 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4597 json_object_array_add(
4599 json_object_new_string(ecommunity_str(ecom
)));
4600 json_object_object_add(json
, "export-rts", json_export_rts
);
4603 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4604 json_object_array_add(
4606 json_object_new_string(ecommunity_str(ecom
)));
4607 json_object_object_add(json
, "import-rts", json_import_rts
);
4608 json_object_string_add(
4610 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4614 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4615 json
, JSON_C_TO_STRING_PRETTY
));
4616 json_object_free(json
);
4621 /* import/export rt for l3vni-vrf */
4622 DEFUN (bgp_evpn_vrf_rt
,
4623 bgp_evpn_vrf_rt_cmd
,
4624 "route-target <both|import|export> RT",
4626 "import and export\n"
4629 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4632 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4633 struct ecommunity
*ecomadd
= NULL
;
4638 if (!strcmp(argv
[1]->arg
, "import"))
4639 rt_type
= RT_TYPE_IMPORT
;
4640 else if (!strcmp(argv
[1]->arg
, "export"))
4641 rt_type
= RT_TYPE_EXPORT
;
4642 else if (!strcmp(argv
[1]->arg
, "both"))
4643 rt_type
= RT_TYPE_BOTH
;
4645 vty_out(vty
, "%% Invalid Route Target type\n");
4649 /* Add/update the import route-target */
4650 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4651 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4652 ECOMMUNITY_ROUTE_TARGET
, 0);
4654 vty_out(vty
, "%% Malformed Route Target list\n");
4657 ecommunity_str(ecomadd
);
4659 /* Do nothing if we already have this import route-target */
4660 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4661 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4664 /* Add/update the export route-target */
4665 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4666 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4667 ECOMMUNITY_ROUTE_TARGET
, 0);
4669 vty_out(vty
, "%% Malformed Route Target list\n");
4672 ecommunity_str(ecomadd
);
4674 /* Do nothing if we already have this export route-target */
4675 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4676 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4682 DEFUN (no_bgp_evpn_vrf_rt
,
4683 no_bgp_evpn_vrf_rt_cmd
,
4684 "no route-target <both|import|export> RT",
4687 "import and export\n"
4690 "ASN:XX or A.B.C.D:XX\n")
4692 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4693 int rt_type
, found_ecomdel
;
4694 struct ecommunity
*ecomdel
= NULL
;
4699 if (!strcmp(argv
[2]->arg
, "import"))
4700 rt_type
= RT_TYPE_IMPORT
;
4701 else if (!strcmp(argv
[2]->arg
, "export"))
4702 rt_type
= RT_TYPE_EXPORT
;
4703 else if (!strcmp(argv
[2]->arg
, "both"))
4704 rt_type
= RT_TYPE_BOTH
;
4706 vty_out(vty
, "%% Invalid Route Target type\n");
4710 if (rt_type
== RT_TYPE_IMPORT
) {
4711 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4713 "%% Import RT is not configured for this VRF\n");
4716 } else if (rt_type
== RT_TYPE_EXPORT
) {
4717 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4719 "%% Export RT is not configured for this VRF\n");
4722 } else if (rt_type
== RT_TYPE_BOTH
) {
4723 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4724 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4726 "%% Import/Export RT is not configured for this VRF\n");
4731 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4733 vty_out(vty
, "%% Malformed Route Target list\n");
4736 ecommunity_str(ecomdel
);
4738 if (rt_type
== RT_TYPE_IMPORT
) {
4739 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4742 "%% RT specified does not match configuration for this VRF\n");
4745 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4746 } else if (rt_type
== RT_TYPE_EXPORT
) {
4747 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4750 "%% RT specified does not match configuration for this VRF\n");
4753 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4754 } else if (rt_type
== RT_TYPE_BOTH
) {
4757 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4759 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4763 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4765 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4769 if (!found_ecomdel
) {
4771 "%% RT specified does not match configuration for this VRF\n");
4779 DEFUN (bgp_evpn_vni_rt
,
4780 bgp_evpn_vni_rt_cmd
,
4781 "route-target <both|import|export> RT",
4783 "import and export\n"
4786 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4788 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4789 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4791 struct ecommunity
*ecomadd
= NULL
;
4796 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4798 "This command is only supported under Default VRF\n");
4802 if (!strcmp(argv
[1]->text
, "import"))
4803 rt_type
= RT_TYPE_IMPORT
;
4804 else if (!strcmp(argv
[1]->text
, "export"))
4805 rt_type
= RT_TYPE_EXPORT
;
4806 else if (!strcmp(argv
[1]->text
, "both"))
4807 rt_type
= RT_TYPE_BOTH
;
4809 vty_out(vty
, "%% Invalid Route Target type\n");
4813 /* Add/update the import route-target */
4814 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4815 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4816 ECOMMUNITY_ROUTE_TARGET
, 0);
4818 vty_out(vty
, "%% Malformed Route Target list\n");
4821 ecommunity_str(ecomadd
);
4823 /* Do nothing if we already have this import route-target */
4824 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4825 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4828 /* Add/update the export route-target */
4829 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4830 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4831 ECOMMUNITY_ROUTE_TARGET
, 0);
4833 vty_out(vty
, "%% Malformed Route Target list\n");
4836 ecommunity_str(ecomadd
);
4838 /* Do nothing if we already have this export route-target */
4839 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4840 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4846 DEFUN (no_bgp_evpn_vni_rt
,
4847 no_bgp_evpn_vni_rt_cmd
,
4848 "no route-target <both|import|export> RT",
4851 "import and export\n"
4854 "ASN:XX or A.B.C.D:XX\n")
4856 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4857 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4858 int rt_type
, found_ecomdel
;
4859 struct ecommunity
*ecomdel
= NULL
;
4864 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4866 "This command is only supported under Default VRF\n");
4870 if (!strcmp(argv
[2]->text
, "import"))
4871 rt_type
= RT_TYPE_IMPORT
;
4872 else if (!strcmp(argv
[2]->text
, "export"))
4873 rt_type
= RT_TYPE_EXPORT
;
4874 else if (!strcmp(argv
[2]->text
, "both"))
4875 rt_type
= RT_TYPE_BOTH
;
4877 vty_out(vty
, "%% Invalid Route Target type\n");
4881 /* The user did "no route-target import", check to see if there are any
4882 * import route-targets configured. */
4883 if (rt_type
== RT_TYPE_IMPORT
) {
4884 if (!is_import_rt_configured(vpn
)) {
4886 "%% Import RT is not configured for this VNI\n");
4889 } else if (rt_type
== RT_TYPE_EXPORT
) {
4890 if (!is_export_rt_configured(vpn
)) {
4892 "%% Export RT is not configured for this VNI\n");
4895 } else if (rt_type
== RT_TYPE_BOTH
) {
4896 if (!is_import_rt_configured(vpn
)
4897 && !is_export_rt_configured(vpn
)) {
4899 "%% Import/Export RT is not configured for this VNI\n");
4904 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4906 vty_out(vty
, "%% Malformed Route Target list\n");
4909 ecommunity_str(ecomdel
);
4911 if (rt_type
== RT_TYPE_IMPORT
) {
4912 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4914 "%% RT specified does not match configuration for this VNI\n");
4917 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4918 } else if (rt_type
== RT_TYPE_EXPORT
) {
4919 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4921 "%% RT specified does not match configuration for this VNI\n");
4924 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4925 } else if (rt_type
== RT_TYPE_BOTH
) {
4928 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4929 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4933 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4934 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4938 if (!found_ecomdel
) {
4940 "%% RT specified does not match configuration for this VNI\n");
4948 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4949 no_bgp_evpn_vni_rt_without_val_cmd
,
4950 "no route-target <import|export>",
4956 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4957 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4963 if (bgp
->vrf_id
!= VRF_DEFAULT
) {
4965 "This command is only supported under Default VRF\n");
4969 if (!strcmp(argv
[2]->text
, "import")) {
4970 rt_type
= RT_TYPE_IMPORT
;
4971 } else if (!strcmp(argv
[2]->text
, "export")) {
4972 rt_type
= RT_TYPE_EXPORT
;
4974 vty_out(vty
, "%% Invalid Route Target type\n");
4978 /* Check if we should disallow. */
4979 if (rt_type
== RT_TYPE_IMPORT
) {
4980 if (!is_import_rt_configured(vpn
)) {
4982 "%% Import RT is not configured for this VNI\n");
4986 if (!is_export_rt_configured(vpn
)) {
4988 "%% Export RT is not configured for this VNI\n");
4993 /* Unconfigure the RT. */
4994 if (rt_type
== RT_TYPE_IMPORT
)
4995 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4997 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5001 static int vni_cmp(const void **a
, const void **b
)
5003 const struct bgpevpn
*first
= *a
;
5004 const struct bgpevpn
*secnd
= *b
;
5006 return secnd
->vni
- first
->vni
;
5010 * Output EVPN configuration information.
5012 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5015 char buf1
[RD_ADDRSTRLEN
];
5018 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5019 struct listnode
*ln
;
5020 struct bgpevpn
*data
;
5022 list_sort(vnilist
, vni_cmp
);
5023 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5024 write_vni_config(vty
, data
);
5026 list_delete(&vnilist
);
5029 if (bgp
->advertise_all_vni
)
5030 vty_out(vty
, " advertise-all-vni\n");
5032 if (bgp
->advertise_autort_rfc8365
)
5033 vty_out(vty
, " autort rfc8365-compatible\n");
5035 if (bgp
->advertise_gw_macip
)
5036 vty_out(vty
, " advertise-default-gw\n");
5038 if (!bgp
->evpn_info
->dup_addr_detect
)
5039 vty_out(vty
, " no dup-addr-detection\n");
5041 if (bgp
->evpn_info
->dad_max_moves
!=
5042 EVPN_DAD_DEFAULT_MAX_MOVES
||
5043 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5044 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5045 bgp
->evpn_info
->dad_max_moves
,
5046 bgp
->evpn_info
->dad_time
);
5048 if (bgp
->evpn_info
->dad_freeze
) {
5049 if (bgp
->evpn_info
->dad_freeze_time
)
5051 " dup-addr-detection freeze %u\n",
5052 bgp
->evpn_info
->dad_freeze_time
);
5055 " dup-addr-detection freeze permanent\n");
5058 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5059 vty_out(vty
, " flooding disable\n");
5061 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5062 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5063 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5064 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5065 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5067 vty_out(vty
, " advertise ipv4 unicast\n");
5070 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5071 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5072 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5073 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5074 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5076 vty_out(vty
, " advertise ipv6 unicast\n");
5079 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5080 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5081 vty_out(vty
, " default-originate ipv4\n");
5083 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5084 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5085 vty_out(vty
, " default-originate ipv6\n");
5087 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5088 vty_out(vty
, " rd %s\n",
5089 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5091 /* import route-target */
5092 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5094 struct listnode
*node
, *nnode
;
5095 struct ecommunity
*ecom
;
5097 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5099 ecom_str
= ecommunity_ecom2str(
5100 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5101 vty_out(vty
, " route-target import %s\n", ecom_str
);
5102 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5106 /* export route-target */
5107 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5109 struct listnode
*node
, *nnode
;
5110 struct ecommunity
*ecom
;
5112 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5114 ecom_str
= ecommunity_ecom2str(
5115 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5116 vty_out(vty
, " route-target export %s\n", ecom_str
);
5117 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5122 void bgp_ethernetvpn_init(void)
5124 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5125 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5126 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5127 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5128 install_element(VIEW_NODE
,
5129 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
5130 install_element(VIEW_NODE
,
5131 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5134 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
5137 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5138 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5139 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5140 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5141 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5142 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5143 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5144 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5145 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5146 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5147 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5148 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5149 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5150 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5151 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5152 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5153 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5154 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5155 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5158 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5159 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5161 /* "show bgp l2vpn evpn" commands. */
5162 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5163 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5164 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5165 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5166 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5167 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5168 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5169 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5170 install_element(VIEW_NODE
,
5171 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5172 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5173 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5174 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5175 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5177 /* "show bgp evpn" commands. */
5178 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5179 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5180 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5181 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5182 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5183 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5184 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5185 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5186 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5187 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5188 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5190 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5191 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5192 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5193 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5194 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5195 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5196 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5197 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5198 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5199 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5200 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5201 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5202 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5203 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5204 install_element(BGP_EVPN_VNI_NODE
,
5205 &bgp_evpn_advertise_default_gw_vni_cmd
);
5206 install_element(BGP_EVPN_VNI_NODE
,
5207 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5208 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5209 install_element(BGP_EVPN_VNI_NODE
,
5210 &no_bgp_evpn_advertise_vni_subnet_cmd
);