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 ecommunity
*ecom
;
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_add(
391 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
392 json_object_string_addf(json
, "originatorIp", "%pI4",
393 &bgp_vrf
->originator_ip
);
394 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
395 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
396 json_object_string_add(json
, "advertisePip",
397 bgp_vrf
->evpn_info
->advertise_pip
?
398 "Enabled" : "Disabled");
399 json_object_string_addf(json
, "sysIP", "%pI4",
400 &bgp_vrf
->evpn_info
->pip_ip
);
401 json_object_string_add(json
, "sysMac",
402 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
403 buf2
, sizeof(buf2
)));
404 json_object_string_add(json
, "rmac",
405 prefix_mac2str(&bgp_vrf
->rmac
,
406 buf2
, sizeof(buf2
)));
408 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
409 vty_out(vty
, " (known to the kernel)");
412 vty_out(vty
, " Type: %s\n", "L3");
413 vty_out(vty
, " Tenant VRF: %s\n",
414 vrf_id_to_name(bgp_vrf
->vrf_id
));
415 vty_out(vty
, " RD: %s\n",
416 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
417 vty_out(vty
, " Originator IP: %pI4\n",
418 &bgp_vrf
->originator_ip
);
419 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
420 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
421 vty_out(vty
, " Advertise-pip: %s\n",
422 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
423 vty_out(vty
, " System-IP: %s\n",
424 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
425 buf1
, INET_ADDRSTRLEN
));
426 vty_out(vty
, " System-MAC: %s\n",
427 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
428 buf2
, sizeof(buf2
)));
429 vty_out(vty
, " Router-MAC: %s\n",
430 prefix_mac2str(&bgp_vrf
->rmac
,
431 buf2
, sizeof(buf2
)));
435 vty_out(vty
, " Import Route Target:\n");
437 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
438 ecom_str
= ecommunity_ecom2str(ecom
,
439 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
442 json_object_array_add(json_import_rtl
,
443 json_object_new_string(ecom_str
));
445 vty_out(vty
, " %s\n", ecom_str
);
447 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
451 json_object_object_add(json
, "importRts", json_import_rtl
);
453 vty_out(vty
, " Export Route Target:\n");
455 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
456 ecom_str
= ecommunity_ecom2str(ecom
,
457 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
460 json_object_array_add(json_export_rtl
,
461 json_object_new_string(ecom_str
));
463 vty_out(vty
, " %s\n", ecom_str
);
465 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
469 json_object_object_add(json
, "exportRts", json_export_rtl
);
472 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
474 char buf1
[RD_ADDRSTRLEN
];
476 struct listnode
*node
, *nnode
;
477 struct ecommunity
*ecom
;
478 json_object
*json_import_rtl
= NULL
;
479 json_object
*json_export_rtl
= NULL
;
480 struct bgp
*bgp_evpn
;
482 bgp_evpn
= bgp_get_evpn();
485 json_import_rtl
= json_object_new_array();
486 json_export_rtl
= json_object_new_array();
487 json_object_int_add(json
, "vni", vpn
->vni
);
488 json_object_string_add(json
, "type", "L2");
489 json_object_string_add(json
, "inKernel",
490 is_vni_live(vpn
) ? "True" : "False");
491 json_object_string_add(
493 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
494 json_object_string_addf(json
, "originatorIp", "%pI4",
495 &vpn
->originator_ip
);
496 json_object_string_addf(json
, "mcastGroup", "%pI4",
498 /* per vni knob is enabled -- Enabled
499 * Global knob is enabled -- Active
500 * default -- Disabled
502 if (!vpn
->advertise_gw_macip
&&
503 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
504 json_object_string_add(json
, "advertiseGatewayMacip",
506 else if (vpn
->advertise_gw_macip
)
507 json_object_string_add(json
, "advertiseGatewayMacip",
510 json_object_string_add(json
, "advertiseGatewayMacip",
512 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
513 bgp_evpn
->evpn_info
->advertise_svi_macip
)
514 json_object_string_add(json
, "advertiseSviMacIp",
516 else if (vpn
->advertise_svi_macip
)
517 json_object_string_add(json
, "advertiseSviMacIp",
520 json_object_string_add(json
, "advertiseSviMacIp",
522 json_object_string_add(
523 json
, "sviInterface",
524 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
526 vty_out(vty
, "VNI: %d", vpn
->vni
);
527 if (is_vni_live(vpn
))
528 vty_out(vty
, " (known to the kernel)");
531 vty_out(vty
, " Type: %s\n", "L2");
532 vty_out(vty
, " Tenant-Vrf: %s\n",
533 vrf_id_to_name(vpn
->tenant_vrf_id
));
534 vty_out(vty
, " RD: %s\n",
535 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
536 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
537 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
538 if (!vpn
->advertise_gw_macip
&&
539 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
540 vty_out(vty
, " Advertise-gw-macip : %s\n",
542 else if (vpn
->advertise_gw_macip
)
543 vty_out(vty
, " Advertise-gw-macip : %s\n",
546 vty_out(vty
, " Advertise-gw-macip : %s\n",
548 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
549 bgp_evpn
->evpn_info
->advertise_svi_macip
)
550 vty_out(vty
, " Advertise-svi-macip : %s\n",
552 else if (vpn
->advertise_svi_macip
)
553 vty_out(vty
, " Advertise-svi-macip : %s\n",
556 vty_out(vty
, " Advertise-svi-macip : %s\n",
558 vty_out(vty
, " SVI interface : %s\n",
559 ifindex2ifname(vpn
->svi_ifindex
, vpn
->tenant_vrf_id
));
563 vty_out(vty
, " Import Route Target:\n");
565 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
566 ecom_str
= ecommunity_ecom2str(ecom
,
567 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
570 json_object_array_add(json_import_rtl
,
571 json_object_new_string(ecom_str
));
573 vty_out(vty
, " %s\n", ecom_str
);
575 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
579 json_object_object_add(json
, "importRts", json_import_rtl
);
581 vty_out(vty
, " Export Route Target:\n");
583 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
584 ecom_str
= ecommunity_ecom2str(ecom
,
585 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
588 json_object_array_add(json_export_rtl
,
589 json_object_new_string(ecom_str
));
591 vty_out(vty
, " %s\n", ecom_str
);
593 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
597 json_object_object_add(json
, "exportRts", json_export_rtl
);
600 static void show_esi_routes(struct bgp
*bgp
,
601 struct bgp_evpn_es
*es
,
606 struct bgp_dest
*dest
;
607 struct bgp_path_info
*pi
;
608 uint32_t prefix_cnt
, path_cnt
;
611 prefix_cnt
= path_cnt
= 0;
613 tbl_ver
= es
->route_table
->version
;
614 for (dest
= bgp_table_top(es
->route_table
); dest
;
615 dest
= bgp_route_next(dest
)) {
616 int add_prefix_to_json
= 0;
617 json_object
*json_paths
= NULL
;
618 json_object
*json_prefix
= NULL
;
619 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
622 json_prefix
= json_object_new_object();
624 pi
= bgp_dest_get_bgp_path_info(dest
);
626 /* Overall header/legend displayed once. */
628 bgp_evpn_show_route_header(vty
, bgp
,
637 json_paths
= json_object_new_array();
639 /* For EVPN, the prefix is displayed for each path (to fit in
640 * with code that already exists).
642 for (; pi
; pi
= pi
->next
) {
643 json_object
*json_path
= NULL
;
646 json_path
= json_object_new_array();
648 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
652 json_object_array_add(json_paths
, json_path
);
655 add_prefix_to_json
= 1;
659 if (add_prefix_to_json
) {
660 json_object_string_addf(json_prefix
, "prefix",
662 json_object_int_add(json_prefix
, "prefixLen",
664 json_object_object_add(json_prefix
, "paths",
666 json_object_object_addf(json
, json_prefix
,
669 json_object_free(json_paths
);
670 json_object_free(json_prefix
);
678 json_object_int_add(json
, "numPrefix", prefix_cnt
);
679 json_object_int_add(json
, "numPaths", path_cnt
);
682 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
684 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
685 prefix_cnt
, path_cnt
);
689 /* Display all MAC-IP VNI routes linked to an ES */
690 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
691 json_object
*json
, int detail
,
695 struct bgp_path_info
*pi
;
696 int header
= detail
? 0 : 1;
698 struct listnode
*node
;
699 struct bgp_evpn_es
*es
;
700 struct bgp_path_es_info
*es_info
;
701 struct bgp
*bgp
= bgp_get_evpn();
702 json_object
*json_paths
= NULL
;
710 json_paths
= json_object_new_array();
712 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
713 struct list
*es_list
;
715 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
719 es_list
= es
->macip_global_path_list
;
721 es_list
= es
->macip_evi_path_list
;
723 for (ALL_LIST_ELEMENTS_RO(es_list
, node
, es_info
)) {
724 json_object
*json_path
= NULL
;
729 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
732 /* Overall header/legend displayed once. */
734 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
741 json_path
= json_object_new_array();
744 route_vty_out_detail(
745 vty
, bgp
, rn
, pi
, AFI_L2VPN
, SAFI_EVPN
,
746 RPKI_NOT_BEING_USED
, json_path
);
748 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
752 json_object_array_add(json_paths
, json_path
);
757 json_object_object_add(json
, "paths", json_paths
);
758 json_object_int_add(json
, "numPaths", path_cnt
);
761 vty_out(vty
, "There are no MAC-IP ES paths");
763 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
768 static void bgp_evpn_show_routes_mac_ip_evi_es(struct vty
*vty
, esi_t
*esi
,
769 json_object
*json
, int detail
)
771 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, false);
774 static void bgp_evpn_show_routes_mac_ip_global_es(struct vty
*vty
, esi_t
*esi
,
775 json_object
*json
, int detail
)
777 bgp_evpn_show_routes_mac_ip_es(vty
, esi
, json
, detail
, true);
780 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
781 struct vty
*vty
, struct in_addr vtep_ip
,
782 json_object
*json
, int detail
)
784 struct bgp_dest
*dest
;
785 struct bgp_path_info
*pi
;
786 struct bgp_table
*table
;
787 int header
= detail
? 0 : 1;
789 uint32_t prefix_cnt
, path_cnt
;
791 prefix_cnt
= path_cnt
= 0;
793 table
= vpn
->route_table
;
794 tbl_ver
= table
->version
;
795 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
796 const struct prefix_evpn
*evp
=
797 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
798 int add_prefix_to_json
= 0;
799 json_object
*json_paths
= NULL
;
800 json_object
*json_prefix
= NULL
;
801 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
803 if (type
&& evp
->prefix
.route_type
!= type
)
807 json_prefix
= json_object_new_object();
809 pi
= bgp_dest_get_bgp_path_info(dest
);
811 /* Overall header/legend displayed once. */
813 bgp_evpn_show_route_header(vty
, bgp
,
822 json_paths
= json_object_new_array();
824 /* For EVPN, the prefix is displayed for each path (to fit in
825 * with code that already exists).
827 for (; pi
; pi
= pi
->next
) {
828 json_object
*json_path
= NULL
;
830 if (vtep_ip
.s_addr
!= INADDR_ANY
831 && !IPV4_ADDR_SAME(&(vtep_ip
),
832 &(pi
->attr
->nexthop
)))
836 json_path
= json_object_new_array();
839 route_vty_out_detail(vty
, bgp
, dest
, pi
,
840 AFI_L2VPN
, SAFI_EVPN
,
844 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
848 json_object_array_add(json_paths
, json_path
);
851 add_prefix_to_json
= 1;
855 if (add_prefix_to_json
) {
856 json_object_string_addf(json_prefix
, "prefix",
858 json_object_int_add(json_prefix
, "prefixLen",
860 json_object_object_add(json_prefix
, "paths",
862 json_object_object_addf(json
, json_prefix
,
865 json_object_free(json_paths
);
866 json_object_free(json_prefix
);
874 json_object_int_add(json
, "numPrefix", prefix_cnt
);
875 json_object_int_add(json
, "numPaths", path_cnt
);
878 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
879 type
? "(of requested type) " : "");
881 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
882 prefix_cnt
, path_cnt
,
883 type
? " (of requested type)" : "");
888 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
890 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
891 struct vni_walk_ctx
*wctx
= arg
;
892 struct vty
*vty
= wctx
->vty
;
893 json_object
*json
= wctx
->json
;
894 json_object
*json_vni
= NULL
;
895 char vni_str
[VNI_STR_LEN
];
897 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
899 json_vni
= json_object_new_object();
900 json_object_int_add(json_vni
, "vni", vpn
->vni
);
902 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
905 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
909 json_object_object_add(json
, vni_str
, json_vni
);
912 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
915 json_object
*json_vni
= NULL
;
916 json_object
*json_import_rtl
= NULL
;
917 json_object
*json_export_rtl
= NULL
;
919 char buf2
[INET6_ADDRSTRLEN
];
922 struct listnode
*node
, *nnode
;
923 struct ecommunity
*ecom
;
929 json_vni
= json_object_new_object();
930 json_import_rtl
= json_object_new_array();
931 json_export_rtl
= json_object_new_array();
934 /* if an l3vni is present in bgp it is live */
936 snprintf(buf1
, sizeof(buf1
), "*");
939 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
940 json_object_string_add(json_vni
, "type", "L3");
941 json_object_string_add(json_vni
, "inKernel", "True");
942 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
943 &bgp
->originator_ip
);
944 json_object_string_add(
946 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
947 json_object_string_add(json_vni
, "advertiseGatewayMacip",
949 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
950 json_object_string_add(
951 json_vni
, "advertisePip",
952 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
953 json_object_string_addf(json_vni
, "sysIP", "%pI4",
954 &bgp
->evpn_info
->pip_ip
);
955 json_object_string_add(json_vni
, "sysMAC",
956 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
957 buf2
, sizeof(buf2
)));
958 json_object_string_add(
960 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
962 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
963 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
966 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
967 ecom_str
= ecommunity_ecom2str(ecom
,
968 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
971 json_object_array_add(json_import_rtl
,
972 json_object_new_string(ecom_str
));
974 if (listcount(bgp
->vrf_import_rtl
) > 1)
975 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
978 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
980 vty_out(vty
, " %-25s", rt_buf
);
983 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
985 /* If there are multiple import RTs we break here and show only
992 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
994 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
995 ecom_str
= ecommunity_ecom2str(ecom
,
996 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
999 json_object_array_add(json_export_rtl
,
1000 json_object_new_string(ecom_str
));
1002 if (listcount(bgp
->vrf_export_rtl
) > 1)
1003 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1006 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1008 vty_out(vty
, " %-25s", rt_buf
);
1011 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1013 /* If there are multiple export RTs we break here and show only
1016 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1022 char vni_str
[VNI_STR_LEN
];
1024 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1025 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1026 json_object_object_add(json
, vni_str
, json_vni
);
1032 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1036 json_object
*json_vni
= NULL
;
1037 json_object
*json_import_rtl
= NULL
;
1038 json_object
*json_export_rtl
= NULL
;
1039 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1041 char buf2
[RD_ADDRSTRLEN
];
1044 struct listnode
*node
, *nnode
;
1045 struct ecommunity
*ecom
;
1046 struct bgp
*bgp_evpn
;
1051 bgp_evpn
= bgp_get_evpn();
1054 json_vni
= json_object_new_object();
1055 json_import_rtl
= json_object_new_array();
1056 json_export_rtl
= json_object_new_array();
1060 if (is_vni_live(vpn
))
1061 snprintf(buf1
, sizeof(buf1
), "*");
1064 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1065 json_object_string_add(json_vni
, "type", "L2");
1066 json_object_string_add(json_vni
, "inKernel",
1067 is_vni_live(vpn
) ? "True" : "False");
1068 json_object_string_add(
1070 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1071 json_object_string_addf(json_vni
, "originatorIp", "%pI4",
1072 &vpn
->originator_ip
);
1073 json_object_string_addf(json_vni
, "mcastGroup", "%pI4",
1075 /* per vni knob is enabled -- Enabled
1076 * Global knob is enabled -- Active
1077 * default -- Disabled
1079 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1080 && bgp_evpn
->advertise_gw_macip
)
1081 json_object_string_add(
1082 json_vni
, "advertiseGatewayMacip", "Active");
1083 else if (vpn
->advertise_gw_macip
)
1084 json_object_string_add(
1085 json_vni
, "advertiseGatewayMacip", "Enabled");
1087 json_object_string_add(
1088 json_vni
, "advertiseGatewayMacip", "Disabled");
1089 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1090 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1091 json_object_string_add(json_vni
, "advertiseSviMacIp",
1093 else if (vpn
->advertise_svi_macip
)
1094 json_object_string_add(json_vni
, "advertiseSviMacIp",
1097 json_object_string_add(json_vni
, "advertiseSviMacIp",
1100 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1101 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1104 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1105 ecom_str
= ecommunity_ecom2str(ecom
,
1106 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1109 json_object_array_add(json_import_rtl
,
1110 json_object_new_string(ecom_str
));
1112 if (listcount(vpn
->import_rtl
) > 1)
1113 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1116 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1118 vty_out(vty
, " %-25s", rt_buf
);
1121 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1123 /* If there are multiple import RTs we break here and show only
1130 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1132 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1133 ecom_str
= ecommunity_ecom2str(ecom
,
1134 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1137 json_object_array_add(json_export_rtl
,
1138 json_object_new_string(ecom_str
));
1140 if (listcount(vpn
->export_rtl
) > 1)
1141 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1144 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1146 vty_out(vty
, " %-25s", rt_buf
);
1149 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1151 /* If there are multiple export RTs we break here and show only
1154 vty_out(vty
, "%-37s",
1155 vrf_id_to_name(vpn
->tenant_vrf_id
));
1161 char vni_str
[VNI_STR_LEN
];
1163 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1164 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1165 json_object_object_add(json
, vni_str
, json_vni
);
1171 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1172 enum bgp_show_type type
, void *output_arg
,
1173 int option
, bool use_json
)
1175 afi_t afi
= AFI_L2VPN
;
1177 struct bgp_table
*table
;
1178 struct bgp_dest
*dest
;
1179 struct bgp_dest
*rm
;
1180 struct bgp_path_info
*pi
;
1183 char rd_str
[RD_ADDRSTRLEN
];
1186 unsigned long output_count
= 0;
1187 unsigned long total_count
= 0;
1188 json_object
*json
= NULL
;
1189 json_object
*json_array
= NULL
;
1190 json_object
*json_prefix_info
= NULL
;
1192 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1194 bgp
= bgp_get_evpn();
1197 vty_out(vty
, "No BGP process is configured\n");
1199 vty_out(vty
, "{}\n");
1204 json
= json_object_new_object();
1206 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1207 dest
= bgp_route_next(dest
)) {
1209 json_object
*json_nroute
= NULL
;
1210 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1212 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1215 table
= bgp_dest_get_bgp_table_info(dest
);
1220 tbl_ver
= table
->version
;
1222 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1223 pi
= bgp_dest_get_bgp_path_info(rm
);
1228 for (; pi
; pi
= pi
->next
) {
1229 struct community
*picomm
= NULL
;
1231 picomm
= bgp_attr_get_community(pi
->attr
);
1234 if (type
== bgp_show_type_neighbor
) {
1235 struct peer
*peer
= output_arg
;
1237 if (peer_cmp(peer
, pi
->peer
) != 0)
1240 if (type
== bgp_show_type_lcommunity_exact
) {
1241 struct lcommunity
*lcom
= output_arg
;
1243 if (!bgp_attr_get_lcommunity(
1246 bgp_attr_get_lcommunity(
1251 if (type
== bgp_show_type_lcommunity
) {
1252 struct lcommunity
*lcom
= output_arg
;
1254 if (!bgp_attr_get_lcommunity(
1257 bgp_attr_get_lcommunity(
1262 if (type
== bgp_show_type_community
) {
1263 struct community
*com
= output_arg
;
1266 !community_match(picomm
, com
))
1269 if (type
== bgp_show_type_community_exact
) {
1270 struct community
*com
= output_arg
;
1273 !community_cmp(picomm
, com
))
1278 json_object_int_add(
1279 json
, "bgpTableVersion",
1281 json_object_string_addf(
1286 json_object_int_add(
1289 bgp
->default_local_pref
);
1290 json_object_int_add(
1294 if (option
== SHOW_DISPLAY_TAGS
)
1299 == SHOW_DISPLAY_OVERLAY
)
1303 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1311 json_object_new_object();
1312 bgp_evpn_show_route_rd_header(
1313 vty
, dest
, json_nroute
, rd_str
,
1317 if (use_json
&& !json_array
)
1318 json_array
= json_object_new_array();
1320 if (option
== SHOW_DISPLAY_TAGS
)
1322 vty
, bgp_dest_get_prefix(rm
),
1323 pi
, no_display
, SAFI_EVPN
,
1325 else if (option
== SHOW_DISPLAY_OVERLAY
)
1326 route_vty_out_overlay(
1327 vty
, bgp_dest_get_prefix(rm
),
1328 pi
, no_display
, json_array
);
1331 bgp_dest_get_prefix(rm
),
1332 pi
, no_display
, SAFI_EVPN
,
1340 if (use_json
&& json_array
) {
1341 const struct prefix
*p
=
1342 bgp_dest_get_prefix(rm
);
1344 json_prefix_info
= json_object_new_object();
1346 json_object_string_addf(json_prefix_info
,
1347 "prefix", "%pFX", p
);
1349 json_object_int_add(json_prefix_info
,
1350 "prefixLen", p
->prefixlen
);
1352 json_object_object_add(json_prefix_info
,
1353 "paths", json_array
);
1354 json_object_object_addf(json_nroute
,
1361 if (use_json
&& json_nroute
)
1362 json_object_object_add(json
, rd_str
, json_nroute
);
1366 json_object_int_add(json
, "numPrefix", output_count
);
1367 json_object_int_add(json
, "totalPrefix", total_count
);
1368 vty_json(vty
, json
);
1370 if (output_count
== 0)
1371 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1375 "\nDisplayed %ld out of %ld total prefixes\n",
1376 output_count
, total_count
);
1381 DEFUN(show_ip_bgp_l2vpn_evpn
,
1382 show_ip_bgp_l2vpn_evpn_cmd
,
1383 "show [ip] bgp l2vpn evpn [json]",
1384 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1386 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1387 SHOW_DISPLAY_STANDARD
,
1388 use_json(argc
, argv
));
1391 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1392 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1393 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> [json]",
1399 "Display information for a route distinguisher\n"
1400 "VPN Route Distinguisher\n"
1401 "All VPN Route Distinguishers\n"
1404 int idx_ext_community
= 0;
1406 struct prefix_rd prd
;
1409 if (argv_find(argv
, argc
, "all", &rd_all
))
1410 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1411 NULL
, SHOW_DISPLAY_STANDARD
,
1412 use_json(argc
, argv
));
1414 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1415 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1417 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1420 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1421 SHOW_DISPLAY_STANDARD
,
1422 use_json(argc
, argv
));
1425 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1426 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1427 "show [ip] bgp l2vpn evpn all tags",
1433 "Display information about all EVPN NLRIs\n"
1434 "Display BGP tags for prefixes\n")
1436 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1437 SHOW_DISPLAY_TAGS
, 0);
1440 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1441 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1442 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> tags",
1448 "Display information for a route distinguisher\n"
1449 "VPN Route Distinguisher\n"
1450 "All VPN Route Distinguishers\n"
1451 "Display BGP tags for prefixes\n")
1453 int idx_ext_community
= 0;
1455 struct prefix_rd prd
;
1458 if (argv_find(argv
, argc
, "all", &rd_all
))
1459 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1460 NULL
, SHOW_DISPLAY_TAGS
, 0);
1462 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1463 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1465 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1468 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1469 SHOW_DISPLAY_TAGS
, 0);
1472 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1473 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1474 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1480 "Detailed information on TCP and BGP neighbor connections\n"
1481 "IPv4 Neighbor to display information about\n"
1482 "IPv6 Neighbor to display information about\n"
1483 "Neighbor on BGP configured interface\n"
1484 "Display routes learned from neighbor\n" JSON_STR
)
1488 char *peerstr
= NULL
;
1489 bool uj
= use_json(argc
, argv
);
1490 afi_t afi
= AFI_L2VPN
;
1491 safi_t safi
= SAFI_EVPN
;
1492 struct bgp
*bgp
= NULL
;
1494 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1497 vty_out(vty
, "No index\n");
1501 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1502 argv_find(argv
, argc
, "neighbors", &idx
);
1503 peerstr
= argv
[++idx
]->arg
;
1505 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1508 json_object
*json_no
= NULL
;
1509 json_no
= json_object_new_object();
1510 json_object_string_add(json_no
, "warning",
1511 "Malformed address");
1512 vty_out(vty
, "%s\n",
1513 json_object_to_json_string(json_no
));
1514 json_object_free(json_no
);
1516 vty_out(vty
, "Malformed address: %s\n",
1520 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1522 json_object
*json_no
= NULL
;
1523 json_no
= json_object_new_object();
1524 json_object_string_add(
1526 "No such neighbor or address family");
1527 vty_out(vty
, "%s\n",
1528 json_object_to_json_string(json_no
));
1529 json_object_free(json_no
);
1531 vty_out(vty
, "%% No such neighbor or address family\n");
1535 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
,
1536 SHOW_DISPLAY_STANDARD
, uj
);
1539 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1540 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1541 "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]",
1547 "Display information for a route distinguisher\n"
1548 "VPN Route Distinguisher\n"
1549 "All VPN Route Distinguishers\n"
1550 "Detailed information on TCP and BGP neighbor connections\n"
1551 "IPv4 Neighbor to display information about\n"
1552 "IPv6 Neighbor to display information about\n"
1553 "Neighbor on BGP configured interface\n"
1554 "Display routes learned from neighbor\n" JSON_STR
)
1556 int idx_ext_community
= 0;
1560 char *peerstr
= NULL
;
1561 struct prefix_rd prd
= {};
1562 bool uj
= use_json(argc
, argv
);
1563 afi_t afi
= AFI_L2VPN
;
1564 safi_t safi
= SAFI_EVPN
;
1565 struct bgp
*bgp
= NULL
;
1568 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1571 vty_out(vty
, "No index\n");
1575 if (argv_find(argv
, argc
, "all", &rd_all
)) {
1576 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1577 &idx_ext_community
);
1578 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1581 json_object
*json_no
= NULL
;
1582 json_no
= json_object_new_object();
1583 json_object_string_add(
1585 "Malformed Route Distinguisher");
1586 vty_out(vty
, "%s\n",
1587 json_object_to_json_string(json_no
));
1588 json_object_free(json_no
);
1591 "%% Malformed Route Distinguisher\n");
1596 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1597 argv_find(argv
, argc
, "neighbors", &idx
);
1598 peerstr
= argv
[++idx
]->arg
;
1600 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1603 json_object
*json_no
= NULL
;
1604 json_no
= json_object_new_object();
1605 json_object_string_add(json_no
, "warning",
1606 "Malformed address");
1607 vty_out(vty
, "%s\n",
1608 json_object_to_json_string(json_no
));
1609 json_object_free(json_no
);
1611 vty_out(vty
, "Malformed address: %s\n",
1615 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1617 json_object
*json_no
= NULL
;
1618 json_no
= json_object_new_object();
1619 json_object_string_add(
1621 "No such neighbor or address family");
1622 vty_out(vty
, "%s\n",
1623 json_object_to_json_string(json_no
));
1624 json_object_free(json_no
);
1626 vty_out(vty
, "%% No such neighbor or address family\n");
1632 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
,
1633 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1635 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
,
1636 peer
, SHOW_DISPLAY_STANDARD
, uj
);
1639 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1640 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1641 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1647 "Detailed information on TCP and BGP neighbor connections\n"
1648 "IPv4 Neighbor to display information about\n"
1649 "IPv6 Neighbor to display information about\n"
1650 "Neighbor on BGP configured interface\n"
1651 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1655 bool uj
= use_json(argc
, argv
);
1656 struct bgp
*bgp
= NULL
;
1657 afi_t afi
= AFI_L2VPN
;
1658 safi_t safi
= SAFI_EVPN
;
1659 char *peerstr
= NULL
;
1664 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1667 vty_out(vty
, "No index\n");
1671 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1672 argv_find(argv
, argc
, "neighbors", &idx
);
1673 peerstr
= argv
[++idx
]->arg
;
1675 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1678 json_object
*json_no
= NULL
;
1679 json_no
= json_object_new_object();
1680 json_object_string_add(json_no
, "warning",
1681 "Malformed address");
1682 vty_out(vty
, "%s\n",
1683 json_object_to_json_string(json_no
));
1684 json_object_free(json_no
);
1686 vty_out(vty
, "Malformed address: %s\n",
1690 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1692 json_object
*json_no
= NULL
;
1693 json_no
= json_object_new_object();
1694 json_object_string_add(
1696 "No such neighbor or address family");
1697 vty_out(vty
, "%s\n",
1698 json_object_to_json_string(json_no
));
1699 json_object_free(json_no
);
1701 vty_out(vty
, "%% No such neighbor or address family\n");
1705 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1708 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1709 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1710 "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]",
1716 "Display information for a route distinguisher\n"
1717 "VPN Route Distinguisher\n"
1718 "All VPN Route Distinguishers\n"
1719 "Detailed information on TCP and BGP neighbor connections\n"
1720 "IPv4 Neighbor to display information about\n"
1721 "IPv6 Neighbor to display information about\n"
1722 "Neighbor on BGP configured interface\n"
1723 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1725 int idx_ext_community
= 0;
1729 struct prefix_rd prd
;
1730 struct bgp
*bgp
= NULL
;
1731 bool uj
= use_json(argc
, argv
);
1732 char *peerstr
= NULL
;
1733 afi_t afi
= AFI_L2VPN
;
1734 safi_t safi
= SAFI_EVPN
;
1743 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1746 vty_out(vty
, "No index\n");
1750 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1751 argv_find(argv
, argc
, "neighbors", &idx
);
1752 peerstr
= argv
[++idx
]->arg
;
1754 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1757 json_object
*json_no
= NULL
;
1758 json_no
= json_object_new_object();
1759 json_object_string_add(json_no
, "warning",
1760 "Malformed address");
1761 vty_out(vty
, "%s\n",
1762 json_object_to_json_string(json_no
));
1763 json_object_free(json_no
);
1765 vty_out(vty
, "Malformed address: %s\n",
1769 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1771 json_object
*json_no
= NULL
;
1772 json_no
= json_object_new_object();
1773 json_object_string_add(
1775 "No such neighbor or address family");
1776 vty_out(vty
, "%s\n",
1777 json_object_to_json_string(json_no
));
1778 json_object_free(json_no
);
1780 vty_out(vty
, "%% No such neighbor or address family\n");
1784 if (argv_find(argv
, argc
, "all", &rd_all
))
1785 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
,
1788 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
1789 &idx_ext_community
);
1790 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1793 json_object
*json_no
= NULL
;
1794 json_no
= json_object_new_object();
1795 json_object_string_add(
1797 "Malformed Route Distinguisher");
1798 vty_out(vty
, "%s\n",
1799 json_object_to_json_string(json_no
));
1800 json_object_free(json_no
);
1803 "%% Malformed Route Distinguisher\n");
1808 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1811 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1812 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1813 "show [ip] bgp l2vpn evpn all overlay [json]",
1819 "Display information about all EVPN NLRIs\n"
1820 "Display BGP Overlay Information for prefixes\n"
1823 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1824 SHOW_DISPLAY_OVERLAY
,
1825 use_json(argc
, argv
));
1828 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1829 show_ip_bgp_evpn_rd_overlay_cmd
,
1830 "show [ip] bgp l2vpn evpn rd <ASN:NN_OR_IP-ADDRESS:NN|all> overlay",
1836 "Display information for a route distinguisher\n"
1837 "VPN Route Distinguisher\n"
1838 "All VPN Route Distinguishers\n"
1839 "Display BGP Overlay Information for prefixes\n")
1841 int idx_ext_community
= 0;
1843 struct prefix_rd prd
;
1846 if (argv_find(argv
, argc
, "all", &rd_all
))
1847 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
,
1848 NULL
, SHOW_DISPLAY_OVERLAY
,
1849 use_json(argc
, argv
));
1851 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1852 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1854 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1857 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1858 SHOW_DISPLAY_OVERLAY
,
1859 use_json(argc
, argv
));
1862 DEFUN(show_bgp_l2vpn_evpn_com
,
1863 show_bgp_l2vpn_evpn_com_cmd
,
1864 "show bgp l2vpn evpn \
1865 <community AA:NN|large-community AA:BB:CC> \
1866 [exact-match] [json]",
1871 "Display routes matching the community\n"
1872 "Community number where AA and NN are (0-65535)\n"
1873 "Display routes matching the large-community\n"
1874 "List of large-community numbers\n"
1875 "Exact match of the communities\n"
1880 const char *clist_number_or_name
;
1881 int show_type
= bgp_show_type_normal
;
1882 struct community
*com
;
1883 struct lcommunity
*lcom
;
1885 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1886 clist_number_or_name
= argv
[++idx
]->arg
;
1887 show_type
= bgp_show_type_lcommunity
;
1889 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1890 show_type
= bgp_show_type_lcommunity_exact
;
1892 lcom
= lcommunity_str2com(clist_number_or_name
);
1894 vty_out(vty
, "%% Large-community malformed\n");
1898 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1899 SHOW_DISPLAY_STANDARD
,
1900 use_json(argc
, argv
));
1902 lcommunity_free(&lcom
);
1903 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1904 clist_number_or_name
= argv
[++idx
]->arg
;
1905 show_type
= bgp_show_type_community
;
1907 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1908 show_type
= bgp_show_type_community_exact
;
1910 com
= community_str2com(clist_number_or_name
);
1913 vty_out(vty
, "%% Community malformed: %s\n",
1914 clist_number_or_name
);
1918 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1919 SHOW_DISPLAY_STANDARD
,
1920 use_json(argc
, argv
));
1921 community_free(&com
);
1927 /* For testing purpose, static route of EVPN RT-5. */
1928 DEFUN(evpnrt5_network
,
1929 evpnrt5_network_cmd
,
1930 "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]",
1931 "Specify a network to announce via BGP\n"
1934 "Specify Route Distinguisher\n"
1935 "VPN Route Distinguisher\n"
1937 "Ethernet Tag Value\n"
1940 "Ethernet Segment Identifier\n"
1941 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1943 "Gateway IP ( A.B.C.D )\n"
1944 "Gateway IPv6 ( X:X::X:X )\n"
1945 "Router Mac Ext Comm\n"
1946 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1947 "Route-map to modify the attributes\n"
1948 "Name of the route map\n")
1950 int idx_ipv4_prefixlen
= 1;
1951 int idx_route_distinguisher
= 3;
1956 int idx_routermac
= 13;
1958 return bgp_static_set_safi(
1959 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1960 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1961 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1962 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1963 argv
[idx_routermac
]->arg
);
1966 /* For testing purpose, static route of EVPN RT-5. */
1967 DEFUN(no_evpnrt5_network
,
1968 no_evpnrt5_network_cmd
,
1969 "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>",
1971 "Specify a network to announce via BGP\n"
1974 "Specify Route Distinguisher\n"
1975 "VPN Route Distinguisher\n"
1977 "Ethernet Tag Value\n"
1980 "Ethernet Segment Identifier\n"
1981 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1982 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1984 int idx_ipv4_prefixlen
= 2;
1985 int idx_ext_community
= 4;
1990 return bgp_static_unset_safi(
1991 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1992 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1993 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1994 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1997 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1999 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
2002 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2004 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
2008 * Configure the Import RTs for a VNI (vty handler). Caller expected to
2009 * check that this is a change.
2011 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2012 struct ecommunity
*ecomadd
)
2014 /* If the VNI is "live", we need to uninstall routes using the current
2015 * import RT(s) first before we update the import RT, and subsequently
2018 if (is_vni_live(vpn
))
2019 bgp_evpn_uninstall_routes(bgp
, vpn
);
2021 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2022 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2024 /* If the auto route-target is in use we must remove it */
2025 evpn_import_rt_delete_auto(bgp
, vpn
);
2027 /* Add new RT and rebuild the RT to VNI mapping */
2028 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
2030 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2031 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2033 /* Install routes that match new import RT */
2034 if (is_vni_live(vpn
))
2035 bgp_evpn_install_routes(bgp
, vpn
);
2039 * Unconfigure Import RT(s) for a VNI (vty handler).
2041 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2042 struct ecommunity
*ecomdel
)
2044 struct listnode
*node
, *nnode
, *node_to_del
;
2045 struct ecommunity
*ecom
;
2047 /* Along the lines of "configure" except we have to reset to the
2050 if (is_vni_live(vpn
))
2051 bgp_evpn_uninstall_routes(bgp
, vpn
);
2053 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2054 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2056 /* Delete all import RTs */
2057 if (ecomdel
== NULL
) {
2058 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2059 ecommunity_free(&ecom
);
2060 list_delete_node(vpn
->import_rtl
, node
);
2064 /* Delete a specific import RT */
2068 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2069 if (ecommunity_match(ecom
, ecomdel
)) {
2070 ecommunity_free(&ecom
);
2077 list_delete_node(vpn
->import_rtl
, node_to_del
);
2080 assert(vpn
->import_rtl
);
2081 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2082 if (list_isempty(vpn
->import_rtl
)) {
2083 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2084 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2086 /* Rebuild the RT to VNI mapping */
2088 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2090 /* Install routes that match new import RT */
2091 if (is_vni_live(vpn
))
2092 bgp_evpn_install_routes(bgp
, vpn
);
2096 * Configure the Export RT for a VNI (vty handler). Caller expected to
2097 * check that this is a change. Note that only a single export RT is
2098 * allowed for a VNI and any change to configuration is implemented as
2099 * a "replace" (similar to other configuration).
2101 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2102 struct ecommunity
*ecomadd
)
2104 /* If the auto route-target is in use we must remove it */
2105 evpn_export_rt_delete_auto(bgp
, vpn
);
2107 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2108 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2110 if (is_vni_live(vpn
))
2111 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2115 * Unconfigure the Export RT for a VNI (vty handler)
2117 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2118 struct ecommunity
*ecomdel
)
2120 struct listnode
*node
, *nnode
, *node_to_del
;
2121 struct ecommunity
*ecom
;
2123 /* Delete all export RTs */
2124 if (ecomdel
== NULL
) {
2125 /* Reset to default and process all routes. */
2126 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2127 ecommunity_free(&ecom
);
2128 list_delete_node(vpn
->export_rtl
, node
);
2132 /* Delete a specific export RT */
2136 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2137 if (ecommunity_match(ecom
, ecomdel
)) {
2138 ecommunity_free(&ecom
);
2145 list_delete_node(vpn
->export_rtl
, node_to_del
);
2148 assert(vpn
->export_rtl
);
2149 if (list_isempty(vpn
->export_rtl
)) {
2150 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2151 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2154 if (is_vni_live(vpn
))
2155 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2159 * Configure RD for VRF
2161 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2163 /* If we have already advertise type-5 routes with a diffrent RD, we
2164 * have to delete and withdraw them firs
2166 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2169 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2170 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2172 /* We have a new RD for VRF.
2173 * Advertise all type-5 routes again with the new RD
2175 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2179 * Unconfigure RD for VRF
2181 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2183 /* If we have already advertise type-5 routes with a diffrent RD, we
2184 * have to delete and withdraw them firs
2186 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2188 /* fall back to default RD */
2189 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2190 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2192 /* We have a new RD for VRF.
2193 * Advertise all type-5 routes again with the new RD
2195 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2199 * Configure RD for a VNI (vty handler)
2201 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2202 struct prefix_rd
*rd
)
2204 /* If the VNI is "live", we need to delete and withdraw this VNI's
2205 * local routes with the prior RD first. Then, after updating RD,
2206 * need to re-advertise.
2208 if (is_vni_live(vpn
))
2209 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2212 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2213 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2215 if (is_vni_live(vpn
))
2216 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2220 * Unconfigure RD for a VNI (vty handler)
2222 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2224 /* If the VNI is "live", we need to delete and withdraw this VNI's
2225 * local routes with the prior RD first. Then, after resetting RD
2226 * to automatic value, need to re-advertise.
2228 if (is_vni_live(vpn
))
2229 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2231 /* reset RD to default */
2232 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2234 if (is_vni_live(vpn
))
2235 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2239 * Create VNI, if not already present (VTY handler). Mark as configured.
2241 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2243 struct bgpevpn
*vpn
;
2244 struct in_addr mcast_grp
= {INADDR_ANY
};
2246 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2248 /* Check if this L2VNI is already configured as L3VNI */
2249 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2252 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2257 /* tenant vrf will be updated when we get local_vni_add from
2260 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
, 0);
2263 /* Mark as configured. */
2264 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2269 * Delete VNI. If VNI does not exist in the system (i.e., just
2270 * configuration), all that is needed is to free it. Otherwise,
2271 * any parameters configured for the VNI need to be reset (with
2272 * appropriate action) and the VNI marked as unconfigured; the
2273 * VNI will continue to exist, purely as a "learnt" entity.
2275 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2277 if (!is_vni_live(vpn
)) {
2278 bgp_evpn_free(bgp
, vpn
);
2282 /* We need to take the unconfigure action for each parameter of this VNI
2283 * that is configured. Some optimization is possible, but not worth the
2284 * additional code for an operation that should be pretty rare.
2286 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2288 /* First, deal with the export side - RD and export RT changes. */
2289 if (is_rd_configured(vpn
))
2290 evpn_unconfigure_rd(bgp
, vpn
);
2291 if (is_export_rt_configured(vpn
))
2292 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2294 /* Next, deal with the import side. */
2295 if (is_import_rt_configured(vpn
))
2296 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2300 * Display import RT mapping to VRFs (vty handler)
2301 * bgp_evpn: evpn bgp instance
2303 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2311 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2312 (void (*)(struct hash_bucket
*,
2313 void *))show_vrf_import_rt_entry
,
2318 * Display import RT mapping to VNIs (vty handler)
2320 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2329 bgp
->import_rt_hash
,
2330 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2335 * Display EVPN routes for all VNIs - vty handler.
2337 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2338 struct in_addr vtep_ip
, json_object
*json
,
2342 struct vni_walk_ctx wctx
;
2344 num_vnis
= hashcount(bgp
->vnihash
);
2347 memset(&wctx
, 0, sizeof(wctx
));
2350 wctx
.vtep_ip
= vtep_ip
;
2352 wctx
.detail
= detail
;
2353 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2354 void *))show_vni_routes_hash
,
2359 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2361 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2362 vni_t vni
, struct in_addr orig_ip
,
2365 struct bgpevpn
*vpn
;
2366 struct prefix_evpn p
;
2367 struct bgp_dest
*dest
;
2368 struct bgp_path_info
*pi
;
2369 uint32_t path_cnt
= 0;
2372 json_object
*json_paths
= NULL
;
2378 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2380 vty_out(vty
, "VNI not found\n");
2384 /* See if route exists. */
2385 build_evpn_type3_prefix(&p
, orig_ip
);
2386 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2387 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2389 vty_out(vty
, "%% Network not in table\n");
2392 bgp_dest_unlock_node(dest
);
2398 json_paths
= json_object_new_array();
2400 /* Prefix and num paths displayed once per prefix. */
2401 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2403 /* Display each path for this prefix. */
2404 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2405 json_object
*json_path
= NULL
;
2408 json_path
= json_object_new_array();
2410 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2411 RPKI_NOT_BEING_USED
, json_path
);
2414 json_object_array_add(json_paths
, json_path
);
2421 json_object_object_add(json
, "paths", json_paths
);
2423 json_object_int_add(json
, "numPaths", path_cnt
);
2425 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2429 bgp_dest_unlock_node(dest
);
2433 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2434 * By definition, only matching type-2 route will be displayed.
2436 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2437 vni_t vni
, struct ethaddr
*mac
,
2438 struct ipaddr
*ip
, json_object
*json
)
2440 struct bgpevpn
*vpn
;
2441 struct prefix_evpn p
;
2442 struct bgp_dest
*dest
;
2443 struct bgp_path_info
*pi
;
2444 uint32_t path_cnt
= 0;
2447 json_object
*json_paths
= NULL
;
2453 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2456 vty_out(vty
, "VNI not found\n");
2460 /* See if route exists. Look for both non-sticky and sticky. */
2461 build_evpn_type2_prefix(&p
, mac
, ip
);
2462 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2463 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2465 vty_out(vty
, "%% Network not in table\n");
2468 bgp_dest_unlock_node(dest
);
2474 json_paths
= json_object_new_array();
2476 /* Prefix and num paths displayed once per prefix. */
2477 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2479 /* Display each path for this prefix. */
2480 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2481 json_object
*json_path
= NULL
;
2484 json_path
= json_object_new_array();
2486 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2487 RPKI_NOT_BEING_USED
, json_path
);
2490 json_object_array_add(json_paths
, json_path
);
2497 json_object_object_add(json
, "paths", json_paths
);
2499 json_object_int_add(json
, "numPaths", path_cnt
);
2501 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2505 bgp_dest_unlock_node(dest
);
2508 /* Disaplay EVPN routes for a ESI - VTY handler */
2509 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2510 esi_t
*esi
, json_object
*json
)
2512 struct bgp_evpn_es
*es
= NULL
;
2515 es
= bgp_evpn_es_find(esi
);
2518 vty_out(vty
, "ESI not found\n");
2522 show_esi_routes(bgp
, es
, vty
, json
);
2526 * Display EVPN routes for a VNI - vty handler.
2527 * If 'type' is non-zero, only routes matching that type are shown.
2528 * If the vtep_ip is non zero, only routes behind that vtep are shown
2530 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2531 int type
, struct in_addr vtep_ip
,
2534 struct bgpevpn
*vpn
;
2537 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2540 vty_out(vty
, "VNI not found\n");
2544 /* Walk this VNI's route table and display appropriate routes. */
2545 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2549 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2550 * IP (vty handler). By definition, only matching type-2 route will be
2553 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2554 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2555 struct ipaddr
*ip
, json_object
*json
)
2557 struct prefix_evpn p
;
2558 struct bgp_dest
*dest
;
2559 struct bgp_path_info
*pi
;
2562 uint32_t path_cnt
= 0;
2563 json_object
*json_paths
= NULL
;
2568 /* See if route exists. Look for both non-sticky and sticky. */
2569 build_evpn_type2_prefix(&p
, mac
, ip
);
2570 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2571 (struct prefix
*)&p
, prd
);
2572 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2574 vty_out(vty
, "%% Network not in table\n");
2577 bgp_dest_unlock_node(dest
);
2582 /* Prefix and num paths displayed once per prefix. */
2583 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2586 json_paths
= json_object_new_array();
2588 /* Display each path for this prefix. */
2589 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2590 json_object
*json_path
= NULL
;
2593 json_path
= json_object_new_array();
2595 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2596 RPKI_NOT_BEING_USED
, json_path
);
2599 json_object_array_add(json_paths
, json_path
);
2604 if (json
&& path_cnt
) {
2606 json_object_object_addf(json
, json_paths
, "%pFX", &p
);
2607 json_object_int_add(json
, "numPaths", path_cnt
);
2609 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2613 bgp_dest_unlock_node(dest
);
2617 * Display BGP EVPN routing table -- for specific RD (vty handler)
2618 * If 'type' is non-zero, only routes matching that type are shown.
2620 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2621 struct prefix_rd
*prd
, int type
,
2624 struct bgp_dest
*rd_dest
;
2625 struct bgp_table
*table
;
2626 struct bgp_dest
*dest
;
2627 struct bgp_path_info
*pi
;
2631 uint32_t prefix_cnt
, path_cnt
;
2632 char rd_str
[RD_ADDRSTRLEN
];
2633 json_object
*json_rd
= NULL
;
2634 int add_rd_to_json
= 0;
2638 prefix_cnt
= path_cnt
= 0;
2640 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2642 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2646 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2647 if (table
== NULL
) {
2648 bgp_dest_unlock_node(rd_dest
);
2653 json_rd
= json_object_new_object();
2654 json_object_string_add(json_rd
, "rd", rd_str
);
2657 bgp_dest_unlock_node(rd_dest
);
2659 /* Display all prefixes with this RD. */
2660 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2661 const struct prefix_evpn
*evp
=
2662 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2663 json_object
*json_prefix
= NULL
;
2664 json_object
*json_paths
= NULL
;
2665 int add_prefix_to_json
= 0;
2667 if (type
&& evp
->prefix
.route_type
!= type
)
2671 json_prefix
= json_object_new_object();
2673 pi
= bgp_dest_get_bgp_path_info(dest
);
2675 /* RD header and legend - once overall. */
2676 if (rd_header
&& !json
) {
2678 "EVPN type-1 prefix: [1]:[EthTag]:[ESI]:[IPlen]:[VTEP-IP]:[Frag-id]\n");
2680 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2682 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2684 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2686 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2690 /* Prefix and num paths displayed once per prefix. */
2691 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2698 json_paths
= json_object_new_array();
2700 /* Display each path for this prefix. */
2701 for (; pi
; pi
= pi
->next
) {
2702 json_object
*json_path
= NULL
;
2705 json_path
= json_object_new_array();
2707 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2708 RPKI_NOT_BEING_USED
, json_path
);
2711 json_object_array_add(json_paths
, json_path
);
2714 add_prefix_to_json
= 1;
2719 if (add_prefix_to_json
) {
2720 json_object_object_add(json_prefix
, "paths",
2722 json_object_object_addf(json_rd
, json_prefix
,
2725 json_object_free(json_paths
);
2726 json_object_free(json_prefix
);
2735 json_object_object_add(json
, rd_str
, json_rd
);
2737 json_object_free(json_rd
);
2741 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2742 json_object_int_add(json
, "numPaths", path_cnt
);
2744 if (prefix_cnt
== 0)
2745 vty_out(vty
, "No prefixes exist with this RD%s\n",
2746 type
? " (of requested type)" : "");
2749 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2750 prefix_cnt
, path_cnt
,
2751 type
? " (of requested type)" : "");
2756 * Display BGP EVPN routing table -- all RDs and MAC and/or IP
2757 * (vty handler). Only matching type-2 routes will be displayed.
2759 static void evpn_show_route_rd_all_macip(struct vty
*vty
, struct bgp
*bgp
,
2760 struct ethaddr
*mac
, struct ipaddr
*ip
,
2763 struct bgp_dest
*rd_dest
;
2764 struct bgp_table
*table
;
2765 struct bgp_dest
*dest
;
2766 struct bgp_path_info
*pi
;
2767 afi_t afi
= AFI_L2VPN
;
2768 safi_t safi
= SAFI_EVPN
;
2769 uint32_t prefix_cnt
, path_cnt
;
2770 prefix_cnt
= path_cnt
= 0;
2772 /* EVPN routing table is a 2-level table with the first level being
2773 * the RD. We need to look in every RD we know about.
2775 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2776 rd_dest
= bgp_route_next(rd_dest
)) {
2777 json_object
*json_paths
= NULL
; /* paths array for prefix */
2778 json_object
*json_prefix
= NULL
; /* prefix within an RD */
2779 json_object
*json_rd
= NULL
; /* holds all prefixes for RD */
2780 char rd_str
[RD_ADDRSTRLEN
];
2781 int add_rd_to_json
= 0;
2782 struct prefix_evpn ep
;
2783 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2785 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2789 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2792 /* Construct an RT-2 from the user-supplied mac(ip),
2793 * then search the l2vpn evpn table for it.
2795 build_evpn_type2_prefix(&ep
, mac
, ip
);
2796 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2797 (struct prefix
*)&ep
,
2798 (struct prefix_rd
*)rd_destp
);
2803 json_rd
= json_object_new_object();
2805 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2807 pi
= bgp_dest_get_bgp_path_info(dest
);
2809 /* RD header - per RD. */
2810 bgp_evpn_show_route_rd_header(vty
, rd_dest
, json_rd
,
2811 rd_str
, RD_ADDRSTRLEN
);
2816 json_prefix
= json_object_new_object();
2817 json_paths
= json_object_new_array();
2818 json_object_string_addf(json_prefix
, "prefix", "%pFX",
2820 json_object_int_add(json_prefix
, "prefixLen",
2823 /* Prefix and num paths displayed once per prefix. */
2824 route_vty_out_detail_header(
2825 vty
, bgp
, dest
, (struct prefix_rd
*)rd_destp
,
2826 AFI_L2VPN
, SAFI_EVPN
, json_prefix
);
2828 /* For EVPN, the prefix is displayed for each path (to
2829 * fit in with code that already exists).
2831 for (; pi
; pi
= pi
->next
) {
2832 json_object
*json_path
= NULL
;
2838 json_path
= json_object_new_array();
2840 route_vty_out_detail(vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2841 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
2845 json_object_array_add(json_paths
, json_path
);
2851 json_object_object_add(json_prefix
, "paths",
2853 json_object_object_addf(json_rd
, json_prefix
, "%pFX",
2856 json_object_object_add(json
, rd_str
, json_rd
);
2858 json_object_free(json_rd
);
2863 bgp_dest_unlock_node(dest
);
2867 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2868 json_object_int_add(json
, "numPaths", path_cnt
);
2870 if (prefix_cnt
== 0) {
2871 vty_out(vty
, "No Matching EVPN prefixes exist\n");
2873 vty_out(vty
, "Displayed %u prefixes (%u paths)\n",
2874 prefix_cnt
, path_cnt
);
2880 * Display BGP EVPN routing table - all routes (vty handler).
2881 * If 'type' is non-zero, only routes matching that type are shown.
2883 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2884 json_object
*json
, int detail
)
2886 struct bgp_dest
*rd_dest
;
2887 struct bgp_table
*table
;
2888 struct bgp_dest
*dest
;
2889 struct bgp_path_info
*pi
;
2890 int header
= detail
? 0 : 1;
2894 uint32_t prefix_cnt
, path_cnt
;
2898 prefix_cnt
= path_cnt
= 0;
2900 /* EVPN routing table is a 2-level table with the first level being
2903 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2904 rd_dest
= bgp_route_next(rd_dest
)) {
2905 char rd_str
[RD_ADDRSTRLEN
];
2906 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2907 int add_rd_to_json
= 0;
2909 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2911 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2915 tbl_ver
= table
->version
;
2916 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2920 json_rd
= json_object_new_object();
2924 /* Display all prefixes for an RD */
2925 for (dest
= bgp_table_top(table
); dest
;
2926 dest
= bgp_route_next(dest
)) {
2927 json_object
*json_prefix
=
2928 NULL
; /* contains prefix under a RD */
2929 json_object
*json_paths
=
2930 NULL
; /* array of paths under a prefix*/
2931 const struct prefix_evpn
*evp
=
2932 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2934 int add_prefix_to_json
= 0;
2935 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2937 if (type
&& evp
->prefix
.route_type
!= type
)
2940 pi
= bgp_dest_get_bgp_path_info(dest
);
2942 /* Overall header/legend displayed once. */
2944 bgp_evpn_show_route_header(vty
, bgp
,
2949 "%19s Extended Community\n"
2954 /* RD header - per RD. */
2956 bgp_evpn_show_route_rd_header(
2957 vty
, rd_dest
, json_rd
, rd_str
,
2966 json_prefix
= json_object_new_object();
2967 json_paths
= json_object_new_array();
2968 json_object_string_addf(json_prefix
, "prefix",
2970 json_object_int_add(json_prefix
, "prefixLen",
2974 /* Prefix and num paths displayed once per prefix. */
2976 route_vty_out_detail_header(
2978 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
2979 SAFI_EVPN
, json_prefix
);
2981 /* For EVPN, the prefix is displayed for each path (to
2983 * with code that already exists).
2985 for (; pi
; pi
= pi
->next
) {
2986 json_object
*json_path
= NULL
;
2989 add_prefix_to_json
= 1;
2993 json_path
= json_object_new_array();
2996 route_vty_out_detail(
2997 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2998 SAFI_EVPN
, RPKI_NOT_BEING_USED
,
3001 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
3005 json_object_array_add(json_paths
,
3010 if (add_prefix_to_json
) {
3011 json_object_object_add(json_prefix
,
3014 json_object_object_addf(json_rd
,
3018 json_object_free(json_prefix
);
3019 json_object_free(json_paths
);
3028 json_object_object_add(json
, rd_str
, json_rd
);
3030 json_object_free(json_rd
);
3037 json_object_int_add(json
, "numPrefix", prefix_cnt
);
3038 json_object_int_add(json
, "numPaths", path_cnt
);
3040 if (prefix_cnt
== 0) {
3041 vty_out(vty
, "No EVPN prefixes %sexist\n",
3042 type
? "(of requested type) " : "");
3044 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
3045 prefix_cnt
, path_cnt
,
3046 type
? " (of requested type)" : "");
3052 * Display specified VNI (vty handler)
3054 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
3058 struct bgpevpn
*vpn
;
3060 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3063 display_vni(vty
, vpn
, json
);
3065 struct bgp
*bgp_temp
;
3066 struct listnode
*node
= NULL
;
3068 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3069 if (bgp_temp
->l3vni
== vni
) {
3071 display_l3vni(vty
, bgp_temp
, json
);
3078 vty_out(vty
, "{}\n");
3080 vty_out(vty
, "VNI not found\n");
3087 * Display a VNI (upon user query).
3089 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
3093 struct bgp
*bgp_temp
= NULL
;
3094 struct listnode
*node
;
3098 vty_out(vty
, "Flags: * - Kernel\n");
3099 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
3100 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
3103 /* print all L2 VNIS */
3106 hash_iterate(bgp
->vnihash
,
3107 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
3110 /* print all L3 VNIs */
3111 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
3112 show_l3vni_entry(vty
, bgp_temp
, json
);
3116 * evpn - enable advertisement of svi MAC-IP
3118 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
3122 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
3124 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
3127 bgp
->evpn_info
->advertise_svi_macip
= set
;
3128 bgp_zebra_advertise_svi_macip(bgp
,
3129 bgp
->evpn_info
->advertise_svi_macip
, 0);
3131 if (set
&& vpn
->advertise_svi_macip
)
3133 else if (!set
&& !vpn
->advertise_svi_macip
)
3136 vpn
->advertise_svi_macip
= set
;
3137 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
3143 * evpn - enable advertisement of default g/w
3145 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3148 if (bgp
->advertise_gw_macip
)
3151 bgp
->advertise_gw_macip
= 1;
3152 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3154 if (vpn
->advertise_gw_macip
)
3157 vpn
->advertise_gw_macip
= 1;
3158 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3165 * evpn - disable advertisement of default g/w
3167 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3168 struct bgpevpn
*vpn
)
3171 if (!bgp
->advertise_gw_macip
)
3174 bgp
->advertise_gw_macip
= 0;
3175 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3177 if (!vpn
->advertise_gw_macip
)
3180 vpn
->advertise_gw_macip
= 0;
3181 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3188 * evpn - enable advertisement of default g/w
3190 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3191 afi_t afi
, bool add
)
3193 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3196 /* bail if we are already advertising default route */
3197 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3201 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3202 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3203 else if (afi
== AFI_IP6
)
3204 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3205 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3207 /* bail out if we havent advertised the default route */
3208 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3211 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3212 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3213 else if (afi
== AFI_IP6
)
3214 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3215 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3218 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3222 * evpn - enable advertisement of default g/w
3224 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3225 struct bgpevpn
*vpn
)
3227 if (vpn
->advertise_subnet
)
3230 vpn
->advertise_subnet
= 1;
3231 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3235 * evpn - disable advertisement of default g/w
3237 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3239 if (!vpn
->advertise_subnet
)
3242 vpn
->advertise_subnet
= 0;
3243 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3247 * EVPN (VNI advertisement) enabled. Register with zebra.
3249 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3251 bgp
->advertise_all_vni
= 1;
3253 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3257 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3258 * cache, EVPN routes (delete and withdraw from peers).
3260 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3262 bgp
->advertise_all_vni
= 0;
3263 bgp_set_evpn(bgp_get_default());
3264 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3265 bgp_evpn_cleanup_on_disable(bgp
);
3268 /* Set resolve overlay index flag */
3269 static void bgp_evpn_set_unset_resolve_overlay_index(struct bgp
*bgp
, bool set
)
3271 if (set
== bgp
->resolve_overlay_index
)
3275 bgp
->resolve_overlay_index
= true;
3276 hash_iterate(bgp
->vnihash
,
3277 (void (*)(struct hash_bucket
*, void *))
3278 bgp_evpn_handle_resolve_overlay_index_set
,
3283 (void (*)(struct hash_bucket
*, void *))
3284 bgp_evpn_handle_resolve_overlay_index_unset
,
3286 bgp
->resolve_overlay_index
= false;
3291 * EVPN - use RFC8365 to auto-derive RT
3293 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3295 bgp
->advertise_autort_rfc8365
= 1;
3296 bgp_evpn_handle_autort_change(bgp
);
3300 * EVPN - don't use RFC8365 to auto-derive RT
3302 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3304 bgp
->advertise_autort_rfc8365
= 0;
3305 bgp_evpn_handle_autort_change(bgp
);
3308 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3310 char buf1
[RD_ADDRSTRLEN
];
3312 struct listnode
*node
, *nnode
;
3313 struct ecommunity
*ecom
;
3315 if (is_vni_configured(vpn
)) {
3316 vty_out(vty
, " vni %d\n", vpn
->vni
);
3317 if (is_rd_configured(vpn
))
3318 vty_out(vty
, " rd %s\n",
3319 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3321 if (is_import_rt_configured(vpn
)) {
3322 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3324 ecom_str
= ecommunity_ecom2str(
3325 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3326 vty_out(vty
, " route-target import %s\n",
3328 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3332 if (is_export_rt_configured(vpn
)) {
3333 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3335 ecom_str
= ecommunity_ecom2str(
3336 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3337 vty_out(vty
, " route-target export %s\n",
3339 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3343 if (vpn
->advertise_gw_macip
)
3344 vty_out(vty
, " advertise-default-gw\n");
3346 if (vpn
->advertise_svi_macip
)
3347 vty_out(vty
, " advertise-svi-ip\n");
3349 if (vpn
->advertise_subnet
)
3350 vty_out(vty
, " advertise-subnet\n");
3352 vty_out(vty
, " exit-vni\n");
3356 #ifndef VTYSH_EXTRACT_PL
3357 #include "bgpd/bgp_evpn_vty_clippy.c"
3360 DEFPY(bgp_evpn_flood_control
,
3361 bgp_evpn_flood_control_cmd
,
3362 "[no$no] flooding <disable$disable|head-end-replication$her>",
3364 "Specify handling for BUM packets\n"
3365 "Do not flood any BUM packets\n"
3366 "Flood BUM packets using head-end replication\n")
3368 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3369 enum vxlan_flood_control flood_ctrl
;
3375 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3377 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3381 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3384 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3385 bgp_evpn_flood_control_change(bgp
);
3390 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3391 bgp_evpn_advertise_default_gw_vni_cmd
,
3392 "advertise-default-gw",
3393 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3395 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3396 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3401 evpn_set_advertise_default_gw(bgp
, vpn
);
3406 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3407 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3408 "no advertise-default-gw",
3410 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3412 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3413 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3418 evpn_unset_advertise_default_gw(bgp
, vpn
);
3424 DEFUN (bgp_evpn_advertise_default_gw
,
3425 bgp_evpn_advertise_default_gw_cmd
,
3426 "advertise-default-gw",
3427 "Advertise All default g/w mac-ip routes in EVPN\n")
3429 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3434 if (!EVPN_ENABLED(bgp
)) {
3436 "This command is only supported under the EVPN VRF\n");
3440 evpn_set_advertise_default_gw(bgp
, NULL
);
3445 DEFUN (no_bgp_evpn_advertise_default_gw
,
3446 no_bgp_evpn_advertise_default_gw_cmd
,
3447 "no advertise-default-gw",
3449 "Withdraw All default g/w mac-ip routes from EVPN\n")
3451 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3456 evpn_unset_advertise_default_gw(bgp
, NULL
);
3461 DEFUN (bgp_evpn_advertise_all_vni
,
3462 bgp_evpn_advertise_all_vni_cmd
,
3463 "advertise-all-vni",
3464 "Advertise All local VNIs\n")
3466 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3467 struct bgp
*bgp_evpn
= NULL
;
3472 bgp_evpn
= bgp_get_evpn();
3473 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3474 vty_out(vty
, "%% Please unconfigure EVPN in %s\n",
3475 bgp_evpn
->name_pretty
);
3476 return CMD_WARNING_CONFIG_FAILED
;
3479 evpn_set_advertise_all_vni(bgp
);
3483 DEFUN (no_bgp_evpn_advertise_all_vni
,
3484 no_bgp_evpn_advertise_all_vni_cmd
,
3485 "no advertise-all-vni",
3487 "Advertise All local VNIs\n")
3489 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3493 evpn_unset_advertise_all_vni(bgp
);
3497 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3498 bgp_evpn_advertise_autort_rfc8365_cmd
,
3499 "autort rfc8365-compatible",
3500 "Auto-derivation of RT\n"
3501 "Auto-derivation of RT using RFC8365\n")
3503 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3507 evpn_set_advertise_autort_rfc8365(bgp
);
3511 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3512 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3513 "no autort rfc8365-compatible",
3515 "Auto-derivation of RT\n"
3516 "Auto-derivation of RT using RFC8365\n")
3518 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3522 evpn_unset_advertise_autort_rfc8365(bgp
);
3526 DEFUN (bgp_evpn_default_originate
,
3527 bgp_evpn_default_originate_cmd
,
3528 "default-originate <ipv4 | ipv6>",
3529 "originate 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
, true);
3544 DEFUN (no_bgp_evpn_default_originate
,
3545 no_bgp_evpn_default_originate_cmd
,
3546 "no default-originate <ipv4 | ipv6>",
3548 "withdraw a default route\n"
3549 "ipv4 address family\n"
3550 "ipv6 address family\n")
3554 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3558 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3559 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3563 DEFPY (dup_addr_detection
,
3564 dup_addr_detection_cmd
,
3565 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3566 "Duplicate address detection\n"
3567 "Max allowed moves before address detected as duplicate\n"
3568 "Num of max allowed moves (2-1000) default 5\n"
3569 "Duplicate address detection time\n"
3570 "Time in seconds (2-1800) default 180\n")
3572 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3577 if (!EVPN_ENABLED(bgp_vrf
)) {
3579 "This command is only supported under the EVPN VRF\n");
3583 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3586 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3588 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3590 bgp_zebra_dup_addr_detection(bgp_vrf
);
3595 DEFPY (dup_addr_detection_auto_recovery
,
3596 dup_addr_detection_auto_recovery_cmd
,
3597 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3598 "Duplicate address detection\n"
3599 "Duplicate address detection freeze\n"
3600 "Duplicate address detection permanent freeze\n"
3601 "Duplicate address detection freeze time (30-3600)\n")
3603 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3604 uint32_t freeze_time
= freeze_time_val
;
3609 if (!EVPN_ENABLED(bgp_vrf
)) {
3611 "This command is only supported under the EVPN VRF\n");
3615 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3616 bgp_vrf
->evpn_info
->dad_freeze
= true;
3617 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3619 bgp_zebra_dup_addr_detection(bgp_vrf
);
3624 DEFPY (no_dup_addr_detection
,
3625 no_dup_addr_detection_cmd
,
3626 "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>]",
3628 "Duplicate address detection\n"
3629 "Max allowed moves before address detected as duplicate\n"
3630 "Num of max allowed moves (2-1000) default 5\n"
3631 "Duplicate address detection time\n"
3632 "Time in seconds (2-1800) default 180\n"
3633 "Duplicate address detection freeze\n"
3634 "Duplicate address detection permanent freeze\n"
3635 "Duplicate address detection freeze time (30-3600)\n")
3637 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3638 uint32_t max_moves
= (uint32_t)max_moves_val
;
3639 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3644 if (!EVPN_ENABLED(bgp_vrf
)) {
3646 "This command is only supported under the EVPN VRF\n");
3651 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3653 /* Reset all parameters to default. */
3654 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3655 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3656 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3657 bgp_vrf
->evpn_info
->dad_freeze
= false;
3658 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3661 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3663 "%% Value does not match with config\n");
3666 bgp_vrf
->evpn_info
->dad_max_moves
=
3667 EVPN_DAD_DEFAULT_MAX_MOVES
;
3671 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3673 "%% Value does not match with config\n");
3676 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3680 if (bgp_vrf
->evpn_info
->dad_freeze_time
3683 "%% Value does not match with config\n");
3686 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3687 bgp_vrf
->evpn_info
->dad_freeze
= false;
3690 if (permanent_val
) {
3691 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3693 "%% Value does not match with config\n");
3696 bgp_vrf
->evpn_info
->dad_freeze
= false;
3700 bgp_zebra_dup_addr_detection(bgp_vrf
);
3705 DEFPY(bgp_evpn_advertise_svi_ip
,
3706 bgp_evpn_advertise_svi_ip_cmd
,
3707 "[no$no] advertise-svi-ip",
3709 "Advertise svi mac-ip routes in EVPN\n")
3711 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3717 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3719 if (!EVPN_ENABLED(bgp
)) {
3721 "This command is only supported under EVPN VRF\n");
3724 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3730 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3731 bgp_evpn_advertise_svi_ip_vni_cmd
,
3732 "[no$no] advertise-svi-ip",
3734 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3736 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3737 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3743 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3745 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3750 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3751 bgp_evpn_advertise_vni_subnet_cmd
,
3753 "Advertise the subnet corresponding to VNI\n")
3755 struct bgp
*bgp_vrf
= NULL
;
3756 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3757 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3762 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3766 evpn_set_advertise_subnet(bgp
, vpn
);
3770 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3771 no_bgp_evpn_advertise_vni_subnet_cmd
,
3772 "no advertise-subnet",
3774 "Advertise All local VNIs\n")
3776 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3777 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3782 evpn_unset_advertise_subnet(bgp
, vpn
);
3786 DEFUN (bgp_evpn_advertise_type5
,
3787 bgp_evpn_advertise_type5_cmd
,
3788 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [gateway-ip] [route-map RMAP_NAME]",
3789 "Advertise prefix routes\n"
3792 "advertise gateway IP overlay index\n"
3793 "route-map for filtering specific routes\n"
3794 "Name of the route map\n")
3796 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3803 int rmap_changed
= 0;
3804 enum overlay_index_type oly
= OVERLAY_INDEX_TYPE_NONE
;
3806 bool adv_flag_changed
= false;
3808 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3809 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3810 argv_find_and_parse_oly_idx(argv
, argc
, &idx_oly
, &oly
);
3812 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3814 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3816 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3817 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3820 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3824 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3826 "%% Only ipv4 or ipv6 address families are supported\n");
3830 if (safi
!= SAFI_UNICAST
) {
3832 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
3836 if ((oly
!= OVERLAY_INDEX_TYPE_NONE
)
3837 && (oly
!= OVERLAY_INDEX_GATEWAY_IP
)) {
3838 vty_out(vty
, "%% Unknown overlay-index type specified\n");
3842 if (afi
== AFI_IP
) {
3843 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3844 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))
3845 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3846 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3849 * this is the case for first time ever configuration
3850 * adv ipv4 unicast is enabled for the first time.
3851 * So no need to reset any flag
3853 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3855 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3856 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3857 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3859 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3860 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3861 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3863 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3864 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
))) {
3867 * This is modify case from gateway-ip
3868 * to no overlay index
3870 adv_flag_changed
= true;
3871 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3872 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3873 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3874 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3875 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3877 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3878 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
3881 * This is modify case from no overlay index
3884 adv_flag_changed
= true;
3885 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3886 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
3887 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3888 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
3892 * Command is issued with the same option
3893 * (no overlay index or gateway-ip) which was
3894 * already configured. So nothing to do.
3895 * However, route-map may have been modified.
3896 * check if route-map has been modified.
3897 * If not, return an error
3903 if ((!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3904 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))
3905 && (!CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3906 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3909 * this is the case for first time ever configuration
3910 * adv ipv6 unicast is enabled for the first time.
3911 * So no need to reset any flag
3913 if (oly
== OVERLAY_INDEX_TYPE_NONE
)
3915 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3916 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3917 else if (oly
== OVERLAY_INDEX_GATEWAY_IP
)
3919 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3920 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3921 } else if ((oly
== OVERLAY_INDEX_TYPE_NONE
)
3923 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3924 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
))) {
3927 * This is modify case from gateway-ip
3928 * to no overlay index
3930 adv_flag_changed
= true;
3931 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3932 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3933 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3934 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3935 } else if ((oly
== OVERLAY_INDEX_GATEWAY_IP
)
3937 bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3938 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))) {
3941 * This is modify case from no overlay index
3944 adv_flag_changed
= true;
3945 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3946 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
3947 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3948 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
3952 * Command is issued with the same option
3953 * (no overlay index or gateway-ip) which was
3954 * already configured. So nothing to do.
3955 * However, route-map may have been modified.
3956 * check if route-map has been modified.
3957 * If not, return an error
3964 if ((rmap_changed
) || (adv_flag_changed
)) {
3966 /* If either of these are changed, then FRR needs to
3967 * withdraw already advertised type5 routes.
3969 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3971 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3972 XFREE(MTYPE_ROUTE_MAP_NAME
,
3973 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3974 route_map_counter_decrement(
3975 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3976 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3977 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3982 /* set the route-map for advertise command */
3983 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3984 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3985 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3986 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3987 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3988 route_map_counter_increment(
3989 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3992 /* advertise type-5 routes */
3993 if (advertise_type5_routes(bgp_vrf
, afi
))
3994 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3998 DEFUN (no_bgp_evpn_advertise_type5
,
3999 no_bgp_evpn_advertise_type5_cmd
,
4000 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
4002 "Advertise prefix routes\n"
4006 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4015 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
4016 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
4018 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
4020 "%% Only ipv4 or ipv6 address families are supported\n");
4024 if (safi
!= SAFI_UNICAST
) {
4026 "%% Only ipv4 unicast or ipv6 unicast are supported\n");
4030 if (afi
== AFI_IP
) {
4032 /* if we are not advertising ipv4 prefix as type-5
4035 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4036 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) ||
4037 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4038 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
))) {
4039 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4040 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4041 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
);
4042 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4043 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
);
4047 /* if we are not advertising ipv6 prefix as type-5
4050 if ((CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4051 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) ||
4052 (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4053 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
))){
4054 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
4055 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4056 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
);
4057 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
4058 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
);
4062 /* clear the route-map information for advertise ipv4/ipv6 unicast */
4063 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
4064 XFREE(MTYPE_ROUTE_MAP_NAME
,
4065 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
4066 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
4067 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
4073 DEFPY (bgp_evpn_use_es_l3nhg
,
4074 bgp_evpn_use_es_l3nhg_cmd
,
4075 "[no$no] use-es-l3nhg",
4077 "use L3 nexthop group for host routes with ES destination\n")
4079 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
4083 DEFPY (bgp_evpn_ead_evi_rx_disable
,
4084 bgp_evpn_ead_evi_rx_disable_cmd
,
4085 "[no$no] disable-ead-evi-rx",
4087 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
4089 bool ead_evi_rx
= no
? true :false;
4091 if (ead_evi_rx
!= bgp_mh_info
->ead_evi_rx
) {
4092 bgp_mh_info
->ead_evi_rx
= ead_evi_rx
;
4093 bgp_evpn_switch_ead_evi_rx();
4098 DEFPY (bgp_evpn_ead_evi_tx_disable
,
4099 bgp_evpn_ead_evi_tx_disable_cmd
,
4100 "[no$no] disable-ead-evi-tx",
4102 "Don't advertise EAD-EVI for local ESs\n")
4104 bgp_mh_info
->ead_evi_tx
= no
? true :false;
4108 DEFPY (bgp_evpn_enable_resolve_overlay_index
,
4109 bgp_evpn_enable_resolve_overlay_index_cmd
,
4110 "[no$no] enable-resolve-overlay-index",
4112 "Enable Recursive Resolution of type-5 route overlay index\n")
4114 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4116 if (bgp
!= bgp_get_evpn()) {
4117 vty_out(vty
, "This command is only supported under EVPN VRF\n");
4121 bgp_evpn_set_unset_resolve_overlay_index(bgp
, no
? false : true);
4125 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
4126 bgp_evpn_advertise_pip_ip_mac_cmd
,
4127 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
4129 "evpn system primary IP\n"
4132 MAC_STR MAC_STR MAC_STR
)
4134 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
4135 struct bgp
*bgp_evpn
= NULL
;
4137 if (EVPN_ENABLED(bgp_vrf
)) {
4139 "This command is supported under L3VNI BGP EVPN VRF\n");
4140 return CMD_WARNING_CONFIG_FAILED
;
4142 bgp_evpn
= bgp_get_evpn();
4145 /* pip is already enabled */
4146 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
4149 bgp_vrf
->evpn_info
->advertise_pip
= true;
4150 if (ip
.s_addr
!= INADDR_ANY
) {
4151 /* Already configured with same IP */
4152 if (IPV4_ADDR_SAME(&ip
,
4153 &bgp_vrf
->evpn_info
->pip_ip_static
))
4156 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
4157 bgp_vrf
->evpn_info
->pip_ip
= ip
;
4159 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
4161 /* default instance router-id assignemt */
4163 bgp_vrf
->evpn_info
->pip_ip
=
4164 bgp_evpn
->router_id
;
4167 if (!is_zero_mac(&mac
->eth_addr
)) {
4168 /* Already configured with same MAC */
4169 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4170 &mac
->eth_addr
, ETH_ALEN
) == 0)
4173 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4174 &mac
->eth_addr
, ETH_ALEN
);
4175 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4176 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4179 /* Copy zebra sys mac */
4180 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4181 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4182 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4187 if (!bgp_vrf
->evpn_info
->advertise_pip
)
4189 /* Disable PIP feature */
4190 bgp_vrf
->evpn_info
->advertise_pip
= false;
4191 /* copy anycast mac */
4192 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4193 &bgp_vrf
->rmac
, ETH_ALEN
);
4195 /* remove MAC-IP option retain PIP knob. */
4196 if ((ip
.s_addr
!= INADDR_ANY
) &&
4197 !IPV4_ADDR_SAME(&ip
,
4198 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
4200 "%% BGP EVPN PIP IP does not match\n");
4201 return CMD_WARNING_CONFIG_FAILED
;
4204 if (!is_zero_mac(&mac
->eth_addr
) &&
4205 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
4206 &mac
->eth_addr
, ETH_ALEN
) != 0) {
4208 "%% BGP EVPN PIP MAC does not match\n");
4209 return CMD_WARNING_CONFIG_FAILED
;
4211 /* pip_rmac can carry vrr_rmac reset only if it matches
4212 * with static value.
4214 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
4215 &bgp_vrf
->evpn_info
->pip_rmac_static
,
4217 /* Copy zebra sys mac */
4219 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
4220 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4221 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
4224 /* copy anycast mac */
4225 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
4226 &bgp_vrf
->rmac
, ETH_ALEN
);
4230 /* reset user configured sys MAC */
4231 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
4232 /* reset user configured sys IP */
4233 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
4234 /* Assign default PIP IP (bgp instance router-id) */
4236 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
4238 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
4241 if (is_evpn_enabled()) {
4242 struct listnode
*node
= NULL
;
4243 struct bgpevpn
*vpn
= NULL
;
4246 * At this point if bgp_evpn is NULL and evpn is enabled
4247 * something stupid has gone wrong
4251 update_advertise_vrf_routes(bgp_vrf
);
4253 /* Update (svi) type-2 routes */
4254 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
4255 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
4257 update_routes_for_vni(bgp_evpn
, vpn
);
4265 * Display VNI information - for all or a specific VNI
4267 DEFUN(show_bgp_l2vpn_evpn_vni
,
4268 show_bgp_l2vpn_evpn_vni_cmd
,
4269 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
4278 struct bgp
*bgp_evpn
;
4282 json_object
*json
= NULL
;
4283 uint32_t num_l2vnis
= 0;
4284 uint32_t num_l3vnis
= 0;
4285 uint32_t num_vnis
= 0;
4286 struct listnode
*node
= NULL
;
4287 struct bgp
*bgp_temp
= NULL
;
4289 uj
= use_json(argc
, argv
);
4291 bgp_evpn
= bgp_get_evpn();
4295 if (!argv_find(argv
, argc
, "evpn", &idx
))
4299 json
= json_object_new_object();
4301 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
4303 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
4305 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
4306 if (bgp_temp
->l3vni
)
4309 num_vnis
= num_l2vnis
+ num_l3vnis
;
4311 json_object_string_add(json
, "advertiseGatewayMacip",
4312 bgp_evpn
->advertise_gw_macip
4315 json_object_string_add(json
, "advertiseSviMacIp",
4316 bgp_evpn
->evpn_info
->advertise_svi_macip
4317 ? "Enabled" : "Disabled");
4318 json_object_string_add(json
, "advertiseAllVnis",
4319 is_evpn_enabled() ? "Enabled"
4321 json_object_string_add(
4323 bgp_evpn
->vxlan_flood_ctrl
==
4324 VXLAN_FLOOD_HEAD_END_REPL
4325 ? "Head-end replication"
4327 json_object_string_add(
4328 json
, "vxlanFlooding",
4329 bgp_evpn
->vxlan_flood_ctrl
==
4330 VXLAN_FLOOD_HEAD_END_REPL
4333 json_object_int_add(json
, "numVnis", num_vnis
);
4334 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
4335 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
4337 vty_out(vty
, "Advertise Gateway Macip: %s\n",
4338 bgp_evpn
->advertise_gw_macip
? "Enabled"
4340 vty_out(vty
, "Advertise SVI Macip: %s\n",
4341 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
4343 vty_out(vty
, "Advertise All VNI flag: %s\n",
4344 is_evpn_enabled() ? "Enabled" : "Disabled");
4345 vty_out(vty
, "BUM flooding: %s\n",
4346 bgp_evpn
->vxlan_flood_ctrl
==
4347 VXLAN_FLOOD_HEAD_END_REPL
4348 ? "Head-end replication"
4350 vty_out(vty
, "VXLAN flooding: %s\n",
4351 bgp_evpn
->vxlan_flood_ctrl
==
4352 VXLAN_FLOOD_HEAD_END_REPL
4355 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4356 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4358 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4362 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4365 /* Display specific VNI */
4366 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4367 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4371 vty_json(vty
, json
);
4376 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_remote_ip_hash
,
4377 show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
,
4378 "show bgp l2vpn evpn vni remote-ip-hash",
4386 struct bgp
*bgp_evpn
;
4389 bgp_evpn
= bgp_get_evpn();
4393 if (!argv_find(argv
, argc
, "evpn", &idx
))
4396 hash_iterate(bgp_evpn
->vnihash
,
4397 (void (*)(struct hash_bucket
*,
4398 void *))bgp_evpn_show_remote_ip_hash
,
4404 DEFUN_HIDDEN(show_bgp_l2vpn_evpn_vni_svi_hash
,
4405 show_bgp_l2vpn_evpn_vni_svi_hash_cmd
,
4406 "show bgp l2vpn evpn vni-svi-hash",
4411 "Show vni-svi-hash\n")
4413 struct bgp
*bgp_evpn
;
4416 bgp_evpn
= bgp_get_evpn();
4420 if (!argv_find(argv
, argc
, "evpn", &idx
))
4423 hash_iterate(bgp_evpn
->vni_svi_hash
,
4424 (void (*)(struct hash_bucket
*,
4425 void *))bgp_evpn_show_vni_svi_hash
,
4431 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4432 show_bgp_l2vpn_evpn_es_evi_cmd
,
4433 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4439 "VxLAN Network Identifier\n"
4442 "Detailed information\n")
4445 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4447 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4452 DEFPY(show_bgp_l2vpn_evpn_es
,
4453 show_bgp_l2vpn_evpn_es_cmd
,
4454 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4459 "Ethernet Segment\n"
4461 "Detailed information\n"
4467 if (!str_to_esi(esi_str
, &esi
)) {
4468 vty_out(vty
, "%% Malformed ESI\n");
4471 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4474 bgp_evpn_es_show(vty
, uj
, !!detail
);
4480 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4481 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4482 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4483 "Ethernet Segment\n"
4489 if (!str_to_esi(esi_str
, &esi
)) {
4490 vty_out(vty
, "%% Malformed ESI\n");
4493 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4496 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4502 DEFPY(show_bgp_l2vpn_evpn_nh
,
4503 show_bgp_l2vpn_evpn_nh_cmd
,
4504 "show bgp l2vpn evpn next-hops [json$uj]",
4512 bgp_evpn_nh_show(vty
, uj
);
4518 * Display EVPN neighbor summary.
4520 DEFUN(show_bgp_l2vpn_evpn_summary
, show_bgp_l2vpn_evpn_summary_cmd
,
4521 "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]",
4524 "vrf name\n" L2VPN_HELP_STR EVPN_HELP_STR
4525 "Summary of BGP neighbor status\n"
4526 "Show only sessions in Established state\n"
4527 "Show only sessions not in Established state\n"
4528 "Show only the specified neighbor session\n"
4529 "Neighbor to display information about\n"
4530 "Neighbor to display information about\n"
4531 "Neighbor on BGP configured interface\n"
4532 "Show only the specified remote AS sessions\n"
4534 "Internal (iBGP) AS sessions\n"
4535 "External (eBGP) AS sessions\n"
4536 "Shorten the information on BGP instances\n"
4537 "Increase table width for longer output\n" JSON_STR
)
4542 char *neighbor
= NULL
;
4543 as_t as
= 0; /* 0 means AS filter not set */
4544 int as_type
= AS_UNSPECIFIED
;
4545 uint16_t show_flags
= 0;
4547 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4548 vrf
= argv
[++idx_vrf
]->arg
;
4550 if (argv_find(argv
, argc
, "failed", &idx
))
4551 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4553 if (argv_find(argv
, argc
, "established", &idx
))
4554 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4557 if (argv_find(argv
, argc
, "neighbor", &idx
))
4558 neighbor
= argv
[idx
+ 1]->arg
;
4560 if (argv_find(argv
, argc
, "remote-as", &idx
)) {
4561 if (argv
[idx
+ 1]->arg
[0] == 'i')
4562 as_type
= AS_INTERNAL
;
4563 else if (argv
[idx
+ 1]->arg
[0] == 'e')
4564 as_type
= AS_EXTERNAL
;
4566 as
= (as_t
)atoi(argv
[idx
+ 1]->arg
);
4569 if (argv_find(argv
, argc
, "terse", &idx
))
4570 SET_FLAG(show_flags
, BGP_SHOW_OPT_TERSE
);
4572 if (argv_find(argv
, argc
, "wide", &idx
))
4573 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4575 if (use_json(argc
, argv
))
4576 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4578 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, neighbor
,
4579 as_type
, as
, show_flags
);
4582 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4586 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4587 /* Specific type is requested */
4588 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4589 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4590 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4591 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4592 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4593 *type
= BGP_EVPN_IMET_ROUTE
;
4594 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4595 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4596 *type
= BGP_EVPN_ES_ROUTE
;
4597 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4598 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4599 *type
= BGP_EVPN_AD_ROUTE
;
4600 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4601 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4602 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4611 * Display global EVPN routing table.
4613 DEFUN(show_bgp_l2vpn_evpn_route
,
4614 show_bgp_l2vpn_evpn_route_cmd
,
4615 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4621 "Display Detailed Information\n"
4623 EVPN_TYPE_ALL_LIST_HELP_STR
4630 json_object
*json
= NULL
;
4632 uj
= use_json(argc
, argv
);
4634 bgp
= bgp_get_evpn();
4639 json
= json_object_new_object();
4641 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4644 if (argv_find(argv
, argc
, "detail", &detail
))
4647 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4650 vty_json(vty
, json
);
4655 * Display global EVPN routing table for specific RD.
4657 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4658 show_bgp_l2vpn_evpn_route_rd_cmd
,
4659 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> [type "EVPN_TYPE_ALL_LIST
"] [json]",
4665 EVPN_RT_DIST_HELP_STR
4666 EVPN_ASN_IP_HELP_STR
4667 "All VPN Route Distinguishers\n"
4669 EVPN_TYPE_ALL_LIST_HELP_STR
4674 struct prefix_rd prd
;
4677 json_object
*json
= NULL
;
4678 int idx_ext_community
= 0;
4681 bgp
= bgp_get_evpn();
4685 /* check if we need json output */
4686 uj
= use_json(argc
, argv
);
4688 json
= json_object_new_object();
4690 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4692 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4693 &idx_ext_community
)) {
4694 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4697 "%% Malformed Route Distinguisher\n");
4703 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4707 evpn_show_all_routes(vty
, bgp
, type
, json
, 1);
4709 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4712 vty_json(vty
, json
);
4718 * Display global EVPN routing table for specific RD and MACIP.
4720 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4721 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4722 "show bgp l2vpn evpn route rd <ASN:NN_OR_IP-ADDRESS:NN|all> mac WORD [ip WORD] [json]",
4728 EVPN_RT_DIST_HELP_STR
4729 EVPN_ASN_IP_HELP_STR
4730 "All VPN Route Distinguishers\n"
4732 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4734 "IP address (IPv4 or IPv6)\n"
4739 struct prefix_rd prd
;
4742 int idx_ext_community
= 0;
4746 json_object
*json
= NULL
;
4749 memset(&mac
, 0, sizeof(struct ethaddr
));
4750 memset(&ip
, 0, sizeof(struct ipaddr
));
4752 bgp
= bgp_get_evpn();
4756 /* check if we need json output */
4757 uj
= use_json(argc
, argv
);
4759 json
= json_object_new_object();
4762 if (!argv_find(argv
, argc
, "all", &rd_all
)) {
4763 if (argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN",
4764 &idx_ext_community
)) {
4765 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
4768 "%% Malformed Route Distinguisher\n");
4775 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4776 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4777 vty_out(vty
, "%% Malformed MAC address\n");
4782 /* get the ip if specified */
4783 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4784 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4785 vty_out(vty
, "%% Malformed IP address\n");
4791 evpn_show_route_rd_all_macip(vty
, bgp
, &mac
, &ip
, json
);
4793 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4796 vty_json(vty
, json
);
4801 /* Display per ESI routing table */
4802 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4803 show_bgp_l2vpn_evpn_route_esi_cmd
,
4804 "show bgp l2vpn evpn route esi ESI [json]",
4810 "Ethernet Segment Identifier\n"
4816 struct bgp
*bgp
= NULL
;
4817 json_object
*json
= NULL
;
4819 memset(&esi
, 0, sizeof(esi
));
4820 bgp
= bgp_get_evpn();
4824 uj
= use_json(argc
, argv
);
4826 json
= json_object_new_object();
4828 /* get the ESI - ESI-ID is at argv[6] */
4829 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4830 vty_out(vty
, "%% Malformed ESI\n");
4834 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4837 vty_json(vty
, json
);
4844 * Display per-VNI EVPN routing table.
4846 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4847 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4853 "VXLAN Network Identifier\n"
4856 EVPN_TYPE_1_HELP_STR
4857 EVPN_TYPE_1_HELP_STR
4858 EVPN_TYPE_2_HELP_STR
4859 EVPN_TYPE_2_HELP_STR
4860 EVPN_TYPE_3_HELP_STR
4861 EVPN_TYPE_3_HELP_STR
4863 "Remote VTEP IP address\n"
4868 struct in_addr vtep_ip
;
4873 json_object
*json
= NULL
;
4875 bgp
= bgp_get_evpn();
4879 /* check if we need json output */
4880 uj
= use_json(argc
, argv
);
4882 json
= json_object_new_object();
4884 if (!argv_find(argv
, argc
, "evpn", &idx
))
4889 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4891 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4894 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4895 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4896 vty_out(vty
, "%% Malformed VTEP IP address\n");
4901 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4904 vty_json(vty
, json
);
4910 * Display per-VNI EVPN routing table for specific MACIP.
4912 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4913 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4914 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4920 "VXLAN Network Identifier\n"
4923 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4925 "IP address (IPv4 or IPv6)\n"
4934 json_object
*json
= NULL
;
4936 bgp
= bgp_get_evpn();
4940 /* check if we need json output */
4941 uj
= use_json(argc
, argv
);
4943 json
= json_object_new_object();
4945 if (!argv_find(argv
, argc
, "evpn", &idx
))
4949 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4952 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4953 vty_out(vty
, "%% Malformed MAC address\n");
4958 memset(&ip
, 0, sizeof(ip
));
4959 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4961 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4962 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4963 vty_out(vty
, "%% Malformed IP address\n");
4968 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4971 vty_json(vty
, json
);
4977 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4979 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4980 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4981 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4987 "VXLAN Network Identifier\n"
4989 EVPN_TYPE_3_HELP_STR
4990 "Originating Router IP address\n"
4996 struct in_addr orig_ip
;
4999 json_object
*json
= NULL
;
5001 bgp
= bgp_get_evpn();
5005 /* check if we need json output */
5006 uj
= use_json(argc
, argv
);
5008 json
= json_object_new_object();
5010 if (!argv_find(argv
, argc
, "evpn", &idx
))
5014 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
5017 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
5019 vty_out(vty
, "%% Malformed Originating Router IP address\n");
5023 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
5026 vty_json(vty
, json
);
5032 * Display per-VNI EVPN routing table - for all VNIs.
5034 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
5035 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
5036 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
5042 "VXLAN Network Identifier\n"
5044 "Print Detailed Output\n"
5046 "Remote VTEP IP address\n"
5050 struct in_addr vtep_ip
;
5053 json_object
*json
= NULL
;
5054 /* Detail Adjust. Adjust indexes according to detail option */
5057 bgp
= bgp_get_evpn();
5061 /* check if we need json output */
5062 uj
= use_json(argc
, argv
);
5064 json
= json_object_new_object();
5066 if (!argv_find(argv
, argc
, "evpn", &idx
))
5069 if (argv_find(argv
, argc
, "detail", &da
))
5072 /* vtep-ip position depends on detail option */
5074 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
5076 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
5077 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
5078 vty_out(vty
, "%% Malformed VTEP IP address\n");
5083 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
5086 vty_json(vty
, json
);
5092 show_bgp_l2vpn_evpn_route_mac_ip_evi_es
,
5093 show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
,
5094 "show bgp l2vpn evpn route mac-ip-evi-es [NAME$esi_str|detail$detail] [json$uj]",
5095 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5096 "EVPN route information\n"
5097 "MAC IP routes in the EVI tables linked to the ES\n"
5099 "Detailed information\n" JSON_STR
)
5103 json_object
*json
= NULL
;
5106 if (!str_to_esi(esi_str
, &esi
)) {
5107 vty_out(vty
, "%% Malformed ESI\n");
5116 json
= json_object_new_object();
5117 bgp_evpn_show_routes_mac_ip_evi_es(vty
, esi_p
, json
, !!detail
);
5119 vty_json(vty
, json
);
5125 show_bgp_l2vpn_evpn_route_mac_ip_global_es
,
5126 show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
,
5127 "show bgp l2vpn evpn route mac-ip-global-es [NAME$esi_str|detail$detail] [json$uj]",
5128 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
5129 "EVPN route information\n"
5130 "MAC IP routes in the global table linked to the ES\n"
5132 "Detailed information\n" JSON_STR
)
5136 json_object
*json
= NULL
;
5139 if (!str_to_esi(esi_str
, &esi
)) {
5140 vty_out(vty
, "%% Malformed ESI\n");
5149 json
= json_object_new_object();
5150 bgp_evpn_show_routes_mac_ip_global_es(vty
, esi_p
, json
, !!detail
);
5152 vty_json(vty
, json
);
5158 * Display EVPN import route-target hash table
5160 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
5161 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
5162 "show bgp l2vpn evpn vrf-import-rt [json]",
5167 "Show vrf import route target\n"
5171 struct bgp
*bgp_evpn
= NULL
;
5172 json_object
*json
= NULL
;
5174 bgp_evpn
= bgp_get_evpn();
5178 uj
= use_json(argc
, argv
);
5180 json
= json_object_new_object();
5182 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
5185 vty_json(vty
, json
);
5191 * Display EVPN import route-target hash table
5193 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
5194 show_bgp_l2vpn_evpn_import_rt_cmd
,
5195 "show bgp l2vpn evpn import-rt [json]",
5200 "Show import route target\n"
5205 json_object
*json
= NULL
;
5207 bgp
= bgp_get_evpn();
5211 uj
= use_json(argc
, argv
);
5213 json
= json_object_new_object();
5215 evpn_show_import_rts(vty
, bgp
, json
);
5218 vty_json(vty
, json
);
5223 DEFPY_HIDDEN(test_es_add
,
5225 "[no$no] test es NAME$esi_str [state NAME$state_str]",
5228 "Ethernet-segment\n"
5229 "Ethernet-Segment Identifier\n"
5237 struct in_addr vtep_ip
;
5240 bgp
= bgp_get_evpn();
5242 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5246 if (!str_to_esi(esi_str
, &esi
)) {
5247 vty_out(vty
, "%% Malformed ESI\n");
5252 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
5254 vty_out(vty
, "%% Failed to delete ES\n");
5258 if (state_str
&& !strcmp(state_str
, "up"))
5262 vtep_ip
= bgp
->router_id
;
5264 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
5265 EVPN_MH_DF_PREF_MIN
, false);
5267 vty_out(vty
, "%% Failed to add ES\n");
5274 DEFPY_HIDDEN(test_es_vni_add
,
5275 test_es_vni_add_cmd
,
5276 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
5279 "Ethernet-segment\n"
5280 "Ethernet-Segment Identifier\n"
5289 bgp
= bgp_get_evpn();
5291 vty_out(vty
, "%% EVPN BGP instance not yet created\n");
5295 if (!str_to_esi(esi_str
, &esi
)) {
5296 vty_out(vty
, "%% Malformed ESI\n");
5301 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
5303 vty_out(vty
, "%% Failed to deref ES VNI\n");
5307 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
5309 vty_out(vty
, "%% Failed to ref ES VNI\n");
5316 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
5317 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
5321 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
5322 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
5323 "Summary of BGP neighbor status\n" JSON_STR
)
5325 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
5326 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
5327 SHOW_STR BGP_STR EVPN_HELP_STR
5329 "Display Detailed Information\n"
5331 EVPN_TYPE_2_HELP_STR
5332 EVPN_TYPE_2_HELP_STR
5333 EVPN_TYPE_3_HELP_STR
5334 EVPN_TYPE_3_HELP_STR
)
5337 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
5338 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
5339 SHOW_STR BGP_STR EVPN_HELP_STR
5341 EVPN_RT_DIST_HELP_STR
5342 EVPN_ASN_IP_HELP_STR
5344 EVPN_TYPE_2_HELP_STR
5345 EVPN_TYPE_2_HELP_STR
5346 EVPN_TYPE_3_HELP_STR
5347 EVPN_TYPE_3_HELP_STR
)
5350 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
5351 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
5352 SHOW_STR BGP_STR EVPN_HELP_STR
5354 EVPN_RT_DIST_HELP_STR
5355 EVPN_ASN_IP_HELP_STR
5357 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5359 "IP address (IPv4 or IPv6)\n")
5362 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
5363 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
5364 SHOW_STR BGP_STR EVPN_HELP_STR
5366 "VXLAN Network Identifier\n"
5369 EVPN_TYPE_2_HELP_STR
5370 EVPN_TYPE_2_HELP_STR
5371 EVPN_TYPE_3_HELP_STR
5372 EVPN_TYPE_3_HELP_STR
5374 "Remote VTEP IP address\n")
5376 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
5377 show_bgp_evpn_route_vni_macip_cmd
,
5378 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
5379 SHOW_STR BGP_STR EVPN_HELP_STR
5381 "VXLAN Network Identifier\n"
5384 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
5386 "IP address (IPv4 or IPv6)\n")
5388 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
5389 show_bgp_evpn_route_vni_multicast_cmd
,
5390 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
5391 SHOW_STR BGP_STR EVPN_HELP_STR
5393 "VXLAN Network Identifier\n"
5395 EVPN_TYPE_3_HELP_STR
5396 "Originating Router IP address\n")
5398 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
5399 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
5400 SHOW_STR BGP_STR EVPN_HELP_STR
5402 "VXLAN Network Identifier\n"
5404 "Print Detailed Output\n"
5406 "Remote VTEP IP address\n")
5408 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
5409 "show bgp evpn import-rt",
5410 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
5412 DEFUN_NOSH (bgp_evpn_vni
,
5414 "vni " CMD_VNI_RANGE
,
5415 "VXLAN Network Identifier\n"
5419 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5420 struct bgpevpn
*vpn
;
5425 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
5427 /* Create VNI, or mark as configured. */
5428 vpn
= evpn_create_update_vni(bgp
, vni
);
5430 vty_out(vty
, "%% Failed to create VNI \n");
5434 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
5438 DEFUN (no_bgp_evpn_vni
,
5439 no_bgp_evpn_vni_cmd
,
5440 "no vni " CMD_VNI_RANGE
,
5442 "VXLAN Network Identifier\n"
5446 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5447 struct bgpevpn
*vpn
;
5452 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
5454 /* Check if we should disallow. */
5455 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
5457 vty_out(vty
, "%% Specified VNI does not exist\n");
5460 if (!is_vni_configured(vpn
)) {
5461 vty_out(vty
, "%% Specified VNI is not configured\n");
5465 evpn_delete_vni(bgp
, vpn
);
5469 DEFUN_NOSH (exit_vni
,
5472 "Exit from VNI mode\n")
5474 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5475 vty
->node
= BGP_EVPN_NODE
;
5479 DEFUN (bgp_evpn_vrf_rd
,
5480 bgp_evpn_vrf_rd_cmd
,
5481 "rd ASN:NN_OR_IP-ADDRESS:NN",
5482 EVPN_RT_DIST_HELP_STR
5483 EVPN_ASN_IP_HELP_STR
)
5486 struct prefix_rd prd
;
5487 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5492 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5494 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5498 /* If same as existing value, there is nothing more to do. */
5499 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5502 /* Configure or update the RD. */
5503 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5507 DEFUN (no_bgp_evpn_vrf_rd
,
5508 no_bgp_evpn_vrf_rd_cmd
,
5509 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5511 EVPN_RT_DIST_HELP_STR
5512 EVPN_ASN_IP_HELP_STR
)
5515 struct prefix_rd prd
;
5516 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5521 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5523 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5527 /* Check if we should disallow. */
5528 if (!is_vrf_rd_configured(bgp_vrf
)) {
5529 vty_out(vty
, "%% RD is not configured for this VRF\n");
5533 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5535 "%% RD specified does not match configuration for this VRF\n");
5539 evpn_unconfigure_vrf_rd(bgp_vrf
);
5543 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5544 no_bgp_evpn_vrf_rd_without_val_cmd
,
5547 EVPN_RT_DIST_HELP_STR
)
5549 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5554 /* Check if we should disallow. */
5555 if (!is_vrf_rd_configured(bgp_vrf
)) {
5556 vty_out(vty
, "%% RD is not configured for this VRF\n");
5560 evpn_unconfigure_vrf_rd(bgp_vrf
);
5564 DEFUN (bgp_evpn_vni_rd
,
5565 bgp_evpn_vni_rd_cmd
,
5566 "rd ASN:NN_OR_IP-ADDRESS:NN",
5567 EVPN_RT_DIST_HELP_STR
5568 EVPN_ASN_IP_HELP_STR
)
5570 struct prefix_rd prd
;
5571 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5572 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5578 if (!EVPN_ENABLED(bgp
)) {
5580 "This command is only supported under EVPN VRF\n");
5584 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5586 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5590 /* If same as existing value, there is nothing more to do. */
5591 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5594 /* Configure or update the RD. */
5595 evpn_configure_rd(bgp
, vpn
, &prd
);
5599 DEFUN (no_bgp_evpn_vni_rd
,
5600 no_bgp_evpn_vni_rd_cmd
,
5601 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5603 EVPN_RT_DIST_HELP_STR
5604 EVPN_ASN_IP_HELP_STR
)
5606 struct prefix_rd prd
;
5607 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5608 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5614 if (!EVPN_ENABLED(bgp
)) {
5616 "This command is only supported under EVPN VRF\n");
5620 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5622 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5626 /* Check if we should disallow. */
5627 if (!is_rd_configured(vpn
)) {
5628 vty_out(vty
, "%% RD is not configured for this VNI\n");
5632 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5634 "%% RD specified does not match configuration for this VNI\n");
5638 evpn_unconfigure_rd(bgp
, vpn
);
5642 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5643 no_bgp_evpn_vni_rd_without_val_cmd
,
5646 EVPN_RT_DIST_HELP_STR
)
5648 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5649 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5654 if (!EVPN_ENABLED(bgp
)) {
5656 "This command is only supported under EVPN VRF\n");
5660 /* Check if we should disallow. */
5661 if (!is_rd_configured(vpn
)) {
5662 vty_out(vty
, "%% RD is not configured for this VNI\n");
5666 evpn_unconfigure_rd(bgp
, vpn
);
5671 * Loop over all extended-communities in the route-target list rtl and
5672 * return 1 if we find ecomtarget
5674 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5675 struct ecommunity
*ecomtarget
)
5677 struct listnode
*node
, *nnode
;
5678 struct ecommunity
*ecom
;
5680 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5681 if (ecommunity_match(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
];
5700 char buf1
[INET6_ADDRSTRLEN
];
5702 const char *name
= NULL
;
5703 struct bgp
*bgp
= NULL
;
5704 struct listnode
*node
= NULL
;
5705 struct bgpevpn
*vpn
= NULL
;
5706 struct ecommunity
*ecom
= NULL
;
5707 json_object
*json
= NULL
;
5708 json_object
*json_vnis
= NULL
;
5709 json_object
*json_export_rts
= NULL
;
5710 json_object
*json_import_rts
= NULL
;
5711 bool uj
= use_json(argc
, argv
);
5714 json
= json_object_new_object();
5715 json_vnis
= json_object_new_array();
5716 json_export_rts
= json_object_new_array();
5717 json_import_rts
= json_object_new_array();
5720 name
= argv
[idx_vrf
]->arg
;
5721 bgp
= bgp_lookup_by_name(name
);
5722 if (strmatch(name
, VRF_DEFAULT_NAME
))
5723 bgp
= bgp_get_default();
5727 vty_out(vty
, "BGP instance for VRF %s not found\n",
5730 json_object_string_add(json
, "warning",
5731 "BGP instance not found");
5732 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5733 json_object_free(json
);
5739 vty_out(vty
, "BGP VRF: %s\n", name
);
5740 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5741 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5742 vty_out(vty
, " Rmac: %s\n",
5743 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5744 vty_out(vty
, " VNI Filter: %s\n",
5745 CHECK_FLAG(bgp
->vrf_flags
,
5746 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5747 ? "prefix-routes-only"
5749 vty_out(vty
, " L2-VNI List:\n");
5751 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5752 vty_out(vty
, "%u ", vpn
->vni
);
5754 vty_out(vty
, " Export-RTs:\n");
5756 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5757 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5759 vty_out(vty
, " Import-RTs:\n");
5761 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5762 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5764 vty_out(vty
, " RD: %s\n",
5765 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5767 json_object_string_add(json
, "vrf", name
);
5768 json_object_string_addf(json
, "local-ip", "%pI4",
5769 &bgp
->originator_ip
);
5770 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5771 json_object_string_add(
5773 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5774 json_object_string_add(
5776 CHECK_FLAG(bgp
->vrf_flags
,
5777 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5778 ? "prefix-routes-only"
5780 /* list of l2vnis */
5781 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5782 json_object_array_add(json_vnis
,
5783 json_object_new_int(vpn
->vni
));
5784 json_object_object_add(json
, "l2vnis", json_vnis
);
5787 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5788 json_object_array_add(
5790 json_object_new_string(ecommunity_str(ecom
)));
5791 json_object_object_add(json
, "export-rts", json_export_rts
);
5794 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5795 json_object_array_add(
5797 json_object_new_string(ecommunity_str(ecom
)));
5798 json_object_object_add(json
, "import-rts", json_import_rts
);
5799 json_object_string_add(
5801 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5805 vty_json(vty
, json
);
5809 /* import/export rt for l3vni-vrf */
5810 DEFUN (bgp_evpn_vrf_rt
,
5811 bgp_evpn_vrf_rt_cmd
,
5812 "route-target <both|import|export> RT",
5814 "import and export\n"
5817 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5820 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5821 struct ecommunity
*ecomadd
= NULL
;
5826 if (!strcmp(argv
[1]->arg
, "import"))
5827 rt_type
= RT_TYPE_IMPORT
;
5828 else if (!strcmp(argv
[1]->arg
, "export"))
5829 rt_type
= RT_TYPE_EXPORT
;
5830 else if (!strcmp(argv
[1]->arg
, "both"))
5831 rt_type
= RT_TYPE_BOTH
;
5833 vty_out(vty
, "%% Invalid Route Target type\n");
5837 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5839 vty_out(vty
, "%% Malformed Route Target list\n");
5842 ecommunity_str(ecomadd
);
5844 /* Add/update the import route-target */
5845 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5846 /* Do nothing if we already have this import route-target */
5847 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5848 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5851 /* Add/update the export route-target */
5852 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5853 /* Do nothing if we already have this export route-target */
5854 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5855 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5861 DEFUN (no_bgp_evpn_vrf_rt
,
5862 no_bgp_evpn_vrf_rt_cmd
,
5863 "no route-target <both|import|export> RT",
5866 "import and export\n"
5869 EVPN_ASN_IP_HELP_STR
)
5871 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5872 int rt_type
, found_ecomdel
;
5873 struct ecommunity
*ecomdel
= NULL
;
5878 if (!strcmp(argv
[2]->arg
, "import"))
5879 rt_type
= RT_TYPE_IMPORT
;
5880 else if (!strcmp(argv
[2]->arg
, "export"))
5881 rt_type
= RT_TYPE_EXPORT
;
5882 else if (!strcmp(argv
[2]->arg
, "both"))
5883 rt_type
= RT_TYPE_BOTH
;
5885 vty_out(vty
, "%% Invalid Route Target type\n");
5889 if (rt_type
== RT_TYPE_IMPORT
) {
5890 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5892 "%% Import RT is not configured for this VRF\n");
5895 } else if (rt_type
== RT_TYPE_EXPORT
) {
5896 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5898 "%% Export RT is not configured for this VRF\n");
5901 } else if (rt_type
== RT_TYPE_BOTH
) {
5902 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5903 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5905 "%% Import/Export RT is not configured for this VRF\n");
5910 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5912 vty_out(vty
, "%% Malformed Route Target list\n");
5915 ecommunity_str(ecomdel
);
5917 if (rt_type
== RT_TYPE_IMPORT
) {
5918 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5920 ecommunity_free(&ecomdel
);
5922 "%% RT specified does not match configuration for this VRF\n");
5925 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5926 } else if (rt_type
== RT_TYPE_EXPORT
) {
5927 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5929 ecommunity_free(&ecomdel
);
5931 "%% RT specified does not match configuration for this VRF\n");
5934 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5935 } else if (rt_type
== RT_TYPE_BOTH
) {
5938 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5940 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5944 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5946 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5950 if (!found_ecomdel
) {
5951 ecommunity_free(&ecomdel
);
5953 "%% RT specified does not match configuration for this VRF\n");
5958 ecommunity_free(&ecomdel
);
5962 DEFPY(bgp_evpn_ead_ess_frag_evi_limit
, bgp_evpn_ead_es_frag_evi_limit_cmd
,
5963 "[no$no] ead-es-frag evi-limit (1-1000)$limit",
5965 "EAD ES fragment config\n"
5966 "EVIs per-fragment\n"
5969 bgp_mh_info
->evi_per_es_frag
=
5970 no
? BGP_EVPN_MAX_EVI_PER_ES_FRAG
: limit
;
5975 DEFUN(bgp_evpn_ead_es_rt
, bgp_evpn_ead_es_rt_cmd
,
5976 "ead-es-route-target export RT",
5977 "EAD ES Route Target\n"
5979 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5981 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5982 struct ecommunity
*ecomadd
= NULL
;
5987 if (!EVPN_ENABLED(bgp
)) {
5988 vty_out(vty
, "This command is only supported under EVPN VRF\n");
5992 /* Add/update the export route-target */
5993 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5995 vty_out(vty
, "%% Malformed Route Target list\n");
5998 ecommunity_str(ecomadd
);
6000 /* Do nothing if we already have this export route-target */
6001 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6003 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomadd
, false);
6008 DEFUN(no_bgp_evpn_ead_es_rt
, no_bgp_evpn_ead_es_rt_cmd
,
6009 "no ead-es-route-target export RT",
6011 "EAD ES Route Target\n"
6012 "export\n" EVPN_ASN_IP_HELP_STR
)
6014 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6015 struct ecommunity
*ecomdel
= NULL
;
6020 if (!EVPN_ENABLED(bgp
)) {
6021 vty_out(vty
, "This command is only supported under EVPN VRF\n");
6025 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6027 vty_out(vty
, "%% Malformed Route Target list\n");
6030 ecommunity_str(ecomdel
);
6032 if (!bgp_evpn_rt_matches_existing(bgp_mh_info
->ead_es_export_rtl
,
6035 "%% RT specified does not match EAD-ES RT configuration\n");
6038 bgp_evpn_mh_config_ead_export_rt(bgp
, ecomdel
, true);
6043 DEFUN (bgp_evpn_vni_rt
,
6044 bgp_evpn_vni_rt_cmd
,
6045 "route-target <both|import|export> RT",
6047 "import and export\n"
6050 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
6052 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6053 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6055 struct ecommunity
*ecomadd
= NULL
;
6060 if (!EVPN_ENABLED(bgp
)) {
6062 "This command is only supported under EVPN VRF\n");
6066 if (!strcmp(argv
[1]->text
, "import"))
6067 rt_type
= RT_TYPE_IMPORT
;
6068 else if (!strcmp(argv
[1]->text
, "export"))
6069 rt_type
= RT_TYPE_EXPORT
;
6070 else if (!strcmp(argv
[1]->text
, "both"))
6071 rt_type
= RT_TYPE_BOTH
;
6073 vty_out(vty
, "%% Invalid Route Target type\n");
6077 ecomadd
= ecommunity_str2com(argv
[2]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6079 vty_out(vty
, "%% Malformed Route Target list\n");
6082 ecommunity_str(ecomadd
);
6084 /* Add/update the import route-target */
6085 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
6086 /* Do nothing if we already have this import route-target */
6087 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
6088 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
6091 /* Add/update the export route-target */
6092 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
6093 /* Do nothing if we already have this export route-target */
6094 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
6095 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
6101 DEFUN (no_bgp_evpn_vni_rt
,
6102 no_bgp_evpn_vni_rt_cmd
,
6103 "no route-target <both|import|export> RT",
6106 "import and export\n"
6109 EVPN_ASN_IP_HELP_STR
)
6111 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6112 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6113 int rt_type
, found_ecomdel
;
6114 struct ecommunity
*ecomdel
= NULL
;
6119 if (!EVPN_ENABLED(bgp
)) {
6121 "This command is only supported under EVPN VRF\n");
6125 if (!strcmp(argv
[2]->text
, "import"))
6126 rt_type
= RT_TYPE_IMPORT
;
6127 else if (!strcmp(argv
[2]->text
, "export"))
6128 rt_type
= RT_TYPE_EXPORT
;
6129 else if (!strcmp(argv
[2]->text
, "both"))
6130 rt_type
= RT_TYPE_BOTH
;
6132 vty_out(vty
, "%% Invalid Route Target type\n");
6136 /* The user did "no route-target import", check to see if there are any
6137 * import route-targets configured. */
6138 if (rt_type
== RT_TYPE_IMPORT
) {
6139 if (!is_import_rt_configured(vpn
)) {
6141 "%% Import RT is not configured for this VNI\n");
6144 } else if (rt_type
== RT_TYPE_EXPORT
) {
6145 if (!is_export_rt_configured(vpn
)) {
6147 "%% Export RT is not configured for this VNI\n");
6150 } else if (rt_type
== RT_TYPE_BOTH
) {
6151 if (!is_import_rt_configured(vpn
)
6152 && !is_export_rt_configured(vpn
)) {
6154 "%% Import/Export RT is not configured for this VNI\n");
6159 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
6161 vty_out(vty
, "%% Malformed Route Target list\n");
6164 ecommunity_str(ecomdel
);
6166 if (rt_type
== RT_TYPE_IMPORT
) {
6167 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6169 "%% RT specified does not match configuration for this VNI\n");
6172 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6173 } else if (rt_type
== RT_TYPE_EXPORT
) {
6174 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6176 "%% RT specified does not match configuration for this VNI\n");
6179 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6180 } else if (rt_type
== RT_TYPE_BOTH
) {
6183 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
6184 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
6188 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
6189 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
6193 if (!found_ecomdel
) {
6195 "%% RT specified does not match configuration for this VNI\n");
6203 DEFUN (no_bgp_evpn_vni_rt_without_val
,
6204 no_bgp_evpn_vni_rt_without_val_cmd
,
6205 "no route-target <import|export>",
6211 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
6212 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
6218 if (!EVPN_ENABLED(bgp
)) {
6220 "This command is only supported under EVPN VRF\n");
6224 if (!strcmp(argv
[2]->text
, "import")) {
6225 rt_type
= RT_TYPE_IMPORT
;
6226 } else if (!strcmp(argv
[2]->text
, "export")) {
6227 rt_type
= RT_TYPE_EXPORT
;
6229 vty_out(vty
, "%% Invalid Route Target type\n");
6233 /* Check if we should disallow. */
6234 if (rt_type
== RT_TYPE_IMPORT
) {
6235 if (!is_import_rt_configured(vpn
)) {
6237 "%% Import RT is not configured for this VNI\n");
6241 if (!is_export_rt_configured(vpn
)) {
6243 "%% Export RT is not configured for this VNI\n");
6248 /* Unconfigure the RT. */
6249 if (rt_type
== RT_TYPE_IMPORT
)
6250 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
6252 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
6256 static int vni_cmp(const void **a
, const void **b
)
6258 const struct bgpevpn
*first
= *a
;
6259 const struct bgpevpn
*secnd
= *b
;
6261 return secnd
->vni
- first
->vni
;
6265 * Output EVPN configuration information.
6267 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
6270 char buf1
[RD_ADDRSTRLEN
];
6271 char buf2
[INET6_ADDRSTRLEN
];
6273 if (bgp
->advertise_all_vni
)
6274 vty_out(vty
, " advertise-all-vni\n");
6276 if (hashcount(bgp
->vnihash
)) {
6277 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
6278 struct listnode
*ln
;
6279 struct bgpevpn
*data
;
6281 list_sort(vnilist
, vni_cmp
);
6282 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
6283 write_vni_config(vty
, data
);
6285 list_delete(&vnilist
);
6288 if (bgp
->advertise_autort_rfc8365
)
6289 vty_out(vty
, " autort rfc8365-compatible\n");
6291 if (bgp
->advertise_gw_macip
)
6292 vty_out(vty
, " advertise-default-gw\n");
6294 if (bgp
->evpn_info
->advertise_svi_macip
)
6295 vty_out(vty
, " advertise-svi-ip\n");
6297 if (bgp
->resolve_overlay_index
)
6298 vty_out(vty
, " enable-resolve-overlay-index\n");
6300 if (bgp_mh_info
->evi_per_es_frag
!= BGP_EVPN_MAX_EVI_PER_ES_FRAG
)
6301 vty_out(vty
, " ead-es-frag evi-limit %u\n",
6302 bgp_mh_info
->evi_per_es_frag
);
6304 if (bgp_mh_info
->host_routes_use_l3nhg
!=
6305 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
6306 if (bgp_mh_info
->host_routes_use_l3nhg
)
6307 vty_out(vty
, " use-es-l3nhg\n");
6309 vty_out(vty
, " no use-es-l3nhg\n");
6312 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
6313 if (bgp_mh_info
->ead_evi_rx
)
6314 vty_out(vty
, " no disable-ead-evi-rx\n");
6316 vty_out(vty
, " disable-ead-evi-rx\n");
6319 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
6320 if (bgp_mh_info
->ead_evi_tx
)
6321 vty_out(vty
, " no disable-ead-evi-tx\n");
6323 vty_out(vty
, " disable-ead-evi-tx\n");
6326 if (!bgp
->evpn_info
->dup_addr_detect
)
6327 vty_out(vty
, " no dup-addr-detection\n");
6329 if (bgp
->evpn_info
->dad_max_moves
!=
6330 EVPN_DAD_DEFAULT_MAX_MOVES
||
6331 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
6332 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
6333 bgp
->evpn_info
->dad_max_moves
,
6334 bgp
->evpn_info
->dad_time
);
6336 if (bgp
->evpn_info
->dad_freeze
) {
6337 if (bgp
->evpn_info
->dad_freeze_time
)
6339 " dup-addr-detection freeze %u\n",
6340 bgp
->evpn_info
->dad_freeze_time
);
6343 " dup-addr-detection freeze permanent\n");
6346 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
6347 vty_out(vty
, " flooding disable\n");
6349 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6350 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST
)) {
6351 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6352 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
6353 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6356 " advertise ipv4 unicast\n");
6357 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6358 BGP_L2VPN_EVPN_ADV_IPV4_UNICAST_GW_IP
)) {
6359 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
6361 " advertise ipv4 unicast gateway-ip route-map %s\n",
6362 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
6364 vty_out(vty
, " advertise ipv4 unicast gateway-ip\n");
6367 /* EAD ES export route-target */
6368 if (listcount(bgp_mh_info
->ead_es_export_rtl
)) {
6369 struct ecommunity
*ecom
;
6371 struct listnode
*node
;
6373 for (ALL_LIST_ELEMENTS_RO(bgp_mh_info
->ead_es_export_rtl
, node
,
6376 ecom_str
= ecommunity_ecom2str(
6377 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6378 vty_out(vty
, " ead-es-route-target export %s\n",
6380 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6384 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6385 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST
)) {
6386 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6388 " advertise ipv6 unicast route-map %s\n",
6389 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6392 " advertise ipv6 unicast\n");
6393 } else if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6394 BGP_L2VPN_EVPN_ADV_IPV6_UNICAST_GW_IP
)) {
6395 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
6397 " advertise ipv6 unicast gateway-ip route-map %s\n",
6398 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
6400 vty_out(vty
, " advertise ipv6 unicast gateway-ip\n");
6403 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6404 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
6405 vty_out(vty
, " default-originate ipv4\n");
6407 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
6408 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
6409 vty_out(vty
, " default-originate ipv6\n");
6411 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
6412 if (!bgp
->evpn_info
->advertise_pip
)
6413 vty_out(vty
, " no advertise-pip\n");
6414 if (bgp
->evpn_info
->advertise_pip
) {
6415 if (bgp
->evpn_info
->pip_ip_static
.s_addr
6417 vty_out(vty
, " advertise-pip ip %s",
6419 &bgp
->evpn_info
->pip_ip_static
,
6420 buf2
, INET_ADDRSTRLEN
));
6422 bgp
->evpn_info
->pip_rmac_static
))) {
6423 char buf
[ETHER_ADDR_STRLEN
];
6425 vty_out(vty
, " mac %s",
6435 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
6436 vty_out(vty
, " rd %s\n",
6437 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
6439 /* import route-target */
6440 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
6442 struct listnode
*node
, *nnode
;
6443 struct ecommunity
*ecom
;
6445 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
6447 ecom_str
= ecommunity_ecom2str(
6448 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6449 vty_out(vty
, " route-target import %s\n", ecom_str
);
6450 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6454 /* export route-target */
6455 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
6457 struct listnode
*node
, *nnode
;
6458 struct ecommunity
*ecom
;
6460 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
6462 ecom_str
= ecommunity_ecom2str(
6463 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
6464 vty_out(vty
, " route-target export %s\n", ecom_str
);
6465 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
6470 void bgp_ethernetvpn_init(void)
6472 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
6473 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
6474 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
6475 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
6476 install_element(VIEW_NODE
,
6477 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
6478 install_element(VIEW_NODE
,
6479 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
6482 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
6485 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
6486 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
6487 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
6488 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
6489 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
6490 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
6491 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
6492 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
6493 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
6494 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
6495 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
6496 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
6497 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
6498 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
6499 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
6500 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
6501 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
6502 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
6503 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
6504 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
6505 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
6506 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
6507 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
6508 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
6509 install_element(BGP_EVPN_NODE
,
6510 &bgp_evpn_enable_resolve_overlay_index_cmd
);
6513 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
6514 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
6516 /* "show bgp l2vpn evpn" commands. */
6517 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
6518 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
6519 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
6520 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_nh_cmd
);
6521 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
6522 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_remote_ip_hash_cmd
);
6523 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_svi_hash_cmd
);
6524 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
6525 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
6526 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
6527 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
6528 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
6529 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
6530 install_element(VIEW_NODE
,
6531 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
6532 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
6533 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
6534 install_element(VIEW_NODE
,
6535 &show_bgp_l2vpn_evpn_route_mac_ip_evi_es_cmd
);
6536 install_element(VIEW_NODE
,
6537 &show_bgp_l2vpn_evpn_route_mac_ip_global_es_cmd
);
6538 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
6539 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
6541 /* "show bgp evpn" commands. */
6542 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
6543 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
6544 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
6545 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
6546 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
6547 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
6548 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
6549 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
6550 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
6551 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
6552 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
6553 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
6555 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
6556 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
6557 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
6558 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
6559 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
6560 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
6561 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
6562 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
6563 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
6564 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
6565 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
6566 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
6567 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
6568 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
6569 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_rt_cmd
);
6570 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_ead_es_rt_cmd
);
6571 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_es_frag_evi_limit_cmd
);
6572 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
6573 install_element(BGP_EVPN_VNI_NODE
,
6574 &bgp_evpn_advertise_default_gw_vni_cmd
);
6575 install_element(BGP_EVPN_VNI_NODE
,
6576 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6577 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6578 install_element(BGP_EVPN_VNI_NODE
,
6579 &no_bgp_evpn_advertise_vni_subnet_cmd
);