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
, RT_ADDRSTRLEN
, "%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
, RT_ADDRSTRLEN
, "%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
, RT_ADDRSTRLEN
, "%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
, RT_ADDRSTRLEN
, "%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
, RT_ADDRSTRLEN
, "%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
, RT_ADDRSTRLEN
, "%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
, VNI_STR_LEN
, "%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 */
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 sprintf(rt_buf
, "%s, ...", ecom_str
);
926 sprintf(rt_buf
, "%s", ecom_str
);
927 vty_out(vty
, " %-25s", rt_buf
);
930 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
932 /* If there are multiple import RTs we break here and show only
939 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
941 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
942 ecom_str
= ecommunity_ecom2str(ecom
,
943 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
946 json_object_array_add(json_export_rtl
,
947 json_object_new_string(ecom_str
));
949 if (listcount(bgp
->vrf_export_rtl
) > 1)
950 sprintf(rt_buf
, "%s, ...", ecom_str
);
952 sprintf(rt_buf
, "%s", ecom_str
);
953 vty_out(vty
, " %-25s", rt_buf
);
956 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
958 /* If there are multiple export RTs we break here and show only
965 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
968 char vni_str
[VNI_STR_LEN
];
970 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
971 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
972 json_object_object_add(json
, vni_str
, json_vni
);
978 static void show_es_entry(struct hash_bucket
*bucket
, void *args
[])
980 char buf
[ESI_STR_LEN
];
981 char buf1
[RD_ADDRSTRLEN
];
982 char buf2
[INET6_ADDRSTRLEN
];
983 struct in_addr
*vtep
= NULL
;
984 struct vty
*vty
= args
[0];
985 json_object
*json
= args
[1];
986 json_object
*json_vteps
= NULL
;
987 struct listnode
*node
= NULL
;
988 struct evpnes
*es
= (struct evpnes
*)bucket
->data
;
991 json_vteps
= json_object_new_array();
992 json_object_string_add(json
, "esi",
993 esi_to_str(&es
->esi
, buf
, sizeof(buf
)));
994 json_object_string_add(json
, "type",
995 is_es_local(es
) ? "Local" : "Remote");
996 json_object_string_add(json
, "rd",
997 prefix_rd2str(&es
->prd
, buf1
,
999 json_object_string_add(
1000 json
, "originatorIp",
1001 ipaddr2str(&es
->originator_ip
, buf2
, sizeof(buf2
)));
1002 if (es
->vtep_list
) {
1003 for (ALL_LIST_ELEMENTS_RO(es
->vtep_list
, node
, vtep
))
1004 json_object_array_add(json_vteps
,
1005 json_object_new_string(
1008 json_object_object_add(json
, "vteps", json_vteps
);
1010 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6d\n",
1011 esi_to_str(&es
->esi
, buf
, sizeof(buf
)),
1012 is_es_local(es
) ? "Local" : "Remote",
1013 prefix_rd2str(&es
->prd
, buf1
, sizeof(buf1
)),
1014 ipaddr2str(&es
->originator_ip
, buf2
,
1016 es
->vtep_list
? listcount(es
->vtep_list
) : 0);
1020 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1024 json_object
*json_vni
= NULL
;
1025 json_object
*json_import_rtl
= NULL
;
1026 json_object
*json_export_rtl
= NULL
;
1027 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1029 char buf2
[RD_ADDRSTRLEN
];
1032 struct listnode
*node
, *nnode
;
1033 struct ecommunity
*ecom
;
1034 struct bgp
*bgp_evpn
;
1039 bgp_evpn
= bgp_get_evpn();
1042 json_vni
= json_object_new_object();
1043 json_import_rtl
= json_object_new_array();
1044 json_export_rtl
= json_object_new_array();
1048 if (is_vni_live(vpn
))
1052 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1053 json_object_string_add(json_vni
, "type", "L2");
1054 json_object_string_add(json_vni
, "inKernel",
1055 is_vni_live(vpn
) ? "True" : "False");
1056 json_object_string_add(
1058 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1059 json_object_string_add(json_vni
, "originatorIp",
1060 inet_ntoa(vpn
->originator_ip
));
1061 json_object_string_add(json_vni
, "mcastGroup",
1062 inet_ntoa(vpn
->mcast_grp
));
1063 /* per vni knob is enabled -- Enabled
1064 * Global knob is enabled -- Active
1065 * default -- Disabled
1067 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1068 && bgp_evpn
->advertise_gw_macip
)
1069 json_object_string_add(
1070 json_vni
, "advertiseGatewayMacip", "Active");
1071 else if (vpn
->advertise_gw_macip
)
1072 json_object_string_add(
1073 json_vni
, "advertiseGatewayMacip", "Enabled");
1075 json_object_string_add(
1076 json_vni
, "advertiseGatewayMacip", "Disabled");
1077 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1078 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1079 json_object_string_add(json_vni
, "advertiseSviMacIp",
1081 else if (vpn
->advertise_svi_macip
)
1082 json_object_string_add(json_vni
, "advertiseSviMacIp",
1085 json_object_string_add(json_vni
, "advertiseSviMacIp",
1088 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1089 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1092 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1093 ecom_str
= ecommunity_ecom2str(ecom
,
1094 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1097 json_object_array_add(json_import_rtl
,
1098 json_object_new_string(ecom_str
));
1100 if (listcount(vpn
->import_rtl
) > 1)
1101 sprintf(rt_buf
, "%s, ...", ecom_str
);
1103 sprintf(rt_buf
, "%s", ecom_str
);
1104 vty_out(vty
, " %-25s", rt_buf
);
1107 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1109 /* If there are multiple import RTs we break here and show only
1116 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1118 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1119 ecom_str
= ecommunity_ecom2str(ecom
,
1120 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1123 json_object_array_add(json_export_rtl
,
1124 json_object_new_string(ecom_str
));
1126 if (listcount(vpn
->export_rtl
) > 1)
1127 sprintf(rt_buf
, "%s, ...", ecom_str
);
1129 sprintf(rt_buf
, "%s", ecom_str
);
1130 vty_out(vty
, " %-25s", rt_buf
);
1133 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1135 /* If there are multiple export RTs we break here and show only
1142 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1145 char vni_str
[VNI_STR_LEN
];
1147 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1148 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
1149 json_object_object_add(json
, vni_str
, json_vni
);
1155 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1156 enum bgp_show_type type
, void *output_arg
,
1157 int option
, bool use_json
)
1159 afi_t afi
= AFI_L2VPN
;
1161 struct bgp_table
*table
;
1162 struct bgp_node
*rn
;
1163 struct bgp_node
*rm
;
1164 struct bgp_path_info
*pi
;
1167 char rd_str
[RD_ADDRSTRLEN
];
1171 unsigned long output_count
= 0;
1172 unsigned long total_count
= 0;
1173 json_object
*json
= NULL
;
1174 json_object
*json_array
= NULL
;
1175 json_object
*json_prefix_info
= NULL
;
1177 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1179 bgp
= bgp_get_evpn();
1182 vty_out(vty
, "No BGP process is configured\n");
1184 vty_out(vty
, "{}\n");
1189 json
= json_object_new_object();
1191 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
1192 rn
= bgp_route_next(rn
)) {
1194 json_object
*json_nroute
= NULL
;
1195 const struct prefix
*p
= bgp_node_get_prefix(rn
);
1197 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1200 table
= bgp_node_get_bgp_table_info(rn
);
1205 tbl_ver
= table
->version
;
1207 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1208 pi
= bgp_node_get_bgp_path_info(rm
);
1213 for (; pi
; pi
= pi
->next
) {
1215 if (type
== bgp_show_type_neighbor
) {
1216 struct peer
*peer
= output_arg
;
1218 if (peer_cmp(peer
, pi
->peer
) != 0)
1221 if (type
== bgp_show_type_lcommunity_exact
) {
1222 struct lcommunity
*lcom
= output_arg
;
1224 if (!pi
->attr
->lcommunity
||
1226 pi
->attr
->lcommunity
, lcom
))
1229 if (type
== bgp_show_type_lcommunity
) {
1230 struct lcommunity
*lcom
= output_arg
;
1232 if (!pi
->attr
->lcommunity
||
1234 pi
->attr
->lcommunity
, lcom
))
1237 if (type
== bgp_show_type_community
) {
1238 struct community
*com
= output_arg
;
1240 if (!pi
->attr
->community
||
1242 pi
->attr
->community
, com
))
1245 if (type
== bgp_show_type_community_exact
) {
1246 struct community
*com
= output_arg
;
1248 if (!pi
->attr
->community
||
1250 pi
->attr
->community
, com
))
1255 json_object_int_add(
1256 json
, "bgpTableVersion",
1258 json_object_string_add(
1263 json_object_int_add(
1266 bgp
->default_local_pref
);
1267 json_object_int_add(
1271 if (option
== SHOW_DISPLAY_TAGS
)
1276 == SHOW_DISPLAY_OVERLAY
)
1280 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1288 json_object_new_object();
1289 bgp_evpn_show_route_rd_header(vty
, rn
,
1290 json_nroute
, rd_str
,
1294 if (use_json
&& !json_array
)
1295 json_array
= json_object_new_array();
1297 if (option
== SHOW_DISPLAY_TAGS
)
1299 vty
, bgp_node_get_prefix(rm
),
1300 pi
, no_display
, SAFI_EVPN
,
1302 else if (option
== SHOW_DISPLAY_OVERLAY
)
1303 route_vty_out_overlay(
1304 vty
, bgp_node_get_prefix(rm
),
1305 pi
, no_display
, json_array
);
1308 bgp_node_get_prefix(rm
),
1309 pi
, no_display
, SAFI_EVPN
,
1317 if (use_json
&& json_array
) {
1318 const struct prefix
*p
=
1319 bgp_node_get_prefix(rm
);
1321 json_prefix_info
= json_object_new_object();
1323 json_object_string_add(
1324 json_prefix_info
, "prefix",
1326 (struct prefix_evpn
*)p
, buf
,
1329 json_object_int_add(json_prefix_info
,
1330 "prefixLen", p
->prefixlen
);
1332 json_object_object_add(json_prefix_info
,
1333 "paths", json_array
);
1334 json_object_object_add(json_nroute
, buf
,
1340 if (use_json
&& json_nroute
)
1341 json_object_object_add(json
, rd_str
, json_nroute
);
1345 json_object_int_add(json
, "numPrefix", output_count
);
1346 json_object_int_add(json
, "totalPrefix", total_count
);
1347 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1348 json
, JSON_C_TO_STRING_PRETTY
));
1349 json_object_free(json
);
1351 if (output_count
== 0)
1352 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1356 "\nDisplayed %ld out of %ld total prefixes\n",
1357 output_count
, total_count
);
1362 DEFUN(show_ip_bgp_l2vpn_evpn
,
1363 show_ip_bgp_l2vpn_evpn_cmd
,
1364 "show [ip] bgp l2vpn evpn [json]",
1365 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1367 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1368 use_json(argc
, argv
));
1371 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1372 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1373 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1379 "Display information for a route distinguisher\n"
1380 "VPN Route Distinguisher\n" JSON_STR
)
1382 int idx_ext_community
= 0;
1384 struct prefix_rd prd
;
1386 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1388 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1390 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1393 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1394 use_json(argc
, argv
));
1397 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1398 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1399 "show [ip] bgp l2vpn evpn all tags",
1405 "Display information about all EVPN NLRIs\n"
1406 "Display BGP tags for prefixes\n")
1408 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1412 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1413 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1414 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1420 "Display information for a route distinguisher\n"
1421 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1423 int idx_ext_community
= 0;
1425 struct prefix_rd prd
;
1427 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1429 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1431 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1434 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1438 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1439 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1440 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1446 "Detailed information on TCP and BGP neighbor connections\n"
1447 "IPv4 Neighbor to display information about\n"
1448 "IPv6 Neighbor to display information about\n"
1449 "Neighbor on BGP configured interface\n"
1450 "Display routes learned from neighbor\n" JSON_STR
)
1454 char *peerstr
= NULL
;
1455 bool uj
= use_json(argc
, argv
);
1456 afi_t afi
= AFI_L2VPN
;
1457 safi_t safi
= SAFI_EVPN
;
1458 struct bgp
*bgp
= NULL
;
1460 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1463 vty_out(vty
, "No index\n");
1467 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1468 argv_find(argv
, argc
, "neighbors", &idx
);
1469 peerstr
= argv
[++idx
]->arg
;
1471 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1474 json_object
*json_no
= NULL
;
1475 json_no
= json_object_new_object();
1476 json_object_string_add(json_no
, "warning",
1477 "Malformed address");
1478 vty_out(vty
, "%s\n",
1479 json_object_to_json_string(json_no
));
1480 json_object_free(json_no
);
1482 vty_out(vty
, "Malformed address: %s\n",
1486 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1488 json_object
*json_no
= NULL
;
1489 json_no
= json_object_new_object();
1490 json_object_string_add(
1492 "No such neighbor or address family");
1493 vty_out(vty
, "%s\n",
1494 json_object_to_json_string(json_no
));
1495 json_object_free(json_no
);
1497 vty_out(vty
, "%% No such neighbor or address family\n");
1501 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1505 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1506 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1507 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1513 "Display information for a route distinguisher\n"
1514 "VPN Route Distinguisher\n"
1515 "Detailed information on TCP and BGP neighbor connections\n"
1516 "IPv4 Neighbor to display information about\n"
1517 "IPv6 Neighbor to display information about\n"
1518 "Neighbor on BGP configured interface\n"
1519 "Display routes learned from neighbor\n" JSON_STR
)
1521 int idx_ext_community
= 0;
1525 char *peerstr
= NULL
;
1526 struct prefix_rd prd
;
1527 bool uj
= use_json(argc
, argv
);
1528 afi_t afi
= AFI_L2VPN
;
1529 safi_t safi
= SAFI_EVPN
;
1530 struct bgp
*bgp
= NULL
;
1532 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1535 vty_out(vty
, "No index\n");
1539 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1540 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1543 json_object
*json_no
= NULL
;
1544 json_no
= json_object_new_object();
1545 json_object_string_add(json_no
, "warning",
1546 "Malformed Route Distinguisher");
1547 vty_out(vty
, "%s\n",
1548 json_object_to_json_string(json_no
));
1549 json_object_free(json_no
);
1551 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1555 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1556 argv_find(argv
, argc
, "neighbors", &idx
);
1557 peerstr
= argv
[++idx
]->arg
;
1559 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1562 json_object
*json_no
= NULL
;
1563 json_no
= json_object_new_object();
1564 json_object_string_add(json_no
, "warning",
1565 "Malformed address");
1566 vty_out(vty
, "%s\n",
1567 json_object_to_json_string(json_no
));
1568 json_object_free(json_no
);
1570 vty_out(vty
, "Malformed address: %s\n",
1574 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1576 json_object
*json_no
= NULL
;
1577 json_no
= json_object_new_object();
1578 json_object_string_add(
1580 "No such neighbor or address family");
1581 vty_out(vty
, "%s\n",
1582 json_object_to_json_string(json_no
));
1583 json_object_free(json_no
);
1585 vty_out(vty
, "%% No such neighbor or address family\n");
1589 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1593 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1594 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1595 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1601 "Detailed information on TCP and BGP neighbor connections\n"
1602 "IPv4 Neighbor to display information about\n"
1603 "IPv6 Neighbor to display information about\n"
1604 "Neighbor on BGP configured interface\n"
1605 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1609 bool uj
= use_json(argc
, argv
);
1610 struct bgp
*bgp
= NULL
;
1611 afi_t afi
= AFI_L2VPN
;
1612 safi_t safi
= SAFI_EVPN
;
1613 char *peerstr
= NULL
;
1618 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1621 vty_out(vty
, "No index\n");
1625 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1626 argv_find(argv
, argc
, "neighbors", &idx
);
1627 peerstr
= argv
[++idx
]->arg
;
1629 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1632 json_object
*json_no
= NULL
;
1633 json_no
= json_object_new_object();
1634 json_object_string_add(json_no
, "warning",
1635 "Malformed address");
1636 vty_out(vty
, "%s\n",
1637 json_object_to_json_string(json_no
));
1638 json_object_free(json_no
);
1640 vty_out(vty
, "Malformed address: %s\n",
1644 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1646 json_object
*json_no
= NULL
;
1647 json_no
= json_object_new_object();
1648 json_object_string_add(
1650 "No such neighbor or address family");
1651 vty_out(vty
, "%s\n",
1652 json_object_to_json_string(json_no
));
1653 json_object_free(json_no
);
1655 vty_out(vty
, "%% No such neighbor or address family\n");
1659 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1662 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1663 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1664 "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]",
1670 "Display information for a route distinguisher\n"
1671 "VPN Route Distinguisher\n"
1672 "Detailed information on TCP and BGP neighbor connections\n"
1673 "IPv4 Neighbor to display information about\n"
1674 "IPv6 Neighbor to display information about\n"
1675 "Neighbor on BGP configured interface\n"
1676 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1678 int idx_ext_community
= 0;
1682 struct prefix_rd prd
;
1683 struct bgp
*bgp
= NULL
;
1684 bool uj
= use_json(argc
, argv
);
1685 char *peerstr
= NULL
;
1686 afi_t afi
= AFI_L2VPN
;
1687 safi_t safi
= SAFI_EVPN
;
1695 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1698 vty_out(vty
, "No index\n");
1702 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1704 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1705 argv_find(argv
, argc
, "neighbors", &idx
);
1706 peerstr
= argv
[++idx
]->arg
;
1708 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1711 json_object
*json_no
= NULL
;
1712 json_no
= json_object_new_object();
1713 json_object_string_add(json_no
, "warning",
1714 "Malformed address");
1715 vty_out(vty
, "%s\n",
1716 json_object_to_json_string(json_no
));
1717 json_object_free(json_no
);
1719 vty_out(vty
, "Malformed address: %s\n",
1723 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1725 json_object
*json_no
= NULL
;
1726 json_no
= json_object_new_object();
1727 json_object_string_add(
1729 "No such neighbor or address family");
1730 vty_out(vty
, "%s\n",
1731 json_object_to_json_string(json_no
));
1732 json_object_free(json_no
);
1734 vty_out(vty
, "%% No such neighbor or address family\n");
1738 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1741 json_object
*json_no
= NULL
;
1742 json_no
= json_object_new_object();
1743 json_object_string_add(json_no
, "warning",
1744 "Malformed Route Distinguisher");
1745 vty_out(vty
, "%s\n",
1746 json_object_to_json_string(json_no
));
1747 json_object_free(json_no
);
1749 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1753 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1756 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1757 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1758 "show [ip] bgp l2vpn evpn all overlay [json]",
1764 "Display information about all EVPN NLRIs\n"
1765 "Display BGP Overlay Information for prefixes\n"
1768 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1769 SHOW_DISPLAY_OVERLAY
,
1770 use_json(argc
, argv
));
1773 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1774 show_ip_bgp_evpn_rd_overlay_cmd
,
1775 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1781 "Display information for a route distinguisher\n"
1782 "VPN Route Distinguisher\n"
1783 "Display BGP Overlay Information for prefixes\n")
1785 int idx_ext_community
= 0;
1787 struct prefix_rd prd
;
1789 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1791 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1793 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1796 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1797 SHOW_DISPLAY_OVERLAY
,
1798 use_json(argc
, argv
));
1801 DEFUN(show_bgp_l2vpn_evpn_com
,
1802 show_bgp_l2vpn_evpn_com_cmd
,
1803 "show bgp l2vpn evpn \
1804 <community AA:NN|large-community AA:BB:CC> \
1805 [exact-match] [json]",
1810 "Display routes matching the community\n"
1811 "Community number where AA and NN are (0-65535)\n"
1812 "Display routes matching the large-community\n"
1813 "List of large-community numbers\n"
1814 "Exact match of the communities\n"
1819 const char *clist_number_or_name
;
1820 int show_type
= bgp_show_type_normal
;
1821 struct community
*com
;
1822 struct lcommunity
*lcom
;
1824 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1825 clist_number_or_name
= argv
[++idx
]->arg
;
1826 show_type
= bgp_show_type_lcommunity
;
1828 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1829 show_type
= bgp_show_type_lcommunity_exact
;
1831 lcom
= lcommunity_str2com(clist_number_or_name
);
1833 vty_out(vty
, "%% Large-community malformed\n");
1837 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1838 SHOW_DISPLAY_STANDARD
,
1839 use_json(argc
, argv
));
1841 lcommunity_free(&lcom
);
1842 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1843 clist_number_or_name
= argv
[++idx
]->arg
;
1844 show_type
= bgp_show_type_community
;
1846 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1847 show_type
= bgp_show_type_community_exact
;
1849 com
= community_str2com(clist_number_or_name
);
1852 vty_out(vty
, "%% Community malformed: %s\n",
1853 clist_number_or_name
);
1857 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1858 SHOW_DISPLAY_STANDARD
,
1859 use_json(argc
, argv
));
1860 community_free(&com
);
1866 /* For testing purpose, static route of EVPN RT-5. */
1867 DEFUN(evpnrt5_network
,
1868 evpnrt5_network_cmd
,
1869 "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]",
1870 "Specify a network to announce via BGP\n"
1873 "Specify Route Distinguisher\n"
1874 "VPN Route Distinguisher\n"
1876 "Ethernet Tag Value\n"
1879 "Ethernet Segment Identifier\n"
1880 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1882 "Gateway IP ( A.B.C.D )\n"
1883 "Gateway IPv6 ( X:X::X:X )\n"
1884 "Router Mac Ext Comm\n"
1885 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1886 "Route-map to modify the attributes\n"
1887 "Name of the route map\n")
1889 int idx_ipv4_prefixlen
= 1;
1890 int idx_route_distinguisher
= 3;
1895 int idx_routermac
= 13;
1897 return bgp_static_set_safi(
1898 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1899 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1900 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1901 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1902 argv
[idx_routermac
]->arg
);
1905 /* For testing purpose, static route of EVPN RT-5. */
1906 DEFUN(no_evpnrt5_network
,
1907 no_evpnrt5_network_cmd
,
1908 "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>",
1910 "Specify a network to announce via BGP\n"
1913 "Specify Route Distinguisher\n"
1914 "VPN Route Distinguisher\n"
1916 "Ethernet Tag Value\n"
1919 "Ethernet Segment Identifier\n"
1920 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1921 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1923 int idx_ipv4_prefixlen
= 2;
1924 int idx_ext_community
= 4;
1929 return bgp_static_unset_safi(
1930 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1931 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1932 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1933 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1936 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1938 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1941 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1943 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1947 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1948 * check that this is a change.
1950 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1951 struct ecommunity
*ecomadd
)
1953 /* If the VNI is "live", we need to uninstall routes using the current
1954 * import RT(s) first before we update the import RT, and subsequently
1957 if (is_vni_live(vpn
))
1958 bgp_evpn_uninstall_routes(bgp
, vpn
);
1960 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1961 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1963 /* If the auto route-target is in use we must remove it */
1964 evpn_import_rt_delete_auto(bgp
, vpn
);
1966 /* Add new RT and rebuild the RT to VNI mapping */
1967 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1969 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1970 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1972 /* Install routes that match new import RT */
1973 if (is_vni_live(vpn
))
1974 bgp_evpn_install_routes(bgp
, vpn
);
1978 * Unconfigure Import RT(s) for a VNI (vty handler).
1980 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1981 struct ecommunity
*ecomdel
)
1983 struct listnode
*node
, *nnode
, *node_to_del
;
1984 struct ecommunity
*ecom
;
1986 /* Along the lines of "configure" except we have to reset to the
1989 if (is_vni_live(vpn
))
1990 bgp_evpn_uninstall_routes(bgp
, vpn
);
1992 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1993 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1995 /* Delete all import RTs */
1996 if (ecomdel
== NULL
) {
1997 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1998 ecommunity_free(&ecom
);
1999 list_delete_node(vpn
->import_rtl
, node
);
2003 /* Delete a specific import RT */
2007 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2008 if (ecommunity_match(ecom
, ecomdel
)) {
2009 ecommunity_free(&ecom
);
2016 list_delete_node(vpn
->import_rtl
, node_to_del
);
2019 assert(vpn
->import_rtl
);
2020 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2021 if (list_isempty(vpn
->import_rtl
)) {
2022 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2023 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2025 /* Rebuild the RT to VNI mapping */
2027 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2029 /* Install routes that match new import RT */
2030 if (is_vni_live(vpn
))
2031 bgp_evpn_install_routes(bgp
, vpn
);
2035 * Configure the Export RT for a VNI (vty handler). Caller expected to
2036 * check that this is a change. Note that only a single export RT is
2037 * allowed for a VNI and any change to configuration is implemented as
2038 * a "replace" (similar to other configuration).
2040 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2041 struct ecommunity
*ecomadd
)
2043 /* If the auto route-target is in use we must remove it */
2044 evpn_export_rt_delete_auto(bgp
, vpn
);
2046 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2047 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2049 if (is_vni_live(vpn
))
2050 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2054 * Unconfigure the Export RT for a VNI (vty handler)
2056 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2057 struct ecommunity
*ecomdel
)
2059 struct listnode
*node
, *nnode
, *node_to_del
;
2060 struct ecommunity
*ecom
;
2062 /* Delete all export RTs */
2063 if (ecomdel
== NULL
) {
2064 /* Reset to default and process all routes. */
2065 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2066 ecommunity_free(&ecom
);
2067 list_delete_node(vpn
->export_rtl
, node
);
2071 /* Delete a specific export RT */
2075 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2076 if (ecommunity_match(ecom
, ecomdel
)) {
2077 ecommunity_free(&ecom
);
2084 list_delete_node(vpn
->export_rtl
, node_to_del
);
2087 assert(vpn
->export_rtl
);
2088 if (list_isempty(vpn
->export_rtl
)) {
2089 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2090 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2093 if (is_vni_live(vpn
))
2094 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2098 * Configure RD for VRF
2100 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2102 /* If we have already advertise type-5 routes with a diffrent RD, we
2103 * have to delete and withdraw them firs
2105 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2108 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2109 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2111 /* We have a new RD for VRF.
2112 * Advertise all type-5 routes again with the new RD
2114 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2118 * Unconfigure RD for VRF
2120 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2122 /* If we have already advertise type-5 routes with a diffrent RD, we
2123 * have to delete and withdraw them firs
2125 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2127 /* fall back to default RD */
2128 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2129 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2131 /* We have a new RD for VRF.
2132 * Advertise all type-5 routes again with the new RD
2134 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2138 * Configure RD for a VNI (vty handler)
2140 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2141 struct prefix_rd
*rd
)
2143 /* If the VNI is "live", we need to delete and withdraw this VNI's
2144 * local routes with the prior RD first. Then, after updating RD,
2145 * need to re-advertise.
2147 if (is_vni_live(vpn
))
2148 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2151 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2152 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2154 if (is_vni_live(vpn
))
2155 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2159 * Unconfigure RD for a VNI (vty handler)
2161 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2163 /* If the VNI is "live", we need to delete and withdraw this VNI's
2164 * local routes with the prior RD first. Then, after resetting RD
2165 * to automatic value, need to re-advertise.
2167 if (is_vni_live(vpn
))
2168 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2170 /* reset RD to default */
2171 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2173 if (is_vni_live(vpn
))
2174 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2178 * Create VNI, if not already present (VTY handler). Mark as configured.
2180 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2182 struct bgpevpn
*vpn
;
2183 struct in_addr mcast_grp
= {INADDR_ANY
};
2188 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2190 /* Check if this L2VNI is already configured as L3VNI */
2191 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2194 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2199 /* tenant vrf will be updated when we get local_vni_add from
2202 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2206 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2212 /* Mark as configured. */
2213 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2218 * Delete VNI. If VNI does not exist in the system (i.e., just
2219 * configuration), all that is needed is to free it. Otherwise,
2220 * any parameters configured for the VNI need to be reset (with
2221 * appropriate action) and the VNI marked as unconfigured; the
2222 * VNI will continue to exist, purely as a "learnt" entity.
2224 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2226 assert(bgp
->vnihash
);
2228 if (!is_vni_live(vpn
)) {
2229 bgp_evpn_free(bgp
, vpn
);
2233 /* We need to take the unconfigure action for each parameter of this VNI
2234 * that is configured. Some optimization is possible, but not worth the
2235 * additional code for an operation that should be pretty rare.
2237 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2239 /* First, deal with the export side - RD and export RT changes. */
2240 if (is_rd_configured(vpn
))
2241 evpn_unconfigure_rd(bgp
, vpn
);
2242 if (is_export_rt_configured(vpn
))
2243 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2245 /* Next, deal with the import side. */
2246 if (is_import_rt_configured(vpn
))
2247 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2251 * Display import RT mapping to VRFs (vty handler)
2252 * bgp_evpn: evpn bgp instance
2254 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2262 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2263 (void (*)(struct hash_bucket
*,
2264 void *))show_vrf_import_rt_entry
,
2269 * Display import RT mapping to VNIs (vty handler)
2271 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2280 bgp
->import_rt_hash
,
2281 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2286 * Display EVPN routes for all VNIs - vty handler.
2288 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2289 struct in_addr vtep_ip
, json_object
*json
,
2293 struct vni_walk_ctx wctx
;
2295 num_vnis
= hashcount(bgp
->vnihash
);
2298 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2301 wctx
.vtep_ip
= vtep_ip
;
2303 wctx
.detail
= detail
;
2304 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2305 void *))show_vni_routes_hash
,
2310 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2312 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2313 vni_t vni
, struct in_addr orig_ip
,
2316 struct bgpevpn
*vpn
;
2317 struct prefix_evpn p
;
2318 struct bgp_node
*rn
;
2319 struct bgp_path_info
*pi
;
2320 uint32_t path_cnt
= 0;
2323 json_object
*json_paths
= NULL
;
2329 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2331 vty_out(vty
, "VNI not found\n");
2335 /* See if route exists. */
2336 build_evpn_type3_prefix(&p
, orig_ip
);
2337 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2338 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2340 vty_out(vty
, "%% Network not in table\n");
2345 json_paths
= json_object_new_array();
2347 /* Prefix and num paths displayed once per prefix. */
2348 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2350 /* Display each path for this prefix. */
2351 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2352 json_object
*json_path
= NULL
;
2355 json_path
= json_object_new_array();
2357 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2361 json_object_array_add(json_paths
, json_path
);
2368 json_object_object_add(json
, "paths", json_paths
);
2370 json_object_int_add(json
, "numPaths", path_cnt
);
2372 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2378 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2379 * By definition, only matching type-2 route will be displayed.
2381 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2382 vni_t vni
, struct ethaddr
*mac
,
2383 struct ipaddr
*ip
, json_object
*json
)
2385 struct bgpevpn
*vpn
;
2386 struct prefix_evpn p
;
2387 struct bgp_node
*rn
;
2388 struct bgp_path_info
*pi
;
2389 uint32_t path_cnt
= 0;
2392 json_object
*json_paths
= NULL
;
2398 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2401 vty_out(vty
, "VNI not found\n");
2405 /* See if route exists. Look for both non-sticky and sticky. */
2406 build_evpn_type2_prefix(&p
, mac
, ip
);
2407 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2408 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2410 vty_out(vty
, "%% Network not in table\n");
2415 json_paths
= json_object_new_array();
2417 /* Prefix and num paths displayed once per prefix. */
2418 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
2420 /* Display each path for this prefix. */
2421 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2422 json_object
*json_path
= NULL
;
2425 json_path
= json_object_new_array();
2427 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2431 json_object_array_add(json_paths
, json_path
);
2438 json_object_object_add(json
, "paths", json_paths
);
2440 json_object_int_add(json
, "numPaths", path_cnt
);
2442 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2447 /* Disaplay EVPN routes for a ESI - VTY handler */
2448 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2449 esi_t
*esi
, json_object
*json
)
2451 struct evpnes
*es
= NULL
;
2454 es
= bgp_evpn_lookup_es(bgp
, esi
);
2457 vty_out(vty
, "ESI not found\n");
2461 show_esi_routes(bgp
, es
, vty
, json
);
2465 * Display EVPN routes for a VNI - vty handler.
2466 * If 'type' is non-zero, only routes matching that type are shown.
2467 * If the vtep_ip is non zero, only routes behind that vtep are shown
2469 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2470 int type
, struct in_addr vtep_ip
,
2473 struct bgpevpn
*vpn
;
2476 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2479 vty_out(vty
, "VNI not found\n");
2483 /* Walk this VNI's route table and display appropriate routes. */
2484 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2488 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2489 * IP (vty handler). By definition, only matching type-2 route will be
2492 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2493 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2494 struct ipaddr
*ip
, json_object
*json
)
2496 struct prefix_evpn p
;
2497 struct bgp_node
*rn
;
2498 struct bgp_path_info
*pi
;
2501 uint32_t path_cnt
= 0;
2502 json_object
*json_paths
= NULL
;
2503 char prefix_str
[BUFSIZ
];
2508 /* See if route exists. Look for both non-sticky and sticky. */
2509 build_evpn_type2_prefix(&p
, mac
, ip
);
2510 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2511 (struct prefix
*)&p
, prd
);
2512 if (!rn
|| !bgp_node_has_bgp_path_info_data(rn
)) {
2514 vty_out(vty
, "%% Network not in table\n");
2518 bgp_evpn_route2str(&p
, prefix_str
, sizeof(prefix_str
));
2520 /* Prefix and num paths displayed once per prefix. */
2521 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2524 json_paths
= json_object_new_array();
2526 /* Display each path for this prefix. */
2527 for (pi
= bgp_node_get_bgp_path_info(rn
); pi
; pi
= pi
->next
) {
2528 json_object
*json_path
= NULL
;
2531 json_path
= json_object_new_array();
2533 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2537 json_object_array_add(json_paths
, json_path
);
2542 if (json
&& path_cnt
) {
2544 json_object_object_add(json
, prefix_str
, json_paths
);
2545 json_object_int_add(json
, "numPaths", path_cnt
);
2547 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2553 * Display BGP EVPN routing table -- for specific RD (vty handler)
2554 * If 'type' is non-zero, only routes matching that type are shown.
2556 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2557 struct prefix_rd
*prd
, int type
,
2560 struct bgp_node
*rd_rn
;
2561 struct bgp_table
*table
;
2562 struct bgp_node
*rn
;
2563 struct bgp_path_info
*pi
;
2567 uint32_t prefix_cnt
, path_cnt
;
2568 char rd_str
[RD_ADDRSTRLEN
];
2569 json_object
*json_rd
= NULL
;
2570 int add_rd_to_json
= 0;
2574 prefix_cnt
= path_cnt
= 0;
2576 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2578 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2582 table
= bgp_node_get_bgp_table_info(rd_rn
);
2587 json_rd
= json_object_new_object();
2588 json_object_string_add(json_rd
, "rd", rd_str
);
2591 /* Display all prefixes with this RD. */
2592 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2593 const struct prefix_evpn
*evp
=
2594 (const struct prefix_evpn
*)bgp_node_get_prefix(rn
);
2595 json_object
*json_prefix
= NULL
;
2596 json_object
*json_paths
= NULL
;
2597 char prefix_str
[BUFSIZ
];
2598 int add_prefix_to_json
= 0;
2600 bgp_evpn_route2str((struct prefix_evpn
*)evp
, prefix_str
,
2601 sizeof(prefix_str
));
2603 if (type
&& evp
->prefix
.route_type
!= type
)
2607 json_prefix
= json_object_new_object();
2609 pi
= bgp_node_get_bgp_path_info(rn
);
2611 /* RD header and legend - once overall. */
2612 if (rd_header
&& !json
) {
2614 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2616 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2618 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2622 /* Prefix and num paths displayed once per prefix. */
2623 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2630 json_paths
= json_object_new_array();
2632 /* Display each path for this prefix. */
2633 for (; pi
; pi
= pi
->next
) {
2634 json_object
*json_path
= NULL
;
2637 json_path
= json_object_new_array();
2639 route_vty_out_detail(vty
, bgp
, rn
, pi
, afi
, safi
,
2643 json_object_array_add(json_paths
, json_path
);
2646 add_prefix_to_json
= 1;
2651 if (add_prefix_to_json
) {
2652 json_object_object_add(json_prefix
, "paths",
2654 json_object_object_add(json_rd
, prefix_str
,
2657 json_object_free(json_paths
);
2658 json_object_free(json_prefix
);
2667 json_object_object_add(json
, rd_str
, json_rd
);
2669 json_object_free(json_rd
);
2673 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2674 json_object_int_add(json
, "numPaths", path_cnt
);
2676 if (prefix_cnt
== 0)
2677 vty_out(vty
, "No prefixes exist with this RD%s\n",
2678 type
? " (of requested type)" : "");
2681 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2682 prefix_cnt
, path_cnt
,
2683 type
? " (of requested type)" : "");
2688 * Display BGP EVPN routing table - all routes (vty handler).
2689 * If 'type' is non-zero, only routes matching that type are shown.
2691 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2692 json_object
*json
, int detail
)
2694 struct bgp_node
*rd_rn
;
2695 struct bgp_table
*table
;
2696 struct bgp_node
*rn
;
2697 struct bgp_path_info
*pi
;
2698 int header
= detail
? 0 : 1;
2702 uint32_t prefix_cnt
, path_cnt
;
2706 prefix_cnt
= path_cnt
= 0;
2708 /* EVPN routing table is a 2-level table with the first level being
2711 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2712 rd_rn
= bgp_route_next(rd_rn
)) {
2713 char rd_str
[RD_ADDRSTRLEN
];
2714 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2715 int add_rd_to_json
= 0;
2717 const struct prefix
*rd_rnp
= bgp_node_get_prefix(rd_rn
);
2719 table
= bgp_node_get_bgp_table_info(rd_rn
);
2723 tbl_ver
= table
->version
;
2724 prefix_rd2str((struct prefix_rd
*)rd_rnp
, rd_str
,
2728 json_rd
= json_object_new_object();
2732 /* Display all prefixes for an RD */
2733 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2734 json_object
*json_prefix
=
2735 NULL
; /* contains prefix under a RD */
2736 json_object
*json_paths
=
2737 NULL
; /* array of paths under a prefix*/
2738 const struct prefix_evpn
*evp
=
2739 (const struct prefix_evpn
*)bgp_node_get_prefix(
2741 char prefix_str
[BUFSIZ
];
2742 int add_prefix_to_json
= 0;
2743 const struct prefix
*p
= bgp_node_get_prefix(rn
);
2745 bgp_evpn_route2str((struct prefix_evpn
*)p
, prefix_str
,
2746 sizeof(prefix_str
));
2748 if (type
&& evp
->prefix
.route_type
!= type
)
2751 pi
= bgp_node_get_bgp_path_info(rn
);
2753 /* Overall header/legend displayed once. */
2755 bgp_evpn_show_route_header(vty
, bgp
,
2760 "%19s Extended Community\n"
2765 /* RD header - per RD. */
2767 bgp_evpn_show_route_rd_header(
2768 vty
, rd_rn
, json_rd
, rd_str
,
2777 json_prefix
= json_object_new_object();
2778 json_paths
= json_object_new_array();
2779 json_object_string_add(json_prefix
, "prefix",
2781 json_object_int_add(json_prefix
, "prefixLen",
2785 /* Prefix and num paths displayed once per prefix. */
2787 route_vty_out_detail_header(
2789 (struct prefix_rd
*)rd_rnp
, AFI_L2VPN
,
2790 SAFI_EVPN
, json_prefix
);
2792 /* For EVPN, the prefix is displayed for each path (to
2794 * with code that already exists).
2796 for (; pi
; pi
= pi
->next
) {
2797 json_object
*json_path
= NULL
;
2799 add_prefix_to_json
= 1;
2803 json_path
= json_object_new_array();
2806 route_vty_out_detail(
2807 vty
, bgp
, rn
, pi
, AFI_L2VPN
,
2808 SAFI_EVPN
, json_path
);
2810 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
2814 json_object_array_add(json_paths
,
2819 if (add_prefix_to_json
) {
2820 json_object_object_add(json_prefix
,
2823 json_object_object_add(json_rd
,
2827 json_object_free(json_prefix
);
2828 json_object_free(json_paths
);
2837 json_object_object_add(json
, rd_str
, json_rd
);
2839 json_object_free(json_rd
);
2846 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2847 json_object_int_add(json
, "numPaths", path_cnt
);
2849 if (prefix_cnt
== 0) {
2850 vty_out(vty
, "No EVPN prefixes %sexist\n",
2851 type
? "(of requested type) " : "");
2853 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2854 prefix_cnt
, path_cnt
,
2855 type
? " (of requested type)" : "");
2860 /* Display specific ES */
2861 static void evpn_show_es(struct vty
*vty
, struct bgp
*bgp
, esi_t
*esi
,
2864 struct evpnes
*es
= NULL
;
2866 es
= bgp_evpn_lookup_es(bgp
, esi
);
2868 display_es(vty
, es
, json
);
2871 vty_out(vty
, "{}\n");
2873 vty_out(vty
, "ESI not found\n");
2879 /* Display all ESs */
2880 static void evpn_show_all_es(struct vty
*vty
, struct bgp
*bgp
,
2886 vty_out(vty
, "%-30s %-6s %-21s %-15s %-6s\n",
2887 "ESI", "Type", "RD", "Originator-IP", "#VTEPs");
2892 hash_iterate(bgp
->esihash
,
2893 (void (*)(struct hash_bucket
*, void *))show_es_entry
,
2898 * Display specified VNI (vty handler)
2900 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2904 struct bgpevpn
*vpn
;
2906 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2909 display_vni(vty
, vpn
, json
);
2911 struct bgp
*bgp_temp
;
2912 struct listnode
*node
= NULL
;
2914 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2915 if (bgp_temp
->l3vni
== vni
) {
2917 display_l3vni(vty
, bgp_temp
, json
);
2924 vty_out(vty
, "{}\n");
2926 vty_out(vty
, "VNI not found\n");
2933 * Display a VNI (upon user query).
2935 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2939 struct bgp
*bgp_temp
= NULL
;
2940 struct listnode
*node
;
2944 vty_out(vty
, "Flags: * - Kernel\n");
2945 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2946 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2949 /* print all L2 VNIS */
2952 hash_iterate(bgp
->vnihash
,
2953 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2956 /* print all L3 VNIs */
2957 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2958 show_l3vni_entry(vty
, bgp_temp
, json
);
2962 * evpn - enable advertisement of svi MAC-IP
2964 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2968 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2970 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2973 bgp
->evpn_info
->advertise_svi_macip
= set
;
2974 bgp_zebra_advertise_svi_macip(bgp
,
2975 bgp
->evpn_info
->advertise_svi_macip
, 0);
2977 if (set
&& vpn
->advertise_svi_macip
)
2979 else if (!set
&& !vpn
->advertise_svi_macip
)
2982 vpn
->advertise_svi_macip
= set
;
2983 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2989 * evpn - enable advertisement of default g/w
2991 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2994 if (bgp
->advertise_gw_macip
)
2997 bgp
->advertise_gw_macip
= 1;
2998 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3000 if (vpn
->advertise_gw_macip
)
3003 vpn
->advertise_gw_macip
= 1;
3004 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3011 * evpn - disable advertisement of default g/w
3013 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
3014 struct bgpevpn
*vpn
)
3017 if (!bgp
->advertise_gw_macip
)
3020 bgp
->advertise_gw_macip
= 0;
3021 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3023 if (!vpn
->advertise_gw_macip
)
3026 vpn
->advertise_gw_macip
= 0;
3027 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3034 * evpn - enable advertisement of default g/w
3036 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3037 afi_t afi
, bool add
)
3039 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3042 /* bail if we are already advertising default route */
3043 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3047 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3048 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3049 else if (afi
== AFI_IP6
)
3050 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3051 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3053 /* bail out if we havent advertised the default route */
3054 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3057 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3058 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3059 else if (afi
== AFI_IP6
)
3060 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3061 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3064 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3068 * evpn - enable advertisement of default g/w
3070 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3071 struct bgpevpn
*vpn
)
3073 if (vpn
->advertise_subnet
)
3076 vpn
->advertise_subnet
= 1;
3077 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3081 * evpn - disable advertisement of default g/w
3083 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3085 if (!vpn
->advertise_subnet
)
3088 vpn
->advertise_subnet
= 0;
3089 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3093 * EVPN (VNI advertisement) enabled. Register with zebra.
3095 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3097 bgp
->advertise_all_vni
= 1;
3099 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3103 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3104 * cache, EVPN routes (delete and withdraw from peers).
3106 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3108 bgp
->advertise_all_vni
= 0;
3109 bgp_set_evpn(bgp_get_default());
3110 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3111 bgp_evpn_cleanup_on_disable(bgp
);
3115 * EVPN - use RFC8365 to auto-derive RT
3117 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3119 bgp
->advertise_autort_rfc8365
= 1;
3120 bgp_evpn_handle_autort_change(bgp
);
3124 * EVPN - don't use RFC8365 to auto-derive RT
3126 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3128 bgp
->advertise_autort_rfc8365
= 0;
3129 bgp_evpn_handle_autort_change(bgp
);
3132 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3134 char buf1
[RD_ADDRSTRLEN
];
3136 struct listnode
*node
, *nnode
;
3137 struct ecommunity
*ecom
;
3139 if (is_vni_configured(vpn
)) {
3140 vty_out(vty
, " vni %d\n", vpn
->vni
);
3141 if (is_rd_configured(vpn
))
3142 vty_out(vty
, " rd %s\n",
3143 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3145 if (is_import_rt_configured(vpn
)) {
3146 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3148 ecom_str
= ecommunity_ecom2str(
3149 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3150 vty_out(vty
, " route-target import %s\n",
3152 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3156 if (is_export_rt_configured(vpn
)) {
3157 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3159 ecom_str
= ecommunity_ecom2str(
3160 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3161 vty_out(vty
, " route-target export %s\n",
3163 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3167 if (vpn
->advertise_gw_macip
)
3168 vty_out(vty
, " advertise-default-gw\n");
3170 if (vpn
->advertise_svi_macip
)
3171 vty_out(vty
, " advertise-svi-ip\n");
3173 if (vpn
->advertise_subnet
)
3174 vty_out(vty
, " advertise-subnet\n");
3176 vty_out(vty
, " exit-vni\n");
3180 #ifndef VTYSH_EXTRACT_PL
3181 #include "bgpd/bgp_evpn_vty_clippy.c"
3184 DEFPY(bgp_evpn_flood_control
,
3185 bgp_evpn_flood_control_cmd
,
3186 "[no$no] flooding <disable$disable|head-end-replication$her>",
3188 "Specify handling for BUM packets\n"
3189 "Do not flood any BUM packets\n"
3190 "Flood BUM packets using head-end replication\n")
3192 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3193 enum vxlan_flood_control flood_ctrl
;
3199 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3201 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3205 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3208 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3209 bgp_evpn_flood_control_change(bgp
);
3214 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3215 bgp_evpn_advertise_default_gw_vni_cmd
,
3216 "advertise-default-gw",
3217 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3219 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3220 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3225 evpn_set_advertise_default_gw(bgp
, vpn
);
3230 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3231 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3232 "no advertise-default-gw",
3234 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3236 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3237 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3242 evpn_unset_advertise_default_gw(bgp
, vpn
);
3248 DEFUN (bgp_evpn_advertise_default_gw
,
3249 bgp_evpn_advertise_default_gw_cmd
,
3250 "advertise-default-gw",
3251 "Advertise All default g/w mac-ip routes in EVPN\n")
3253 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3258 if (!EVPN_ENABLED(bgp
)) {
3260 "This command is only supported under the EVPN VRF\n");
3264 evpn_set_advertise_default_gw(bgp
, NULL
);
3269 DEFUN (no_bgp_evpn_advertise_default_gw
,
3270 no_bgp_evpn_advertise_default_gw_cmd
,
3271 "no advertise-default-gw",
3273 "Withdraw All default g/w mac-ip routes from EVPN\n")
3275 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3280 if (!EVPN_ENABLED(bgp
)) {
3282 "This command is only supported under the EVPN VRF\n");
3286 evpn_unset_advertise_default_gw(bgp
, NULL
);
3291 DEFUN (bgp_evpn_advertise_all_vni
,
3292 bgp_evpn_advertise_all_vni_cmd
,
3293 "advertise-all-vni",
3294 "Advertise All local VNIs\n")
3296 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3297 struct bgp
*bgp_evpn
= NULL
;
3302 bgp_evpn
= bgp_get_evpn();
3303 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3304 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3306 return CMD_WARNING_CONFIG_FAILED
;
3309 evpn_set_advertise_all_vni(bgp
);
3313 DEFUN (no_bgp_evpn_advertise_all_vni
,
3314 no_bgp_evpn_advertise_all_vni_cmd
,
3315 "no advertise-all-vni",
3317 "Advertise All local VNIs\n")
3319 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3323 evpn_unset_advertise_all_vni(bgp
);
3327 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3328 bgp_evpn_advertise_autort_rfc8365_cmd
,
3329 "autort rfc8365-compatible",
3330 "Auto-derivation of RT\n"
3331 "Auto-derivation of RT using RFC8365\n")
3333 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3337 evpn_set_advertise_autort_rfc8365(bgp
);
3341 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3342 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3343 "no autort rfc8365-compatible",
3345 "Auto-derivation of RT\n"
3346 "Auto-derivation of RT using RFC8365\n")
3348 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3352 evpn_unset_advertise_autort_rfc8365(bgp
);
3356 DEFUN (bgp_evpn_default_originate
,
3357 bgp_evpn_default_originate_cmd
,
3358 "default-originate <ipv4 | ipv6>",
3359 "originate a default route\n"
3360 "ipv4 address family\n"
3361 "ipv6 address family\n")
3365 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3369 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3370 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3374 DEFUN (no_bgp_evpn_default_originate
,
3375 no_bgp_evpn_default_originate_cmd
,
3376 "no default-originate <ipv4 | ipv6>",
3378 "withdraw a default route\n"
3379 "ipv4 address family\n"
3380 "ipv6 address family\n")
3384 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3388 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3389 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3393 DEFPY (dup_addr_detection
,
3394 dup_addr_detection_cmd
,
3395 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3396 "Duplicate address detection\n"
3397 "Max allowed moves before address detected as duplicate\n"
3398 "Num of max allowed moves (2-1000) default 5\n"
3399 "Duplicate address detection time\n"
3400 "Time in seconds (2-1800) default 180\n")
3402 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3407 if (!EVPN_ENABLED(bgp_vrf
)) {
3409 "This command is only supported under the EVPN VRF\n");
3413 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3416 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3418 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3420 bgp_zebra_dup_addr_detection(bgp_vrf
);
3425 DEFPY (dup_addr_detection_auto_recovery
,
3426 dup_addr_detection_auto_recovery_cmd
,
3427 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3428 "Duplicate address detection\n"
3429 "Duplicate address detection freeze\n"
3430 "Duplicate address detection permanent freeze\n"
3431 "Duplicate address detection freeze time (30-3600)\n")
3433 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3434 uint32_t freeze_time
= freeze_time_val
;
3439 if (!EVPN_ENABLED(bgp_vrf
)) {
3441 "This command is only supported under the EVPN VRF\n");
3445 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3446 bgp_vrf
->evpn_info
->dad_freeze
= true;
3447 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3449 bgp_zebra_dup_addr_detection(bgp_vrf
);
3454 DEFPY (no_dup_addr_detection
,
3455 no_dup_addr_detection_cmd
,
3456 "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>]",
3458 "Duplicate address detection\n"
3459 "Max allowed moves before address detected as duplicate\n"
3460 "Num of max allowed moves (2-1000) default 5\n"
3461 "Duplicate address detection time\n"
3462 "Time in seconds (2-1800) default 180\n"
3463 "Duplicate address detection freeze\n"
3464 "Duplicate address detection permanent freeze\n"
3465 "Duplicate address detection freeze time (30-3600)\n")
3467 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3468 uint32_t max_moves
= (uint32_t)max_moves_val
;
3469 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3474 if (!EVPN_ENABLED(bgp_vrf
)) {
3476 "This command is only supported under the EVPN VRF\n");
3481 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3483 /* Reset all parameters to default. */
3484 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3485 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3486 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3487 bgp_vrf
->evpn_info
->dad_freeze
= false;
3488 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3491 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3493 "%% Value does not match with config\n");
3496 bgp_vrf
->evpn_info
->dad_max_moves
=
3497 EVPN_DAD_DEFAULT_MAX_MOVES
;
3501 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3503 "%% Value does not match with config\n");
3506 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3510 if (bgp_vrf
->evpn_info
->dad_freeze_time
3513 "%% Value does not match with config\n");
3516 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3517 bgp_vrf
->evpn_info
->dad_freeze
= false;
3520 if (permanent_val
) {
3521 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3523 "%% Value does not match with config\n");
3526 bgp_vrf
->evpn_info
->dad_freeze
= false;
3530 bgp_zebra_dup_addr_detection(bgp_vrf
);
3535 DEFPY(bgp_evpn_advertise_svi_ip
,
3536 bgp_evpn_advertise_svi_ip_cmd
,
3537 "[no$no] advertise-svi-ip",
3539 "Advertise svi mac-ip routes in EVPN\n")
3541 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3546 if (!EVPN_ENABLED(bgp
)) {
3548 "This command is only supported under EVPN VRF\n");
3553 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3555 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3560 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3561 bgp_evpn_advertise_svi_ip_vni_cmd
,
3562 "[no$no] advertise-svi-ip",
3564 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3566 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3567 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3573 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3575 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3580 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3581 bgp_evpn_advertise_vni_subnet_cmd
,
3583 "Advertise the subnet corresponding to VNI\n")
3585 struct bgp
*bgp_vrf
= NULL
;
3586 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3587 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3592 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3596 evpn_set_advertise_subnet(bgp
, vpn
);
3600 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3601 no_bgp_evpn_advertise_vni_subnet_cmd
,
3602 "no advertise-subnet",
3604 "Advertise All local VNIs\n")
3606 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3607 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3612 evpn_unset_advertise_subnet(bgp
, vpn
);
3616 DEFUN (bgp_evpn_advertise_type5
,
3617 bgp_evpn_advertise_type5_cmd
,
3618 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3619 "Advertise prefix routes\n"
3622 "route-map for filtering specific routes\n"
3623 "Name of the route map\n")
3625 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3632 int rmap_changed
= 0;
3634 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3635 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3636 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3638 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3640 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3641 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3644 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3648 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3650 "%%only ipv4 or ipv6 address families are supported");
3654 if (safi
!= SAFI_UNICAST
) {
3656 "%%only ipv4 unicast or ipv6 unicast are supported");
3660 if (afi
== AFI_IP
) {
3662 /* if we are already advertising ipv4 prefix as type-5
3665 if (!rmap_changed
&&
3666 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3667 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3669 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3670 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3673 /* if we are already advertising ipv6 prefix as type-5
3676 if (!rmap_changed
&&
3677 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3678 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3680 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3681 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3685 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3686 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3687 XFREE(MTYPE_ROUTE_MAP_NAME
,
3688 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3689 route_map_counter_decrement(
3690 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3691 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3692 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3696 /* set the route-map for advertise command */
3697 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3698 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3699 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3700 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3701 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3702 route_map_counter_increment(
3703 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3706 /* advertise type-5 routes */
3707 if (advertise_type5_routes(bgp_vrf
, afi
))
3708 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3712 DEFUN (no_bgp_evpn_advertise_type5
,
3713 no_bgp_evpn_advertise_type5_cmd
,
3714 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3716 "Advertise prefix routes\n"
3720 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3726 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3727 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3729 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3731 "%%only ipv4 or ipv6 address families are supported");
3735 if (safi
!= SAFI_UNICAST
) {
3737 "%%only ipv4 unicast or ipv6 unicast are supported");
3741 if (afi
== AFI_IP
) {
3743 /* if we are not advertising ipv4 prefix as type-5
3746 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3747 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3748 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3749 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3750 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3754 /* if we are not advertising ipv6 prefix as type-5
3757 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3758 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3759 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3760 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3761 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3765 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3766 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3767 XFREE(MTYPE_ROUTE_MAP_NAME
,
3768 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3769 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3770 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3776 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3777 bgp_evpn_advertise_pip_ip_mac_cmd
,
3778 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3780 "evpn system primary IP\n"
3783 MAC_STR MAC_STR MAC_STR
)
3785 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3786 struct bgp
*bgp_evpn
= NULL
;
3788 if (EVPN_ENABLED(bgp_vrf
)) {
3790 "This command is supported under L3VNI BGP EVPN VRF\n");
3791 return CMD_WARNING_CONFIG_FAILED
;
3793 bgp_evpn
= bgp_get_evpn();
3796 /* pip is already enabled */
3797 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3800 bgp_vrf
->evpn_info
->advertise_pip
= true;
3801 if (ip
.s_addr
!= INADDR_ANY
) {
3802 /* Already configured with same IP */
3803 if (IPV4_ADDR_SAME(&ip
,
3804 &bgp_vrf
->evpn_info
->pip_ip_static
))
3807 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3808 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3810 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3812 /* default instance router-id assignemt */
3814 bgp_vrf
->evpn_info
->pip_ip
=
3815 bgp_evpn
->router_id
;
3818 if (!is_zero_mac(&mac
->eth_addr
)) {
3819 /* Already configured with same MAC */
3820 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3821 &mac
->eth_addr
, ETH_ALEN
) == 0)
3824 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3825 &mac
->eth_addr
, ETH_ALEN
);
3826 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3827 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3830 /* Copy zebra sys mac */
3831 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3832 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3833 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3838 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3840 /* Disable PIP feature */
3841 bgp_vrf
->evpn_info
->advertise_pip
= false;
3842 /* copy anycast mac */
3843 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3844 &bgp_vrf
->rmac
, ETH_ALEN
);
3846 /* remove MAC-IP option retain PIP knob. */
3847 if ((ip
.s_addr
!= INADDR_ANY
) &&
3848 !IPV4_ADDR_SAME(&ip
,
3849 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3851 "%% BGP EVPN PIP IP does not match\n");
3852 return CMD_WARNING_CONFIG_FAILED
;
3855 if (!is_zero_mac(&mac
->eth_addr
) &&
3856 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3857 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3859 "%% BGP EVPN PIP MAC does not match\n");
3860 return CMD_WARNING_CONFIG_FAILED
;
3862 /* pip_rmac can carry vrr_rmac reset only if it matches
3863 * with static value.
3865 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3866 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3868 /* Copy zebra sys mac */
3870 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3871 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3872 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3875 /* copy anycast mac */
3876 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3877 &bgp_vrf
->rmac
, ETH_ALEN
);
3881 /* reset user configured sys MAC */
3882 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3883 /* reset user configured sys IP */
3884 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3885 /* Assign default PIP IP (bgp instance router-id) */
3887 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3889 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3892 if (is_evpn_enabled()) {
3893 struct listnode
*node
= NULL
;
3894 struct bgpevpn
*vpn
= NULL
;
3896 update_advertise_vrf_routes(bgp_vrf
);
3898 /* Update (svi) type-2 routes */
3899 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3900 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3902 update_routes_for_vni(bgp_evpn
, vpn
);
3910 * Display VNI information - for all or a specific VNI
3912 DEFUN(show_bgp_l2vpn_evpn_vni
,
3913 show_bgp_l2vpn_evpn_vni_cmd
,
3914 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3923 struct bgp
*bgp_evpn
;
3927 json_object
*json
= NULL
;
3928 uint32_t num_l2vnis
= 0;
3929 uint32_t num_l3vnis
= 0;
3930 uint32_t num_vnis
= 0;
3931 struct listnode
*node
= NULL
;
3932 struct bgp
*bgp_temp
= NULL
;
3934 uj
= use_json(argc
, argv
);
3936 bgp_evpn
= bgp_get_evpn();
3940 if (!argv_find(argv
, argc
, "evpn", &idx
))
3944 json
= json_object_new_object();
3946 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3948 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3950 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3951 if (bgp_temp
->l3vni
)
3954 num_vnis
= num_l2vnis
+ num_l3vnis
;
3956 json_object_string_add(json
, "advertiseGatewayMacip",
3957 bgp_evpn
->advertise_gw_macip
3960 json_object_string_add(json
, "advertiseSviMacIp",
3961 bgp_evpn
->evpn_info
->advertise_svi_macip
3962 ? "Enabled" : "Disabled");
3963 json_object_string_add(json
, "advertiseAllVnis",
3964 is_evpn_enabled() ? "Enabled"
3966 json_object_string_add(
3968 bgp_evpn
->vxlan_flood_ctrl
3969 == VXLAN_FLOOD_HEAD_END_REPL
3970 ? "Head-end replication"
3972 json_object_int_add(json
, "numVnis", num_vnis
);
3973 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3974 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3976 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3977 bgp_evpn
->advertise_gw_macip
? "Enabled"
3979 vty_out(vty
, "Advertise SVI Macip: %s\n",
3980 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3982 vty_out(vty
, "Advertise All VNI flag: %s\n",
3983 is_evpn_enabled() ? "Enabled" : "Disabled");
3984 vty_out(vty
, "BUM flooding: %s\n",
3985 bgp_evpn
->vxlan_flood_ctrl
3986 == VXLAN_FLOOD_HEAD_END_REPL
3987 ? "Head-end replication"
3989 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
3990 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
3992 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
3996 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
3999 /* Display specific VNI */
4000 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4001 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4005 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4006 json
, JSON_C_TO_STRING_PRETTY
));
4007 json_object_free(json
);
4014 DEFUN(show_bgp_l2vpn_evpn_es
,
4015 show_bgp_l2vpn_evpn_es_cmd
,
4016 "show bgp l2vpn evpn es [ESI] [json]",
4021 "ethernet-Segment\n"
4022 "Ethernet-Segment Identifier\n"
4028 json_object
*json
= NULL
;
4029 struct bgp
*bgp
= NULL
;
4031 memset(&esi
, 0, sizeof(esi
));
4032 uj
= use_json(argc
, argv
);
4034 bgp
= bgp_get_evpn();
4038 if (!argv_find(argv
, argc
, "evpn", &idx
))
4041 if ((uj
&& argc
== ((idx
+ 1) + 2)) ||
4042 (!uj
&& argc
== (idx
+ 1) + 1)) {
4045 evpn_show_all_es(vty
, bgp
, json
);
4048 /* show a specific ES */
4050 /* get the ESI - ESI-ID is at argv[5] */
4051 if (!str_to_esi(argv
[idx
+ 2]->arg
, &esi
)) {
4052 vty_out(vty
, "%% Malformed ESI\n");
4055 evpn_show_es(vty
, bgp
, &esi
, json
);
4059 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4060 json
, JSON_C_TO_STRING_PRETTY
));
4061 json_object_free(json
);
4068 * Display EVPN neighbor summary.
4070 DEFUN(show_bgp_l2vpn_evpn_summary
,
4071 show_bgp_l2vpn_evpn_summary_cmd
,
4072 "show bgp [vrf VRFNAME] l2vpn evpn summary [failed] [json]",
4079 "Summary of BGP neighbor status\n"
4080 "Show only sessions not in Established state\n"
4084 bool uj
= use_json(argc
, argv
);
4086 bool show_failed
= false;
4088 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4089 vrf
= argv
[++idx_vrf
]->arg
;
4090 if (argv_find(argv
, argc
, "failed", &idx_vrf
))
4092 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
,
4097 * Display global EVPN routing table.
4099 DEFUN(show_bgp_l2vpn_evpn_route
,
4100 show_bgp_l2vpn_evpn_route_cmd
,
4101 "show bgp l2vpn evpn route [detail] [type <macip|multicast|es|prefix>] [json]",
4106 "EVPN route information\n"
4107 "Display Detailed Information\n"
4108 "Specify Route type\n"
4109 "MAC-IP (Type-2) route\n"
4110 "Multicast (Type-3) route\n"
4111 "Ethernet Segment (type-4) route \n"
4112 "Prefix (type-5 )route\n"
4120 json_object
*json
= NULL
;
4122 uj
= use_json(argc
, argv
);
4124 bgp
= bgp_get_evpn();
4129 json
= json_object_new_object();
4132 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4133 /* Specific type is requested */
4134 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4135 type
= BGP_EVPN_MAC_IP_ROUTE
;
4136 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4137 type
= BGP_EVPN_IMET_ROUTE
;
4138 else if (strncmp(argv
[type_idx
+ 1]->arg
, "e", 1) == 0)
4139 type
= BGP_EVPN_ES_ROUTE
;
4140 else if (strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4141 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4146 if (argv_find(argv
, argc
, "detail", &detail
))
4149 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4152 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4153 json
, JSON_C_TO_STRING_PRETTY
));
4154 json_object_free(json
);
4160 * Display global EVPN routing table for specific RD.
4162 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4163 show_bgp_l2vpn_evpn_route_rd_cmd
,
4164 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|es|prefix>] [json]",
4169 "EVPN route information\n"
4170 "Route Distinguisher\n"
4171 "ASN:XX or A.B.C.D:XX\n"
4172 "Specify Route type\n"
4173 "MAC-IP (Type-2) route\n"
4174 "Multicast (Type-3) route\n"
4175 "Ethernet Segment route\n"
4181 struct prefix_rd prd
;
4186 json_object
*json
= NULL
;
4188 bgp
= bgp_get_evpn();
4192 /* check if we need json output */
4193 uj
= use_json(argc
, argv
);
4195 json
= json_object_new_object();
4198 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4199 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4202 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4208 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4209 /* Specific type is requested */
4210 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4211 type
= BGP_EVPN_MAC_IP_ROUTE
;
4212 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4213 type
= BGP_EVPN_IMET_ROUTE
;
4214 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
4215 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4220 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4223 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4224 json
, JSON_C_TO_STRING_PRETTY
));
4225 json_object_free(json
);
4232 * Display global EVPN routing table for specific RD and MACIP.
4234 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4235 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4236 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4241 "EVPN route information\n"
4242 "Route Distinguisher\n"
4243 "ASN:XX or A.B.C.D:XX\n"
4245 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4247 "IP address (IPv4 or IPv6)\n"
4252 struct prefix_rd prd
;
4259 json_object
*json
= NULL
;
4261 memset(&mac
, 0, sizeof(struct ethaddr
));
4262 memset(&ip
, 0, sizeof(struct ipaddr
));
4264 bgp
= bgp_get_evpn();
4268 /* check if we need json output */
4269 uj
= use_json(argc
, argv
);
4271 json
= json_object_new_object();
4274 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4275 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4277 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4283 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4284 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4285 vty_out(vty
, "%% Malformed MAC address\n");
4290 /* get the ip if specified */
4291 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4292 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4293 vty_out(vty
, "%% Malformed IP address\n");
4298 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4301 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4302 json
, JSON_C_TO_STRING_PRETTY
));
4303 json_object_free(json
);
4309 /* Display per ESI routing table */
4310 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4311 show_bgp_l2vpn_evpn_route_esi_cmd
,
4312 "show bgp l2vpn evpn route esi ESI [json]",
4317 "EVPN route information\n"
4318 "Ethernet Segment Identifier\n"
4324 struct bgp
*bgp
= NULL
;
4325 json_object
*json
= NULL
;
4327 memset(&esi
, 0, sizeof(esi
));
4328 bgp
= bgp_get_evpn();
4332 uj
= use_json(argc
, argv
);
4334 json
= json_object_new_object();
4336 /* get the ESI - ESI-ID is at argv[6] */
4337 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4338 vty_out(vty
, "%% Malformed ESI\n");
4342 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4345 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4346 json
, JSON_C_TO_STRING_PRETTY
));
4347 json_object_free(json
);
4355 * Display per-VNI EVPN routing table.
4357 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4358 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>] [json]",
4363 "EVPN route information\n"
4364 "VXLAN Network Identifier\n"
4366 "Specify Route type\n"
4367 "MAC-IP (Type-2) route\n"
4368 "Multicast (Type-3) route\n"
4370 "Remote VTEP IP address\n"
4375 struct in_addr vtep_ip
;
4379 json_object
*json
= NULL
;
4381 bgp
= bgp_get_evpn();
4385 /* check if we need json output */
4386 uj
= use_json(argc
, argv
);
4388 json
= json_object_new_object();
4390 if (!argv_find(argv
, argc
, "evpn", &idx
))
4395 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4397 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
4398 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
4399 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
4400 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
4401 type
= BGP_EVPN_MAC_IP_ROUTE
;
4402 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
4403 type
= BGP_EVPN_IMET_ROUTE
;
4406 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
4407 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
4408 vty_out(vty
, "%% Malformed VTEP IP address\n");
4415 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4418 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4419 json
, JSON_C_TO_STRING_PRETTY
));
4420 json_object_free(json
);
4427 * Display per-VNI EVPN routing table for specific MACIP.
4429 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4430 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4431 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4436 "EVPN route information\n"
4437 "VXLAN Network Identifier\n"
4440 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4442 "IP address (IPv4 or IPv6)\n"
4451 json_object
*json
= NULL
;
4453 bgp
= bgp_get_evpn();
4457 /* check if we need json output */
4458 uj
= use_json(argc
, argv
);
4460 json
= json_object_new_object();
4462 if (!argv_find(argv
, argc
, "evpn", &idx
))
4466 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4469 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4470 vty_out(vty
, "%% Malformed MAC address\n");
4475 memset(&ip
, 0, sizeof(ip
));
4476 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4478 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4479 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4480 vty_out(vty
, "%% Malformed IP address\n");
4485 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4488 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4489 json
, JSON_C_TO_STRING_PRETTY
));
4490 json_object_free(json
);
4497 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4499 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4500 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4501 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4506 "EVPN route information\n"
4507 "VXLAN Network Identifier\n"
4509 "Multicast (Type-3) route\n"
4510 "Originating Router IP address\n"
4516 struct in_addr orig_ip
;
4519 json_object
*json
= NULL
;
4521 bgp
= bgp_get_evpn();
4525 /* check if we need json output */
4526 uj
= use_json(argc
, argv
);
4528 json
= json_object_new_object();
4530 if (!argv_find(argv
, argc
, "evpn", &idx
))
4534 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4537 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4539 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4543 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4546 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4547 json
, JSON_C_TO_STRING_PRETTY
));
4548 json_object_free(json
);
4555 * Display per-VNI EVPN routing table - for all VNIs.
4557 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4558 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4559 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4564 "EVPN route information\n"
4565 "VXLAN Network Identifier\n"
4567 "Print Detailed Output\n"
4569 "Remote VTEP IP address\n"
4573 struct in_addr vtep_ip
;
4576 json_object
*json
= NULL
;
4577 /* Detail Adjust. Adjust indexes according to detail option */
4580 bgp
= bgp_get_evpn();
4584 /* check if we need json output */
4585 uj
= use_json(argc
, argv
);
4587 json
= json_object_new_object();
4589 if (!argv_find(argv
, argc
, "evpn", &idx
))
4592 if (argv_find(argv
, argc
, "detail", &da
))
4595 /* vtep-ip position depends on detail option */
4597 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4599 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4600 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4601 vty_out(vty
, "%% Malformed VTEP IP address\n");
4606 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4609 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4610 json
, JSON_C_TO_STRING_PRETTY
));
4611 json_object_free(json
);
4618 * Display EVPN import route-target hash table
4620 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4621 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4622 "show bgp l2vpn evpn vrf-import-rt [json]",
4627 "Show vrf import route target\n"
4631 struct bgp
*bgp_evpn
= NULL
;
4632 json_object
*json
= NULL
;
4634 bgp_evpn
= bgp_get_evpn();
4638 uj
= use_json(argc
, argv
);
4640 json
= json_object_new_object();
4642 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4645 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4646 json
, JSON_C_TO_STRING_PRETTY
));
4647 json_object_free(json
);
4654 * Display EVPN import route-target hash table
4656 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4657 show_bgp_l2vpn_evpn_import_rt_cmd
,
4658 "show bgp l2vpn evpn import-rt [json]",
4663 "Show import route target\n"
4668 json_object
*json
= NULL
;
4670 bgp
= bgp_get_evpn();
4674 uj
= use_json(argc
, argv
);
4676 json
= json_object_new_object();
4678 evpn_show_import_rts(vty
, bgp
, json
);
4681 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4682 json
, JSON_C_TO_STRING_PRETTY
));
4683 json_object_free(json
);
4689 DEFUN(test_adv_evpn_type4_route
,
4690 test_adv_evpn_type4_route_cmd
,
4692 "Advertise EVPN ES route\n"
4693 "Ethernet-segment\n"
4694 "Ethernet-Segment Identifier\n")
4699 struct ipaddr vtep_ip
;
4701 bgp
= bgp_get_evpn();
4703 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4707 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4708 vty_out(vty
, "%%Malformed ESI\n");
4712 vtep_ip
.ipa_type
= IPADDR_V4
;
4713 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4715 ret
= bgp_evpn_local_es_add(bgp
, &esi
, &vtep_ip
);
4717 vty_out(vty
, "%%Failed to EVPN advertise type-4 route\n");
4723 DEFUN(test_withdraw_evpn_type4_route
,
4724 test_withdraw_evpn_type4_route_cmd
,
4726 "Advertise EVPN ES route\n"
4727 "Ethernet-segment\n"
4728 "Ethernet-Segment Identifier\n")
4733 struct ipaddr vtep_ip
;
4735 bgp
= bgp_get_evpn();
4737 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4741 if (!bgp
->peer_self
) {
4742 vty_out(vty
, "%%BGP instance doesn't have self peer\n");
4746 if (!str_to_esi(argv
[2]->arg
, &esi
)) {
4747 vty_out(vty
, "%%Malformed ESI\n");
4751 vtep_ip
.ipa_type
= IPADDR_V4
;
4752 vtep_ip
.ipaddr_v4
= bgp
->router_id
;
4753 ret
= bgp_evpn_local_es_del(bgp
, &esi
, &vtep_ip
);
4755 vty_out(vty
, "%%Failed to withdraw EVPN type-4 route\n");
4761 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4762 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4766 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4767 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4768 "Summary of BGP neighbor status\n" JSON_STR
)
4770 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4771 "show bgp evpn route [detail] [type <macip|multicast>]",
4772 SHOW_STR BGP_STR EVPN_HELP_STR
4773 "EVPN route information\n"
4774 "Display Detailed Information\n"
4775 "Specify Route type\n"
4776 "MAC-IP (Type-2) route\n"
4777 "Multicast (Type-3) route\n")
4780 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4781 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
4782 SHOW_STR BGP_STR EVPN_HELP_STR
4783 "EVPN route information\n"
4784 "Route Distinguisher\n"
4785 "ASN:XX or A.B.C.D:XX\n"
4786 "Specify Route type\n"
4787 "MAC-IP (Type-2) route\n"
4788 "Multicast (Type-3) route\n")
4791 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4792 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4793 SHOW_STR BGP_STR EVPN_HELP_STR
4794 "EVPN route information\n"
4795 "Route Distinguisher\n"
4796 "ASN:XX or A.B.C.D:XX\n"
4798 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4800 "IP address (IPv4 or IPv6)\n")
4803 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4804 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|multicast> | vtep A.B.C.D>]",
4805 SHOW_STR BGP_STR EVPN_HELP_STR
4806 "EVPN route information\n"
4807 "VXLAN Network Identifier\n"
4809 "Specify Route type\n"
4810 "MAC-IP (Type-2) route\n"
4811 "Multicast (Type-3) route\n"
4813 "Remote VTEP IP address\n")
4815 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4816 show_bgp_evpn_route_vni_macip_cmd
,
4817 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4818 SHOW_STR BGP_STR EVPN_HELP_STR
4819 "EVPN route information\n"
4820 "VXLAN Network Identifier\n"
4823 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4825 "IP address (IPv4 or IPv6)\n")
4827 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4828 show_bgp_evpn_route_vni_multicast_cmd
,
4829 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4830 SHOW_STR BGP_STR EVPN_HELP_STR
4831 "EVPN route information\n"
4832 "VXLAN Network Identifier\n"
4834 "Multicast (Type-3) route\n"
4835 "Originating Router IP address\n")
4837 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4838 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4839 SHOW_STR BGP_STR EVPN_HELP_STR
4840 "EVPN route information\n"
4841 "VXLAN Network Identifier\n"
4843 "Print Detailed Output\n"
4845 "Remote VTEP IP address\n")
4847 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4848 "show bgp evpn import-rt",
4849 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4851 DEFUN_NOSH (bgp_evpn_vni
,
4853 "vni " CMD_VNI_RANGE
,
4854 "VXLAN Network Identifier\n"
4858 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4859 struct bgpevpn
*vpn
;
4864 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4866 /* Create VNI, or mark as configured. */
4867 vpn
= evpn_create_update_vni(bgp
, vni
);
4869 vty_out(vty
, "%% Failed to create VNI \n");
4873 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4877 DEFUN (no_bgp_evpn_vni
,
4878 no_bgp_evpn_vni_cmd
,
4879 "no vni " CMD_VNI_RANGE
,
4881 "VXLAN Network Identifier\n"
4885 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4886 struct bgpevpn
*vpn
;
4891 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4893 /* Check if we should disallow. */
4894 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4896 vty_out(vty
, "%% Specified VNI does not exist\n");
4899 if (!is_vni_configured(vpn
)) {
4900 vty_out(vty
, "%% Specified VNI is not configured\n");
4904 evpn_delete_vni(bgp
, vpn
);
4908 DEFUN_NOSH (exit_vni
,
4911 "Exit from VNI mode\n")
4913 if (vty
->node
== BGP_EVPN_VNI_NODE
)
4914 vty
->node
= BGP_EVPN_NODE
;
4918 DEFUN (bgp_evpn_vrf_rd
,
4919 bgp_evpn_vrf_rd_cmd
,
4920 "rd ASN:NN_OR_IP-ADDRESS:NN",
4921 "Route Distinguisher\n"
4922 "ASN:XX or A.B.C.D:XX\n")
4925 struct prefix_rd prd
;
4926 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4931 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
4933 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4937 /* If same as existing value, there is nothing more to do. */
4938 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
4941 /* Configure or update the RD. */
4942 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
4946 DEFUN (no_bgp_evpn_vrf_rd
,
4947 no_bgp_evpn_vrf_rd_cmd
,
4948 "no rd ASN:NN_OR_IP-ADDRESS:NN",
4950 "Route Distinguisher\n"
4951 "ASN:XX or A.B.C.D:XX\n")
4954 struct prefix_rd prd
;
4955 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4960 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
4962 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4966 /* Check if we should disallow. */
4967 if (!is_vrf_rd_configured(bgp_vrf
)) {
4968 vty_out(vty
, "%% RD is not configured for this VRF\n");
4972 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
4974 "%% RD specified does not match configuration for this VRF\n");
4978 evpn_unconfigure_vrf_rd(bgp_vrf
);
4982 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
4983 no_bgp_evpn_vrf_rd_without_val_cmd
,
4986 "Route Distinguisher\n")
4988 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
4993 /* Check if we should disallow. */
4994 if (!is_vrf_rd_configured(bgp_vrf
)) {
4995 vty_out(vty
, "%% RD is not configured for this VRF\n");
4999 evpn_unconfigure_vrf_rd(bgp_vrf
);
5003 DEFUN (bgp_evpn_vni_rd
,
5004 bgp_evpn_vni_rd_cmd
,
5005 "rd ASN:NN_OR_IP-ADDRESS:NN",
5006 "Route Distinguisher\n"
5007 "ASN:XX or A.B.C.D:XX\n")
5009 struct prefix_rd prd
;
5010 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5011 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5017 if (!EVPN_ENABLED(bgp
)) {
5019 "This command is only supported under EVPN VRF\n");
5023 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5025 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5029 /* If same as existing value, there is nothing more to do. */
5030 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5033 /* Configure or update the RD. */
5034 evpn_configure_rd(bgp
, vpn
, &prd
);
5038 DEFUN (no_bgp_evpn_vni_rd
,
5039 no_bgp_evpn_vni_rd_cmd
,
5040 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5042 "Route Distinguisher\n"
5043 "ASN:XX or A.B.C.D:XX\n")
5045 struct prefix_rd prd
;
5046 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5047 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5053 if (!EVPN_ENABLED(bgp
)) {
5055 "This command is only supported under EVPN VRF\n");
5059 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5061 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5065 /* Check if we should disallow. */
5066 if (!is_rd_configured(vpn
)) {
5067 vty_out(vty
, "%% RD is not configured for this VNI\n");
5071 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5073 "%% RD specified does not match configuration for this VNI\n");
5077 evpn_unconfigure_rd(bgp
, vpn
);
5081 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5082 no_bgp_evpn_vni_rd_without_val_cmd
,
5085 "Route Distinguisher\n")
5087 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5088 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5093 if (!EVPN_ENABLED(bgp
)) {
5095 "This command is only supported under EVPN VRF\n");
5099 /* Check if we should disallow. */
5100 if (!is_rd_configured(vpn
)) {
5101 vty_out(vty
, "%% RD is not configured for this VNI\n");
5105 evpn_unconfigure_rd(bgp
, vpn
);
5110 * Loop over all extended-communities in the route-target list rtl and
5111 * return 1 if we find ecomtarget
5113 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5114 struct ecommunity
*ecomtarget
)
5116 struct listnode
*node
, *nnode
;
5117 struct ecommunity
*ecom
;
5119 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5120 if (ecommunity_match(ecom
, ecomtarget
))
5127 /* display L3VNI related info for a VRF instance */
5128 DEFUN (show_bgp_vrf_l3vni_info
,
5129 show_bgp_vrf_l3vni_info_cmd
,
5130 "show bgp vrf VRFNAME vni [json]",
5138 char buf
[ETHER_ADDR_STRLEN
];
5139 char buf1
[INET6_ADDRSTRLEN
];
5141 const char *name
= NULL
;
5142 struct bgp
*bgp
= NULL
;
5143 struct listnode
*node
= NULL
;
5144 struct bgpevpn
*vpn
= NULL
;
5145 struct ecommunity
*ecom
= NULL
;
5146 json_object
*json
= NULL
;
5147 json_object
*json_vnis
= NULL
;
5148 json_object
*json_export_rts
= NULL
;
5149 json_object
*json_import_rts
= NULL
;
5150 bool uj
= use_json(argc
, argv
);
5153 json
= json_object_new_object();
5154 json_vnis
= json_object_new_array();
5155 json_export_rts
= json_object_new_array();
5156 json_import_rts
= json_object_new_array();
5159 name
= argv
[idx_vrf
]->arg
;
5160 bgp
= bgp_lookup_by_name(name
);
5163 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5165 json_object_string_add(json
, "warning",
5166 "BGP instance not found");
5167 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5168 json_object_free(json
);
5174 vty_out(vty
, "BGP VRF: %s\n", name
);
5175 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
5176 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5177 vty_out(vty
, " Rmac: %s\n",
5178 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5179 vty_out(vty
, " VNI Filter: %s\n",
5180 CHECK_FLAG(bgp
->vrf_flags
,
5181 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5182 ? "prefix-routes-only"
5184 vty_out(vty
, " L2-VNI List:\n");
5186 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5187 vty_out(vty
, "%u ", vpn
->vni
);
5189 vty_out(vty
, " Export-RTs:\n");
5191 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5192 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5194 vty_out(vty
, " Import-RTs:\n");
5196 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5197 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5199 vty_out(vty
, " RD: %s\n",
5200 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5202 json_object_string_add(json
, "vrf", name
);
5203 json_object_string_add(json
, "local-ip",
5204 inet_ntoa(bgp
->originator_ip
));
5205 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5206 json_object_string_add(
5208 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5209 json_object_string_add(
5211 CHECK_FLAG(bgp
->vrf_flags
,
5212 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5213 ? "prefix-routes-only"
5215 /* list of l2vnis */
5216 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5217 json_object_array_add(json_vnis
,
5218 json_object_new_int(vpn
->vni
));
5219 json_object_object_add(json
, "l2vnis", json_vnis
);
5222 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5223 json_object_array_add(
5225 json_object_new_string(ecommunity_str(ecom
)));
5226 json_object_object_add(json
, "export-rts", json_export_rts
);
5229 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5230 json_object_array_add(
5232 json_object_new_string(ecommunity_str(ecom
)));
5233 json_object_object_add(json
, "import-rts", json_import_rts
);
5234 json_object_string_add(
5236 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5240 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5241 json
, JSON_C_TO_STRING_PRETTY
));
5242 json_object_free(json
);
5247 /* import/export rt for l3vni-vrf */
5248 DEFUN (bgp_evpn_vrf_rt
,
5249 bgp_evpn_vrf_rt_cmd
,
5250 "route-target <both|import|export> RT",
5252 "import and export\n"
5255 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5258 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5259 struct ecommunity
*ecomadd
= NULL
;
5264 if (!strcmp(argv
[1]->arg
, "import"))
5265 rt_type
= RT_TYPE_IMPORT
;
5266 else if (!strcmp(argv
[1]->arg
, "export"))
5267 rt_type
= RT_TYPE_EXPORT
;
5268 else if (!strcmp(argv
[1]->arg
, "both"))
5269 rt_type
= RT_TYPE_BOTH
;
5271 vty_out(vty
, "%% Invalid Route Target type\n");
5275 /* Add/update the import route-target */
5276 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5277 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5278 ECOMMUNITY_ROUTE_TARGET
, 0);
5280 vty_out(vty
, "%% Malformed Route Target list\n");
5283 ecommunity_str(ecomadd
);
5285 /* Do nothing if we already have this import route-target */
5286 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5287 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5290 /* Add/update the export route-target */
5291 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5292 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5293 ECOMMUNITY_ROUTE_TARGET
, 0);
5295 vty_out(vty
, "%% Malformed Route Target list\n");
5298 ecommunity_str(ecomadd
);
5300 /* Do nothing if we already have this export route-target */
5301 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5302 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5308 DEFUN (no_bgp_evpn_vrf_rt
,
5309 no_bgp_evpn_vrf_rt_cmd
,
5310 "no route-target <both|import|export> RT",
5313 "import and export\n"
5316 "ASN:XX or A.B.C.D:XX\n")
5318 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5319 int rt_type
, found_ecomdel
;
5320 struct ecommunity
*ecomdel
= NULL
;
5325 if (!strcmp(argv
[2]->arg
, "import"))
5326 rt_type
= RT_TYPE_IMPORT
;
5327 else if (!strcmp(argv
[2]->arg
, "export"))
5328 rt_type
= RT_TYPE_EXPORT
;
5329 else if (!strcmp(argv
[2]->arg
, "both"))
5330 rt_type
= RT_TYPE_BOTH
;
5332 vty_out(vty
, "%% Invalid Route Target type\n");
5336 if (rt_type
== RT_TYPE_IMPORT
) {
5337 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5339 "%% Import RT is not configured for this VRF\n");
5342 } else if (rt_type
== RT_TYPE_EXPORT
) {
5343 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5345 "%% Export RT is not configured for this VRF\n");
5348 } else if (rt_type
== RT_TYPE_BOTH
) {
5349 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5350 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5352 "%% Import/Export RT is not configured for this VRF\n");
5357 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5359 vty_out(vty
, "%% Malformed Route Target list\n");
5362 ecommunity_str(ecomdel
);
5364 if (rt_type
== RT_TYPE_IMPORT
) {
5365 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5368 "%% RT specified does not match configuration for this VRF\n");
5371 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5372 } else if (rt_type
== RT_TYPE_EXPORT
) {
5373 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5376 "%% RT specified does not match configuration for this VRF\n");
5379 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5380 } else if (rt_type
== RT_TYPE_BOTH
) {
5383 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5385 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5389 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5391 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5395 if (!found_ecomdel
) {
5397 "%% RT specified does not match configuration for this VRF\n");
5405 DEFUN (bgp_evpn_vni_rt
,
5406 bgp_evpn_vni_rt_cmd
,
5407 "route-target <both|import|export> RT",
5409 "import and export\n"
5412 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5414 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5415 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5417 struct ecommunity
*ecomadd
= NULL
;
5422 if (!EVPN_ENABLED(bgp
)) {
5424 "This command is only supported under EVPN VRF\n");
5428 if (!strcmp(argv
[1]->text
, "import"))
5429 rt_type
= RT_TYPE_IMPORT
;
5430 else if (!strcmp(argv
[1]->text
, "export"))
5431 rt_type
= RT_TYPE_EXPORT
;
5432 else if (!strcmp(argv
[1]->text
, "both"))
5433 rt_type
= RT_TYPE_BOTH
;
5435 vty_out(vty
, "%% Invalid Route Target type\n");
5439 /* Add/update the import route-target */
5440 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5441 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5442 ECOMMUNITY_ROUTE_TARGET
, 0);
5444 vty_out(vty
, "%% Malformed Route Target list\n");
5447 ecommunity_str(ecomadd
);
5449 /* Do nothing if we already have this import route-target */
5450 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5451 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5454 /* Add/update the export route-target */
5455 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5456 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5457 ECOMMUNITY_ROUTE_TARGET
, 0);
5459 vty_out(vty
, "%% Malformed Route Target list\n");
5462 ecommunity_str(ecomadd
);
5464 /* Do nothing if we already have this export route-target */
5465 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5466 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5472 DEFUN (no_bgp_evpn_vni_rt
,
5473 no_bgp_evpn_vni_rt_cmd
,
5474 "no route-target <both|import|export> RT",
5477 "import and export\n"
5480 "ASN:XX or A.B.C.D:XX\n")
5482 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5483 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5484 int rt_type
, found_ecomdel
;
5485 struct ecommunity
*ecomdel
= NULL
;
5490 if (!EVPN_ENABLED(bgp
)) {
5492 "This command is only supported under EVPN VRF\n");
5496 if (!strcmp(argv
[2]->text
, "import"))
5497 rt_type
= RT_TYPE_IMPORT
;
5498 else if (!strcmp(argv
[2]->text
, "export"))
5499 rt_type
= RT_TYPE_EXPORT
;
5500 else if (!strcmp(argv
[2]->text
, "both"))
5501 rt_type
= RT_TYPE_BOTH
;
5503 vty_out(vty
, "%% Invalid Route Target type\n");
5507 /* The user did "no route-target import", check to see if there are any
5508 * import route-targets configured. */
5509 if (rt_type
== RT_TYPE_IMPORT
) {
5510 if (!is_import_rt_configured(vpn
)) {
5512 "%% Import RT is not configured for this VNI\n");
5515 } else if (rt_type
== RT_TYPE_EXPORT
) {
5516 if (!is_export_rt_configured(vpn
)) {
5518 "%% Export RT is not configured for this VNI\n");
5521 } else if (rt_type
== RT_TYPE_BOTH
) {
5522 if (!is_import_rt_configured(vpn
)
5523 && !is_export_rt_configured(vpn
)) {
5525 "%% Import/Export RT is not configured for this VNI\n");
5530 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5532 vty_out(vty
, "%% Malformed Route Target list\n");
5535 ecommunity_str(ecomdel
);
5537 if (rt_type
== RT_TYPE_IMPORT
) {
5538 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5540 "%% RT specified does not match configuration for this VNI\n");
5543 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5544 } else if (rt_type
== RT_TYPE_EXPORT
) {
5545 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5547 "%% RT specified does not match configuration for this VNI\n");
5550 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5551 } else if (rt_type
== RT_TYPE_BOTH
) {
5554 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5555 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5559 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5560 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5564 if (!found_ecomdel
) {
5566 "%% RT specified does not match configuration for this VNI\n");
5574 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5575 no_bgp_evpn_vni_rt_without_val_cmd
,
5576 "no route-target <import|export>",
5582 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5583 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5589 if (!EVPN_ENABLED(bgp
)) {
5591 "This command is only supported under EVPN VRF\n");
5595 if (!strcmp(argv
[2]->text
, "import")) {
5596 rt_type
= RT_TYPE_IMPORT
;
5597 } else if (!strcmp(argv
[2]->text
, "export")) {
5598 rt_type
= RT_TYPE_EXPORT
;
5600 vty_out(vty
, "%% Invalid Route Target type\n");
5604 /* Check if we should disallow. */
5605 if (rt_type
== RT_TYPE_IMPORT
) {
5606 if (!is_import_rt_configured(vpn
)) {
5608 "%% Import RT is not configured for this VNI\n");
5612 if (!is_export_rt_configured(vpn
)) {
5614 "%% Export RT is not configured for this VNI\n");
5619 /* Unconfigure the RT. */
5620 if (rt_type
== RT_TYPE_IMPORT
)
5621 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5623 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5627 static int vni_cmp(const void **a
, const void **b
)
5629 const struct bgpevpn
*first
= *a
;
5630 const struct bgpevpn
*secnd
= *b
;
5632 return secnd
->vni
- first
->vni
;
5636 * Output EVPN configuration information.
5638 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5641 char buf1
[RD_ADDRSTRLEN
];
5642 char buf2
[INET6_ADDRSTRLEN
];
5645 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5646 struct listnode
*ln
;
5647 struct bgpevpn
*data
;
5649 list_sort(vnilist
, vni_cmp
);
5650 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5651 write_vni_config(vty
, data
);
5653 list_delete(&vnilist
);
5656 if (bgp
->advertise_all_vni
)
5657 vty_out(vty
, " advertise-all-vni\n");
5659 if (bgp
->advertise_autort_rfc8365
)
5660 vty_out(vty
, " autort rfc8365-compatible\n");
5662 if (bgp
->advertise_gw_macip
)
5663 vty_out(vty
, " advertise-default-gw\n");
5665 if (bgp
->evpn_info
->advertise_svi_macip
)
5666 vty_out(vty
, " advertise-svi-ip\n");
5668 if (!bgp
->evpn_info
->dup_addr_detect
)
5669 vty_out(vty
, " no dup-addr-detection\n");
5671 if (bgp
->evpn_info
->dad_max_moves
!=
5672 EVPN_DAD_DEFAULT_MAX_MOVES
||
5673 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5674 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5675 bgp
->evpn_info
->dad_max_moves
,
5676 bgp
->evpn_info
->dad_time
);
5678 if (bgp
->evpn_info
->dad_freeze
) {
5679 if (bgp
->evpn_info
->dad_freeze_time
)
5681 " dup-addr-detection freeze %u\n",
5682 bgp
->evpn_info
->dad_freeze_time
);
5685 " dup-addr-detection freeze permanent\n");
5688 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5689 vty_out(vty
, " flooding disable\n");
5691 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5692 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5693 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5694 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5695 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5697 vty_out(vty
, " advertise ipv4 unicast\n");
5700 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5701 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5702 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5703 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5704 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5706 vty_out(vty
, " advertise ipv6 unicast\n");
5709 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5710 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5711 vty_out(vty
, " default-originate ipv4\n");
5713 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5714 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5715 vty_out(vty
, " default-originate ipv6\n");
5717 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5718 if (!bgp
->evpn_info
->advertise_pip
)
5719 vty_out(vty
, " no advertise-pip\n");
5720 if (bgp
->evpn_info
->advertise_pip
) {
5721 if (bgp
->evpn_info
->pip_ip_static
.s_addr
5723 vty_out(vty
, " advertise-pip ip %s",
5725 &bgp
->evpn_info
->pip_ip_static
,
5726 buf2
, INET_ADDRSTRLEN
));
5728 bgp
->evpn_info
->pip_rmac_static
))) {
5729 char buf
[ETHER_ADDR_STRLEN
];
5731 vty_out(vty
, " mac %s",
5741 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5742 vty_out(vty
, " rd %s\n",
5743 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5745 /* import route-target */
5746 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5748 struct listnode
*node
, *nnode
;
5749 struct ecommunity
*ecom
;
5751 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5753 ecom_str
= ecommunity_ecom2str(
5754 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5755 vty_out(vty
, " route-target import %s\n", ecom_str
);
5756 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5760 /* export route-target */
5761 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5763 struct listnode
*node
, *nnode
;
5764 struct ecommunity
*ecom
;
5766 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5768 ecom_str
= ecommunity_ecom2str(
5769 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5770 vty_out(vty
, " route-target export %s\n", ecom_str
);
5771 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5776 void bgp_ethernetvpn_init(void)
5778 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5779 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5780 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5781 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5782 install_element(VIEW_NODE
,
5783 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5784 install_element(VIEW_NODE
,
5785 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5788 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5791 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5792 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5793 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5794 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5795 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5796 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5797 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5798 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5799 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5800 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5801 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5802 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5803 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5804 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5805 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5806 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5807 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5808 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5809 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5810 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5811 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5814 install_element(BGP_EVPN_NODE
, &test_adv_evpn_type4_route_cmd
);
5815 install_element(BGP_EVPN_NODE
, &test_withdraw_evpn_type4_route_cmd
);
5817 /* "show bgp l2vpn evpn" commands. */
5818 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5819 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5820 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5821 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5822 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5823 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5824 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5825 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5826 install_element(VIEW_NODE
,
5827 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5828 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5829 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5830 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5831 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5833 /* "show bgp evpn" commands. */
5834 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5835 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5836 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5837 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5838 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5839 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5840 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5841 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5842 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5843 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5844 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5845 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5847 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5848 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5849 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5850 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5851 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5852 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5853 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5854 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5855 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5856 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5857 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5858 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5859 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5860 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5861 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5862 install_element(BGP_EVPN_VNI_NODE
,
5863 &bgp_evpn_advertise_default_gw_vni_cmd
);
5864 install_element(BGP_EVPN_VNI_NODE
,
5865 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
5866 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
5867 install_element(BGP_EVPN_VNI_NODE
,
5868 &no_bgp_evpn_advertise_vni_subnet_cmd
);