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
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
62 int argv_find_and_parse_oly_idx(struct cmd_token
**argv
, int argc
, int *oly_idx
,
63 enum overlay_index_type
*oly
)
65 *oly
= OVERLAY_INDEX_TYPE_NONE
;
66 if (argv_find(argv
, argc
, "gateway-ip", oly_idx
))
67 *oly
= OVERLAY_INDEX_GATEWAY_IP
;
71 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
75 uint8_t type
, sub_type
;
76 struct ecommunity_as eas
;
77 struct ecommunity_ip eip
;
78 struct listnode
*node
, *nnode
;
79 struct bgp
*tmp_bgp_vrf
= NULL
;
80 json_object
*json_rt
= NULL
;
81 json_object
*json_vrfs
= NULL
;
82 char rt_buf
[RT_ADDRSTRLEN
];
85 json_rt
= json_object_new_object();
86 json_vrfs
= json_object_new_array();
89 pnt
= (uint8_t *)&irt
->rt
.val
;
92 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
95 memset(&eas
, 0, sizeof(eas
));
97 case ECOMMUNITY_ENCODE_AS
:
98 eas
.as
= (*pnt
++ << 8);
100 ptr_get_be32(pnt
, &eas
.val
);
102 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
105 json_object_string_add(json_rt
, "rt", rt_buf
);
107 vty_out(vty
, "Route-target: %s", rt_buf
);
111 case ECOMMUNITY_ENCODE_IP
:
112 memcpy(&eip
.ip
, pnt
, 4);
114 eip
.val
= (*pnt
++ << 8);
117 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
126 case ECOMMUNITY_ENCODE_AS4
:
127 pnt
= ptr_get_be32(pnt
, &eas
.val
);
128 eas
.val
= (*pnt
++ << 8);
131 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
134 json_object_string_add(json_rt
, "rt", rt_buf
);
136 vty_out(vty
, "Route-target: %s", rt_buf
);
146 "\nList of VRFs importing routes with this route-target:\n");
149 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
151 json_object_array_add(
153 json_object_new_string(
154 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
156 vty_out(vty
, " %s\n",
157 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
161 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
162 json_object_object_add(json
, rt_buf
, json_rt
);
166 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
168 json_object
*json
= NULL
;
169 struct vty
*vty
= NULL
;
170 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
172 vty
= (struct vty
*)args
[0];
173 json
= (struct json_object
*)args
[1];
175 display_vrf_import_rt(vty
, irt
, json
);
178 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
182 uint8_t type
, sub_type
;
183 struct ecommunity_as eas
;
184 struct ecommunity_ip eip
;
185 struct listnode
*node
, *nnode
;
186 struct bgpevpn
*tmp_vpn
;
187 json_object
*json_rt
= NULL
;
188 json_object
*json_vnis
= NULL
;
189 char rt_buf
[RT_ADDRSTRLEN
];
192 json_rt
= json_object_new_object();
193 json_vnis
= json_object_new_array();
196 /* TODO: This needs to go into a function */
198 pnt
= (uint8_t *)&irt
->rt
.val
;
201 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
204 memset(&eas
, 0, sizeof(eas
));
206 case ECOMMUNITY_ENCODE_AS
:
207 eas
.as
= (*pnt
++ << 8);
209 ptr_get_be32(pnt
, &eas
.val
);
211 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
214 json_object_string_add(json_rt
, "rt", rt_buf
);
216 vty_out(vty
, "Route-target: %s", rt_buf
);
220 case ECOMMUNITY_ENCODE_IP
:
221 memcpy(&eip
.ip
, pnt
, 4);
223 eip
.val
= (*pnt
++ << 8);
226 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
229 json_object_string_add(json_rt
, "rt", rt_buf
);
231 vty_out(vty
, "Route-target: %s", rt_buf
);
235 case ECOMMUNITY_ENCODE_AS4
:
236 pnt
= ptr_get_be32(pnt
, &eas
.val
);
237 eas
.val
= (*pnt
++ << 8);
240 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
243 json_object_string_add(json_rt
, "rt", rt_buf
);
245 vty_out(vty
, "Route-target: %s", rt_buf
);
255 "\nList of VNIs importing routes with this route-target:\n");
258 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
260 json_object_array_add(
261 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
263 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
267 json_object_object_add(json_rt
, "vnis", json_vnis
);
268 json_object_object_add(json
, rt_buf
, json_rt
);
272 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
274 json_object
*json
= NULL
;
275 struct vty
*vty
= NULL
;
276 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
281 display_import_rt(vty
, irt
, json
);
286 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
287 struct bgp_dest
*rd_dest
,
288 json_object
*json
, char *rd_str
,
295 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
299 /* Decode RD type. */
300 type
= decode_rd_type(pnt
);
303 vty_out(vty
, "Route Distinguisher: ");
307 decode_rd_as(pnt
+ 2, &rd_as
);
308 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
310 json_object_string_add(json
, "rd", rd_str
);
312 vty_out(vty
, "%s\n", rd_str
);
316 decode_rd_as4(pnt
+ 2, &rd_as
);
317 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
325 decode_rd_ip(pnt
+ 2, &rd_ip
);
326 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
328 json_object_string_add(json
, "rd", rd_str
);
330 vty_out(vty
, "%s\n", rd_str
);
335 snprintf(rd_str
, len
, "Unknown");
336 json_object_string_add(json
, "rd", rd_str
);
338 snprintf(rd_str
, len
, "Unknown RD type");
339 vty_out(vty
, "%s\n", rd_str
);
345 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
346 uint64_t tbl_ver
, json_object
*json
)
349 " Network Next Hop Metric LocPrf Weight Path\n";
355 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
356 tbl_ver
, &bgp
->router_id
);
358 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
359 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
361 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
363 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
364 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
365 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
366 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
367 vty_out(vty
, "%s", ri_header
);
370 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
373 char buf1
[INET6_ADDRSTRLEN
];
375 struct listnode
*node
, *nnode
;
376 struct vrf_route_target
*l3rt
;
377 json_object
*json_import_rtl
= NULL
;
378 json_object
*json_export_rtl
= NULL
;
379 char buf2
[ETHER_ADDR_STRLEN
];
381 json_import_rtl
= json_export_rtl
= 0;
384 json_import_rtl
= json_object_new_array();
385 json_export_rtl
= json_object_new_array();
386 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
387 json_object_string_add(json
, "type", "L3");
388 json_object_string_add(json
, "inKernel", "True");
389 json_object_string_addf(json
, "rd", "%pRD", &bgp_vrf
->vrf_prd
);
390 json_object_string_addf(json
, "originatorIp", "%pI4",
391 &bgp_vrf
->originator_ip
);
392 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
393 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
394 json_object_string_add(json
, "advertisePip",
395 bgp_vrf
->evpn_info
->advertise_pip
?
396 "Enabled" : "Disabled");
397 json_object_string_addf(json
, "sysIP", "%pI4",
398 &bgp_vrf
->evpn_info
->pip_ip
);
399 json_object_string_add(json
, "sysMac",
400 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
401 buf2
, sizeof(buf2
)));
402 json_object_string_add(json
, "rmac",
403 prefix_mac2str(&bgp_vrf
->rmac
,
404 buf2
, sizeof(buf2
)));
406 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
407 vty_out(vty
, " (known to the kernel)");
410 vty_out(vty
, " Type: %s\n", "L3");
411 vty_out(vty
, " Tenant VRF: %s\n",
412 vrf_id_to_name(bgp_vrf
->vrf_id
));
413 vty_out(vty
, " RD: %pRD\n", &bgp_vrf
->vrf_prd
);
414 vty_out(vty
, " Originator IP: %pI4\n",
415 &bgp_vrf
->originator_ip
);
416 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
417 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
418 vty_out(vty
, " Advertise-pip: %s\n",
419 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
420 vty_out(vty
, " System-IP: %s\n",
421 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
422 buf1
, INET_ADDRSTRLEN
));
423 vty_out(vty
, " System-MAC: %s\n",
424 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
425 buf2
, sizeof(buf2
)));
426 vty_out(vty
, " Router-MAC: %s\n",
427 prefix_mac2str(&bgp_vrf
->rmac
,
428 buf2
, sizeof(buf2
)));
432 vty_out(vty
, " Import Route Target:\n");
434 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
435 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
436 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
439 json_object_array_add(json_import_rtl
,
440 json_object_new_string(ecom_str
));
442 vty_out(vty
, " %s\n", ecom_str
);
444 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
448 json_object_object_add(json
, "importRts", json_import_rtl
);
450 vty_out(vty
, " Export Route Target:\n");
452 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
453 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
454 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
457 json_object_array_add(json_export_rtl
,
458 json_object_new_string(ecom_str
));
460 vty_out(vty
, " %s\n", ecom_str
);
462 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
466 json_object_object_add(json
, "exportRts", json_export_rtl
);
469 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
472 struct listnode
*node
, *nnode
;
473 struct ecommunity
*ecom
;
474 json_object
*json_import_rtl
= NULL
;
475 json_object
*json_export_rtl
= NULL
;
476 struct bgp
*bgp_evpn
;
478 bgp_evpn
= bgp_get_evpn();
481 json_import_rtl
= json_object_new_array();
482 json_export_rtl
= json_object_new_array();
483 json_object_int_add(json
, "vni", vpn
->vni
);
484 json_object_string_add(json
, "type", "L2");
485 json_object_string_add(json
, "inKernel",
486 is_vni_live(vpn
) ? "True" : "False");
487 json_object_string_addf(json
, "rd", "%pRD", &vpn
->prd
);
488 json_object_string_addf(json
, "originatorIp", "%pI4",
489 &vpn
->originator_ip
);
490 json_object_string_addf(json
, "mcastGroup", "%pI4",
492 /* per vni knob is enabled -- Enabled
493 * Global knob is enabled -- Active
494 * default -- Disabled
496 if (!vpn
->advertise_gw_macip
&&
497 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
498 json_object_string_add(json
, "advertiseGatewayMacip",
500 else if (vpn
->advertise_gw_macip
)
501 json_object_string_add(json
, "advertiseGatewayMacip",
504 json_object_string_add(json
, "advertiseGatewayMacip",
506 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
507 bgp_evpn
->evpn_info
->advertise_svi_macip
)
508 json_object_string_add(json
, "advertiseSviMacIp",
510 else if (vpn
->advertise_svi_macip
)
511 json_object_string_add(json
, "advertiseSviMacIp",
514 json_object_string_add(json
, "advertiseSviMacIp",
516 json_object_string_add(
517 json
, "sviInterface",
518 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
520 vty_out(vty
, "VNI: %d", vpn
->vni
);
521 if (is_vni_live(vpn
))
522 vty_out(vty
, " (known to the kernel)");
525 vty_out(vty
, " Type: %s\n", "L2");
526 vty_out(vty
, " Tenant-Vrf: %s\n",
527 vrf_id_to_name(vpn
->tenant_vrf_id
));
528 vty_out(vty
, " RD: %pRD\n", &vpn
->prd
);
529 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
530 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
531 if (!vpn
->advertise_gw_macip
&&
532 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
533 vty_out(vty
, " Advertise-gw-macip : %s\n",
535 else if (vpn
->advertise_gw_macip
)
536 vty_out(vty
, " Advertise-gw-macip : %s\n",
539 vty_out(vty
, " Advertise-gw-macip : %s\n",
541 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
542 bgp_evpn
->evpn_info
->advertise_svi_macip
)
543 vty_out(vty
, " Advertise-svi-macip : %s\n",
545 else if (vpn
->advertise_svi_macip
)
546 vty_out(vty
, " Advertise-svi-macip : %s\n",
549 vty_out(vty
, " Advertise-svi-macip : %s\n",
551 vty_out(vty
, " SVI interface : %s\n",
552 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
556 vty_out(vty
, " Import Route Target:\n");
558 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
559 ecom_str
= ecommunity_ecom2str(ecom
,
560 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
563 json_object_array_add(json_import_rtl
,
564 json_object_new_string(ecom_str
));
566 vty_out(vty
, " %s\n", ecom_str
);
568 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
572 json_object_object_add(json
, "importRts", json_import_rtl
);
574 vty_out(vty
, " Export Route Target:\n");
576 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
577 ecom_str
= ecommunity_ecom2str(ecom
,
578 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
581 json_object_array_add(json_export_rtl
,
582 json_object_new_string(ecom_str
));
584 vty_out(vty
, " %s\n", ecom_str
);
586 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
590 json_object_object_add(json
, "exportRts", json_export_rtl
);
593 static void show_esi_routes(struct bgp
*bgp
,
594 struct bgp_evpn_es
*es
,
599 struct bgp_dest
*dest
;
600 struct bgp_path_info
*pi
;
601 uint32_t prefix_cnt
, path_cnt
;
604 prefix_cnt
= path_cnt
= 0;
606 tbl_ver
= es
->route_table
->version
;
607 for (dest
= bgp_table_top(es
->route_table
); dest
;
608 dest
= bgp_route_next(dest
)) {
609 int add_prefix_to_json
= 0;
610 json_object
*json_paths
= NULL
;
611 json_object
*json_prefix
= NULL
;
612 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
615 json_prefix
= json_object_new_object();
617 pi
= bgp_dest_get_bgp_path_info(dest
);
619 /* Overall header/legend displayed once. */
621 bgp_evpn_show_route_header(vty
, bgp
,
630 json_paths
= json_object_new_array();
632 /* For EVPN, the prefix is displayed for each path (to fit in
633 * with code that already exists).
635 for (; pi
; pi
= pi
->next
) {
636 json_object
*json_path
= NULL
;
639 json_path
= json_object_new_array();
641 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
645 json_object_array_add(json_paths
, json_path
);
648 add_prefix_to_json
= 1;
652 if (add_prefix_to_json
) {
653 json_object_string_addf(json_prefix
, "prefix",
655 json_object_int_add(json_prefix
, "prefixLen",
657 json_object_object_add(json_prefix
, "paths",
659 json_object_object_addf(json
, json_prefix
,
662 json_object_free(json_paths
);
663 json_object_free(json_prefix
);
671 json_object_int_add(json
, "numPrefix", prefix_cnt
);
672 json_object_int_add(json
, "numPaths", path_cnt
);
675 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
677 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
678 prefix_cnt
, path_cnt
);
682 /* Display all MAC-IP VNI routes linked to an ES */
683 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
684 json_object
*json
, int detail
,
688 struct bgp_path_info
*pi
;
689 int header
= detail
? 0 : 1;
691 struct listnode
*node
;
692 struct bgp_evpn_es
*es
;
693 struct bgp_path_es_info
*es_info
;
694 struct bgp
*bgp
= bgp_get_evpn();
695 json_object
*json_paths
= NULL
;
703 json_paths
= json_object_new_array();
705 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
706 struct list
*es_list
;
708 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
712 es_list
= es
->macip_global_path_list
;
714 es_list
= es
->macip_evi_path_list
;
716 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
717 json_object
*json_path
= NULL
;
722 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
725 /* Overall header/legend displayed once. */
727 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
734 json_path
= json_object_new_array();
737 route_vty_out_detail(
738 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
739 RPKI_NOT_BEING_USED
, json_path
);
741 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
745 json_object_array_add(json_paths
, json_path
);
750 json_object_object_add(json
, "paths", json_paths
);
751 json_object_int_add(json
, "numPaths", path_cnt
);
754 vty_out(vty
, "There are no MAC-IP ES paths");
756 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
761 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
762 json_object
*json
, int detail
)
764 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
767 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
768 json_object
*json
, int detail
)
770 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
773 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
774 struct vty
*vty
, struct in_addr vtep_ip
,
775 json_object
*json
, int detail
)
777 struct bgp_dest
*dest
;
778 struct bgp_path_info
*pi
;
779 struct bgp_table
*table
;
780 int header
= detail
? 0 : 1;
782 uint32_t prefix_cnt
, path_cnt
;
784 prefix_cnt
= path_cnt
= 0;
786 table
= vpn
->route_table
;
787 tbl_ver
= table
->version
;
788 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
789 const struct prefix_evpn
*evp
=
790 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
791 int add_prefix_to_json
= 0;
792 json_object
*json_paths
= NULL
;
793 json_object
*json_prefix
= NULL
;
794 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
796 if (type
&& evp
->prefix
.route_type
!= type
)
800 json_prefix
= json_object_new_object();
802 pi
= bgp_dest_get_bgp_path_info(dest
);
804 /* Overall header/legend displayed once. */
806 bgp_evpn_show_route_header(vty
, bgp
,
815 json_paths
= json_object_new_array();
817 /* For EVPN, the prefix is displayed for each path (to fit in
818 * with code that already exists).
820 for (; pi
; pi
= pi
->next
) {
821 json_object
*json_path
= NULL
;
823 if (vtep_ip
.s_addr
!= INADDR_ANY
824 && !IPV4_ADDR_SAME(&(vtep_ip
),
825 &(pi
->attr
->nexthop
)))
829 json_path
= json_object_new_array();
832 route_vty_out_detail(vty
, bgp
, dest
, pi
,
833 AFI_L2VPN
, SAFI_EVPN
,
837 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
841 json_object_array_add(json_paths
, json_path
);
844 add_prefix_to_json
= 1;
848 if (add_prefix_to_json
) {
849 json_object_string_addf(json_prefix
, "prefix",
851 json_object_int_add(json_prefix
, "prefixLen",
853 json_object_object_add(json_prefix
, "paths",
855 json_object_object_addf(json
, json_prefix
,
858 json_object_free(json_paths
);
859 json_object_free(json_prefix
);
867 json_object_int_add(json
, "numPrefix", prefix_cnt
);
868 json_object_int_add(json
, "numPaths", path_cnt
);
871 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
872 type
? "(of requested type) " : "");
874 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
875 prefix_cnt
, path_cnt
,
876 type
? " (of requested type)" : "");
881 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
883 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
884 struct vni_walk_ctx
*wctx
= arg
;
885 struct vty
*vty
= wctx
->vty
;
886 json_object
*json
= wctx
->json
;
887 json_object
*json_vni
= NULL
;
888 char vni_str
[VNI_STR_LEN
];
890 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
892 json_vni
= json_object_new_object();
893 json_object_int_add(json_vni
, "vni", vpn
->vni
);
895 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
898 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
902 json_object_object_add(json
, vni_str
, json_vni
);
905 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
908 json_object
*json_vni
= NULL
;
909 json_object
*json_import_rtl
= NULL
;
910 json_object
*json_export_rtl
= NULL
;
912 char buf2
[INET6_ADDRSTRLEN
];
915 struct listnode
*node
, *nnode
;
916 struct vrf_route_target
*l3rt
;
922 json_vni
= json_object_new_object();
923 json_import_rtl
= json_object_new_array();
924 json_export_rtl
= json_object_new_array();
927 /* if an l3vni is present in bgp it is live */
929 snprintf(buf1
, sizeof(buf1
), "*");
932 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
933 json_object_string_add(json_vni
, "type", "L3");
934 json_object_string_add(json_vni
, "inKernel", "True");
935 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
936 &bgp
->originator_ip
);
937 json_object_string_addf(json_vni
, "rd", "%pRD", &bgp
->vrf_prd
);
938 json_object_string_add(json_vni
, "advertiseGatewayMacip",
940 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
941 json_object_string_add(
942 json_vni
, "advertisePip",
943 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
944 json_object_string_addf(json_vni
, "sysIP", "%pI4",
945 &bgp
->evpn_info
->pip_ip
);
946 json_object_string_add(json_vni
, "sysMAC",
947 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
948 buf2
, sizeof(buf2
)));
949 json_object_string_add(
951 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
953 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, bgp
->l3vni
, "L3",
957 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, l3rt
)) {
958 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
959 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
962 json_object_array_add(json_import_rtl
,
963 json_object_new_string(ecom_str
));
965 if (listcount(bgp
->vrf_import_rtl
) > 1)
966 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
969 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
971 vty_out(vty
, " %-25s", rt_buf
);
974 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
976 /* If there are multiple import RTs we break here and show only
983 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
985 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, l3rt
)) {
986 ecom_str
= ecommunity_ecom2str(l3rt
->ecom
,
987 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
990 json_object_array_add(json_export_rtl
,
991 json_object_new_string(ecom_str
));
993 if (listcount(bgp
->vrf_export_rtl
) > 1)
994 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
997 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
999 vty_out(vty
, " %-25s", rt_buf
);
1002 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1004 /* If there are multiple export RTs we break here and show only
1007 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1013 char vni_str
[VNI_STR_LEN
];
1015 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1016 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1017 json_object_object_add(json
, vni_str
, json_vni
);
1023 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1027 json_object
*json_vni
= NULL
;
1028 json_object
*json_import_rtl
= NULL
;
1029 json_object
*json_export_rtl
= NULL
;
1030 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1034 struct listnode
*node
, *nnode
;
1035 struct ecommunity
*ecom
;
1036 struct bgp
*bgp_evpn
;
1041 bgp_evpn
= bgp_get_evpn();
1044 json_vni
= json_object_new_object();
1045 json_import_rtl
= json_object_new_array();
1046 json_export_rtl
= json_object_new_array();
1050 if (is_vni_live(vpn
))
1051 snprintf(buf1
, sizeof(buf1
), "*");
1054 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1055 json_object_string_add(json_vni
, "type", "L2");
1056 json_object_string_add(json_vni
, "inKernel",
1057 is_vni_live(vpn
) ? "True" : "False");
1058 json_object_string_addf(json_vni
, "rd", "%pRD", &vpn
->prd
);
1059 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1060 &vpn
->originator_ip
);
1061 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1063 /* per vni knob is enabled -- Enabled
1064 * Global knob is enabled -- Active
1065 * default -- Disabled
1067 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1068 && bgp_evpn
->advertise_gw_macip
)
1069 json_object_string_add(
1070 json_vni
, "advertiseGatewayMacip", "Active");
1071 else if (vpn
->advertise_gw_macip
)
1072 json_object_string_add(
1073 json_vni
, "advertiseGatewayMacip", "Enabled");
1075 json_object_string_add(
1076 json_vni
, "advertiseGatewayMacip", "Disabled");
1077 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1078 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1079 json_object_string_add(json_vni
, "advertiseSviMacIp",
1081 else if (vpn
->advertise_svi_macip
)
1082 json_object_string_add(json_vni
, "advertiseSviMacIp",
1085 json_object_string_add(json_vni
, "advertiseSviMacIp",
1088 vty_out(vty
, "%-1s %-10u %-4s %-21pRD", buf1
, vpn
->vni
, "L2",
1092 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1093 ecom_str
= ecommunity_ecom2str(ecom
,
1094 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1097 json_object_array_add(json_import_rtl
,
1098 json_object_new_string(ecom_str
));
1100 if (listcount(vpn
->import_rtl
) > 1)
1101 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1104 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1106 vty_out(vty
, " %-25s", rt_buf
);
1109 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1111 /* If there are multiple import RTs we break here and show only
1118 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1120 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1121 ecom_str
= ecommunity_ecom2str(ecom
,
1122 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1125 json_object_array_add(json_export_rtl
,
1126 json_object_new_string(ecom_str
));
1128 if (listcount(vpn
->export_rtl
) > 1)
1129 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1132 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1134 vty_out(vty
, " %-25s", rt_buf
);
1137 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1139 /* If there are multiple export RTs we break here and show only
1142 vty_out(vty
, "%-37s",
1143 vrf_id_to_name(vpn
->tenant_vrf_id
));
1149 char vni_str
[VNI_STR_LEN
];
1151 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1152 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1153 json_object_object_add(json
, vni_str
, json_vni
);
1159 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1160 enum bgp_show_type type
, void *output_arg
,
1161 int option
, bool use_json
)
1163 afi_t afi
= AFI_L2VPN
;
1165 struct bgp_table
*table
;
1166 struct bgp_dest
*dest
;
1167 struct bgp_dest
*rm
;
1168 struct bgp_path_info
*pi
;
1171 char rd_str
[RD_ADDRSTRLEN
];
1174 unsigned long output_count
= 0;
1175 unsigned long total_count
= 0;
1176 json_object
*json
= NULL
;
1177 json_object
*json_array
= NULL
;
1178 json_object
*json_prefix_info
= NULL
;
1180 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1182 bgp
= bgp_get_evpn();
1185 vty_out(vty
, "No BGP process is configured\n");
1187 vty_out(vty
, "{}\n");
1192 json
= json_object_new_object();
1194 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1195 dest
= bgp_route_next(dest
)) {
1197 json_object
*json_nroute
= NULL
;
1198 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1200 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1203 table
= bgp_dest_get_bgp_table_info(dest
);
1208 tbl_ver
= table
->version
;
1210 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1211 pi
= bgp_dest_get_bgp_path_info(rm
);
1216 for (; pi
; pi
= pi
->next
) {
1217 struct community
*picomm
= NULL
;
1219 picomm
= bgp_attr_get_community(pi
->attr
);
1222 if (type
== bgp_show_type_neighbor
) {
1223 struct peer
*peer
= output_arg
;
1225 if (peer_cmp(peer
, pi
->peer
) != 0)
1228 if (type
== bgp_show_type_lcommunity_exact
) {
1229 struct lcommunity
*lcom
= output_arg
;
1231 if (!bgp_attr_get_lcommunity(
1234 bgp_attr_get_lcommunity(
1239 if (type
== bgp_show_type_lcommunity
) {
1240 struct lcommunity
*lcom
= output_arg
;
1242 if (!bgp_attr_get_lcommunity(
1245 bgp_attr_get_lcommunity(
1250 if (type
== bgp_show_type_community
) {
1251 struct community
*com
= output_arg
;
1254 !community_match(picomm
, com
))
1257 if (type
== bgp_show_type_community_exact
) {
1258 struct community
*com
= output_arg
;
1261 !community_cmp(picomm
, com
))
1266 json_object_int_add(
1267 json
, "bgpTableVersion",
1269 json_object_string_addf(
1274 json_object_int_add(
1277 bgp
->default_local_pref
);
1278 json_object_int_add(
1282 if (option
== SHOW_DISPLAY_TAGS
)
1287 == SHOW_DISPLAY_OVERLAY
)
1291 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1299 json_object_new_object();
1300 bgp_evpn_show_route_rd_header(
1301 vty
, dest
, json_nroute
, rd_str
,
1305 if (use_json
&& !json_array
)
1306 json_array
= json_object_new_array();
1308 if (option
== SHOW_DISPLAY_TAGS
)
1310 vty
, bgp_dest_get_prefix(rm
),
1311 pi
, no_display
, SAFI_EVPN
,
1313 else if (option
== SHOW_DISPLAY_OVERLAY
)
1314 route_vty_out_overlay(
1315 vty
, bgp_dest_get_prefix(rm
),
1316 pi
, no_display
, json_array
);
1319 bgp_dest_get_prefix(rm
),
1320 pi
, no_display
, SAFI_EVPN
,
1328 if (use_json
&& json_array
) {
1329 const struct prefix
*p
=
1330 bgp_dest_get_prefix(rm
);
1332 json_prefix_info
= json_object_new_object();
1334 json_object_string_addf(json_prefix_info
,
1335 "prefix", "%pFX", p
);
1337 json_object_int_add(json_prefix_info
,
1338 "prefixLen", p
->prefixlen
);
1340 json_object_object_add(json_prefix_info
,
1341 "paths", json_array
);
1342 json_object_object_addf(json_nroute
,
1349 if (use_json
&& json_nroute
)
1350 json_object_object_add(json
, rd_str
, json_nroute
);
1354 json_object_int_add(json
, "numPrefix", output_count
);
1355 json_object_int_add(json
, "totalPrefix", total_count
);
1356 vty_json(vty
, json
);
1358 if (output_count
== 0)
1359 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1363 "\nDisplayed %ld out of %ld total prefixes\n",
1364 output_count
, total_count
);
1369 DEFUN(show_ip_bgp_l2vpn_evpn
,
1370 show_ip_bgp_l2vpn_evpn_cmd
,
1371 "show [ip] bgp l2vpn evpn [json]",
1372 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1374 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1375 SHOW_DISPLAY_STANDARD
,
1376 use_json(argc
, argv
));
1379 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1380 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1381 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1387 "Display information for a route distinguisher\n"
1388 "VPN Route Distinguisher\n"
1389 "All VPN Route Distinguishers\n"
1392 int idx_ext_community
= 0;
1394 struct prefix_rd prd
;
1397 if (argv_find(argv
, argc
, "all", &rd_all
))
1398 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1399 NULL
, SHOW_DISPLAY_STANDARD
,
1400 use_json(argc
, argv
));
1402 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1403 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1405 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1408 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1409 SHOW_DISPLAY_STANDARD
,
1410 use_json(argc
, argv
));
1413 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1414 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1415 "show [ip] bgp l2vpn evpn all tags",
1421 "Display information about all EVPN NLRIs\n"
1422 "Display BGP tags for prefixes\n")
1424 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1425 SHOW_DISPLAY_TAGS
, 0);
1428 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1429 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1430 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1436 "Display information for a route distinguisher\n"
1437 "VPN Route Distinguisher\n"
1438 "All VPN Route Distinguishers\n"
1439 "Display BGP tags for prefixes\n")
1441 int idx_ext_community
= 0;
1443 struct prefix_rd prd
;
1446 if (argv_find(argv
, argc
, "all", &rd_all
))
1447 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1448 NULL
, SHOW_DISPLAY_TAGS
, 0);
1450 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1451 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1453 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1456 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1457 SHOW_DISPLAY_TAGS
, 0);
1460 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1461 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1462 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1468 "Detailed information on TCP and BGP neighbor connections\n"
1469 "IPv4 Neighbor to display information about\n"
1470 "IPv6 Neighbor to display information about\n"
1471 "Neighbor on BGP configured interface\n"
1472 "Display routes learned from neighbor\n" JSON_STR
)
1476 char *peerstr
= NULL
;
1477 bool uj
= use_json(argc
, argv
);
1478 afi_t afi
= AFI_L2VPN
;
1479 safi_t safi
= SAFI_EVPN
;
1480 struct bgp
*bgp
= NULL
;
1482 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1485 vty_out(vty
, "No index\n");
1489 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1490 argv_find(argv
, argc
, "neighbors", &idx
);
1491 peerstr
= argv
[++idx
]->arg
;
1493 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1496 json_object
*json_no
= NULL
;
1497 json_no
= json_object_new_object();
1498 json_object_string_add(json_no
, "warning",
1499 "Malformed address");
1500 vty_out(vty
, "%s\n",
1501 json_object_to_json_string(json_no
));
1502 json_object_free(json_no
);
1504 vty_out(vty
, "Malformed address: %s\n",
1508 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1510 json_object
*json_no
= NULL
;
1511 json_no
= json_object_new_object();
1512 json_object_string_add(
1514 "No such neighbor or address family");
1515 vty_out(vty
, "%s\n",
1516 json_object_to_json_string(json_no
));
1517 json_object_free(json_no
);
1519 vty_out(vty
, "%% No such neighbor or address family\n");
1523 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1524 SHOW_DISPLAY_STANDARD
, uj
);
1527 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1528 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1529 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1535 "Display information for a route distinguisher\n"
1536 "VPN Route Distinguisher\n"
1537 "All VPN Route Distinguishers\n"
1538 "Detailed information on TCP and BGP neighbor connections\n"
1539 "IPv4 Neighbor to display information about\n"
1540 "IPv6 Neighbor to display information about\n"
1541 "Neighbor on BGP configured interface\n"
1542 "Display routes learned from neighbor\n" JSON_STR
)
1544 int idx_ext_community
= 0;
1548 char *peerstr
= NULL
;
1549 struct prefix_rd prd
= {};
1550 bool uj
= use_json(argc
, argv
);
1551 afi_t afi
= AFI_L2VPN
;
1552 safi_t safi
= SAFI_EVPN
;
1553 struct bgp
*bgp
= NULL
;
1556 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1559 vty_out(vty
, "No index\n");
1563 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1564 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1565 &idx_ext_community
);
1566 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1569 json_object
*json_no
= NULL
;
1570 json_no
= json_object_new_object();
1571 json_object_string_add(
1573 "Malformed Route Distinguisher");
1574 vty_out(vty
, "%s\n",
1575 json_object_to_json_string(json_no
));
1576 json_object_free(json_no
);
1579 "%% Malformed Route Distinguisher\n");
1584 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1585 argv_find(argv
, argc
, "neighbors", &idx
);
1586 peerstr
= argv
[++idx
]->arg
;
1588 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1591 json_object
*json_no
= NULL
;
1592 json_no
= json_object_new_object();
1593 json_object_string_add(json_no
, "warning",
1594 "Malformed address");
1595 vty_out(vty
, "%s\n",
1596 json_object_to_json_string(json_no
));
1597 json_object_free(json_no
);
1599 vty_out(vty
, "Malformed address: %s\n",
1603 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1605 json_object
*json_no
= NULL
;
1606 json_no
= json_object_new_object();
1607 json_object_string_add(
1609 "No such neighbor or address family");
1610 vty_out(vty
, "%s\n",
1611 json_object_to_json_string(json_no
));
1612 json_object_free(json_no
);
1614 vty_out(vty
, "%% No such neighbor or address family\n");
1620 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1621 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1623 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1624 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1627 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1628 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1629 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1635 "Detailed information on TCP and BGP neighbor connections\n"
1636 "IPv4 Neighbor to display information about\n"
1637 "IPv6 Neighbor to display information about\n"
1638 "Neighbor on BGP configured interface\n"
1639 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1643 bool uj
= use_json(argc
, argv
);
1644 struct bgp
*bgp
= NULL
;
1645 afi_t afi
= AFI_L2VPN
;
1646 safi_t safi
= SAFI_EVPN
;
1647 char *peerstr
= NULL
;
1652 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1655 vty_out(vty
, "No index\n");
1659 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1660 argv_find(argv
, argc
, "neighbors", &idx
);
1661 peerstr
= argv
[++idx
]->arg
;
1663 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1666 json_object
*json_no
= NULL
;
1667 json_no
= json_object_new_object();
1668 json_object_string_add(json_no
, "warning",
1669 "Malformed address");
1670 vty_out(vty
, "%s\n",
1671 json_object_to_json_string(json_no
));
1672 json_object_free(json_no
);
1674 vty_out(vty
, "Malformed address: %s\n",
1678 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1680 json_object
*json_no
= NULL
;
1681 json_no
= json_object_new_object();
1682 json_object_string_add(
1684 "No such neighbor or address family");
1685 vty_out(vty
, "%s\n",
1686 json_object_to_json_string(json_no
));
1687 json_object_free(json_no
);
1689 vty_out(vty
, "%% No such neighbor or address family\n");
1693 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1696 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1697 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1698 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1704 "Display information for a route distinguisher\n"
1705 "VPN Route Distinguisher\n"
1706 "All VPN Route Distinguishers\n"
1707 "Detailed information on TCP and BGP neighbor connections\n"
1708 "IPv4 Neighbor to display information about\n"
1709 "IPv6 Neighbor to display information about\n"
1710 "Neighbor on BGP configured interface\n"
1711 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1713 int idx_ext_community
= 0;
1717 struct prefix_rd prd
;
1718 struct bgp
*bgp
= NULL
;
1719 bool uj
= use_json(argc
, argv
);
1720 char *peerstr
= NULL
;
1721 afi_t afi
= AFI_L2VPN
;
1722 safi_t safi
= SAFI_EVPN
;
1731 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1734 vty_out(vty
, "No index\n");
1738 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1739 argv_find(argv
, argc
, "neighbors", &idx
);
1740 peerstr
= argv
[++idx
]->arg
;
1742 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1745 json_object
*json_no
= NULL
;
1746 json_no
= json_object_new_object();
1747 json_object_string_add(json_no
, "warning",
1748 "Malformed address");
1749 vty_out(vty
, "%s\n",
1750 json_object_to_json_string(json_no
));
1751 json_object_free(json_no
);
1753 vty_out(vty
, "Malformed address: %s\n",
1757 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1759 json_object
*json_no
= NULL
;
1760 json_no
= json_object_new_object();
1761 json_object_string_add(
1763 "No such neighbor or address family");
1764 vty_out(vty
, "%s\n",
1765 json_object_to_json_string(json_no
));
1766 json_object_free(json_no
);
1768 vty_out(vty
, "%% No such neighbor or address family\n");
1772 if (argv_find(argv
, argc
, "all", &rd_all
))
1773 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1776 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1777 &idx_ext_community
);
1778 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1781 json_object
*json_no
= NULL
;
1782 json_no
= json_object_new_object();
1783 json_object_string_add(
1785 "Malformed Route Distinguisher");
1786 vty_out(vty
, "%s\n",
1787 json_object_to_json_string(json_no
));
1788 json_object_free(json_no
);
1791 "%% Malformed Route Distinguisher\n");
1796 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1799 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1800 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1801 "show [ip] bgp l2vpn evpn all overlay [json]",
1807 "Display information about all EVPN NLRIs\n"
1808 "Display BGP Overlay Information for prefixes\n"
1811 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1812 SHOW_DISPLAY_OVERLAY
,
1813 use_json(argc
, argv
));
1816 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1817 show_ip_bgp_evpn_rd_overlay_cmd
,
1818 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1824 "Display information for a route distinguisher\n"
1825 "VPN Route Distinguisher\n"
1826 "All VPN Route Distinguishers\n"
1827 "Display BGP Overlay Information for prefixes\n")
1829 int idx_ext_community
= 0;
1831 struct prefix_rd prd
;
1834 if (argv_find(argv
, argc
, "all", &rd_all
))
1835 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1836 NULL
, SHOW_DISPLAY_OVERLAY
,
1837 use_json(argc
, argv
));
1839 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1840 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1842 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1845 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1846 SHOW_DISPLAY_OVERLAY
,
1847 use_json(argc
, argv
));
1850 DEFUN(show_bgp_l2vpn_evpn_com
,
1851 show_bgp_l2vpn_evpn_com_cmd
,
1852 "show bgp l2vpn evpn \
1853 <community AA:NN|large-community AA:BB:CC> \
1854 [exact-match] [json]",
1859 "Display routes matching the community\n"
1860 "Community number where AA and NN are (0-65535)\n"
1861 "Display routes matching the large-community\n"
1862 "List of large-community numbers\n"
1863 "Exact match of the communities\n"
1868 const char *clist_number_or_name
;
1869 int show_type
= bgp_show_type_normal
;
1870 struct community
*com
;
1871 struct lcommunity
*lcom
;
1873 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1874 clist_number_or_name
= argv
[++idx
]->arg
;
1875 show_type
= bgp_show_type_lcommunity
;
1877 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1878 show_type
= bgp_show_type_lcommunity_exact
;
1880 lcom
= lcommunity_str2com(clist_number_or_name
);
1882 vty_out(vty
, "%% Large-community malformed\n");
1886 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1887 SHOW_DISPLAY_STANDARD
,
1888 use_json(argc
, argv
));
1890 lcommunity_free(&lcom
);
1891 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1892 clist_number_or_name
= argv
[++idx
]->arg
;
1893 show_type
= bgp_show_type_community
;
1895 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1896 show_type
= bgp_show_type_community_exact
;
1898 com
= community_str2com(clist_number_or_name
);
1901 vty_out(vty
, "%% Community malformed: %s\n",
1902 clist_number_or_name
);
1906 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1907 SHOW_DISPLAY_STANDARD
,
1908 use_json(argc
, argv
));
1909 community_free(&com
);
1915 /* For testing purpose, static route of EVPN RT-5. */
1916 DEFUN(evpnrt5_network
,
1917 evpnrt5_network_cmd
,
1918 "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 RMAP_NAME]",
1919 "Specify a network to announce via BGP\n"
1922 "Specify Route Distinguisher\n"
1923 "VPN Route Distinguisher\n"
1925 "Ethernet Tag Value\n"
1928 "Ethernet Segment Identifier\n"
1929 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1931 "Gateway IP ( A.B.C.D )\n"
1932 "Gateway IPv6 ( X:X::X:X )\n"
1933 "Router Mac Ext Comm\n"
1934 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1935 "Route-map to modify the attributes\n"
1936 "Name of the route map\n")
1938 int idx_ipv4_prefixlen
= 1;
1939 int idx_route_distinguisher
= 3;
1944 int idx_routermac
= 13;
1946 return bgp_static_set_safi(
1947 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1948 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1949 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1950 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1951 argv
[idx_routermac
]->arg
);
1954 /* For testing purpose, static route of EVPN RT-5. */
1955 DEFUN(no_evpnrt5_network
,
1956 no_evpnrt5_network_cmd
,
1957 "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>",
1959 "Specify a network to announce via BGP\n"
1962 "Specify Route Distinguisher\n"
1963 "VPN Route Distinguisher\n"
1965 "Ethernet Tag Value\n"
1968 "Ethernet Segment Identifier\n"
1969 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1970 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1972 int idx_ipv4_prefixlen
= 2;
1973 int idx_ext_community
= 4;
1978 return bgp_static_unset_safi(
1979 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1980 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1981 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1982 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1985 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1987 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
, false);
1990 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1992 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
, false);
1996 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1997 * check that this is a change.
1999 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2000 struct ecommunity
*ecomadd
)
2002 /* If the VNI is "live", we need to uninstall routes using the current
2003 * import RT(s) first before we update the import RT, and subsequently
2006 if (is_vni_live(vpn
))
2007 bgp_evpn_uninstall_routes(bgp
, vpn
);
2009 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2010 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2012 /* If the auto route-target is in use we must remove it */
2013 evpn_import_rt_delete_auto(bgp
, vpn
);
2015 /* Add new RT and rebuild the RT to VNI mapping */
2016 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2018 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2019 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2021 /* Install routes that match new import RT */
2022 if (is_vni_live(vpn
))
2023 bgp_evpn_install_routes(bgp
, vpn
);
2027 * Unconfigure Import RT(s) for a VNI (vty handler).
2029 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2030 struct ecommunity
*ecomdel
)
2032 struct listnode
*node
, *nnode
, *node_to_del
;
2033 struct ecommunity
*ecom
;
2035 /* Along the lines of "configure" except we have to reset to the
2038 if (is_vni_live(vpn
))
2039 bgp_evpn_uninstall_routes(bgp
, vpn
);
2041 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2042 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2044 /* Delete all import RTs */
2045 if (ecomdel
== NULL
) {
2046 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2047 ecommunity_free(&ecom
);
2048 list_delete_node(vpn
->import_rtl
, node
);
2052 /* Delete a specific import RT */
2056 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2057 if (ecommunity_match(ecom
, ecomdel
)) {
2058 ecommunity_free(&ecom
);
2065 list_delete_node(vpn
->import_rtl
, node_to_del
);
2068 assert(vpn
->import_rtl
);
2069 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2070 if (list_isempty(vpn
->import_rtl
)) {
2071 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2072 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2074 /* Rebuild the RT to VNI mapping */
2076 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2078 /* Install routes that match new import RT */
2079 if (is_vni_live(vpn
))
2080 bgp_evpn_install_routes(bgp
, vpn
);
2084 * Configure the Export RT for a VNI (vty handler). Caller expected to
2085 * check that this is a change. Note that only a single export RT is
2086 * allowed for a VNI and any change to configuration is implemented as
2087 * a "replace" (similar to other configuration).
2089 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2090 struct ecommunity
*ecomadd
)
2092 /* If the auto route-target is in use we must remove it */
2093 evpn_export_rt_delete_auto(bgp
, vpn
);
2095 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2096 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2098 if (is_vni_live(vpn
))
2099 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2103 * Unconfigure the Export RT for a VNI (vty handler)
2105 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2106 struct ecommunity
*ecomdel
)
2108 struct listnode
*node
, *nnode
, *node_to_del
;
2109 struct ecommunity
*ecom
;
2111 /* Delete all export RTs */
2112 if (ecomdel
== NULL
) {
2113 /* Reset to default and process all routes. */
2114 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2115 ecommunity_free(&ecom
);
2116 list_delete_node(vpn
->export_rtl
, node
);
2120 /* Delete a specific export RT */
2124 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2125 if (ecommunity_match(ecom
, ecomdel
)) {
2126 ecommunity_free(&ecom
);
2133 list_delete_node(vpn
->export_rtl
, node_to_del
);
2136 assert(vpn
->export_rtl
);
2137 if (list_isempty(vpn
->export_rtl
)) {
2138 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2139 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2142 if (is_vni_live(vpn
))
2143 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2147 * Configure RD for VRF
2149 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2151 /* If we have already advertise type-5 routes with a diffrent RD, we
2152 * have to delete and withdraw them firs
2154 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2157 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2158 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2160 /* We have a new RD for VRF.
2161 * Advertise all type-5 routes again with the new RD
2163 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2167 * Unconfigure RD for VRF
2169 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2171 /* If we have already advertise type-5 routes with a diffrent RD, we
2172 * have to delete and withdraw them firs
2174 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2176 /* fall back to default RD */
2177 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2178 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2180 /* We have a new RD for VRF.
2181 * Advertise all type-5 routes again with the new RD
2183 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2187 * Configure RD for a VNI (vty handler)
2189 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2190 struct prefix_rd
*rd
)
2192 /* If the VNI is "live", we need to delete and withdraw this VNI's
2193 * local routes with the prior RD first. Then, after updating RD,
2194 * need to re-advertise.
2196 if (is_vni_live(vpn
))
2197 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2200 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2201 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2203 if (is_vni_live(vpn
))
2204 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2208 * Unconfigure RD for a VNI (vty handler)
2210 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2212 /* If the VNI is "live", we need to delete and withdraw this VNI's
2213 * local routes with the prior RD first. Then, after resetting RD
2214 * to automatic value, need to re-advertise.
2216 if (is_vni_live(vpn
))
2217 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2219 /* reset RD to default */
2220 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2222 if (is_vni_live(vpn
))
2223 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2227 * Create VNI, if not already present (VTY handler). Mark as configured.
2229 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2231 struct bgpevpn
*vpn
;
2232 struct in_addr mcast_grp
= {INADDR_ANY
};
2234 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2236 /* Check if this L2VNI is already configured as L3VNI */
2237 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2240 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2245 /* tenant vrf will be updated when we get local_vni_add from
2248 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2251 /* Mark as configured. */
2252 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2257 * Delete VNI. If VNI does not exist in the system (i.e., just
2258 * configuration), all that is needed is to free it. Otherwise,
2259 * any parameters configured for the VNI need to be reset (with
2260 * appropriate action) and the VNI marked as unconfigured; the
2261 * VNI will continue to exist, purely as a "learnt" entity.
2263 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2265 if (!is_vni_live(vpn
)) {
2266 bgp_evpn_free(bgp
, vpn
);
2270 /* We need to take the unconfigure action for each parameter of this VNI
2271 * that is configured. Some optimization is possible, but not worth the
2272 * additional code for an operation that should be pretty rare.
2274 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2276 /* First, deal with the export side - RD and export RT changes. */
2277 if (is_rd_configured(vpn
))
2278 evpn_unconfigure_rd(bgp
, vpn
);
2279 if (is_export_rt_configured(vpn
))
2280 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2282 /* Next, deal with the import side. */
2283 if (is_import_rt_configured(vpn
))
2284 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2288 * Display import RT mapping to VRFs (vty handler)
2289 * bgp_evpn: evpn bgp instance
2291 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2299 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2300 (void (*)(struct hash_bucket
*,
2301 void *))show_vrf_import_rt_entry
,
2306 * Display import RT mapping to VNIs (vty handler)
2308 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2317 bgp
->import_rt_hash
,
2318 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2323 * Display EVPN routes for all VNIs - vty handler.
2325 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2326 struct in_addr vtep_ip
, json_object
*json
,
2330 struct vni_walk_ctx wctx
;
2332 num_vnis
= hashcount(bgp
->vnihash
);
2335 memset(&wctx
, 0, sizeof(wctx
));
2338 wctx
.vtep_ip
= vtep_ip
;
2340 wctx
.detail
= detail
;
2341 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2342 void *))show_vni_routes_hash
,
2347 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2349 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2350 vni_t vni
, struct in_addr orig_ip
,
2353 struct bgpevpn
*vpn
;
2354 struct prefix_evpn p
;
2355 struct bgp_dest
*dest
;
2356 struct bgp_path_info
*pi
;
2357 uint32_t path_cnt
= 0;
2360 json_object
*json_paths
= NULL
;
2366 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2368 vty_out(vty
, "VNI not found\n");
2372 /* See if route exists. */
2373 build_evpn_type3_prefix(&p
, orig_ip
);
2374 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2375 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2377 vty_out(vty
, "%% Network not in table\n");
2380 bgp_dest_unlock_node(dest
);
2386 json_paths
= json_object_new_array();
2388 /* Prefix and num paths displayed once per prefix. */
2389 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2391 /* Display each path for this prefix. */
2392 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2393 json_object
*json_path
= NULL
;
2396 json_path
= json_object_new_array();
2398 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2399 RPKI_NOT_BEING_USED
, json_path
);
2402 json_object_array_add(json_paths
, json_path
);
2409 json_object_object_add(json
, "paths", json_paths
);
2411 json_object_int_add(json
, "numPaths", path_cnt
);
2413 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2417 bgp_dest_unlock_node(dest
);
2421 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2422 * By definition, only matching type-2 route will be displayed.
2424 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2425 vni_t vni
, struct ethaddr
*mac
,
2426 struct ipaddr
*ip
, json_object
*json
)
2428 struct bgpevpn
*vpn
;
2429 struct prefix_evpn p
;
2430 struct bgp_dest
*dest
;
2431 struct bgp_path_info
*pi
;
2432 uint32_t path_cnt
= 0;
2435 json_object
*json_paths
= NULL
;
2441 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2444 vty_out(vty
, "VNI not found\n");
2448 /* See if route exists. Look for both non-sticky and sticky. */
2449 build_evpn_type2_prefix(&p
, mac
, ip
);
2450 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2451 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2453 vty_out(vty
, "%% Network not in table\n");
2456 bgp_dest_unlock_node(dest
);
2462 json_paths
= json_object_new_array();
2464 /* Prefix and num paths displayed once per prefix. */
2465 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2467 /* Display each path for this prefix. */
2468 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2469 json_object
*json_path
= NULL
;
2472 json_path
= json_object_new_array();
2474 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2475 RPKI_NOT_BEING_USED
, json_path
);
2478 json_object_array_add(json_paths
, json_path
);
2485 json_object_object_add(json
, "paths", json_paths
);
2487 json_object_int_add(json
, "numPaths", path_cnt
);
2489 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2493 bgp_dest_unlock_node(dest
);
2496 /* Disaplay EVPN routes for a ESI - VTY handler */
2497 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2498 esi_t
*esi
, json_object
*json
)
2500 struct bgp_evpn_es
*es
= NULL
;
2503 es
= bgp_evpn_es_find(esi
);
2506 vty_out(vty
, "ESI not found\n");
2510 show_esi_routes(bgp
, es
, vty
, json
);
2514 * Display EVPN routes for a VNI - vty handler.
2515 * If 'type' is non-zero, only routes matching that type are shown.
2516 * If the vtep_ip is non zero, only routes behind that vtep are shown
2518 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2519 int type
, struct in_addr vtep_ip
,
2522 struct bgpevpn
*vpn
;
2525 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2528 vty_out(vty
, "VNI not found\n");
2532 /* Walk this VNI's route table and display appropriate routes. */
2533 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2537 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2538 * IP (vty handler). By definition, only matching type-2 route will be
2541 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2542 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2543 struct ipaddr
*ip
, json_object
*json
)
2545 struct prefix_evpn p
;
2546 struct bgp_dest
*dest
;
2547 struct bgp_path_info
*pi
;
2550 uint32_t path_cnt
= 0;
2551 json_object
*json_paths
= NULL
;
2556 /* See if route exists. Look for both non-sticky and sticky. */
2557 build_evpn_type2_prefix(&p
, mac
, ip
);
2558 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2559 (struct prefix
*)&p
, prd
);
2560 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2562 vty_out(vty
, "%% Network not in table\n");
2565 bgp_dest_unlock_node(dest
);
2570 /* Prefix and num paths displayed once per prefix. */
2571 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2574 json_paths
= json_object_new_array();
2576 /* Display each path for this prefix. */
2577 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2578 json_object
*json_path
= NULL
;
2581 json_path
= json_object_new_array();
2583 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2584 RPKI_NOT_BEING_USED
, json_path
);
2587 json_object_array_add(json_paths
, json_path
);
2592 if (json
&& path_cnt
) {
2594 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2595 json_object_int_add(json
, "numPaths", path_cnt
);
2597 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2601 bgp_dest_unlock_node(dest
);
2605 * Display BGP EVPN routing table -- for specific RD (vty handler)
2606 * If 'type' is non-zero, only routes matching that type are shown.
2608 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2609 struct prefix_rd
*prd
, int type
,
2612 struct bgp_dest
*rd_dest
;
2613 struct bgp_table
*table
;
2614 struct bgp_dest
*dest
;
2615 struct bgp_path_info
*pi
;
2619 uint32_t prefix_cnt
, path_cnt
;
2620 json_object
*json_rd
= NULL
;
2621 int add_rd_to_json
= 0;
2625 prefix_cnt
= path_cnt
= 0;
2627 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2631 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2632 if (table
== NULL
) {
2633 bgp_dest_unlock_node(rd_dest
);
2638 json_rd
= json_object_new_object();
2639 json_object_string_addf(json_rd
, "rd", "%pRD", prd
);
2642 bgp_dest_unlock_node(rd_dest
);
2644 /* Display all prefixes with this RD. */
2645 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2646 const struct prefix_evpn
*evp
=
2647 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2648 json_object
*json_prefix
= NULL
;
2649 json_object
*json_paths
= NULL
;
2650 int add_prefix_to_json
= 0;
2652 if (type
&& evp
->prefix
.route_type
!= type
)
2656 json_prefix
= json_object_new_object();
2658 pi
= bgp_dest_get_bgp_path_info(dest
);
2660 /* RD header and legend - once overall. */
2661 if (rd_header
&& !json
) {
2663 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2665 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2667 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2669 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2671 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2675 /* Prefix and num paths displayed once per prefix. */
2676 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2683 json_paths
= json_object_new_array();
2685 /* Display each path for this prefix. */
2686 for (; pi
; pi
= pi
->next
) {
2687 json_object
*json_path
= NULL
;
2690 json_path
= json_object_new_array();
2692 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2693 RPKI_NOT_BEING_USED
, json_path
);
2696 json_object_array_add(json_paths
, json_path
);
2699 add_prefix_to_json
= 1;
2704 if (add_prefix_to_json
) {
2705 json_object_object_add(json_prefix
, "paths",
2707 json_object_object_addf(json_rd
, json_prefix
,
2710 json_object_free(json_paths
);
2711 json_object_free(json_prefix
);
2720 json_object_object_addf(json
, json_rd
, "%pRD", prd
);
2722 json_object_free(json_rd
);
2726 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2727 json_object_int_add(json
, "numPaths", path_cnt
);
2729 if (prefix_cnt
== 0)
2730 vty_out(vty
, "No prefixes exist with this RD%s\n",
2731 type
? " (of requested type)" : "");
2734 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2735 prefix_cnt
, path_cnt
,
2736 type
? " (of requested type)" : "");
2741 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2742 * (vty handler). Only matching type-2 routes will be displayed.
2744 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2745 struct ethaddr
*mac
, struct ipaddr
*ip
,
2748 struct bgp_dest
*rd_dest
;
2749 struct bgp_table
*table
;
2750 struct bgp_dest
*dest
;
2751 struct bgp_path_info
*pi
;
2752 afi_t afi
= AFI_L2VPN
;
2753 safi_t safi
= SAFI_EVPN
;
2754 uint32_t prefix_cnt
, path_cnt
;
2755 prefix_cnt
= path_cnt
= 0;
2757 /* EVPN routing table is a 2-level table with the first level being
2758 * the RD. We need to look in every RD we know about.
2760 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2761 rd_dest
= bgp_route_next(rd_dest
)) {
2762 json_object
*json_paths
= NULL
; /* paths array for prefix */
2763 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2764 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2765 char rd_str
[RD_ADDRSTRLEN
];
2766 int add_rd_to_json
= 0;
2767 struct prefix_evpn ep
;
2768 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2770 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2774 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2777 /* Construct an RT-2 from the user-supplied mac(ip),
2778 * then search the l2vpn evpn table for it.
2780 build_evpn_type2_prefix(&ep
, mac
, ip
);
2781 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2782 (struct prefix
*)&ep
,
2783 (struct prefix_rd
*)rd_destp
);
2788 json_rd
= json_object_new_object();
2790 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2792 pi
= bgp_dest_get_bgp_path_info(dest
);
2794 /* RD header - per RD. */
2795 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2796 rd_str
, RD_ADDRSTRLEN
);
2801 json_prefix
= json_object_new_object();
2802 json_paths
= json_object_new_array();
2803 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2805 json_object_int_add(json_prefix
, "prefixLen",
2808 /* Prefix and num paths displayed once per prefix. */
2809 route_vty_out_detail_header(
2810 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2811 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2813 /* For EVPN, the prefix is displayed for each path (to
2814 * fit in with code that already exists).
2816 for (; pi
; pi
= pi
->next
) {
2817 json_object
*json_path
= NULL
;
2823 json_path
= json_object_new_array();
2825 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2826 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2830 json_object_array_add(json_paths
, json_path
);
2836 json_object_object_add(json_prefix
, "paths",
2838 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
2841 json_object_object_add(json
, rd_str
, json_rd
);
2843 json_object_free(json_rd
);
2848 bgp_dest_unlock_node(dest
);
2852 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2853 json_object_int_add(json
, "numPaths", path_cnt
);
2855 if (prefix_cnt
== 0) {
2856 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2858 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2859 prefix_cnt
, path_cnt
);
2865 * Display BGP EVPN routing table - all routes (vty handler).
2866 * If 'type' is non-zero, only routes matching that type are shown.
2868 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2869 json_object
*json
, int detail
)
2871 struct bgp_dest
*rd_dest
;
2872 struct bgp_table
*table
;
2873 struct bgp_dest
*dest
;
2874 struct bgp_path_info
*pi
;
2875 int header
= detail
? 0 : 1;
2879 uint32_t prefix_cnt
, path_cnt
;
2883 prefix_cnt
= path_cnt
= 0;
2885 /* EVPN routing table is a 2-level table with the first level being
2888 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2889 rd_dest
= bgp_route_next(rd_dest
)) {
2890 char rd_str
[RD_ADDRSTRLEN
];
2891 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2892 int add_rd_to_json
= 0;
2894 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2896 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2900 tbl_ver
= table
->version
;
2901 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2905 json_rd
= json_object_new_object();
2909 /* Display all prefixes for an RD */
2910 for (dest
= bgp_table_top(table
); dest
;
2911 dest
= bgp_route_next(dest
)) {
2912 json_object
*json_prefix
=
2913 NULL
; /* contains prefix under a RD */
2914 json_object
*json_paths
=
2915 NULL
; /* array of paths under a prefix*/
2916 const struct prefix_evpn
*evp
=
2917 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2919 int add_prefix_to_json
= 0;
2920 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2922 if (type
&& evp
->prefix
.route_type
!= type
)
2925 pi
= bgp_dest_get_bgp_path_info(dest
);
2927 /* Overall header/legend displayed once. */
2929 bgp_evpn_show_route_header(vty
, bgp
,
2934 "%19s Extended Community\n"
2939 /* RD header - per RD. */
2941 bgp_evpn_show_route_rd_header(
2942 vty
, rd_dest
, json_rd
, rd_str
,
2951 json_prefix
= json_object_new_object();
2952 json_paths
= json_object_new_array();
2953 json_object_string_addf(json_prefix
, "prefix",
2955 json_object_int_add(json_prefix
, "prefixLen",
2959 /* Prefix and num paths displayed once per prefix. */
2961 route_vty_out_detail_header(
2963 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
2964 SAFI_EVPN
, json_prefix
);
2966 /* For EVPN, the prefix is displayed for each path (to
2968 * with code that already exists).
2970 for (; pi
; pi
= pi
->next
) {
2971 json_object
*json_path
= NULL
;
2974 add_prefix_to_json
= 1;
2978 json_path
= json_object_new_array();
2981 route_vty_out_detail(
2982 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2983 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2986 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
2990 json_object_array_add(json_paths
,
2995 if (add_prefix_to_json
) {
2996 json_object_object_add(json_prefix
,
2999 json_object_object_addf(json_rd
,
3003 json_object_free(json_prefix
);
3004 json_object_free(json_paths
);
3013 json_object_object_add(json
, rd_str
, json_rd
);
3015 json_object_free(json_rd
);
3022 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3023 json_object_int_add(json
, "numPaths", path_cnt
);
3025 if (prefix_cnt
== 0) {
3026 vty_out(vty
, "No EVPN prefixes %sexist\n",
3027 type
? "(of requested type) " : "");
3029 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3030 prefix_cnt
, path_cnt
,
3031 type
? " (of requested type)" : "");
3037 * Display specified VNI (vty handler)
3039 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3043 struct bgpevpn
*vpn
;
3045 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3048 display_vni(vty
, vpn
, json
);
3050 struct bgp
*bgp_temp
;
3051 struct listnode
*node
= NULL
;
3053 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3054 if (bgp_temp
->l3vni
== vni
) {
3056 display_l3vni(vty
, bgp_temp
, json
);
3063 vty_out(vty
, "{}\n");
3065 vty_out(vty
, "VNI not found\n");
3072 * Display a VNI (upon user query).
3074 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3078 struct bgp
*bgp_temp
= NULL
;
3079 struct listnode
*node
;
3083 vty_out(vty
, "Flags: * - Kernel\n");
3084 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3085 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3088 /* print all L2 VNIS */
3091 hash_iterate(bgp
->vnihash
,
3092 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3095 /* print all L3 VNIs */
3096 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3097 show_l3vni_entry(vty
, bgp_temp
, json
);
3101 * evpn - enable advertisement of svi MAC-IP
3103 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3107 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3109 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3112 bgp
->evpn_info
->advertise_svi_macip
= set
;
3113 bgp_zebra_advertise_svi_macip(bgp
,
3114 bgp
->evpn_info
->advertise_svi_macip
, 0);
3116 if (set
&& vpn
->advertise_svi_macip
)
3118 else if (!set
&& !vpn
->advertise_svi_macip
)
3121 vpn
->advertise_svi_macip
= set
;
3122 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3128 * evpn - enable advertisement of default g/w
3130 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3133 if (bgp
->advertise_gw_macip
)
3136 bgp
->advertise_gw_macip
= 1;
3137 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3139 if (vpn
->advertise_gw_macip
)
3142 vpn
->advertise_gw_macip
= 1;
3143 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3150 * evpn - disable advertisement of default g/w
3152 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3153 struct bgpevpn
*vpn
)
3156 if (!bgp
->advertise_gw_macip
)
3159 bgp
->advertise_gw_macip
= 0;
3160 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3162 if (!vpn
->advertise_gw_macip
)
3165 vpn
->advertise_gw_macip
= 0;
3166 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3173 * evpn - enable advertisement of default g/w
3175 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3176 afi_t afi
, bool add
)
3178 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3181 /* bail if we are already advertising default route */
3182 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3186 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3187 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3188 else if (afi
== AFI_IP6
)
3189 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3190 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3192 /* bail out if we havent advertised the default route */
3193 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3196 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3197 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3198 else if (afi
== AFI_IP6
)
3199 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3200 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3203 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3207 * evpn - enable advertisement of default g/w
3209 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3210 struct bgpevpn
*vpn
)
3212 if (vpn
->advertise_subnet
)
3215 vpn
->advertise_subnet
= 1;
3216 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3220 * evpn - disable advertisement of default g/w
3222 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3224 if (!vpn
->advertise_subnet
)
3227 vpn
->advertise_subnet
= 0;
3228 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3232 * EVPN (VNI advertisement) enabled. Register with zebra.
3234 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3236 bgp
->advertise_all_vni
= 1;
3238 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3242 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3243 * cache, EVPN routes (delete and withdraw from peers).
3245 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3247 bgp
->advertise_all_vni
= 0;
3248 bgp_set_evpn(bgp_get_default());
3249 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3250 bgp_evpn_cleanup_on_disable(bgp
);
3253 /* Set resolve overlay index flag */
3254 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3256 if (set
== bgp
->resolve_overlay_index
)
3260 bgp
->resolve_overlay_index
= true;
3261 hash_iterate(bgp
->vnihash
,
3262 (void (*)(struct hash_bucket
*, void *))
3263 bgp_evpn_handle_resolve_overlay_index_set
,
3268 (void (*)(struct hash_bucket
*, void *))
3269 bgp_evpn_handle_resolve_overlay_index_unset
,
3271 bgp
->resolve_overlay_index
= false;
3276 * EVPN - use RFC8365 to auto-derive RT
3278 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3280 bgp
->advertise_autort_rfc8365
= 1;
3281 bgp_evpn_handle_autort_change(bgp
);
3285 * EVPN - don't use RFC8365 to auto-derive RT
3287 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3289 bgp
->advertise_autort_rfc8365
= 0;
3290 bgp_evpn_handle_autort_change(bgp
);
3293 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3296 struct listnode
*node
, *nnode
;
3297 struct ecommunity
*ecom
;
3299 if (is_vni_configured(vpn
)) {
3300 vty_out(vty
, " vni %d\n", vpn
->vni
);
3301 if (is_rd_configured(vpn
))
3302 vty_out(vty
, " rd %pRD\n", &vpn
->prd
);
3304 if (is_import_rt_configured(vpn
)) {
3305 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3307 ecom_str
= ecommunity_ecom2str(
3308 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3309 vty_out(vty
, " route-target import %s\n",
3311 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3315 if (is_export_rt_configured(vpn
)) {
3316 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3318 ecom_str
= ecommunity_ecom2str(
3319 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3320 vty_out(vty
, " route-target export %s\n",
3322 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3326 if (vpn
->advertise_gw_macip
)
3327 vty_out(vty
, " advertise-default-gw\n");
3329 if (vpn
->advertise_svi_macip
)
3330 vty_out(vty
, " advertise-svi-ip\n");
3332 if (vpn
->advertise_subnet
)
3333 vty_out(vty
, " advertise-subnet\n");
3335 vty_out(vty
, " exit-vni\n");
3339 #ifndef VTYSH_EXTRACT_PL
3340 #include "bgpd/bgp_evpn_vty_clippy.c"
3343 DEFPY(bgp_evpn_flood_control
,
3344 bgp_evpn_flood_control_cmd
,
3345 "[no$no] flooding <disable$disable|head-end-replication$her>",
3347 "Specify handling for BUM packets\n"
3348 "Do not flood any BUM packets\n"
3349 "Flood BUM packets using head-end replication\n")
3351 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3352 enum vxlan_flood_control flood_ctrl
;
3358 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3360 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3364 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3367 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3368 bgp_evpn_flood_control_change(bgp
);
3373 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3374 bgp_evpn_advertise_default_gw_vni_cmd
,
3375 "advertise-default-gw",
3376 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3378 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3379 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3384 evpn_set_advertise_default_gw(bgp
, vpn
);
3389 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3390 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3391 "no advertise-default-gw",
3393 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3395 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3396 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3401 evpn_unset_advertise_default_gw(bgp
, vpn
);
3407 DEFUN (bgp_evpn_advertise_default_gw
,
3408 bgp_evpn_advertise_default_gw_cmd
,
3409 "advertise-default-gw",
3410 "Advertise All default g/w mac-ip routes in EVPN\n")
3412 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3417 if (!EVPN_ENABLED(bgp
)) {
3419 "This command is only supported under the EVPN VRF\n");
3423 evpn_set_advertise_default_gw(bgp
, NULL
);
3428 DEFUN (no_bgp_evpn_advertise_default_gw
,
3429 no_bgp_evpn_advertise_default_gw_cmd
,
3430 "no advertise-default-gw",
3432 "Withdraw All default g/w mac-ip routes from EVPN\n")
3434 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3439 evpn_unset_advertise_default_gw(bgp
, NULL
);
3444 DEFUN (bgp_evpn_advertise_all_vni
,
3445 bgp_evpn_advertise_all_vni_cmd
,
3446 "advertise-all-vni",
3447 "Advertise All local VNIs\n")
3449 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3450 struct bgp
*bgp_evpn
= NULL
;
3455 bgp_evpn
= bgp_get_evpn();
3456 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3457 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3458 bgp_evpn
->name_pretty
);
3459 return CMD_WARNING_CONFIG_FAILED
;
3462 evpn_set_advertise_all_vni(bgp
);
3466 DEFUN (no_bgp_evpn_advertise_all_vni
,
3467 no_bgp_evpn_advertise_all_vni_cmd
,
3468 "no advertise-all-vni",
3470 "Advertise All local VNIs\n")
3472 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3476 evpn_unset_advertise_all_vni(bgp
);
3480 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3481 bgp_evpn_advertise_autort_rfc8365_cmd
,
3482 "autort rfc8365-compatible",
3483 "Auto-derivation of RT\n"
3484 "Auto-derivation of RT using RFC8365\n")
3486 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3490 evpn_set_advertise_autort_rfc8365(bgp
);
3494 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3495 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3496 "no autort rfc8365-compatible",
3498 "Auto-derivation of RT\n"
3499 "Auto-derivation of RT using RFC8365\n")
3501 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3505 evpn_unset_advertise_autort_rfc8365(bgp
);
3509 DEFUN (bgp_evpn_default_originate
,
3510 bgp_evpn_default_originate_cmd
,
3511 "default-originate <ipv4 | ipv6>",
3512 "originate a default route\n"
3513 "ipv4 address family\n"
3514 "ipv6 address family\n")
3518 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3522 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3523 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3527 DEFUN (no_bgp_evpn_default_originate
,
3528 no_bgp_evpn_default_originate_cmd
,
3529 "no default-originate <ipv4 | ipv6>",
3531 "withdraw a default route\n"
3532 "ipv4 address family\n"
3533 "ipv6 address family\n")
3537 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3541 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3542 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3546 DEFPY (dup_addr_detection
,
3547 dup_addr_detection_cmd
,
3548 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3549 "Duplicate address detection\n"
3550 "Max allowed moves before address detected as duplicate\n"
3551 "Num of max allowed moves (2-1000) default 5\n"
3552 "Duplicate address detection time\n"
3553 "Time in seconds (2-1800) default 180\n")
3555 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3560 if (!EVPN_ENABLED(bgp_vrf
)) {
3562 "This command is only supported under the EVPN VRF\n");
3566 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3569 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3571 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3573 bgp_zebra_dup_addr_detection(bgp_vrf
);
3578 DEFPY (dup_addr_detection_auto_recovery
,
3579 dup_addr_detection_auto_recovery_cmd
,
3580 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3581 "Duplicate address detection\n"
3582 "Duplicate address detection freeze\n"
3583 "Duplicate address detection permanent freeze\n"
3584 "Duplicate address detection freeze time (30-3600)\n")
3586 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3587 uint32_t freeze_time
= freeze_time_val
;
3592 if (!EVPN_ENABLED(bgp_vrf
)) {
3594 "This command is only supported under the EVPN VRF\n");
3598 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3599 bgp_vrf
->evpn_info
->dad_freeze
= true;
3600 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3602 bgp_zebra_dup_addr_detection(bgp_vrf
);
3607 DEFPY (no_dup_addr_detection
,
3608 no_dup_addr_detection_cmd
,
3609 "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>]",
3611 "Duplicate address detection\n"
3612 "Max allowed moves before address detected as duplicate\n"
3613 "Num of max allowed moves (2-1000) default 5\n"
3614 "Duplicate address detection time\n"
3615 "Time in seconds (2-1800) default 180\n"
3616 "Duplicate address detection freeze\n"
3617 "Duplicate address detection permanent freeze\n"
3618 "Duplicate address detection freeze time (30-3600)\n")
3620 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3621 uint32_t max_moves
= (uint32_t)max_moves_val
;
3622 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3627 if (!EVPN_ENABLED(bgp_vrf
)) {
3629 "This command is only supported under the EVPN VRF\n");
3634 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3636 /* Reset all parameters to default. */
3637 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3638 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3639 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3640 bgp_vrf
->evpn_info
->dad_freeze
= false;
3641 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3644 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3646 "%% Value does not match with config\n");
3649 bgp_vrf
->evpn_info
->dad_max_moves
=
3650 EVPN_DAD_DEFAULT_MAX_MOVES
;
3654 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3656 "%% Value does not match with config\n");
3659 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3663 if (bgp_vrf
->evpn_info
->dad_freeze_time
3666 "%% Value does not match with config\n");
3669 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3670 bgp_vrf
->evpn_info
->dad_freeze
= false;
3673 if (permanent_val
) {
3674 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3676 "%% Value does not match with config\n");
3679 bgp_vrf
->evpn_info
->dad_freeze
= false;
3683 bgp_zebra_dup_addr_detection(bgp_vrf
);
3688 DEFPY(bgp_evpn_advertise_svi_ip
,
3689 bgp_evpn_advertise_svi_ip_cmd
,
3690 "[no$no] advertise-svi-ip",
3692 "Advertise svi mac-ip routes in EVPN\n")
3694 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3700 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3702 if (!EVPN_ENABLED(bgp
)) {
3704 "This command is only supported under EVPN VRF\n");
3707 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3713 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3714 bgp_evpn_advertise_svi_ip_vni_cmd
,
3715 "[no$no] advertise-svi-ip",
3717 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3719 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3720 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3726 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3728 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3733 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3734 bgp_evpn_advertise_vni_subnet_cmd
,
3736 "Advertise the subnet corresponding to VNI\n")
3738 struct bgp
*bgp_vrf
= NULL
;
3739 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3740 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3745 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3749 evpn_set_advertise_subnet(bgp
, vpn
);
3753 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3754 no_bgp_evpn_advertise_vni_subnet_cmd
,
3755 "no advertise-subnet",
3757 "Advertise All local VNIs\n")
3759 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3760 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3765 evpn_unset_advertise_subnet(bgp
, vpn
);
3769 DEFUN (bgp_evpn_advertise_type5
,
3770 bgp_evpn_advertise_type5_cmd
,
3771 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3772 "Advertise prefix routes\n"
3775 "advertise gateway IP overlay index\n"
3776 "route-map for filtering specific routes\n"
3777 "Name of the route map\n")
3779 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3786 int rmap_changed
= 0;
3787 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3789 bool adv_flag_changed
= false;
3791 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3792 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3793 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3795 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3797 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3799 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3800 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3803 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3807 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3809 "%% Only ipv4 or ipv6 address families are supported\n");
3813 if (safi
!= SAFI_UNICAST
) {
3815 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3819 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3820 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3821 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3825 if (afi
== AFI_IP
) {
3826 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3827 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3828 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3829 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3832 * this is the case for first time ever configuration
3833 * adv ipv4 unicast is enabled for the first time.
3834 * So no need to reset any flag
3836 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3838 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3839 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3840 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3842 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3843 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3844 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3846 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3847 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3850 * This is modify case from gateway-ip
3851 * to no overlay index
3853 adv_flag_changed
= true;
3854 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3855 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3856 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3857 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3858 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3860 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3861 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3864 * This is modify case from no overlay index
3867 adv_flag_changed
= true;
3868 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3869 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3870 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3871 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3875 * Command is issued with the same option
3876 * (no overlay index or gateway-ip) which was
3877 * already configured. So nothing to do.
3878 * However, route-map may have been modified.
3879 * check if route-map has been modified.
3880 * If not, return an error
3886 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3887 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3888 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3889 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3892 * this is the case for first time ever configuration
3893 * adv ipv6 unicast is enabled for the first time.
3894 * So no need to reset any flag
3896 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3898 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3899 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3900 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3902 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3903 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3904 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3906 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3907 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3910 * This is modify case from gateway-ip
3911 * to no overlay index
3913 adv_flag_changed
= true;
3914 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3915 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3916 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3917 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3918 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3920 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3921 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3924 * This is modify case from no overlay index
3927 adv_flag_changed
= true;
3928 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3929 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3930 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3931 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3935 * Command is issued with the same option
3936 * (no overlay index or gateway-ip) which was
3937 * already configured. So nothing to do.
3938 * However, route-map may have been modified.
3939 * check if route-map has been modified.
3940 * If not, return an error
3947 if ((rmap_changed
) || (adv_flag_changed
)) {
3949 /* If either of these are changed, then FRR needs to
3950 * withdraw already advertised type5 routes.
3952 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3954 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3955 XFREE(MTYPE_ROUTE_MAP_NAME
,
3956 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3957 route_map_counter_decrement(
3958 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3959 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3960 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3965 /* set the route-map for advertise command */
3966 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3967 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3968 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3969 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3970 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3971 route_map_counter_increment(
3972 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3975 /* advertise type-5 routes */
3976 if (advertise_type5_routes(bgp_vrf
, afi
))
3977 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3981 DEFUN (no_bgp_evpn_advertise_type5
,
3982 no_bgp_evpn_advertise_type5_cmd
,
3983 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3985 "Advertise prefix routes\n"
3988 "route-map for filtering specific routes\n"
3989 "Name of the route map\n")
3991 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4000 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4001 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4003 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4005 "%% Only ipv4 or ipv6 address families are supported\n");
4009 if (safi
!= SAFI_UNICAST
) {
4011 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4015 if (afi
== AFI_IP
) {
4017 /* if we are not advertising ipv4 prefix as type-5
4020 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4021 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4022 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4023 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4024 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4025 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4027 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4028 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4032 /* if we are not advertising ipv6 prefix as type-5
4035 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4036 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4037 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4038 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4039 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4040 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4041 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4042 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4043 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4047 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4048 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4049 XFREE(MTYPE_ROUTE_MAP_NAME
,
4050 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4051 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4052 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4058 DEFPY (bgp_evpn_use_es_l3nhg
,
4059 bgp_evpn_use_es_l3nhg_cmd
,
4060 "[no$no] use-es-l3nhg",
4062 "use L3 nexthop group for host routes with ES destination\n")
4064 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4068 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4069 bgp_evpn_ead_evi_rx_disable_cmd
,
4070 "[no$no] disable-ead-evi-rx",
4072 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4074 bool ead_evi_rx
= no
? true :false;
4076 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4077 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4078 bgp_evpn_switch_ead_evi_rx();
4083 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4084 bgp_evpn_ead_evi_tx_disable_cmd
,
4085 "[no$no] disable-ead-evi-tx",
4087 "Don't advertise EAD-EVI for local ESs\n")
4089 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4093 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4094 bgp_evpn_enable_resolve_overlay_index_cmd
,
4095 "[no$no] enable-resolve-overlay-index",
4097 "Enable Recursive Resolution of type-5 route overlay index\n")
4099 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4101 if (bgp
!= bgp_get_evpn()) {
4102 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4106 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4110 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4111 bgp_evpn_advertise_pip_ip_mac_cmd
,
4112 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4114 "evpn system primary IP\n"
4117 MAC_STR MAC_STR MAC_STR
)
4119 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4120 struct bgp
*bgp_evpn
= NULL
;
4122 if (EVPN_ENABLED(bgp_vrf
)) {
4124 "This command is supported under L3VNI BGP EVPN VRF\n");
4125 return CMD_WARNING_CONFIG_FAILED
;
4127 bgp_evpn
= bgp_get_evpn();
4130 /* pip is already enabled */
4131 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4134 bgp_vrf
->evpn_info
->advertise_pip
= true;
4135 if (ip
.s_addr
!= INADDR_ANY
) {
4136 /* Already configured with same IP */
4137 if (IPV4_ADDR_SAME(&ip
,
4138 &bgp_vrf
->evpn_info
->pip_ip_static
))
4141 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4142 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4144 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4146 /* default instance router-id assignemt */
4148 bgp_vrf
->evpn_info
->pip_ip
=
4149 bgp_evpn
->router_id
;
4152 if (!is_zero_mac(&mac
->eth_addr
)) {
4153 /* Already configured with same MAC */
4154 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4155 &mac
->eth_addr
, ETH_ALEN
) == 0)
4158 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4159 &mac
->eth_addr
, ETH_ALEN
);
4160 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4161 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4164 /* Copy zebra sys mac */
4165 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4166 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4167 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4172 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4174 /* Disable PIP feature */
4175 bgp_vrf
->evpn_info
->advertise_pip
= false;
4176 /* copy anycast mac */
4177 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4178 &bgp_vrf
->rmac
, ETH_ALEN
);
4180 /* remove MAC-IP option retain PIP knob. */
4181 if ((ip
.s_addr
!= INADDR_ANY
) &&
4182 !IPV4_ADDR_SAME(&ip
,
4183 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4185 "%% BGP EVPN PIP IP does not match\n");
4186 return CMD_WARNING_CONFIG_FAILED
;
4189 if (!is_zero_mac(&mac
->eth_addr
) &&
4190 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4191 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4193 "%% BGP EVPN PIP MAC does not match\n");
4194 return CMD_WARNING_CONFIG_FAILED
;
4196 /* pip_rmac can carry vrr_rmac reset only if it matches
4197 * with static value.
4199 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4200 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4202 /* Copy zebra sys mac */
4204 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4205 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4206 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4209 /* copy anycast mac */
4210 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4211 &bgp_vrf
->rmac
, ETH_ALEN
);
4215 /* reset user configured sys MAC */
4216 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4217 /* reset user configured sys IP */
4218 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4219 /* Assign default PIP IP (bgp instance router-id) */
4221 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4223 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4226 if (is_evpn_enabled()) {
4227 struct listnode
*node
= NULL
;
4228 struct bgpevpn
*vpn
= NULL
;
4231 * At this point if bgp_evpn is NULL and evpn is enabled
4232 * something stupid has gone wrong
4236 update_advertise_vrf_routes(bgp_vrf
);
4238 /* Update (svi) type-2 routes */
4239 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4240 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4242 update_routes_for_vni(bgp_evpn
, vpn
);
4250 * Display VNI information - for all or a specific VNI
4252 DEFUN(show_bgp_l2vpn_evpn_vni
,
4253 show_bgp_l2vpn_evpn_vni_cmd
,
4254 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4263 struct bgp
*bgp_evpn
;
4267 json_object
*json
= NULL
;
4268 uint32_t num_l2vnis
= 0;
4269 uint32_t num_l3vnis
= 0;
4270 uint32_t num_vnis
= 0;
4271 struct listnode
*node
= NULL
;
4272 struct bgp
*bgp_temp
= NULL
;
4274 uj
= use_json(argc
, argv
);
4276 bgp_evpn
= bgp_get_evpn();
4280 if (!argv_find(argv
, argc
, "evpn", &idx
))
4284 json
= json_object_new_object();
4286 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4288 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4290 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4291 if (bgp_temp
->l3vni
)
4294 num_vnis
= num_l2vnis
+ num_l3vnis
;
4296 json_object_string_add(json
, "advertiseGatewayMacip",
4297 bgp_evpn
->advertise_gw_macip
4300 json_object_string_add(json
, "advertiseSviMacIp",
4301 bgp_evpn
->evpn_info
->advertise_svi_macip
4302 ? "Enabled" : "Disabled");
4303 json_object_string_add(json
, "advertiseAllVnis",
4304 is_evpn_enabled() ? "Enabled"
4306 json_object_string_add(
4308 bgp_evpn
->vxlan_flood_ctrl
==
4309 VXLAN_FLOOD_HEAD_END_REPL
4310 ? "Head-end replication"
4312 json_object_string_add(
4313 json
, "vxlanFlooding",
4314 bgp_evpn
->vxlan_flood_ctrl
==
4315 VXLAN_FLOOD_HEAD_END_REPL
4318 json_object_int_add(json
, "numVnis", num_vnis
);
4319 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4320 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4322 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4323 bgp_evpn
->advertise_gw_macip
? "Enabled"
4325 vty_out(vty
, "Advertise SVI Macip: %s\n",
4326 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4328 vty_out(vty
, "Advertise All VNI flag: %s\n",
4329 is_evpn_enabled() ? "Enabled" : "Disabled");
4330 vty_out(vty
, "BUM flooding: %s\n",
4331 bgp_evpn
->vxlan_flood_ctrl
==
4332 VXLAN_FLOOD_HEAD_END_REPL
4333 ? "Head-end replication"
4335 vty_out(vty
, "VXLAN flooding: %s\n",
4336 bgp_evpn
->vxlan_flood_ctrl
==
4337 VXLAN_FLOOD_HEAD_END_REPL
4340 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4341 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4343 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4347 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4350 /* Display specific VNI */
4351 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4352 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4356 vty_json(vty
, json
);
4361 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4362 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4363 "show bgp l2vpn evpn vni remote-ip-hash",
4371 struct bgp
*bgp_evpn
;
4374 bgp_evpn
= bgp_get_evpn();
4378 if (!argv_find(argv
, argc
, "evpn", &idx
))
4381 hash_iterate(bgp_evpn
->vnihash
,
4382 (void (*)(struct hash_bucket
*,
4383 void *))bgp_evpn_show_remote_ip_hash
,
4389 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4390 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4391 "show bgp l2vpn evpn vni-svi-hash",
4396 "Show vni-svi-hash\n")
4398 struct bgp
*bgp_evpn
;
4401 bgp_evpn
= bgp_get_evpn();
4405 if (!argv_find(argv
, argc
, "evpn", &idx
))
4408 hash_iterate(bgp_evpn
->vni_svi_hash
,
4409 (void (*)(struct hash_bucket
*,
4410 void *))bgp_evpn_show_vni_svi_hash
,
4416 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4417 show_bgp_l2vpn_evpn_es_evi_cmd
,
4418 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4424 "VxLAN Network Identifier\n"
4427 "Detailed information\n")
4430 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4432 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4437 DEFPY(show_bgp_l2vpn_evpn_es
,
4438 show_bgp_l2vpn_evpn_es_cmd
,
4439 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4444 "Ethernet Segment\n"
4446 "Detailed information\n"
4452 if (!str_to_esi(esi_str
, &esi
)) {
4453 vty_out(vty
, "%% Malformed ESI\n");
4456 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4459 bgp_evpn_es_show(vty
, uj
, !!detail
);
4465 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4466 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4467 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4468 "Ethernet Segment\n"
4474 if (!str_to_esi(esi_str
, &esi
)) {
4475 vty_out(vty
, "%% Malformed ESI\n");
4478 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4481 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4487 DEFPY(show_bgp_l2vpn_evpn_nh
,
4488 show_bgp_l2vpn_evpn_nh_cmd
,
4489 "show bgp l2vpn evpn next-hops [json$uj]",
4497 bgp_evpn_nh_show(vty
, uj
);
4503 * Display EVPN neighbor summary.
4505 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4506 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [<neighbor <A.B.C.D|X:X::X:X|WORD>|remote-as <(1-4294967295)|internal|external>>] [terse] [wide] [json]",
4509 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4510 "Summary of BGP neighbor status\n"
4511 "Show only sessions in Established state\n"
4512 "Show only sessions not in Established state\n"
4513 "Show only the specified neighbor session\n"
4514 "Neighbor to display information about\n"
4515 "Neighbor to display information about\n"
4516 "Neighbor on BGP configured interface\n"
4517 "Show only the specified remote AS sessions\n"
4519 "Internal (iBGP) AS sessions\n"
4520 "External (eBGP) AS sessions\n"
4521 "Shorten the information on BGP instances\n"
4522 "Increase table width for longer output\n" JSON_STR
)
4527 char *neighbor
= NULL
;
4528 as_t as
= 0; /* 0 means AS filter not set */
4529 int as_type
= AS_UNSPECIFIED
;
4530 uint16_t show_flags
= 0;
4532 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4533 vrf
= argv
[++idx_vrf
]->arg
;
4535 if (argv_find(argv
, argc
, "failed", &idx
))
4536 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4538 if (argv_find(argv
, argc
, "established", &idx
))
4539 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4542 if (argv_find(argv
, argc
, "neighbor", &idx
))
4543 neighbor
= argv
[idx
+ 1]->arg
;
4545 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4546 if (argv
[idx
+ 1]->arg
[0] == 'i')
4547 as_type
= AS_INTERNAL
;
4548 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4549 as_type
= AS_EXTERNAL
;
4551 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4554 if (argv_find(argv
, argc
, "terse", &idx
))
4555 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4557 if (argv_find(argv
, argc
, "wide", &idx
))
4558 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4560 if (use_json(argc
, argv
))
4561 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4563 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4564 as_type
, as
, show_flags
);
4567 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4571 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4572 /* Specific type is requested */
4573 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4574 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4575 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4576 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4577 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4578 *type
= BGP_EVPN_IMET_ROUTE
;
4579 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4580 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4581 *type
= BGP_EVPN_ES_ROUTE
;
4582 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4583 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4584 *type
= BGP_EVPN_AD_ROUTE
;
4585 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4586 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4587 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4596 * Display global EVPN routing table.
4598 DEFUN(show_bgp_l2vpn_evpn_route
,
4599 show_bgp_l2vpn_evpn_route_cmd
,
4600 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4606 "Display Detailed Information\n"
4608 EVPN_TYPE_ALL_LIST_HELP_STR
4615 json_object
*json
= NULL
;
4617 uj
= use_json(argc
, argv
);
4619 bgp
= bgp_get_evpn();
4624 json
= json_object_new_object();
4626 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4629 if (argv_find(argv
, argc
, "detail", &detail
))
4632 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4635 vty_json(vty
, json
);
4640 * Display global EVPN routing table for specific RD.
4642 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4643 show_bgp_l2vpn_evpn_route_rd_cmd
,
4644 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4650 EVPN_RT_DIST_HELP_STR
4651 EVPN_ASN_IP_HELP_STR
4652 "All VPN Route Distinguishers\n"
4654 EVPN_TYPE_ALL_LIST_HELP_STR
4659 struct prefix_rd prd
;
4662 json_object
*json
= NULL
;
4663 int idx_ext_community
= 0;
4666 bgp
= bgp_get_evpn();
4670 /* check if we need json output */
4671 uj
= use_json(argc
, argv
);
4673 json
= json_object_new_object();
4675 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4677 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4678 &idx_ext_community
)) {
4679 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4682 "%% Malformed Route Distinguisher\n");
4688 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4692 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4694 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4697 vty_json(vty
, json
);
4703 * Display global EVPN routing table for specific RD and MACIP.
4705 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4706 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4707 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4713 EVPN_RT_DIST_HELP_STR
4714 EVPN_ASN_IP_HELP_STR
4715 "All VPN Route Distinguishers\n"
4717 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4719 "IP address (IPv4 or IPv6)\n"
4724 struct prefix_rd prd
;
4727 int idx_ext_community
= 0;
4731 json_object
*json
= NULL
;
4734 memset(&mac
, 0, sizeof(struct ethaddr
));
4735 memset(&ip
, 0, sizeof(struct ipaddr
));
4737 bgp
= bgp_get_evpn();
4741 /* check if we need json output */
4742 uj
= use_json(argc
, argv
);
4744 json
= json_object_new_object();
4747 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4748 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4749 &idx_ext_community
)) {
4750 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4753 "%% Malformed Route Distinguisher\n");
4760 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4761 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4762 vty_out(vty
, "%% Malformed MAC address\n");
4767 /* get the ip if specified */
4768 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4769 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4770 vty_out(vty
, "%% Malformed IP address\n");
4776 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4778 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4781 vty_json(vty
, json
);
4786 /* Display per ESI routing table */
4787 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4788 show_bgp_l2vpn_evpn_route_esi_cmd
,
4789 "show bgp l2vpn evpn route esi ESI [json]",
4795 "Ethernet Segment Identifier\n"
4801 struct bgp
*bgp
= NULL
;
4802 json_object
*json
= NULL
;
4804 memset(&esi
, 0, sizeof(esi
));
4805 bgp
= bgp_get_evpn();
4809 uj
= use_json(argc
, argv
);
4811 json
= json_object_new_object();
4813 /* get the ESI - ESI-ID is at argv[6] */
4814 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4815 vty_out(vty
, "%% Malformed ESI\n");
4819 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4822 vty_json(vty
, json
);
4829 * Display per-VNI EVPN routing table.
4831 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4832 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4838 "VXLAN Network Identifier\n"
4841 EVPN_TYPE_1_HELP_STR
4842 EVPN_TYPE_1_HELP_STR
4843 EVPN_TYPE_2_HELP_STR
4844 EVPN_TYPE_2_HELP_STR
4845 EVPN_TYPE_3_HELP_STR
4846 EVPN_TYPE_3_HELP_STR
4848 "Remote VTEP IP address\n"
4853 struct in_addr vtep_ip
;
4858 json_object
*json
= NULL
;
4860 bgp
= bgp_get_evpn();
4864 /* check if we need json output */
4865 uj
= use_json(argc
, argv
);
4867 json
= json_object_new_object();
4869 if (!argv_find(argv
, argc
, "evpn", &idx
))
4874 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4876 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4879 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4880 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4881 vty_out(vty
, "%% Malformed VTEP IP address\n");
4886 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4889 vty_json(vty
, json
);
4895 * Display per-VNI EVPN routing table for specific MACIP.
4897 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4898 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4899 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4905 "VXLAN Network Identifier\n"
4908 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4910 "IP address (IPv4 or IPv6)\n"
4919 json_object
*json
= NULL
;
4921 bgp
= bgp_get_evpn();
4925 /* check if we need json output */
4926 uj
= use_json(argc
, argv
);
4928 json
= json_object_new_object();
4930 if (!argv_find(argv
, argc
, "evpn", &idx
))
4934 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4937 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4938 vty_out(vty
, "%% Malformed MAC address\n");
4943 memset(&ip
, 0, sizeof(ip
));
4944 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4946 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4947 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4948 vty_out(vty
, "%% Malformed IP address\n");
4953 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4956 vty_json(vty
, json
);
4962 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4964 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4965 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4966 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4972 "VXLAN Network Identifier\n"
4974 EVPN_TYPE_3_HELP_STR
4975 "Originating Router IP address\n"
4981 struct in_addr orig_ip
;
4984 json_object
*json
= NULL
;
4986 bgp
= bgp_get_evpn();
4990 /* check if we need json output */
4991 uj
= use_json(argc
, argv
);
4993 json
= json_object_new_object();
4995 if (!argv_find(argv
, argc
, "evpn", &idx
))
4999 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5002 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5004 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5008 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5011 vty_json(vty
, json
);
5017 * Display per-VNI EVPN routing table - for all VNIs.
5019 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5020 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5021 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5027 "VXLAN Network Identifier\n"
5029 "Print Detailed Output\n"
5031 "Remote VTEP IP address\n"
5035 struct in_addr vtep_ip
;
5038 json_object
*json
= NULL
;
5039 /* Detail Adjust. Adjust indexes according to detail option */
5042 bgp
= bgp_get_evpn();
5046 /* check if we need json output */
5047 uj
= use_json(argc
, argv
);
5049 json
= json_object_new_object();
5051 if (!argv_find(argv
, argc
, "evpn", &idx
))
5054 if (argv_find(argv
, argc
, "detail", &da
))
5057 /* vtep-ip position depends on detail option */
5059 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5061 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5062 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5063 vty_out(vty
, "%% Malformed VTEP IP address\n");
5068 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5071 vty_json(vty
, json
);
5077 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5078 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5079 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5080 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5081 "EVPN route information\n"
5082 "MAC IP routes in the EVI tables linked to the ES\n"
5084 "Detailed information\n" JSON_STR
)
5088 json_object
*json
= NULL
;
5091 if (!str_to_esi(esi_str
, &esi
)) {
5092 vty_out(vty
, "%% Malformed ESI\n");
5101 json
= json_object_new_object();
5102 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5104 vty_json(vty
, json
);
5110 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5111 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5112 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5113 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5114 "EVPN route information\n"
5115 "MAC IP routes in the global table linked to the ES\n"
5117 "Detailed information\n" JSON_STR
)
5121 json_object
*json
= NULL
;
5124 if (!str_to_esi(esi_str
, &esi
)) {
5125 vty_out(vty
, "%% Malformed ESI\n");
5134 json
= json_object_new_object();
5135 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5137 vty_json(vty
, json
);
5143 * Display EVPN import route-target hash table
5145 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5146 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5147 "show bgp l2vpn evpn vrf-import-rt [json]",
5152 "Show vrf import route target\n"
5156 struct bgp
*bgp_evpn
= NULL
;
5157 json_object
*json
= NULL
;
5159 bgp_evpn
= bgp_get_evpn();
5163 uj
= use_json(argc
, argv
);
5165 json
= json_object_new_object();
5167 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5170 vty_json(vty
, json
);
5176 * Display EVPN import route-target hash table
5178 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5179 show_bgp_l2vpn_evpn_import_rt_cmd
,
5180 "show bgp l2vpn evpn import-rt [json]",
5185 "Show import route target\n"
5190 json_object
*json
= NULL
;
5192 bgp
= bgp_get_evpn();
5196 uj
= use_json(argc
, argv
);
5198 json
= json_object_new_object();
5200 evpn_show_import_rts(vty
, bgp
, json
);
5203 vty_json(vty
, json
);
5208 DEFPY_HIDDEN(test_es_add
,
5210 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5213 "Ethernet-segment\n"
5214 "Ethernet-Segment Identifier\n"
5222 struct in_addr vtep_ip
;
5225 bgp
= bgp_get_evpn();
5227 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5231 if (!str_to_esi(esi_str
, &esi
)) {
5232 vty_out(vty
, "%% Malformed ESI\n");
5237 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5239 vty_out(vty
, "%% Failed to delete ES\n");
5243 if (state_str
&& !strcmp(state_str
, "up"))
5247 vtep_ip
= bgp
->router_id
;
5249 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5250 EVPN_MH_DF_PREF_MIN
, false);
5252 vty_out(vty
, "%% Failed to add ES\n");
5259 DEFPY_HIDDEN(test_es_vni_add
,
5260 test_es_vni_add_cmd
,
5261 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5264 "Ethernet-segment\n"
5265 "Ethernet-Segment Identifier\n"
5274 bgp
= bgp_get_evpn();
5276 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5280 if (!str_to_esi(esi_str
, &esi
)) {
5281 vty_out(vty
, "%% Malformed ESI\n");
5286 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5288 vty_out(vty
, "%% Failed to deref ES VNI\n");
5292 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5294 vty_out(vty
, "%% Failed to ref ES VNI\n");
5301 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5302 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5306 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5307 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5308 "Summary of BGP neighbor status\n" JSON_STR
)
5310 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5311 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5312 SHOW_STR BGP_STR EVPN_HELP_STR
5314 "Display Detailed Information\n"
5316 EVPN_TYPE_2_HELP_STR
5317 EVPN_TYPE_2_HELP_STR
5318 EVPN_TYPE_3_HELP_STR
5319 EVPN_TYPE_3_HELP_STR
)
5322 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5323 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5324 SHOW_STR BGP_STR EVPN_HELP_STR
5326 EVPN_RT_DIST_HELP_STR
5327 EVPN_ASN_IP_HELP_STR
5329 EVPN_TYPE_2_HELP_STR
5330 EVPN_TYPE_2_HELP_STR
5331 EVPN_TYPE_3_HELP_STR
5332 EVPN_TYPE_3_HELP_STR
)
5335 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5336 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5337 SHOW_STR BGP_STR EVPN_HELP_STR
5339 EVPN_RT_DIST_HELP_STR
5340 EVPN_ASN_IP_HELP_STR
5342 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5344 "IP address (IPv4 or IPv6)\n")
5347 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5348 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5349 SHOW_STR BGP_STR EVPN_HELP_STR
5351 "VXLAN Network Identifier\n"
5354 EVPN_TYPE_2_HELP_STR
5355 EVPN_TYPE_2_HELP_STR
5356 EVPN_TYPE_3_HELP_STR
5357 EVPN_TYPE_3_HELP_STR
5359 "Remote VTEP IP address\n")
5361 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5362 show_bgp_evpn_route_vni_macip_cmd
,
5363 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5364 SHOW_STR BGP_STR EVPN_HELP_STR
5366 "VXLAN Network Identifier\n"
5369 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5371 "IP address (IPv4 or IPv6)\n")
5373 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5374 show_bgp_evpn_route_vni_multicast_cmd
,
5375 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5376 SHOW_STR BGP_STR EVPN_HELP_STR
5378 "VXLAN Network Identifier\n"
5380 EVPN_TYPE_3_HELP_STR
5381 "Originating Router IP address\n")
5383 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5384 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5385 SHOW_STR BGP_STR EVPN_HELP_STR
5387 "VXLAN Network Identifier\n"
5389 "Print Detailed Output\n"
5391 "Remote VTEP IP address\n")
5393 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5394 "show bgp evpn import-rt",
5395 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5397 DEFUN_NOSH (bgp_evpn_vni
,
5399 "vni " CMD_VNI_RANGE
,
5400 "VXLAN Network Identifier\n"
5404 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5405 struct bgpevpn
*vpn
;
5410 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5412 /* Create VNI, or mark as configured. */
5413 vpn
= evpn_create_update_vni(bgp
, vni
);
5415 vty_out(vty
, "%% Failed to create VNI \n");
5419 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5423 DEFUN (no_bgp_evpn_vni
,
5424 no_bgp_evpn_vni_cmd
,
5425 "no vni " CMD_VNI_RANGE
,
5427 "VXLAN Network Identifier\n"
5431 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5432 struct bgpevpn
*vpn
;
5437 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5439 /* Check if we should disallow. */
5440 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5442 vty_out(vty
, "%% Specified VNI does not exist\n");
5445 if (!is_vni_configured(vpn
)) {
5446 vty_out(vty
, "%% Specified VNI is not configured\n");
5450 evpn_delete_vni(bgp
, vpn
);
5454 DEFUN_NOSH (exit_vni
,
5457 "Exit from VNI mode\n")
5459 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5460 vty
->node
= BGP_EVPN_NODE
;
5464 DEFUN (bgp_evpn_vrf_rd
,
5465 bgp_evpn_vrf_rd_cmd
,
5466 "rd ASN:NN_OR_IP-ADDRESS:NN",
5467 EVPN_RT_DIST_HELP_STR
5468 EVPN_ASN_IP_HELP_STR
)
5471 struct prefix_rd prd
;
5472 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5477 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5479 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5483 /* If same as existing value, there is nothing more to do. */
5484 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5487 /* Configure or update the RD. */
5488 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5492 DEFUN (no_bgp_evpn_vrf_rd
,
5493 no_bgp_evpn_vrf_rd_cmd
,
5494 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5496 EVPN_RT_DIST_HELP_STR
5497 EVPN_ASN_IP_HELP_STR
)
5500 struct prefix_rd prd
;
5501 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5506 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5508 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5512 /* Check if we should disallow. */
5513 if (!is_vrf_rd_configured(bgp_vrf
)) {
5514 vty_out(vty
, "%% RD is not configured for this VRF\n");
5518 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5520 "%% RD specified does not match configuration for this VRF\n");
5524 evpn_unconfigure_vrf_rd(bgp_vrf
);
5528 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5529 no_bgp_evpn_vrf_rd_without_val_cmd
,
5532 EVPN_RT_DIST_HELP_STR
)
5534 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5539 /* Check if we should disallow. */
5540 if (!is_vrf_rd_configured(bgp_vrf
)) {
5541 vty_out(vty
, "%% RD is not configured for this VRF\n");
5545 evpn_unconfigure_vrf_rd(bgp_vrf
);
5549 DEFUN (bgp_evpn_vni_rd
,
5550 bgp_evpn_vni_rd_cmd
,
5551 "rd ASN:NN_OR_IP-ADDRESS:NN",
5552 EVPN_RT_DIST_HELP_STR
5553 EVPN_ASN_IP_HELP_STR
)
5555 struct prefix_rd prd
;
5556 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5557 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5563 if (!EVPN_ENABLED(bgp
)) {
5565 "This command is only supported under EVPN VRF\n");
5569 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5571 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5575 /* If same as existing value, there is nothing more to do. */
5576 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5579 /* Configure or update the RD. */
5580 evpn_configure_rd(bgp
, vpn
, &prd
);
5584 DEFUN (no_bgp_evpn_vni_rd
,
5585 no_bgp_evpn_vni_rd_cmd
,
5586 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5588 EVPN_RT_DIST_HELP_STR
5589 EVPN_ASN_IP_HELP_STR
)
5591 struct prefix_rd prd
;
5592 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5593 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5599 if (!EVPN_ENABLED(bgp
)) {
5601 "This command is only supported under EVPN VRF\n");
5605 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5607 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5611 /* Check if we should disallow. */
5612 if (!is_rd_configured(vpn
)) {
5613 vty_out(vty
, "%% RD is not configured for this VNI\n");
5617 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5619 "%% RD specified does not match configuration for this VNI\n");
5623 evpn_unconfigure_rd(bgp
, vpn
);
5627 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5628 no_bgp_evpn_vni_rd_without_val_cmd
,
5631 EVPN_RT_DIST_HELP_STR
)
5633 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5634 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5639 if (!EVPN_ENABLED(bgp
)) {
5641 "This command is only supported under EVPN VRF\n");
5645 /* Check if we should disallow. */
5646 if (!is_rd_configured(vpn
)) {
5647 vty_out(vty
, "%% RD is not configured for this VNI\n");
5651 evpn_unconfigure_rd(bgp
, vpn
);
5656 * Loop over all extended-communities in the route-target list rtl and
5657 * return 1 if we find ecomtarget
5659 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
5660 struct ecommunity
*ecomtarget
)
5662 struct listnode
*node
;
5663 struct ecommunity
*ecom
;
5665 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
5666 if (ecommunity_match(ecom
, ecomtarget
))
5674 * L3 RT version of above.
5676 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
5677 struct ecommunity
*ecomtarget
)
5679 struct listnode
*node
;
5680 struct vrf_route_target
*l3rt
;
5682 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
5683 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
5690 /* display L3VNI related info for a VRF instance */
5691 DEFUN (show_bgp_vrf_l3vni_info
,
5692 show_bgp_vrf_l3vni_info_cmd
,
5693 "show bgp vrf VRFNAME vni [json]",
5701 char buf
[ETHER_ADDR_STRLEN
];
5703 const char *name
= NULL
;
5704 struct bgp
*bgp
= NULL
;
5705 struct listnode
*node
= NULL
;
5706 struct bgpevpn
*vpn
= NULL
;
5707 struct vrf_route_target
*l3rt
;
5708 json_object
*json
= NULL
;
5709 json_object
*json_vnis
= NULL
;
5710 json_object
*json_export_rts
= NULL
;
5711 json_object
*json_import_rts
= NULL
;
5712 bool uj
= use_json(argc
, argv
);
5715 json
= json_object_new_object();
5716 json_vnis
= json_object_new_array();
5717 json_export_rts
= json_object_new_array();
5718 json_import_rts
= json_object_new_array();
5721 name
= argv
[idx_vrf
]->arg
;
5722 bgp
= bgp_lookup_by_name(name
);
5723 if (strmatch(name
, VRF_DEFAULT_NAME
))
5724 bgp
= bgp_get_default();
5728 vty_out(vty
, "BGP instance for VRF %s not found\n",
5731 json_object_string_add(json
, "warning",
5732 "BGP instance not found");
5733 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5734 json_object_free(json
);
5740 vty_out(vty
, "BGP VRF: %s\n", name
);
5741 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5742 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5743 vty_out(vty
, " Rmac: %s\n",
5744 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5745 vty_out(vty
, " VNI Filter: %s\n",
5746 CHECK_FLAG(bgp
->vrf_flags
,
5747 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5748 ? "prefix-routes-only"
5750 vty_out(vty
, " L2-VNI List:\n");
5752 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5753 vty_out(vty
, "%u ", vpn
->vni
);
5755 vty_out(vty
, " Export-RTs:\n");
5757 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
5758 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
5760 vty_out(vty
, " Import-RTs:\n");
5762 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
5763 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
5765 vty_out(vty
, " RD: %pRD\n", &bgp
->vrf_prd
);
5767 json_object_string_add(json
, "vrf", name
);
5768 json_object_string_addf(json
, "local-ip", "%pI4",
5769 &bgp
->originator_ip
);
5770 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5771 json_object_string_add(
5773 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5774 json_object_string_add(
5776 CHECK_FLAG(bgp
->vrf_flags
,
5777 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5778 ? "prefix-routes-only"
5780 /* list of l2vnis */
5781 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5782 json_object_array_add(json_vnis
,
5783 json_object_new_int(vpn
->vni
));
5784 json_object_object_add(json
, "l2vnis", json_vnis
);
5787 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
5788 json_object_array_add(
5790 json_object_new_string(
5791 ecommunity_str(l3rt
->ecom
)));
5792 json_object_object_add(json
, "export-rts", json_export_rts
);
5795 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
5796 json_object_array_add(
5798 json_object_new_string(
5799 ecommunity_str(l3rt
->ecom
)));
5800 json_object_object_add(json
, "import-rts", json_import_rts
);
5801 json_object_string_addf(json
, "rd", "%pRD", &bgp
->vrf_prd
);
5805 vty_json(vty
, json
);
5809 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
5812 /* Do nothing if we already have this route-target */
5814 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
5816 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
5821 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
5823 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
5831 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
5833 /* Verify we already have this route-target */
5835 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
5839 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
5841 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
5845 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
5851 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
5852 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
5855 int ret
= CMD_SUCCESS
;
5856 bool is_wildcard
= false;
5857 struct ecommunity
*ecom
= NULL
;
5859 for (int i
= rt_idx
; i
< argc
; i
++) {
5860 is_wildcard
= false;
5863 * Special handling for wildcard '*' here.
5865 * Let's just convert it to 0 here so we dont have to modify
5866 * the ecommunity parser.
5868 if ((argv
[i
]->arg
)[0] == '*') {
5869 (argv
[i
]->arg
)[0] = '0';
5873 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
5876 /* Put it back as was */
5878 (argv
[i
]->arg
)[0] = '*';
5881 vty_out(vty
, "%% Malformed Route Target list\n");
5886 ecommunity_str(ecom
);
5889 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
5891 "%% RT specified already configured for this VRF: %s\n",
5893 ecommunity_free(&ecom
);
5898 if (del_rt(bgp
, ecom
, is_import
) != 0) {
5900 "%% RT specified does not match configuration for this VRF: %s\n",
5905 ecommunity_free(&ecom
);
5912 /* import/export rt for l3vni-vrf */
5913 DEFUN (bgp_evpn_vrf_rt
,
5914 bgp_evpn_vrf_rt_cmd
,
5915 "route-target <both|import|export> RTLIST...",
5917 "import and export\n"
5920 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
5922 int ret
= CMD_SUCCESS
;
5923 int tmp_ret
= CMD_SUCCESS
;
5925 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5928 return CMD_WARNING_CONFIG_FAILED
;
5930 if (!strcmp(argv
[1]->arg
, "import"))
5931 rt_type
= RT_TYPE_IMPORT
;
5932 else if (!strcmp(argv
[1]->arg
, "export"))
5933 rt_type
= RT_TYPE_EXPORT
;
5934 else if (!strcmp(argv
[1]->arg
, "both"))
5935 rt_type
= RT_TYPE_BOTH
;
5937 vty_out(vty
, "%% Invalid Route Target type\n");
5938 return CMD_WARNING_CONFIG_FAILED
;
5941 if (strmatch(argv
[2]->arg
, "auto")) {
5942 vty_out(vty
, "%% `auto` cannot be configured via list\n");
5943 return CMD_WARNING_CONFIG_FAILED
;
5946 if (rt_type
!= RT_TYPE_IMPORT
) {
5947 for (int i
= 2; i
< argc
; i
++) {
5948 if ((argv
[i
]->arg
)[0] == '*') {
5950 "%% Wildcard '*' only applicable for import\n");
5951 return CMD_WARNING_CONFIG_FAILED
;
5956 /* Add/update the import route-target */
5957 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
5958 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
5960 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
5963 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
5964 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
5966 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
5972 DEFPY (bgp_evpn_vrf_rt_auto
,
5973 bgp_evpn_vrf_rt_auto_cmd
,
5974 "route-target <both|import|export>$type auto",
5976 "import and export\n"
5979 "Automatically derive route target\n")
5981 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5985 return CMD_WARNING_CONFIG_FAILED
;
5987 if (strmatch(type
, "import"))
5988 rt_type
= RT_TYPE_IMPORT
;
5989 else if (strmatch(type
, "export"))
5990 rt_type
= RT_TYPE_EXPORT
;
5991 else if (strmatch(type
, "both"))
5992 rt_type
= RT_TYPE_BOTH
;
5994 vty_out(vty
, "%% Invalid Route Target type\n");
5995 return CMD_WARNING_CONFIG_FAILED
;
5998 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
5999 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
6001 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6002 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6007 DEFUN (no_bgp_evpn_vrf_rt
,
6008 no_bgp_evpn_vrf_rt_cmd
,
6009 "no route-target <both|import|export> RTLIST...",
6012 "import and export\n"
6015 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6017 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6018 int ret
= CMD_SUCCESS
;
6019 int tmp_ret
= CMD_SUCCESS
;
6023 return CMD_WARNING_CONFIG_FAILED
;
6025 if (!strcmp(argv
[2]->arg
, "import"))
6026 rt_type
= RT_TYPE_IMPORT
;
6027 else if (!strcmp(argv
[2]->arg
, "export"))
6028 rt_type
= RT_TYPE_EXPORT
;
6029 else if (!strcmp(argv
[2]->arg
, "both"))
6030 rt_type
= RT_TYPE_BOTH
;
6032 vty_out(vty
, "%% Invalid Route Target type\n");
6033 return CMD_WARNING_CONFIG_FAILED
;
6036 if (!strcmp(argv
[3]->arg
, "auto")) {
6037 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6038 return CMD_WARNING_CONFIG_FAILED
;
6041 if (rt_type
== RT_TYPE_IMPORT
) {
6042 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6044 "%% Import RT is not configured for this VRF\n");
6045 return CMD_WARNING_CONFIG_FAILED
;
6047 } else if (rt_type
== RT_TYPE_EXPORT
) {
6048 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6050 "%% Export RT is not configured for this VRF\n");
6051 return CMD_WARNING_CONFIG_FAILED
;
6053 } else if (rt_type
== RT_TYPE_BOTH
) {
6054 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6055 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6057 "%% Import/Export RT is not configured for this VRF\n");
6058 return CMD_WARNING_CONFIG_FAILED
;
6062 if (rt_type
!= RT_TYPE_IMPORT
) {
6063 for (int i
= 3; i
< argc
; i
++) {
6064 if ((argv
[i
]->arg
)[0] == '*') {
6066 "%% Wildcard '*' only applicable for import\n");
6067 return CMD_WARNING_CONFIG_FAILED
;
6072 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6073 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6075 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6078 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6079 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6081 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6087 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6088 no_bgp_evpn_vrf_rt_auto_cmd
,
6089 "no route-target <both|import|export>$type auto",
6092 "import and export\n"
6095 "Automatically derive route target\n")
6097 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6101 return CMD_WARNING_CONFIG_FAILED
;
6103 if (strmatch(type
, "import"))
6104 rt_type
= RT_TYPE_IMPORT
;
6105 else if (strmatch(type
, "export"))
6106 rt_type
= RT_TYPE_EXPORT
;
6107 else if (strmatch(type
, "both"))
6108 rt_type
= RT_TYPE_BOTH
;
6110 vty_out(vty
, "%% Invalid Route Target type\n");
6111 return CMD_WARNING_CONFIG_FAILED
;
6114 if (rt_type
== RT_TYPE_IMPORT
) {
6115 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6117 "%% Import AUTO RT is not configured for this VRF\n");
6118 return CMD_WARNING_CONFIG_FAILED
;
6120 } else if (rt_type
== RT_TYPE_EXPORT
) {
6121 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6123 "%% Export AUTO RT is not configured for this VRF\n");
6124 return CMD_WARNING_CONFIG_FAILED
;
6126 } else if (rt_type
== RT_TYPE_BOTH
) {
6127 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6128 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6130 "%% Import/Export AUTO RT is not configured for this VRF\n");
6131 return CMD_WARNING_CONFIG_FAILED
;
6135 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6136 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6138 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6139 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6144 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6145 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6147 "EAD ES fragment config\n"
6148 "EVIs per-fragment\n"
6151 bgp_mh_info
->evi_per_es_frag
=
6152 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6157 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6158 "ead-es-route-target export RT",
6159 "EAD ES Route Target\n"
6161 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6163 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6164 struct ecommunity
*ecomadd
= NULL
;
6169 if (!EVPN_ENABLED(bgp
)) {
6170 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6174 /* Add/update the export route-target */
6175 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6177 vty_out(vty
, "%% Malformed Route Target list\n");
6180 ecommunity_str(ecomadd
);
6182 /* Do nothing if we already have this export route-target */
6183 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6185 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6190 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6191 "no ead-es-route-target export RT",
6193 "EAD ES Route Target\n"
6194 "export\n" EVPN_ASN_IP_HELP_STR
)
6196 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6197 struct ecommunity
*ecomdel
= NULL
;
6202 if (!EVPN_ENABLED(bgp
)) {
6203 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6207 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6209 vty_out(vty
, "%% Malformed Route Target list\n");
6212 ecommunity_str(ecomdel
);
6214 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6216 ecommunity_free(&ecomdel
);
6218 "%% RT specified does not match EAD-ES RT configuration\n");
6221 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6226 DEFUN (bgp_evpn_vni_rt
,
6227 bgp_evpn_vni_rt_cmd
,
6228 "route-target <both|import|export> RT",
6230 "import and export\n"
6233 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6235 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6236 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6238 struct ecommunity
*ecomadd
= NULL
;
6243 if (!EVPN_ENABLED(bgp
)) {
6245 "This command is only supported under EVPN VRF\n");
6249 if (!strcmp(argv
[1]->text
, "import"))
6250 rt_type
= RT_TYPE_IMPORT
;
6251 else if (!strcmp(argv
[1]->text
, "export"))
6252 rt_type
= RT_TYPE_EXPORT
;
6253 else if (!strcmp(argv
[1]->text
, "both"))
6254 rt_type
= RT_TYPE_BOTH
;
6256 vty_out(vty
, "%% Invalid Route Target type\n");
6260 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6262 vty_out(vty
, "%% Malformed Route Target list\n");
6265 ecommunity_str(ecomadd
);
6267 /* Add/update the import route-target */
6268 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6269 /* Do nothing if we already have this import route-target */
6270 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6271 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6274 /* Add/update the export route-target */
6275 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6276 /* Do nothing if we already have this export route-target */
6277 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6278 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6284 DEFUN (no_bgp_evpn_vni_rt
,
6285 no_bgp_evpn_vni_rt_cmd
,
6286 "no route-target <both|import|export> RT",
6289 "import and export\n"
6292 EVPN_ASN_IP_HELP_STR
)
6294 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6295 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6296 int rt_type
, found_ecomdel
;
6297 struct ecommunity
*ecomdel
= NULL
;
6302 if (!EVPN_ENABLED(bgp
)) {
6304 "This command is only supported under EVPN VRF\n");
6308 if (!strcmp(argv
[2]->text
, "import"))
6309 rt_type
= RT_TYPE_IMPORT
;
6310 else if (!strcmp(argv
[2]->text
, "export"))
6311 rt_type
= RT_TYPE_EXPORT
;
6312 else if (!strcmp(argv
[2]->text
, "both"))
6313 rt_type
= RT_TYPE_BOTH
;
6315 vty_out(vty
, "%% Invalid Route Target type\n");
6319 /* The user did "no route-target import", check to see if there are any
6320 * import route-targets configured. */
6321 if (rt_type
== RT_TYPE_IMPORT
) {
6322 if (!is_import_rt_configured(vpn
)) {
6324 "%% Import RT is not configured for this VNI\n");
6327 } else if (rt_type
== RT_TYPE_EXPORT
) {
6328 if (!is_export_rt_configured(vpn
)) {
6330 "%% Export RT is not configured for this VNI\n");
6333 } else if (rt_type
== RT_TYPE_BOTH
) {
6334 if (!is_import_rt_configured(vpn
)
6335 && !is_export_rt_configured(vpn
)) {
6337 "%% Import/Export RT is not configured for this VNI\n");
6342 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6344 vty_out(vty
, "%% Malformed Route Target list\n");
6347 ecommunity_str(ecomdel
);
6349 if (rt_type
== RT_TYPE_IMPORT
) {
6350 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6351 ecommunity_free(&ecomdel
);
6353 "%% RT specified does not match configuration for this VNI\n");
6356 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6357 } else if (rt_type
== RT_TYPE_EXPORT
) {
6358 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6359 ecommunity_free(&ecomdel
);
6361 "%% RT specified does not match configuration for this VNI\n");
6364 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6365 } else if (rt_type
== RT_TYPE_BOTH
) {
6368 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6369 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6373 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6374 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6378 if (!found_ecomdel
) {
6379 ecommunity_free(&ecomdel
);
6381 "%% RT specified does not match configuration for this VNI\n");
6389 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6390 no_bgp_evpn_vni_rt_without_val_cmd
,
6391 "no route-target <import|export>",
6397 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6398 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6404 if (!EVPN_ENABLED(bgp
)) {
6406 "This command is only supported under EVPN VRF\n");
6410 if (!strcmp(argv
[2]->text
, "import")) {
6411 rt_type
= RT_TYPE_IMPORT
;
6412 } else if (!strcmp(argv
[2]->text
, "export")) {
6413 rt_type
= RT_TYPE_EXPORT
;
6415 vty_out(vty
, "%% Invalid Route Target type\n");
6419 /* Check if we should disallow. */
6420 if (rt_type
== RT_TYPE_IMPORT
) {
6421 if (!is_import_rt_configured(vpn
)) {
6423 "%% Import RT is not configured for this VNI\n");
6427 if (!is_export_rt_configured(vpn
)) {
6429 "%% Export RT is not configured for this VNI\n");
6434 /* Unconfigure the RT. */
6435 if (rt_type
== RT_TYPE_IMPORT
)
6436 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6438 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6442 static int vni_cmp(const void **a
, const void **b
)
6444 const struct bgpevpn
*first
= *a
;
6445 const struct bgpevpn
*secnd
= *b
;
6447 return secnd
->vni
- first
->vni
;
6451 * Output EVPN configuration information.
6453 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6456 char buf2
[INET6_ADDRSTRLEN
];
6458 if (bgp
->advertise_all_vni
)
6459 vty_out(vty
, " advertise-all-vni\n");
6461 if (hashcount(bgp
->vnihash
)) {
6462 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6463 struct listnode
*ln
;
6464 struct bgpevpn
*data
;
6466 list_sort(vnilist
, vni_cmp
);
6467 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6468 write_vni_config(vty
, data
);
6470 list_delete(&vnilist
);
6473 if (bgp
->advertise_autort_rfc8365
)
6474 vty_out(vty
, " autort rfc8365-compatible\n");
6476 if (bgp
->advertise_gw_macip
)
6477 vty_out(vty
, " advertise-default-gw\n");
6479 if (bgp
->evpn_info
->advertise_svi_macip
)
6480 vty_out(vty
, " advertise-svi-ip\n");
6482 if (bgp
->resolve_overlay_index
)
6483 vty_out(vty
, " enable-resolve-overlay-index\n");
6485 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
6486 vty_out(vty
, " ead-es-frag evi-limit %u\n",
6487 bgp_mh_info
->evi_per_es_frag
);
6489 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6490 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6491 if (bgp_mh_info
->host_routes_use_l3nhg
)
6492 vty_out(vty
, " use-es-l3nhg\n");
6494 vty_out(vty
, " no use-es-l3nhg\n");
6497 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6498 if (bgp_mh_info
->ead_evi_rx
)
6499 vty_out(vty
, " no disable-ead-evi-rx\n");
6501 vty_out(vty
, " disable-ead-evi-rx\n");
6504 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6505 if (bgp_mh_info
->ead_evi_tx
)
6506 vty_out(vty
, " no disable-ead-evi-tx\n");
6508 vty_out(vty
, " disable-ead-evi-tx\n");
6511 if (!bgp
->evpn_info
->dup_addr_detect
)
6512 vty_out(vty
, " no dup-addr-detection\n");
6514 if (bgp
->evpn_info
->dad_max_moves
!=
6515 EVPN_DAD_DEFAULT_MAX_MOVES
||
6516 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6517 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6518 bgp
->evpn_info
->dad_max_moves
,
6519 bgp
->evpn_info
->dad_time
);
6521 if (bgp
->evpn_info
->dad_freeze
) {
6522 if (bgp
->evpn_info
->dad_freeze_time
)
6524 " dup-addr-detection freeze %u\n",
6525 bgp
->evpn_info
->dad_freeze_time
);
6528 " dup-addr-detection freeze permanent\n");
6531 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6532 vty_out(vty
, " flooding disable\n");
6534 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6535 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6536 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6537 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6538 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6541 " advertise ipv4 unicast\n");
6542 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6543 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6544 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6546 " advertise ipv4 unicast gateway-ip route-map %s\n",
6547 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6549 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6552 /* EAD ES export route-target */
6553 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
6554 struct ecommunity
*ecom
;
6556 struct listnode
*node
;
6558 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
6561 ecom_str
= ecommunity_ecom2str(
6562 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6563 vty_out(vty
, " ead-es-route-target export %s\n",
6565 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6569 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6570 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6571 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6573 " advertise ipv6 unicast route-map %s\n",
6574 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6577 " advertise ipv6 unicast\n");
6578 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6579 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6580 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6582 " advertise ipv6 unicast gateway-ip route-map %s\n",
6583 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6585 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6588 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6589 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6590 vty_out(vty
, " default-originate ipv4\n");
6592 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6593 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6594 vty_out(vty
, " default-originate ipv6\n");
6596 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6597 if (!bgp
->evpn_info
->advertise_pip
)
6598 vty_out(vty
, " no advertise-pip\n");
6599 if (bgp
->evpn_info
->advertise_pip
) {
6600 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6602 vty_out(vty
, " advertise-pip ip %s",
6604 &bgp
->evpn_info
->pip_ip_static
,
6605 buf2
, INET_ADDRSTRLEN
));
6607 bgp
->evpn_info
->pip_rmac_static
))) {
6608 char buf
[ETHER_ADDR_STRLEN
];
6610 vty_out(vty
, " mac %s",
6620 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6621 vty_out(vty
, " rd %pRD\n", &bgp
->vrf_prd
);
6623 /* import route-target */
6624 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6626 struct listnode
*node
, *nnode
;
6627 struct vrf_route_target
*l3rt
;
6629 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6632 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
6635 ecom_str
= ecommunity_ecom2str(
6636 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6638 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
6639 char *vni_str
= NULL
;
6641 vni_str
= strchr(ecom_str
, ':');
6644 continue; /* This should never happen */
6646 /* Move pointer to vni */
6649 vty_out(vty
, " route-target import *:%s\n",
6653 vty_out(vty
, " route-target import %s\n",
6656 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6660 /* import route-target auto */
6661 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
6662 vty_out(vty
, " route-target import auto\n");
6664 /* export route-target */
6665 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6667 struct listnode
*node
, *nnode
;
6668 struct vrf_route_target
*l3rt
;
6670 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6673 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
6676 ecom_str
= ecommunity_ecom2str(
6677 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6678 vty_out(vty
, " route-target export %s\n", ecom_str
);
6679 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6683 /* export route-target auto */
6684 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
6685 vty_out(vty
, " route-target export auto\n");
6688 void bgp_ethernetvpn_init(void)
6690 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6691 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6692 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6693 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6694 install_element(VIEW_NODE
,
6695 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6696 install_element(VIEW_NODE
,
6697 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6700 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6703 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6704 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6705 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6706 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6707 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6708 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6709 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6710 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6711 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6712 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6713 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6714 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6715 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6716 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6717 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6718 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6719 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6720 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6721 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6722 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6723 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6724 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6725 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6726 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6727 install_element(BGP_EVPN_NODE
,
6728 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6731 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6732 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6734 /* "show bgp l2vpn evpn" commands. */
6735 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6736 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6737 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6738 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6739 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6740 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6741 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6742 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6743 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6744 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6745 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6746 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6747 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6748 install_element(VIEW_NODE
,
6749 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6750 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6751 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6752 install_element(VIEW_NODE
,
6753 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6754 install_element(VIEW_NODE
,
6755 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6756 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6757 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6759 /* "show bgp evpn" commands. */
6760 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6761 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6762 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6763 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6764 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6765 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6766 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6767 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6768 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6769 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6770 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6771 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6773 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6774 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6775 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6776 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6777 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6778 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6779 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6780 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6781 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6782 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6783 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6784 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6785 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6786 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6787 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
6788 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
6789 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
6790 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
6791 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
6792 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6793 install_element(BGP_EVPN_VNI_NODE
,
6794 &bgp_evpn_advertise_default_gw_vni_cmd
);
6795 install_element(BGP_EVPN_VNI_NODE
,
6796 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6797 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6798 install_element(BGP_EVPN_VNI_NODE
,
6799 &no_bgp_evpn_advertise_vni_subnet_cmd
);