1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "bgpd/bgpd.h"
28 #include "bgpd/bgp_table.h"
29 #include "bgpd/bgp_attr.h"
30 #include "bgpd/bgp_route.h"
31 #include "bgpd/bgp_mplsvpn.h"
32 #include "bgpd/bgp_vpn.h"
33 #include "bgpd/bgp_evpn_vty.h"
34 #include "bgpd/bgp_evpn.h"
35 #include "bgpd/bgp_evpn_private.h"
36 #include "bgpd/bgp_zebra.h"
37 #include "bgpd/bgp_vty.h"
38 #include "bgpd/bgp_errors.h"
39 #include "bgpd/bgp_ecommunity.h"
40 #include "bgpd/bgp_lcommunity.h"
41 #include "bgpd/bgp_community.h"
43 #define SHOW_DISPLAY_STANDARD 0
44 #define SHOW_DISPLAY_TAGS 1
45 #define SHOW_DISPLAY_OVERLAY 2
46 #define VNI_STR_LEN 32
49 * Context for VNI hash walk - used by callbacks.
54 struct in_addr vtep_ip
;
59 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
63 uint8_t type
, sub_type
;
64 struct ecommunity_as eas
;
65 struct ecommunity_ip eip
;
66 struct listnode
*node
, *nnode
;
67 struct bgp
*tmp_bgp_vrf
= NULL
;
68 json_object
*json_rt
= NULL
;
69 json_object
*json_vrfs
= NULL
;
70 char rt_buf
[RT_ADDRSTRLEN
];
73 json_rt
= json_object_new_object();
74 json_vrfs
= json_object_new_array();
77 pnt
= (uint8_t *)&irt
->rt
.val
;
80 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
83 memset(&eas
, 0, sizeof(eas
));
85 case ECOMMUNITY_ENCODE_AS
:
86 eas
.as
= (*pnt
++ << 8);
88 ptr_get_be32(pnt
, &eas
.val
);
90 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
93 json_object_string_add(json_rt
, "rt", rt_buf
);
95 vty_out(vty
, "Route-target: %s", rt_buf
);
99 case ECOMMUNITY_ENCODE_IP
:
100 memcpy(&eip
.ip
, pnt
, 4);
102 eip
.val
= (*pnt
++ << 8);
105 snprintf(rt_buf
, sizeof(rt_buf
), "%s:%u", inet_ntoa(eip
.ip
),
109 json_object_string_add(json_rt
, "rt", rt_buf
);
111 vty_out(vty
, "Route-target: %s", rt_buf
);
115 case ECOMMUNITY_ENCODE_AS4
:
116 pnt
= ptr_get_be32(pnt
, &eas
.val
);
117 eas
.val
= (*pnt
++ << 8);
120 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
123 json_object_string_add(json_rt
, "rt", rt_buf
);
125 vty_out(vty
, "Route-target: %s", rt_buf
);
135 "\nList of VRFs importing routes with this route-target:\n");
138 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
140 json_object_array_add(
142 json_object_new_string(
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
145 vty_out(vty
, " %s\n",
146 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
150 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
151 json_object_object_add(json
, rt_buf
, json_rt
);
155 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
157 json_object
*json
= NULL
;
158 struct vty
*vty
= NULL
;
159 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
161 vty
= (struct vty
*)args
[0];
162 json
= (struct json_object
*)args
[1];
164 display_vrf_import_rt(vty
, irt
, json
);
167 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
171 uint8_t type
, sub_type
;
172 struct ecommunity_as eas
;
173 struct ecommunity_ip eip
;
174 struct listnode
*node
, *nnode
;
175 struct bgpevpn
*tmp_vpn
;
176 json_object
*json_rt
= NULL
;
177 json_object
*json_vnis
= NULL
;
178 char rt_buf
[RT_ADDRSTRLEN
];
181 json_rt
= json_object_new_object();
182 json_vnis
= json_object_new_array();
185 /* TODO: This needs to go into a function */
187 pnt
= (uint8_t *)&irt
->rt
.val
;
190 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
193 memset(&eas
, 0, sizeof(eas
));
195 case ECOMMUNITY_ENCODE_AS
:
196 eas
.as
= (*pnt
++ << 8);
198 ptr_get_be32(pnt
, &eas
.val
);
200 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
203 json_object_string_add(json_rt
, "rt", rt_buf
);
205 vty_out(vty
, "Route-target: %s", rt_buf
);
209 case ECOMMUNITY_ENCODE_IP
:
210 memcpy(&eip
.ip
, pnt
, 4);
212 eip
.val
= (*pnt
++ << 8);
215 snprintf(rt_buf
, sizeof(rt_buf
), "%s:%u", inet_ntoa(eip
.ip
),
219 json_object_string_add(json_rt
, "rt", rt_buf
);
221 vty_out(vty
, "Route-target: %s", rt_buf
);
225 case ECOMMUNITY_ENCODE_AS4
:
226 pnt
= ptr_get_be32(pnt
, &eas
.val
);
227 eas
.val
= (*pnt
++ << 8);
230 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
233 json_object_string_add(json_rt
, "rt", rt_buf
);
235 vty_out(vty
, "Route-target: %s", rt_buf
);
245 "\nList of VNIs importing routes with this route-target:\n");
248 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
250 json_object_array_add(
251 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
253 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
257 json_object_object_add(json_rt
, "vnis", json_vnis
);
258 json_object_object_add(json
, rt_buf
, json_rt
);
262 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
264 json_object
*json
= NULL
;
265 struct vty
*vty
= NULL
;
266 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
271 display_import_rt(vty
, irt
, json
);
276 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
277 struct bgp_node
*rd_rn
,
279 char *rd_str
, int len
)
285 const struct prefix
*p
= bgp_node_get_prefix(rd_rn
);
289 /* Decode RD type. */
290 type
= decode_rd_type(pnt
);
293 vty_out(vty
, "Route Distinguisher: ");
297 decode_rd_as(pnt
+ 2, &rd_as
);
298 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
300 json_object_string_add(json
, "rd", rd_str
);
302 vty_out(vty
, "%s\n", rd_str
);
306 decode_rd_as4(pnt
+ 2, &rd_as
);
307 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
309 json_object_string_add(json
, "rd", rd_str
);
311 vty_out(vty
, "%s\n", rd_str
);
315 decode_rd_ip(pnt
+ 2, &rd_ip
);
316 snprintf(rd_str
, len
, "%s:%d", inet_ntoa(rd_ip
.ip
),
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
326 snprintf(rd_str
, len
, "Unknown");
327 json_object_string_add(json
, "rd", rd_str
);
329 snprintf(rd_str
, len
, "Unknown RD type");
330 vty_out(vty
, "%s\n", rd_str
);
336 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
337 uint64_t tbl_ver
, json_object
*json
)
340 " Network Next Hop Metric LocPrf Weight Path\n";
345 vty_out(vty
, "BGP table version is %" PRIu64
", local router ID is %s\n",
346 tbl_ver
, inet_ntoa(bgp
->router_id
));
348 "Status codes: s suppressed, d damped, h history, "
349 "* valid, > best, i - internal\n");
350 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
352 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
353 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
354 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
355 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
356 vty_out(vty
, "%s", ri_header
);
359 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
362 char buf1
[INET6_ADDRSTRLEN
];
364 struct listnode
*node
, *nnode
;
365 struct ecommunity
*ecom
;
366 json_object
*json_import_rtl
= NULL
;
367 json_object
*json_export_rtl
= NULL
;
368 char buf2
[ETHER_ADDR_STRLEN
];
370 json_import_rtl
= json_export_rtl
= 0;
373 json_import_rtl
= json_object_new_array();
374 json_export_rtl
= json_object_new_array();
375 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
376 json_object_string_add(json
, "type", "L3");
377 json_object_string_add(json
, "inKernel", "True");
378 json_object_string_add(
380 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
381 json_object_string_add(json
, "originatorIp",
382 inet_ntoa(bgp_vrf
->originator_ip
));
383 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
384 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
385 json_object_to_json_string_ext(json
,
386 JSON_C_TO_STRING_NOSLASHESCAPE
);
387 json_object_string_add(json
, "advertisePip",
388 bgp_vrf
->evpn_info
->advertise_pip
?
389 "Enabled" : "Disabled");
390 json_object_string_add(json
, "sysIP",
392 &bgp_vrf
->evpn_info
->pip_ip
,
393 buf1
, INET_ADDRSTRLEN
));
394 json_object_string_add(json
, "sysMac",
395 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
396 buf2
, sizeof(buf2
)));
397 json_object_string_add(json
, "rmac",
398 prefix_mac2str(&bgp_vrf
->rmac
,
399 buf2
, sizeof(buf2
)));
401 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
402 vty_out(vty
, " (known to the kernel)");
405 vty_out(vty
, " Type: %s\n", "L3");
406 vty_out(vty
, " Tenant VRF: %s\n",
407 vrf_id_to_name(bgp_vrf
->vrf_id
));
408 vty_out(vty
, " RD: %s\n",
409 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
410 vty_out(vty
, " Originator IP: %s\n",
411 inet_ntoa(bgp_vrf
->originator_ip
));
412 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
413 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
414 vty_out(vty
, " Advertise-pip: %s\n",
415 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
416 vty_out(vty
, " System-IP: %s\n",
417 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
418 buf1
, INET_ADDRSTRLEN
));
419 vty_out(vty
, " System-MAC: %s\n",
420 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
421 buf2
, sizeof(buf2
)));
422 vty_out(vty
, " Router-MAC: %s\n",
423 prefix_mac2str(&bgp_vrf
->rmac
,
424 buf2
, sizeof(buf2
)));
428 vty_out(vty
, " Import Route Target:\n");
430 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
431 ecom_str
= ecommunity_ecom2str(ecom
,
432 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
435 json_object_array_add(json_import_rtl
,
436 json_object_new_string(ecom_str
));
438 vty_out(vty
, " %s\n", ecom_str
);
440 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
444 json_object_object_add(json
, "importRts", json_import_rtl
);
446 vty_out(vty
, " Export Route Target:\n");
448 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
449 ecom_str
= ecommunity_ecom2str(ecom
,
450 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
453 json_object_array_add(json_export_rtl
,
454 json_object_new_string(ecom_str
));
456 vty_out(vty
, " %s\n", ecom_str
);
458 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
462 json_object_object_add(json
, "exportRts", json_export_rtl
);
465 static void display_es(struct vty
*vty
, struct evpnes
*es
, json_object
*json
)
467 struct in_addr
*vtep
;
468 char buf
[ESI_STR_LEN
];
469 char buf1
[RD_ADDRSTRLEN
];
470 char buf2
[INET6_ADDRSTRLEN
];
471 struct listnode
*node
= NULL
;
472 json_object
*json_vteps
= NULL
;
475 json_vteps
= json_object_new_array();
476 json_object_string_add(json
, "esi",
477 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
478 json_object_string_add(json
, "rd",
479 prefix_rd2str(&es
->prd
, buf1
,
481 json_object_string_add(
482 json
, "originatorIp",
483 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
485 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
486 json_object_array_add(
487 json_vteps
, json_object_new_string(
490 json_object_object_add(json
, "vteps", json_vteps
);
492 vty_out(vty
, "ESI: %s\n",
493 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
494 vty_out(vty
, " RD: %s\n", prefix_rd2str(&es
->prd
, buf1
,
496 vty_out(vty
, " Originator-IP: %s\n",
497 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
499 vty_out(vty
, " VTEP List:\n");
500 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
501 vty_out(vty
, " %s\n", inet_ntoa(*vtep
));
506 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
508 char buf1
[RD_ADDRSTRLEN
];
510 struct listnode
*node
, *nnode
;
511 struct ecommunity
*ecom
;
512 json_object
*json_import_rtl
= NULL
;
513 json_object
*json_export_rtl
= NULL
;
514 struct bgp
*bgp_evpn
;
516 bgp_evpn
= bgp_get_evpn();
519 json_import_rtl
= json_object_new_array();
520 json_export_rtl
= json_object_new_array();
521 json_object_int_add(json
, "vni", vpn
->vni
);
522 json_object_string_add(json
, "type", "L2");
523 json_object_string_add(json
, "inKernel",
524 is_vni_live(vpn
) ? "True" : "False");
525 json_object_string_add(
527 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
528 json_object_string_add(json
, "originatorIp",
529 inet_ntoa(vpn
->originator_ip
));
530 json_object_string_add(json
, "mcastGroup",
531 inet_ntoa(vpn
->mcast_grp
));
532 /* per vni knob is enabled -- Enabled
533 * Global knob is enabled -- Active
534 * default -- Disabled
536 if (!vpn
->advertise_gw_macip
&&
537 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
538 json_object_string_add(json
, "advertiseGatewayMacip",
540 else if (vpn
->advertise_gw_macip
)
541 json_object_string_add(json
, "advertiseGatewayMacip",
544 json_object_string_add(json
, "advertiseGatewayMacip",
546 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
547 bgp_evpn
->evpn_info
->advertise_svi_macip
)
548 json_object_string_add(json
, "advertiseSviMacIp",
550 else if (vpn
->advertise_svi_macip
)
551 json_object_string_add(json
, "advertiseSviMacIp",
554 json_object_string_add(json
, "advertiseSviMacIp",
557 vty_out(vty
, "VNI: %d", vpn
->vni
);
558 if (is_vni_live(vpn
))
559 vty_out(vty
, " (known to the kernel)");
562 vty_out(vty
, " Type: %s\n", "L2");
563 vty_out(vty
, " Tenant-Vrf: %s\n",
564 vrf_id_to_name(vpn
->tenant_vrf_id
));
565 vty_out(vty
, " RD: %s\n",
566 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
567 vty_out(vty
, " Originator IP: %s\n",
568 inet_ntoa(vpn
->originator_ip
));
569 vty_out(vty
, " Mcast group: %s\n",
570 inet_ntoa(vpn
->mcast_grp
));
571 if (!vpn
->advertise_gw_macip
&&
572 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
573 vty_out(vty
, " Advertise-gw-macip : %s\n",
575 else if (vpn
->advertise_gw_macip
)
576 vty_out(vty
, " Advertise-gw-macip : %s\n",
579 vty_out(vty
, " Advertise-gw-macip : %s\n",
581 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
582 bgp_evpn
->evpn_info
->advertise_svi_macip
)
583 vty_out(vty
, " Advertise-svi-macip : %s\n",
585 else if (vpn
->advertise_svi_macip
)
586 vty_out(vty
, " Advertise-svi-macip : %s\n",
589 vty_out(vty
, " Advertise-svi-macip : %s\n",
594 vty_out(vty
, " Import Route Target:\n");
596 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
597 ecom_str
= ecommunity_ecom2str(ecom
,
598 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
601 json_object_array_add(json_import_rtl
,
602 json_object_new_string(ecom_str
));
604 vty_out(vty
, " %s\n", ecom_str
);
606 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
610 json_object_object_add(json
, "importRts", json_import_rtl
);
612 vty_out(vty
, " Export Route Target:\n");
614 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
615 ecom_str
= ecommunity_ecom2str(ecom
,
616 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
619 json_object_array_add(json_export_rtl
,
620 json_object_new_string(ecom_str
));
622 vty_out(vty
, " %s\n", ecom_str
);
624 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
628 json_object_object_add(json
, "exportRts", json_export_rtl
);
631 static void show_esi_routes(struct bgp
*bgp
,
638 struct bgp_path_info
*pi
;
639 uint32_t prefix_cnt
, path_cnt
;
642 prefix_cnt
= path_cnt
= 0;
644 tbl_ver
= es
->route_table
->version
;
645 for (rn
= bgp_table_top(es
->route_table
); rn
;
646 rn
= bgp_route_next(rn
)) {
647 int add_prefix_to_json
= 0;
648 char prefix_str
[BUFSIZ
];
649 json_object
*json_paths
= NULL
;
650 json_object
*json_prefix
= NULL
;
651 const struct prefix
*p
= bgp_node_get_prefix(rn
);
653 bgp_evpn_route2str((struct prefix_evpn
*)p
, prefix_str
,
657 json_prefix
= json_object_new_object();
659 pi
= bgp_node_get_bgp_path_info(rn
);
661 /* Overall header/legend displayed once. */
663 bgp_evpn_show_route_header(vty
, bgp
,
672 json_paths
= json_object_new_array();
674 /* For EVPN, the prefix is displayed for each path (to fit in
675 * with code that already exists).
677 for (; pi
; pi
= pi
->next
) {
678 json_object
*json_path
= NULL
;
681 json_path
= json_object_new_array();
683 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
);
686 json_object_array_add(json_paths
, json_path
);
689 add_prefix_to_json
= 1;
693 if (add_prefix_to_json
) {
694 json_object_string_add(json_prefix
, "prefix",
696 json_object_int_add(json_prefix
, "prefixLen",
698 json_object_object_add(json_prefix
, "paths",
700 json_object_object_add(json
, prefix_str
,
703 json_object_free(json_paths
);
704 json_object_free(json_prefix
);
712 json_object_int_add(json
, "numPrefix", prefix_cnt
);
713 json_object_int_add(json
, "numPaths", path_cnt
);
716 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
718 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
719 prefix_cnt
, path_cnt
);
723 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
724 struct vty
*vty
, struct in_addr vtep_ip
,
725 json_object
*json
, int detail
)
728 struct bgp_path_info
*pi
;
729 struct bgp_table
*table
;
730 int header
= detail
? 0 : 1;
732 uint32_t prefix_cnt
, path_cnt
;
734 prefix_cnt
= path_cnt
= 0;
736 table
= vpn
->route_table
;
737 tbl_ver
= table
->version
;
738 for (rn
= bgp_table_top(table
); rn
;
739 rn
= bgp_route_next(rn
)) {
740 const struct prefix_evpn
*evp
=
741 (const struct prefix_evpn
*)bgp_node_get_prefix(rn
);
742 int add_prefix_to_json
= 0;
743 char prefix_str
[BUFSIZ
];
744 json_object
*json_paths
= NULL
;
745 json_object
*json_prefix
= NULL
;
746 const struct prefix
*p
= bgp_node_get_prefix(rn
);
748 bgp_evpn_route2str((const struct prefix_evpn
*)p
, prefix_str
,
751 if (type
&& evp
->prefix
.route_type
!= type
)
755 json_prefix
= json_object_new_object();
757 pi
= bgp_node_get_bgp_path_info(rn
);
759 /* Overall header/legend displayed once. */
761 bgp_evpn_show_route_header(vty
, bgp
,
770 json_paths
= json_object_new_array();
772 /* For EVPN, the prefix is displayed for each path (to fit in
773 * with code that already exists).
775 for (; pi
; pi
= pi
->next
) {
776 json_object
*json_path
= NULL
;
778 if (vtep_ip
.s_addr
!= INADDR_ANY
779 && !IPV4_ADDR_SAME(&(vtep_ip
),
780 &(pi
->attr
->nexthop
)))
784 json_path
= json_object_new_array();
787 route_vty_out_detail(vty
, bgp
, rn
, pi
,
788 AFI_L2VPN
, SAFI_EVPN
,
791 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
795 json_object_array_add(json_paths
, json_path
);
798 add_prefix_to_json
= 1;
802 if (add_prefix_to_json
) {
803 json_object_string_add(json_prefix
, "prefix",
805 json_object_int_add(json_prefix
, "prefixLen",
807 json_object_object_add(json_prefix
, "paths",
809 json_object_object_add(json
, prefix_str
,
812 json_object_free(json_paths
);
813 json_object_free(json_prefix
);
821 json_object_int_add(json
, "numPrefix", prefix_cnt
);
822 json_object_int_add(json
, "numPaths", path_cnt
);
825 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
826 type
? "(of requested type) " : "");
828 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
829 prefix_cnt
, path_cnt
,
830 type
? " (of requested type)" : "");
835 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
837 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
838 struct vni_walk_ctx
*wctx
= arg
;
839 struct vty
*vty
= wctx
->vty
;
840 json_object
*json
= wctx
->json
;
841 json_object
*json_vni
= NULL
;
842 char vni_str
[VNI_STR_LEN
];
844 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
846 json_vni
= json_object_new_object();
847 json_object_int_add(json_vni
, "vni", vpn
->vni
);
849 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
852 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
856 json_object_object_add(json
, vni_str
, json_vni
);
859 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
862 json_object
*json_vni
= NULL
;
863 json_object
*json_import_rtl
= NULL
;
864 json_object
*json_export_rtl
= NULL
;
866 char buf2
[INET6_ADDRSTRLEN
];
869 struct listnode
*node
, *nnode
;
870 struct ecommunity
*ecom
;
876 json_vni
= json_object_new_object();
877 json_import_rtl
= json_object_new_array();
878 json_export_rtl
= json_object_new_array();
881 /* if an l3vni is present in bgp it is live */
883 snprintf(buf1
, sizeof(buf1
), "*");
886 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
887 json_object_string_add(json_vni
, "type", "L3");
888 json_object_string_add(json_vni
, "inKernel", "True");
889 json_object_string_add(json_vni
, "originatorIp",
890 inet_ntoa(bgp
->originator_ip
));
891 json_object_string_add(
893 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
894 json_object_string_add(json_vni
, "advertiseGatewayMacip",
896 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
897 json_object_to_json_string_ext(json_vni
,
898 JSON_C_TO_STRING_NOSLASHESCAPE
);
899 json_object_string_add(
900 json_vni
, "advertisePip",
901 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
902 json_object_string_add(json_vni
, "sysIP",
903 inet_ntoa(bgp
->evpn_info
->pip_ip
));
904 json_object_string_add(json_vni
, "sysMAC",
905 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
906 buf2
, sizeof(buf2
)));
907 json_object_string_add(
909 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
911 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
912 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
915 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
916 ecom_str
= ecommunity_ecom2str(ecom
,
917 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
920 json_object_array_add(json_import_rtl
,
921 json_object_new_string(ecom_str
));
923 if (listcount(bgp
->vrf_import_rtl
) > 1)
924 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
927 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
929 vty_out(vty
, " %-25s", rt_buf
);
932 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
934 /* If there are multiple import RTs we break here and show only
941 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
943 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
944 ecom_str
= ecommunity_ecom2str(ecom
,
945 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
948 json_object_array_add(json_export_rtl
,
949 json_object_new_string(ecom_str
));
951 if (listcount(bgp
->vrf_export_rtl
) > 1)
952 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
955 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
957 vty_out(vty
, " %-25s", rt_buf
);
960 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
962 /* If there are multiple export RTs we break here and show only
969 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
972 char vni_str
[VNI_STR_LEN
];
974 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
975 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
976 json_object_object_add(json
, vni_str
, json_vni
);
982 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
984 char buf
[ESI_STR_LEN
];
985 char buf1
[RD_ADDRSTRLEN
];
986 char buf2
[INET6_ADDRSTRLEN
];
987 struct in_addr
*vtep
= NULL
;
988 struct vty
*vty
= args
[0];
989 json_object
*json
= args
[1];
990 json_object
*json_vteps
= NULL
;
991 struct listnode
*node
= NULL
;
992 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
995 json_vteps
= json_object_new_array();
996 json_object_string_add(json
, "esi",
997 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
998 json_object_string_add(json
, "type",
999 is_es_local(es
) ? "Local" : "Remote");
1000 json_object_string_add(json
, "rd",
1001 prefix_rd2str(&es
->prd
, buf1
,
1003 json_object_string_add(
1004 json
, "originatorIp",
1005 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
1006 if (es
->vtep_list
) {
1007 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
1008 json_object_array_add(json_vteps
,
1009 json_object_new_string(
1012 json_object_object_add(json
, "vteps", json_vteps
);
1014 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
1015 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
1016 is_es_local(es
) ? "Local" : "Remote",
1017 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
1018 ipaddr2str(&es
->originator_ip
, buf2
,
1020 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
1024 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1028 json_object
*json_vni
= NULL
;
1029 json_object
*json_import_rtl
= NULL
;
1030 json_object
*json_export_rtl
= NULL
;
1031 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1033 char buf2
[RD_ADDRSTRLEN
];
1036 struct listnode
*node
, *nnode
;
1037 struct ecommunity
*ecom
;
1038 struct bgp
*bgp_evpn
;
1043 bgp_evpn
= bgp_get_evpn();
1046 json_vni
= json_object_new_object();
1047 json_import_rtl
= json_object_new_array();
1048 json_export_rtl
= json_object_new_array();
1052 if (is_vni_live(vpn
))
1053 snprintf(buf1
, sizeof(buf1
), "*");
1056 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1057 json_object_string_add(json_vni
, "type", "L2");
1058 json_object_string_add(json_vni
, "inKernel",
1059 is_vni_live(vpn
) ? "True" : "False");
1060 json_object_string_add(
1062 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1063 json_object_string_add(json_vni
, "originatorIp",
1064 inet_ntoa(vpn
->originator_ip
));
1065 json_object_string_add(json_vni
, "mcastGroup",
1066 inet_ntoa(vpn
->mcast_grp
));
1067 /* per vni knob is enabled -- Enabled
1068 * Global knob is enabled -- Active
1069 * default -- Disabled
1071 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1072 && bgp_evpn
->advertise_gw_macip
)
1073 json_object_string_add(
1074 json_vni
, "advertiseGatewayMacip", "Active");
1075 else if (vpn
->advertise_gw_macip
)
1076 json_object_string_add(
1077 json_vni
, "advertiseGatewayMacip", "Enabled");
1079 json_object_string_add(
1080 json_vni
, "advertiseGatewayMacip", "Disabled");
1081 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1082 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1083 json_object_string_add(json_vni
, "advertiseSviMacIp",
1085 else if (vpn
->advertise_svi_macip
)
1086 json_object_string_add(json_vni
, "advertiseSviMacIp",
1089 json_object_string_add(json_vni
, "advertiseSviMacIp",
1092 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1093 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1096 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1097 ecom_str
= ecommunity_ecom2str(ecom
,
1098 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1101 json_object_array_add(json_import_rtl
,
1102 json_object_new_string(ecom_str
));
1104 if (listcount(vpn
->import_rtl
) > 1)
1105 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1108 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1110 vty_out(vty
, " %-25s", rt_buf
);
1113 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1115 /* If there are multiple import RTs we break here and show only
1122 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1124 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1125 ecom_str
= ecommunity_ecom2str(ecom
,
1126 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1129 json_object_array_add(json_export_rtl
,
1130 json_object_new_string(ecom_str
));
1132 if (listcount(vpn
->export_rtl
) > 1)
1133 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1136 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1138 vty_out(vty
, " %-25s", rt_buf
);
1141 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1143 /* If there are multiple export RTs we break here and show only
1150 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1153 char vni_str
[VNI_STR_LEN
];
1155 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1156 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1157 json_object_object_add(json
, vni_str
, json_vni
);
1163 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1164 enum bgp_show_type type
, void *output_arg
,
1165 int option
, bool use_json
)
1167 afi_t afi
= AFI_L2VPN
;
1169 struct bgp_table
*table
;
1170 struct bgp_node
*rn
;
1171 struct bgp_node
*rm
;
1172 struct bgp_path_info
*pi
;
1175 char rd_str
[RD_ADDRSTRLEN
];
1179 unsigned long output_count
= 0;
1180 unsigned long total_count
= 0;
1181 json_object
*json
= NULL
;
1182 json_object
*json_array
= NULL
;
1183 json_object
*json_prefix_info
= NULL
;
1185 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1187 bgp
= bgp_get_evpn();
1190 vty_out(vty
, "No BGP process is configured\n");
1192 vty_out(vty
, "{}\n");
1197 json
= json_object_new_object();
1199 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1200 rn
= bgp_route_next(rn
)) {
1202 json_object
*json_nroute
= NULL
;
1203 const struct prefix
*p
= bgp_node_get_prefix(rn
);
1205 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1208 table
= bgp_node_get_bgp_table_info(rn
);
1213 tbl_ver
= table
->version
;
1215 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1216 pi
= bgp_node_get_bgp_path_info(rm
);
1221 for (; pi
; pi
= pi
->next
) {
1223 if (type
== bgp_show_type_neighbor
) {
1224 struct peer
*peer
= output_arg
;
1226 if (peer_cmp(peer
, pi
->peer
) != 0)
1229 if (type
== bgp_show_type_lcommunity_exact
) {
1230 struct lcommunity
*lcom
= output_arg
;
1232 if (!pi
->attr
->lcommunity
||
1234 pi
->attr
->lcommunity
, lcom
))
1237 if (type
== bgp_show_type_lcommunity
) {
1238 struct lcommunity
*lcom
= output_arg
;
1240 if (!pi
->attr
->lcommunity
||
1242 pi
->attr
->lcommunity
, lcom
))
1245 if (type
== bgp_show_type_community
) {
1246 struct community
*com
= output_arg
;
1248 if (!pi
->attr
->community
||
1250 pi
->attr
->community
, com
))
1253 if (type
== bgp_show_type_community_exact
) {
1254 struct community
*com
= output_arg
;
1256 if (!pi
->attr
->community
||
1258 pi
->attr
->community
, com
))
1263 json_object_int_add(
1264 json
, "bgpTableVersion",
1266 json_object_string_add(
1271 json_object_int_add(
1274 bgp
->default_local_pref
);
1275 json_object_int_add(
1279 if (option
== SHOW_DISPLAY_TAGS
)
1284 == SHOW_DISPLAY_OVERLAY
)
1288 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1296 json_object_new_object();
1297 bgp_evpn_show_route_rd_header(vty
, rn
,
1298 json_nroute
, rd_str
,
1302 if (use_json
&& !json_array
)
1303 json_array
= json_object_new_array();
1305 if (option
== SHOW_DISPLAY_TAGS
)
1307 vty
, bgp_node_get_prefix(rm
),
1308 pi
, no_display
, SAFI_EVPN
,
1310 else if (option
== SHOW_DISPLAY_OVERLAY
)
1311 route_vty_out_overlay(
1312 vty
, bgp_node_get_prefix(rm
),
1313 pi
, no_display
, json_array
);
1316 bgp_node_get_prefix(rm
),
1317 pi
, no_display
, SAFI_EVPN
,
1325 if (use_json
&& json_array
) {
1326 const struct prefix
*p
=
1327 bgp_node_get_prefix(rm
);
1329 json_prefix_info
= json_object_new_object();
1331 json_object_string_add(
1332 json_prefix_info
, "prefix",
1334 (struct prefix_evpn
*)p
, buf
,
1337 json_object_int_add(json_prefix_info
,
1338 "prefixLen", p
->prefixlen
);
1340 json_object_object_add(json_prefix_info
,
1341 "paths", json_array
);
1342 json_object_object_add(json_nroute
, buf
,
1348 if (use_json
&& json_nroute
)
1349 json_object_object_add(json
, rd_str
, json_nroute
);
1353 json_object_int_add(json
, "numPrefix", output_count
);
1354 json_object_int_add(json
, "totalPrefix", total_count
);
1355 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1356 json
, JSON_C_TO_STRING_PRETTY
));
1357 json_object_free(json
);
1359 if (output_count
== 0)
1360 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1364 "\nDisplayed %ld out of %ld total prefixes\n",
1365 output_count
, total_count
);
1370 DEFUN(show_ip_bgp_l2vpn_evpn
,
1371 show_ip_bgp_l2vpn_evpn_cmd
,
1372 "show [ip] bgp l2vpn evpn [json]",
1373 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1375 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1376 use_json(argc
, argv
));
1379 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1380 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1381 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1387 "Display information for a route distinguisher\n"
1388 "VPN Route Distinguisher\n" JSON_STR
)
1390 int idx_ext_community
= 0;
1392 struct prefix_rd prd
;
1394 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1396 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1398 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1401 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1402 use_json(argc
, argv
));
1405 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1406 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1407 "show [ip] bgp l2vpn evpn all tags",
1413 "Display information about all EVPN NLRIs\n"
1414 "Display BGP tags for prefixes\n")
1416 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1420 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1421 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1422 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1428 "Display information for a route distinguisher\n"
1429 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1431 int idx_ext_community
= 0;
1433 struct prefix_rd prd
;
1435 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1437 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1439 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1442 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1446 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1447 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1448 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1454 "Detailed information on TCP and BGP neighbor connections\n"
1455 "IPv4 Neighbor to display information about\n"
1456 "IPv6 Neighbor to display information about\n"
1457 "Neighbor on BGP configured interface\n"
1458 "Display routes learned from neighbor\n" JSON_STR
)
1462 char *peerstr
= NULL
;
1463 bool uj
= use_json(argc
, argv
);
1464 afi_t afi
= AFI_L2VPN
;
1465 safi_t safi
= SAFI_EVPN
;
1466 struct bgp
*bgp
= NULL
;
1468 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1471 vty_out(vty
, "No index\n");
1475 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1476 argv_find(argv
, argc
, "neighbors", &idx
);
1477 peerstr
= argv
[++idx
]->arg
;
1479 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1482 json_object
*json_no
= NULL
;
1483 json_no
= json_object_new_object();
1484 json_object_string_add(json_no
, "warning",
1485 "Malformed address");
1486 vty_out(vty
, "%s\n",
1487 json_object_to_json_string(json_no
));
1488 json_object_free(json_no
);
1490 vty_out(vty
, "Malformed address: %s\n",
1494 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1496 json_object
*json_no
= NULL
;
1497 json_no
= json_object_new_object();
1498 json_object_string_add(
1500 "No such neighbor or address family");
1501 vty_out(vty
, "%s\n",
1502 json_object_to_json_string(json_no
));
1503 json_object_free(json_no
);
1505 vty_out(vty
, "%% No such neighbor or address family\n");
1509 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1513 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1514 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1515 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1521 "Display information for a route distinguisher\n"
1522 "VPN Route Distinguisher\n"
1523 "Detailed information on TCP and BGP neighbor connections\n"
1524 "IPv4 Neighbor to display information about\n"
1525 "IPv6 Neighbor to display information about\n"
1526 "Neighbor on BGP configured interface\n"
1527 "Display routes learned from neighbor\n" JSON_STR
)
1529 int idx_ext_community
= 0;
1533 char *peerstr
= NULL
;
1534 struct prefix_rd prd
;
1535 bool uj
= use_json(argc
, argv
);
1536 afi_t afi
= AFI_L2VPN
;
1537 safi_t safi
= SAFI_EVPN
;
1538 struct bgp
*bgp
= NULL
;
1540 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1543 vty_out(vty
, "No index\n");
1547 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1548 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1551 json_object
*json_no
= NULL
;
1552 json_no
= json_object_new_object();
1553 json_object_string_add(json_no
, "warning",
1554 "Malformed Route Distinguisher");
1555 vty_out(vty
, "%s\n",
1556 json_object_to_json_string(json_no
));
1557 json_object_free(json_no
);
1559 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1563 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1564 argv_find(argv
, argc
, "neighbors", &idx
);
1565 peerstr
= argv
[++idx
]->arg
;
1567 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1570 json_object
*json_no
= NULL
;
1571 json_no
= json_object_new_object();
1572 json_object_string_add(json_no
, "warning",
1573 "Malformed address");
1574 vty_out(vty
, "%s\n",
1575 json_object_to_json_string(json_no
));
1576 json_object_free(json_no
);
1578 vty_out(vty
, "Malformed address: %s\n",
1582 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1584 json_object
*json_no
= NULL
;
1585 json_no
= json_object_new_object();
1586 json_object_string_add(
1588 "No such neighbor or address family");
1589 vty_out(vty
, "%s\n",
1590 json_object_to_json_string(json_no
));
1591 json_object_free(json_no
);
1593 vty_out(vty
, "%% No such neighbor or address family\n");
1597 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1601 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1602 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1603 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1609 "Detailed information on TCP and BGP neighbor connections\n"
1610 "IPv4 Neighbor to display information about\n"
1611 "IPv6 Neighbor to display information about\n"
1612 "Neighbor on BGP configured interface\n"
1613 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1617 bool uj
= use_json(argc
, argv
);
1618 struct bgp
*bgp
= NULL
;
1619 afi_t afi
= AFI_L2VPN
;
1620 safi_t safi
= SAFI_EVPN
;
1621 char *peerstr
= NULL
;
1626 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1629 vty_out(vty
, "No index\n");
1633 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1634 argv_find(argv
, argc
, "neighbors", &idx
);
1635 peerstr
= argv
[++idx
]->arg
;
1637 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1640 json_object
*json_no
= NULL
;
1641 json_no
= json_object_new_object();
1642 json_object_string_add(json_no
, "warning",
1643 "Malformed address");
1644 vty_out(vty
, "%s\n",
1645 json_object_to_json_string(json_no
));
1646 json_object_free(json_no
);
1648 vty_out(vty
, "Malformed address: %s\n",
1652 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1654 json_object
*json_no
= NULL
;
1655 json_no
= json_object_new_object();
1656 json_object_string_add(
1658 "No such neighbor or address family");
1659 vty_out(vty
, "%s\n",
1660 json_object_to_json_string(json_no
));
1661 json_object_free(json_no
);
1663 vty_out(vty
, "%% No such neighbor or address family\n");
1667 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1670 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1671 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1672 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1678 "Display information for a route distinguisher\n"
1679 "VPN Route Distinguisher\n"
1680 "Detailed information on TCP and BGP neighbor connections\n"
1681 "IPv4 Neighbor to display information about\n"
1682 "IPv6 Neighbor to display information about\n"
1683 "Neighbor on BGP configured interface\n"
1684 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1686 int idx_ext_community
= 0;
1690 struct prefix_rd prd
;
1691 struct bgp
*bgp
= NULL
;
1692 bool uj
= use_json(argc
, argv
);
1693 char *peerstr
= NULL
;
1694 afi_t afi
= AFI_L2VPN
;
1695 safi_t safi
= SAFI_EVPN
;
1703 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1706 vty_out(vty
, "No index\n");
1710 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1712 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1713 argv_find(argv
, argc
, "neighbors", &idx
);
1714 peerstr
= argv
[++idx
]->arg
;
1716 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1719 json_object
*json_no
= NULL
;
1720 json_no
= json_object_new_object();
1721 json_object_string_add(json_no
, "warning",
1722 "Malformed address");
1723 vty_out(vty
, "%s\n",
1724 json_object_to_json_string(json_no
));
1725 json_object_free(json_no
);
1727 vty_out(vty
, "Malformed address: %s\n",
1731 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1733 json_object
*json_no
= NULL
;
1734 json_no
= json_object_new_object();
1735 json_object_string_add(
1737 "No such neighbor or address family");
1738 vty_out(vty
, "%s\n",
1739 json_object_to_json_string(json_no
));
1740 json_object_free(json_no
);
1742 vty_out(vty
, "%% No such neighbor or address family\n");
1746 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1749 json_object
*json_no
= NULL
;
1750 json_no
= json_object_new_object();
1751 json_object_string_add(json_no
, "warning",
1752 "Malformed Route Distinguisher");
1753 vty_out(vty
, "%s\n",
1754 json_object_to_json_string(json_no
));
1755 json_object_free(json_no
);
1757 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1761 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1764 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1765 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1766 "show [ip] bgp l2vpn evpn all overlay [json]",
1772 "Display information about all EVPN NLRIs\n"
1773 "Display BGP Overlay Information for prefixes\n"
1776 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1777 SHOW_DISPLAY_OVERLAY
,
1778 use_json(argc
, argv
));
1781 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1782 show_ip_bgp_evpn_rd_overlay_cmd
,
1783 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1789 "Display information for a route distinguisher\n"
1790 "VPN Route Distinguisher\n"
1791 "Display BGP Overlay Information for prefixes\n")
1793 int idx_ext_community
= 0;
1795 struct prefix_rd prd
;
1797 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1799 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1801 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1804 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1805 SHOW_DISPLAY_OVERLAY
,
1806 use_json(argc
, argv
));
1809 DEFUN(show_bgp_l2vpn_evpn_com
,
1810 show_bgp_l2vpn_evpn_com_cmd
,
1811 "show bgp l2vpn evpn \
1812 <community AA:NN|large-community AA:BB:CC> \
1813 [exact-match] [json]",
1818 "Display routes matching the community\n"
1819 "Community number where AA and NN are (0-65535)\n"
1820 "Display routes matching the large-community\n"
1821 "List of large-community numbers\n"
1822 "Exact match of the communities\n"
1827 const char *clist_number_or_name
;
1828 int show_type
= bgp_show_type_normal
;
1829 struct community
*com
;
1830 struct lcommunity
*lcom
;
1832 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1833 clist_number_or_name
= argv
[++idx
]->arg
;
1834 show_type
= bgp_show_type_lcommunity
;
1836 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1837 show_type
= bgp_show_type_lcommunity_exact
;
1839 lcom
= lcommunity_str2com(clist_number_or_name
);
1841 vty_out(vty
, "%% Large-community malformed\n");
1845 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1846 SHOW_DISPLAY_STANDARD
,
1847 use_json(argc
, argv
));
1849 lcommunity_free(&lcom
);
1850 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1851 clist_number_or_name
= argv
[++idx
]->arg
;
1852 show_type
= bgp_show_type_community
;
1854 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1855 show_type
= bgp_show_type_community_exact
;
1857 com
= community_str2com(clist_number_or_name
);
1860 vty_out(vty
, "%% Community malformed: %s\n",
1861 clist_number_or_name
);
1865 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1866 SHOW_DISPLAY_STANDARD
,
1867 use_json(argc
, argv
));
1868 community_free(&com
);
1874 /* For testing purpose, static route of EVPN RT-5. */
1875 DEFUN(evpnrt5_network
,
1876 evpnrt5_network_cmd
,
1877 "network <A.B.C.D/M|X:X::X:X/M> rd ASN:NN_OR_IP-ADDRESS:NN ethtag WORD label WORD esi WORD gwip <A.B.C.D|X:X::X:X> routermac WORD [route-map WORD]",
1878 "Specify a network to announce via BGP\n"
1881 "Specify Route Distinguisher\n"
1882 "VPN Route Distinguisher\n"
1884 "Ethernet Tag Value\n"
1887 "Ethernet Segment Identifier\n"
1888 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1890 "Gateway IP ( A.B.C.D )\n"
1891 "Gateway IPv6 ( X:X::X:X )\n"
1892 "Router Mac Ext Comm\n"
1893 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1894 "Route-map to modify the attributes\n"
1895 "Name of the route map\n")
1897 int idx_ipv4_prefixlen
= 1;
1898 int idx_route_distinguisher
= 3;
1903 int idx_routermac
= 13;
1905 return bgp_static_set_safi(
1906 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1907 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1908 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1909 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1910 argv
[idx_routermac
]->arg
);
1913 /* For testing purpose, static route of EVPN RT-5. */
1914 DEFUN(no_evpnrt5_network
,
1915 no_evpnrt5_network_cmd
,
1916 "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>",
1918 "Specify a network to announce via BGP\n"
1921 "Specify Route Distinguisher\n"
1922 "VPN Route Distinguisher\n"
1924 "Ethernet Tag Value\n"
1927 "Ethernet Segment Identifier\n"
1928 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1929 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1931 int idx_ipv4_prefixlen
= 2;
1932 int idx_ext_community
= 4;
1937 return bgp_static_unset_safi(
1938 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1939 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1940 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1941 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1944 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1946 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1949 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1951 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1955 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1956 * check that this is a change.
1958 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1959 struct ecommunity
*ecomadd
)
1961 /* If the VNI is "live", we need to uninstall routes using the current
1962 * import RT(s) first before we update the import RT, and subsequently
1965 if (is_vni_live(vpn
))
1966 bgp_evpn_uninstall_routes(bgp
, vpn
);
1968 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1969 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1971 /* If the auto route-target is in use we must remove it */
1972 evpn_import_rt_delete_auto(bgp
, vpn
);
1974 /* Add new RT and rebuild the RT to VNI mapping */
1975 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1977 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1978 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1980 /* Install routes that match new import RT */
1981 if (is_vni_live(vpn
))
1982 bgp_evpn_install_routes(bgp
, vpn
);
1986 * Unconfigure Import RT(s) for a VNI (vty handler).
1988 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1989 struct ecommunity
*ecomdel
)
1991 struct listnode
*node
, *nnode
, *node_to_del
;
1992 struct ecommunity
*ecom
;
1994 /* Along the lines of "configure" except we have to reset to the
1997 if (is_vni_live(vpn
))
1998 bgp_evpn_uninstall_routes(bgp
, vpn
);
2000 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2001 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2003 /* Delete all import RTs */
2004 if (ecomdel
== NULL
) {
2005 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2006 ecommunity_free(&ecom
);
2007 list_delete_node(vpn
->import_rtl
, node
);
2011 /* Delete a specific import RT */
2015 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2016 if (ecommunity_match(ecom
, ecomdel
)) {
2017 ecommunity_free(&ecom
);
2024 list_delete_node(vpn
->import_rtl
, node_to_del
);
2027 assert(vpn
->import_rtl
);
2028 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2029 if (list_isempty(vpn
->import_rtl
)) {
2030 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2031 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2033 /* Rebuild the RT to VNI mapping */
2035 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2037 /* Install routes that match new import RT */
2038 if (is_vni_live(vpn
))
2039 bgp_evpn_install_routes(bgp
, vpn
);
2043 * Configure the Export RT for a VNI (vty handler). Caller expected to
2044 * check that this is a change. Note that only a single export RT is
2045 * allowed for a VNI and any change to configuration is implemented as
2046 * a "replace" (similar to other configuration).
2048 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2049 struct ecommunity
*ecomadd
)
2051 /* If the auto route-target is in use we must remove it */
2052 evpn_export_rt_delete_auto(bgp
, vpn
);
2054 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2055 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2057 if (is_vni_live(vpn
))
2058 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2062 * Unconfigure the Export RT for a VNI (vty handler)
2064 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2065 struct ecommunity
*ecomdel
)
2067 struct listnode
*node
, *nnode
, *node_to_del
;
2068 struct ecommunity
*ecom
;
2070 /* Delete all export RTs */
2071 if (ecomdel
== NULL
) {
2072 /* Reset to default and process all routes. */
2073 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2074 ecommunity_free(&ecom
);
2075 list_delete_node(vpn
->export_rtl
, node
);
2079 /* Delete a specific export RT */
2083 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2084 if (ecommunity_match(ecom
, ecomdel
)) {
2085 ecommunity_free(&ecom
);
2092 list_delete_node(vpn
->export_rtl
, node_to_del
);
2095 assert(vpn
->export_rtl
);
2096 if (list_isempty(vpn
->export_rtl
)) {
2097 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2098 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2101 if (is_vni_live(vpn
))
2102 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2106 * Configure RD for VRF
2108 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2110 /* If we have already advertise type-5 routes with a diffrent RD, we
2111 * have to delete and withdraw them firs
2113 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2116 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2117 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2119 /* We have a new RD for VRF.
2120 * Advertise all type-5 routes again with the new RD
2122 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2126 * Unconfigure RD for VRF
2128 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2130 /* If we have already advertise type-5 routes with a diffrent RD, we
2131 * have to delete and withdraw them firs
2133 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2135 /* fall back to default RD */
2136 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2137 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2139 /* We have a new RD for VRF.
2140 * Advertise all type-5 routes again with the new RD
2142 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2146 * Configure RD for a VNI (vty handler)
2148 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2149 struct prefix_rd
*rd
)
2151 /* If the VNI is "live", we need to delete and withdraw this VNI's
2152 * local routes with the prior RD first. Then, after updating RD,
2153 * need to re-advertise.
2155 if (is_vni_live(vpn
))
2156 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2159 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2160 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2162 if (is_vni_live(vpn
))
2163 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2167 * Unconfigure RD for a VNI (vty handler)
2169 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2171 /* If the VNI is "live", we need to delete and withdraw this VNI's
2172 * local routes with the prior RD first. Then, after resetting RD
2173 * to automatic value, need to re-advertise.
2175 if (is_vni_live(vpn
))
2176 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2178 /* reset RD to default */
2179 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2181 if (is_vni_live(vpn
))
2182 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2186 * Create VNI, if not already present (VTY handler). Mark as configured.
2188 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2190 struct bgpevpn
*vpn
;
2191 struct in_addr mcast_grp
= {INADDR_ANY
};
2196 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2198 /* Check if this L2VNI is already configured as L3VNI */
2199 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2202 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2207 /* tenant vrf will be updated when we get local_vni_add from
2210 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2214 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2220 /* Mark as configured. */
2221 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2226 * Delete VNI. If VNI does not exist in the system (i.e., just
2227 * configuration), all that is needed is to free it. Otherwise,
2228 * any parameters configured for the VNI need to be reset (with
2229 * appropriate action) and the VNI marked as unconfigured; the
2230 * VNI will continue to exist, purely as a "learnt" entity.
2232 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2234 assert(bgp
->vnihash
);
2236 if (!is_vni_live(vpn
)) {
2237 bgp_evpn_free(bgp
, vpn
);
2241 /* We need to take the unconfigure action for each parameter of this VNI
2242 * that is configured. Some optimization is possible, but not worth the
2243 * additional code for an operation that should be pretty rare.
2245 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2247 /* First, deal with the export side - RD and export RT changes. */
2248 if (is_rd_configured(vpn
))
2249 evpn_unconfigure_rd(bgp
, vpn
);
2250 if (is_export_rt_configured(vpn
))
2251 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2253 /* Next, deal with the import side. */
2254 if (is_import_rt_configured(vpn
))
2255 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2259 * Display import RT mapping to VRFs (vty handler)
2260 * bgp_evpn: evpn bgp instance
2262 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2270 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2271 (void (*)(struct hash_bucket
*,
2272 void *))show_vrf_import_rt_entry
,
2277 * Display import RT mapping to VNIs (vty handler)
2279 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2288 bgp
->import_rt_hash
,
2289 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2294 * Display EVPN routes for all VNIs - vty handler.
2296 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2297 struct in_addr vtep_ip
, json_object
*json
,
2301 struct vni_walk_ctx wctx
;
2303 num_vnis
= hashcount(bgp
->vnihash
);
2306 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2309 wctx
.vtep_ip
= vtep_ip
;
2311 wctx
.detail
= detail
;
2312 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2313 void *))show_vni_routes_hash
,
2318 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2320 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2321 vni_t vni
, struct in_addr orig_ip
,
2324 struct bgpevpn
*vpn
;
2325 struct prefix_evpn p
;
2326 struct bgp_node
*rn
;
2327 struct bgp_path_info
*pi
;
2328 uint32_t path_cnt
= 0;
2331 json_object
*json_paths
= NULL
;
2337 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2339 vty_out(vty
, "VNI not found\n");
2343 /* See if route exists. */
2344 build_evpn_type3_prefix(&p
, orig_ip
);
2345 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2346 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2348 vty_out(vty
, "%% Network not in table\n");
2353 json_paths
= json_object_new_array();
2355 /* Prefix and num paths displayed once per prefix. */
2356 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2358 /* Display each path for this prefix. */
2359 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2360 json_object
*json_path
= NULL
;
2363 json_path
= json_object_new_array();
2365 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2369 json_object_array_add(json_paths
, json_path
);
2376 json_object_object_add(json
, "paths", json_paths
);
2378 json_object_int_add(json
, "numPaths", path_cnt
);
2380 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2386 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2387 * By definition, only matching type-2 route will be displayed.
2389 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2390 vni_t vni
, struct ethaddr
*mac
,
2391 struct ipaddr
*ip
, json_object
*json
)
2393 struct bgpevpn
*vpn
;
2394 struct prefix_evpn p
;
2395 struct bgp_node
*rn
;
2396 struct bgp_path_info
*pi
;
2397 uint32_t path_cnt
= 0;
2400 json_object
*json_paths
= NULL
;
2406 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2409 vty_out(vty
, "VNI not found\n");
2413 /* See if route exists. Look for both non-sticky and sticky. */
2414 build_evpn_type2_prefix(&p
, mac
, ip
);
2415 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2416 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2418 vty_out(vty
, "%% Network not in table\n");
2423 json_paths
= json_object_new_array();
2425 /* Prefix and num paths displayed once per prefix. */
2426 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2428 /* Display each path for this prefix. */
2429 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2430 json_object
*json_path
= NULL
;
2433 json_path
= json_object_new_array();
2435 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2439 json_object_array_add(json_paths
, json_path
);
2446 json_object_object_add(json
, "paths", json_paths
);
2448 json_object_int_add(json
, "numPaths", path_cnt
);
2450 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2455 /* Disaplay EVPN routes for a ESI - VTY handler */
2456 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2457 esi_t
*esi
, json_object
*json
)
2459 struct evpnes
*es
= NULL
;
2462 es
= bgp_evpn_lookup_es(bgp
, esi
);
2465 vty_out(vty
, "ESI not found\n");
2469 show_esi_routes(bgp
, es
, vty
, json
);
2473 * Display EVPN routes for a VNI - vty handler.
2474 * If 'type' is non-zero, only routes matching that type are shown.
2475 * If the vtep_ip is non zero, only routes behind that vtep are shown
2477 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2478 int type
, struct in_addr vtep_ip
,
2481 struct bgpevpn
*vpn
;
2484 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2487 vty_out(vty
, "VNI not found\n");
2491 /* Walk this VNI's route table and display appropriate routes. */
2492 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2496 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2497 * IP (vty handler). By definition, only matching type-2 route will be
2500 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2501 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2502 struct ipaddr
*ip
, json_object
*json
)
2504 struct prefix_evpn p
;
2505 struct bgp_node
*rn
;
2506 struct bgp_path_info
*pi
;
2509 uint32_t path_cnt
= 0;
2510 json_object
*json_paths
= NULL
;
2511 char prefix_str
[BUFSIZ
];
2516 /* See if route exists. Look for both non-sticky and sticky. */
2517 build_evpn_type2_prefix(&p
, mac
, ip
);
2518 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2519 (struct prefix
*)&p
, prd
);
2520 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2522 vty_out(vty
, "%% Network not in table\n");
2526 bgp_evpn_route2str(&p
, prefix_str
, sizeof(prefix_str
));
2528 /* Prefix and num paths displayed once per prefix. */
2529 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2532 json_paths
= json_object_new_array();
2534 /* Display each path for this prefix. */
2535 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2536 json_object
*json_path
= NULL
;
2539 json_path
= json_object_new_array();
2541 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2545 json_object_array_add(json_paths
, json_path
);
2550 if (json
&& path_cnt
) {
2552 json_object_object_add(json
, prefix_str
, json_paths
);
2553 json_object_int_add(json
, "numPaths", path_cnt
);
2555 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2561 * Display BGP EVPN routing table -- for specific RD (vty handler)
2562 * If 'type' is non-zero, only routes matching that type are shown.
2564 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2565 struct prefix_rd
*prd
, int type
,
2568 struct bgp_node
*rd_rn
;
2569 struct bgp_table
*table
;
2570 struct bgp_node
*rn
;
2571 struct bgp_path_info
*pi
;
2575 uint32_t prefix_cnt
, path_cnt
;
2576 char rd_str
[RD_ADDRSTRLEN
];
2577 json_object
*json_rd
= NULL
;
2578 int add_rd_to_json
= 0;
2582 prefix_cnt
= path_cnt
= 0;
2584 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2586 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2590 table
= bgp_node_get_bgp_table_info(rd_rn
);
2595 json_rd
= json_object_new_object();
2596 json_object_string_add(json_rd
, "rd", rd_str
);
2599 /* Display all prefixes with this RD. */
2600 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2601 const struct prefix_evpn
*evp
=
2602 (const struct prefix_evpn
*)bgp_node_get_prefix(rn
);
2603 json_object
*json_prefix
= NULL
;
2604 json_object
*json_paths
= NULL
;
2605 char prefix_str
[BUFSIZ
];
2606 int add_prefix_to_json
= 0;
2608 bgp_evpn_route2str((struct prefix_evpn
*)evp
, prefix_str
,
2609 sizeof(prefix_str
));
2611 if (type
&& evp
->prefix
.route_type
!= type
)
2615 json_prefix
= json_object_new_object();
2617 pi
= bgp_node_get_bgp_path_info(rn
);
2619 /* RD header and legend - once overall. */
2620 if (rd_header
&& !json
) {
2622 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2624 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2626 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2630 /* Prefix and num paths displayed once per prefix. */
2631 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2638 json_paths
= json_object_new_array();
2640 /* Display each path for this prefix. */
2641 for (; pi
; pi
= pi
->next
) {
2642 json_object
*json_path
= NULL
;
2645 json_path
= json_object_new_array();
2647 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2651 json_object_array_add(json_paths
, json_path
);
2654 add_prefix_to_json
= 1;
2659 if (add_prefix_to_json
) {
2660 json_object_object_add(json_prefix
, "paths",
2662 json_object_object_add(json_rd
, prefix_str
,
2665 json_object_free(json_paths
);
2666 json_object_free(json_prefix
);
2675 json_object_object_add(json
, rd_str
, json_rd
);
2677 json_object_free(json_rd
);
2681 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2682 json_object_int_add(json
, "numPaths", path_cnt
);
2684 if (prefix_cnt
== 0)
2685 vty_out(vty
, "No prefixes exist with this RD%s\n",
2686 type
? " (of requested type)" : "");
2689 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2690 prefix_cnt
, path_cnt
,
2691 type
? " (of requested type)" : "");
2696 * Display BGP EVPN routing table - all routes (vty handler).
2697 * If 'type' is non-zero, only routes matching that type are shown.
2699 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2700 json_object
*json
, int detail
)
2702 struct bgp_node
*rd_rn
;
2703 struct bgp_table
*table
;
2704 struct bgp_node
*rn
;
2705 struct bgp_path_info
*pi
;
2706 int header
= detail
? 0 : 1;
2710 uint32_t prefix_cnt
, path_cnt
;
2714 prefix_cnt
= path_cnt
= 0;
2716 /* EVPN routing table is a 2-level table with the first level being
2719 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2720 rd_rn
= bgp_route_next(rd_rn
)) {
2721 char rd_str
[RD_ADDRSTRLEN
];
2722 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2723 int add_rd_to_json
= 0;
2725 const struct prefix
*rd_rnp
= bgp_node_get_prefix(rd_rn
);
2727 table
= bgp_node_get_bgp_table_info(rd_rn
);
2731 tbl_ver
= table
->version
;
2732 prefix_rd2str((struct prefix_rd
*)rd_rnp
, rd_str
,
2736 json_rd
= json_object_new_object();
2740 /* Display all prefixes for an RD */
2741 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2742 json_object
*json_prefix
=
2743 NULL
; /* contains prefix under a RD */
2744 json_object
*json_paths
=
2745 NULL
; /* array of paths under a prefix*/
2746 const struct prefix_evpn
*evp
=
2747 (const struct prefix_evpn
*)bgp_node_get_prefix(
2749 char prefix_str
[BUFSIZ
];
2750 int add_prefix_to_json
= 0;
2751 const struct prefix
*p
= bgp_node_get_prefix(rn
);
2753 bgp_evpn_route2str((struct prefix_evpn
*)p
, prefix_str
,
2754 sizeof(prefix_str
));
2756 if (type
&& evp
->prefix
.route_type
!= type
)
2759 pi
= bgp_node_get_bgp_path_info(rn
);
2761 /* Overall header/legend displayed once. */
2763 bgp_evpn_show_route_header(vty
, bgp
,
2768 "%19s Extended Community\n"
2773 /* RD header - per RD. */
2775 bgp_evpn_show_route_rd_header(
2776 vty
, rd_rn
, json_rd
, rd_str
,
2785 json_prefix
= json_object_new_object();
2786 json_paths
= json_object_new_array();
2787 json_object_string_add(json_prefix
, "prefix",
2789 json_object_int_add(json_prefix
, "prefixLen",
2793 /* Prefix and num paths displayed once per prefix. */
2795 route_vty_out_detail_header(
2797 (struct prefix_rd
*)rd_rnp
, AFI_L2VPN
,
2798 SAFI_EVPN
, json_prefix
);
2800 /* For EVPN, the prefix is displayed for each path (to
2802 * with code that already exists).
2804 for (; pi
; pi
= pi
->next
) {
2805 json_object
*json_path
= NULL
;
2807 add_prefix_to_json
= 1;
2811 json_path
= json_object_new_array();
2814 route_vty_out_detail(
2815 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2816 SAFI_EVPN
, json_path
);
2818 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
2822 json_object_array_add(json_paths
,
2827 if (add_prefix_to_json
) {
2828 json_object_object_add(json_prefix
,
2831 json_object_object_add(json_rd
,
2835 json_object_free(json_prefix
);
2836 json_object_free(json_paths
);
2845 json_object_object_add(json
, rd_str
, json_rd
);
2847 json_object_free(json_rd
);
2854 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2855 json_object_int_add(json
, "numPaths", path_cnt
);
2857 if (prefix_cnt
== 0) {
2858 vty_out(vty
, "No EVPN prefixes %sexist\n",
2859 type
? "(of requested type) " : "");
2861 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2862 prefix_cnt
, path_cnt
,
2863 type
? " (of requested type)" : "");
2868 /* Display specific ES */
2869 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2872 struct evpnes
*es
= NULL
;
2874 es
= bgp_evpn_lookup_es(bgp
, esi
);
2876 display_es(vty
, es
, json
);
2879 vty_out(vty
, "{}\n");
2881 vty_out(vty
, "ESI not found\n");
2887 /* Display all ESs */
2888 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2894 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2895 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2900 hash_iterate(bgp
->esihash
,
2901 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2906 * Display specified VNI (vty handler)
2908 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2912 struct bgpevpn
*vpn
;
2914 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2917 display_vni(vty
, vpn
, json
);
2919 struct bgp
*bgp_temp
;
2920 struct listnode
*node
= NULL
;
2922 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2923 if (bgp_temp
->l3vni
== vni
) {
2925 display_l3vni(vty
, bgp_temp
, json
);
2932 vty_out(vty
, "{}\n");
2934 vty_out(vty
, "VNI not found\n");
2941 * Display a VNI (upon user query).
2943 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2947 struct bgp
*bgp_temp
= NULL
;
2948 struct listnode
*node
;
2952 vty_out(vty
, "Flags: * - Kernel\n");
2953 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2954 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2957 /* print all L2 VNIS */
2960 hash_iterate(bgp
->vnihash
,
2961 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2964 /* print all L3 VNIs */
2965 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2966 show_l3vni_entry(vty
, bgp_temp
, json
);
2970 * evpn - enable advertisement of svi MAC-IP
2972 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2976 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2978 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2981 bgp
->evpn_info
->advertise_svi_macip
= set
;
2982 bgp_zebra_advertise_svi_macip(bgp
,
2983 bgp
->evpn_info
->advertise_svi_macip
, 0);
2985 if (set
&& vpn
->advertise_svi_macip
)
2987 else if (!set
&& !vpn
->advertise_svi_macip
)
2990 vpn
->advertise_svi_macip
= set
;
2991 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2997 * evpn - enable advertisement of default g/w
2999 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3002 if (bgp
->advertise_gw_macip
)
3005 bgp
->advertise_gw_macip
= 1;
3006 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3008 if (vpn
->advertise_gw_macip
)
3011 vpn
->advertise_gw_macip
= 1;
3012 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3019 * evpn - disable advertisement of default g/w
3021 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3022 struct bgpevpn
*vpn
)
3025 if (!bgp
->advertise_gw_macip
)
3028 bgp
->advertise_gw_macip
= 0;
3029 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3031 if (!vpn
->advertise_gw_macip
)
3034 vpn
->advertise_gw_macip
= 0;
3035 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3042 * evpn - enable advertisement of default g/w
3044 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3045 afi_t afi
, bool add
)
3047 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3050 /* bail if we are already advertising default route */
3051 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3055 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3056 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3057 else if (afi
== AFI_IP6
)
3058 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3059 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3061 /* bail out if we havent advertised the default route */
3062 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3065 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3066 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3067 else if (afi
== AFI_IP6
)
3068 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3069 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3072 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3076 * evpn - enable advertisement of default g/w
3078 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3079 struct bgpevpn
*vpn
)
3081 if (vpn
->advertise_subnet
)
3084 vpn
->advertise_subnet
= 1;
3085 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3089 * evpn - disable advertisement of default g/w
3091 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3093 if (!vpn
->advertise_subnet
)
3096 vpn
->advertise_subnet
= 0;
3097 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3101 * EVPN (VNI advertisement) enabled. Register with zebra.
3103 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3105 bgp
->advertise_all_vni
= 1;
3107 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3111 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3112 * cache, EVPN routes (delete and withdraw from peers).
3114 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3116 bgp
->advertise_all_vni
= 0;
3117 bgp_set_evpn(bgp_get_default());
3118 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3119 bgp_evpn_cleanup_on_disable(bgp
);
3123 * EVPN - use RFC8365 to auto-derive RT
3125 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3127 bgp
->advertise_autort_rfc8365
= 1;
3128 bgp_evpn_handle_autort_change(bgp
);
3132 * EVPN - don't use RFC8365 to auto-derive RT
3134 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3136 bgp
->advertise_autort_rfc8365
= 0;
3137 bgp_evpn_handle_autort_change(bgp
);
3140 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3142 char buf1
[RD_ADDRSTRLEN
];
3144 struct listnode
*node
, *nnode
;
3145 struct ecommunity
*ecom
;
3147 if (is_vni_configured(vpn
)) {
3148 vty_out(vty
, " vni %d\n", vpn
->vni
);
3149 if (is_rd_configured(vpn
))
3150 vty_out(vty
, " rd %s\n",
3151 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3153 if (is_import_rt_configured(vpn
)) {
3154 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3156 ecom_str
= ecommunity_ecom2str(
3157 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3158 vty_out(vty
, " route-target import %s\n",
3160 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3164 if (is_export_rt_configured(vpn
)) {
3165 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3167 ecom_str
= ecommunity_ecom2str(
3168 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3169 vty_out(vty
, " route-target export %s\n",
3171 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3175 if (vpn
->advertise_gw_macip
)
3176 vty_out(vty
, " advertise-default-gw\n");
3178 if (vpn
->advertise_svi_macip
)
3179 vty_out(vty
, " advertise-svi-ip\n");
3181 if (vpn
->advertise_subnet
)
3182 vty_out(vty
, " advertise-subnet\n");
3184 vty_out(vty
, " exit-vni\n");
3188 #ifndef VTYSH_EXTRACT_PL
3189 #include "bgpd/bgp_evpn_vty_clippy.c"
3192 DEFPY(bgp_evpn_flood_control
,
3193 bgp_evpn_flood_control_cmd
,
3194 "[no$no] flooding <disable$disable|head-end-replication$her>",
3196 "Specify handling for BUM packets\n"
3197 "Do not flood any BUM packets\n"
3198 "Flood BUM packets using head-end replication\n")
3200 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3201 enum vxlan_flood_control flood_ctrl
;
3207 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3209 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3213 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3216 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3217 bgp_evpn_flood_control_change(bgp
);
3222 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3223 bgp_evpn_advertise_default_gw_vni_cmd
,
3224 "advertise-default-gw",
3225 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3227 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3228 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3233 evpn_set_advertise_default_gw(bgp
, vpn
);
3238 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3239 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3240 "no advertise-default-gw",
3242 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3244 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3245 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3250 evpn_unset_advertise_default_gw(bgp
, vpn
);
3256 DEFUN (bgp_evpn_advertise_default_gw
,
3257 bgp_evpn_advertise_default_gw_cmd
,
3258 "advertise-default-gw",
3259 "Advertise All default g/w mac-ip routes in EVPN\n")
3261 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3266 if (!EVPN_ENABLED(bgp
)) {
3268 "This command is only supported under the EVPN VRF\n");
3272 evpn_set_advertise_default_gw(bgp
, NULL
);
3277 DEFUN (no_bgp_evpn_advertise_default_gw
,
3278 no_bgp_evpn_advertise_default_gw_cmd
,
3279 "no advertise-default-gw",
3281 "Withdraw All default g/w mac-ip routes from EVPN\n")
3283 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3288 if (!EVPN_ENABLED(bgp
)) {
3290 "This command is only supported under the EVPN VRF\n");
3294 evpn_unset_advertise_default_gw(bgp
, NULL
);
3299 DEFUN (bgp_evpn_advertise_all_vni
,
3300 bgp_evpn_advertise_all_vni_cmd
,
3301 "advertise-all-vni",
3302 "Advertise All local VNIs\n")
3304 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3305 struct bgp
*bgp_evpn
= NULL
;
3310 bgp_evpn
= bgp_get_evpn();
3311 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3312 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3314 return CMD_WARNING_CONFIG_FAILED
;
3317 evpn_set_advertise_all_vni(bgp
);
3321 DEFUN (no_bgp_evpn_advertise_all_vni
,
3322 no_bgp_evpn_advertise_all_vni_cmd
,
3323 "no advertise-all-vni",
3325 "Advertise All local VNIs\n")
3327 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3331 evpn_unset_advertise_all_vni(bgp
);
3335 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3336 bgp_evpn_advertise_autort_rfc8365_cmd
,
3337 "autort rfc8365-compatible",
3338 "Auto-derivation of RT\n"
3339 "Auto-derivation of RT using RFC8365\n")
3341 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3345 evpn_set_advertise_autort_rfc8365(bgp
);
3349 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3350 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3351 "no autort rfc8365-compatible",
3353 "Auto-derivation of RT\n"
3354 "Auto-derivation of RT using RFC8365\n")
3356 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3360 evpn_unset_advertise_autort_rfc8365(bgp
);
3364 DEFUN (bgp_evpn_default_originate
,
3365 bgp_evpn_default_originate_cmd
,
3366 "default-originate <ipv4 | ipv6>",
3367 "originate a default route\n"
3368 "ipv4 address family\n"
3369 "ipv6 address family\n")
3373 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3377 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3378 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3382 DEFUN (no_bgp_evpn_default_originate
,
3383 no_bgp_evpn_default_originate_cmd
,
3384 "no default-originate <ipv4 | ipv6>",
3386 "withdraw a default route\n"
3387 "ipv4 address family\n"
3388 "ipv6 address family\n")
3392 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3396 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3397 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3401 DEFPY (dup_addr_detection
,
3402 dup_addr_detection_cmd
,
3403 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3404 "Duplicate address detection\n"
3405 "Max allowed moves before address detected as duplicate\n"
3406 "Num of max allowed moves (2-1000) default 5\n"
3407 "Duplicate address detection time\n"
3408 "Time in seconds (2-1800) default 180\n")
3410 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3415 if (!EVPN_ENABLED(bgp_vrf
)) {
3417 "This command is only supported under the EVPN VRF\n");
3421 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3424 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3426 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3428 bgp_zebra_dup_addr_detection(bgp_vrf
);
3433 DEFPY (dup_addr_detection_auto_recovery
,
3434 dup_addr_detection_auto_recovery_cmd
,
3435 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3436 "Duplicate address detection\n"
3437 "Duplicate address detection freeze\n"
3438 "Duplicate address detection permanent freeze\n"
3439 "Duplicate address detection freeze time (30-3600)\n")
3441 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3442 uint32_t freeze_time
= freeze_time_val
;
3447 if (!EVPN_ENABLED(bgp_vrf
)) {
3449 "This command is only supported under the EVPN VRF\n");
3453 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3454 bgp_vrf
->evpn_info
->dad_freeze
= true;
3455 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3457 bgp_zebra_dup_addr_detection(bgp_vrf
);
3462 DEFPY (no_dup_addr_detection
,
3463 no_dup_addr_detection_cmd
,
3464 "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>]",
3466 "Duplicate address detection\n"
3467 "Max allowed moves before address detected as duplicate\n"
3468 "Num of max allowed moves (2-1000) default 5\n"
3469 "Duplicate address detection time\n"
3470 "Time in seconds (2-1800) default 180\n"
3471 "Duplicate address detection freeze\n"
3472 "Duplicate address detection permanent freeze\n"
3473 "Duplicate address detection freeze time (30-3600)\n")
3475 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3476 uint32_t max_moves
= (uint32_t)max_moves_val
;
3477 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3482 if (!EVPN_ENABLED(bgp_vrf
)) {
3484 "This command is only supported under the EVPN VRF\n");
3489 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3491 /* Reset all parameters to default. */
3492 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3493 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3494 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3495 bgp_vrf
->evpn_info
->dad_freeze
= false;
3496 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3499 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3501 "%% Value does not match with config\n");
3504 bgp_vrf
->evpn_info
->dad_max_moves
=
3505 EVPN_DAD_DEFAULT_MAX_MOVES
;
3509 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3511 "%% Value does not match with config\n");
3514 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3518 if (bgp_vrf
->evpn_info
->dad_freeze_time
3521 "%% Value does not match with config\n");
3524 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3525 bgp_vrf
->evpn_info
->dad_freeze
= false;
3528 if (permanent_val
) {
3529 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3531 "%% Value does not match with config\n");
3534 bgp_vrf
->evpn_info
->dad_freeze
= false;
3538 bgp_zebra_dup_addr_detection(bgp_vrf
);
3543 DEFPY(bgp_evpn_advertise_svi_ip
,
3544 bgp_evpn_advertise_svi_ip_cmd
,
3545 "[no$no] advertise-svi-ip",
3547 "Advertise svi mac-ip routes in EVPN\n")
3549 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3554 if (!EVPN_ENABLED(bgp
)) {
3556 "This command is only supported under EVPN VRF\n");
3561 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3563 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3568 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3569 bgp_evpn_advertise_svi_ip_vni_cmd
,
3570 "[no$no] advertise-svi-ip",
3572 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3574 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3575 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3581 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3583 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3588 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3589 bgp_evpn_advertise_vni_subnet_cmd
,
3591 "Advertise the subnet corresponding to VNI\n")
3593 struct bgp
*bgp_vrf
= NULL
;
3594 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3595 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3600 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3604 evpn_set_advertise_subnet(bgp
, vpn
);
3608 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3609 no_bgp_evpn_advertise_vni_subnet_cmd
,
3610 "no advertise-subnet",
3612 "Advertise All local VNIs\n")
3614 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3615 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3620 evpn_unset_advertise_subnet(bgp
, vpn
);
3624 DEFUN (bgp_evpn_advertise_type5
,
3625 bgp_evpn_advertise_type5_cmd
,
3626 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3627 "Advertise prefix routes\n"
3630 "route-map for filtering specific routes\n"
3631 "Name of the route map\n")
3633 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3640 int rmap_changed
= 0;
3642 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3643 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3644 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3646 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3648 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3649 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3652 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3656 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3658 "%%only ipv4 or ipv6 address families are supported");
3662 if (safi
!= SAFI_UNICAST
) {
3664 "%%only ipv4 unicast or ipv6 unicast are supported");
3668 if (afi
== AFI_IP
) {
3670 /* if we are already advertising ipv4 prefix as type-5
3673 if (!rmap_changed
&&
3674 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3675 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3677 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3678 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3681 /* if we are already advertising ipv6 prefix as type-5
3684 if (!rmap_changed
&&
3685 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3686 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3688 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3689 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3693 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3694 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3695 XFREE(MTYPE_ROUTE_MAP_NAME
,
3696 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3697 route_map_counter_decrement(
3698 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3699 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3700 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3704 /* set the route-map for advertise command */
3705 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3706 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3707 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3708 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3709 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3710 route_map_counter_increment(
3711 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3714 /* advertise type-5 routes */
3715 if (advertise_type5_routes(bgp_vrf
, afi
))
3716 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3720 DEFUN (no_bgp_evpn_advertise_type5
,
3721 no_bgp_evpn_advertise_type5_cmd
,
3722 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3724 "Advertise prefix routes\n"
3728 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3734 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3735 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3737 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3739 "%%only ipv4 or ipv6 address families are supported");
3743 if (safi
!= SAFI_UNICAST
) {
3745 "%%only ipv4 unicast or ipv6 unicast are supported");
3749 if (afi
== AFI_IP
) {
3751 /* if we are not advertising ipv4 prefix as type-5
3754 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3755 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3756 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3757 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3758 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3762 /* if we are not advertising ipv6 prefix as type-5
3765 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3766 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3767 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3768 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3769 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3773 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3774 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3775 XFREE(MTYPE_ROUTE_MAP_NAME
,
3776 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3777 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3778 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3784 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3785 bgp_evpn_advertise_pip_ip_mac_cmd
,
3786 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3788 "evpn system primary IP\n"
3791 MAC_STR MAC_STR MAC_STR
)
3793 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3794 struct bgp
*bgp_evpn
= NULL
;
3796 if (EVPN_ENABLED(bgp_vrf
)) {
3798 "This command is supported under L3VNI BGP EVPN VRF\n");
3799 return CMD_WARNING_CONFIG_FAILED
;
3801 bgp_evpn
= bgp_get_evpn();
3804 /* pip is already enabled */
3805 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3808 bgp_vrf
->evpn_info
->advertise_pip
= true;
3809 if (ip
.s_addr
!= INADDR_ANY
) {
3810 /* Already configured with same IP */
3811 if (IPV4_ADDR_SAME(&ip
,
3812 &bgp_vrf
->evpn_info
->pip_ip_static
))
3815 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3816 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3818 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3820 /* default instance router-id assignemt */
3822 bgp_vrf
->evpn_info
->pip_ip
=
3823 bgp_evpn
->router_id
;
3826 if (!is_zero_mac(&mac
->eth_addr
)) {
3827 /* Already configured with same MAC */
3828 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3829 &mac
->eth_addr
, ETH_ALEN
) == 0)
3832 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3833 &mac
->eth_addr
, ETH_ALEN
);
3834 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3835 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3838 /* Copy zebra sys mac */
3839 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3840 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3841 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3846 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3848 /* Disable PIP feature */
3849 bgp_vrf
->evpn_info
->advertise_pip
= false;
3850 /* copy anycast mac */
3851 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3852 &bgp_vrf
->rmac
, ETH_ALEN
);
3854 /* remove MAC-IP option retain PIP knob. */
3855 if ((ip
.s_addr
!= INADDR_ANY
) &&
3856 !IPV4_ADDR_SAME(&ip
,
3857 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3859 "%% BGP EVPN PIP IP does not match\n");
3860 return CMD_WARNING_CONFIG_FAILED
;
3863 if (!is_zero_mac(&mac
->eth_addr
) &&
3864 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3865 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3867 "%% BGP EVPN PIP MAC does not match\n");
3868 return CMD_WARNING_CONFIG_FAILED
;
3870 /* pip_rmac can carry vrr_rmac reset only if it matches
3871 * with static value.
3873 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3874 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3876 /* Copy zebra sys mac */
3878 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3879 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3880 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3883 /* copy anycast mac */
3884 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3885 &bgp_vrf
->rmac
, ETH_ALEN
);
3889 /* reset user configured sys MAC */
3890 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3891 /* reset user configured sys IP */
3892 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3893 /* Assign default PIP IP (bgp instance router-id) */
3895 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3897 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3900 if (is_evpn_enabled()) {
3901 struct listnode
*node
= NULL
;
3902 struct bgpevpn
*vpn
= NULL
;
3904 update_advertise_vrf_routes(bgp_vrf
);
3906 /* Update (svi) type-2 routes */
3907 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3908 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3910 update_routes_for_vni(bgp_evpn
, vpn
);
3918 * Display VNI information - for all or a specific VNI
3920 DEFUN(show_bgp_l2vpn_evpn_vni
,
3921 show_bgp_l2vpn_evpn_vni_cmd
,
3922 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3931 struct bgp
*bgp_evpn
;
3935 json_object
*json
= NULL
;
3936 uint32_t num_l2vnis
= 0;
3937 uint32_t num_l3vnis
= 0;
3938 uint32_t num_vnis
= 0;
3939 struct listnode
*node
= NULL
;
3940 struct bgp
*bgp_temp
= NULL
;
3942 uj
= use_json(argc
, argv
);
3944 bgp_evpn
= bgp_get_evpn();
3948 if (!argv_find(argv
, argc
, "evpn", &idx
))
3952 json
= json_object_new_object();
3954 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3956 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3958 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3959 if (bgp_temp
->l3vni
)
3962 num_vnis
= num_l2vnis
+ num_l3vnis
;
3964 json_object_string_add(json
, "advertiseGatewayMacip",
3965 bgp_evpn
->advertise_gw_macip
3968 json_object_string_add(json
, "advertiseSviMacIp",
3969 bgp_evpn
->evpn_info
->advertise_svi_macip
3970 ? "Enabled" : "Disabled");
3971 json_object_string_add(json
, "advertiseAllVnis",
3972 is_evpn_enabled() ? "Enabled"
3974 json_object_string_add(
3976 bgp_evpn
->vxlan_flood_ctrl
3977 == VXLAN_FLOOD_HEAD_END_REPL
3978 ? "Head-end replication"
3980 json_object_int_add(json
, "numVnis", num_vnis
);
3981 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3982 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3984 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3985 bgp_evpn
->advertise_gw_macip
? "Enabled"
3987 vty_out(vty
, "Advertise SVI Macip: %s\n",
3988 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3990 vty_out(vty
, "Advertise All VNI flag: %s\n",
3991 is_evpn_enabled() ? "Enabled" : "Disabled");
3992 vty_out(vty
, "BUM flooding: %s\n",
3993 bgp_evpn
->vxlan_flood_ctrl
3994 == VXLAN_FLOOD_HEAD_END_REPL
3995 ? "Head-end replication"
3997 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3998 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4000 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4004 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4007 /* Display specific VNI */
4008 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4009 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4013 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4014 json
, JSON_C_TO_STRING_PRETTY
));
4015 json_object_free(json
);
4022 DEFUN(show_bgp_l2vpn_evpn_es
,
4023 show_bgp_l2vpn_evpn_es_cmd
,
4024 "show bgp l2vpn evpn es [ESI] [json]",
4029 "ethernet-Segment\n"
4030 "Ethernet-Segment Identifier\n"
4036 json_object
*json
= NULL
;
4037 struct bgp
*bgp
= NULL
;
4039 memset(&esi
, 0, sizeof(esi
));
4040 uj
= use_json(argc
, argv
);
4042 bgp
= bgp_get_evpn();
4046 if (!argv_find(argv
, argc
, "evpn", &idx
))
4049 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
4050 (!uj
&& argc
== (idx
+ 1) + 1)) {
4053 evpn_show_all_es(vty
, bgp
, json
);
4056 /* show a specific ES */
4058 /* get the ESI - ESI-ID is at argv[5] */
4059 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
4060 vty_out(vty
, "%% Malformed ESI\n");
4063 evpn_show_es(vty
, bgp
, &esi
, json
);
4067 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4068 json
, JSON_C_TO_STRING_PRETTY
));
4069 json_object_free(json
);
4076 * Display EVPN neighbor summary.
4078 DEFUN(show_bgp_l2vpn_evpn_summary
,
4079 show_bgp_l2vpn_evpn_summary_cmd
,
4080 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
4087 "Summary of BGP neighbor status\n"
4088 "Show only sessions not in Established state\n"
4092 bool uj
= use_json(argc
, argv
);
4094 bool show_failed
= false;
4096 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4097 vrf
= argv
[++idx_vrf
]->arg
;
4098 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
4100 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
4105 * Display global EVPN routing table.
4107 DEFUN(show_bgp_l2vpn_evpn_route
,
4108 show_bgp_l2vpn_evpn_route_cmd
,
4109 "show bgp l2vpn evpn route [detail] [type <macip|2|multicast|3|es|4|prefix|5>] [json]",
4114 "EVPN route information\n"
4115 "Display Detailed Information\n"
4116 "Specify Route type\n"
4117 "MAC-IP (Type-2) route\n"
4118 "MAC-IP (Type-2) route\n"
4119 "Multicast (Type-3) route\n"
4120 "Multicast (Type-3) route\n"
4121 "Ethernet Segment (Type-4) route\n"
4122 "Ethernet Segment (Type-4) route\n"
4123 "Prefix (Type-5) route\n"
4124 "Prefix (Type-5) route\n"
4132 json_object
*json
= NULL
;
4134 uj
= use_json(argc
, argv
);
4136 bgp
= bgp_get_evpn();
4141 json
= json_object_new_object();
4144 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4145 /* Specific type is requested */
4146 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4147 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4148 type
= BGP_EVPN_MAC_IP_ROUTE
;
4149 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4150 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4151 type
= BGP_EVPN_IMET_ROUTE
;
4152 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
4153 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4154 type
= BGP_EVPN_ES_ROUTE
;
4155 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4156 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4157 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4162 if (argv_find(argv
, argc
, "detail", &detail
))
4165 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4168 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4169 json
, JSON_C_TO_STRING_PRETTY
));
4170 json_object_free(json
);
4176 * Display global EVPN routing table for specific RD.
4178 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4179 show_bgp_l2vpn_evpn_route_rd_cmd
,
4180 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
4185 "EVPN route information\n"
4186 "Route Distinguisher\n"
4187 "ASN:XX or A.B.C.D:XX\n"
4188 "Specify Route type\n"
4189 "MAC-IP (Type-2) route\n"
4190 "Multicast (Type-3) route\n"
4191 "Ethernet Segment route\n"
4197 struct prefix_rd prd
;
4202 json_object
*json
= NULL
;
4204 bgp
= bgp_get_evpn();
4208 /* check if we need json output */
4209 uj
= use_json(argc
, argv
);
4211 json
= json_object_new_object();
4214 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4215 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4218 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4224 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4225 /* Specific type is requested */
4226 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4227 type
= BGP_EVPN_MAC_IP_ROUTE
;
4228 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4229 type
= BGP_EVPN_IMET_ROUTE
;
4230 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
4231 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4236 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4239 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4240 json
, JSON_C_TO_STRING_PRETTY
));
4241 json_object_free(json
);
4248 * Display global EVPN routing table for specific RD and MACIP.
4250 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4251 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4252 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4257 "EVPN route information\n"
4258 "Route Distinguisher\n"
4259 "ASN:XX or A.B.C.D:XX\n"
4261 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4263 "IP address (IPv4 or IPv6)\n"
4268 struct prefix_rd prd
;
4275 json_object
*json
= NULL
;
4277 memset(&mac
, 0, sizeof(struct ethaddr
));
4278 memset(&ip
, 0, sizeof(struct ipaddr
));
4280 bgp
= bgp_get_evpn();
4284 /* check if we need json output */
4285 uj
= use_json(argc
, argv
);
4287 json
= json_object_new_object();
4290 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4291 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4293 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4299 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4300 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4301 vty_out(vty
, "%% Malformed MAC address\n");
4306 /* get the ip if specified */
4307 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4308 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4309 vty_out(vty
, "%% Malformed IP address\n");
4314 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4317 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4318 json
, JSON_C_TO_STRING_PRETTY
));
4319 json_object_free(json
);
4325 /* Display per ESI routing table */
4326 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4327 show_bgp_l2vpn_evpn_route_esi_cmd
,
4328 "show bgp l2vpn evpn route esi ESI [json]",
4333 "EVPN route information\n"
4334 "Ethernet Segment Identifier\n"
4340 struct bgp
*bgp
= NULL
;
4341 json_object
*json
= NULL
;
4343 memset(&esi
, 0, sizeof(esi
));
4344 bgp
= bgp_get_evpn();
4348 uj
= use_json(argc
, argv
);
4350 json
= json_object_new_object();
4352 /* get the ESI - ESI-ID is at argv[6] */
4353 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4354 vty_out(vty
, "%% Malformed ESI\n");
4358 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4361 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4362 json
, JSON_C_TO_STRING_PRETTY
));
4363 json_object_free(json
);
4371 * Display per-VNI EVPN routing table.
4373 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4374 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4379 "EVPN route information\n"
4380 "VXLAN Network Identifier\n"
4382 "Specify Route type\n"
4383 "MAC-IP (Type-2) route\n"
4384 "Multicast (Type-3) route\n"
4386 "Remote VTEP IP address\n"
4391 struct in_addr vtep_ip
;
4395 json_object
*json
= NULL
;
4397 bgp
= bgp_get_evpn();
4401 /* check if we need json output */
4402 uj
= use_json(argc
, argv
);
4404 json
= json_object_new_object();
4406 if (!argv_find(argv
, argc
, "evpn", &idx
))
4411 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4413 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4414 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4415 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4416 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4417 type
= BGP_EVPN_MAC_IP_ROUTE
;
4418 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4419 type
= BGP_EVPN_IMET_ROUTE
;
4422 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4423 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4424 vty_out(vty
, "%% Malformed VTEP IP address\n");
4431 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4434 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4435 json
, JSON_C_TO_STRING_PRETTY
));
4436 json_object_free(json
);
4443 * Display per-VNI EVPN routing table for specific MACIP.
4445 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4446 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4447 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4452 "EVPN route information\n"
4453 "VXLAN Network Identifier\n"
4456 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4458 "IP address (IPv4 or IPv6)\n"
4467 json_object
*json
= NULL
;
4469 bgp
= bgp_get_evpn();
4473 /* check if we need json output */
4474 uj
= use_json(argc
, argv
);
4476 json
= json_object_new_object();
4478 if (!argv_find(argv
, argc
, "evpn", &idx
))
4482 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4485 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4486 vty_out(vty
, "%% Malformed MAC address\n");
4491 memset(&ip
, 0, sizeof(ip
));
4492 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4494 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4495 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4496 vty_out(vty
, "%% Malformed IP address\n");
4501 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4504 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4505 json
, JSON_C_TO_STRING_PRETTY
));
4506 json_object_free(json
);
4513 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4515 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4516 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4517 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4522 "EVPN route information\n"
4523 "VXLAN Network Identifier\n"
4525 "Multicast (Type-3) route\n"
4526 "Originating Router IP address\n"
4532 struct in_addr orig_ip
;
4535 json_object
*json
= NULL
;
4537 bgp
= bgp_get_evpn();
4541 /* check if we need json output */
4542 uj
= use_json(argc
, argv
);
4544 json
= json_object_new_object();
4546 if (!argv_find(argv
, argc
, "evpn", &idx
))
4550 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4553 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4555 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4559 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4562 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4563 json
, JSON_C_TO_STRING_PRETTY
));
4564 json_object_free(json
);
4571 * Display per-VNI EVPN routing table - for all VNIs.
4573 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4574 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4575 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4580 "EVPN route information\n"
4581 "VXLAN Network Identifier\n"
4583 "Print Detailed Output\n"
4585 "Remote VTEP IP address\n"
4589 struct in_addr vtep_ip
;
4592 json_object
*json
= NULL
;
4593 /* Detail Adjust. Adjust indexes according to detail option */
4596 bgp
= bgp_get_evpn();
4600 /* check if we need json output */
4601 uj
= use_json(argc
, argv
);
4603 json
= json_object_new_object();
4605 if (!argv_find(argv
, argc
, "evpn", &idx
))
4608 if (argv_find(argv
, argc
, "detail", &da
))
4611 /* vtep-ip position depends on detail option */
4613 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4615 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4616 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4617 vty_out(vty
, "%% Malformed VTEP IP address\n");
4622 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4625 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4626 json
, JSON_C_TO_STRING_PRETTY
));
4627 json_object_free(json
);
4634 * Display EVPN import route-target hash table
4636 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4637 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4638 "show bgp l2vpn evpn vrf-import-rt [json]",
4643 "Show vrf import route target\n"
4647 struct bgp
*bgp_evpn
= NULL
;
4648 json_object
*json
= NULL
;
4650 bgp_evpn
= bgp_get_evpn();
4654 uj
= use_json(argc
, argv
);
4656 json
= json_object_new_object();
4658 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4661 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4662 json
, JSON_C_TO_STRING_PRETTY
));
4663 json_object_free(json
);
4670 * Display EVPN import route-target hash table
4672 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4673 show_bgp_l2vpn_evpn_import_rt_cmd
,
4674 "show bgp l2vpn evpn import-rt [json]",
4679 "Show import route target\n"
4684 json_object
*json
= NULL
;
4686 bgp
= bgp_get_evpn();
4690 uj
= use_json(argc
, argv
);
4692 json
= json_object_new_object();
4694 evpn_show_import_rts(vty
, bgp
, json
);
4697 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4698 json
, JSON_C_TO_STRING_PRETTY
));
4699 json_object_free(json
);
4705 DEFUN(test_adv_evpn_type4_route
,
4706 test_adv_evpn_type4_route_cmd
,
4708 "Advertise EVPN ES route\n"
4709 "Ethernet-segment\n"
4710 "Ethernet-Segment Identifier\n")
4715 struct ipaddr vtep_ip
;
4717 bgp
= bgp_get_evpn();
4719 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4723 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4724 vty_out(vty
, "%%Malformed ESI\n");
4728 vtep_ip
.ipa_type
= IPADDR_V4
;
4729 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4731 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4733 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4739 DEFUN(test_withdraw_evpn_type4_route
,
4740 test_withdraw_evpn_type4_route_cmd
,
4742 "Advertise EVPN ES route\n"
4743 "Ethernet-segment\n"
4744 "Ethernet-Segment Identifier\n")
4749 struct ipaddr vtep_ip
;
4751 bgp
= bgp_get_evpn();
4753 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4757 if (!bgp
->peer_self
) {
4758 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4762 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4763 vty_out(vty
, "%%Malformed ESI\n");
4767 vtep_ip
.ipa_type
= IPADDR_V4
;
4768 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4769 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4771 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4777 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4778 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4782 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4783 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4784 "Summary of BGP neighbor status\n" JSON_STR
)
4786 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4787 "show bgp evpn route [detail] [type <macip|multicast>]",
4788 SHOW_STR BGP_STR EVPN_HELP_STR
4789 "EVPN route information\n"
4790 "Display Detailed Information\n"
4791 "Specify Route type\n"
4792 "MAC-IP (Type-2) route\n"
4793 "Multicast (Type-3) route\n")
4796 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4797 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4798 SHOW_STR BGP_STR EVPN_HELP_STR
4799 "EVPN route information\n"
4800 "Route Distinguisher\n"
4801 "ASN:XX or A.B.C.D:XX\n"
4802 "Specify Route type\n"
4803 "MAC-IP (Type-2) route\n"
4804 "Multicast (Type-3) route\n")
4807 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4808 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4809 SHOW_STR BGP_STR EVPN_HELP_STR
4810 "EVPN route information\n"
4811 "Route Distinguisher\n"
4812 "ASN:XX or A.B.C.D:XX\n"
4814 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4816 "IP address (IPv4 or IPv6)\n")
4819 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4820 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4821 SHOW_STR BGP_STR EVPN_HELP_STR
4822 "EVPN route information\n"
4823 "VXLAN Network Identifier\n"
4825 "Specify Route type\n"
4826 "MAC-IP (Type-2) route\n"
4827 "Multicast (Type-3) route\n"
4829 "Remote VTEP IP address\n")
4831 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4832 show_bgp_evpn_route_vni_macip_cmd
,
4833 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4834 SHOW_STR BGP_STR EVPN_HELP_STR
4835 "EVPN route information\n"
4836 "VXLAN Network Identifier\n"
4839 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4841 "IP address (IPv4 or IPv6)\n")
4843 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4844 show_bgp_evpn_route_vni_multicast_cmd
,
4845 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4846 SHOW_STR BGP_STR EVPN_HELP_STR
4847 "EVPN route information\n"
4848 "VXLAN Network Identifier\n"
4850 "Multicast (Type-3) route\n"
4851 "Originating Router IP address\n")
4853 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4854 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4855 SHOW_STR BGP_STR EVPN_HELP_STR
4856 "EVPN route information\n"
4857 "VXLAN Network Identifier\n"
4859 "Print Detailed Output\n"
4861 "Remote VTEP IP address\n")
4863 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4864 "show bgp evpn import-rt",
4865 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4867 DEFUN_NOSH (bgp_evpn_vni
,
4869 "vni " CMD_VNI_RANGE
,
4870 "VXLAN Network Identifier\n"
4874 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4875 struct bgpevpn
*vpn
;
4880 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4882 /* Create VNI, or mark as configured. */
4883 vpn
= evpn_create_update_vni(bgp
, vni
);
4885 vty_out(vty
, "%% Failed to create VNI \n");
4889 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4893 DEFUN (no_bgp_evpn_vni
,
4894 no_bgp_evpn_vni_cmd
,
4895 "no vni " CMD_VNI_RANGE
,
4897 "VXLAN Network Identifier\n"
4901 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4902 struct bgpevpn
*vpn
;
4907 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4909 /* Check if we should disallow. */
4910 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4912 vty_out(vty
, "%% Specified VNI does not exist\n");
4915 if (!is_vni_configured(vpn
)) {
4916 vty_out(vty
, "%% Specified VNI is not configured\n");
4920 evpn_delete_vni(bgp
, vpn
);
4924 DEFUN_NOSH (exit_vni
,
4927 "Exit from VNI mode\n")
4929 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4930 vty
->node
= BGP_EVPN_NODE
;
4934 DEFUN (bgp_evpn_vrf_rd
,
4935 bgp_evpn_vrf_rd_cmd
,
4936 "rd ASN:NN_OR_IP-ADDRESS:NN",
4937 "Route Distinguisher\n"
4938 "ASN:XX or A.B.C.D:XX\n")
4941 struct prefix_rd prd
;
4942 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4947 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4949 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4953 /* If same as existing value, there is nothing more to do. */
4954 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4957 /* Configure or update the RD. */
4958 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4962 DEFUN (no_bgp_evpn_vrf_rd
,
4963 no_bgp_evpn_vrf_rd_cmd
,
4964 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4966 "Route Distinguisher\n"
4967 "ASN:XX or A.B.C.D:XX\n")
4970 struct prefix_rd prd
;
4971 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4976 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4978 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4982 /* Check if we should disallow. */
4983 if (!is_vrf_rd_configured(bgp_vrf
)) {
4984 vty_out(vty
, "%% RD is not configured for this VRF\n");
4988 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4990 "%% RD specified does not match configuration for this VRF\n");
4994 evpn_unconfigure_vrf_rd(bgp_vrf
);
4998 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4999 no_bgp_evpn_vrf_rd_without_val_cmd
,
5002 "Route Distinguisher\n")
5004 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5009 /* Check if we should disallow. */
5010 if (!is_vrf_rd_configured(bgp_vrf
)) {
5011 vty_out(vty
, "%% RD is not configured for this VRF\n");
5015 evpn_unconfigure_vrf_rd(bgp_vrf
);
5019 DEFUN (bgp_evpn_vni_rd
,
5020 bgp_evpn_vni_rd_cmd
,
5021 "rd ASN:NN_OR_IP-ADDRESS:NN",
5022 "Route Distinguisher\n"
5023 "ASN:XX or A.B.C.D:XX\n")
5025 struct prefix_rd prd
;
5026 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5027 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5033 if (!EVPN_ENABLED(bgp
)) {
5035 "This command is only supported under EVPN VRF\n");
5039 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5041 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5045 /* If same as existing value, there is nothing more to do. */
5046 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5049 /* Configure or update the RD. */
5050 evpn_configure_rd(bgp
, vpn
, &prd
);
5054 DEFUN (no_bgp_evpn_vni_rd
,
5055 no_bgp_evpn_vni_rd_cmd
,
5056 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5058 "Route Distinguisher\n"
5059 "ASN:XX or A.B.C.D:XX\n")
5061 struct prefix_rd prd
;
5062 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5063 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5069 if (!EVPN_ENABLED(bgp
)) {
5071 "This command is only supported under EVPN VRF\n");
5075 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5077 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5081 /* Check if we should disallow. */
5082 if (!is_rd_configured(vpn
)) {
5083 vty_out(vty
, "%% RD is not configured for this VNI\n");
5087 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5089 "%% RD specified does not match configuration for this VNI\n");
5093 evpn_unconfigure_rd(bgp
, vpn
);
5097 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5098 no_bgp_evpn_vni_rd_without_val_cmd
,
5101 "Route Distinguisher\n")
5103 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5104 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5109 if (!EVPN_ENABLED(bgp
)) {
5111 "This command is only supported under EVPN VRF\n");
5115 /* Check if we should disallow. */
5116 if (!is_rd_configured(vpn
)) {
5117 vty_out(vty
, "%% RD is not configured for this VNI\n");
5121 evpn_unconfigure_rd(bgp
, vpn
);
5126 * Loop over all extended-communities in the route-target list rtl and
5127 * return 1 if we find ecomtarget
5129 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5130 struct ecommunity
*ecomtarget
)
5132 struct listnode
*node
, *nnode
;
5133 struct ecommunity
*ecom
;
5135 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5136 if (ecommunity_match(ecom
, ecomtarget
))
5143 /* display L3VNI related info for a VRF instance */
5144 DEFUN (show_bgp_vrf_l3vni_info
,
5145 show_bgp_vrf_l3vni_info_cmd
,
5146 "show bgp vrf VRFNAME vni [json]",
5154 char buf
[ETHER_ADDR_STRLEN
];
5155 char buf1
[INET6_ADDRSTRLEN
];
5157 const char *name
= NULL
;
5158 struct bgp
*bgp
= NULL
;
5159 struct listnode
*node
= NULL
;
5160 struct bgpevpn
*vpn
= NULL
;
5161 struct ecommunity
*ecom
= NULL
;
5162 json_object
*json
= NULL
;
5163 json_object
*json_vnis
= NULL
;
5164 json_object
*json_export_rts
= NULL
;
5165 json_object
*json_import_rts
= NULL
;
5166 bool uj
= use_json(argc
, argv
);
5169 json
= json_object_new_object();
5170 json_vnis
= json_object_new_array();
5171 json_export_rts
= json_object_new_array();
5172 json_import_rts
= json_object_new_array();
5175 name
= argv
[idx_vrf
]->arg
;
5176 bgp
= bgp_lookup_by_name(name
);
5179 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5181 json_object_string_add(json
, "warning",
5182 "BGP instance not found");
5183 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5184 json_object_free(json
);
5190 vty_out(vty
, "BGP VRF: %s\n", name
);
5191 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
5192 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5193 vty_out(vty
, " Rmac: %s\n",
5194 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5195 vty_out(vty
, " VNI Filter: %s\n",
5196 CHECK_FLAG(bgp
->vrf_flags
,
5197 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5198 ? "prefix-routes-only"
5200 vty_out(vty
, " L2-VNI List:\n");
5202 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5203 vty_out(vty
, "%u ", vpn
->vni
);
5205 vty_out(vty
, " Export-RTs:\n");
5207 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5208 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5210 vty_out(vty
, " Import-RTs:\n");
5212 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5213 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5215 vty_out(vty
, " RD: %s\n",
5216 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5218 json_object_string_add(json
, "vrf", name
);
5219 json_object_string_add(json
, "local-ip",
5220 inet_ntoa(bgp
->originator_ip
));
5221 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5222 json_object_string_add(
5224 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5225 json_object_string_add(
5227 CHECK_FLAG(bgp
->vrf_flags
,
5228 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5229 ? "prefix-routes-only"
5231 /* list of l2vnis */
5232 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5233 json_object_array_add(json_vnis
,
5234 json_object_new_int(vpn
->vni
));
5235 json_object_object_add(json
, "l2vnis", json_vnis
);
5238 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5239 json_object_array_add(
5241 json_object_new_string(ecommunity_str(ecom
)));
5242 json_object_object_add(json
, "export-rts", json_export_rts
);
5245 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5246 json_object_array_add(
5248 json_object_new_string(ecommunity_str(ecom
)));
5249 json_object_object_add(json
, "import-rts", json_import_rts
);
5250 json_object_string_add(
5252 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5256 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5257 json
, JSON_C_TO_STRING_PRETTY
));
5258 json_object_free(json
);
5263 /* import/export rt for l3vni-vrf */
5264 DEFUN (bgp_evpn_vrf_rt
,
5265 bgp_evpn_vrf_rt_cmd
,
5266 "route-target <both|import|export> RT",
5268 "import and export\n"
5271 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5274 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5275 struct ecommunity
*ecomadd
= NULL
;
5280 if (!strcmp(argv
[1]->arg
, "import"))
5281 rt_type
= RT_TYPE_IMPORT
;
5282 else if (!strcmp(argv
[1]->arg
, "export"))
5283 rt_type
= RT_TYPE_EXPORT
;
5284 else if (!strcmp(argv
[1]->arg
, "both"))
5285 rt_type
= RT_TYPE_BOTH
;
5287 vty_out(vty
, "%% Invalid Route Target type\n");
5291 /* Add/update the import route-target */
5292 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5293 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5294 ECOMMUNITY_ROUTE_TARGET
, 0);
5296 vty_out(vty
, "%% Malformed Route Target list\n");
5299 ecommunity_str(ecomadd
);
5301 /* Do nothing if we already have this import route-target */
5302 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5303 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5306 /* Add/update the export route-target */
5307 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5308 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5309 ECOMMUNITY_ROUTE_TARGET
, 0);
5311 vty_out(vty
, "%% Malformed Route Target list\n");
5314 ecommunity_str(ecomadd
);
5316 /* Do nothing if we already have this export route-target */
5317 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5318 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5324 DEFUN (no_bgp_evpn_vrf_rt
,
5325 no_bgp_evpn_vrf_rt_cmd
,
5326 "no route-target <both|import|export> RT",
5329 "import and export\n"
5332 "ASN:XX or A.B.C.D:XX\n")
5334 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5335 int rt_type
, found_ecomdel
;
5336 struct ecommunity
*ecomdel
= NULL
;
5341 if (!strcmp(argv
[2]->arg
, "import"))
5342 rt_type
= RT_TYPE_IMPORT
;
5343 else if (!strcmp(argv
[2]->arg
, "export"))
5344 rt_type
= RT_TYPE_EXPORT
;
5345 else if (!strcmp(argv
[2]->arg
, "both"))
5346 rt_type
= RT_TYPE_BOTH
;
5348 vty_out(vty
, "%% Invalid Route Target type\n");
5352 if (rt_type
== RT_TYPE_IMPORT
) {
5353 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5355 "%% Import RT is not configured for this VRF\n");
5358 } else if (rt_type
== RT_TYPE_EXPORT
) {
5359 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5361 "%% Export RT is not configured for this VRF\n");
5364 } else if (rt_type
== RT_TYPE_BOTH
) {
5365 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5366 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5368 "%% Import/Export RT is not configured for this VRF\n");
5373 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5375 vty_out(vty
, "%% Malformed Route Target list\n");
5378 ecommunity_str(ecomdel
);
5380 if (rt_type
== RT_TYPE_IMPORT
) {
5381 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5384 "%% RT specified does not match configuration for this VRF\n");
5387 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5388 } else if (rt_type
== RT_TYPE_EXPORT
) {
5389 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5392 "%% RT specified does not match configuration for this VRF\n");
5395 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5396 } else if (rt_type
== RT_TYPE_BOTH
) {
5399 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5401 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5405 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5407 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5411 if (!found_ecomdel
) {
5413 "%% RT specified does not match configuration for this VRF\n");
5421 DEFUN (bgp_evpn_vni_rt
,
5422 bgp_evpn_vni_rt_cmd
,
5423 "route-target <both|import|export> RT",
5425 "import and export\n"
5428 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5430 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5431 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5433 struct ecommunity
*ecomadd
= NULL
;
5438 if (!EVPN_ENABLED(bgp
)) {
5440 "This command is only supported under EVPN VRF\n");
5444 if (!strcmp(argv
[1]->text
, "import"))
5445 rt_type
= RT_TYPE_IMPORT
;
5446 else if (!strcmp(argv
[1]->text
, "export"))
5447 rt_type
= RT_TYPE_EXPORT
;
5448 else if (!strcmp(argv
[1]->text
, "both"))
5449 rt_type
= RT_TYPE_BOTH
;
5451 vty_out(vty
, "%% Invalid Route Target type\n");
5455 /* Add/update the import route-target */
5456 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5457 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5458 ECOMMUNITY_ROUTE_TARGET
, 0);
5460 vty_out(vty
, "%% Malformed Route Target list\n");
5463 ecommunity_str(ecomadd
);
5465 /* Do nothing if we already have this import route-target */
5466 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5467 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5470 /* Add/update the export route-target */
5471 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5472 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5473 ECOMMUNITY_ROUTE_TARGET
, 0);
5475 vty_out(vty
, "%% Malformed Route Target list\n");
5478 ecommunity_str(ecomadd
);
5480 /* Do nothing if we already have this export route-target */
5481 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5482 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5488 DEFUN (no_bgp_evpn_vni_rt
,
5489 no_bgp_evpn_vni_rt_cmd
,
5490 "no route-target <both|import|export> RT",
5493 "import and export\n"
5496 "ASN:XX or A.B.C.D:XX\n")
5498 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5499 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5500 int rt_type
, found_ecomdel
;
5501 struct ecommunity
*ecomdel
= NULL
;
5506 if (!EVPN_ENABLED(bgp
)) {
5508 "This command is only supported under EVPN VRF\n");
5512 if (!strcmp(argv
[2]->text
, "import"))
5513 rt_type
= RT_TYPE_IMPORT
;
5514 else if (!strcmp(argv
[2]->text
, "export"))
5515 rt_type
= RT_TYPE_EXPORT
;
5516 else if (!strcmp(argv
[2]->text
, "both"))
5517 rt_type
= RT_TYPE_BOTH
;
5519 vty_out(vty
, "%% Invalid Route Target type\n");
5523 /* The user did "no route-target import", check to see if there are any
5524 * import route-targets configured. */
5525 if (rt_type
== RT_TYPE_IMPORT
) {
5526 if (!is_import_rt_configured(vpn
)) {
5528 "%% Import RT is not configured for this VNI\n");
5531 } else if (rt_type
== RT_TYPE_EXPORT
) {
5532 if (!is_export_rt_configured(vpn
)) {
5534 "%% Export RT is not configured for this VNI\n");
5537 } else if (rt_type
== RT_TYPE_BOTH
) {
5538 if (!is_import_rt_configured(vpn
)
5539 && !is_export_rt_configured(vpn
)) {
5541 "%% Import/Export RT is not configured for this VNI\n");
5546 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5548 vty_out(vty
, "%% Malformed Route Target list\n");
5551 ecommunity_str(ecomdel
);
5553 if (rt_type
== RT_TYPE_IMPORT
) {
5554 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5556 "%% RT specified does not match configuration for this VNI\n");
5559 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5560 } else if (rt_type
== RT_TYPE_EXPORT
) {
5561 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5563 "%% RT specified does not match configuration for this VNI\n");
5566 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5567 } else if (rt_type
== RT_TYPE_BOTH
) {
5570 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5571 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5575 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5576 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5580 if (!found_ecomdel
) {
5582 "%% RT specified does not match configuration for this VNI\n");
5590 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5591 no_bgp_evpn_vni_rt_without_val_cmd
,
5592 "no route-target <import|export>",
5598 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5599 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5605 if (!EVPN_ENABLED(bgp
)) {
5607 "This command is only supported under EVPN VRF\n");
5611 if (!strcmp(argv
[2]->text
, "import")) {
5612 rt_type
= RT_TYPE_IMPORT
;
5613 } else if (!strcmp(argv
[2]->text
, "export")) {
5614 rt_type
= RT_TYPE_EXPORT
;
5616 vty_out(vty
, "%% Invalid Route Target type\n");
5620 /* Check if we should disallow. */
5621 if (rt_type
== RT_TYPE_IMPORT
) {
5622 if (!is_import_rt_configured(vpn
)) {
5624 "%% Import RT is not configured for this VNI\n");
5628 if (!is_export_rt_configured(vpn
)) {
5630 "%% Export RT is not configured for this VNI\n");
5635 /* Unconfigure the RT. */
5636 if (rt_type
== RT_TYPE_IMPORT
)
5637 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5639 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5643 static int vni_cmp(const void **a
, const void **b
)
5645 const struct bgpevpn
*first
= *a
;
5646 const struct bgpevpn
*secnd
= *b
;
5648 return secnd
->vni
- first
->vni
;
5652 * Output EVPN configuration information.
5654 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5657 char buf1
[RD_ADDRSTRLEN
];
5658 char buf2
[INET6_ADDRSTRLEN
];
5661 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5662 struct listnode
*ln
;
5663 struct bgpevpn
*data
;
5665 list_sort(vnilist
, vni_cmp
);
5666 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5667 write_vni_config(vty
, data
);
5669 list_delete(&vnilist
);
5672 if (bgp
->advertise_all_vni
)
5673 vty_out(vty
, " advertise-all-vni\n");
5675 if (bgp
->advertise_autort_rfc8365
)
5676 vty_out(vty
, " autort rfc8365-compatible\n");
5678 if (bgp
->advertise_gw_macip
)
5679 vty_out(vty
, " advertise-default-gw\n");
5681 if (bgp
->evpn_info
->advertise_svi_macip
)
5682 vty_out(vty
, " advertise-svi-ip\n");
5684 if (!bgp
->evpn_info
->dup_addr_detect
)
5685 vty_out(vty
, " no dup-addr-detection\n");
5687 if (bgp
->evpn_info
->dad_max_moves
!=
5688 EVPN_DAD_DEFAULT_MAX_MOVES
||
5689 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5690 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5691 bgp
->evpn_info
->dad_max_moves
,
5692 bgp
->evpn_info
->dad_time
);
5694 if (bgp
->evpn_info
->dad_freeze
) {
5695 if (bgp
->evpn_info
->dad_freeze_time
)
5697 " dup-addr-detection freeze %u\n",
5698 bgp
->evpn_info
->dad_freeze_time
);
5701 " dup-addr-detection freeze permanent\n");
5704 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5705 vty_out(vty
, " flooding disable\n");
5707 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5708 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5709 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5710 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5711 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5713 vty_out(vty
, " advertise ipv4 unicast\n");
5716 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5717 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5718 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5719 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5720 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5722 vty_out(vty
, " advertise ipv6 unicast\n");
5725 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5726 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5727 vty_out(vty
, " default-originate ipv4\n");
5729 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5730 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5731 vty_out(vty
, " default-originate ipv6\n");
5733 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5734 if (!bgp
->evpn_info
->advertise_pip
)
5735 vty_out(vty
, " no advertise-pip\n");
5736 if (bgp
->evpn_info
->advertise_pip
) {
5737 if (bgp
->evpn_info
->pip_ip_static
.s_addr
5739 vty_out(vty
, " advertise-pip ip %s",
5741 &bgp
->evpn_info
->pip_ip_static
,
5742 buf2
, INET_ADDRSTRLEN
));
5744 bgp
->evpn_info
->pip_rmac_static
))) {
5745 char buf
[ETHER_ADDR_STRLEN
];
5747 vty_out(vty
, " mac %s",
5757 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5758 vty_out(vty
, " rd %s\n",
5759 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5761 /* import route-target */
5762 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5764 struct listnode
*node
, *nnode
;
5765 struct ecommunity
*ecom
;
5767 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5769 ecom_str
= ecommunity_ecom2str(
5770 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5771 vty_out(vty
, " route-target import %s\n", ecom_str
);
5772 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5776 /* export route-target */
5777 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5779 struct listnode
*node
, *nnode
;
5780 struct ecommunity
*ecom
;
5782 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5784 ecom_str
= ecommunity_ecom2str(
5785 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5786 vty_out(vty
, " route-target export %s\n", ecom_str
);
5787 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5792 void bgp_ethernetvpn_init(void)
5794 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5795 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5796 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5797 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5798 install_element(VIEW_NODE
,
5799 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5800 install_element(VIEW_NODE
,
5801 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5804 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5807 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5808 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5809 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5810 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5811 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5812 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5813 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5814 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5815 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5816 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5817 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5818 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5819 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5820 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5821 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5822 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5823 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5824 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5825 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5826 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5827 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5830 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5831 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5833 /* "show bgp l2vpn evpn" commands. */
5834 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5835 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5836 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5837 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5838 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5839 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5840 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5841 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5842 install_element(VIEW_NODE
,
5843 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5844 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5845 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5846 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5847 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5849 /* "show bgp evpn" commands. */
5850 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5851 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5852 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5853 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5854 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5855 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5856 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5857 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5858 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5859 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5860 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5861 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5863 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5864 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5865 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5866 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5867 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5868 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5869 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5870 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5871 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5872 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5873 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5874 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5875 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5876 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5877 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5878 install_element(BGP_EVPN_VNI_NODE
,
5879 &bgp_evpn_advertise_default_gw_vni_cmd
);
5880 install_element(BGP_EVPN_VNI_NODE
,
5881 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5882 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5883 install_element(BGP_EVPN_VNI_NODE
,
5884 &no_bgp_evpn_advertise_vni_subnet_cmd
);