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_bucket
*bucket
, void *args
[])
154 json_object
*json
= NULL
;
155 struct vty
*vty
= NULL
;
156 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->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_bucket
*bucket
, void *args
[])
261 json_object
*json
= NULL
;
262 struct vty
*vty
= NULL
;
263 struct irt_node
*irt
= (struct irt_node
*)bucket
->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");
492 vty_out(vty
, " Advertise-svi-macip : %s\n",
493 vpn
->advertise_svi_macip
? "Yes" : "No");
497 vty_out(vty
, " Import Route Target:\n");
499 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
500 ecom_str
= ecommunity_ecom2str(ecom
,
501 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
504 json_object_array_add(json_import_rtl
,
505 json_object_new_string(ecom_str
));
507 vty_out(vty
, " %s\n", ecom_str
);
509 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
513 json_object_object_add(json
, "importRts", json_import_rtl
);
515 vty_out(vty
, " Export Route Target:\n");
517 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
518 ecom_str
= ecommunity_ecom2str(ecom
,
519 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
522 json_object_array_add(json_export_rtl
,
523 json_object_new_string(ecom_str
));
525 vty_out(vty
, " %s\n", ecom_str
);
527 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
531 json_object_object_add(json
, "exportRts", json_export_rtl
);
534 static void show_esi_routes(struct bgp
*bgp
,
541 struct bgp_path_info
*pi
;
542 uint32_t prefix_cnt
, path_cnt
;
545 prefix_cnt
= path_cnt
= 0;
547 tbl_ver
= es
->route_table
->version
;
548 for (rn
= bgp_table_top(es
->route_table
); rn
;
549 rn
= bgp_route_next(rn
)) {
550 int add_prefix_to_json
= 0;
551 char prefix_str
[BUFSIZ
];
552 json_object
*json_paths
= NULL
;
553 json_object
*json_prefix
= NULL
;
555 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
559 json_prefix
= json_object_new_object();
561 pi
= bgp_node_get_bgp_path_info(rn
);
563 /* Overall header/legend displayed once. */
565 bgp_evpn_show_route_header(vty
, bgp
,
574 json_paths
= json_object_new_array();
576 /* For EVPN, the prefix is displayed for each path (to fit in
577 * with code that already exists).
579 for (; pi
; pi
= pi
->next
) {
580 json_object
*json_path
= NULL
;
583 json_path
= json_object_new_array();
585 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
588 json_object_array_add(json_paths
, json_path
);
591 add_prefix_to_json
= 1;
594 if (json
&& add_prefix_to_json
) {
595 json_object_string_add(json_prefix
, "prefix",
597 json_object_int_add(json_prefix
, "prefixLen",
599 json_object_object_add(json_prefix
, "paths",
601 json_object_object_add(json
, prefix_str
, json_prefix
);
606 json_object_int_add(json
, "numPrefix", prefix_cnt
);
607 json_object_int_add(json
, "numPaths", path_cnt
);
610 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
612 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
613 prefix_cnt
, path_cnt
);
617 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
618 struct vty
*vty
, struct in_addr vtep_ip
,
622 struct bgp_path_info
*pi
;
623 struct bgp_table
*table
;
626 uint32_t prefix_cnt
, path_cnt
;
628 prefix_cnt
= path_cnt
= 0;
630 table
= vpn
->route_table
;
631 tbl_ver
= table
->version
;
632 for (rn
= bgp_table_top(table
); rn
;
633 rn
= bgp_route_next(rn
)) {
634 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
635 int add_prefix_to_json
= 0;
636 char prefix_str
[BUFSIZ
];
637 json_object
*json_paths
= NULL
;
638 json_object
*json_prefix
= NULL
;
640 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
643 if (type
&& evp
->prefix
.route_type
!= type
)
647 json_prefix
= json_object_new_object();
649 pi
= bgp_node_get_bgp_path_info(rn
);
651 /* Overall header/legend displayed once. */
653 bgp_evpn_show_route_header(vty
, bgp
,
662 json_paths
= json_object_new_array();
664 /* For EVPN, the prefix is displayed for each path (to fit in
665 * with code that already exists).
667 for (; pi
; pi
= pi
->next
) {
668 json_object
*json_path
= NULL
;
671 && !IPV4_ADDR_SAME(&(vtep_ip
),
672 &(pi
->attr
->nexthop
)))
676 json_path
= json_object_new_array();
678 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
, json_path
);
681 json_object_array_add(json_paths
, json_path
);
684 add_prefix_to_json
= 1;
687 if (json
&& add_prefix_to_json
) {
688 json_object_string_add(json_prefix
, "prefix",
690 json_object_int_add(json_prefix
, "prefixLen",
692 json_object_object_add(json_prefix
, "paths",
694 json_object_object_add(json
, prefix_str
, json_prefix
);
699 json_object_int_add(json
, "numPrefix", prefix_cnt
);
700 json_object_int_add(json
, "numPaths", path_cnt
);
703 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
704 type
? "(of requested type) " : "");
706 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
707 prefix_cnt
, path_cnt
,
708 type
? " (of requested type)" : "");
712 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
714 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
715 struct vni_walk_ctx
*wctx
= arg
;
716 struct vty
*vty
= wctx
->vty
;
717 json_object
*json
= wctx
->json
;
718 json_object
*json_vni
= NULL
;
719 char vni_str
[VNI_STR_LEN
];
721 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
723 json_vni
= json_object_new_object();
724 json_object_int_add(json_vni
, "vni", vpn
->vni
);
726 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
729 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
732 json_object_object_add(json
, vni_str
, json_vni
);
735 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
738 json_object
*json_vni
= NULL
;
739 json_object
*json_import_rtl
= NULL
;
740 json_object
*json_export_rtl
= NULL
;
742 char buf2
[INET6_ADDRSTRLEN
];
745 struct listnode
*node
, *nnode
;
746 struct ecommunity
*ecom
;
752 json_vni
= json_object_new_object();
753 json_import_rtl
= json_object_new_array();
754 json_export_rtl
= json_object_new_array();
757 /* if an l3vni is present in bgp it is live */
762 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
763 json_object_string_add(json_vni
, "type", "L3");
764 json_object_string_add(json_vni
, "inKernel", "True");
765 json_object_string_add(json_vni
, "originatorIp",
766 inet_ntoa(bgp
->originator_ip
));
767 json_object_string_add(
769 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
771 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
772 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
775 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
776 ecom_str
= ecommunity_ecom2str(ecom
,
777 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
780 json_object_array_add(json_import_rtl
,
781 json_object_new_string(ecom_str
));
783 if (listcount(bgp
->vrf_import_rtl
) > 1)
784 sprintf(rt_buf
, "%s, ...", ecom_str
);
786 sprintf(rt_buf
, "%s", ecom_str
);
787 vty_out(vty
, " %-25s", rt_buf
);
790 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
792 /* If there are multiple import RTs we break here and show only
799 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
801 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
802 ecom_str
= ecommunity_ecom2str(ecom
,
803 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
806 json_object_array_add(json_export_rtl
,
807 json_object_new_string(ecom_str
));
809 if (listcount(bgp
->vrf_export_rtl
) > 1)
810 sprintf(rt_buf
, "%s, ...", ecom_str
);
812 sprintf(rt_buf
, "%s", ecom_str
);
813 vty_out(vty
, " %-25s", rt_buf
);
816 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
818 /* If there are multiple export RTs we break here and show only
825 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
828 char vni_str
[VNI_STR_LEN
];
830 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
831 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
832 json_object_object_add(json
, vni_str
, json_vni
);
838 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
840 char buf
[ESI_STR_LEN
];
841 char buf1
[RD_ADDRSTRLEN
];
842 char buf2
[INET6_ADDRSTRLEN
];
843 struct in_addr
*vtep
= NULL
;
844 struct vty
*vty
= args
[0];
845 json_object
*json
= args
[1];
846 json_object
*json_vteps
= NULL
;
847 struct listnode
*node
= NULL
;
848 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
851 json_vteps
= json_object_new_array();
852 json_object_string_add(json
, "esi",
853 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
854 json_object_string_add(json
, "type",
855 is_es_local(es
) ? "Local" : "Remote");
856 json_object_string_add(json
, "rd",
857 prefix_rd2str(&es
->prd
, buf1
,
859 json_object_string_add(
860 json
, "originatorIp",
861 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
863 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
864 json_object_array_add(json_vteps
,
865 json_object_new_string(
868 json_object_object_add(json
, "vteps", json_vteps
);
870 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
871 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
872 is_es_local(es
) ? "Local" : "Remote",
873 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
874 ipaddr2str(&es
->originator_ip
, buf2
,
876 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
880 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
884 json_object
*json_vni
= NULL
;
885 json_object
*json_import_rtl
= NULL
;
886 json_object
*json_export_rtl
= NULL
;
887 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
889 char buf2
[RD_ADDRSTRLEN
];
892 struct listnode
*node
, *nnode
;
893 struct ecommunity
*ecom
;
899 json_vni
= json_object_new_object();
900 json_import_rtl
= json_object_new_array();
901 json_export_rtl
= json_object_new_array();
905 if (is_vni_live(vpn
))
909 json_object_int_add(json_vni
, "vni", vpn
->vni
);
910 json_object_string_add(json_vni
, "type", "L2");
911 json_object_string_add(json_vni
, "inKernel",
912 is_vni_live(vpn
) ? "True" : "False");
913 json_object_string_add(json_vni
, "originatorIp",
914 inet_ntoa(vpn
->originator_ip
));
915 json_object_string_add(json_vni
, "originatorIp",
916 inet_ntoa(vpn
->originator_ip
));
917 json_object_string_add(
919 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
921 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
922 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
925 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
926 ecom_str
= ecommunity_ecom2str(ecom
,
927 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
930 json_object_array_add(json_import_rtl
,
931 json_object_new_string(ecom_str
));
933 if (listcount(vpn
->import_rtl
) > 1)
934 sprintf(rt_buf
, "%s, ...", ecom_str
);
936 sprintf(rt_buf
, "%s", ecom_str
);
937 vty_out(vty
, " %-25s", rt_buf
);
940 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
942 /* If there are multiple import RTs we break here and show only
949 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
951 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
952 ecom_str
= ecommunity_ecom2str(ecom
,
953 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
956 json_object_array_add(json_export_rtl
,
957 json_object_new_string(ecom_str
));
959 if (listcount(vpn
->export_rtl
) > 1)
960 sprintf(rt_buf
, "%s, ...", ecom_str
);
962 sprintf(rt_buf
, "%s", ecom_str
);
963 vty_out(vty
, " %-25s", rt_buf
);
966 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
968 /* If there are multiple export RTs we break here and show only
975 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
978 char vni_str
[VNI_STR_LEN
];
980 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
981 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
982 json_object_object_add(json
, vni_str
, json_vni
);
988 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
989 enum bgp_show_type type
, void *output_arg
,
990 int option
, bool use_json
)
992 afi_t afi
= AFI_L2VPN
;
994 struct bgp_table
*table
;
997 struct bgp_path_info
*pi
;
1001 unsigned long output_count
= 0;
1002 unsigned long total_count
= 0;
1003 json_object
*json
= NULL
;
1004 json_object
*json_nroute
= NULL
;
1005 json_object
*json_array
= NULL
;
1006 json_object
*json_scode
= NULL
;
1007 json_object
*json_ocode
= NULL
;
1009 bgp
= bgp_get_evpn();
1012 vty_out(vty
, "No BGP process is configured\n");
1014 vty_out(vty
, "{}\n");
1019 json_scode
= json_object_new_object();
1020 json_ocode
= json_object_new_object();
1021 json
= json_object_new_object();
1022 json_nroute
= json_object_new_object();
1024 json_object_string_add(json_scode
, "suppressed", "s");
1025 json_object_string_add(json_scode
, "damped", "d");
1026 json_object_string_add(json_scode
, "history", "h");
1027 json_object_string_add(json_scode
, "valid", "*");
1028 json_object_string_add(json_scode
, "best", ">");
1029 json_object_string_add(json_scode
, "internal", "i");
1031 json_object_string_add(json_ocode
, "igp", "i");
1032 json_object_string_add(json_ocode
, "egp", "e");
1033 json_object_string_add(json_ocode
, "incomplete", "?");
1036 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1037 rn
= bgp_route_next(rn
)) {
1041 continue; /* XXX json TODO */
1043 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
1046 table
= bgp_node_get_bgp_table_info(rn
);
1051 tbl_ver
= table
->version
;
1053 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
1054 for (pi
= bgp_node_get_bgp_path_info(rm
); pi
;
1057 if (type
== bgp_show_type_neighbor
) {
1058 union sockunion
*su
= output_arg
;
1060 if (pi
->peer
->su_remote
== NULL
1062 pi
->peer
->su_remote
, su
))
1068 == SHOW_DISPLAY_TAGS
) {
1069 json_object_int_add(
1073 json_object_string_add(
1078 json_object_object_add(
1082 json_object_object_add(
1088 if (option
== SHOW_DISPLAY_TAGS
)
1093 == SHOW_DISPLAY_OVERLAY
)
1098 "BGP table version is %" PRIu64
", local router ID is %s\n",
1103 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
1105 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
1106 vty_out(vty
, V4_HEADER
);
1119 /* Decode RD type. */
1120 type
= decode_rd_type(pnt
);
1121 /* Decode RD value. */
1122 if (type
== RD_TYPE_AS
)
1123 decode_rd_as(pnt
+ 2, &rd_as
);
1124 else if (type
== RD_TYPE_AS4
)
1125 decode_rd_as4(pnt
+ 2, &rd_as
);
1126 else if (type
== RD_TYPE_IP
)
1127 decode_rd_ip(pnt
+ 2, &rd_ip
);
1129 char buffer
[BUFSIZ
];
1130 if (type
== RD_TYPE_AS
1131 || type
== RD_TYPE_AS4
)
1132 sprintf(buffer
, "%u:%d",
1135 else if (type
== RD_TYPE_IP
)
1136 sprintf(buffer
, "%s:%d",
1140 json_object_string_add(
1142 "routeDistinguisher",
1146 "Route Distinguisher: ");
1147 if (type
== RD_TYPE_AS
)
1152 else if (type
== RD_TYPE_AS4
)
1157 else if (type
== RD_TYPE_IP
)
1158 vty_out(vty
, "ip %s:%d",
1162 vty_out(vty
, "\n\n");
1167 json_array
= json_object_new_array();
1170 if (option
== SHOW_DISPLAY_TAGS
)
1171 route_vty_out_tag(vty
, &rm
->p
, pi
, 0,
1174 else if (option
== SHOW_DISPLAY_OVERLAY
)
1175 route_vty_out_overlay(vty
, &rm
->p
, pi
,
1178 route_vty_out(vty
, &rm
->p
, pi
, 0,
1179 SAFI_EVPN
, json_array
);
1184 if (output_count
== 0)
1185 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1187 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1188 output_count
, total_count
);
1192 DEFUN(show_ip_bgp_l2vpn_evpn
,
1193 show_ip_bgp_l2vpn_evpn_cmd
,
1194 "show [ip] bgp l2vpn evpn [json]",
1195 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1197 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1198 use_json(argc
, argv
));
1201 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1202 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1203 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1209 "Display information for a route distinguisher\n"
1210 "VPN Route Distinguisher\n" JSON_STR
)
1212 int idx_ext_community
= 0;
1214 struct prefix_rd prd
;
1216 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1218 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1220 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1223 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1224 use_json(argc
, argv
));
1227 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1228 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1229 "show [ip] bgp l2vpn evpn all tags",
1235 "Display information about all EVPN NLRIs\n"
1236 "Display BGP tags for prefixes\n")
1238 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1242 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1243 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1244 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1250 "Display information for a route distinguisher\n"
1251 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1253 int idx_ext_community
= 0;
1255 struct prefix_rd prd
;
1257 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1259 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1261 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1264 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1268 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1269 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1270 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1276 "Display information about all EVPN NLRIs\n"
1277 "Detailed information on TCP and BGP neighbor connections\n"
1278 "Neighbor to display information about\n"
1279 "Display routes learned from neighbor\n" JSON_STR
)
1285 bool uj
= use_json(argc
, argv
);
1287 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1289 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1292 json_object
*json_no
= NULL
;
1293 json_no
= json_object_new_object();
1294 json_object_string_add(json_no
, "warning",
1295 "Malformed address");
1296 vty_out(vty
, "%s\n",
1297 json_object_to_json_string(json_no
));
1298 json_object_free(json_no
);
1300 vty_out(vty
, "Malformed address: %s\n",
1301 argv
[idx_ipv4
]->arg
);
1305 peer
= peer_lookup(NULL
, &su
);
1306 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1308 json_object
*json_no
= NULL
;
1309 json_no
= json_object_new_object();
1310 json_object_string_add(
1312 "No such neighbor or address family");
1313 vty_out(vty
, "%s\n",
1314 json_object_to_json_string(json_no
));
1315 json_object_free(json_no
);
1317 vty_out(vty
, "%% No such neighbor or address family\n");
1321 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1325 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1326 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1327 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1333 "Display information for a route distinguisher\n"
1334 "VPN Route Distinguisher\n"
1335 "Detailed information on TCP and BGP neighbor connections\n"
1336 "Neighbor to display information about\n"
1337 "Display routes learned from neighbor\n" JSON_STR
)
1339 int idx_ext_community
= 0;
1344 struct prefix_rd prd
;
1345 bool uj
= use_json(argc
, argv
);
1347 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1348 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1350 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1353 json_object
*json_no
= NULL
;
1354 json_no
= json_object_new_object();
1355 json_object_string_add(json_no
, "warning",
1356 "Malformed Route Distinguisher");
1357 vty_out(vty
, "%s\n",
1358 json_object_to_json_string(json_no
));
1359 json_object_free(json_no
);
1361 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1365 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1368 json_object
*json_no
= NULL
;
1369 json_no
= json_object_new_object();
1370 json_object_string_add(json_no
, "warning",
1371 "Malformed address");
1372 vty_out(vty
, "%s\n",
1373 json_object_to_json_string(json_no
));
1374 json_object_free(json_no
);
1376 vty_out(vty
, "Malformed address: %s\n",
1377 argv
[idx_ext_community
]->arg
);
1381 peer
= peer_lookup(NULL
, &su
);
1382 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1384 json_object
*json_no
= NULL
;
1385 json_no
= json_object_new_object();
1386 json_object_string_add(
1388 "No such neighbor or address family");
1389 vty_out(vty
, "%s\n",
1390 json_object_to_json_string(json_no
));
1391 json_object_free(json_no
);
1393 vty_out(vty
, "%% No such neighbor or address family\n");
1397 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1401 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1402 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1403 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1409 "Display information about all EVPN NLRIs\n"
1410 "Detailed information on TCP and BGP neighbor connections\n"
1411 "Neighbor to display information about\n"
1412 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1418 bool uj
= use_json(argc
, argv
);
1420 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1422 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1425 json_object
*json_no
= NULL
;
1426 json_no
= json_object_new_object();
1427 json_object_string_add(json_no
, "warning",
1428 "Malformed address");
1429 vty_out(vty
, "%s\n",
1430 json_object_to_json_string(json_no
));
1431 json_object_free(json_no
);
1433 vty_out(vty
, "Malformed address: %s\n",
1434 argv
[idx_ipv4
]->arg
);
1437 peer
= peer_lookup(NULL
, &su
);
1438 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1440 json_object
*json_no
= NULL
;
1441 json_no
= json_object_new_object();
1442 json_object_string_add(
1444 "No such neighbor or address family");
1445 vty_out(vty
, "%s\n",
1446 json_object_to_json_string(json_no
));
1447 json_object_free(json_no
);
1449 vty_out(vty
, "%% No such neighbor or address family\n");
1453 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1456 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1457 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1458 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1464 "Display information for a route distinguisher\n"
1465 "VPN Route Distinguisher\n"
1466 "Detailed information on TCP and BGP neighbor connections\n"
1467 "Neighbor to display information about\n"
1468 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1470 int idx_ext_community
= 0;
1474 struct prefix_rd prd
;
1476 bool uj
= use_json(argc
, argv
);
1478 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1479 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1481 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1484 json_object
*json_no
= NULL
;
1485 json_no
= json_object_new_object();
1486 json_object_string_add(json_no
, "warning",
1487 "Malformed address");
1488 vty_out(vty
, "%s\n",
1489 json_object_to_json_string(json_no
));
1490 json_object_free(json_no
);
1492 vty_out(vty
, "Malformed address: %s\n",
1493 argv
[idx_ext_community
]->arg
);
1496 peer
= peer_lookup(NULL
, &su
);
1497 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1499 json_object
*json_no
= NULL
;
1500 json_no
= json_object_new_object();
1501 json_object_string_add(
1503 "No such neighbor or address family");
1504 vty_out(vty
, "%s\n",
1505 json_object_to_json_string(json_no
));
1506 json_object_free(json_no
);
1508 vty_out(vty
, "%% No such neighbor or address family\n");
1512 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1515 json_object
*json_no
= NULL
;
1516 json_no
= json_object_new_object();
1517 json_object_string_add(json_no
, "warning",
1518 "Malformed Route Distinguisher");
1519 vty_out(vty
, "%s\n",
1520 json_object_to_json_string(json_no
));
1521 json_object_free(json_no
);
1523 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1527 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1530 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1531 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1532 "show [ip] bgp l2vpn evpn all overlay",
1538 "Display information about all EVPN NLRIs\n"
1539 "Display BGP Overlay Information for prefixes\n")
1541 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1542 SHOW_DISPLAY_OVERLAY
,
1543 use_json(argc
, argv
));
1546 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1547 show_ip_bgp_evpn_rd_overlay_cmd
,
1548 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1554 "Display information for a route distinguisher\n"
1555 "VPN Route Distinguisher\n"
1556 "Display BGP Overlay Information for prefixes\n")
1558 int idx_ext_community
= 0;
1560 struct prefix_rd prd
;
1562 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1564 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1566 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1569 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1570 SHOW_DISPLAY_OVERLAY
,
1571 use_json(argc
, argv
));
1574 /* For testing purpose, static route of MPLS-VPN. */
1575 DEFUN(evpnrt5_network
,
1576 evpnrt5_network_cmd
,
1577 "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]",
1578 "Specify a network to announce via BGP\n"
1581 "Specify Route Distinguisher\n"
1582 "VPN Route Distinguisher\n"
1584 "Ethernet Tag Value\n"
1587 "Ethernet Segment Identifier\n"
1588 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1590 "Gateway IP ( A.B.C.D )\n"
1591 "Gateway IPv6 ( X:X::X:X )\n"
1592 "Router Mac Ext Comm\n"
1593 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1594 "Route-map to modify the attributes\n"
1595 "Name of the route map\n")
1597 int idx_ipv4_prefixlen
= 1;
1598 int idx_route_distinguisher
= 3;
1603 int idx_routermac
= 13;
1605 return bgp_static_set_safi(
1606 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1607 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1608 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1609 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1610 argv
[idx_routermac
]->arg
);
1613 /* For testing purpose, static route of MPLS-VPN. */
1614 DEFUN(no_evpnrt5_network
,
1615 no_evpnrt5_network_cmd
,
1616 "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>",
1618 "Specify a network to announce via BGP\n"
1621 "Specify Route Distinguisher\n"
1622 "VPN Route Distinguisher\n"
1624 "Ethernet Tag Value\n"
1627 "Ethernet Segment Identifier\n"
1628 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1629 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1631 int idx_ipv4_prefixlen
= 2;
1632 int idx_ext_community
= 4;
1637 return bgp_static_unset_safi(
1638 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1639 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1640 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1641 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1644 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1646 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1649 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1651 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1655 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1656 * check that this is a change.
1658 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1659 struct ecommunity
*ecomadd
)
1661 /* If the VNI is "live", we need to uninstall routes using the current
1662 * import RT(s) first before we update the import RT, and subsequently
1665 if (is_vni_live(vpn
))
1666 bgp_evpn_uninstall_routes(bgp
, vpn
);
1668 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1669 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1671 /* If the auto route-target is in use we must remove it */
1672 evpn_import_rt_delete_auto(bgp
, vpn
);
1674 /* Add new RT and rebuild the RT to VNI mapping */
1675 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1677 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1678 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1680 /* Install routes that match new import RT */
1681 if (is_vni_live(vpn
))
1682 bgp_evpn_install_routes(bgp
, vpn
);
1686 * Unconfigure Import RT(s) for a VNI (vty handler).
1688 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1689 struct ecommunity
*ecomdel
)
1691 struct listnode
*node
, *nnode
, *node_to_del
;
1692 struct ecommunity
*ecom
;
1694 /* Along the lines of "configure" except we have to reset to the
1697 if (is_vni_live(vpn
))
1698 bgp_evpn_uninstall_routes(bgp
, vpn
);
1700 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1701 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1703 /* Delete all import RTs */
1704 if (ecomdel
== NULL
) {
1705 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1706 ecommunity_free(&ecom
);
1707 list_delete_node(vpn
->import_rtl
, node
);
1711 /* Delete a specific import RT */
1715 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1716 if (ecommunity_match(ecom
, ecomdel
)) {
1717 ecommunity_free(&ecom
);
1724 list_delete_node(vpn
->import_rtl
, node_to_del
);
1727 assert(vpn
->import_rtl
);
1728 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1729 if (list_isempty(vpn
->import_rtl
)) {
1730 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1731 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1733 /* Rebuild the RT to VNI mapping */
1735 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1737 /* Install routes that match new import RT */
1738 if (is_vni_live(vpn
))
1739 bgp_evpn_install_routes(bgp
, vpn
);
1743 * Configure the Export RT for a VNI (vty handler). Caller expected to
1744 * check that this is a change. Note that only a single export RT is
1745 * allowed for a VNI and any change to configuration is implemented as
1746 * a "replace" (similar to other configuration).
1748 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1749 struct ecommunity
*ecomadd
)
1751 /* If the auto route-target is in use we must remove it */
1752 evpn_export_rt_delete_auto(bgp
, vpn
);
1754 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1755 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1757 if (is_vni_live(vpn
))
1758 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1762 * Unconfigure the Export RT for a VNI (vty handler)
1764 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1765 struct ecommunity
*ecomdel
)
1767 struct listnode
*node
, *nnode
, *node_to_del
;
1768 struct ecommunity
*ecom
;
1770 /* Delete all export RTs */
1771 if (ecomdel
== NULL
) {
1772 /* Reset to default and process all routes. */
1773 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1774 ecommunity_free(&ecom
);
1775 list_delete_node(vpn
->export_rtl
, node
);
1779 /* Delete a specific export RT */
1783 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1784 if (ecommunity_match(ecom
, ecomdel
)) {
1785 ecommunity_free(&ecom
);
1792 list_delete_node(vpn
->export_rtl
, node_to_del
);
1795 assert(vpn
->export_rtl
);
1796 if (list_isempty(vpn
->export_rtl
)) {
1797 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1798 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1801 if (is_vni_live(vpn
))
1802 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1806 * Configure RD for VRF
1808 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1810 /* If we have already advertise type-5 routes with a diffrent RD, we
1811 * have to delete and withdraw them firs
1813 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1816 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1817 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1819 /* We have a new RD for VRF.
1820 * Advertise all type-5 routes again with the new RD
1822 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1826 * Unconfigure RD for VRF
1828 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1830 /* If we have already advertise type-5 routes with a diffrent RD, we
1831 * have to delete and withdraw them firs
1833 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1835 /* fall back to default RD */
1836 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1837 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1839 /* We have a new RD for VRF.
1840 * Advertise all type-5 routes again with the new RD
1842 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1846 * Configure RD for a VNI (vty handler)
1848 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1849 struct prefix_rd
*rd
)
1851 /* If the VNI is "live", we need to delete and withdraw this VNI's
1852 * local routes with the prior RD first. Then, after updating RD,
1853 * need to re-advertise.
1855 if (is_vni_live(vpn
))
1856 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1859 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1860 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1862 if (is_vni_live(vpn
))
1863 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1867 * Unconfigure RD for a VNI (vty handler)
1869 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1871 /* If the VNI is "live", we need to delete and withdraw this VNI's
1872 * local routes with the prior RD first. Then, after resetting RD
1873 * to automatic value, need to re-advertise.
1875 if (is_vni_live(vpn
))
1876 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1878 /* reset RD to default */
1879 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1881 if (is_vni_live(vpn
))
1882 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1886 * Create VNI, if not already present (VTY handler). Mark as configured.
1888 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1890 struct bgpevpn
*vpn
;
1895 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1897 /* Check if this L2VNI is already configured as L3VNI */
1898 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
1901 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
1906 /* tenant vrf will be updated when we get local_vni_add from
1909 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1913 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1919 /* Mark as configured. */
1920 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1925 * Delete VNI. If VNI does not exist in the system (i.e., just
1926 * configuration), all that is needed is to free it. Otherwise,
1927 * any parameters configured for the VNI need to be reset (with
1928 * appropriate action) and the VNI marked as unconfigured; the
1929 * VNI will continue to exist, purely as a "learnt" entity.
1931 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1933 assert(bgp
->vnihash
);
1935 if (!is_vni_live(vpn
)) {
1936 bgp_evpn_free(bgp
, vpn
);
1940 /* We need to take the unconfigure action for each parameter of this VNI
1941 * that is configured. Some optimization is possible, but not worth the
1942 * additional code for an operation that should be pretty rare.
1944 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1946 /* First, deal with the export side - RD and export RT changes. */
1947 if (is_rd_configured(vpn
))
1948 evpn_unconfigure_rd(bgp
, vpn
);
1949 if (is_export_rt_configured(vpn
))
1950 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1952 /* Next, deal with the import side. */
1953 if (is_import_rt_configured(vpn
))
1954 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1960 * Display import RT mapping to VRFs (vty handler)
1961 * bgp_evpn: evpn bgp instance
1963 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
1971 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
1972 (void (*)(struct hash_bucket
*,
1973 void *))show_vrf_import_rt_entry
,
1978 * Display import RT mapping to VNIs (vty handler)
1980 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1989 bgp
->import_rt_hash
,
1990 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
1995 * Display EVPN routes for all VNIs - vty handler.
1997 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1998 struct in_addr vtep_ip
, json_object
*json
)
2001 struct vni_walk_ctx wctx
;
2003 num_vnis
= hashcount(bgp
->vnihash
);
2006 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2009 wctx
.vtep_ip
= vtep_ip
;
2011 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2012 void *))show_vni_routes_hash
,
2017 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2019 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2020 vni_t vni
, struct in_addr orig_ip
,
2023 struct bgpevpn
*vpn
;
2024 struct prefix_evpn p
;
2025 struct bgp_node
*rn
;
2026 struct bgp_path_info
*pi
;
2027 uint32_t path_cnt
= 0;
2030 json_object
*json_paths
= NULL
;
2036 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2038 vty_out(vty
, "VNI not found\n");
2042 /* See if route exists. */
2043 build_evpn_type3_prefix(&p
, orig_ip
);
2044 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2045 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2047 vty_out(vty
, "%% Network not in table\n");
2052 json_paths
= json_object_new_array();
2054 /* Prefix and num paths displayed once per prefix. */
2055 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2057 /* Display each path for this prefix. */
2058 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2059 json_object
*json_path
= NULL
;
2062 json_path
= json_object_new_array();
2064 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2068 json_object_array_add(json_paths
, json_path
);
2075 json_object_object_add(json
, "paths", json_paths
);
2077 json_object_int_add(json
, "numPaths", path_cnt
);
2079 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2085 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2086 * By definition, only matching type-2 route will be displayed.
2088 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2089 vni_t vni
, struct ethaddr
*mac
,
2090 struct ipaddr
*ip
, json_object
*json
)
2092 struct bgpevpn
*vpn
;
2093 struct prefix_evpn p
;
2094 struct bgp_node
*rn
;
2095 struct bgp_path_info
*pi
;
2096 uint32_t path_cnt
= 0;
2099 json_object
*json_paths
= NULL
;
2105 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2108 vty_out(vty
, "VNI not found\n");
2112 /* See if route exists. Look for both non-sticky and sticky. */
2113 build_evpn_type2_prefix(&p
, mac
, ip
);
2114 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2115 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2117 vty_out(vty
, "%% Network not in table\n");
2122 json_paths
= json_object_new_array();
2124 /* Prefix and num paths displayed once per prefix. */
2125 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2127 /* Display each path for this prefix. */
2128 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2129 json_object
*json_path
= NULL
;
2132 json_path
= json_object_new_array();
2134 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2138 json_object_array_add(json_paths
, json_path
);
2145 json_object_object_add(json
, "paths", json_paths
);
2147 json_object_int_add(json
, "numPaths", path_cnt
);
2149 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2154 /* Disaplay EVPN routes for a ESI - VTY handler */
2155 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2156 esi_t
*esi
, json_object
*json
)
2158 struct evpnes
*es
= NULL
;
2161 es
= bgp_evpn_lookup_es(bgp
, esi
);
2164 vty_out(vty
, "ESI not found\n");
2168 show_esi_routes(bgp
, es
, vty
, json
);
2172 * Display EVPN routes for a VNI - vty handler.
2173 * If 'type' is non-zero, only routes matching that type are shown.
2174 * If the vtep_ip is non zero, only routes behind that vtep are shown
2176 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2177 int type
, struct in_addr vtep_ip
,
2180 struct bgpevpn
*vpn
;
2183 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2186 vty_out(vty
, "VNI not found\n");
2190 /* Walk this VNI's route table and display appropriate routes. */
2191 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
2195 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2196 * IP (vty handler). By definition, only matching type-2 route will be
2199 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2200 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2201 struct ipaddr
*ip
, json_object
*json
)
2203 struct prefix_evpn p
;
2204 struct bgp_node
*rn
;
2205 struct bgp_path_info
*pi
;
2208 uint32_t path_cnt
= 0;
2209 json_object
*json_paths
= NULL
;
2210 char prefix_str
[BUFSIZ
];
2215 /* See if route exists. Look for both non-sticky and sticky. */
2216 build_evpn_type2_prefix(&p
, mac
, ip
);
2217 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2218 (struct prefix
*)&p
, prd
);
2219 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2221 vty_out(vty
, "%% Network not in table\n");
2225 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2226 sizeof(prefix_str
));
2228 /* Prefix and num paths displayed once per prefix. */
2229 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2232 json_paths
= json_object_new_array();
2234 /* Display each path for this prefix. */
2235 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2236 json_object
*json_path
= NULL
;
2239 json_path
= json_object_new_array();
2241 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2245 json_object_array_add(json_paths
, json_path
);
2250 if (json
&& path_cnt
) {
2252 json_object_object_add(json
, prefix_str
, json_paths
);
2253 json_object_int_add(json
, "numPaths", path_cnt
);
2255 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2261 * Display BGP EVPN routing table -- for specific RD (vty handler)
2262 * If 'type' is non-zero, only routes matching that type are shown.
2264 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2265 struct prefix_rd
*prd
, int type
,
2268 struct bgp_node
*rd_rn
;
2269 struct bgp_table
*table
;
2270 struct bgp_node
*rn
;
2271 struct bgp_path_info
*pi
;
2275 uint32_t prefix_cnt
, path_cnt
;
2276 char rd_str
[RD_ADDRSTRLEN
];
2277 json_object
*json_rd
= NULL
;
2278 int add_rd_to_json
= 0;
2282 prefix_cnt
= path_cnt
= 0;
2284 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2286 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2290 table
= bgp_node_get_bgp_table_info(rd_rn
);
2295 json_rd
= json_object_new_object();
2296 json_object_string_add(json_rd
, "rd", rd_str
);
2299 /* Display all prefixes with this RD. */
2300 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2301 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2302 json_object
*json_prefix
= NULL
;
2303 json_object
*json_paths
= NULL
;
2304 char prefix_str
[BUFSIZ
];
2305 int add_prefix_to_json
= 0;
2307 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2308 sizeof(prefix_str
));
2310 if (type
&& evp
->prefix
.route_type
!= type
)
2314 json_prefix
= json_object_new_object();
2316 pi
= bgp_node_get_bgp_path_info(rn
);
2318 /* RD header and legend - once overall. */
2319 if (rd_header
&& !json
) {
2321 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2323 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2325 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2329 /* Prefix and num paths displayed once per prefix. */
2330 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2337 json_paths
= json_object_new_array();
2339 /* Display each path for this prefix. */
2340 for (; pi
; pi
= pi
->next
) {
2341 json_object
*json_path
= NULL
;
2344 json_path
= json_object_new_array();
2346 route_vty_out_detail(vty
, bgp
, &rn
->p
, pi
, afi
, safi
,
2350 json_object_array_add(json_paths
, json_path
);
2353 add_prefix_to_json
= 1;
2357 if (json
&& add_prefix_to_json
) {
2358 json_object_object_add(json_prefix
, "paths",
2360 json_object_object_add(json_rd
, prefix_str
,
2365 if (json
&& add_rd_to_json
)
2366 json_object_object_add(json
, rd_str
, json_rd
);
2369 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2370 json_object_int_add(json
, "numPaths", path_cnt
);
2372 if (prefix_cnt
== 0)
2373 vty_out(vty
, "No prefixes exist with this RD%s\n",
2374 type
? " (of requested type)" : "");
2377 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2378 prefix_cnt
, path_cnt
,
2379 type
? " (of requested type)" : "");
2384 * Display BGP EVPN routing table - all routes (vty handler).
2385 * If 'type' is non-zero, only routes matching that type are shown.
2387 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2390 struct bgp_node
*rd_rn
;
2391 struct bgp_table
*table
;
2392 struct bgp_node
*rn
;
2393 struct bgp_path_info
*pi
;
2398 uint32_t prefix_cnt
, path_cnt
;
2402 prefix_cnt
= path_cnt
= 0;
2404 /* EVPN routing table is a 2-level table with the first level being
2407 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2408 rd_rn
= bgp_route_next(rd_rn
)) {
2409 char rd_str
[RD_ADDRSTRLEN
];
2410 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2411 int add_rd_to_json
= 0;
2414 table
= bgp_node_get_bgp_table_info(rd_rn
);
2418 tbl_ver
= table
->version
;
2419 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2423 json_rd
= json_object_new_object();
2424 json_object_string_add(json_rd
, "rd", rd_str
);
2429 /* Display all prefixes for an RD */
2430 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2431 json_object
*json_prefix
=
2432 NULL
; /* contains prefix under a RD */
2433 json_object
*json_paths
=
2434 NULL
; /* array of paths under a prefix*/
2435 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2436 char prefix_str
[BUFSIZ
];
2437 int add_prefix_to_json
= 0;
2439 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2440 prefix_str
, sizeof(prefix_str
));
2442 if (type
&& evp
->prefix
.route_type
!= type
)
2445 pi
= bgp_node_get_bgp_path_info(rn
);
2447 /* Overall header/legend displayed once. */
2449 bgp_evpn_show_route_header(vty
, bgp
,
2455 /* RD header - per RD. */
2457 bgp_evpn_show_route_rd_header(
2466 json_prefix
= json_object_new_object();
2467 json_paths
= json_object_new_array();
2468 json_object_string_add(json_prefix
, "prefix",
2470 json_object_int_add(json_prefix
, "prefixLen",
2474 /* For EVPN, the prefix is displayed for each path (to
2476 * with code that already exists).
2478 for (; pi
; pi
= pi
->next
) {
2479 json_object
*json_path
= NULL
;
2481 add_prefix_to_json
= 1;
2485 json_path
= json_object_new_array();
2487 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
2491 json_object_array_add(json_paths
,
2495 if (json
&& add_prefix_to_json
) {
2496 json_object_object_add(json_prefix
, "paths",
2498 json_object_object_add(json_rd
, prefix_str
,
2503 if (json
&& add_rd_to_json
)
2504 json_object_object_add(json
, rd_str
, json_rd
);
2508 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2509 json_object_int_add(json
, "numPaths", path_cnt
);
2511 if (prefix_cnt
== 0) {
2512 vty_out(vty
, "No EVPN prefixes %sexist\n",
2513 type
? "(of requested type) " : "");
2515 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2516 prefix_cnt
, path_cnt
,
2517 type
? " (of requested type)" : "");
2522 /* Display specific ES */
2523 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2526 struct evpnes
*es
= NULL
;
2528 es
= bgp_evpn_lookup_es(bgp
, esi
);
2530 display_es(vty
, es
, json
);
2533 vty_out(vty
, "{}\n");
2535 vty_out(vty
, "ESI not found\n");
2541 /* Display all ESs */
2542 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2548 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2549 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2554 hash_iterate(bgp
->esihash
,
2555 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2560 * Display specified VNI (vty handler)
2562 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2566 struct bgpevpn
*vpn
;
2568 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2571 display_vni(vty
, vpn
, json
);
2573 struct bgp
*bgp_temp
;
2574 struct listnode
*node
= NULL
;
2576 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2577 if (bgp_temp
->l3vni
== vni
) {
2579 display_l3vni(vty
, bgp_temp
, json
);
2586 vty_out(vty
, "{}\n");
2588 vty_out(vty
, "VNI not found\n");
2595 * Display a VNI (upon user query).
2597 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2601 struct bgp
*bgp_temp
= NULL
;
2602 struct listnode
*node
;
2606 vty_out(vty
, "Flags: * - Kernel\n");
2607 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2608 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2611 /* print all L2 VNIS */
2614 hash_iterate(bgp
->vnihash
,
2615 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2618 /* print all L3 VNIs */
2619 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2620 show_l3vni_entry(vty
, bgp_temp
, json
);
2624 * evpn - enable advertisement of svi MAC-IP
2626 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2630 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2632 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2635 bgp
->evpn_info
->advertise_svi_macip
= set
;
2636 bgp_zebra_advertise_svi_macip(bgp
,
2637 bgp
->evpn_info
->advertise_svi_macip
, 0);
2639 if (set
&& vpn
->advertise_svi_macip
)
2641 else if (!set
&& !vpn
->advertise_svi_macip
)
2644 vpn
->advertise_svi_macip
= set
;
2645 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2651 * evpn - enable advertisement of default g/w
2653 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2656 if (bgp
->advertise_gw_macip
)
2659 bgp
->advertise_gw_macip
= 1;
2660 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2662 if (vpn
->advertise_gw_macip
)
2665 vpn
->advertise_gw_macip
= 1;
2666 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2673 * evpn - disable advertisement of default g/w
2675 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2676 struct bgpevpn
*vpn
)
2679 if (!bgp
->advertise_gw_macip
)
2682 bgp
->advertise_gw_macip
= 0;
2683 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2685 if (!vpn
->advertise_gw_macip
)
2688 vpn
->advertise_gw_macip
= 0;
2689 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2696 * evpn - enable advertisement of default g/w
2698 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
2699 afi_t afi
, bool add
)
2701 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
2704 /* bail if we are already advertising default route */
2705 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2709 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2710 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2711 else if (afi
== AFI_IP6
)
2712 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2713 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2715 /* bail out if we havent advertised the default route */
2716 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
2719 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2720 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
2721 else if (afi
== AFI_IP6
)
2722 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
2723 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
2726 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
2730 * evpn - enable advertisement of default g/w
2732 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
2733 struct bgpevpn
*vpn
)
2735 if (vpn
->advertise_subnet
)
2738 vpn
->advertise_subnet
= 1;
2739 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2743 * evpn - disable advertisement of default g/w
2745 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2747 if (!vpn
->advertise_subnet
)
2750 vpn
->advertise_subnet
= 0;
2751 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2755 * EVPN (VNI advertisement) enabled. Register with zebra.
2757 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2759 bgp
->advertise_all_vni
= 1;
2761 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2765 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2766 * cache, EVPN routes (delete and withdraw from peers).
2768 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2770 bgp
->advertise_all_vni
= 0;
2771 bgp_set_evpn(bgp_get_default());
2772 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2773 bgp_evpn_cleanup_on_disable(bgp
);
2777 * EVPN - use RFC8365 to auto-derive RT
2779 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
2781 bgp
->advertise_autort_rfc8365
= 1;
2782 bgp_evpn_handle_autort_change(bgp
);
2786 * EVPN - don't use RFC8365 to auto-derive RT
2788 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
2790 bgp
->advertise_autort_rfc8365
= 0;
2791 bgp_evpn_handle_autort_change(bgp
);
2794 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2796 char buf1
[RD_ADDRSTRLEN
];
2798 struct listnode
*node
, *nnode
;
2799 struct ecommunity
*ecom
;
2801 if (is_vni_configured(vpn
)) {
2802 vty_out(vty
, " vni %d\n", vpn
->vni
);
2803 if (is_rd_configured(vpn
))
2804 vty_out(vty
, " rd %s\n",
2805 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2807 if (is_import_rt_configured(vpn
)) {
2808 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2810 ecom_str
= ecommunity_ecom2str(
2811 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2812 vty_out(vty
, " route-target import %s\n",
2814 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2818 if (is_export_rt_configured(vpn
)) {
2819 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2821 ecom_str
= ecommunity_ecom2str(
2822 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2823 vty_out(vty
, " route-target export %s\n",
2825 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2829 if (vpn
->advertise_gw_macip
)
2830 vty_out(vty
, " advertise-default-gw\n");
2832 if (vpn
->advertise_svi_macip
)
2833 vty_out(vty
, " advertise-svi-ip\n");
2835 if (vpn
->advertise_subnet
)
2836 vty_out(vty
, " advertise-subnet\n");
2838 vty_out(vty
, " exit-vni\n");
2842 #ifndef VTYSH_EXTRACT_PL
2843 #include "bgpd/bgp_evpn_vty_clippy.c"
2846 DEFPY(bgp_evpn_flood_control
,
2847 bgp_evpn_flood_control_cmd
,
2848 "[no$no] flooding <disable$disable|head-end-replication$her>",
2850 "Specify handling for BUM packets\n"
2851 "Do not flood any BUM packets\n"
2852 "Flood BUM packets using head-end replication\n")
2854 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2855 enum vxlan_flood_control flood_ctrl
;
2861 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
2863 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
2867 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
2870 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
2871 bgp_evpn_flood_control_change(bgp
);
2876 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2877 bgp_evpn_advertise_default_gw_vni_cmd
,
2878 "advertise-default-gw",
2879 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2881 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2882 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2887 evpn_set_advertise_default_gw(bgp
, vpn
);
2892 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2893 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2894 "no advertise-default-gw",
2896 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2898 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2899 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2904 evpn_unset_advertise_default_gw(bgp
, vpn
);
2910 DEFUN (bgp_evpn_advertise_default_gw
,
2911 bgp_evpn_advertise_default_gw_cmd
,
2912 "advertise-default-gw",
2913 "Advertise All default g/w mac-ip routes in EVPN\n")
2915 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2920 if (!bgp
->advertise_all_vni
) {
2922 "This command is only supported under the EVPN VRF\n");
2926 evpn_set_advertise_default_gw(bgp
, NULL
);
2931 DEFUN (no_bgp_evpn_advertise_default_gw
,
2932 no_bgp_evpn_advertise_default_gw_cmd
,
2933 "no advertise-default-gw",
2935 "Withdraw All default g/w mac-ip routes from EVPN\n")
2937 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2942 if (!bgp
->advertise_all_vni
) {
2944 "This command is only supported under the EVPN VRF\n");
2948 evpn_unset_advertise_default_gw(bgp
, NULL
);
2953 DEFUN (bgp_evpn_advertise_all_vni
,
2954 bgp_evpn_advertise_all_vni_cmd
,
2955 "advertise-all-vni",
2956 "Advertise All local VNIs\n")
2958 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2959 struct bgp
*bgp_evpn
= NULL
;
2964 bgp_evpn
= bgp_get_evpn();
2965 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
2966 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
2968 return CMD_WARNING_CONFIG_FAILED
;
2971 evpn_set_advertise_all_vni(bgp
);
2975 DEFUN (no_bgp_evpn_advertise_all_vni
,
2976 no_bgp_evpn_advertise_all_vni_cmd
,
2977 "no advertise-all-vni",
2979 "Advertise All local VNIs\n")
2981 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2985 evpn_unset_advertise_all_vni(bgp
);
2989 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
2990 bgp_evpn_advertise_autort_rfc8365_cmd
,
2991 "autort rfc8365-compatible",
2992 "Auto-derivation of RT\n"
2993 "Auto-derivation of RT using RFC8365\n")
2995 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2999 evpn_set_advertise_autort_rfc8365(bgp
);
3003 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3004 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3005 "no autort rfc8365-compatible",
3007 "Auto-derivation of RT\n"
3008 "Auto-derivation of RT using RFC8365\n")
3010 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3014 evpn_unset_advertise_autort_rfc8365(bgp
);
3018 DEFUN (bgp_evpn_default_originate
,
3019 bgp_evpn_default_originate_cmd
,
3020 "default-originate <ipv4 | ipv6>",
3021 "originate a default route\n"
3022 "ipv4 address family\n"
3023 "ipv6 address family\n")
3027 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3031 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3032 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3036 DEFUN (no_bgp_evpn_default_originate
,
3037 no_bgp_evpn_default_originate_cmd
,
3038 "no default-originate <ipv4 | ipv6>",
3040 "withdraw a default route\n"
3041 "ipv4 address family\n"
3042 "ipv6 address family\n")
3046 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3050 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3051 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3055 DEFPY (dup_addr_detection
,
3056 dup_addr_detection_cmd
,
3057 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3058 "Duplicate address detection\n"
3059 "Max allowed moves before address detected as duplicate\n"
3060 "Num of max allowed moves (2-1000) default 5\n"
3061 "Duplicate address detection time\n"
3062 "Time in seconds (2-1800) default 180\n")
3064 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3069 if (!bgp_vrf
->advertise_all_vni
) {
3071 "This command is only supported under the EVPN VRF\n");
3075 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3078 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3080 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3082 bgp_zebra_dup_addr_detection(bgp_vrf
);
3087 DEFPY (dup_addr_detection_auto_recovery
,
3088 dup_addr_detection_auto_recovery_cmd
,
3089 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3090 "Duplicate address detection\n"
3091 "Duplicate address detection freeze\n"
3092 "Duplicate address detection permanent freeze\n"
3093 "Duplicate address detection freeze time (30-3600)\n")
3095 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3096 uint32_t freeze_time
= freeze_time_val
;
3101 if (!bgp_vrf
->advertise_all_vni
) {
3103 "This command is only supported under the EVPN VRF\n");
3107 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3108 bgp_vrf
->evpn_info
->dad_freeze
= true;
3109 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3111 bgp_zebra_dup_addr_detection(bgp_vrf
);
3116 DEFPY (no_dup_addr_detection
,
3117 no_dup_addr_detection_cmd
,
3118 "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>]",
3120 "Duplicate address detection\n"
3121 "Max allowed moves before address detected as duplicate\n"
3122 "Num of max allowed moves (2-1000) default 5\n"
3123 "Duplicate address detection time\n"
3124 "Time in seconds (2-1800) default 180\n"
3125 "Duplicate address detection freeze\n"
3126 "Duplicate address detection permanent freeze\n"
3127 "Duplicate address detection freeze time (30-3600)\n")
3129 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3130 uint32_t max_moves
= (uint32_t)max_moves_val
;
3131 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3136 if (!bgp_vrf
->advertise_all_vni
) {
3138 "This command is only supported under the EVPN VRF\n");
3143 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3145 /* Reset all parameters to default. */
3146 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3147 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3148 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3149 bgp_vrf
->evpn_info
->dad_freeze
= false;
3150 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3153 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3155 "%% Value does not match with config\n");
3158 bgp_vrf
->evpn_info
->dad_max_moves
=
3159 EVPN_DAD_DEFAULT_MAX_MOVES
;
3163 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3165 "%% Value does not match with config\n");
3168 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3172 if (bgp_vrf
->evpn_info
->dad_freeze_time
3175 "%% Value does not match with config\n");
3178 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3179 bgp_vrf
->evpn_info
->dad_freeze
= false;
3182 if (permanent_val
) {
3183 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3185 "%% Value does not match with config\n");
3188 bgp_vrf
->evpn_info
->dad_freeze
= false;
3192 bgp_zebra_dup_addr_detection(bgp_vrf
);
3197 DEFPY(bgp_evpn_advertise_svi_ip
,
3198 bgp_evpn_advertise_svi_ip_cmd
,
3199 "[no$no] advertise-svi-ip",
3201 "Advertise svi mac-ip routes in EVPN\n")
3203 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3208 if (!bgp
->advertise_all_vni
) {
3210 "This command is only supported under EVPN VRF\n");
3215 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3217 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3222 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3223 bgp_evpn_advertise_svi_ip_vni_cmd
,
3224 "[no$no] advertise-svi-ip",
3226 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3228 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3229 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3238 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3240 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3245 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3246 bgp_evpn_advertise_vni_subnet_cmd
,
3248 "Advertise the subnet corresponding to VNI\n")
3250 struct bgp
*bgp_vrf
= NULL
;
3251 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3252 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3257 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3261 evpn_set_advertise_subnet(bgp
, vpn
);
3265 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3266 no_bgp_evpn_advertise_vni_subnet_cmd
,
3267 "no advertise-subnet",
3269 "Advertise All local VNIs\n")
3271 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3272 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3277 evpn_unset_advertise_subnet(bgp
, vpn
);
3281 DEFUN (bgp_evpn_advertise_type5
,
3282 bgp_evpn_advertise_type5_cmd
,
3283 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3284 "Advertise prefix routes\n"
3287 "route-map for filtering specific routes\n"
3288 "Name of the route map\n")
3290 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3297 int rmap_changed
= 0;
3299 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3300 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3301 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3303 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3305 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3306 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3309 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3313 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3315 "%%only ipv4 or ipv6 address families are supported");
3319 if (safi
!= SAFI_UNICAST
) {
3321 "%%only ipv4 unicast or ipv6 unicast are supported");
3325 if (afi
== AFI_IP
) {
3327 /* if we are already advertising ipv4 prefix as type-5
3330 if (!rmap_changed
&&
3331 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3332 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3334 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3335 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3338 /* if we are already advertising ipv6 prefix as type-5
3341 if (!rmap_changed
&&
3342 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3343 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3345 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3346 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3350 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3351 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3352 XFREE(MTYPE_ROUTE_MAP_NAME
,
3353 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3354 route_map_counter_decrement(
3355 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3356 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3357 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3361 /* set the route-map for advertise command */
3362 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3363 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3364 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3365 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3366 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3367 route_map_counter_increment(
3368 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3371 /* advertise type-5 routes */
3372 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3376 DEFUN (no_bgp_evpn_advertise_type5
,
3377 no_bgp_evpn_advertise_type5_cmd
,
3378 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3380 "Advertise prefix routes\n"
3384 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3390 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3391 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3393 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3395 "%%only ipv4 or ipv6 address families are supported");
3399 if (safi
!= SAFI_UNICAST
) {
3401 "%%only ipv4 unicast or ipv6 unicast are supported");
3405 if (afi
== AFI_IP
) {
3407 /* if we are not advertising ipv4 prefix as type-5
3410 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3411 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3412 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3413 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3414 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3418 /* if we are not advertising ipv6 prefix as type-5
3421 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3422 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3423 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3424 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3425 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3429 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3430 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3431 XFREE(MTYPE_ROUTE_MAP_NAME
,
3432 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3433 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3434 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3441 * Display VNI information - for all or a specific VNI
3443 DEFUN(show_bgp_l2vpn_evpn_vni
,
3444 show_bgp_l2vpn_evpn_vni_cmd
,
3445 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3454 struct bgp
*bgp_evpn
;
3458 json_object
*json
= NULL
;
3459 uint32_t num_l2vnis
= 0;
3460 uint32_t num_l3vnis
= 0;
3461 uint32_t num_vnis
= 0;
3462 struct listnode
*node
= NULL
;
3463 struct bgp
*bgp_temp
= NULL
;
3465 uj
= use_json(argc
, argv
);
3467 bgp_evpn
= bgp_get_evpn();
3471 if (!argv_find(argv
, argc
, "evpn", &idx
))
3475 json
= json_object_new_object();
3477 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3479 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3481 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3482 if (bgp_temp
->l3vni
)
3485 num_vnis
= num_l2vnis
+ num_l3vnis
;
3487 json_object_string_add(json
, "advertiseGatewayMacip",
3488 bgp_evpn
->advertise_gw_macip
3491 json_object_string_add(json
, "advertiseAllVnis",
3492 is_evpn_enabled() ? "Enabled"
3494 json_object_string_add(
3496 bgp_evpn
->vxlan_flood_ctrl
3497 == VXLAN_FLOOD_HEAD_END_REPL
3498 ? "Head-end replication"
3500 json_object_int_add(json
, "numVnis", num_vnis
);
3501 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3502 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3504 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3505 bgp_evpn
->advertise_gw_macip
? "Enabled"
3507 vty_out(vty
, "Advertise SVI Macip: %s\n",
3508 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3510 vty_out(vty
, "Advertise All VNI flag: %s\n",
3511 is_evpn_enabled() ? "Enabled" : "Disabled");
3512 vty_out(vty
, "BUM flooding: %s\n",
3513 bgp_evpn
->vxlan_flood_ctrl
3514 == VXLAN_FLOOD_HEAD_END_REPL
3515 ? "Head-end replication"
3517 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3518 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3520 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3524 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3527 /* Display specific VNI */
3528 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
3529 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
3533 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3534 json
, JSON_C_TO_STRING_PRETTY
));
3535 json_object_free(json
);
3542 DEFUN(show_bgp_l2vpn_evpn_es
,
3543 show_bgp_l2vpn_evpn_es_cmd
,
3544 "show bgp l2vpn evpn es [ESI] [json]",
3549 "ethernet-Segment\n"
3550 "Ethernet-Segment Identifier\n"
3556 json_object
*json
= NULL
;
3557 struct bgp
*bgp
= NULL
;
3559 memset(&esi
, 0, sizeof(esi
));
3560 uj
= use_json(argc
, argv
);
3562 bgp
= bgp_get_evpn();
3566 if (!argv_find(argv
, argc
, "evpn", &idx
))
3569 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
3570 (!uj
&& argc
== (idx
+ 1) + 1)) {
3573 evpn_show_all_es(vty
, bgp
, json
);
3576 /* show a specific ES */
3578 /* get the ESI - ESI-ID is at argv[5] */
3579 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
3580 vty_out(vty
, "%% Malformed ESI\n");
3583 evpn_show_es(vty
, bgp
, &esi
, json
);
3587 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3588 json
, JSON_C_TO_STRING_PRETTY
));
3589 json_object_free(json
);
3596 * Display EVPN neighbor summary.
3598 DEFUN(show_bgp_l2vpn_evpn_summary
,
3599 show_bgp_l2vpn_evpn_summary_cmd
,
3600 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
3607 "Summary of BGP neighbor status\n"
3611 bool uj
= use_json(argc
, argv
);
3614 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
3615 vrf
= argv
[++idx_vrf
]->arg
;
3616 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
3620 * Display global EVPN routing table.
3622 DEFUN(show_bgp_l2vpn_evpn_route
,
3623 show_bgp_l2vpn_evpn_route_cmd
,
3624 "show bgp l2vpn evpn route [type <macip|multicast|es|prefix>] [json]",
3629 "EVPN route information\n"
3630 "Specify Route type\n"
3631 "MAC-IP (Type-2) route\n"
3632 "Multicast (Type-3) route\n"
3633 "Ethernet Segment (type-4) route \n"
3634 "Prefix (type-5 )route\n"
3641 json_object
*json
= NULL
;
3643 uj
= use_json(argc
, argv
);
3645 bgp
= bgp_get_evpn();
3650 json
= json_object_new_object();
3653 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3654 /* Specific type is requested */
3655 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3656 type
= BGP_EVPN_MAC_IP_ROUTE
;
3657 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3658 type
= BGP_EVPN_IMET_ROUTE
;
3659 else if (strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
3660 type
= BGP_EVPN_ES_ROUTE
;
3661 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3662 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3667 evpn_show_all_routes(vty
, bgp
, type
, json
);
3670 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3671 json
, JSON_C_TO_STRING_PRETTY
));
3672 json_object_free(json
);
3678 * Display global EVPN routing table for specific RD.
3680 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
3681 show_bgp_l2vpn_evpn_route_rd_cmd
,
3682 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
3687 "EVPN route information\n"
3688 "Route Distinguisher\n"
3689 "ASN:XX or A.B.C.D:XX\n"
3690 "Specify Route type\n"
3691 "MAC-IP (Type-2) route\n"
3692 "Multicast (Type-3) route\n"
3693 "Ethernet Segment route\n"
3699 struct prefix_rd prd
;
3704 json_object
*json
= NULL
;
3706 bgp
= bgp_get_evpn();
3710 /* check if we need json output */
3711 uj
= use_json(argc
, argv
);
3713 json
= json_object_new_object();
3716 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3717 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3720 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3726 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3727 /* Specific type is requested */
3728 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3729 type
= BGP_EVPN_MAC_IP_ROUTE
;
3730 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3731 type
= BGP_EVPN_IMET_ROUTE
;
3732 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3733 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3738 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3741 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3742 json
, JSON_C_TO_STRING_PRETTY
));
3743 json_object_free(json
);
3750 * Display global EVPN routing table for specific RD and MACIP.
3752 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3753 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3754 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3759 "EVPN route information\n"
3760 "Route Distinguisher\n"
3761 "ASN:XX or A.B.C.D:XX\n"
3763 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3765 "IP address (IPv4 or IPv6)\n"
3770 struct prefix_rd prd
;
3777 json_object
*json
= NULL
;
3779 memset(&mac
, 0, sizeof(struct ethaddr
));
3780 memset(&ip
, 0, sizeof(struct ipaddr
));
3782 bgp
= bgp_get_evpn();
3786 /* check if we need json output */
3787 uj
= use_json(argc
, argv
);
3789 json
= json_object_new_object();
3792 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3793 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3795 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3801 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3802 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3803 vty_out(vty
, "%% Malformed MAC address\n");
3808 /* get the ip if specified */
3809 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3810 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3811 vty_out(vty
, "%% Malformed IP address\n");
3816 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3819 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3820 json
, JSON_C_TO_STRING_PRETTY
));
3821 json_object_free(json
);
3827 /* Display per ESI routing table */
3828 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
3829 show_bgp_l2vpn_evpn_route_esi_cmd
,
3830 "show bgp l2vpn evpn route esi ESI [json]",
3835 "EVPN route information\n"
3836 "Ethernet Segment Identifier\n"
3842 struct bgp
*bgp
= NULL
;
3843 json_object
*json
= NULL
;
3845 memset(&esi
, 0, sizeof(esi
));
3846 bgp
= bgp_get_evpn();
3850 uj
= use_json(argc
, argv
);
3852 json
= json_object_new_object();
3854 /* get the ESI - ESI-ID is at argv[6] */
3855 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
3856 vty_out(vty
, "%% Malformed ESI\n");
3860 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
3863 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3864 json
, JSON_C_TO_STRING_PRETTY
));
3865 json_object_free(json
);
3873 * Display per-VNI EVPN routing table.
3875 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3876 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3881 "EVPN route information\n"
3882 "VXLAN Network Identifier\n"
3884 "Specify Route type\n"
3885 "MAC-IP (Type-2) route\n"
3886 "Multicast (Type-3) route\n"
3888 "Remote VTEP IP address\n"
3893 struct in_addr vtep_ip
;
3897 json_object
*json
= NULL
;
3899 bgp
= bgp_get_evpn();
3903 /* check if we need json output */
3904 uj
= use_json(argc
, argv
);
3906 json
= json_object_new_object();
3908 if (!argv_find(argv
, argc
, "evpn", &idx
))
3913 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3915 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3916 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3917 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3918 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3919 type
= BGP_EVPN_MAC_IP_ROUTE
;
3920 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3921 type
= BGP_EVPN_IMET_ROUTE
;
3924 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3925 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3926 vty_out(vty
, "%% Malformed VTEP IP address\n");
3933 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3936 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3937 json
, JSON_C_TO_STRING_PRETTY
));
3938 json_object_free(json
);
3945 * Display per-VNI EVPN routing table for specific MACIP.
3947 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3948 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3949 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
3954 "EVPN route information\n"
3955 "VXLAN Network Identifier\n"
3958 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3960 "IP address (IPv4 or IPv6)\n"
3969 json_object
*json
= NULL
;
3971 bgp
= bgp_get_evpn();
3975 /* check if we need json output */
3976 uj
= use_json(argc
, argv
);
3978 json
= json_object_new_object();
3980 if (!argv_find(argv
, argc
, "evpn", &idx
))
3984 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3987 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3988 vty_out(vty
, "%% Malformed MAC address\n");
3993 memset(&ip
, 0, sizeof(ip
));
3994 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3996 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3997 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3998 vty_out(vty
, "%% Malformed IP address\n");
4003 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4006 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4007 json
, JSON_C_TO_STRING_PRETTY
));
4008 json_object_free(json
);
4015 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4017 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4018 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4019 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4024 "EVPN route information\n"
4025 "VXLAN Network Identifier\n"
4027 "Multicast (Type-3) route\n"
4028 "Originating Router IP address\n"
4034 struct in_addr orig_ip
;
4037 json_object
*json
= NULL
;
4039 bgp
= bgp_get_evpn();
4043 /* check if we need json output */
4044 uj
= use_json(argc
, argv
);
4046 json
= json_object_new_object();
4048 if (!argv_find(argv
, argc
, "evpn", &idx
))
4052 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4055 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4057 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4061 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4064 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4065 json
, JSON_C_TO_STRING_PRETTY
));
4066 json_object_free(json
);
4073 * Display per-VNI EVPN routing table - for all VNIs.
4075 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4076 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4077 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
4082 "EVPN route information\n"
4083 "VXLAN Network Identifier\n"
4086 "Remote VTEP IP address\n"
4090 struct in_addr vtep_ip
;
4093 json_object
*json
= NULL
;
4095 bgp
= bgp_get_evpn();
4099 /* check if we need json output */
4100 uj
= use_json(argc
, argv
);
4102 json
= json_object_new_object();
4104 if (!argv_find(argv
, argc
, "evpn", &idx
))
4108 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
4109 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
4110 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4111 vty_out(vty
, "%% Malformed VTEP IP address\n");
4116 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
4119 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4120 json
, JSON_C_TO_STRING_PRETTY
));
4121 json_object_free(json
);
4128 * Display EVPN import route-target hash table
4130 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4131 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4132 "show bgp l2vpn evpn vrf-import-rt [json]",
4137 "Show vrf import route target\n"
4141 struct bgp
*bgp_evpn
= NULL
;
4142 json_object
*json
= NULL
;
4144 bgp_evpn
= bgp_get_evpn();
4148 uj
= use_json(argc
, argv
);
4150 json
= json_object_new_object();
4152 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4155 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4156 json
, JSON_C_TO_STRING_PRETTY
));
4157 json_object_free(json
);
4164 * Display EVPN import route-target hash table
4166 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4167 show_bgp_l2vpn_evpn_import_rt_cmd
,
4168 "show bgp l2vpn evpn import-rt [json]",
4173 "Show import route target\n"
4178 json_object
*json
= NULL
;
4180 bgp
= bgp_get_evpn();
4184 uj
= use_json(argc
, argv
);
4186 json
= json_object_new_object();
4188 evpn_show_import_rts(vty
, bgp
, json
);
4191 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4192 json
, JSON_C_TO_STRING_PRETTY
));
4193 json_object_free(json
);
4199 DEFUN(test_adv_evpn_type4_route
,
4200 test_adv_evpn_type4_route_cmd
,
4202 "Advertise EVPN ES route\n"
4203 "Ethernet-segment\n"
4204 "Ethernet-Segment Identifier\n")
4209 struct ipaddr vtep_ip
;
4211 bgp
= bgp_get_evpn();
4213 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4217 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4218 vty_out(vty
, "%%Malformed ESI\n");
4222 vtep_ip
.ipa_type
= IPADDR_V4
;
4223 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4225 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4227 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4233 DEFUN(test_withdraw_evpn_type4_route
,
4234 test_withdraw_evpn_type4_route_cmd
,
4236 "Advertise EVPN ES route\n"
4237 "Ethernet-segment\n"
4238 "Ethernet-Segment Identifier\n")
4243 struct ipaddr vtep_ip
;
4245 bgp
= bgp_get_evpn();
4247 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4251 if (!bgp
->peer_self
) {
4252 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4256 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4257 vty_out(vty
, "%%Malformed ESI\n");
4261 vtep_ip
.ipa_type
= IPADDR_V4
;
4262 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4263 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4265 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4271 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4272 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4276 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4277 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4278 "Summary of BGP neighbor status\n" JSON_STR
)
4280 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4281 "show bgp evpn route [type <macip|multicast>]",
4282 SHOW_STR BGP_STR EVPN_HELP_STR
4283 "EVPN route information\n"
4284 "Specify Route type\n"
4285 "MAC-IP (Type-2) route\n"
4286 "Multicast (Type-3) route\n")
4289 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4290 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4291 SHOW_STR BGP_STR EVPN_HELP_STR
4292 "EVPN route information\n"
4293 "Route Distinguisher\n"
4294 "ASN:XX or A.B.C.D:XX\n"
4295 "Specify Route type\n"
4296 "MAC-IP (Type-2) route\n"
4297 "Multicast (Type-3) route\n")
4300 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4301 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4302 SHOW_STR BGP_STR EVPN_HELP_STR
4303 "EVPN route information\n"
4304 "Route Distinguisher\n"
4305 "ASN:XX or A.B.C.D:XX\n"
4307 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4309 "IP address (IPv4 or IPv6)\n")
4312 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4313 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4314 SHOW_STR BGP_STR EVPN_HELP_STR
4315 "EVPN route information\n"
4316 "VXLAN Network Identifier\n"
4318 "Specify Route type\n"
4319 "MAC-IP (Type-2) route\n"
4320 "Multicast (Type-3) route\n"
4322 "Remote VTEP IP address\n")
4324 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4325 show_bgp_evpn_route_vni_macip_cmd
,
4326 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4327 SHOW_STR BGP_STR EVPN_HELP_STR
4328 "EVPN route information\n"
4329 "VXLAN Network Identifier\n"
4332 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4334 "IP address (IPv4 or IPv6)\n")
4336 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4337 show_bgp_evpn_route_vni_multicast_cmd
,
4338 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4339 SHOW_STR BGP_STR EVPN_HELP_STR
4340 "EVPN route information\n"
4341 "VXLAN Network Identifier\n"
4343 "Multicast (Type-3) route\n"
4344 "Originating Router IP address\n")
4346 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4347 "show bgp evpn route vni all [vtep A.B.C.D]",
4348 SHOW_STR BGP_STR EVPN_HELP_STR
4349 "EVPN route information\n"
4350 "VXLAN Network Identifier\n"
4353 "Remote VTEP IP address\n")
4355 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4356 "show bgp evpn import-rt",
4357 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4359 DEFUN_NOSH (bgp_evpn_vni
,
4361 "vni " CMD_VNI_RANGE
,
4362 "VXLAN Network Identifier\n"
4366 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4367 struct bgpevpn
*vpn
;
4372 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4374 /* Create VNI, or mark as configured. */
4375 vpn
= evpn_create_update_vni(bgp
, vni
);
4377 vty_out(vty
, "%% Failed to create VNI \n");
4381 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4385 DEFUN (no_bgp_evpn_vni
,
4386 no_bgp_evpn_vni_cmd
,
4387 "no vni " CMD_VNI_RANGE
,
4389 "VXLAN Network Identifier\n"
4393 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4394 struct bgpevpn
*vpn
;
4399 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4401 /* Check if we should disallow. */
4402 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4404 vty_out(vty
, "%% Specified VNI does not exist\n");
4407 if (!is_vni_configured(vpn
)) {
4408 vty_out(vty
, "%% Specified VNI is not configured\n");
4412 evpn_delete_vni(bgp
, vpn
);
4416 DEFUN_NOSH (exit_vni
,
4419 "Exit from VNI mode\n")
4421 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4422 vty
->node
= BGP_EVPN_NODE
;
4426 DEFUN (bgp_evpn_vrf_rd
,
4427 bgp_evpn_vrf_rd_cmd
,
4428 "rd ASN:NN_OR_IP-ADDRESS:NN",
4429 "Route Distinguisher\n"
4430 "ASN:XX or A.B.C.D:XX\n")
4433 struct prefix_rd prd
;
4434 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4439 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4441 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4445 /* If same as existing value, there is nothing more to do. */
4446 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4449 /* Configure or update the RD. */
4450 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4454 DEFUN (no_bgp_evpn_vrf_rd
,
4455 no_bgp_evpn_vrf_rd_cmd
,
4456 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4458 "Route Distinguisher\n"
4459 "ASN:XX or A.B.C.D:XX\n")
4462 struct prefix_rd prd
;
4463 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4468 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4470 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4474 /* Check if we should disallow. */
4475 if (!is_vrf_rd_configured(bgp_vrf
)) {
4476 vty_out(vty
, "%% RD is not configured for this VRF\n");
4480 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4482 "%% RD specified does not match configuration for this VRF\n");
4486 evpn_unconfigure_vrf_rd(bgp_vrf
);
4490 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4491 no_bgp_evpn_vrf_rd_without_val_cmd
,
4494 "Route Distinguisher\n")
4496 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4501 /* Check if we should disallow. */
4502 if (!is_vrf_rd_configured(bgp_vrf
)) {
4503 vty_out(vty
, "%% RD is not configured for this VRF\n");
4507 evpn_unconfigure_vrf_rd(bgp_vrf
);
4511 DEFUN (bgp_evpn_vni_rd
,
4512 bgp_evpn_vni_rd_cmd
,
4513 "rd ASN:NN_OR_IP-ADDRESS:NN",
4514 "Route Distinguisher\n"
4515 "ASN:XX or A.B.C.D:XX\n")
4517 struct prefix_rd prd
;
4518 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4519 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4525 if (!bgp
->advertise_all_vni
) {
4527 "This command is only supported under EVPN VRF\n");
4531 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4533 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4537 /* If same as existing value, there is nothing more to do. */
4538 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
4541 /* Configure or update the RD. */
4542 evpn_configure_rd(bgp
, vpn
, &prd
);
4546 DEFUN (no_bgp_evpn_vni_rd
,
4547 no_bgp_evpn_vni_rd_cmd
,
4548 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4550 "Route Distinguisher\n"
4551 "ASN:XX or A.B.C.D:XX\n")
4553 struct prefix_rd prd
;
4554 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4555 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4561 if (!bgp
->advertise_all_vni
) {
4563 "This command is only supported under EVPN VRF\n");
4567 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4569 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4573 /* Check if we should disallow. */
4574 if (!is_rd_configured(vpn
)) {
4575 vty_out(vty
, "%% RD is not configured for this VNI\n");
4579 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
4581 "%% RD specified does not match configuration for this VNI\n");
4585 evpn_unconfigure_rd(bgp
, vpn
);
4589 DEFUN (no_bgp_evpn_vni_rd_without_val
,
4590 no_bgp_evpn_vni_rd_without_val_cmd
,
4593 "Route Distinguisher\n")
4595 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4596 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4601 if (!bgp
->advertise_all_vni
) {
4603 "This command is only supported under EVPN VRF\n");
4607 /* Check if we should disallow. */
4608 if (!is_rd_configured(vpn
)) {
4609 vty_out(vty
, "%% RD is not configured for this VNI\n");
4613 evpn_unconfigure_rd(bgp
, vpn
);
4618 * Loop over all extended-communities in the route-target list rtl and
4619 * return 1 if we find ecomtarget
4621 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
4622 struct ecommunity
*ecomtarget
)
4624 struct listnode
*node
, *nnode
;
4625 struct ecommunity
*ecom
;
4627 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
4628 if (ecommunity_match(ecom
, ecomtarget
))
4635 /* display L3VNI related info for a VRF instance */
4636 DEFUN (show_bgp_vrf_l3vni_info
,
4637 show_bgp_vrf_l3vni_info_cmd
,
4638 "show bgp vrf VRFNAME vni [json]",
4646 char buf
[ETHER_ADDR_STRLEN
];
4647 char buf1
[INET6_ADDRSTRLEN
];
4649 const char *name
= NULL
;
4650 struct bgp
*bgp
= NULL
;
4651 struct listnode
*node
= NULL
;
4652 struct bgpevpn
*vpn
= NULL
;
4653 struct ecommunity
*ecom
= NULL
;
4654 json_object
*json
= NULL
;
4655 json_object
*json_vnis
= NULL
;
4656 json_object
*json_export_rts
= NULL
;
4657 json_object
*json_import_rts
= NULL
;
4658 bool uj
= use_json(argc
, argv
);
4661 json
= json_object_new_object();
4662 json_vnis
= json_object_new_array();
4663 json_export_rts
= json_object_new_array();
4664 json_import_rts
= json_object_new_array();
4667 name
= argv
[idx_vrf
]->arg
;
4668 bgp
= bgp_lookup_by_name(name
);
4671 vty_out(vty
, "BGP instance for VRF %s not found", name
);
4673 json_object_string_add(json
, "warning",
4674 "BGP instance not found");
4675 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
4676 json_object_free(json
);
4682 vty_out(vty
, "BGP VRF: %s\n", name
);
4683 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
4684 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
4685 vty_out(vty
, " Rmac: %s\n",
4686 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4687 vty_out(vty
, " VNI Filter: %s\n",
4688 CHECK_FLAG(bgp
->vrf_flags
,
4689 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4690 ? "prefix-routes-only"
4692 vty_out(vty
, " L2-VNI List:\n");
4694 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4695 vty_out(vty
, "%u ", vpn
->vni
);
4697 vty_out(vty
, " Export-RTs:\n");
4699 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4700 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4702 vty_out(vty
, " Import-RTs:\n");
4704 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4705 vty_out(vty
, "%s ", ecommunity_str(ecom
));
4707 vty_out(vty
, " RD: %s\n",
4708 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4710 json_object_string_add(json
, "vrf", name
);
4711 json_object_string_add(json
, "local-ip",
4712 inet_ntoa(bgp
->originator_ip
));
4713 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
4714 json_object_string_add(
4716 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
4717 json_object_string_add(
4719 CHECK_FLAG(bgp
->vrf_flags
,
4720 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
4721 ? "prefix-routes-only"
4723 /* list of l2vnis */
4724 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
4725 json_object_array_add(json_vnis
,
4726 json_object_new_int(vpn
->vni
));
4727 json_object_object_add(json
, "l2vnis", json_vnis
);
4730 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
4731 json_object_array_add(
4733 json_object_new_string(ecommunity_str(ecom
)));
4734 json_object_object_add(json
, "export-rts", json_export_rts
);
4737 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
4738 json_object_array_add(
4740 json_object_new_string(ecommunity_str(ecom
)));
4741 json_object_object_add(json
, "import-rts", json_import_rts
);
4742 json_object_string_add(
4744 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
4748 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4749 json
, JSON_C_TO_STRING_PRETTY
));
4750 json_object_free(json
);
4755 /* import/export rt for l3vni-vrf */
4756 DEFUN (bgp_evpn_vrf_rt
,
4757 bgp_evpn_vrf_rt_cmd
,
4758 "route-target <both|import|export> RT",
4760 "import and export\n"
4763 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4766 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4767 struct ecommunity
*ecomadd
= NULL
;
4772 if (!strcmp(argv
[1]->arg
, "import"))
4773 rt_type
= RT_TYPE_IMPORT
;
4774 else if (!strcmp(argv
[1]->arg
, "export"))
4775 rt_type
= RT_TYPE_EXPORT
;
4776 else if (!strcmp(argv
[1]->arg
, "both"))
4777 rt_type
= RT_TYPE_BOTH
;
4779 vty_out(vty
, "%% Invalid Route Target type\n");
4783 /* Add/update the import route-target */
4784 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4785 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4786 ECOMMUNITY_ROUTE_TARGET
, 0);
4788 vty_out(vty
, "%% Malformed Route Target list\n");
4791 ecommunity_str(ecomadd
);
4793 /* Do nothing if we already have this import route-target */
4794 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
4795 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
4798 /* Add/update the export route-target */
4799 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4800 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4801 ECOMMUNITY_ROUTE_TARGET
, 0);
4803 vty_out(vty
, "%% Malformed Route Target list\n");
4806 ecommunity_str(ecomadd
);
4808 /* Do nothing if we already have this export route-target */
4809 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
4810 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
4816 DEFUN (no_bgp_evpn_vrf_rt
,
4817 no_bgp_evpn_vrf_rt_cmd
,
4818 "no route-target <both|import|export> RT",
4821 "import and export\n"
4824 "ASN:XX or A.B.C.D:XX\n")
4826 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4827 int rt_type
, found_ecomdel
;
4828 struct ecommunity
*ecomdel
= NULL
;
4833 if (!strcmp(argv
[2]->arg
, "import"))
4834 rt_type
= RT_TYPE_IMPORT
;
4835 else if (!strcmp(argv
[2]->arg
, "export"))
4836 rt_type
= RT_TYPE_EXPORT
;
4837 else if (!strcmp(argv
[2]->arg
, "both"))
4838 rt_type
= RT_TYPE_BOTH
;
4840 vty_out(vty
, "%% Invalid Route Target type\n");
4844 if (rt_type
== RT_TYPE_IMPORT
) {
4845 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4847 "%% Import RT is not configured for this VRF\n");
4850 } else if (rt_type
== RT_TYPE_EXPORT
) {
4851 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4853 "%% Export RT is not configured for this VRF\n");
4856 } else if (rt_type
== RT_TYPE_BOTH
) {
4857 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4858 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4860 "%% Import/Export RT is not configured for this VRF\n");
4865 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4867 vty_out(vty
, "%% Malformed Route Target list\n");
4870 ecommunity_str(ecomdel
);
4872 if (rt_type
== RT_TYPE_IMPORT
) {
4873 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4876 "%% RT specified does not match configuration for this VRF\n");
4879 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4880 } else if (rt_type
== RT_TYPE_EXPORT
) {
4881 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4884 "%% RT specified does not match configuration for this VRF\n");
4887 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4888 } else if (rt_type
== RT_TYPE_BOTH
) {
4891 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4893 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4897 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4899 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4903 if (!found_ecomdel
) {
4905 "%% RT specified does not match configuration for this VRF\n");
4913 DEFUN (bgp_evpn_vni_rt
,
4914 bgp_evpn_vni_rt_cmd
,
4915 "route-target <both|import|export> RT",
4917 "import and export\n"
4920 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4922 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4923 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4925 struct ecommunity
*ecomadd
= NULL
;
4930 if (!bgp
->advertise_all_vni
) {
4932 "This command is only supported under EVPN VRF\n");
4936 if (!strcmp(argv
[1]->text
, "import"))
4937 rt_type
= RT_TYPE_IMPORT
;
4938 else if (!strcmp(argv
[1]->text
, "export"))
4939 rt_type
= RT_TYPE_EXPORT
;
4940 else if (!strcmp(argv
[1]->text
, "both"))
4941 rt_type
= RT_TYPE_BOTH
;
4943 vty_out(vty
, "%% Invalid Route Target type\n");
4947 /* Add/update the import route-target */
4948 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4949 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4950 ECOMMUNITY_ROUTE_TARGET
, 0);
4952 vty_out(vty
, "%% Malformed Route Target list\n");
4955 ecommunity_str(ecomadd
);
4957 /* Do nothing if we already have this import route-target */
4958 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4959 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4962 /* Add/update the export route-target */
4963 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4964 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4965 ECOMMUNITY_ROUTE_TARGET
, 0);
4967 vty_out(vty
, "%% Malformed Route Target list\n");
4970 ecommunity_str(ecomadd
);
4972 /* Do nothing if we already have this export route-target */
4973 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4974 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4980 DEFUN (no_bgp_evpn_vni_rt
,
4981 no_bgp_evpn_vni_rt_cmd
,
4982 "no route-target <both|import|export> RT",
4985 "import and export\n"
4988 "ASN:XX or A.B.C.D:XX\n")
4990 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4991 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4992 int rt_type
, found_ecomdel
;
4993 struct ecommunity
*ecomdel
= NULL
;
4998 if (!bgp
->advertise_all_vni
) {
5000 "This command is only supported under EVPN VRF\n");
5004 if (!strcmp(argv
[2]->text
, "import"))
5005 rt_type
= RT_TYPE_IMPORT
;
5006 else if (!strcmp(argv
[2]->text
, "export"))
5007 rt_type
= RT_TYPE_EXPORT
;
5008 else if (!strcmp(argv
[2]->text
, "both"))
5009 rt_type
= RT_TYPE_BOTH
;
5011 vty_out(vty
, "%% Invalid Route Target type\n");
5015 /* The user did "no route-target import", check to see if there are any
5016 * import route-targets configured. */
5017 if (rt_type
== RT_TYPE_IMPORT
) {
5018 if (!is_import_rt_configured(vpn
)) {
5020 "%% Import RT is not configured for this VNI\n");
5023 } else if (rt_type
== RT_TYPE_EXPORT
) {
5024 if (!is_export_rt_configured(vpn
)) {
5026 "%% Export RT is not configured for this VNI\n");
5029 } else if (rt_type
== RT_TYPE_BOTH
) {
5030 if (!is_import_rt_configured(vpn
)
5031 && !is_export_rt_configured(vpn
)) {
5033 "%% Import/Export RT is not configured for this VNI\n");
5038 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5040 vty_out(vty
, "%% Malformed Route Target list\n");
5043 ecommunity_str(ecomdel
);
5045 if (rt_type
== RT_TYPE_IMPORT
) {
5046 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5048 "%% RT specified does not match configuration for this VNI\n");
5051 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5052 } else if (rt_type
== RT_TYPE_EXPORT
) {
5053 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5055 "%% RT specified does not match configuration for this VNI\n");
5058 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5059 } else if (rt_type
== RT_TYPE_BOTH
) {
5062 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5063 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5067 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5068 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5072 if (!found_ecomdel
) {
5074 "%% RT specified does not match configuration for this VNI\n");
5082 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5083 no_bgp_evpn_vni_rt_without_val_cmd
,
5084 "no route-target <import|export>",
5090 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5091 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5097 if (!bgp
->advertise_all_vni
) {
5099 "This command is only supported under EVPN VRF\n");
5103 if (!strcmp(argv
[2]->text
, "import")) {
5104 rt_type
= RT_TYPE_IMPORT
;
5105 } else if (!strcmp(argv
[2]->text
, "export")) {
5106 rt_type
= RT_TYPE_EXPORT
;
5108 vty_out(vty
, "%% Invalid Route Target type\n");
5112 /* Check if we should disallow. */
5113 if (rt_type
== RT_TYPE_IMPORT
) {
5114 if (!is_import_rt_configured(vpn
)) {
5116 "%% Import RT is not configured for this VNI\n");
5120 if (!is_export_rt_configured(vpn
)) {
5122 "%% Export RT is not configured for this VNI\n");
5127 /* Unconfigure the RT. */
5128 if (rt_type
== RT_TYPE_IMPORT
)
5129 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5131 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5135 static int vni_cmp(const void **a
, const void **b
)
5137 const struct bgpevpn
*first
= *a
;
5138 const struct bgpevpn
*secnd
= *b
;
5140 return secnd
->vni
- first
->vni
;
5144 * Output EVPN configuration information.
5146 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5149 char buf1
[RD_ADDRSTRLEN
];
5152 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5153 struct listnode
*ln
;
5154 struct bgpevpn
*data
;
5156 list_sort(vnilist
, vni_cmp
);
5157 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5158 write_vni_config(vty
, data
);
5160 list_delete(&vnilist
);
5163 if (bgp
->advertise_all_vni
)
5164 vty_out(vty
, " advertise-all-vni\n");
5166 if (bgp
->advertise_autort_rfc8365
)
5167 vty_out(vty
, " autort rfc8365-compatible\n");
5169 if (bgp
->advertise_gw_macip
)
5170 vty_out(vty
, " advertise-default-gw\n");
5172 if (bgp
->evpn_info
->advertise_svi_macip
)
5173 vty_out(vty
, " advertise-svi-ip\n");
5175 if (!bgp
->evpn_info
->dup_addr_detect
)
5176 vty_out(vty
, " no dup-addr-detection\n");
5178 if (bgp
->evpn_info
->dad_max_moves
!=
5179 EVPN_DAD_DEFAULT_MAX_MOVES
||
5180 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5181 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5182 bgp
->evpn_info
->dad_max_moves
,
5183 bgp
->evpn_info
->dad_time
);
5185 if (bgp
->evpn_info
->dad_freeze
) {
5186 if (bgp
->evpn_info
->dad_freeze_time
)
5188 " dup-addr-detection freeze %u\n",
5189 bgp
->evpn_info
->dad_freeze_time
);
5192 " dup-addr-detection freeze permanent\n");
5195 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5196 vty_out(vty
, " flooding disable\n");
5198 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5199 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5200 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5201 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5202 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5204 vty_out(vty
, " advertise ipv4 unicast\n");
5207 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5208 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5209 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5210 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5211 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5213 vty_out(vty
, " advertise ipv6 unicast\n");
5216 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5217 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5218 vty_out(vty
, " default-originate ipv4\n");
5220 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5221 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5222 vty_out(vty
, " default-originate ipv6\n");
5224 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5225 vty_out(vty
, " rd %s\n",
5226 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5228 /* import route-target */
5229 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5231 struct listnode
*node
, *nnode
;
5232 struct ecommunity
*ecom
;
5234 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5236 ecom_str
= ecommunity_ecom2str(
5237 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5238 vty_out(vty
, " route-target import %s\n", ecom_str
);
5239 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5243 /* export route-target */
5244 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5246 struct listnode
*node
, *nnode
;
5247 struct ecommunity
*ecom
;
5249 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5251 ecom_str
= ecommunity_ecom2str(
5252 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5253 vty_out(vty
, " route-target export %s\n", ecom_str
);
5254 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5259 void bgp_ethernetvpn_init(void)
5261 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5262 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5263 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5264 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5265 install_element(VIEW_NODE
,
5266 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
5267 install_element(VIEW_NODE
,
5268 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5271 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
5274 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5275 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5276 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5277 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5278 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5279 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5280 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5281 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5282 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5283 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5284 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5285 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5286 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5287 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5288 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5289 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5290 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5291 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5292 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5293 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5296 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5297 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5299 /* "show bgp l2vpn evpn" commands. */
5300 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5301 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5302 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5303 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5304 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5305 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5306 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5307 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5308 install_element(VIEW_NODE
,
5309 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5310 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5311 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5312 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5313 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5315 /* "show bgp evpn" commands. */
5316 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5317 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5318 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5319 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5320 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5321 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5322 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5323 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5324 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5325 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5326 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5328 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5329 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5330 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5331 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5332 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5333 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5334 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5335 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5336 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5337 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5338 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5339 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5340 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5341 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5342 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5343 install_element(BGP_EVPN_VNI_NODE
,
5344 &bgp_evpn_advertise_default_gw_vni_cmd
);
5345 install_element(BGP_EVPN_VNI_NODE
,
5346 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5347 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5348 install_element(BGP_EVPN_VNI_NODE
,
5349 &no_bgp_evpn_advertise_vni_subnet_cmd
);