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_ecommunity.h"
40 #define SHOW_DISPLAY_STANDARD 0
41 #define SHOW_DISPLAY_TAGS 1
42 #define SHOW_DISPLAY_OVERLAY 2
43 #define VNI_STR_LEN 32
46 * Context for VNI hash walk - used by callbacks.
51 struct in_addr vtep_ip
;
55 #if defined(HAVE_CUMULUS)
56 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
60 u_char type
, sub_type
;
61 struct ecommunity_as eas
;
62 struct ecommunity_ip eip
;
63 struct listnode
*node
, *nnode
;
64 struct bgp
*tmp_bgp_vrf
= NULL
;
65 json_object
*json_rt
= NULL
;
66 json_object
*json_vrfs
= NULL
;
67 char rt_buf
[RT_ADDRSTRLEN
];
70 json_rt
= json_object_new_object();
71 json_vrfs
= json_object_new_array();
74 pnt
= (u_char
*)&irt
->rt
.val
;
77 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
80 memset(&eas
, 0, sizeof(eas
));
82 case ECOMMUNITY_ENCODE_AS
:
83 eas
.as
= (*pnt
++ << 8);
85 ptr_get_be32(pnt
, &eas
.val
);
87 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
90 json_object_string_add(json_rt
, "rt", rt_buf
);
92 vty_out(vty
, "Route-target: %s", rt_buf
);
96 case ECOMMUNITY_ENCODE_IP
:
97 memcpy(&eip
.ip
, pnt
, 4);
99 eip
.val
= (*pnt
++ << 8);
102 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
106 json_object_string_add(json_rt
, "rt", rt_buf
);
108 vty_out(vty
, "Route-target: %s", rt_buf
);
112 case ECOMMUNITY_ENCODE_AS4
:
113 pnt
= ptr_get_be32(pnt
, &eas
.val
);
114 eas
.val
= (*pnt
++ << 8);
117 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
120 json_object_string_add(json_rt
, "rt", rt_buf
);
122 vty_out(vty
, "Route-target: %s", rt_buf
);
132 "\nList of VRFs importing routes with this route-target:\n");
135 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
137 json_object_array_add(
139 json_object_new_string(
140 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
142 vty_out(vty
, " %s\n",
143 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
147 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
148 json_object_object_add(json
, rt_buf
, json_rt
);
152 static void show_vrf_import_rt_entry(struct hash_backet
*backet
, void *args
[])
154 json_object
*json
= NULL
;
155 struct vty
*vty
= NULL
;
156 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)backet
->data
;
158 vty
= (struct vty
*)args
[0];
159 json
= (struct json_object
*)args
[1];
161 display_vrf_import_rt(vty
, irt
, json
);
164 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
168 u_char type
, sub_type
;
169 struct ecommunity_as eas
;
170 struct ecommunity_ip eip
;
171 struct listnode
*node
, *nnode
;
172 struct bgpevpn
*tmp_vpn
;
173 json_object
*json_rt
= NULL
;
174 json_object
*json_vnis
= NULL
;
175 char rt_buf
[RT_ADDRSTRLEN
];
178 json_rt
= json_object_new_object();
179 json_vnis
= json_object_new_array();
182 /* TODO: This needs to go into a function */
184 pnt
= (u_char
*)&irt
->rt
.val
;
187 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
190 memset(&eas
, 0, sizeof(eas
));
192 case ECOMMUNITY_ENCODE_AS
:
193 eas
.as
= (*pnt
++ << 8);
195 ptr_get_be32(pnt
, &eas
.val
);
197 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
200 json_object_string_add(json_rt
, "rt", rt_buf
);
202 vty_out(vty
, "Route-target: %s", rt_buf
);
206 case ECOMMUNITY_ENCODE_IP
:
207 memcpy(&eip
.ip
, pnt
, 4);
209 eip
.val
= (*pnt
++ << 8);
212 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%s:%u", inet_ntoa(eip
.ip
),
216 json_object_string_add(json_rt
, "rt", rt_buf
);
218 vty_out(vty
, "Route-target: %s", rt_buf
);
222 case ECOMMUNITY_ENCODE_AS4
:
223 pnt
= ptr_get_be32(pnt
, &eas
.val
);
224 eas
.val
= (*pnt
++ << 8);
227 snprintf(rt_buf
, RT_ADDRSTRLEN
, "%u:%u", eas
.as
, eas
.val
);
230 json_object_string_add(json_rt
, "rt", rt_buf
);
232 vty_out(vty
, "Route-target: %s", rt_buf
);
242 "\nList of VNIs importing routes with this route-target:\n");
245 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
247 json_object_array_add(
248 json_vnis
, json_object_new_int64(tmp_vpn
->vni
));
250 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
254 json_object_object_add(json_rt
, "vnis", json_vnis
);
255 json_object_object_add(json
, rt_buf
, json_rt
);
259 static void show_import_rt_entry(struct hash_backet
*backet
, void *args
[])
261 json_object
*json
= NULL
;
262 struct vty
*vty
= NULL
;
263 struct irt_node
*irt
= (struct irt_node
*)backet
->data
;
268 display_import_rt(vty
, irt
, json
);
273 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
274 struct bgp_node
*rd_rn
,
281 char rd_str
[RD_ADDRSTRLEN
];
283 pnt
= rd_rn
->p
.u
.val
;
285 /* Decode RD type. */
286 type
= decode_rd_type(pnt
);
291 vty_out(vty
, "Route Distinguisher: ");
295 decode_rd_as(pnt
+ 2, &rd_as
);
296 snprintf(rd_str
, RD_ADDRSTRLEN
, "%u:%d", rd_as
.as
, rd_as
.val
);
300 decode_rd_ip(pnt
+ 2, &rd_ip
);
301 snprintf(rd_str
, RD_ADDRSTRLEN
, "%s:%d", inet_ntoa(rd_ip
.ip
),
306 snprintf(rd_str
, RD_ADDRSTRLEN
, "Unknown RD type");
310 vty_out(vty
, "%s\n", rd_str
);
313 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
317 " Network Next Hop Metric LocPrf Weight Path\n";
323 vty_out(vty
, "BGP table version is 0, local router ID is %s\n",
324 inet_ntoa(bgp
->router_id
));
326 "Status codes: s suppressed, d damped, h history, "
327 "* valid, > best, i - internal\n");
328 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
330 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
331 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
332 vty_out(vty
, "EVPN type-5 prefix: [5]:[ESI]:[EthTag]:[IPlen]:[IP]\n\n");
333 vty_out(vty
, "%s", ri_header
);
336 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
339 char buf1
[INET6_ADDRSTRLEN
];
341 struct listnode
*node
, *nnode
;
342 struct ecommunity
*ecom
;
343 json_object
*json_import_rtl
= NULL
;
344 json_object
*json_export_rtl
= NULL
;
346 json_import_rtl
= json_export_rtl
= 0;
349 json_import_rtl
= json_object_new_array();
350 json_export_rtl
= json_object_new_array();
351 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
352 json_object_string_add(json
, "type", "L3");
353 json_object_string_add(json
, "kernelFlag", "Yes");
354 json_object_string_add(
356 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
357 json_object_string_add(json
, "originatorIp",
358 inet_ntoa(bgp_vrf
->originator_ip
));
359 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
361 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
362 vty_out(vty
, " (known to the kernel)");
365 vty_out(vty
, " Type: %s\n", "L3");
366 vty_out(vty
, " Tenant VRF: %s\n",
367 vrf_id_to_name(bgp_vrf
->vrf_id
));
368 vty_out(vty
, " RD: %s\n",
369 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
370 vty_out(vty
, " Originator IP: %s\n",
371 inet_ntoa(bgp_vrf
->originator_ip
));
372 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
376 vty_out(vty
, " Import Route Target:\n");
378 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
379 ecom_str
= ecommunity_ecom2str(ecom
,
380 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
383 json_object_array_add(json_import_rtl
,
384 json_object_new_string(ecom_str
));
386 vty_out(vty
, " %s\n", ecom_str
);
388 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
392 json_object_object_add(json
, "importRts", json_import_rtl
);
394 vty_out(vty
, " Export Route Target:\n");
396 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
397 ecom_str
= ecommunity_ecom2str(ecom
,
398 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
401 json_object_array_add(json_export_rtl
,
402 json_object_new_string(ecom_str
));
404 vty_out(vty
, " %s\n", ecom_str
);
406 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
410 json_object_object_add(json
, "exportRts", json_export_rtl
);
413 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
415 char buf1
[RD_ADDRSTRLEN
];
417 struct listnode
*node
, *nnode
;
418 struct ecommunity
*ecom
;
419 json_object
*json_import_rtl
= NULL
;
420 json_object
*json_export_rtl
= NULL
;
423 json_import_rtl
= json_object_new_array();
424 json_export_rtl
= json_object_new_array();
425 json_object_int_add(json
, "vni", vpn
->vni
);
426 json_object_string_add(json
, "type", "L2");
427 json_object_string_add(json
, "kernelFlag",
428 is_vni_live(vpn
) ? "Yes" : "No");
429 json_object_string_add(
431 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
432 json_object_string_add(json
, "originatorIp",
433 inet_ntoa(vpn
->originator_ip
));
434 json_object_string_add(json
, "advertiseGatewayMacip",
435 vpn
->advertise_gw_macip
? "Yes" : "No");
437 vty_out(vty
, "VNI: %d", vpn
->vni
);
438 if (is_vni_live(vpn
))
439 vty_out(vty
, " (known to the kernel)");
442 vty_out(vty
, " Type: %s\n", "L2");
443 vty_out(vty
, " Tenant-Vrf: %s\n",
444 vrf_id_to_name(vpn
->tenant_vrf_id
));
445 vty_out(vty
, " RD: %s\n",
446 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
447 vty_out(vty
, " Originator IP: %s\n",
448 inet_ntoa(vpn
->originator_ip
));
449 vty_out(vty
, " Advertise-gw-macip : %s\n",
450 vpn
->advertise_gw_macip
? "Yes" : "No");
454 vty_out(vty
, " Import Route Target:\n");
456 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
457 ecom_str
= ecommunity_ecom2str(ecom
,
458 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
461 json_object_array_add(json_import_rtl
,
462 json_object_new_string(ecom_str
));
464 vty_out(vty
, " %s\n", ecom_str
);
466 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
470 json_object_object_add(json
, "importRts", json_import_rtl
);
472 vty_out(vty
, " Export Route Target:\n");
474 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
475 ecom_str
= ecommunity_ecom2str(ecom
,
476 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
479 json_object_array_add(json_export_rtl
,
480 json_object_new_string(ecom_str
));
482 vty_out(vty
, " %s\n", ecom_str
);
484 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
488 json_object_object_add(json
, "exportRts", json_export_rtl
);
491 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
492 struct vty
*vty
, struct in_addr vtep_ip
,
498 u_int32_t prefix_cnt
, path_cnt
;
500 prefix_cnt
= path_cnt
= 0;
502 for (rn
= bgp_table_top(vpn
->route_table
); rn
;
503 rn
= bgp_route_next(rn
)) {
504 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
505 int add_prefix_to_json
= 0;
506 char prefix_str
[BUFSIZ
];
507 json_object
*json_paths
= NULL
;
508 json_object
*json_prefix
= NULL
;
510 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
513 if (type
&& evp
->prefix
.route_type
!= type
)
517 json_prefix
= json_object_new_object();
520 /* Overall header/legend displayed once. */
522 bgp_evpn_show_route_header(vty
, bgp
, json
);
530 json_paths
= json_object_new_array();
532 /* For EVPN, the prefix is displayed for each path (to fit in
533 * with code that already exists).
535 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
536 json_object
*json_path
= NULL
;
539 && !IPV4_ADDR_SAME(&(vtep_ip
),
540 &(ri
->attr
->nexthop
)))
544 json_path
= json_object_new_array();
546 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
, json_path
);
549 json_object_array_add(json_paths
, json_path
);
552 add_prefix_to_json
= 1;
555 if (json
&& add_prefix_to_json
) {
556 json_object_string_add(json_prefix
, "prefix",
558 json_object_int_add(json_prefix
, "prefixLen",
560 json_object_object_add(json_prefix
, "paths",
562 json_object_object_add(json
, prefix_str
, json_prefix
);
567 json_object_int_add(json
, "numPrefix", prefix_cnt
);
568 json_object_int_add(json
, "numPaths", path_cnt
);
571 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
572 type
? "(of requested type) " : "");
574 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s",
575 prefix_cnt
, path_cnt
,
576 type
? " (of requested type)" : "");
580 static void show_vni_routes_hash(struct hash_backet
*backet
, void *arg
)
582 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
583 struct vni_walk_ctx
*wctx
= arg
;
584 struct vty
*vty
= wctx
->vty
;
585 json_object
*json
= wctx
->json
;
586 json_object
*json_vni
= NULL
;
587 char vni_str
[VNI_STR_LEN
];
589 snprintf(vni_str
, VNI_STR_LEN
, "%d", vpn
->vni
);
591 json_vni
= json_object_new_object();
592 json_object_int_add(json_vni
, "vni", vpn
->vni
);
594 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
597 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
);
600 json_object_object_add(json
, vni_str
, json_vni
);
603 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
606 json_object
*json_vni
;
607 json_object
*json_import_rtl
;
608 json_object
*json_export_rtl
;
610 char buf2
[INET6_ADDRSTRLEN
];
613 struct listnode
*node
, *nnode
;
614 struct ecommunity
*ecom
;
620 json_vni
= json_object_new_object();
621 json_import_rtl
= json_object_new_array();
622 json_export_rtl
= json_object_new_array();
625 /* if an l3vni is present in bgp it is live */
630 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
631 json_object_string_add(json_vni
, "type", "L3");
632 json_object_string_add(json_vni
, "inKernel", "True");
633 json_object_string_add(json_vni
, "originatorIp",
634 inet_ntoa(bgp
->originator_ip
));
635 json_object_string_add(
637 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
639 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
640 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
643 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
644 ecom_str
= ecommunity_ecom2str(ecom
,
645 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
648 json_object_array_add(json_import_rtl
,
649 json_object_new_string(ecom_str
));
651 if (listcount(bgp
->vrf_import_rtl
) > 1)
652 sprintf(rt_buf
, "%s, ...", ecom_str
);
654 sprintf(rt_buf
, "%s", ecom_str
);
655 vty_out(vty
, " %-25s", rt_buf
);
658 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
660 /* If there are multiple import RTs we break here and show only
667 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
669 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
670 ecom_str
= ecommunity_ecom2str(ecom
,
671 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
674 json_object_array_add(json_export_rtl
,
675 json_object_new_string(ecom_str
));
677 if (listcount(bgp
->vrf_export_rtl
) > 1)
678 sprintf(rt_buf
, "%s, ...", ecom_str
);
680 sprintf(rt_buf
, "%s", ecom_str
);
681 vty_out(vty
, " %-25s", rt_buf
);
684 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
686 /* If there are multiple export RTs we break here and show only
693 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
696 char vni_str
[VNI_STR_LEN
];
698 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
699 snprintf(vni_str
, VNI_STR_LEN
, "%u", bgp
->l3vni
);
700 json_object_object_add(json
, vni_str
, json_vni
);
706 static void show_vni_entry(struct hash_backet
*backet
, void *args
[])
710 json_object
*json_vni
= NULL
;
711 json_object
*json_import_rtl
= NULL
;
712 json_object
*json_export_rtl
= NULL
;
713 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
715 char buf2
[RD_ADDRSTRLEN
];
718 struct listnode
*node
, *nnode
;
719 struct ecommunity
*ecom
;
725 json_vni
= json_object_new_object();
726 json_import_rtl
= json_object_new_array();
727 json_export_rtl
= json_object_new_array();
731 if (is_vni_live(vpn
))
735 json_object_int_add(json_vni
, "vni", vpn
->vni
);
736 json_object_string_add(json_vni
, "type", "L2");
737 json_object_string_add(json_vni
, "inKernel",
738 is_vni_live(vpn
) ? "True" : "False");
739 json_object_string_add(json_vni
, "originatorIp",
740 inet_ntoa(vpn
->originator_ip
));
741 json_object_string_add(json_vni
, "originatorIp",
742 inet_ntoa(vpn
->originator_ip
));
743 json_object_string_add(
745 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
747 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
748 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
751 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
752 ecom_str
= ecommunity_ecom2str(ecom
,
753 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
756 json_object_array_add(json_import_rtl
,
757 json_object_new_string(ecom_str
));
759 if (listcount(vpn
->import_rtl
) > 1)
760 sprintf(rt_buf
, "%s, ...", ecom_str
);
762 sprintf(rt_buf
, "%s", ecom_str
);
763 vty_out(vty
, " %-25s", rt_buf
);
766 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
768 /* If there are multiple import RTs we break here and show only
775 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
777 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
778 ecom_str
= ecommunity_ecom2str(ecom
,
779 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
782 json_object_array_add(json_export_rtl
,
783 json_object_new_string(ecom_str
));
785 if (listcount(vpn
->export_rtl
) > 1)
786 sprintf(rt_buf
, "%s, ...", ecom_str
);
788 sprintf(rt_buf
, "%s", ecom_str
);
789 vty_out(vty
, " %-25s", rt_buf
);
792 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
794 /* If there are multiple export RTs we break here and show only
801 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
804 char vni_str
[VNI_STR_LEN
];
806 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
807 snprintf(vni_str
, VNI_STR_LEN
, "%u", vpn
->vni
);
808 json_object_object_add(json
, vni_str
, json_vni
);
813 #endif /* HAVE_CUMULUS */
815 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
816 enum bgp_show_type type
, void *output_arg
,
817 int option
, u_char use_json
)
819 afi_t afi
= AFI_L2VPN
;
821 struct bgp_table
*table
;
828 unsigned long output_count
= 0;
829 unsigned long total_count
= 0;
830 json_object
*json
= NULL
;
831 json_object
*json_nroute
= NULL
;
832 json_object
*json_array
= NULL
;
833 json_object
*json_scode
= NULL
;
834 json_object
*json_ocode
= NULL
;
836 bgp
= bgp_get_default();
839 vty_out(vty
, "No BGP process is configured\n");
841 vty_out(vty
, "{}\n");
846 json_scode
= json_object_new_object();
847 json_ocode
= json_object_new_object();
848 json
= json_object_new_object();
849 json_nroute
= json_object_new_object();
851 json_object_string_add(json_scode
, "suppressed", "s");
852 json_object_string_add(json_scode
, "damped", "d");
853 json_object_string_add(json_scode
, "history", "h");
854 json_object_string_add(json_scode
, "valid", "*");
855 json_object_string_add(json_scode
, "best", ">");
856 json_object_string_add(json_scode
, "internal", "i");
858 json_object_string_add(json_ocode
, "igp", "i");
859 json_object_string_add(json_ocode
, "egp", "e");
860 json_object_string_add(json_ocode
, "incomplete", "?");
863 for (rn
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); rn
;
864 rn
= bgp_route_next(rn
)) {
866 continue; /* XXX json TODO */
868 if (prd
&& memcmp(rn
->p
.u
.val
, prd
->val
, 8) != 0)
871 if ((table
= rn
->info
) == NULL
)
876 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
))
877 for (ri
= rm
->info
; ri
; ri
= ri
->next
) {
879 if (type
== bgp_show_type_neighbor
) {
880 union sockunion
*su
= output_arg
;
882 if (ri
->peer
->su_remote
== NULL
884 ri
->peer
->su_remote
, su
))
890 == SHOW_DISPLAY_TAGS
) {
895 json_object_string_add(
900 json_object_object_add(
904 json_object_object_add(
910 if (option
== SHOW_DISPLAY_TAGS
)
915 == SHOW_DISPLAY_OVERLAY
)
920 "BGP table version is 0, local router ID is %s\n",
924 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
926 "Origin codes: i - IGP, e - EGP, ? - incomplete\n\n");
927 vty_out(vty
, V4_HEADER
);
940 /* Decode RD type. */
941 type
= decode_rd_type(pnt
);
942 /* Decode RD value. */
943 if (type
== RD_TYPE_AS
)
944 decode_rd_as(pnt
+ 2, &rd_as
);
945 else if (type
== RD_TYPE_AS4
)
946 decode_rd_as4(pnt
+ 2, &rd_as
);
947 else if (type
== RD_TYPE_IP
)
948 decode_rd_ip(pnt
+ 2, &rd_ip
);
951 if (type
== RD_TYPE_AS
952 || type
== RD_TYPE_AS4
)
953 sprintf(buffer
, "%u:%d",
956 else if (type
== RD_TYPE_IP
)
957 sprintf(buffer
, "%s:%d",
961 json_object_string_add(
963 "routeDistinguisher",
967 "Route Distinguisher: ");
968 if (type
== RD_TYPE_AS
)
973 else if (type
== RD_TYPE_AS4
)
978 else if (type
== RD_TYPE_IP
)
979 vty_out(vty
, "ip %s:%d",
983 vty_out(vty
, "\n\n");
988 json_array
= json_object_new_array();
991 if (option
== SHOW_DISPLAY_TAGS
)
992 route_vty_out_tag(vty
, &rm
->p
, ri
, 0,
995 else if (option
== SHOW_DISPLAY_OVERLAY
)
996 route_vty_out_overlay(vty
, &rm
->p
, ri
,
999 route_vty_out(vty
, &rm
->p
, ri
, 0,
1000 SAFI_EVPN
, json_array
);
1005 if (output_count
== 0)
1006 vty_out(vty
, "No prefixes displayed, %ld exist\n", total_count
);
1008 vty_out(vty
, "\nDisplayed %ld out of %ld total prefixes\n",
1009 output_count
, total_count
);
1013 DEFUN(show_ip_bgp_l2vpn_evpn
,
1014 show_ip_bgp_l2vpn_evpn_cmd
,
1015 "show [ip] bgp l2vpn evpn [json]",
1016 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1018 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1019 use_json(argc
, argv
));
1022 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1023 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1024 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1030 "Display information for a route distinguisher\n"
1031 "VPN Route Distinguisher\n" JSON_STR
)
1033 int idx_ext_community
= 0;
1035 struct prefix_rd prd
;
1037 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1039 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1041 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1044 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1045 use_json(argc
, argv
));
1048 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1049 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1050 "show [ip] bgp l2vpn evpn all tags",
1056 "Display information about all EVPN NLRIs\n"
1057 "Display BGP tags for prefixes\n")
1059 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1063 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1064 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1065 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1071 "Display information for a route distinguisher\n"
1072 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1074 int idx_ext_community
= 0;
1076 struct prefix_rd prd
;
1078 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1080 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1082 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1085 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1089 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_routes
,
1090 show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
,
1091 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D routes [json]",
1097 "Display information about all EVPN NLRIs\n"
1098 "Detailed information on TCP and BGP neighbor connections\n"
1099 "Neighbor to display information about\n"
1100 "Display routes learned from neighbor\n" JSON_STR
)
1106 u_char uj
= use_json(argc
, argv
);
1108 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1110 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1113 json_object
*json_no
= NULL
;
1114 json_no
= json_object_new_object();
1115 json_object_string_add(json_no
, "warning",
1116 "Malformed address");
1117 vty_out(vty
, "%s\n",
1118 json_object_to_json_string(json_no
));
1119 json_object_free(json_no
);
1121 vty_out(vty
, "Malformed address: %s\n",
1122 argv
[idx_ipv4
]->arg
);
1126 peer
= peer_lookup(NULL
, &su
);
1127 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1129 json_object
*json_no
= NULL
;
1130 json_no
= json_object_new_object();
1131 json_object_string_add(
1133 "No such neighbor or address family");
1134 vty_out(vty
, "%s\n",
1135 json_object_to_json_string(json_no
));
1136 json_object_free(json_no
);
1138 vty_out(vty
, "%% No such neighbor or address family\n");
1142 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, &su
, 0,
1146 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1147 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1148 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D routes [json]",
1154 "Display information for a route distinguisher\n"
1155 "VPN Route Distinguisher\n"
1156 "Detailed information on TCP and BGP neighbor connections\n"
1157 "Neighbor to display information about\n"
1158 "Display routes learned from neighbor\n" JSON_STR
)
1160 int idx_ext_community
= 0;
1165 struct prefix_rd prd
;
1166 u_char uj
= use_json(argc
, argv
);
1168 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1169 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1171 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1174 json_object
*json_no
= NULL
;
1175 json_no
= json_object_new_object();
1176 json_object_string_add(json_no
, "warning",
1177 "Malformed Route Distinguisher");
1178 vty_out(vty
, "%s\n",
1179 json_object_to_json_string(json_no
));
1180 json_object_free(json_no
);
1182 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1186 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1189 json_object
*json_no
= NULL
;
1190 json_no
= json_object_new_object();
1191 json_object_string_add(json_no
, "warning",
1192 "Malformed address");
1193 vty_out(vty
, "%s\n",
1194 json_object_to_json_string(json_no
));
1195 json_object_free(json_no
);
1197 vty_out(vty
, "Malformed address: %s\n",
1198 argv
[idx_ext_community
]->arg
);
1202 peer
= peer_lookup(NULL
, &su
);
1203 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1205 json_object
*json_no
= NULL
;
1206 json_no
= json_object_new_object();
1207 json_object_string_add(
1209 "No such neighbor or address family");
1210 vty_out(vty
, "%s\n",
1211 json_object_to_json_string(json_no
));
1212 json_object_free(json_no
);
1214 vty_out(vty
, "%% No such neighbor or address family\n");
1218 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, &su
, 0,
1222 DEFUN(show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes
,
1223 show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
,
1224 "show [ip] bgp l2vpn evpn all neighbors A.B.C.D advertised-routes [json]",
1230 "Display information about all EVPN NLRIs\n"
1231 "Detailed information on TCP and BGP neighbor connections\n"
1232 "Neighbor to display information about\n"
1233 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1239 u_char uj
= use_json(argc
, argv
);
1241 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1243 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1246 json_object
*json_no
= NULL
;
1247 json_no
= json_object_new_object();
1248 json_object_string_add(json_no
, "warning",
1249 "Malformed address");
1250 vty_out(vty
, "%s\n",
1251 json_object_to_json_string(json_no
));
1252 json_object_free(json_no
);
1254 vty_out(vty
, "Malformed address: %s\n",
1255 argv
[idx_ipv4
]->arg
);
1258 peer
= peer_lookup(NULL
, &su
);
1259 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1261 json_object
*json_no
= NULL
;
1262 json_no
= json_object_new_object();
1263 json_object_string_add(
1265 "No such neighbor or address family");
1266 vty_out(vty
, "%s\n",
1267 json_object_to_json_string(json_no
));
1268 json_object_free(json_no
);
1270 vty_out(vty
, "%% No such neighbor or address family\n");
1274 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1277 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1278 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1279 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors A.B.C.D advertised-routes [json]",
1285 "Display information for a route distinguisher\n"
1286 "VPN Route Distinguisher\n"
1287 "Detailed information on TCP and BGP neighbor connections\n"
1288 "Neighbor to display information about\n"
1289 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1291 int idx_ext_community
= 0;
1295 struct prefix_rd prd
;
1297 u_char uj
= use_json(argc
, argv
);
1299 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1300 argv_find(argv
, argc
, "A.B.C.D", &idx_ipv4
);
1302 ret
= str2sockunion(argv
[idx_ipv4
]->arg
, &su
);
1305 json_object
*json_no
= NULL
;
1306 json_no
= json_object_new_object();
1307 json_object_string_add(json_no
, "warning",
1308 "Malformed address");
1309 vty_out(vty
, "%s\n",
1310 json_object_to_json_string(json_no
));
1311 json_object_free(json_no
);
1313 vty_out(vty
, "Malformed address: %s\n",
1314 argv
[idx_ext_community
]->arg
);
1317 peer
= peer_lookup(NULL
, &su
);
1318 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1320 json_object
*json_no
= NULL
;
1321 json_no
= json_object_new_object();
1322 json_object_string_add(
1324 "No such neighbor or address family");
1325 vty_out(vty
, "%s\n",
1326 json_object_to_json_string(json_no
));
1327 json_object_free(json_no
);
1329 vty_out(vty
, "%% No such neighbor or address family\n");
1333 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1336 json_object
*json_no
= NULL
;
1337 json_no
= json_object_new_object();
1338 json_object_string_add(json_no
, "warning",
1339 "Malformed Route Distinguisher");
1340 vty_out(vty
, "%s\n",
1341 json_object_to_json_string(json_no
));
1342 json_object_free(json_no
);
1344 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1348 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1351 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1352 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1353 "show [ip] bgp l2vpn evpn all overlay",
1359 "Display information about all EVPN NLRIs\n"
1360 "Display BGP Overlay Information for prefixes\n")
1362 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1363 SHOW_DISPLAY_OVERLAY
,
1364 use_json(argc
, argv
));
1367 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1368 show_ip_bgp_evpn_rd_overlay_cmd
,
1369 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1375 "Display information for a route distinguisher\n"
1376 "VPN Route Distinguisher\n"
1377 "Display BGP Overlay Information for prefixes\n")
1379 int idx_ext_community
= 0;
1381 struct prefix_rd prd
;
1383 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1385 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1387 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1390 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1391 SHOW_DISPLAY_OVERLAY
,
1392 use_json(argc
, argv
));
1395 /* For testing purpose, static route of MPLS-VPN. */
1396 DEFUN(evpnrt5_network
,
1397 evpnrt5_network_cmd
,
1398 "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]",
1399 "Specify a network to announce via BGP\n"
1402 "Specify Route Distinguisher\n"
1403 "VPN Route Distinguisher\n"
1405 "Ethernet Tag Value\n"
1408 "Ethernet Segment Identifier\n"
1409 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1411 "Gateway IP ( A.B.C.D )\n"
1412 "Gateway IPv6 ( X:X::X:X )\n"
1413 "Router Mac Ext Comm\n"
1414 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1415 "Route-map to modify the attributes\n"
1416 "Name of the route map\n")
1418 int idx_ipv4_prefixlen
= 1;
1419 int idx_route_distinguisher
= 3;
1424 int idx_routermac
= 13;
1426 return bgp_static_set_safi(
1427 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1428 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1429 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1430 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1431 argv
[idx_routermac
]->arg
);
1434 /* For testing purpose, static route of MPLS-VPN. */
1435 DEFUN(no_evpnrt5_network
,
1436 no_evpnrt5_network_cmd
,
1437 "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>",
1439 "Specify a network to announce via BGP\n"
1442 "Specify Route Distinguisher\n"
1443 "VPN Route Distinguisher\n"
1445 "Ethernet Tag Value\n"
1448 "Ethernet Segment Identifier\n"
1449 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1450 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1452 int idx_ipv4_prefixlen
= 2;
1453 int idx_ext_community
= 4;
1458 return bgp_static_unset_safi(
1459 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1460 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1461 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1462 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1465 #if defined(HAVE_CUMULUS)
1467 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1469 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1472 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1474 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1478 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1479 * check that this is a change.
1481 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1482 struct ecommunity
*ecomadd
)
1484 /* If the VNI is "live", we need to uninstall routes using the current
1485 * import RT(s) first before we update the import RT, and subsequently
1488 if (is_vni_live(vpn
))
1489 bgp_evpn_uninstall_routes(bgp
, vpn
);
1491 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1492 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1494 /* If the auto route-target is in use we must remove it */
1495 evpn_import_rt_delete_auto(bgp
, vpn
);
1497 /* Add new RT and rebuild the RT to VNI mapping */
1498 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1500 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1501 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1503 /* Install routes that match new import RT */
1504 if (is_vni_live(vpn
))
1505 bgp_evpn_install_routes(bgp
, vpn
);
1509 * Unconfigure Import RT(s) for a VNI (vty handler).
1511 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1512 struct ecommunity
*ecomdel
)
1514 struct listnode
*node
, *nnode
, *node_to_del
;
1515 struct ecommunity
*ecom
;
1517 /* Along the lines of "configure" except we have to reset to the
1520 if (is_vni_live(vpn
))
1521 bgp_evpn_uninstall_routes(bgp
, vpn
);
1523 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1524 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1526 /* Delete all import RTs */
1527 if (ecomdel
== NULL
) {
1528 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
))
1529 ecommunity_free(&ecom
);
1531 list_delete_all_node(vpn
->import_rtl
);
1534 /* Delete a specific import RT */
1538 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1539 if (ecommunity_match(ecom
, ecomdel
)) {
1540 ecommunity_free(&ecom
);
1547 list_delete_node(vpn
->import_rtl
, node_to_del
);
1550 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
1551 if (list_isempty(vpn
->import_rtl
)) {
1552 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1553 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
1555 /* Rebuild the RT to VNI mapping */
1557 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1559 /* Install routes that match new import RT */
1560 if (is_vni_live(vpn
))
1561 bgp_evpn_install_routes(bgp
, vpn
);
1565 * Configure the Export RT for a VNI (vty handler). Caller expected to
1566 * check that this is a change. Note that only a single export RT is
1567 * allowed for a VNI and any change to configuration is implemented as
1568 * a "replace" (similar to other configuration).
1570 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1571 struct ecommunity
*ecomadd
)
1573 /* If the auto route-target is in use we must remove it */
1574 evpn_export_rt_delete_auto(bgp
, vpn
);
1576 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
1577 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1579 if (is_vni_live(vpn
))
1580 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1584 * Unconfigure the Export RT for a VNI (vty handler)
1586 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1587 struct ecommunity
*ecomdel
)
1589 struct listnode
*node
, *nnode
, *node_to_del
;
1590 struct ecommunity
*ecom
;
1592 /* Delete all export RTs */
1593 if (ecomdel
== NULL
) {
1594 /* Reset to default and process all routes. */
1595 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
))
1596 ecommunity_free(&ecom
);
1598 list_delete_all_node(vpn
->export_rtl
);
1601 /* Delete a specific export RT */
1605 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1606 if (ecommunity_match(ecom
, ecomdel
)) {
1607 ecommunity_free(&ecom
);
1614 list_delete_node(vpn
->export_rtl
, node_to_del
);
1617 if (list_isempty(vpn
->export_rtl
)) {
1618 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
1619 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
1622 if (is_vni_live(vpn
))
1623 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
1627 * Configure RD for VRF
1629 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
1631 /* If we have already advertise type-5 routes with a diffrent RD, we
1632 * have to delete and withdraw them firs
1634 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1637 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
1638 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
1640 /* We have a new RD for VRF.
1641 * Advertise all type-5 routes again with the new RD
1643 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1647 * Unconfigure RD for VRF
1649 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
1651 /* If we have already advertise type-5 routes with a diffrent RD, we
1652 * have to delete and withdraw them firs
1654 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
1656 /* fall back to default RD */
1657 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
1659 /* We have a new RD for VRF.
1660 * Advertise all type-5 routes again with the new RD
1662 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
1666 * Configure RD for a VNI (vty handler)
1668 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1669 struct prefix_rd
*rd
)
1671 /* If the VNI is "live", we need to delete and withdraw this VNI's
1672 * local routes with the prior RD first. Then, after updating RD,
1673 * need to re-advertise.
1675 if (is_vni_live(vpn
))
1676 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1679 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
1680 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
1682 if (is_vni_live(vpn
))
1683 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1687 * Unconfigure RD for a VNI (vty handler)
1689 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1691 /* If the VNI is "live", we need to delete and withdraw this VNI's
1692 * local routes with the prior RD first. Then, after resetting RD
1693 * to automatic value, need to re-advertise.
1695 if (is_vni_live(vpn
))
1696 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
1698 /* reset RD to default */
1699 bgp_evpn_derive_auto_rd(bgp
, vpn
);
1701 if (is_vni_live(vpn
))
1702 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
1706 * Create VNI, if not already present (VTY handler). Mark as configured.
1708 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
1710 struct bgpevpn
*vpn
;
1715 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1717 /* tenant vrf will be updated when we get local_vni_add from
1720 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0);
1723 "%u: Failed to allocate VNI entry for VNI %u - at Config",
1729 /* Mark as configured. */
1730 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1735 * Delete VNI. If VNI does not exist in the system (i.e., just
1736 * configuration), all that is needed is to free it. Otherwise,
1737 * any parameters configured for the VNI need to be reset (with
1738 * appropriate action) and the VNI marked as unconfigured; the
1739 * VNI will continue to exist, purely as a "learnt" entity.
1741 static int evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1743 assert(bgp
->vnihash
);
1745 if (!is_vni_live(vpn
)) {
1746 bgp_evpn_free(bgp
, vpn
);
1750 /* We need to take the unconfigure action for each parameter of this VNI
1751 * that is configured. Some optimization is possible, but not worth the
1752 * additional code for an operation that should be pretty rare.
1754 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
1756 /* First, deal with the export side - RD and export RT changes. */
1757 if (is_rd_configured(vpn
))
1758 evpn_unconfigure_rd(bgp
, vpn
);
1759 if (is_export_rt_configured(vpn
))
1760 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
1762 /* Next, deal with the import side. */
1763 if (is_import_rt_configured(vpn
))
1764 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
1770 * Display import RT mapping to VRFs (vty handler)
1771 * bgp_def: default bgp instance
1773 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_def
,
1781 hash_iterate(bgp_def
->vrf_import_rt_hash
,
1782 (void (*)(struct hash_backet
*,
1783 void *))show_vrf_import_rt_entry
,
1788 * Display import RT mapping to VNIs (vty handler)
1790 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
1799 bgp
->import_rt_hash
,
1800 (void (*)(struct hash_backet
*, void *))show_import_rt_entry
,
1805 * Display EVPN routes for all VNIs - vty handler.
1807 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
1808 struct in_addr vtep_ip
, json_object
*json
)
1811 struct vni_walk_ctx wctx
;
1813 num_vnis
= hashcount(bgp
->vnihash
);
1816 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
1819 wctx
.vtep_ip
= vtep_ip
;
1821 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_backet
*,
1822 void *))show_vni_routes_hash
,
1827 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
1829 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
1830 vni_t vni
, struct in_addr orig_ip
,
1833 struct bgpevpn
*vpn
;
1834 struct prefix_evpn p
;
1835 struct bgp_node
*rn
;
1836 struct bgp_info
*ri
;
1837 u_int32_t path_cnt
= 0;
1840 json_object
*json_paths
= NULL
;
1846 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1848 vty_out(vty
, "VNI not found\n");
1852 /* See if route exists. */
1853 build_evpn_type3_prefix(&p
, orig_ip
);
1854 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1855 if (!rn
|| !rn
->info
) {
1857 vty_out(vty
, "%% Network not in table\n");
1862 json_paths
= json_object_new_array();
1864 /* Prefix and num paths displayed once per prefix. */
1865 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1867 /* Display each path for this prefix. */
1868 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1869 json_object
*json_path
= NULL
;
1872 json_path
= json_object_new_array();
1874 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1878 json_object_array_add(json_paths
, json_path
);
1885 json_object_object_add(json
, "paths", json_paths
);
1887 json_object_int_add(json
, "numPaths", path_cnt
);
1889 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1895 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
1896 * By definition, only matching type-2 route will be displayed.
1898 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
1899 vni_t vni
, struct ethaddr
*mac
,
1900 struct ipaddr
*ip
, json_object
*json
)
1902 struct bgpevpn
*vpn
;
1903 struct prefix_evpn p
;
1904 struct bgp_node
*rn
;
1905 struct bgp_info
*ri
;
1906 u_int32_t path_cnt
= 0;
1909 json_object
*json_paths
= NULL
;
1915 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1918 vty_out(vty
, "VNI not found\n");
1922 /* See if route exists. Look for both non-sticky and sticky. */
1923 build_evpn_type2_prefix(&p
, mac
, ip
);
1924 rn
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
1925 if (!rn
|| !rn
->info
) {
1927 vty_out(vty
, "%% Network not in table\n");
1932 json_paths
= json_object_new_array();
1934 /* Prefix and num paths displayed once per prefix. */
1935 route_vty_out_detail_header(vty
, bgp
, rn
, NULL
, afi
, safi
, json
);
1937 /* Display each path for this prefix. */
1938 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
1939 json_object
*json_path
= NULL
;
1942 json_path
= json_object_new_array();
1944 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
1948 json_object_array_add(json_paths
, json_path
);
1955 json_object_object_add(json
, "paths", json_paths
);
1957 json_object_int_add(json
, "numPaths", path_cnt
);
1959 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
1965 * Display EVPN routes for a VNI - vty handler.
1966 * If 'type' is non-zero, only routes matching that type are shown.
1967 * If the vtep_ip is non zero, only routes behind that vtep are shown
1969 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
1970 int type
, struct in_addr vtep_ip
,
1973 struct bgpevpn
*vpn
;
1976 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
1979 vty_out(vty
, "VNI not found\n");
1983 /* Walk this VNI's route table and display appropriate routes. */
1984 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
);
1988 * Display BGP EVPN routing table -- for specific RD and MAC and/or
1989 * IP (vty handler). By definition, only matching type-2 route will be
1992 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
1993 struct prefix_rd
*prd
, struct ethaddr
*mac
,
1994 struct ipaddr
*ip
, json_object
*json
)
1996 struct prefix_evpn p
;
1997 struct bgp_node
*rn
;
1998 struct bgp_info
*ri
;
2001 u_int32_t path_cnt
= 0;
2002 json_object
*json_paths
= NULL
;
2003 char prefix_str
[BUFSIZ
];
2008 /* See if route exists. Look for both non-sticky and sticky. */
2009 build_evpn_type2_prefix(&p
, mac
, ip
);
2010 rn
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2011 (struct prefix
*)&p
, prd
);
2012 if (!rn
|| !rn
->info
) {
2014 vty_out(vty
, "%% Network not in table\n");
2018 bgp_evpn_route2str((struct prefix_evpn
*)&p
, prefix_str
,
2019 sizeof(prefix_str
));
2021 /* Prefix and num paths displayed once per prefix. */
2022 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
, safi
, json
);
2025 json_paths
= json_object_new_array();
2027 /* Display each path for this prefix. */
2028 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2029 json_object
*json_path
= NULL
;
2032 json_path
= json_object_new_array();
2034 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2038 json_object_array_add(json_paths
, json_path
);
2043 if (json
&& path_cnt
) {
2045 json_object_object_add(json
, prefix_str
, json_paths
);
2046 json_object_int_add(json
, "numPaths", path_cnt
);
2048 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2054 * Display BGP EVPN routing table -- for specific RD (vty handler)
2055 * If 'type' is non-zero, only routes matching that type are shown.
2057 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2058 struct prefix_rd
*prd
, int type
,
2061 struct bgp_node
*rd_rn
;
2062 struct bgp_table
*table
;
2063 struct bgp_node
*rn
;
2064 struct bgp_info
*ri
;
2068 u_int32_t prefix_cnt
, path_cnt
;
2069 char rd_str
[RD_ADDRSTRLEN
];
2070 json_object
*json_rd
= NULL
;
2071 int add_rd_to_json
= 0;
2075 prefix_cnt
= path_cnt
= 0;
2077 prefix_rd2str((struct prefix_rd
*)prd
, rd_str
, sizeof(rd_str
));
2079 rd_rn
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2083 table
= (struct bgp_table
*)rd_rn
->info
;
2088 json_rd
= json_object_new_object();
2089 json_object_string_add(json_rd
, "rd", rd_str
);
2092 /* Display all prefixes with this RD. */
2093 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2094 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2095 json_object
*json_prefix
= NULL
;
2096 json_object
*json_paths
= NULL
;
2097 char prefix_str
[BUFSIZ
];
2098 int add_prefix_to_json
= 0;
2100 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
, prefix_str
,
2101 sizeof(prefix_str
));
2103 if (type
&& evp
->prefix
.route_type
!= type
)
2107 json_prefix
= json_object_new_object();
2110 /* RD header and legend - once overall. */
2111 if (rd_header
&& !json
) {
2113 "EVPN type-2 prefix: [2]:[ESI]:[EthTag]:[MAClen]:[MAC]\n");
2115 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2117 "EVPN type-5 prefix: [5]:[ESI]:[EthTag]:[IPlen]:[IP]\n\n");
2121 /* Prefix and num paths displayed once per prefix. */
2122 route_vty_out_detail_header(vty
, bgp
, rn
, prd
, afi
,
2129 json_paths
= json_object_new_array();
2131 /* Display each path for this prefix. */
2132 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2133 json_object
*json_path
= NULL
;
2136 json_path
= json_object_new_array();
2138 route_vty_out_detail(vty
, bgp
, &rn
->p
, ri
, afi
, safi
,
2142 json_object_array_add(json_paths
, json_path
);
2145 add_prefix_to_json
= 1;
2149 if (json
&& add_prefix_to_json
) {
2150 json_object_object_add(json_prefix
, "paths",
2152 json_object_object_add(json_rd
, prefix_str
,
2157 if (json
&& add_rd_to_json
)
2158 json_object_object_add(json
, rd_str
, json_rd
);
2161 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2162 json_object_int_add(json
, "numPaths", path_cnt
);
2164 if (prefix_cnt
== 0)
2165 vty_out(vty
, "No prefixes exist with this RD%s\n",
2166 type
? " (of requested type)" : "");
2169 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2170 prefix_cnt
, path_cnt
,
2171 type
? " (of requested type)" : "");
2176 * Display BGP EVPN routing table - all routes (vty handler).
2177 * If 'type' is non-zero, only routes matching that type are shown.
2179 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2182 struct bgp_node
*rd_rn
;
2183 struct bgp_table
*table
;
2184 struct bgp_node
*rn
;
2185 struct bgp_info
*ri
;
2190 u_int32_t prefix_cnt
, path_cnt
;
2194 prefix_cnt
= path_cnt
= 0;
2196 /* EVPN routing table is a 2-level table with the first level being
2199 for (rd_rn
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_rn
;
2200 rd_rn
= bgp_route_next(rd_rn
)) {
2201 char rd_str
[RD_ADDRSTRLEN
];
2202 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2203 int add_rd_to_json
= 0;
2205 table
= (struct bgp_table
*)rd_rn
->info
;
2209 prefix_rd2str((struct prefix_rd
*)&rd_rn
->p
, rd_str
,
2213 json_rd
= json_object_new_object();
2214 json_object_string_add(json_rd
, "rd", rd_str
);
2219 /* Display all prefixes for an RD */
2220 for (rn
= bgp_table_top(table
); rn
; rn
= bgp_route_next(rn
)) {
2221 json_object
*json_prefix
=
2222 NULL
; /* contains prefix under a RD */
2223 json_object
*json_paths
=
2224 NULL
; /* array of paths under a prefix*/
2225 struct prefix_evpn
*evp
= (struct prefix_evpn
*)&rn
->p
;
2226 char prefix_str
[BUFSIZ
];
2227 int add_prefix_to_json
= 0;
2229 bgp_evpn_route2str((struct prefix_evpn
*)&rn
->p
,
2230 prefix_str
, sizeof(prefix_str
));
2232 if (type
&& evp
->prefix
.route_type
!= type
)
2236 /* Overall header/legend displayed once. */
2238 bgp_evpn_show_route_header(vty
, bgp
,
2243 /* RD header - per RD. */
2245 bgp_evpn_show_route_rd_header(
2254 json_prefix
= json_object_new_object();
2255 json_paths
= json_object_new_array();
2256 json_object_string_add(json_prefix
, "prefix",
2258 json_object_int_add(json_prefix
, "prefixLen",
2262 /* For EVPN, the prefix is displayed for each path (to
2264 * with code that already exists).
2266 for (ri
= rn
->info
; ri
; ri
= ri
->next
) {
2267 json_object
*json_path
= NULL
;
2269 add_prefix_to_json
= 1;
2273 json_path
= json_object_new_array();
2275 route_vty_out(vty
, &rn
->p
, ri
, 0, SAFI_EVPN
,
2279 json_object_array_add(json_paths
,
2283 if (json
&& add_prefix_to_json
) {
2284 json_object_object_add(json_prefix
, "paths",
2286 json_object_object_add(json_rd
, prefix_str
,
2291 if (json
&& add_rd_to_json
)
2292 json_object_object_add(json
, rd_str
, json_rd
);
2296 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2297 json_object_int_add(json
, "numPaths", path_cnt
);
2299 if (prefix_cnt
== 0) {
2300 vty_out(vty
, "No EVPN prefixes %sexist\n",
2301 type
? "(of requested type) " : "");
2303 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2304 prefix_cnt
, path_cnt
,
2305 type
? " (of requested type)" : "");
2311 * Display specified VNI (vty handler)
2313 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2317 struct bgpevpn
*vpn
;
2319 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2322 display_vni(vty
, vpn
, json
);
2324 struct bgp
*bgp_temp
;
2325 struct listnode
*node
= NULL
;
2327 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2328 if (bgp_temp
->l3vni
== vni
) {
2330 display_l3vni(vty
, bgp_temp
, json
);
2337 vty_out(vty
, "{}\n");
2339 vty_out(vty
, "VNI not found\n");
2346 * Display a VNI (upon user query).
2348 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2352 struct bgp
*bgp_temp
= NULL
;
2353 struct listnode
*node
;
2357 vty_out(vty
, "Flags: * - Kernel\n");
2358 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2359 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2362 /* print all L2 VNIS */
2365 hash_iterate(bgp
->vnihash
,
2366 (void (*)(struct hash_backet
*, void *))show_vni_entry
,
2369 /* print all L3 VNIs */
2370 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2371 show_l3vni_entry(vty
, bgp_temp
, json
);
2375 * evpn - enable advertisement of default g/w
2377 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2380 if (bgp
->advertise_gw_macip
)
2383 bgp
->advertise_gw_macip
= 1;
2384 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2386 if (vpn
->advertise_gw_macip
)
2389 vpn
->advertise_gw_macip
= 1;
2390 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2397 * evpn - disable advertisement of default g/w
2399 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2400 struct bgpevpn
*vpn
)
2403 if (!bgp
->advertise_gw_macip
)
2406 bgp
->advertise_gw_macip
= 0;
2407 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2409 if (!vpn
->advertise_gw_macip
)
2412 vpn
->advertise_gw_macip
= 0;
2413 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2420 * evpn - enable advertisement of default g/w
2422 static void evpn_set_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2424 if (vpn
->advertise_subnet
)
2427 vpn
->advertise_subnet
= 1;
2428 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2432 * evpn - disable advertisement of default g/w
2434 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2436 if (!vpn
->advertise_subnet
)
2439 vpn
->advertise_subnet
= 0;
2440 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
2444 * EVPN (VNI advertisement) enabled. Register with zebra.
2446 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
2448 bgp
->advertise_all_vni
= 1;
2449 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2453 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
2454 * cache, EVPN routes (delete and withdraw from peers).
2456 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
2458 bgp
->advertise_all_vni
= 0;
2459 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
2460 bgp_evpn_cleanup_on_disable(bgp
);
2462 #endif /* HAVE_CUMULUS */
2464 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
2466 char buf1
[RD_ADDRSTRLEN
];
2468 struct listnode
*node
, *nnode
;
2469 struct ecommunity
*ecom
;
2471 if (is_vni_configured(vpn
)) {
2472 vty_out(vty
, " vni %d\n", vpn
->vni
);
2473 if (is_rd_configured(vpn
))
2474 vty_out(vty
, " rd %s\n",
2475 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
2477 if (is_import_rt_configured(vpn
)) {
2478 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
2480 ecom_str
= ecommunity_ecom2str(
2481 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2482 vty_out(vty
, " route-target import %s\n",
2484 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2488 if (is_export_rt_configured(vpn
)) {
2489 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
2491 ecom_str
= ecommunity_ecom2str(
2492 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
2493 vty_out(vty
, " route-target export %s\n",
2495 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
2499 if (vpn
->advertise_gw_macip
)
2500 vty_out(vty
, " advertise-default-gw\n");
2502 if (vpn
->advertise_subnet
)
2503 vty_out(vty
, " advertise-subnet\n");
2505 vty_out(vty
, " exit-vni\n");
2509 static void write_vni_config_for_entry(struct hash_backet
*backet
,
2512 struct bgpevpn
*vpn
= (struct bgpevpn
*)backet
->data
;
2513 write_vni_config(vty
, vpn
);
2516 #if defined(HAVE_CUMULUS)
2517 DEFUN (bgp_evpn_advertise_default_gw_vni
,
2518 bgp_evpn_advertise_default_gw_vni_cmd
,
2519 "advertise-default-gw",
2520 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
2522 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2523 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2531 evpn_set_advertise_default_gw(bgp
, vpn
);
2536 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
2537 no_bgp_evpn_advertise_default_gw_vni_cmd
,
2538 "no advertise-default-gw",
2540 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
2542 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2543 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2551 evpn_unset_advertise_default_gw(bgp
, vpn
);
2557 DEFUN (bgp_evpn_advertise_default_gw
,
2558 bgp_evpn_advertise_default_gw_cmd
,
2559 "advertise-default-gw",
2560 "Advertise All default g/w mac-ip routes in EVPN\n")
2562 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2567 evpn_set_advertise_default_gw(bgp
, NULL
);
2572 DEFUN (no_bgp_evpn_advertise_default_gw
,
2573 no_bgp_evpn_advertise_default_gw_cmd
,
2574 "no advertise-default-gw",
2576 "Withdraw All default g/w mac-ip routes from EVPN\n")
2578 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2583 evpn_unset_advertise_default_gw(bgp
, NULL
);
2588 DEFUN (bgp_evpn_advertise_all_vni
,
2589 bgp_evpn_advertise_all_vni_cmd
,
2590 "advertise-all-vni",
2591 "Advertise All local VNIs\n")
2593 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2597 evpn_set_advertise_all_vni(bgp
);
2601 DEFUN (no_bgp_evpn_advertise_all_vni
,
2602 no_bgp_evpn_advertise_all_vni_cmd
,
2603 "no advertise-all-vni",
2605 "Advertise All local VNIs\n")
2607 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2611 evpn_unset_advertise_all_vni(bgp
);
2615 DEFUN (bgp_evpn_advertise_vni_subnet
,
2616 bgp_evpn_advertise_vni_subnet_cmd
,
2618 "Advertise the subnet corresponding to VNI\n")
2620 struct bgp
*bgp_vrf
= NULL
;
2621 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2622 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2630 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
2634 if (!(advertise_type5_routes(bgp_vrf
, AFI_IP
)
2635 || advertise_type5_routes(bgp_vrf
, AFI_IP6
))) {
2637 "%%Please enable ip prefix advertisement under l2vpn evpn in %s",
2638 vrf_id_to_name(bgp_vrf
->vrf_id
));
2642 evpn_set_advertise_subnet(bgp
, vpn
);
2646 DEFUN (no_bgp_evpn_advertise_vni_subnet
,
2647 no_bgp_evpn_advertise_vni_subnet_cmd
,
2648 "no advertise-subnet",
2650 "Advertise All local VNIs\n")
2652 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
2653 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
2661 evpn_unset_advertise_subnet(bgp
, vpn
);
2665 DEFUN (bgp_evpn_advertise_type5
,
2666 bgp_evpn_advertise_type5_cmd
,
2667 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
2668 "Advertise prefix routes\n"
2671 "route-map for filtering specific routes\n"
2672 "Name of the route map\n")
2674 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
2681 int rmap_changed
= 0;
2683 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2684 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
2685 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
2687 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
2689 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
2690 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
2693 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
2697 if (!(afi
== AFI_IP
) || (afi
== AFI_IP6
)) {
2699 "%%only ipv4 or ipv6 address families are supported");
2703 if (safi
!= SAFI_UNICAST
) {
2705 "%%only ipv4 unicast or ipv6 unicast are supported");
2709 if (afi
== AFI_IP
) {
2711 /* if we are already advertising ipv4 prefix as type-5
2714 if (!rmap_changed
&& CHECK_FLAG(bgp_vrf
->vrf_flags
,
2715 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
))
2717 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_ADVERTISE_IPV4_IN_EVPN
);
2720 /* if we are already advertising ipv6 prefix as type-5
2723 if (!rmap_changed
&& CHECK_FLAG(bgp_vrf
->vrf_flags
,
2724 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
))
2726 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_ADVERTISE_IPV6_IN_EVPN
);
2730 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
2731 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
2732 XFREE(MTYPE_ROUTE_MAP_NAME
,
2733 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
2734 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
2735 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
2739 /* set the route-map for advertise command */
2740 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
2741 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
2742 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
2743 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
2744 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
2747 /* advertise type-5 routes */
2748 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
2752 DEFUN (no_bgp_evpn_advertise_type5
,
2753 no_bgp_evpn_advertise_type5_cmd
,
2754 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
2756 "Advertise prefix routes\n"
2760 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
2766 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
2767 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
2769 if (!(afi
== AFI_IP
) || (afi
== AFI_IP6
)) {
2771 "%%only ipv4 or ipv6 address families are supported");
2775 if (safi
!= SAFI_UNICAST
) {
2777 "%%only ipv4 unicast or ipv6 unicast are supported");
2781 if (afi
== AFI_IP
) {
2783 /* if we are already advertising ipv4 prefix as type-5
2786 if (CHECK_FLAG(bgp_vrf
->vrf_flags
,
2787 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
)) {
2788 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
2789 UNSET_FLAG(bgp_vrf
->vrf_flags
,
2790 BGP_VRF_ADVERTISE_IPV4_IN_EVPN
);
2794 /* if we are already advertising ipv6 prefix as type-5
2797 if (CHECK_FLAG(bgp_vrf
->vrf_flags
,
2798 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
)) {
2799 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
2800 UNSET_FLAG(bgp_vrf
->vrf_flags
,
2801 BGP_VRF_ADVERTISE_IPV6_IN_EVPN
);
2805 /* clear the route-map information for advertise ipv4/ipv6 unicast */
2806 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
2807 XFREE(MTYPE_ROUTE_MAP_NAME
,
2808 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
2809 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
2810 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
2817 * Display VNI information - for all or a specific VNI
2819 DEFUN(show_bgp_l2vpn_evpn_vni
,
2820 show_bgp_l2vpn_evpn_vni_cmd
,
2821 "show bgp l2vpn evpn vni [(1-16777215)] [json]",
2830 struct bgp
*bgp_def
;
2834 json_object
*json
= NULL
;
2835 u_int32_t num_l2vnis
= 0;
2836 u_int32_t num_l3vnis
= 0;
2837 uint32_t num_vnis
= 0;
2838 struct listnode
*node
= NULL
;
2839 struct bgp
*bgp_temp
= NULL
;
2841 uj
= use_json(argc
, argv
);
2843 bgp_def
= bgp_get_default();
2847 if (!argv_find(argv
, argc
, "evpn", &idx
))
2851 json
= json_object_new_object();
2853 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
2855 num_l2vnis
= hashcount(bgp_def
->vnihash
);
2857 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2858 if (bgp_temp
->l3vni
)
2861 num_vnis
= num_l2vnis
+ num_l3vnis
;
2863 json_object_string_add(json
, "advertiseGatewayMacip",
2864 bgp_def
->advertise_gw_macip
2867 json_object_string_add(json
, "advertiseAllVnis",
2868 is_evpn_enabled() ? "Enabled"
2870 json_object_int_add(json
, "numVnis", num_vnis
);
2871 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
2872 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
2874 vty_out(vty
, "Advertise Gateway Macip: %s\n",
2875 bgp_def
->advertise_gw_macip
? "Enabled"
2877 vty_out(vty
, "Advertise All VNI flag: %s\n",
2878 is_evpn_enabled() ? "Enabled" : "Disabled");
2879 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
2880 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
2882 evpn_show_all_vnis(vty
, bgp_def
, json
);
2886 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
2889 /* Display specific VNI */
2890 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
2891 evpn_show_vni(vty
, bgp_def
, vni
, json
);
2895 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2896 json
, JSON_C_TO_STRING_PRETTY
));
2897 json_object_free(json
);
2904 * Display EVPN neighbor summary.
2906 DEFUN(show_bgp_l2vpn_evpn_summary
,
2907 show_bgp_l2vpn_evpn_summary_cmd
,
2908 "show bgp [vrf VRFNAME] l2vpn evpn summary [json]",
2915 "Summary of BGP neighbor status\n"
2919 u_char uj
= use_json(argc
, argv
);
2922 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
2923 vrf
= argv
[++idx_vrf
]->arg
;
2924 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, uj
);
2928 * Display global EVPN routing table.
2930 DEFUN(show_bgp_l2vpn_evpn_route
,
2931 show_bgp_l2vpn_evpn_route_cmd
,
2932 "show bgp l2vpn evpn route [type <macip|multicast|prefix>] [json]",
2937 "EVPN route information\n"
2938 "Specify Route type\n"
2939 "MAC-IP (Type-2) route\n"
2940 "Multicast (Type-3) route\n"
2948 json_object
*json
= NULL
;
2950 uj
= use_json(argc
, argv
);
2952 bgp
= bgp_get_default();
2957 json
= json_object_new_object();
2960 if (argv_find(argv
, argc
, "type", &type_idx
)) {
2961 /* Specific type is requested */
2962 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
2963 type
= BGP_EVPN_MAC_IP_ROUTE
;
2964 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
2965 type
= BGP_EVPN_IMET_ROUTE
;
2966 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
2967 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
2972 evpn_show_all_routes(vty
, bgp
, type
, json
);
2975 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
2976 json
, JSON_C_TO_STRING_PRETTY
));
2977 json_object_free(json
);
2983 * Display global EVPN routing table for specific RD.
2985 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
2986 show_bgp_l2vpn_evpn_route_rd_cmd
,
2987 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast|prefix>] [json]",
2992 "EVPN route information\n"
2993 "Route Distinguisher\n"
2994 "ASN:XX or A.B.C.D:XX\n"
2995 "Specify Route type\n"
2996 "MAC-IP (Type-2) route\n"
2997 "Multicast (Type-3) route\n"
3003 struct prefix_rd prd
;
3008 json_object
*json
= NULL
;
3010 bgp
= bgp_get_default();
3014 /* check if we need json output */
3015 uj
= use_json(argc
, argv
);
3017 json
= json_object_new_object();
3020 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3021 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3024 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3030 if (argv_find(argv
, argc
, "type", &type_idx
)) {
3031 /* Specific type is requested */
3032 if (strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
3033 type
= BGP_EVPN_MAC_IP_ROUTE
;
3034 else if (strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
3035 type
= BGP_EVPN_IMET_ROUTE
;
3036 else if (strncmp(argv
[type_idx
+ 1]->arg
, "pr", 2) == 0)
3037 type
= BGP_EVPN_IP_PREFIX_ROUTE
;
3042 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
3045 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3046 json
, JSON_C_TO_STRING_PRETTY
));
3047 json_object_free(json
);
3054 * Display global EVPN routing table for specific RD and MACIP.
3056 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
3057 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
3058 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
3063 "EVPN route information\n"
3064 "Route Distinguisher\n"
3065 "ASN:XX or A.B.C.D:XX\n"
3067 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3069 "IP address (IPv4 or IPv6)\n"
3074 struct prefix_rd prd
;
3081 json_object
*json
= NULL
;
3083 memset(&mac
, 0, sizeof(struct ethaddr
));
3084 memset(&ip
, 0, sizeof(struct ipaddr
));
3086 bgp
= bgp_get_default();
3090 /* check if we need json output */
3091 uj
= use_json(argc
, argv
);
3093 json
= json_object_new_object();
3096 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
3097 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
3099 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3105 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
3106 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
3107 vty_out(vty
, "%% Malformed MAC address\n");
3112 /* get the ip if specified */
3113 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
3114 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
3115 vty_out(vty
, "%% Malformed IP address\n");
3120 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
3123 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3124 json
, JSON_C_TO_STRING_PRETTY
));
3125 json_object_free(json
);
3132 * Display per-VNI EVPN routing table.
3134 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
3135 "show bgp l2vpn evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>] [json]",
3140 "EVPN route information\n"
3141 "VXLAN Network Identifier\n"
3143 "Specify Route type\n"
3144 "MAC-IP (Type-2) route\n"
3145 "Multicast (Type-3) route\n"
3147 "Remote VTEP IP address\n"
3152 struct in_addr vtep_ip
;
3156 json_object
*json
= NULL
;
3158 bgp
= bgp_get_default();
3162 /* check if we need json output */
3163 uj
= use_json(argc
, argv
);
3165 json
= json_object_new_object();
3167 if (!argv_find(argv
, argc
, "evpn", &idx
))
3172 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3174 if ((!uj
&& ((argc
== (idx
+ 1 + 5)) && argv
[idx
+ 4]->arg
))
3175 || (uj
&& ((argc
== (idx
+ 1 + 6)) && argv
[idx
+ 4]->arg
))) {
3176 if (strncmp(argv
[idx
+ 4]->arg
, "type", 4) == 0) {
3177 if (strncmp(argv
[idx
+ 5]->arg
, "ma", 2) == 0)
3178 type
= BGP_EVPN_MAC_IP_ROUTE
;
3179 else if (strncmp(argv
[idx
+ 5]->arg
, "mu", 2) == 0)
3180 type
= BGP_EVPN_IMET_ROUTE
;
3183 } else if (strncmp(argv
[idx
+ 4]->arg
, "vtep", 4) == 0) {
3184 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3185 vty_out(vty
, "%% Malformed VTEP IP address\n");
3192 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
3195 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3196 json
, JSON_C_TO_STRING_PRETTY
));
3197 json_object_free(json
);
3204 * Display per-VNI EVPN routing table for specific MACIP.
3206 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
3207 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
3208 "show bgp l2vpn evpn route vni (1-16777215) mac WORD [ip WORD] [json]",
3213 "EVPN route information\n"
3214 "VXLAN Network Identifier\n"
3217 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3219 "IP address (IPv4 or IPv6)\n"
3228 json_object
*json
= NULL
;
3230 bgp
= bgp_get_default();
3234 /* check if we need json output */
3235 uj
= use_json(argc
, argv
);
3237 json
= json_object_new_object();
3239 if (!argv_find(argv
, argc
, "evpn", &idx
))
3243 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3246 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
3247 vty_out(vty
, "%% Malformed MAC address\n");
3252 memset(&ip
, 0, sizeof(ip
));
3253 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
3255 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
3256 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
3257 vty_out(vty
, "%% Malformed IP address\n");
3262 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
3265 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3266 json
, JSON_C_TO_STRING_PRETTY
));
3267 json_object_free(json
);
3274 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
3276 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3277 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
3278 "show bgp l2vpn evpn route vni (1-16777215) multicast A.B.C.D [json]",
3283 "EVPN route information\n"
3284 "VXLAN Network Identifier\n"
3286 "Multicast (Type-3) route\n"
3287 "Originating Router IP address\n"
3293 struct in_addr orig_ip
;
3296 json_object
*json
= NULL
;
3298 bgp
= bgp_get_default();
3302 /* check if we need json output */
3303 uj
= use_json(argc
, argv
);
3305 json
= json_object_new_object();
3307 if (!argv_find(argv
, argc
, "evpn", &idx
))
3311 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
3314 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
3316 vty_out(vty
, "%% Malformed Originating Router IP address\n");
3320 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
3323 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3324 json
, JSON_C_TO_STRING_PRETTY
));
3325 json_object_free(json
);
3332 * Display per-VNI EVPN routing table - for all VNIs.
3334 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
3335 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
3336 "show bgp l2vpn evpn route vni all [vtep A.B.C.D] [json]",
3341 "EVPN route information\n"
3342 "VXLAN Network Identifier\n"
3345 "Remote VTEP IP address\n"
3349 struct in_addr vtep_ip
;
3352 json_object
*json
= NULL
;
3354 bgp
= bgp_get_default();
3358 /* check if we need json output */
3359 uj
= use_json(argc
, argv
);
3361 json
= json_object_new_object();
3363 if (!argv_find(argv
, argc
, "evpn", &idx
))
3367 if ((!uj
&& (argc
== (idx
+ 1 + 5) && argv
[idx
+ 5]->arg
))
3368 || (uj
&& (argc
== (idx
+ 1 + 6) && argv
[idx
+ 5]->arg
))) {
3369 if (!inet_aton(argv
[idx
+ 5]->arg
, &vtep_ip
)) {
3370 vty_out(vty
, "%% Malformed VTEP IP address\n");
3375 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
);
3378 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3379 json
, JSON_C_TO_STRING_PRETTY
));
3380 json_object_free(json
);
3387 * Display EVPN import route-target hash table
3389 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
3390 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
3391 "show bgp l2vpn evpn vrf-import-rt [json]",
3396 "Show vrf import route target\n"
3400 struct bgp
*bgp_def
= NULL
;
3401 json_object
*json
= NULL
;
3403 bgp_def
= bgp_get_default();
3407 uj
= use_json(argc
, argv
);
3409 json
= json_object_new_object();
3411 evpn_show_vrf_import_rts(vty
, bgp_def
, json
);
3414 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3415 json
, JSON_C_TO_STRING_PRETTY
));
3416 json_object_free(json
);
3423 * Display EVPN import route-target hash table
3425 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
3426 show_bgp_l2vpn_evpn_import_rt_cmd
,
3427 "show bgp l2vpn evpn import-rt [json]",
3432 "Show import route target\n"
3437 json_object
*json
= NULL
;
3439 bgp
= bgp_get_default();
3443 uj
= use_json(argc
, argv
);
3445 json
= json_object_new_object();
3447 evpn_show_import_rts(vty
, bgp
, json
);
3450 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3451 json
, JSON_C_TO_STRING_PRETTY
));
3452 json_object_free(json
);
3458 #if defined(HAVE_CUMULUS)
3459 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
3460 "show bgp evpn vni [(1-16777215)]", SHOW_STR BGP_STR EVPN_HELP_STR
3464 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
3465 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
3466 "Summary of BGP neighbor status\n" JSON_STR
)
3468 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
3469 "show bgp evpn route [type <macip|multicast>]",
3470 SHOW_STR BGP_STR EVPN_HELP_STR
3471 "EVPN route information\n"
3472 "Specify Route type\n"
3473 "MAC-IP (Type-2) route\n"
3474 "Multicast (Type-3) route\n")
3477 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
3478 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|multicast>]",
3479 SHOW_STR BGP_STR EVPN_HELP_STR
3480 "EVPN route information\n"
3481 "Route Distinguisher\n"
3482 "ASN:XX or A.B.C.D:XX\n"
3483 "Specify Route type\n"
3484 "MAC-IP (Type-2) route\n"
3485 "Multicast (Type-3) route\n")
3488 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
3489 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
3490 SHOW_STR BGP_STR EVPN_HELP_STR
3491 "EVPN route information\n"
3492 "Route Distinguisher\n"
3493 "ASN:XX or A.B.C.D:XX\n"
3495 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3497 "IP address (IPv4 or IPv6)\n")
3500 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
3501 "show bgp evpn route vni (1-16777215) [<type <macip|multicast> | vtep A.B.C.D>]",
3502 SHOW_STR BGP_STR EVPN_HELP_STR
3503 "EVPN route information\n"
3504 "VXLAN Network Identifier\n"
3506 "Specify Route type\n"
3507 "MAC-IP (Type-2) route\n"
3508 "Multicast (Type-3) route\n"
3510 "Remote VTEP IP address\n")
3512 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
3513 show_bgp_evpn_route_vni_macip_cmd
,
3514 "show bgp evpn route vni (1-16777215) mac WORD [ip WORD]",
3515 SHOW_STR BGP_STR EVPN_HELP_STR
3516 "EVPN route information\n"
3517 "VXLAN Network Identifier\n"
3520 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3522 "IP address (IPv4 or IPv6)\n")
3524 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
3525 show_bgp_evpn_route_vni_multicast_cmd
,
3526 "show bgp evpn route vni (1-16777215) multicast A.B.C.D",
3527 SHOW_STR BGP_STR EVPN_HELP_STR
3528 "EVPN route information\n"
3529 "VXLAN Network Identifier\n"
3531 "Multicast (Type-3) route\n"
3532 "Originating Router IP address\n")
3534 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
3535 "show bgp evpn route vni all [vtep A.B.C.D]",
3536 SHOW_STR BGP_STR EVPN_HELP_STR
3537 "EVPN route information\n"
3538 "VXLAN Network Identifier\n"
3541 "Remote VTEP IP address\n")
3543 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
3544 "show bgp evpn import-rt",
3545 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
3548 DEFUN_NOSH (bgp_evpn_vni
,
3551 "VXLAN Network Identifier\n"
3555 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3556 struct bgpevpn
*vpn
;
3561 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
3563 /* Create VNI, or mark as configured. */
3564 vpn
= evpn_create_update_vni(bgp
, vni
);
3566 vty_out(vty
, "%% Failed to create VNI \n");
3570 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
3574 DEFUN (no_bgp_evpn_vni
,
3575 no_bgp_evpn_vni_cmd
,
3576 "no vni (1-16777215)",
3578 "VXLAN Network Identifier\n"
3582 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3583 struct bgpevpn
*vpn
;
3588 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3590 /* Check if we should disallow. */
3591 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
3593 vty_out(vty
, "%% Specified VNI does not exist\n");
3596 if (!is_vni_configured(vpn
)) {
3597 vty_out(vty
, "%% Specified VNI is not configured\n");
3601 evpn_delete_vni(bgp
, vpn
);
3605 DEFUN_NOSH (exit_vni
,
3608 "Exit from VNI mode\n")
3610 if (vty
->node
== BGP_EVPN_VNI_NODE
)
3611 vty
->node
= BGP_EVPN_NODE
;
3615 DEFUN (bgp_evpn_vrf_rd
,
3616 bgp_evpn_vrf_rd_cmd
,
3617 "rd ASN:NN_OR_IP-ADDRESS:NN",
3618 "Route Distinguisher\n"
3619 "ASN:XX or A.B.C.D:XX\n")
3622 struct prefix_rd prd
;
3623 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3628 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3630 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3634 /* If same as existing value, there is nothing more to do. */
3635 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
3638 /* Configure or update the RD. */
3639 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
3643 DEFUN (no_bgp_evpn_vrf_rd
,
3644 no_bgp_evpn_vrf_rd_cmd
,
3645 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3647 "Route Distinguisher\n"
3648 "ASN:XX or A.B.C.D:XX\n")
3651 struct prefix_rd prd
;
3652 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3657 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3659 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3663 /* Check if we should disallow. */
3664 if (!is_vrf_rd_configured(bgp_vrf
)) {
3665 vty_out(vty
, "%% RD is not configured for this VRF\n");
3669 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
3671 "%% RD specified does not match configuration for this VRF\n");
3675 evpn_unconfigure_vrf_rd(bgp_vrf
);
3679 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
3680 no_bgp_evpn_vrf_rd_without_val_cmd
,
3683 "Route Distinguisher\n")
3685 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3690 /* Check if we should disallow. */
3691 if (!is_vrf_rd_configured(bgp_vrf
)) {
3692 vty_out(vty
, "%% RD is not configured for this VRF\n");
3696 evpn_unconfigure_vrf_rd(bgp_vrf
);
3700 DEFUN (bgp_evpn_vni_rd
,
3701 bgp_evpn_vni_rd_cmd
,
3702 "rd ASN:NN_OR_IP-ADDRESS:NN",
3703 "Route Distinguisher\n"
3704 "ASN:XX or A.B.C.D:XX\n")
3706 struct prefix_rd prd
;
3707 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3708 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3714 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
3716 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3720 /* If same as existing value, there is nothing more to do. */
3721 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
3724 /* Configure or update the RD. */
3725 evpn_configure_rd(bgp
, vpn
, &prd
);
3729 DEFUN (no_bgp_evpn_vni_rd
,
3730 no_bgp_evpn_vni_rd_cmd
,
3731 "no rd ASN:NN_OR_IP-ADDRESS:NN",
3733 "Route Distinguisher\n"
3734 "ASN:XX or A.B.C.D:XX\n")
3736 struct prefix_rd prd
;
3737 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3738 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3744 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
3746 vty_out(vty
, "%% Malformed Route Distinguisher\n");
3750 /* Check if we should disallow. */
3751 if (!is_rd_configured(vpn
)) {
3752 vty_out(vty
, "%% RD is not configured for this VNI\n");
3756 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
3758 "%% RD specified does not match configuration for this VNI\n");
3762 evpn_unconfigure_rd(bgp
, vpn
);
3766 DEFUN (no_bgp_evpn_vni_rd_without_val
,
3767 no_bgp_evpn_vni_rd_without_val_cmd
,
3770 "Route Distinguisher\n")
3772 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3773 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3778 /* Check if we should disallow. */
3779 if (!is_rd_configured(vpn
)) {
3780 vty_out(vty
, "%% RD is not configured for this VNI\n");
3784 evpn_unconfigure_rd(bgp
, vpn
);
3789 * Loop over all extended-communities in the route-target list rtl and
3790 * return 1 if we find ecomtarget
3792 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
3793 struct ecommunity
*ecomtarget
)
3795 struct listnode
*node
, *nnode
;
3796 struct ecommunity
*ecom
;
3798 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
3799 if (ecommunity_match(ecom
, ecomtarget
))
3806 /* display L3VNI related info for a VRF instance */
3807 DEFUN (show_bgp_vrf_l3vni_info
,
3808 show_bgp_vrf_l3vni_info_cmd
,
3809 "show bgp vrf VRFNAME vni [json]",
3817 char buf
[ETHER_ADDR_STRLEN
];
3818 char buf1
[INET6_ADDRSTRLEN
];
3820 const char *name
= NULL
;
3821 struct bgp
*bgp
= NULL
;
3822 struct listnode
*node
= NULL
;
3823 struct bgpevpn
*vpn
= NULL
;
3824 struct ecommunity
*ecom
= NULL
;
3825 json_object
*json
= NULL
;
3826 json_object
*json_vnis
= NULL
;
3827 json_object
*json_export_rts
= NULL
;
3828 json_object
*json_import_rts
= NULL
;
3829 u_char uj
= use_json(argc
, argv
);
3832 json
= json_object_new_object();
3833 json_vnis
= json_object_new_array();
3834 json_export_rts
= json_object_new_array();
3835 json_import_rts
= json_object_new_array();
3838 name
= argv
[idx_vrf
]->arg
;
3839 bgp
= bgp_lookup_by_name(name
);
3842 vty_out(vty
, "BGP instance for VRF %s not found", name
);
3844 json_object_string_add(json
, "warning",
3845 "BGP instance not found");
3846 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
3847 json_object_free(json
);
3853 vty_out(vty
, "BGP VRF: %s\n", name
);
3854 vty_out(vty
, " Local-Ip: %s\n", inet_ntoa(bgp
->originator_ip
));
3855 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
3856 vty_out(vty
, " Rmac: %s\n",
3857 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
3858 vty_out(vty
, " VNI Filter: %s\n",
3859 CHECK_FLAG(bgp
->vrf_flags
,
3860 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
3861 ? "prefix-routes-only"
3863 vty_out(vty
, " L2-VNI List:\n");
3865 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
3866 vty_out(vty
, "%u ", vpn
->vni
);
3868 vty_out(vty
, " Export-RTs:\n");
3870 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
3871 vty_out(vty
, "%s ", ecommunity_str(ecom
));
3873 vty_out(vty
, " Import-RTs:\n");
3875 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
3876 vty_out(vty
, "%s ", ecommunity_str(ecom
));
3878 vty_out(vty
, " RD: %s\n",
3879 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
3881 json_object_string_add(json
, "vrf", name
);
3882 json_object_string_add(json
, "local-ip",
3883 inet_ntoa(bgp
->originator_ip
));
3884 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
3885 json_object_string_add(
3887 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
3888 json_object_string_add(
3890 CHECK_FLAG(bgp
->vrf_flags
,
3891 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
3892 ? "prefix-routes-only"
3894 /* list of l2vnis */
3895 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
3896 json_object_array_add(json_vnis
,
3897 json_object_new_int(vpn
->vni
));
3898 json_object_object_add(json
, "l2vnis", json_vnis
);
3901 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
3902 json_object_array_add(
3904 json_object_new_string(ecommunity_str(ecom
)));
3905 json_object_object_add(json
, "export-rts", json_export_rts
);
3908 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
3909 json_object_array_add(
3911 json_object_new_string(ecommunity_str(ecom
)));
3912 json_object_object_add(json
, "import-rts", json_import_rts
);
3913 json_object_string_add(
3915 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
3919 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
3920 json
, JSON_C_TO_STRING_PRETTY
));
3921 json_object_free(json
);
3926 /* import/export rt for l3vni-vrf */
3927 DEFUN (bgp_evpn_vrf_rt
,
3928 bgp_evpn_vrf_rt_cmd
,
3929 "route-target <both|import|export> RT",
3931 "import and export\n"
3934 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
3937 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3938 struct ecommunity
*ecomadd
= NULL
;
3943 if (!strcmp(argv
[1]->arg
, "import"))
3944 rt_type
= RT_TYPE_IMPORT
;
3945 else if (!strcmp(argv
[1]->arg
, "export"))
3946 rt_type
= RT_TYPE_EXPORT
;
3947 else if (!strcmp(argv
[1]->arg
, "both"))
3948 rt_type
= RT_TYPE_BOTH
;
3950 vty_out(vty
, "%% Invalid Route Target type\n");
3954 /* Add/update the import route-target */
3955 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
3956 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3957 ECOMMUNITY_ROUTE_TARGET
, 0);
3959 vty_out(vty
, "%% Malformed Route Target list\n");
3962 ecommunity_str(ecomadd
);
3964 /* Do nothing if we already have this import route-target */
3965 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
3966 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
3969 /* Add/update the export route-target */
3970 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
3971 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
3972 ECOMMUNITY_ROUTE_TARGET
, 0);
3974 vty_out(vty
, "%% Malformed Route Target list\n");
3977 ecommunity_str(ecomadd
);
3979 /* Do nothing if we already have this export route-target */
3980 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
3981 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
3987 DEFUN (no_bgp_evpn_vrf_rt
,
3988 no_bgp_evpn_vrf_rt_cmd
,
3989 "no route-target <both|import|export> RT",
3992 "import and export\n"
3995 "ASN:XX or A.B.C.D:XX\n")
3997 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3998 int rt_type
, found_ecomdel
;
3999 struct ecommunity
*ecomdel
= NULL
;
4004 if (!strcmp(argv
[2]->arg
, "import"))
4005 rt_type
= RT_TYPE_IMPORT
;
4006 else if (!strcmp(argv
[2]->arg
, "export"))
4007 rt_type
= RT_TYPE_EXPORT
;
4008 else if (!strcmp(argv
[2]->arg
, "both"))
4009 rt_type
= RT_TYPE_BOTH
;
4011 vty_out(vty
, "%% Invalid Route Target type\n");
4015 if (rt_type
== RT_TYPE_IMPORT
) {
4016 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4018 "%% Import RT is not configured for this VRF\n");
4021 } else if (rt_type
== RT_TYPE_EXPORT
) {
4022 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4024 "%% Export RT is not configured for this VRF\n");
4027 } else if (rt_type
== RT_TYPE_BOTH
) {
4028 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
4029 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4031 "%% Import/Export RT is not configured for this VRF\n");
4036 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4038 vty_out(vty
, "%% Malformed Route Target list\n");
4041 ecommunity_str(ecomdel
);
4043 if (rt_type
== RT_TYPE_IMPORT
) {
4044 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4047 "%% RT specified does not match configuration for this VRF\n");
4050 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4051 } else if (rt_type
== RT_TYPE_EXPORT
) {
4052 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4055 "%% RT specified does not match configuration for this VRF\n");
4058 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4059 } else if (rt_type
== RT_TYPE_BOTH
) {
4062 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
4064 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
4068 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
4070 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
4074 if (!found_ecomdel
) {
4076 "%% RT specified does not match configuration for this VRF\n");
4084 DEFUN (bgp_evpn_vni_rt
,
4085 bgp_evpn_vni_rt_cmd
,
4086 "route-target <both|import|export> RT",
4088 "import and export\n"
4091 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
4093 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4094 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4096 struct ecommunity
*ecomadd
= NULL
;
4101 if (!strcmp(argv
[1]->text
, "import"))
4102 rt_type
= RT_TYPE_IMPORT
;
4103 else if (!strcmp(argv
[1]->text
, "export"))
4104 rt_type
= RT_TYPE_EXPORT
;
4105 else if (!strcmp(argv
[1]->text
, "both"))
4106 rt_type
= RT_TYPE_BOTH
;
4108 vty_out(vty
, "%% Invalid Route Target type\n");
4112 /* Add/update the import route-target */
4113 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
4114 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4115 ECOMMUNITY_ROUTE_TARGET
, 0);
4117 vty_out(vty
, "%% Malformed Route Target list\n");
4120 ecommunity_str(ecomadd
);
4122 /* Do nothing if we already have this import route-target */
4123 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
4124 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
4127 /* Add/update the export route-target */
4128 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
4129 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
4130 ECOMMUNITY_ROUTE_TARGET
, 0);
4132 vty_out(vty
, "%% Malformed Route Target list\n");
4135 ecommunity_str(ecomadd
);
4137 /* Do nothing if we already have this export route-target */
4138 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
4139 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
4145 DEFUN (no_bgp_evpn_vni_rt
,
4146 no_bgp_evpn_vni_rt_cmd
,
4147 "no route-target <both|import|export> RT",
4150 "import and export\n"
4153 "ASN:XX or A.B.C.D:XX\n")
4155 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4156 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4157 int rt_type
, found_ecomdel
;
4158 struct ecommunity
*ecomdel
= NULL
;
4163 if (!strcmp(argv
[2]->text
, "import"))
4164 rt_type
= RT_TYPE_IMPORT
;
4165 else if (!strcmp(argv
[2]->text
, "export"))
4166 rt_type
= RT_TYPE_EXPORT
;
4167 else if (!strcmp(argv
[2]->text
, "both"))
4168 rt_type
= RT_TYPE_BOTH
;
4170 vty_out(vty
, "%% Invalid Route Target type\n");
4174 /* The user did "no route-target import", check to see if there are any
4175 * import route-targets configured. */
4176 if (rt_type
== RT_TYPE_IMPORT
) {
4177 if (!is_import_rt_configured(vpn
)) {
4179 "%% Import RT is not configured for this VNI\n");
4182 } else if (rt_type
== RT_TYPE_EXPORT
) {
4183 if (!is_export_rt_configured(vpn
)) {
4185 "%% Export RT is not configured for this VNI\n");
4188 } else if (rt_type
== RT_TYPE_BOTH
) {
4189 if (!is_import_rt_configured(vpn
)
4190 && !is_export_rt_configured(vpn
)) {
4192 "%% Import/Export RT is not configured for this VNI\n");
4197 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
4199 vty_out(vty
, "%% Malformed Route Target list\n");
4202 ecommunity_str(ecomdel
);
4204 if (rt_type
== RT_TYPE_IMPORT
) {
4205 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4207 "%% RT specified does not match configuration for this VNI\n");
4210 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4211 } else if (rt_type
== RT_TYPE_EXPORT
) {
4212 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4214 "%% RT specified does not match configuration for this VNI\n");
4217 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4218 } else if (rt_type
== RT_TYPE_BOTH
) {
4221 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
4222 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
4226 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
4227 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
4231 if (!found_ecomdel
) {
4233 "%% RT specified does not match configuration for this VNI\n");
4241 DEFUN (no_bgp_evpn_vni_rt_without_val
,
4242 no_bgp_evpn_vni_rt_without_val_cmd
,
4243 "no route-target <import|export>",
4249 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4250 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
4256 if (!strcmp(argv
[2]->text
, "import")) {
4257 rt_type
= RT_TYPE_IMPORT
;
4258 } else if (!strcmp(argv
[2]->text
, "export")) {
4259 rt_type
= RT_TYPE_EXPORT
;
4261 vty_out(vty
, "%% Invalid Route Target type\n");
4265 /* Check if we should disallow. */
4266 if (rt_type
== RT_TYPE_IMPORT
) {
4267 if (!is_import_rt_configured(vpn
)) {
4269 "%% Import RT is not configured for this VNI\n");
4273 if (!is_export_rt_configured(vpn
)) {
4275 "%% Export RT is not configured for this VNI\n");
4280 /* Unconfigure the RT. */
4281 if (rt_type
== RT_TYPE_IMPORT
)
4282 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
4284 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
4289 * Output EVPN configuration information.
4291 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
4294 char buf1
[RD_ADDRSTRLEN
];
4297 hash_iterate(bgp
->vnihash
,
4298 (void (*)(struct hash_backet
*,
4299 void *))write_vni_config_for_entry
,
4302 if (bgp
->advertise_all_vni
)
4303 vty_out(vty
, " advertise-all-vni\n");
4305 if (bgp
->advertise_gw_macip
)
4306 vty_out(vty
, " advertise-default-gw\n");
4308 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_ADVERTISE_IPV4_IN_EVPN
))
4309 vty_out(vty
, " advertise ipv4 unicast\n");
4311 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_ADVERTISE_IPV6_IN_EVPN
))
4312 vty_out(vty
, " advertise ipv6 unicast\n");
4314 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
4315 vty_out(vty
, " rd %s\n",
4316 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
4318 /* import route-target */
4319 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
4321 struct listnode
*node
, *nnode
;
4322 struct ecommunity
*ecom
;
4324 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
4326 ecom_str
= ecommunity_ecom2str(
4327 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4328 vty_out(vty
, " route-target import %s\n", ecom_str
);
4329 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4333 /* export route-target */
4334 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
4336 struct listnode
*node
, *nnode
;
4337 struct ecommunity
*ecom
;
4339 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
4341 ecom_str
= ecommunity_ecom2str(
4342 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
4343 vty_out(vty
, " route-target export %s\n", ecom_str
);
4344 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
4349 void bgp_ethernetvpn_init(void)
4351 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
4352 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
4353 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
4354 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
4355 install_element(VIEW_NODE
,
4356 &show_ip_bgp_l2vpn_evpn_all_neighbor_routes_cmd
);
4357 install_element(VIEW_NODE
,
4358 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
4361 &show_ip_bgp_l2vpn_evpn_all_neighbor_advertised_routes_cmd
);
4364 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
4365 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
4366 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
4367 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
4368 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
4369 #if defined(HAVE_CUMULUS)
4370 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
4371 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
4372 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
4373 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
4374 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
4375 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
4377 /* "show bgp l2vpn evpn" commands. */
4378 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
4379 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
4380 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
4381 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
4382 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
4383 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
4384 install_element(VIEW_NODE
,
4385 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
4386 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
4387 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
4388 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
4389 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
4391 /* "show bgp evpn" commands. */
4392 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
4393 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
4394 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
4395 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
4396 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
4397 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
4398 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
4399 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
4400 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
4401 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
4402 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
4404 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
4405 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
4406 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
4407 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
4408 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
4409 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
4410 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
4411 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
4412 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
4413 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
4414 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
4415 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
4416 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
4417 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
4418 install_element(BGP_EVPN_VNI_NODE
,
4419 &bgp_evpn_advertise_default_gw_vni_cmd
);
4420 install_element(BGP_EVPN_VNI_NODE
,
4421 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
4422 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
4423 install_element(BGP_EVPN_VNI_NODE
,
4424 &no_bgp_evpn_advertise_vni_subnet_cmd
);