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 #include "bgpd/bgp_evpn_vty_clippy.c"
3341 DEFPY(bgp_evpn_flood_control
,
3342 bgp_evpn_flood_control_cmd
,
3343 "[no$no] flooding <disable$disable|head-end-replication$her>",
3345 "Specify handling for BUM packets\n"
3346 "Do not flood any BUM packets\n"
3347 "Flood BUM packets using head-end replication\n")
3349 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3350 enum vxlan_flood_control flood_ctrl
;
3356 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3358 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3362 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3365 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3366 bgp_evpn_flood_control_change(bgp
);
3371 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3372 bgp_evpn_advertise_default_gw_vni_cmd
,
3373 "advertise-default-gw",
3374 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3376 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3377 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3382 evpn_set_advertise_default_gw(bgp
, vpn
);
3387 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3388 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3389 "no advertise-default-gw",
3391 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3393 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3394 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3399 evpn_unset_advertise_default_gw(bgp
, vpn
);
3405 DEFUN (bgp_evpn_advertise_default_gw
,
3406 bgp_evpn_advertise_default_gw_cmd
,
3407 "advertise-default-gw",
3408 "Advertise All default g/w mac-ip routes in EVPN\n")
3410 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3415 if (!EVPN_ENABLED(bgp
)) {
3417 "This command is only supported under the EVPN VRF\n");
3421 evpn_set_advertise_default_gw(bgp
, NULL
);
3426 DEFUN (no_bgp_evpn_advertise_default_gw
,
3427 no_bgp_evpn_advertise_default_gw_cmd
,
3428 "no advertise-default-gw",
3430 "Withdraw All default g/w mac-ip routes from EVPN\n")
3432 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3437 evpn_unset_advertise_default_gw(bgp
, NULL
);
3442 DEFUN (bgp_evpn_advertise_all_vni
,
3443 bgp_evpn_advertise_all_vni_cmd
,
3444 "advertise-all-vni",
3445 "Advertise All local VNIs\n")
3447 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3448 struct bgp
*bgp_evpn
= NULL
;
3453 bgp_evpn
= bgp_get_evpn();
3454 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3455 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3456 bgp_evpn
->name_pretty
);
3457 return CMD_WARNING_CONFIG_FAILED
;
3460 evpn_set_advertise_all_vni(bgp
);
3464 DEFUN (no_bgp_evpn_advertise_all_vni
,
3465 no_bgp_evpn_advertise_all_vni_cmd
,
3466 "no advertise-all-vni",
3468 "Advertise All local VNIs\n")
3470 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3474 evpn_unset_advertise_all_vni(bgp
);
3478 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3479 bgp_evpn_advertise_autort_rfc8365_cmd
,
3480 "autort rfc8365-compatible",
3481 "Auto-derivation of RT\n"
3482 "Auto-derivation of RT using RFC8365\n")
3484 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3488 evpn_set_advertise_autort_rfc8365(bgp
);
3492 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3493 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3494 "no autort rfc8365-compatible",
3496 "Auto-derivation of RT\n"
3497 "Auto-derivation of RT using RFC8365\n")
3499 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3503 evpn_unset_advertise_autort_rfc8365(bgp
);
3507 DEFUN (bgp_evpn_default_originate
,
3508 bgp_evpn_default_originate_cmd
,
3509 "default-originate <ipv4 | ipv6>",
3510 "originate a default route\n"
3511 "ipv4 address family\n"
3512 "ipv6 address family\n")
3516 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3520 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3521 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3525 DEFUN (no_bgp_evpn_default_originate
,
3526 no_bgp_evpn_default_originate_cmd
,
3527 "no default-originate <ipv4 | ipv6>",
3529 "withdraw a default route\n"
3530 "ipv4 address family\n"
3531 "ipv6 address family\n")
3535 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3539 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3540 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3544 DEFPY (dup_addr_detection
,
3545 dup_addr_detection_cmd
,
3546 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3547 "Duplicate address detection\n"
3548 "Max allowed moves before address detected as duplicate\n"
3549 "Num of max allowed moves (2-1000) default 5\n"
3550 "Duplicate address detection time\n"
3551 "Time in seconds (2-1800) default 180\n")
3553 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3558 if (!EVPN_ENABLED(bgp_vrf
)) {
3560 "This command is only supported under the EVPN VRF\n");
3564 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3567 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3569 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3571 bgp_zebra_dup_addr_detection(bgp_vrf
);
3576 DEFPY (dup_addr_detection_auto_recovery
,
3577 dup_addr_detection_auto_recovery_cmd
,
3578 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3579 "Duplicate address detection\n"
3580 "Duplicate address detection freeze\n"
3581 "Duplicate address detection permanent freeze\n"
3582 "Duplicate address detection freeze time (30-3600)\n")
3584 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3585 uint32_t freeze_time
= freeze_time_val
;
3590 if (!EVPN_ENABLED(bgp_vrf
)) {
3592 "This command is only supported under the EVPN VRF\n");
3596 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3597 bgp_vrf
->evpn_info
->dad_freeze
= true;
3598 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3600 bgp_zebra_dup_addr_detection(bgp_vrf
);
3605 DEFPY (no_dup_addr_detection
,
3606 no_dup_addr_detection_cmd
,
3607 "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>]",
3609 "Duplicate address detection\n"
3610 "Max allowed moves before address detected as duplicate\n"
3611 "Num of max allowed moves (2-1000) default 5\n"
3612 "Duplicate address detection time\n"
3613 "Time in seconds (2-1800) default 180\n"
3614 "Duplicate address detection freeze\n"
3615 "Duplicate address detection permanent freeze\n"
3616 "Duplicate address detection freeze time (30-3600)\n")
3618 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3619 uint32_t max_moves
= (uint32_t)max_moves_val
;
3620 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3625 if (!EVPN_ENABLED(bgp_vrf
)) {
3627 "This command is only supported under the EVPN VRF\n");
3632 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3634 /* Reset all parameters to default. */
3635 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3636 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3637 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3638 bgp_vrf
->evpn_info
->dad_freeze
= false;
3639 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3642 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3644 "%% Value does not match with config\n");
3647 bgp_vrf
->evpn_info
->dad_max_moves
=
3648 EVPN_DAD_DEFAULT_MAX_MOVES
;
3652 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3654 "%% Value does not match with config\n");
3657 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3661 if (bgp_vrf
->evpn_info
->dad_freeze_time
3664 "%% Value does not match with config\n");
3667 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3668 bgp_vrf
->evpn_info
->dad_freeze
= false;
3671 if (permanent_val
) {
3672 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3674 "%% Value does not match with config\n");
3677 bgp_vrf
->evpn_info
->dad_freeze
= false;
3681 bgp_zebra_dup_addr_detection(bgp_vrf
);
3686 DEFPY(bgp_evpn_advertise_svi_ip
,
3687 bgp_evpn_advertise_svi_ip_cmd
,
3688 "[no$no] advertise-svi-ip",
3690 "Advertise svi mac-ip routes in EVPN\n")
3692 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3698 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3700 if (!EVPN_ENABLED(bgp
)) {
3702 "This command is only supported under EVPN VRF\n");
3705 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3711 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3712 bgp_evpn_advertise_svi_ip_vni_cmd
,
3713 "[no$no] advertise-svi-ip",
3715 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3717 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3718 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3724 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3726 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3731 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3732 bgp_evpn_advertise_vni_subnet_cmd
,
3734 "Advertise the subnet corresponding to VNI\n")
3736 struct bgp
*bgp_vrf
= NULL
;
3737 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3738 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3743 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3747 evpn_set_advertise_subnet(bgp
, vpn
);
3751 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3752 no_bgp_evpn_advertise_vni_subnet_cmd
,
3753 "no advertise-subnet",
3755 "Advertise All local VNIs\n")
3757 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3758 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3763 evpn_unset_advertise_subnet(bgp
, vpn
);
3767 DEFUN (bgp_evpn_advertise_type5
,
3768 bgp_evpn_advertise_type5_cmd
,
3769 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3770 "Advertise prefix routes\n"
3773 "advertise gateway IP overlay index\n"
3774 "route-map for filtering specific routes\n"
3775 "Name of the route map\n")
3777 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3784 int rmap_changed
= 0;
3785 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3787 bool adv_flag_changed
= false;
3789 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3790 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3791 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3793 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3795 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3797 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3798 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3801 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3805 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3807 "%% Only ipv4 or ipv6 address families are supported\n");
3811 if (safi
!= SAFI_UNICAST
) {
3813 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3817 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3818 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3819 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3823 if (afi
== AFI_IP
) {
3824 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3825 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3826 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3827 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3830 * this is the case for first time ever configuration
3831 * adv ipv4 unicast is enabled for the first time.
3832 * So no need to reset any flag
3834 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3836 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3837 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3838 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3840 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3841 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3842 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3844 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3845 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3848 * This is modify case from gateway-ip
3849 * to no overlay index
3851 adv_flag_changed
= true;
3852 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3853 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3854 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3855 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3856 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3858 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3859 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3862 * This is modify case from no overlay index
3865 adv_flag_changed
= true;
3866 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3867 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3868 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3869 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3873 * Command is issued with the same option
3874 * (no overlay index or gateway-ip) which was
3875 * already configured. So nothing to do.
3876 * However, route-map may have been modified.
3877 * check if route-map has been modified.
3878 * If not, return an error
3884 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3885 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3886 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3887 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3890 * this is the case for first time ever configuration
3891 * adv ipv6 unicast is enabled for the first time.
3892 * So no need to reset any flag
3894 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3896 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3897 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3898 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3900 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3901 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3902 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3904 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3905 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3908 * This is modify case from gateway-ip
3909 * to no overlay index
3911 adv_flag_changed
= true;
3912 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3913 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3914 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3915 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3916 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3918 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3919 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3922 * This is modify case from no overlay index
3925 adv_flag_changed
= true;
3926 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3927 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3928 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3929 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3933 * Command is issued with the same option
3934 * (no overlay index or gateway-ip) which was
3935 * already configured. So nothing to do.
3936 * However, route-map may have been modified.
3937 * check if route-map has been modified.
3938 * If not, return an error
3945 if ((rmap_changed
) || (adv_flag_changed
)) {
3947 /* If either of these are changed, then FRR needs to
3948 * withdraw already advertised type5 routes.
3950 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3952 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3953 XFREE(MTYPE_ROUTE_MAP_NAME
,
3954 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3955 route_map_counter_decrement(
3956 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3957 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3958 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3963 /* set the route-map for advertise command */
3964 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3965 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3966 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3967 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3968 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3969 route_map_counter_increment(
3970 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3973 /* advertise type-5 routes */
3974 if (advertise_type5_routes(bgp_vrf
, afi
))
3975 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3979 DEFUN (no_bgp_evpn_advertise_type5
,
3980 no_bgp_evpn_advertise_type5_cmd
,
3981 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3983 "Advertise prefix routes\n"
3986 "route-map for filtering specific routes\n"
3987 "Name of the route map\n")
3989 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3998 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3999 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4001 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4003 "%% Only ipv4 or ipv6 address families are supported\n");
4007 if (safi
!= SAFI_UNICAST
) {
4009 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4013 if (afi
== AFI_IP
) {
4015 /* if we are not advertising ipv4 prefix as type-5
4018 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4019 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4020 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4021 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4022 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4023 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4024 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4025 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4026 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4030 /* if we are not advertising ipv6 prefix as type-5
4033 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4034 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4035 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4036 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4037 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4038 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4039 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4040 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4041 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4045 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4046 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4047 XFREE(MTYPE_ROUTE_MAP_NAME
,
4048 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4049 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4050 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4056 DEFPY (bgp_evpn_use_es_l3nhg
,
4057 bgp_evpn_use_es_l3nhg_cmd
,
4058 "[no$no] use-es-l3nhg",
4060 "use L3 nexthop group for host routes with ES destination\n")
4062 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4066 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4067 bgp_evpn_ead_evi_rx_disable_cmd
,
4068 "[no$no] disable-ead-evi-rx",
4070 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4072 bool ead_evi_rx
= no
? true :false;
4074 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4075 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4076 bgp_evpn_switch_ead_evi_rx();
4081 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4082 bgp_evpn_ead_evi_tx_disable_cmd
,
4083 "[no$no] disable-ead-evi-tx",
4085 "Don't advertise EAD-EVI for local ESs\n")
4087 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4091 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4092 bgp_evpn_enable_resolve_overlay_index_cmd
,
4093 "[no$no] enable-resolve-overlay-index",
4095 "Enable Recursive Resolution of type-5 route overlay index\n")
4097 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4099 if (bgp
!= bgp_get_evpn()) {
4100 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4104 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4108 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4109 bgp_evpn_advertise_pip_ip_mac_cmd
,
4110 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4112 "evpn system primary IP\n"
4115 MAC_STR MAC_STR MAC_STR
)
4117 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4118 struct bgp
*bgp_evpn
= NULL
;
4120 if (EVPN_ENABLED(bgp_vrf
)) {
4122 "This command is supported under L3VNI BGP EVPN VRF\n");
4123 return CMD_WARNING_CONFIG_FAILED
;
4125 bgp_evpn
= bgp_get_evpn();
4128 /* pip is already enabled */
4129 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4132 bgp_vrf
->evpn_info
->advertise_pip
= true;
4133 if (ip
.s_addr
!= INADDR_ANY
) {
4134 /* Already configured with same IP */
4135 if (IPV4_ADDR_SAME(&ip
,
4136 &bgp_vrf
->evpn_info
->pip_ip_static
))
4139 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4140 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4142 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4144 /* default instance router-id assignemt */
4146 bgp_vrf
->evpn_info
->pip_ip
=
4147 bgp_evpn
->router_id
;
4150 if (!is_zero_mac(&mac
->eth_addr
)) {
4151 /* Already configured with same MAC */
4152 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4153 &mac
->eth_addr
, ETH_ALEN
) == 0)
4156 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4157 &mac
->eth_addr
, ETH_ALEN
);
4158 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4159 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4162 /* Copy zebra sys mac */
4163 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4164 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4165 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4170 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4172 /* Disable PIP feature */
4173 bgp_vrf
->evpn_info
->advertise_pip
= false;
4174 /* copy anycast mac */
4175 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4176 &bgp_vrf
->rmac
, ETH_ALEN
);
4178 /* remove MAC-IP option retain PIP knob. */
4179 if ((ip
.s_addr
!= INADDR_ANY
) &&
4180 !IPV4_ADDR_SAME(&ip
,
4181 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4183 "%% BGP EVPN PIP IP does not match\n");
4184 return CMD_WARNING_CONFIG_FAILED
;
4187 if (!is_zero_mac(&mac
->eth_addr
) &&
4188 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4189 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4191 "%% BGP EVPN PIP MAC does not match\n");
4192 return CMD_WARNING_CONFIG_FAILED
;
4194 /* pip_rmac can carry vrr_rmac reset only if it matches
4195 * with static value.
4197 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4198 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4200 /* Copy zebra sys mac */
4202 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4203 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4204 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4207 /* copy anycast mac */
4208 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4209 &bgp_vrf
->rmac
, ETH_ALEN
);
4213 /* reset user configured sys MAC */
4214 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4215 /* reset user configured sys IP */
4216 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4217 /* Assign default PIP IP (bgp instance router-id) */
4219 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4221 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4224 if (is_evpn_enabled()) {
4225 struct listnode
*node
= NULL
;
4226 struct bgpevpn
*vpn
= NULL
;
4229 * At this point if bgp_evpn is NULL and evpn is enabled
4230 * something stupid has gone wrong
4234 update_advertise_vrf_routes(bgp_vrf
);
4236 /* Update (svi) type-2 routes */
4237 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4238 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4240 update_routes_for_vni(bgp_evpn
, vpn
);
4248 * Display VNI information - for all or a specific VNI
4250 DEFUN(show_bgp_l2vpn_evpn_vni
,
4251 show_bgp_l2vpn_evpn_vni_cmd
,
4252 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4261 struct bgp
*bgp_evpn
;
4265 json_object
*json
= NULL
;
4266 uint32_t num_l2vnis
= 0;
4267 uint32_t num_l3vnis
= 0;
4268 uint32_t num_vnis
= 0;
4269 struct listnode
*node
= NULL
;
4270 struct bgp
*bgp_temp
= NULL
;
4272 uj
= use_json(argc
, argv
);
4274 bgp_evpn
= bgp_get_evpn();
4278 if (!argv_find(argv
, argc
, "evpn", &idx
))
4282 json
= json_object_new_object();
4284 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4286 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4288 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4289 if (bgp_temp
->l3vni
)
4292 num_vnis
= num_l2vnis
+ num_l3vnis
;
4294 json_object_string_add(json
, "advertiseGatewayMacip",
4295 bgp_evpn
->advertise_gw_macip
4298 json_object_string_add(json
, "advertiseSviMacIp",
4299 bgp_evpn
->evpn_info
->advertise_svi_macip
4300 ? "Enabled" : "Disabled");
4301 json_object_string_add(json
, "advertiseAllVnis",
4302 is_evpn_enabled() ? "Enabled"
4304 json_object_string_add(
4306 bgp_evpn
->vxlan_flood_ctrl
==
4307 VXLAN_FLOOD_HEAD_END_REPL
4308 ? "Head-end replication"
4310 json_object_string_add(
4311 json
, "vxlanFlooding",
4312 bgp_evpn
->vxlan_flood_ctrl
==
4313 VXLAN_FLOOD_HEAD_END_REPL
4316 json_object_int_add(json
, "numVnis", num_vnis
);
4317 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4318 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4320 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4321 bgp_evpn
->advertise_gw_macip
? "Enabled"
4323 vty_out(vty
, "Advertise SVI Macip: %s\n",
4324 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4326 vty_out(vty
, "Advertise All VNI flag: %s\n",
4327 is_evpn_enabled() ? "Enabled" : "Disabled");
4328 vty_out(vty
, "BUM flooding: %s\n",
4329 bgp_evpn
->vxlan_flood_ctrl
==
4330 VXLAN_FLOOD_HEAD_END_REPL
4331 ? "Head-end replication"
4333 vty_out(vty
, "VXLAN flooding: %s\n",
4334 bgp_evpn
->vxlan_flood_ctrl
==
4335 VXLAN_FLOOD_HEAD_END_REPL
4338 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4339 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4341 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4345 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4348 /* Display specific VNI */
4349 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4350 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4354 vty_json(vty
, json
);
4359 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4360 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4361 "show bgp l2vpn evpn vni remote-ip-hash",
4369 struct bgp
*bgp_evpn
;
4372 bgp_evpn
= bgp_get_evpn();
4376 if (!argv_find(argv
, argc
, "evpn", &idx
))
4379 hash_iterate(bgp_evpn
->vnihash
,
4380 (void (*)(struct hash_bucket
*,
4381 void *))bgp_evpn_show_remote_ip_hash
,
4387 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4388 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4389 "show bgp l2vpn evpn vni-svi-hash",
4394 "Show vni-svi-hash\n")
4396 struct bgp
*bgp_evpn
;
4399 bgp_evpn
= bgp_get_evpn();
4403 if (!argv_find(argv
, argc
, "evpn", &idx
))
4406 hash_iterate(bgp_evpn
->vni_svi_hash
,
4407 (void (*)(struct hash_bucket
*,
4408 void *))bgp_evpn_show_vni_svi_hash
,
4414 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4415 show_bgp_l2vpn_evpn_es_evi_cmd
,
4416 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4422 "VxLAN Network Identifier\n"
4425 "Detailed information\n")
4428 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4430 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4435 DEFPY(show_bgp_l2vpn_evpn_es
,
4436 show_bgp_l2vpn_evpn_es_cmd
,
4437 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4442 "Ethernet Segment\n"
4444 "Detailed information\n"
4450 if (!str_to_esi(esi_str
, &esi
)) {
4451 vty_out(vty
, "%% Malformed ESI\n");
4454 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4457 bgp_evpn_es_show(vty
, uj
, !!detail
);
4463 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4464 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4465 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4466 "Ethernet Segment\n"
4472 if (!str_to_esi(esi_str
, &esi
)) {
4473 vty_out(vty
, "%% Malformed ESI\n");
4476 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4479 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4485 DEFPY(show_bgp_l2vpn_evpn_nh
,
4486 show_bgp_l2vpn_evpn_nh_cmd
,
4487 "show bgp l2vpn evpn next-hops [json$uj]",
4495 bgp_evpn_nh_show(vty
, uj
);
4501 * Display EVPN neighbor summary.
4503 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4504 "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]",
4507 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4508 "Summary of BGP neighbor status\n"
4509 "Show only sessions in Established state\n"
4510 "Show only sessions not in Established state\n"
4511 "Show only the specified neighbor session\n"
4512 "Neighbor to display information about\n"
4513 "Neighbor to display information about\n"
4514 "Neighbor on BGP configured interface\n"
4515 "Show only the specified remote AS sessions\n"
4517 "Internal (iBGP) AS sessions\n"
4518 "External (eBGP) AS sessions\n"
4519 "Shorten the information on BGP instances\n"
4520 "Increase table width for longer output\n" JSON_STR
)
4525 char *neighbor
= NULL
;
4526 as_t as
= 0; /* 0 means AS filter not set */
4527 int as_type
= AS_UNSPECIFIED
;
4528 uint16_t show_flags
= 0;
4530 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4531 vrf
= argv
[++idx_vrf
]->arg
;
4533 if (argv_find(argv
, argc
, "failed", &idx
))
4534 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4536 if (argv_find(argv
, argc
, "established", &idx
))
4537 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4540 if (argv_find(argv
, argc
, "neighbor", &idx
))
4541 neighbor
= argv
[idx
+ 1]->arg
;
4543 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4544 if (argv
[idx
+ 1]->arg
[0] == 'i')
4545 as_type
= AS_INTERNAL
;
4546 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4547 as_type
= AS_EXTERNAL
;
4549 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4552 if (argv_find(argv
, argc
, "terse", &idx
))
4553 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4555 if (argv_find(argv
, argc
, "wide", &idx
))
4556 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4558 if (use_json(argc
, argv
))
4559 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4561 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4562 as_type
, as
, show_flags
);
4565 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4569 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4570 /* Specific type is requested */
4571 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4572 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4573 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4574 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4575 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4576 *type
= BGP_EVPN_IMET_ROUTE
;
4577 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4578 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4579 *type
= BGP_EVPN_ES_ROUTE
;
4580 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4581 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4582 *type
= BGP_EVPN_AD_ROUTE
;
4583 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4584 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4585 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4594 * Display global EVPN routing table.
4596 DEFUN(show_bgp_l2vpn_evpn_route
,
4597 show_bgp_l2vpn_evpn_route_cmd
,
4598 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4604 "Display Detailed Information\n"
4606 EVPN_TYPE_ALL_LIST_HELP_STR
4613 json_object
*json
= NULL
;
4615 uj
= use_json(argc
, argv
);
4617 bgp
= bgp_get_evpn();
4622 json
= json_object_new_object();
4624 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4627 if (argv_find(argv
, argc
, "detail", &detail
))
4630 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4633 vty_json(vty
, json
);
4638 * Display global EVPN routing table for specific RD.
4640 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4641 show_bgp_l2vpn_evpn_route_rd_cmd
,
4642 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4648 EVPN_RT_DIST_HELP_STR
4649 EVPN_ASN_IP_HELP_STR
4650 "All VPN Route Distinguishers\n"
4652 EVPN_TYPE_ALL_LIST_HELP_STR
4657 struct prefix_rd prd
;
4660 json_object
*json
= NULL
;
4661 int idx_ext_community
= 0;
4664 bgp
= bgp_get_evpn();
4668 /* check if we need json output */
4669 uj
= use_json(argc
, argv
);
4671 json
= json_object_new_object();
4673 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4675 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4676 &idx_ext_community
)) {
4677 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4680 "%% Malformed Route Distinguisher\n");
4686 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4690 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4692 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4695 vty_json(vty
, json
);
4701 * Display global EVPN routing table for specific RD and MACIP.
4703 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4704 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4705 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4711 EVPN_RT_DIST_HELP_STR
4712 EVPN_ASN_IP_HELP_STR
4713 "All VPN Route Distinguishers\n"
4715 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4717 "IP address (IPv4 or IPv6)\n"
4722 struct prefix_rd prd
;
4725 int idx_ext_community
= 0;
4729 json_object
*json
= NULL
;
4732 memset(&mac
, 0, sizeof(struct ethaddr
));
4733 memset(&ip
, 0, sizeof(struct ipaddr
));
4735 bgp
= bgp_get_evpn();
4739 /* check if we need json output */
4740 uj
= use_json(argc
, argv
);
4742 json
= json_object_new_object();
4745 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4746 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4747 &idx_ext_community
)) {
4748 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4751 "%% Malformed Route Distinguisher\n");
4758 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4759 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4760 vty_out(vty
, "%% Malformed MAC address\n");
4765 /* get the ip if specified */
4766 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4767 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4768 vty_out(vty
, "%% Malformed IP address\n");
4774 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4776 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4779 vty_json(vty
, json
);
4784 /* Display per ESI routing table */
4785 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4786 show_bgp_l2vpn_evpn_route_esi_cmd
,
4787 "show bgp l2vpn evpn route esi ESI [json]",
4793 "Ethernet Segment Identifier\n"
4799 struct bgp
*bgp
= NULL
;
4800 json_object
*json
= NULL
;
4802 memset(&esi
, 0, sizeof(esi
));
4803 bgp
= bgp_get_evpn();
4807 uj
= use_json(argc
, argv
);
4809 json
= json_object_new_object();
4811 /* get the ESI - ESI-ID is at argv[6] */
4812 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4813 vty_out(vty
, "%% Malformed ESI\n");
4817 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4820 vty_json(vty
, json
);
4827 * Display per-VNI EVPN routing table.
4829 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4830 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4836 "VXLAN Network Identifier\n"
4839 EVPN_TYPE_1_HELP_STR
4840 EVPN_TYPE_1_HELP_STR
4841 EVPN_TYPE_2_HELP_STR
4842 EVPN_TYPE_2_HELP_STR
4843 EVPN_TYPE_3_HELP_STR
4844 EVPN_TYPE_3_HELP_STR
4846 "Remote VTEP IP address\n"
4851 struct in_addr vtep_ip
;
4856 json_object
*json
= NULL
;
4858 bgp
= bgp_get_evpn();
4862 /* check if we need json output */
4863 uj
= use_json(argc
, argv
);
4865 json
= json_object_new_object();
4867 if (!argv_find(argv
, argc
, "evpn", &idx
))
4872 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4874 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4877 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4878 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4879 vty_out(vty
, "%% Malformed VTEP IP address\n");
4884 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4887 vty_json(vty
, json
);
4893 * Display per-VNI EVPN routing table for specific MACIP.
4895 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4896 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4897 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4903 "VXLAN Network Identifier\n"
4906 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4908 "IP address (IPv4 or IPv6)\n"
4917 json_object
*json
= NULL
;
4919 bgp
= bgp_get_evpn();
4923 /* check if we need json output */
4924 uj
= use_json(argc
, argv
);
4926 json
= json_object_new_object();
4928 if (!argv_find(argv
, argc
, "evpn", &idx
))
4932 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4935 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4936 vty_out(vty
, "%% Malformed MAC address\n");
4941 memset(&ip
, 0, sizeof(ip
));
4942 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4944 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4945 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4946 vty_out(vty
, "%% Malformed IP address\n");
4951 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4954 vty_json(vty
, json
);
4960 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4962 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4963 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4964 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4970 "VXLAN Network Identifier\n"
4972 EVPN_TYPE_3_HELP_STR
4973 "Originating Router IP address\n"
4979 struct in_addr orig_ip
;
4982 json_object
*json
= NULL
;
4984 bgp
= bgp_get_evpn();
4988 /* check if we need json output */
4989 uj
= use_json(argc
, argv
);
4991 json
= json_object_new_object();
4993 if (!argv_find(argv
, argc
, "evpn", &idx
))
4997 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5000 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5002 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5006 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5009 vty_json(vty
, json
);
5015 * Display per-VNI EVPN routing table - for all VNIs.
5017 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5018 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5019 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5025 "VXLAN Network Identifier\n"
5027 "Print Detailed Output\n"
5029 "Remote VTEP IP address\n"
5033 struct in_addr vtep_ip
;
5036 json_object
*json
= NULL
;
5037 /* Detail Adjust. Adjust indexes according to detail option */
5040 bgp
= bgp_get_evpn();
5044 /* check if we need json output */
5045 uj
= use_json(argc
, argv
);
5047 json
= json_object_new_object();
5049 if (!argv_find(argv
, argc
, "evpn", &idx
))
5052 if (argv_find(argv
, argc
, "detail", &da
))
5055 /* vtep-ip position depends on detail option */
5057 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5059 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5060 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5061 vty_out(vty
, "%% Malformed VTEP IP address\n");
5066 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5069 vty_json(vty
, json
);
5075 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5076 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5077 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5078 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5079 "EVPN route information\n"
5080 "MAC IP routes in the EVI tables linked to the ES\n"
5082 "Detailed information\n" JSON_STR
)
5086 json_object
*json
= NULL
;
5089 if (!str_to_esi(esi_str
, &esi
)) {
5090 vty_out(vty
, "%% Malformed ESI\n");
5099 json
= json_object_new_object();
5100 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5102 vty_json(vty
, json
);
5108 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5109 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5110 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5111 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5112 "EVPN route information\n"
5113 "MAC IP routes in the global table linked to the ES\n"
5115 "Detailed information\n" JSON_STR
)
5119 json_object
*json
= NULL
;
5122 if (!str_to_esi(esi_str
, &esi
)) {
5123 vty_out(vty
, "%% Malformed ESI\n");
5132 json
= json_object_new_object();
5133 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5135 vty_json(vty
, json
);
5141 * Display EVPN import route-target hash table
5143 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5144 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5145 "show bgp l2vpn evpn vrf-import-rt [json]",
5150 "Show vrf import route target\n"
5154 struct bgp
*bgp_evpn
= NULL
;
5155 json_object
*json
= NULL
;
5157 bgp_evpn
= bgp_get_evpn();
5161 uj
= use_json(argc
, argv
);
5163 json
= json_object_new_object();
5165 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5168 vty_json(vty
, json
);
5174 * Display EVPN import route-target hash table
5176 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5177 show_bgp_l2vpn_evpn_import_rt_cmd
,
5178 "show bgp l2vpn evpn import-rt [json]",
5183 "Show import route target\n"
5188 json_object
*json
= NULL
;
5190 bgp
= bgp_get_evpn();
5194 uj
= use_json(argc
, argv
);
5196 json
= json_object_new_object();
5198 evpn_show_import_rts(vty
, bgp
, json
);
5201 vty_json(vty
, json
);
5206 DEFPY_HIDDEN(test_es_add
,
5208 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5211 "Ethernet-segment\n"
5212 "Ethernet-Segment Identifier\n"
5220 struct in_addr vtep_ip
;
5223 bgp
= bgp_get_evpn();
5225 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5229 if (!str_to_esi(esi_str
, &esi
)) {
5230 vty_out(vty
, "%% Malformed ESI\n");
5235 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5237 vty_out(vty
, "%% Failed to delete ES\n");
5241 if (state_str
&& !strcmp(state_str
, "up"))
5245 vtep_ip
= bgp
->router_id
;
5247 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5248 EVPN_MH_DF_PREF_MIN
, false);
5250 vty_out(vty
, "%% Failed to add ES\n");
5257 DEFPY_HIDDEN(test_es_vni_add
,
5258 test_es_vni_add_cmd
,
5259 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5262 "Ethernet-segment\n"
5263 "Ethernet-Segment Identifier\n"
5272 bgp
= bgp_get_evpn();
5274 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5278 if (!str_to_esi(esi_str
, &esi
)) {
5279 vty_out(vty
, "%% Malformed ESI\n");
5284 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5286 vty_out(vty
, "%% Failed to deref ES VNI\n");
5290 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5292 vty_out(vty
, "%% Failed to ref ES VNI\n");
5299 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5300 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5304 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5305 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5306 "Summary of BGP neighbor status\n" JSON_STR
)
5308 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5309 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5310 SHOW_STR BGP_STR EVPN_HELP_STR
5312 "Display Detailed Information\n"
5314 EVPN_TYPE_2_HELP_STR
5315 EVPN_TYPE_2_HELP_STR
5316 EVPN_TYPE_3_HELP_STR
5317 EVPN_TYPE_3_HELP_STR
)
5320 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5321 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5322 SHOW_STR BGP_STR EVPN_HELP_STR
5324 EVPN_RT_DIST_HELP_STR
5325 EVPN_ASN_IP_HELP_STR
5327 EVPN_TYPE_2_HELP_STR
5328 EVPN_TYPE_2_HELP_STR
5329 EVPN_TYPE_3_HELP_STR
5330 EVPN_TYPE_3_HELP_STR
)
5333 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5334 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5335 SHOW_STR BGP_STR EVPN_HELP_STR
5337 EVPN_RT_DIST_HELP_STR
5338 EVPN_ASN_IP_HELP_STR
5340 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5342 "IP address (IPv4 or IPv6)\n")
5345 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5346 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5347 SHOW_STR BGP_STR EVPN_HELP_STR
5349 "VXLAN Network Identifier\n"
5352 EVPN_TYPE_2_HELP_STR
5353 EVPN_TYPE_2_HELP_STR
5354 EVPN_TYPE_3_HELP_STR
5355 EVPN_TYPE_3_HELP_STR
5357 "Remote VTEP IP address\n")
5359 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5360 show_bgp_evpn_route_vni_macip_cmd
,
5361 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5362 SHOW_STR BGP_STR EVPN_HELP_STR
5364 "VXLAN Network Identifier\n"
5367 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5369 "IP address (IPv4 or IPv6)\n")
5371 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5372 show_bgp_evpn_route_vni_multicast_cmd
,
5373 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5374 SHOW_STR BGP_STR EVPN_HELP_STR
5376 "VXLAN Network Identifier\n"
5378 EVPN_TYPE_3_HELP_STR
5379 "Originating Router IP address\n")
5381 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5382 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5383 SHOW_STR BGP_STR EVPN_HELP_STR
5385 "VXLAN Network Identifier\n"
5387 "Print Detailed Output\n"
5389 "Remote VTEP IP address\n")
5391 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5392 "show bgp evpn import-rt",
5393 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5395 DEFUN_NOSH (bgp_evpn_vni
,
5397 "vni " CMD_VNI_RANGE
,
5398 "VXLAN Network Identifier\n"
5402 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5403 struct bgpevpn
*vpn
;
5408 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5410 /* Create VNI, or mark as configured. */
5411 vpn
= evpn_create_update_vni(bgp
, vni
);
5413 vty_out(vty
, "%% Failed to create VNI \n");
5417 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5421 DEFUN (no_bgp_evpn_vni
,
5422 no_bgp_evpn_vni_cmd
,
5423 "no vni " CMD_VNI_RANGE
,
5425 "VXLAN Network Identifier\n"
5429 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5430 struct bgpevpn
*vpn
;
5435 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5437 /* Check if we should disallow. */
5438 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5440 vty_out(vty
, "%% Specified VNI does not exist\n");
5443 if (!is_vni_configured(vpn
)) {
5444 vty_out(vty
, "%% Specified VNI is not configured\n");
5448 evpn_delete_vni(bgp
, vpn
);
5452 DEFUN_NOSH (exit_vni
,
5455 "Exit from VNI mode\n")
5457 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5458 vty
->node
= BGP_EVPN_NODE
;
5462 DEFUN (bgp_evpn_vrf_rd
,
5463 bgp_evpn_vrf_rd_cmd
,
5464 "rd ASN:NN_OR_IP-ADDRESS:NN",
5465 EVPN_RT_DIST_HELP_STR
5466 EVPN_ASN_IP_HELP_STR
)
5469 struct prefix_rd prd
;
5470 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5475 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5477 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5481 /* If same as existing value, there is nothing more to do. */
5482 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5485 /* Configure or update the RD. */
5486 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5490 DEFUN (no_bgp_evpn_vrf_rd
,
5491 no_bgp_evpn_vrf_rd_cmd
,
5492 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5494 EVPN_RT_DIST_HELP_STR
5495 EVPN_ASN_IP_HELP_STR
)
5498 struct prefix_rd prd
;
5499 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5504 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5506 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5510 /* Check if we should disallow. */
5511 if (!is_vrf_rd_configured(bgp_vrf
)) {
5512 vty_out(vty
, "%% RD is not configured for this VRF\n");
5516 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5518 "%% RD specified does not match configuration for this VRF\n");
5522 evpn_unconfigure_vrf_rd(bgp_vrf
);
5526 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5527 no_bgp_evpn_vrf_rd_without_val_cmd
,
5530 EVPN_RT_DIST_HELP_STR
)
5532 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5537 /* Check if we should disallow. */
5538 if (!is_vrf_rd_configured(bgp_vrf
)) {
5539 vty_out(vty
, "%% RD is not configured for this VRF\n");
5543 evpn_unconfigure_vrf_rd(bgp_vrf
);
5547 DEFUN (bgp_evpn_vni_rd
,
5548 bgp_evpn_vni_rd_cmd
,
5549 "rd ASN:NN_OR_IP-ADDRESS:NN",
5550 EVPN_RT_DIST_HELP_STR
5551 EVPN_ASN_IP_HELP_STR
)
5553 struct prefix_rd prd
;
5554 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5555 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5561 if (!EVPN_ENABLED(bgp
)) {
5563 "This command is only supported under EVPN VRF\n");
5567 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5569 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5573 /* If same as existing value, there is nothing more to do. */
5574 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5577 /* Configure or update the RD. */
5578 evpn_configure_rd(bgp
, vpn
, &prd
);
5582 DEFUN (no_bgp_evpn_vni_rd
,
5583 no_bgp_evpn_vni_rd_cmd
,
5584 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5586 EVPN_RT_DIST_HELP_STR
5587 EVPN_ASN_IP_HELP_STR
)
5589 struct prefix_rd prd
;
5590 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5591 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5597 if (!EVPN_ENABLED(bgp
)) {
5599 "This command is only supported under EVPN VRF\n");
5603 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5605 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5609 /* Check if we should disallow. */
5610 if (!is_rd_configured(vpn
)) {
5611 vty_out(vty
, "%% RD is not configured for this VNI\n");
5615 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5617 "%% RD specified does not match configuration for this VNI\n");
5621 evpn_unconfigure_rd(bgp
, vpn
);
5625 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5626 no_bgp_evpn_vni_rd_without_val_cmd
,
5629 EVPN_RT_DIST_HELP_STR
)
5631 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5632 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5637 if (!EVPN_ENABLED(bgp
)) {
5639 "This command is only supported under EVPN VRF\n");
5643 /* Check if we should disallow. */
5644 if (!is_rd_configured(vpn
)) {
5645 vty_out(vty
, "%% RD is not configured for this VNI\n");
5649 evpn_unconfigure_rd(bgp
, vpn
);
5654 * Loop over all extended-communities in the route-target list rtl and
5655 * return 1 if we find ecomtarget
5657 static bool bgp_evpn_rt_matches_existing(struct list
*rtl
,
5658 struct ecommunity
*ecomtarget
)
5660 struct listnode
*node
;
5661 struct ecommunity
*ecom
;
5663 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, ecom
)) {
5664 if (ecommunity_match(ecom
, ecomtarget
))
5672 * L3 RT version of above.
5674 static bool bgp_evpn_vrf_rt_matches_existing(struct list
*rtl
,
5675 struct ecommunity
*ecomtarget
)
5677 struct listnode
*node
;
5678 struct vrf_route_target
*l3rt
;
5680 for (ALL_LIST_ELEMENTS_RO(rtl
, node
, l3rt
)) {
5681 if (ecommunity_match(l3rt
->ecom
, ecomtarget
))
5688 /* display L3VNI related info for a VRF instance */
5689 DEFUN (show_bgp_vrf_l3vni_info
,
5690 show_bgp_vrf_l3vni_info_cmd
,
5691 "show bgp vrf VRFNAME vni [json]",
5699 char buf
[ETHER_ADDR_STRLEN
];
5701 const char *name
= NULL
;
5702 struct bgp
*bgp
= NULL
;
5703 struct listnode
*node
= NULL
;
5704 struct bgpevpn
*vpn
= NULL
;
5705 struct vrf_route_target
*l3rt
;
5706 json_object
*json
= NULL
;
5707 json_object
*json_vnis
= NULL
;
5708 json_object
*json_export_rts
= NULL
;
5709 json_object
*json_import_rts
= NULL
;
5710 bool uj
= use_json(argc
, argv
);
5713 json
= json_object_new_object();
5714 json_vnis
= json_object_new_array();
5715 json_export_rts
= json_object_new_array();
5716 json_import_rts
= json_object_new_array();
5719 name
= argv
[idx_vrf
]->arg
;
5720 bgp
= bgp_lookup_by_name(name
);
5721 if (strmatch(name
, VRF_DEFAULT_NAME
))
5722 bgp
= bgp_get_default();
5726 vty_out(vty
, "BGP instance for VRF %s not found\n",
5729 json_object_string_add(json
, "warning",
5730 "BGP instance not found");
5731 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5732 json_object_free(json
);
5738 vty_out(vty
, "BGP VRF: %s\n", name
);
5739 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5740 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5741 vty_out(vty
, " Rmac: %s\n",
5742 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5743 vty_out(vty
, " VNI Filter: %s\n",
5744 CHECK_FLAG(bgp
->vrf_flags
,
5745 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5746 ? "prefix-routes-only"
5748 vty_out(vty
, " L2-VNI List:\n");
5750 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5751 vty_out(vty
, "%u ", vpn
->vni
);
5753 vty_out(vty
, " Export-RTs:\n");
5755 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
5756 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
5758 vty_out(vty
, " Import-RTs:\n");
5760 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
5761 vty_out(vty
, "%s ", ecommunity_str(l3rt
->ecom
));
5763 vty_out(vty
, " RD: %pRD\n", &bgp
->vrf_prd
);
5765 json_object_string_add(json
, "vrf", name
);
5766 json_object_string_addf(json
, "local-ip", "%pI4",
5767 &bgp
->originator_ip
);
5768 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5769 json_object_string_add(
5771 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5772 json_object_string_add(
5774 CHECK_FLAG(bgp
->vrf_flags
,
5775 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5776 ? "prefix-routes-only"
5778 /* list of l2vnis */
5779 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5780 json_object_array_add(json_vnis
,
5781 json_object_new_int(vpn
->vni
));
5782 json_object_object_add(json
, "l2vnis", json_vnis
);
5785 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, l3rt
))
5786 json_object_array_add(
5788 json_object_new_string(
5789 ecommunity_str(l3rt
->ecom
)));
5790 json_object_object_add(json
, "export-rts", json_export_rts
);
5793 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, l3rt
))
5794 json_object_array_add(
5796 json_object_new_string(
5797 ecommunity_str(l3rt
->ecom
)));
5798 json_object_object_add(json
, "import-rts", json_import_rts
);
5799 json_object_string_addf(json
, "rd", "%pRD", &bgp
->vrf_prd
);
5803 vty_json(vty
, json
);
5807 static int add_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
,
5810 /* Do nothing if we already have this route-target */
5812 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
5814 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecom
,
5819 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
5821 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecom
);
5829 static int del_rt(struct bgp
*bgp
, struct ecommunity
*ecom
, bool is_import
)
5831 /* Verify we already have this route-target */
5833 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_import_rtl
,
5837 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecom
);
5839 if (!bgp_evpn_vrf_rt_matches_existing(bgp
->vrf_export_rtl
,
5843 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecom
);
5849 static int parse_rtlist(struct bgp
*bgp
, struct vty
*vty
, int argc
,
5850 struct cmd_token
**argv
, int rt_idx
, bool is_add
,
5853 int ret
= CMD_SUCCESS
;
5854 bool is_wildcard
= false;
5855 struct ecommunity
*ecom
= NULL
;
5857 for (int i
= rt_idx
; i
< argc
; i
++) {
5858 is_wildcard
= false;
5861 * Special handling for wildcard '*' here.
5863 * Let's just convert it to 0 here so we dont have to modify
5864 * the ecommunity parser.
5866 if ((argv
[i
]->arg
)[0] == '*') {
5867 (argv
[i
]->arg
)[0] = '0';
5871 ecom
= ecommunity_str2com(argv
[i
]->arg
, ECOMMUNITY_ROUTE_TARGET
,
5874 /* Put it back as was */
5876 (argv
[i
]->arg
)[0] = '*';
5879 vty_out(vty
, "%% Malformed Route Target list\n");
5884 ecommunity_str(ecom
);
5887 if (add_rt(bgp
, ecom
, is_import
, is_wildcard
) != 0) {
5889 "%% RT specified already configured for this VRF: %s\n",
5891 ecommunity_free(&ecom
);
5896 if (del_rt(bgp
, ecom
, is_import
) != 0) {
5898 "%% RT specified does not match configuration for this VRF: %s\n",
5903 ecommunity_free(&ecom
);
5910 /* import/export rt for l3vni-vrf */
5911 DEFUN (bgp_evpn_vrf_rt
,
5912 bgp_evpn_vrf_rt_cmd
,
5913 "route-target <both|import|export> RTLIST...",
5915 "import and export\n"
5918 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN|*:OPQR|*:MN)\n")
5920 int ret
= CMD_SUCCESS
;
5921 int tmp_ret
= CMD_SUCCESS
;
5923 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5926 return CMD_WARNING_CONFIG_FAILED
;
5928 if (!strcmp(argv
[1]->arg
, "import"))
5929 rt_type
= RT_TYPE_IMPORT
;
5930 else if (!strcmp(argv
[1]->arg
, "export"))
5931 rt_type
= RT_TYPE_EXPORT
;
5932 else if (!strcmp(argv
[1]->arg
, "both"))
5933 rt_type
= RT_TYPE_BOTH
;
5935 vty_out(vty
, "%% Invalid Route Target type\n");
5936 return CMD_WARNING_CONFIG_FAILED
;
5939 if (strmatch(argv
[2]->arg
, "auto")) {
5940 vty_out(vty
, "%% `auto` cannot be configured via list\n");
5941 return CMD_WARNING_CONFIG_FAILED
;
5944 if (rt_type
!= RT_TYPE_IMPORT
) {
5945 for (int i
= 2; i
< argc
; i
++) {
5946 if ((argv
[i
]->arg
)[0] == '*') {
5948 "%% Wildcard '*' only applicable for import\n");
5949 return CMD_WARNING_CONFIG_FAILED
;
5954 /* Add/update the import route-target */
5955 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
5956 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, true);
5958 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
5961 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
5962 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 2, true, false);
5964 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
5970 DEFPY (bgp_evpn_vrf_rt_auto
,
5971 bgp_evpn_vrf_rt_auto_cmd
,
5972 "route-target <both|import|export>$type auto",
5974 "import and export\n"
5977 "Automatically derive route target\n")
5979 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5983 return CMD_WARNING_CONFIG_FAILED
;
5985 if (strmatch(type
, "import"))
5986 rt_type
= RT_TYPE_IMPORT
;
5987 else if (strmatch(type
, "export"))
5988 rt_type
= RT_TYPE_EXPORT
;
5989 else if (strmatch(type
, "both"))
5990 rt_type
= RT_TYPE_BOTH
;
5992 vty_out(vty
, "%% Invalid Route Target type\n");
5993 return CMD_WARNING_CONFIG_FAILED
;
5996 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
5997 bgp_evpn_configure_import_auto_rt_for_vrf(bgp
);
5999 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6000 bgp_evpn_configure_export_auto_rt_for_vrf(bgp
);
6005 DEFUN (no_bgp_evpn_vrf_rt
,
6006 no_bgp_evpn_vrf_rt_cmd
,
6007 "no route-target <both|import|export> RTLIST...",
6010 "import and export\n"
6013 "Space separated route target list (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6015 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6016 int ret
= CMD_SUCCESS
;
6017 int tmp_ret
= CMD_SUCCESS
;
6021 return CMD_WARNING_CONFIG_FAILED
;
6023 if (!strcmp(argv
[2]->arg
, "import"))
6024 rt_type
= RT_TYPE_IMPORT
;
6025 else if (!strcmp(argv
[2]->arg
, "export"))
6026 rt_type
= RT_TYPE_EXPORT
;
6027 else if (!strcmp(argv
[2]->arg
, "both"))
6028 rt_type
= RT_TYPE_BOTH
;
6030 vty_out(vty
, "%% Invalid Route Target type\n");
6031 return CMD_WARNING_CONFIG_FAILED
;
6034 if (!strcmp(argv
[3]->arg
, "auto")) {
6035 vty_out(vty
, "%% `auto` cannot be unconfigured via list\n");
6036 return CMD_WARNING_CONFIG_FAILED
;
6039 if (rt_type
== RT_TYPE_IMPORT
) {
6040 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6042 "%% Import RT is not configured for this VRF\n");
6043 return CMD_WARNING_CONFIG_FAILED
;
6045 } else if (rt_type
== RT_TYPE_EXPORT
) {
6046 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6048 "%% Export RT is not configured for this VRF\n");
6049 return CMD_WARNING_CONFIG_FAILED
;
6051 } else if (rt_type
== RT_TYPE_BOTH
) {
6052 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
6053 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6055 "%% Import/Export RT is not configured for this VRF\n");
6056 return CMD_WARNING_CONFIG_FAILED
;
6060 if (rt_type
!= RT_TYPE_IMPORT
) {
6061 for (int i
= 3; i
< argc
; i
++) {
6062 if ((argv
[i
]->arg
)[0] == '*') {
6064 "%% Wildcard '*' only applicable for import\n");
6065 return CMD_WARNING_CONFIG_FAILED
;
6070 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6071 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, true);
6073 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6076 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6077 tmp_ret
= parse_rtlist(bgp
, vty
, argc
, argv
, 3, false, false);
6079 if (ret
== CMD_SUCCESS
&& tmp_ret
!= CMD_SUCCESS
)
6085 DEFPY (no_bgp_evpn_vrf_rt_auto
,
6086 no_bgp_evpn_vrf_rt_auto_cmd
,
6087 "no route-target <both|import|export>$type auto",
6090 "import and export\n"
6093 "Automatically derive route target\n")
6095 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6099 return CMD_WARNING_CONFIG_FAILED
;
6101 if (strmatch(type
, "import"))
6102 rt_type
= RT_TYPE_IMPORT
;
6103 else if (strmatch(type
, "export"))
6104 rt_type
= RT_TYPE_EXPORT
;
6105 else if (strmatch(type
, "both"))
6106 rt_type
= RT_TYPE_BOTH
;
6108 vty_out(vty
, "%% Invalid Route Target type\n");
6109 return CMD_WARNING_CONFIG_FAILED
;
6112 if (rt_type
== RT_TYPE_IMPORT
) {
6113 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
)) {
6115 "%% Import AUTO RT is not configured for this VRF\n");
6116 return CMD_WARNING_CONFIG_FAILED
;
6118 } else if (rt_type
== RT_TYPE_EXPORT
) {
6119 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6121 "%% Export AUTO RT is not configured for this VRF\n");
6122 return CMD_WARNING_CONFIG_FAILED
;
6124 } else if (rt_type
== RT_TYPE_BOTH
) {
6125 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
) &&
6126 !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
)) {
6128 "%% Import/Export AUTO RT is not configured for this VRF\n");
6129 return CMD_WARNING_CONFIG_FAILED
;
6133 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
)
6134 bgp_evpn_unconfigure_import_auto_rt_for_vrf(bgp
);
6136 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
)
6137 bgp_evpn_unconfigure_export_auto_rt_for_vrf(bgp
);
6142 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
6143 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
6145 "EAD ES fragment config\n"
6146 "EVIs per-fragment\n"
6149 bgp_mh_info
->evi_per_es_frag
=
6150 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
6155 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
6156 "ead-es-route-target export RT",
6157 "EAD ES Route Target\n"
6159 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6161 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6162 struct ecommunity
*ecomadd
= NULL
;
6167 if (!EVPN_ENABLED(bgp
)) {
6168 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6172 /* Add/update the export route-target */
6173 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6175 vty_out(vty
, "%% Malformed Route Target list\n");
6178 ecommunity_str(ecomadd
);
6180 /* Do nothing if we already have this export route-target */
6181 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6183 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6188 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6189 "no ead-es-route-target export RT",
6191 "EAD ES Route Target\n"
6192 "export\n" EVPN_ASN_IP_HELP_STR
)
6194 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6195 struct ecommunity
*ecomdel
= NULL
;
6200 if (!EVPN_ENABLED(bgp
)) {
6201 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6205 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6207 vty_out(vty
, "%% Malformed Route Target list\n");
6210 ecommunity_str(ecomdel
);
6212 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6214 ecommunity_free(&ecomdel
);
6216 "%% RT specified does not match EAD-ES RT configuration\n");
6219 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6224 DEFUN (bgp_evpn_vni_rt
,
6225 bgp_evpn_vni_rt_cmd
,
6226 "route-target <both|import|export> RT",
6228 "import and export\n"
6231 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6233 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6234 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6236 struct ecommunity
*ecomadd
= NULL
;
6241 if (!EVPN_ENABLED(bgp
)) {
6243 "This command is only supported under EVPN VRF\n");
6247 if (!strcmp(argv
[1]->text
, "import"))
6248 rt_type
= RT_TYPE_IMPORT
;
6249 else if (!strcmp(argv
[1]->text
, "export"))
6250 rt_type
= RT_TYPE_EXPORT
;
6251 else if (!strcmp(argv
[1]->text
, "both"))
6252 rt_type
= RT_TYPE_BOTH
;
6254 vty_out(vty
, "%% Invalid Route Target type\n");
6258 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6260 vty_out(vty
, "%% Malformed Route Target list\n");
6263 ecommunity_str(ecomadd
);
6265 /* Add/update the import route-target */
6266 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6267 /* Do nothing if we already have this import route-target */
6268 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6269 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6272 /* Add/update the export route-target */
6273 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6274 /* Do nothing if we already have this export route-target */
6275 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6276 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6282 DEFUN (no_bgp_evpn_vni_rt
,
6283 no_bgp_evpn_vni_rt_cmd
,
6284 "no route-target <both|import|export> RT",
6287 "import and export\n"
6290 EVPN_ASN_IP_HELP_STR
)
6292 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6293 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6294 int rt_type
, found_ecomdel
;
6295 struct ecommunity
*ecomdel
= NULL
;
6300 if (!EVPN_ENABLED(bgp
)) {
6302 "This command is only supported under EVPN VRF\n");
6306 if (!strcmp(argv
[2]->text
, "import"))
6307 rt_type
= RT_TYPE_IMPORT
;
6308 else if (!strcmp(argv
[2]->text
, "export"))
6309 rt_type
= RT_TYPE_EXPORT
;
6310 else if (!strcmp(argv
[2]->text
, "both"))
6311 rt_type
= RT_TYPE_BOTH
;
6313 vty_out(vty
, "%% Invalid Route Target type\n");
6317 /* The user did "no route-target import", check to see if there are any
6318 * import route-targets configured. */
6319 if (rt_type
== RT_TYPE_IMPORT
) {
6320 if (!is_import_rt_configured(vpn
)) {
6322 "%% Import RT is not configured for this VNI\n");
6325 } else if (rt_type
== RT_TYPE_EXPORT
) {
6326 if (!is_export_rt_configured(vpn
)) {
6328 "%% Export RT is not configured for this VNI\n");
6331 } else if (rt_type
== RT_TYPE_BOTH
) {
6332 if (!is_import_rt_configured(vpn
)
6333 && !is_export_rt_configured(vpn
)) {
6335 "%% Import/Export RT is not configured for this VNI\n");
6340 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6342 vty_out(vty
, "%% Malformed Route Target list\n");
6345 ecommunity_str(ecomdel
);
6347 if (rt_type
== RT_TYPE_IMPORT
) {
6348 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6349 ecommunity_free(&ecomdel
);
6351 "%% RT specified does not match configuration for this VNI\n");
6354 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6355 } else if (rt_type
== RT_TYPE_EXPORT
) {
6356 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6357 ecommunity_free(&ecomdel
);
6359 "%% RT specified does not match configuration for this VNI\n");
6362 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6363 } else if (rt_type
== RT_TYPE_BOTH
) {
6366 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6367 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6371 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6372 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6376 if (!found_ecomdel
) {
6377 ecommunity_free(&ecomdel
);
6379 "%% RT specified does not match configuration for this VNI\n");
6387 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6388 no_bgp_evpn_vni_rt_without_val_cmd
,
6389 "no route-target <import|export>",
6395 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6396 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6402 if (!EVPN_ENABLED(bgp
)) {
6404 "This command is only supported under EVPN VRF\n");
6408 if (!strcmp(argv
[2]->text
, "import")) {
6409 rt_type
= RT_TYPE_IMPORT
;
6410 } else if (!strcmp(argv
[2]->text
, "export")) {
6411 rt_type
= RT_TYPE_EXPORT
;
6413 vty_out(vty
, "%% Invalid Route Target type\n");
6417 /* Check if we should disallow. */
6418 if (rt_type
== RT_TYPE_IMPORT
) {
6419 if (!is_import_rt_configured(vpn
)) {
6421 "%% Import RT is not configured for this VNI\n");
6425 if (!is_export_rt_configured(vpn
)) {
6427 "%% Export RT is not configured for this VNI\n");
6432 /* Unconfigure the RT. */
6433 if (rt_type
== RT_TYPE_IMPORT
)
6434 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6436 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6440 static int vni_cmp(const void **a
, const void **b
)
6442 const struct bgpevpn
*first
= *a
;
6443 const struct bgpevpn
*secnd
= *b
;
6445 return secnd
->vni
- first
->vni
;
6449 * Output EVPN configuration information.
6451 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6454 char buf2
[INET6_ADDRSTRLEN
];
6456 if (bgp
->advertise_all_vni
)
6457 vty_out(vty
, " advertise-all-vni\n");
6459 if (hashcount(bgp
->vnihash
)) {
6460 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6461 struct listnode
*ln
;
6462 struct bgpevpn
*data
;
6464 list_sort(vnilist
, vni_cmp
);
6465 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6466 write_vni_config(vty
, data
);
6468 list_delete(&vnilist
);
6471 if (bgp
->advertise_autort_rfc8365
)
6472 vty_out(vty
, " autort rfc8365-compatible\n");
6474 if (bgp
->advertise_gw_macip
)
6475 vty_out(vty
, " advertise-default-gw\n");
6477 if (bgp
->evpn_info
->advertise_svi_macip
)
6478 vty_out(vty
, " advertise-svi-ip\n");
6480 if (bgp
->resolve_overlay_index
)
6481 vty_out(vty
, " enable-resolve-overlay-index\n");
6483 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
6484 vty_out(vty
, " ead-es-frag evi-limit %u\n",
6485 bgp_mh_info
->evi_per_es_frag
);
6487 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6488 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6489 if (bgp_mh_info
->host_routes_use_l3nhg
)
6490 vty_out(vty
, " use-es-l3nhg\n");
6492 vty_out(vty
, " no use-es-l3nhg\n");
6495 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6496 if (bgp_mh_info
->ead_evi_rx
)
6497 vty_out(vty
, " no disable-ead-evi-rx\n");
6499 vty_out(vty
, " disable-ead-evi-rx\n");
6502 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6503 if (bgp_mh_info
->ead_evi_tx
)
6504 vty_out(vty
, " no disable-ead-evi-tx\n");
6506 vty_out(vty
, " disable-ead-evi-tx\n");
6509 if (!bgp
->evpn_info
->dup_addr_detect
)
6510 vty_out(vty
, " no dup-addr-detection\n");
6512 if (bgp
->evpn_info
->dad_max_moves
!=
6513 EVPN_DAD_DEFAULT_MAX_MOVES
||
6514 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6515 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6516 bgp
->evpn_info
->dad_max_moves
,
6517 bgp
->evpn_info
->dad_time
);
6519 if (bgp
->evpn_info
->dad_freeze
) {
6520 if (bgp
->evpn_info
->dad_freeze_time
)
6522 " dup-addr-detection freeze %u\n",
6523 bgp
->evpn_info
->dad_freeze_time
);
6526 " dup-addr-detection freeze permanent\n");
6529 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6530 vty_out(vty
, " flooding disable\n");
6532 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6533 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6534 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6535 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6536 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6539 " advertise ipv4 unicast\n");
6540 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6541 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6542 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6544 " advertise ipv4 unicast gateway-ip route-map %s\n",
6545 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6547 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6550 /* EAD ES export route-target */
6551 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
6552 struct ecommunity
*ecom
;
6554 struct listnode
*node
;
6556 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
6559 ecom_str
= ecommunity_ecom2str(
6560 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6561 vty_out(vty
, " ead-es-route-target export %s\n",
6563 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6567 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6568 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6569 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6571 " advertise ipv6 unicast route-map %s\n",
6572 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6575 " advertise ipv6 unicast\n");
6576 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6577 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6578 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6580 " advertise ipv6 unicast gateway-ip route-map %s\n",
6581 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6583 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6586 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6587 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6588 vty_out(vty
, " default-originate ipv4\n");
6590 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6591 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6592 vty_out(vty
, " default-originate ipv6\n");
6594 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6595 if (!bgp
->evpn_info
->advertise_pip
)
6596 vty_out(vty
, " no advertise-pip\n");
6597 if (bgp
->evpn_info
->advertise_pip
) {
6598 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6600 vty_out(vty
, " advertise-pip ip %s",
6602 &bgp
->evpn_info
->pip_ip_static
,
6603 buf2
, INET_ADDRSTRLEN
));
6605 bgp
->evpn_info
->pip_rmac_static
))) {
6606 char buf
[ETHER_ADDR_STRLEN
];
6608 vty_out(vty
, " mac %s",
6618 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6619 vty_out(vty
, " rd %pRD\n", &bgp
->vrf_prd
);
6621 /* import route-target */
6622 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6624 struct listnode
*node
, *nnode
;
6625 struct vrf_route_target
*l3rt
;
6627 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6630 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
6633 ecom_str
= ecommunity_ecom2str(
6634 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6636 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_WILD
)) {
6637 char *vni_str
= NULL
;
6639 vni_str
= strchr(ecom_str
, ':');
6642 continue; /* This should never happen */
6644 /* Move pointer to vni */
6647 vty_out(vty
, " route-target import *:%s\n",
6651 vty_out(vty
, " route-target import %s\n",
6654 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6658 /* import route-target auto */
6659 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_AUTO_RT_CFGD
))
6660 vty_out(vty
, " route-target import auto\n");
6662 /* export route-target */
6663 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6665 struct listnode
*node
, *nnode
;
6666 struct vrf_route_target
*l3rt
;
6668 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6671 if (CHECK_FLAG(l3rt
->flags
, BGP_VRF_RT_AUTO
))
6674 ecom_str
= ecommunity_ecom2str(
6675 l3rt
->ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6676 vty_out(vty
, " route-target export %s\n", ecom_str
);
6677 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6681 /* export route-target auto */
6682 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_AUTO_RT_CFGD
))
6683 vty_out(vty
, " route-target export auto\n");
6686 void bgp_ethernetvpn_init(void)
6688 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6689 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6690 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6691 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6692 install_element(VIEW_NODE
,
6693 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6694 install_element(VIEW_NODE
,
6695 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6698 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6701 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6702 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6703 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6704 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6705 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6706 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6707 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6708 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6709 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6710 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6711 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6712 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6713 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6714 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6715 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6716 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6717 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6718 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6719 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6720 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6721 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6722 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6723 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6724 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6725 install_element(BGP_EVPN_NODE
,
6726 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6729 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6730 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6732 /* "show bgp l2vpn evpn" commands. */
6733 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6734 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6735 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6736 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6737 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6738 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6739 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6740 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6741 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6742 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6743 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6744 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6745 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6746 install_element(VIEW_NODE
,
6747 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6748 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6749 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6750 install_element(VIEW_NODE
,
6751 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6752 install_element(VIEW_NODE
,
6753 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6754 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6755 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6757 /* "show bgp evpn" commands. */
6758 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6759 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6760 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6761 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6762 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6763 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6764 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6765 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6766 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6767 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6768 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6769 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6771 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6772 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6773 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6774 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6775 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6776 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6777 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6778 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6779 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6780 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6781 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6782 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6783 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6784 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6785 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_auto_cmd
);
6786 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_auto_cmd
);
6787 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
6788 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
6789 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
6790 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6791 install_element(BGP_EVPN_VNI_NODE
,
6792 &bgp_evpn_advertise_default_gw_vni_cmd
);
6793 install_element(BGP_EVPN_VNI_NODE
,
6794 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6795 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6796 install_element(BGP_EVPN_VNI_NODE
,
6797 &no_bgp_evpn_advertise_vni_subnet_cmd
);