1 /* Ethernet-VPN Packet and vty Processing File
2 * Copyright (C) 2017 6WIND
4 * This file is part of FRRouting
6 * FRRouting is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * FRRouting is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include "lib/printfrr.h"
26 #include "lib/vxlan.h"
29 #include "bgpd/bgpd.h"
30 #include "bgpd/bgp_table.h"
31 #include "bgpd/bgp_attr.h"
32 #include "bgpd/bgp_route.h"
33 #include "bgpd/bgp_mplsvpn.h"
34 #include "bgpd/bgp_vpn.h"
35 #include "bgpd/bgp_evpn_vty.h"
36 #include "bgpd/bgp_evpn.h"
37 #include "bgpd/bgp_evpn_private.h"
38 #include "bgpd/bgp_evpn_mh.h"
39 #include "bgpd/bgp_zebra.h"
40 #include "bgpd/bgp_vty.h"
41 #include "bgpd/bgp_errors.h"
42 #include "bgpd/bgp_ecommunity.h"
43 #include "bgpd/bgp_lcommunity.h"
44 #include "bgpd/bgp_community.h"
46 #define SHOW_DISPLAY_STANDARD 0
47 #define SHOW_DISPLAY_TAGS 1
48 #define SHOW_DISPLAY_OVERLAY 2
49 #define VNI_STR_LEN 32
52 * Context for VNI hash walk - used by callbacks.
57 struct in_addr vtep_ip
;
62 static void display_vrf_import_rt(struct vty
*vty
, struct vrf_irt_node
*irt
,
66 uint8_t type
, sub_type
;
67 struct ecommunity_as eas
;
68 struct ecommunity_ip eip
;
69 struct listnode
*node
, *nnode
;
70 struct bgp
*tmp_bgp_vrf
= NULL
;
71 json_object
*json_rt
= NULL
;
72 json_object
*json_vrfs
= NULL
;
73 char rt_buf
[RT_ADDRSTRLEN
];
76 json_rt
= json_object_new_object();
77 json_vrfs
= json_object_new_array();
80 pnt
= (uint8_t *)&irt
->rt
.val
;
83 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
86 memset(&eas
, 0, sizeof(eas
));
88 case ECOMMUNITY_ENCODE_AS
:
89 eas
.as
= (*pnt
++ << 8);
91 ptr_get_be32(pnt
, &eas
.val
);
93 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
96 json_object_string_add(json_rt
, "rt", rt_buf
);
98 vty_out(vty
, "Route-target: %s", rt_buf
);
102 case ECOMMUNITY_ENCODE_IP
:
103 memcpy(&eip
.ip
, pnt
, 4);
105 eip
.val
= (*pnt
++ << 8);
108 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
111 json_object_string_add(json_rt
, "rt", rt_buf
);
113 vty_out(vty
, "Route-target: %s", rt_buf
);
117 case ECOMMUNITY_ENCODE_AS4
:
118 pnt
= ptr_get_be32(pnt
, &eas
.val
);
119 eas
.val
= (*pnt
++ << 8);
122 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
125 json_object_string_add(json_rt
, "rt", rt_buf
);
127 vty_out(vty
, "Route-target: %s", rt_buf
);
137 "\nList of VRFs importing routes with this route-target:\n");
140 for (ALL_LIST_ELEMENTS(irt
->vrfs
, node
, nnode
, tmp_bgp_vrf
)) {
142 json_object_array_add(
144 json_object_new_string(
145 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
)));
147 vty_out(vty
, " %s\n",
148 vrf_id_to_name(tmp_bgp_vrf
->vrf_id
));
152 json_object_object_add(json_rt
, "vrfs", json_vrfs
);
153 json_object_object_add(json
, rt_buf
, json_rt
);
157 static void show_vrf_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
159 json_object
*json
= NULL
;
160 struct vty
*vty
= NULL
;
161 struct vrf_irt_node
*irt
= (struct vrf_irt_node
*)bucket
->data
;
163 vty
= (struct vty
*)args
[0];
164 json
= (struct json_object
*)args
[1];
166 display_vrf_import_rt(vty
, irt
, json
);
169 static void display_import_rt(struct vty
*vty
, struct irt_node
*irt
,
173 uint8_t type
, sub_type
;
174 struct ecommunity_as eas
;
175 struct ecommunity_ip eip
;
176 struct listnode
*node
, *nnode
;
177 struct bgpevpn
*tmp_vpn
;
178 json_object
*json_rt
= NULL
;
179 json_object
*json_vnis
= NULL
;
180 char rt_buf
[RT_ADDRSTRLEN
];
183 json_rt
= json_object_new_object();
184 json_vnis
= json_object_new_array();
187 /* TODO: This needs to go into a function */
189 pnt
= (uint8_t *)&irt
->rt
.val
;
192 if (sub_type
!= ECOMMUNITY_ROUTE_TARGET
)
195 memset(&eas
, 0, sizeof(eas
));
197 case ECOMMUNITY_ENCODE_AS
:
198 eas
.as
= (*pnt
++ << 8);
200 ptr_get_be32(pnt
, &eas
.val
);
202 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
205 json_object_string_add(json_rt
, "rt", rt_buf
);
207 vty_out(vty
, "Route-target: %s", rt_buf
);
211 case ECOMMUNITY_ENCODE_IP
:
212 memcpy(&eip
.ip
, pnt
, 4);
214 eip
.val
= (*pnt
++ << 8);
217 snprintfrr(rt_buf
, sizeof(rt_buf
), "%pI4:%u", &eip
.ip
, eip
.val
);
220 json_object_string_add(json_rt
, "rt", rt_buf
);
222 vty_out(vty
, "Route-target: %s", rt_buf
);
226 case ECOMMUNITY_ENCODE_AS4
:
227 pnt
= ptr_get_be32(pnt
, &eas
.val
);
228 eas
.val
= (*pnt
++ << 8);
231 snprintf(rt_buf
, sizeof(rt_buf
), "%u:%u", eas
.as
, eas
.val
);
234 json_object_string_add(json_rt
, "rt", rt_buf
);
236 vty_out(vty
, "Route-target: %s", rt_buf
);
246 "\nList of VNIs importing routes with this route-target:\n");
249 for (ALL_LIST_ELEMENTS(irt
->vnis
, node
, nnode
, tmp_vpn
)) {
251 json_object_array_add(
252 json_vnis
, json_object_new_int(tmp_vpn
->vni
));
254 vty_out(vty
, " %u\n", tmp_vpn
->vni
);
258 json_object_object_add(json_rt
, "vnis", json_vnis
);
259 json_object_object_add(json
, rt_buf
, json_rt
);
263 static void show_import_rt_entry(struct hash_bucket
*bucket
, void *args
[])
265 json_object
*json
= NULL
;
266 struct vty
*vty
= NULL
;
267 struct irt_node
*irt
= (struct irt_node
*)bucket
->data
;
272 display_import_rt(vty
, irt
, json
);
277 static void bgp_evpn_show_route_rd_header(struct vty
*vty
,
278 struct bgp_dest
*rd_dest
,
279 json_object
*json
, char *rd_str
,
286 const struct prefix
*p
= bgp_dest_get_prefix(rd_dest
);
290 /* Decode RD type. */
291 type
= decode_rd_type(pnt
);
294 vty_out(vty
, "Route Distinguisher: ");
298 decode_rd_as(pnt
+ 2, &rd_as
);
299 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
301 json_object_string_add(json
, "rd", rd_str
);
303 vty_out(vty
, "%s\n", rd_str
);
307 decode_rd_as4(pnt
+ 2, &rd_as
);
308 snprintf(rd_str
, len
, "%u:%d", rd_as
.as
, rd_as
.val
);
310 json_object_string_add(json
, "rd", rd_str
);
312 vty_out(vty
, "%s\n", rd_str
);
316 decode_rd_ip(pnt
+ 2, &rd_ip
);
317 snprintfrr(rd_str
, len
, "%pI4:%d", &rd_ip
.ip
, rd_ip
.val
);
319 json_object_string_add(json
, "rd", rd_str
);
321 vty_out(vty
, "%s\n", rd_str
);
326 snprintf(rd_str
, len
, "Unknown");
327 json_object_string_add(json
, "rd", rd_str
);
329 snprintf(rd_str
, len
, "Unknown RD type");
330 vty_out(vty
, "%s\n", rd_str
);
336 static void bgp_evpn_show_route_header(struct vty
*vty
, struct bgp
*bgp
,
337 uint64_t tbl_ver
, json_object
*json
)
340 " Network Next Hop Metric LocPrf Weight Path\n";
346 "BGP table version is %" PRIu64
", local router ID is %pI4\n",
347 tbl_ver
, &bgp
->router_id
);
349 "Status codes: s suppressed, d damped, h history, * valid, > best, i - internal\n");
350 vty_out(vty
, "Origin codes: i - IGP, e - EGP, ? - incomplete\n");
352 "EVPN type-1 prefix: [1]:[ESI]:[EthTag]:[IPlen]:[VTEP-IP]\n");
354 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]:[IPlen]:[IP]\n");
355 vty_out(vty
, "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
356 vty_out(vty
, "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
357 vty_out(vty
, "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
358 vty_out(vty
, "%s", ri_header
);
361 static void display_l3vni(struct vty
*vty
, struct bgp
*bgp_vrf
,
364 char buf1
[INET6_ADDRSTRLEN
];
366 struct listnode
*node
, *nnode
;
367 struct ecommunity
*ecom
;
368 json_object
*json_import_rtl
= NULL
;
369 json_object
*json_export_rtl
= NULL
;
370 char buf2
[ETHER_ADDR_STRLEN
];
371 char originator_ip
[BUFSIZ
] = {0};
373 json_import_rtl
= json_export_rtl
= 0;
376 json_import_rtl
= json_object_new_array();
377 json_export_rtl
= json_object_new_array();
378 json_object_int_add(json
, "vni", bgp_vrf
->l3vni
);
379 json_object_string_add(json
, "type", "L3");
380 json_object_string_add(json
, "inKernel", "True");
381 json_object_string_add(
383 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
384 json_object_string_add(
385 json
, "originatorIp",
386 inet_ntop(AF_INET
, &bgp_vrf
->originator_ip
,
387 originator_ip
, sizeof(originator_ip
)));
388 json_object_string_add(json
, "advertiseGatewayMacip", "n/a");
389 json_object_string_add(json
, "advertiseSviMacIp", "n/a");
390 json_object_to_json_string_ext(json
,
391 JSON_C_TO_STRING_NOSLASHESCAPE
);
392 json_object_string_add(json
, "advertisePip",
393 bgp_vrf
->evpn_info
->advertise_pip
?
394 "Enabled" : "Disabled");
395 json_object_string_add(json
, "sysIP",
397 &bgp_vrf
->evpn_info
->pip_ip
,
398 buf1
, INET_ADDRSTRLEN
));
399 json_object_string_add(json
, "sysMac",
400 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
401 buf2
, sizeof(buf2
)));
402 json_object_string_add(json
, "rmac",
403 prefix_mac2str(&bgp_vrf
->rmac
,
404 buf2
, sizeof(buf2
)));
406 vty_out(vty
, "VNI: %d", bgp_vrf
->l3vni
);
407 vty_out(vty
, " (known to the kernel)");
410 vty_out(vty
, " Type: %s\n", "L3");
411 vty_out(vty
, " Tenant VRF: %s\n",
412 vrf_id_to_name(bgp_vrf
->vrf_id
));
413 vty_out(vty
, " RD: %s\n",
414 prefix_rd2str(&bgp_vrf
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
415 vty_out(vty
, " Originator IP: %pI4\n",
416 &bgp_vrf
->originator_ip
);
417 vty_out(vty
, " Advertise-gw-macip : %s\n", "n/a");
418 vty_out(vty
, " Advertise-svi-macip : %s\n", "n/a");
419 vty_out(vty
, " Advertise-pip: %s\n",
420 bgp_vrf
->evpn_info
->advertise_pip
? "Yes" : "No");
421 vty_out(vty
, " System-IP: %s\n",
422 inet_ntop(AF_INET
, &bgp_vrf
->evpn_info
->pip_ip
,
423 buf1
, INET_ADDRSTRLEN
));
424 vty_out(vty
, " System-MAC: %s\n",
425 prefix_mac2str(&bgp_vrf
->evpn_info
->pip_rmac
,
426 buf2
, sizeof(buf2
)));
427 vty_out(vty
, " Router-MAC: %s\n",
428 prefix_mac2str(&bgp_vrf
->rmac
,
429 buf2
, sizeof(buf2
)));
433 vty_out(vty
, " Import Route Target:\n");
435 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_import_rtl
, node
, nnode
, ecom
)) {
436 ecom_str
= ecommunity_ecom2str(ecom
,
437 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
440 json_object_array_add(json_import_rtl
,
441 json_object_new_string(ecom_str
));
443 vty_out(vty
, " %s\n", ecom_str
);
445 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
449 json_object_object_add(json
, "importRts", json_import_rtl
);
451 vty_out(vty
, " Export Route Target:\n");
453 for (ALL_LIST_ELEMENTS(bgp_vrf
->vrf_export_rtl
, node
, nnode
, ecom
)) {
454 ecom_str
= ecommunity_ecom2str(ecom
,
455 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
458 json_object_array_add(json_export_rtl
,
459 json_object_new_string(ecom_str
));
461 vty_out(vty
, " %s\n", ecom_str
);
463 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
467 json_object_object_add(json
, "exportRts", json_export_rtl
);
470 static void display_vni(struct vty
*vty
, struct bgpevpn
*vpn
, json_object
*json
)
472 char buf1
[RD_ADDRSTRLEN
];
474 struct listnode
*node
, *nnode
;
475 struct ecommunity
*ecom
;
476 json_object
*json_import_rtl
= NULL
;
477 json_object
*json_export_rtl
= NULL
;
478 struct bgp
*bgp_evpn
;
479 char buf
[BUFSIZ
] = {0};
481 bgp_evpn
= bgp_get_evpn();
484 json_import_rtl
= json_object_new_array();
485 json_export_rtl
= json_object_new_array();
486 json_object_int_add(json
, "vni", vpn
->vni
);
487 json_object_string_add(json
, "type", "L2");
488 json_object_string_add(json
, "inKernel",
489 is_vni_live(vpn
) ? "True" : "False");
490 json_object_string_add(
492 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
493 json_object_string_add(json
, "originatorIp",
494 inet_ntop(AF_INET
, &vpn
->originator_ip
,
496 json_object_string_add(
498 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf
, sizeof(buf
)));
499 /* per vni knob is enabled -- Enabled
500 * Global knob is enabled -- Active
501 * default -- Disabled
503 if (!vpn
->advertise_gw_macip
&&
504 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
505 json_object_string_add(json
, "advertiseGatewayMacip",
507 else if (vpn
->advertise_gw_macip
)
508 json_object_string_add(json
, "advertiseGatewayMacip",
511 json_object_string_add(json
, "advertiseGatewayMacip",
513 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
514 bgp_evpn
->evpn_info
->advertise_svi_macip
)
515 json_object_string_add(json
, "advertiseSviMacIp",
517 else if (vpn
->advertise_svi_macip
)
518 json_object_string_add(json
, "advertiseSviMacIp",
521 json_object_string_add(json
, "advertiseSviMacIp",
524 vty_out(vty
, "VNI: %d", vpn
->vni
);
525 if (is_vni_live(vpn
))
526 vty_out(vty
, " (known to the kernel)");
529 vty_out(vty
, " Type: %s\n", "L2");
530 vty_out(vty
, " Tenant-Vrf: %s\n",
531 vrf_id_to_name(vpn
->tenant_vrf_id
));
532 vty_out(vty
, " RD: %s\n",
533 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
534 vty_out(vty
, " Originator IP: %pI4\n", &vpn
->originator_ip
);
535 vty_out(vty
, " Mcast group: %pI4\n", &vpn
->mcast_grp
);
536 if (!vpn
->advertise_gw_macip
&&
537 bgp_evpn
&& bgp_evpn
->advertise_gw_macip
)
538 vty_out(vty
, " Advertise-gw-macip : %s\n",
540 else if (vpn
->advertise_gw_macip
)
541 vty_out(vty
, " Advertise-gw-macip : %s\n",
544 vty_out(vty
, " Advertise-gw-macip : %s\n",
546 if (!vpn
->advertise_svi_macip
&& bgp_evpn
&&
547 bgp_evpn
->evpn_info
->advertise_svi_macip
)
548 vty_out(vty
, " Advertise-svi-macip : %s\n",
550 else if (vpn
->advertise_svi_macip
)
551 vty_out(vty
, " Advertise-svi-macip : %s\n",
554 vty_out(vty
, " Advertise-svi-macip : %s\n",
559 vty_out(vty
, " Import Route Target:\n");
561 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
562 ecom_str
= ecommunity_ecom2str(ecom
,
563 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
566 json_object_array_add(json_import_rtl
,
567 json_object_new_string(ecom_str
));
569 vty_out(vty
, " %s\n", ecom_str
);
571 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
575 json_object_object_add(json
, "importRts", json_import_rtl
);
577 vty_out(vty
, " Export Route Target:\n");
579 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
580 ecom_str
= ecommunity_ecom2str(ecom
,
581 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
584 json_object_array_add(json_export_rtl
,
585 json_object_new_string(ecom_str
));
587 vty_out(vty
, " %s\n", ecom_str
);
589 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
593 json_object_object_add(json
, "exportRts", json_export_rtl
);
596 static void show_esi_routes(struct bgp
*bgp
,
597 struct bgp_evpn_es
*es
,
602 struct bgp_dest
*dest
;
603 struct bgp_path_info
*pi
;
604 uint32_t prefix_cnt
, path_cnt
;
607 prefix_cnt
= path_cnt
= 0;
609 tbl_ver
= es
->route_table
->version
;
610 for (dest
= bgp_table_top(es
->route_table
); dest
;
611 dest
= bgp_route_next(dest
)) {
612 int add_prefix_to_json
= 0;
613 char prefix_str
[BUFSIZ
];
614 json_object
*json_paths
= NULL
;
615 json_object
*json_prefix
= NULL
;
616 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
618 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
622 json_prefix
= json_object_new_object();
624 pi
= bgp_dest_get_bgp_path_info(dest
);
626 /* Overall header/legend displayed once. */
628 bgp_evpn_show_route_header(vty
, bgp
,
637 json_paths
= json_object_new_array();
639 /* For EVPN, the prefix is displayed for each path (to fit in
640 * with code that already exists).
642 for (; pi
; pi
= pi
->next
) {
643 json_object
*json_path
= NULL
;
646 json_path
= json_object_new_array();
648 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
, json_path
,
652 json_object_array_add(json_paths
, json_path
);
655 add_prefix_to_json
= 1;
659 if (add_prefix_to_json
) {
660 json_object_string_add(json_prefix
, "prefix",
662 json_object_int_add(json_prefix
, "prefixLen",
664 json_object_object_add(json_prefix
, "paths",
666 json_object_object_add(json
, prefix_str
,
669 json_object_free(json_paths
);
670 json_object_free(json_prefix
);
678 json_object_int_add(json
, "numPrefix", prefix_cnt
);
679 json_object_int_add(json
, "numPaths", path_cnt
);
682 vty_out(vty
, "No EVPN prefixes exist for this ESI\n");
684 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)\n",
685 prefix_cnt
, path_cnt
);
689 /* Display all MAC-IP VNI routes linked to an ES */
690 static void bgp_evpn_show_routes_mac_ip_es(struct vty
*vty
, esi_t
*esi
,
691 json_object
*json
, int detail
)
694 struct bgp_path_info
*pi
;
695 int header
= detail
? 0 : 1;
697 struct listnode
*node
;
698 struct bgp_evpn_es
*es
;
699 struct bgp_path_es_info
*es_info
;
700 struct bgp
*bgp
= bgp_get_evpn();
701 json_object
*json_paths
= NULL
;
709 json_paths
= json_object_new_array();
711 RB_FOREACH (es
, bgp_es_rb_head
, &bgp_mh_info
->es_rb_tree
) {
713 if (esi
&& memcmp(esi
, &es
->esi
, sizeof(*esi
)))
716 for (ALL_LIST_ELEMENTS_RO(es
->macip_path_list
, node
, es_info
)) {
717 json_object
*json_path
= NULL
;
722 if (!CHECK_FLAG(pi
->flags
, BGP_PATH_VALID
))
725 /* Overall header/legend displayed once. */
727 bgp_evpn_show_route_header(vty
, bgp
, 0, json
);
734 json_path
= json_object_new_array();
737 route_vty_out_detail(vty
, bgp
, rn
, pi
,
738 AFI_L2VPN
, SAFI_EVPN
,
741 route_vty_out(vty
, &rn
->p
, pi
, 0, SAFI_EVPN
,
745 json_object_array_add(json_paths
, json_path
);
750 json_object_object_add(json
, "paths", json_paths
);
751 json_object_int_add(json
, "numPaths", path_cnt
);
754 vty_out(vty
, "There are no MAC-IP ES paths");
756 vty_out(vty
, "\nDisplayed %u paths\n", path_cnt
);
761 static void show_vni_routes(struct bgp
*bgp
, struct bgpevpn
*vpn
, int type
,
762 struct vty
*vty
, struct in_addr vtep_ip
,
763 json_object
*json
, int detail
)
765 struct bgp_dest
*dest
;
766 struct bgp_path_info
*pi
;
767 struct bgp_table
*table
;
768 int header
= detail
? 0 : 1;
770 uint32_t prefix_cnt
, path_cnt
;
772 prefix_cnt
= path_cnt
= 0;
774 table
= vpn
->route_table
;
775 tbl_ver
= table
->version
;
776 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
777 const struct prefix_evpn
*evp
=
778 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
779 int add_prefix_to_json
= 0;
780 char prefix_str
[BUFSIZ
];
781 json_object
*json_paths
= NULL
;
782 json_object
*json_prefix
= NULL
;
783 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
785 prefix2str((struct prefix_evpn
*)bgp_dest_get_prefix(dest
),
786 prefix_str
, sizeof(prefix_str
));
788 if (type
&& evp
->prefix
.route_type
!= type
)
792 json_prefix
= json_object_new_object();
794 pi
= bgp_dest_get_bgp_path_info(dest
);
796 /* Overall header/legend displayed once. */
798 bgp_evpn_show_route_header(vty
, bgp
,
807 json_paths
= json_object_new_array();
809 /* For EVPN, the prefix is displayed for each path (to fit in
810 * with code that already exists).
812 for (; pi
; pi
= pi
->next
) {
813 json_object
*json_path
= NULL
;
815 if (vtep_ip
.s_addr
!= INADDR_ANY
816 && !IPV4_ADDR_SAME(&(vtep_ip
),
817 &(pi
->attr
->nexthop
)))
821 json_path
= json_object_new_array();
824 route_vty_out_detail(vty
, bgp
, dest
, pi
,
825 AFI_L2VPN
, SAFI_EVPN
,
828 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
832 json_object_array_add(json_paths
, json_path
);
835 add_prefix_to_json
= 1;
839 if (add_prefix_to_json
) {
840 json_object_string_add(json_prefix
, "prefix",
842 json_object_int_add(json_prefix
, "prefixLen",
844 json_object_object_add(json_prefix
, "paths",
846 json_object_object_add(json
, prefix_str
,
849 json_object_free(json_paths
);
850 json_object_free(json_prefix
);
858 json_object_int_add(json
, "numPrefix", prefix_cnt
);
859 json_object_int_add(json
, "numPaths", path_cnt
);
862 vty_out(vty
, "No EVPN prefixes %sexist for this VNI",
863 type
? "(of requested type) " : "");
865 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
866 prefix_cnt
, path_cnt
,
867 type
? " (of requested type)" : "");
872 static void show_vni_routes_hash(struct hash_bucket
*bucket
, void *arg
)
874 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
875 struct vni_walk_ctx
*wctx
= arg
;
876 struct vty
*vty
= wctx
->vty
;
877 json_object
*json
= wctx
->json
;
878 json_object
*json_vni
= NULL
;
879 char vni_str
[VNI_STR_LEN
];
881 snprintf(vni_str
, sizeof(vni_str
), "%d", vpn
->vni
);
883 json_vni
= json_object_new_object();
884 json_object_int_add(json_vni
, "vni", vpn
->vni
);
886 vty_out(vty
, "\nVNI: %d\n\n", vpn
->vni
);
889 show_vni_routes(wctx
->bgp
, vpn
, 0, wctx
->vty
, wctx
->vtep_ip
, json_vni
,
893 json_object_object_add(json
, vni_str
, json_vni
);
896 static void show_l3vni_entry(struct vty
*vty
, struct bgp
*bgp
,
899 json_object
*json_vni
= NULL
;
900 json_object
*json_import_rtl
= NULL
;
901 json_object
*json_export_rtl
= NULL
;
903 char buf2
[INET6_ADDRSTRLEN
];
904 char buf3
[BUFSIZ
] = {0};
907 struct listnode
*node
, *nnode
;
908 struct ecommunity
*ecom
;
914 json_vni
= json_object_new_object();
915 json_import_rtl
= json_object_new_array();
916 json_export_rtl
= json_object_new_array();
919 /* if an l3vni is present in bgp it is live */
921 snprintf(buf1
, sizeof(buf1
), "*");
924 json_object_int_add(json_vni
, "vni", bgp
->l3vni
);
925 json_object_string_add(json_vni
, "type", "L3");
926 json_object_string_add(json_vni
, "inKernel", "True");
927 json_object_string_add(json_vni
, "originatorIp",
928 inet_ntop(AF_INET
, &bgp
->originator_ip
,
929 buf3
, sizeof(buf3
)));
930 json_object_string_add(
932 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
933 json_object_string_add(json_vni
, "advertiseGatewayMacip",
935 json_object_string_add(json_vni
, "advertiseSviMacIp", "n/a");
936 json_object_to_json_string_ext(json_vni
,
937 JSON_C_TO_STRING_NOSLASHESCAPE
);
938 json_object_string_add(
939 json_vni
, "advertisePip",
940 bgp
->evpn_info
->advertise_pip
? "Enabled" : "Disabled");
941 json_object_string_add(json_vni
, "sysIP",
943 &bgp
->evpn_info
->pip_ip
, buf3
,
945 json_object_string_add(json_vni
, "sysMAC",
946 prefix_mac2str(&bgp
->evpn_info
->pip_rmac
,
947 buf2
, sizeof(buf2
)));
948 json_object_string_add(
950 prefix_mac2str(&bgp
->rmac
, buf2
, sizeof(buf2
)));
952 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, bgp
->l3vni
, "L3",
953 prefix_rd2str(&bgp
->vrf_prd
, buf2
, RD_ADDRSTRLEN
));
956 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
, ecom
)) {
957 ecom_str
= ecommunity_ecom2str(ecom
,
958 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
961 json_object_array_add(json_import_rtl
,
962 json_object_new_string(ecom_str
));
964 if (listcount(bgp
->vrf_import_rtl
) > 1)
965 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
968 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
970 vty_out(vty
, " %-25s", rt_buf
);
973 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
975 /* If there are multiple import RTs we break here and show only
982 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
984 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
, ecom
)) {
985 ecom_str
= ecommunity_ecom2str(ecom
,
986 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
989 json_object_array_add(json_export_rtl
,
990 json_object_new_string(ecom_str
));
992 if (listcount(bgp
->vrf_export_rtl
) > 1)
993 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
996 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
998 vty_out(vty
, " %-25s", rt_buf
);
1001 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1003 /* If there are multiple export RTs we break here and show only
1010 vty_out(vty
, "%-37s", vrf_id_to_name(bgp
->vrf_id
));
1013 char vni_str
[VNI_STR_LEN
];
1015 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1016 snprintf(vni_str
, sizeof(vni_str
), "%u", bgp
->l3vni
);
1017 json_object_object_add(json
, vni_str
, json_vni
);
1023 static void show_vni_entry(struct hash_bucket
*bucket
, void *args
[])
1027 json_object
*json_vni
= NULL
;
1028 json_object
*json_import_rtl
= NULL
;
1029 json_object
*json_export_rtl
= NULL
;
1030 struct bgpevpn
*vpn
= (struct bgpevpn
*)bucket
->data
;
1032 char buf2
[RD_ADDRSTRLEN
];
1033 char buf3
[BUFSIZ
] = {0};
1036 struct listnode
*node
, *nnode
;
1037 struct ecommunity
*ecom
;
1038 struct bgp
*bgp_evpn
;
1043 bgp_evpn
= bgp_get_evpn();
1046 json_vni
= json_object_new_object();
1047 json_import_rtl
= json_object_new_array();
1048 json_export_rtl
= json_object_new_array();
1052 if (is_vni_live(vpn
))
1053 snprintf(buf1
, sizeof(buf1
), "*");
1056 json_object_int_add(json_vni
, "vni", vpn
->vni
);
1057 json_object_string_add(json_vni
, "type", "L2");
1058 json_object_string_add(json_vni
, "inKernel",
1059 is_vni_live(vpn
) ? "True" : "False");
1060 json_object_string_add(
1062 prefix_rd2str(&vpn
->prd
, buf2
, sizeof(buf2
)));
1063 json_object_string_add(json_vni
, "originatorIp",
1064 inet_ntop(AF_INET
, &vpn
->originator_ip
,
1065 buf3
, sizeof(buf3
)));
1066 json_object_string_add(json_vni
, "mcastGroup",
1067 inet_ntop(AF_INET
, &vpn
->mcast_grp
, buf3
,
1069 /* per vni knob is enabled -- Enabled
1070 * Global knob is enabled -- Active
1071 * default -- Disabled
1073 if (!vpn
->advertise_gw_macip
&& bgp_evpn
1074 && bgp_evpn
->advertise_gw_macip
)
1075 json_object_string_add(
1076 json_vni
, "advertiseGatewayMacip", "Active");
1077 else if (vpn
->advertise_gw_macip
)
1078 json_object_string_add(
1079 json_vni
, "advertiseGatewayMacip", "Enabled");
1081 json_object_string_add(
1082 json_vni
, "advertiseGatewayMacip", "Disabled");
1083 if (!vpn
->advertise_svi_macip
&& bgp_evpn
1084 && bgp_evpn
->evpn_info
->advertise_svi_macip
)
1085 json_object_string_add(json_vni
, "advertiseSviMacIp",
1087 else if (vpn
->advertise_svi_macip
)
1088 json_object_string_add(json_vni
, "advertiseSviMacIp",
1091 json_object_string_add(json_vni
, "advertiseSviMacIp",
1094 vty_out(vty
, "%-1s %-10u %-4s %-21s", buf1
, vpn
->vni
, "L2",
1095 prefix_rd2str(&vpn
->prd
, buf2
, RD_ADDRSTRLEN
));
1098 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
1099 ecom_str
= ecommunity_ecom2str(ecom
,
1100 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1103 json_object_array_add(json_import_rtl
,
1104 json_object_new_string(ecom_str
));
1106 if (listcount(vpn
->import_rtl
) > 1)
1107 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1110 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1112 vty_out(vty
, " %-25s", rt_buf
);
1115 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1117 /* If there are multiple import RTs we break here and show only
1124 json_object_object_add(json_vni
, "importRTs", json_import_rtl
);
1126 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
1127 ecom_str
= ecommunity_ecom2str(ecom
,
1128 ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
1131 json_object_array_add(json_export_rtl
,
1132 json_object_new_string(ecom_str
));
1134 if (listcount(vpn
->export_rtl
) > 1)
1135 snprintf(rt_buf
, sizeof(rt_buf
), "%s, ...",
1138 snprintf(rt_buf
, sizeof(rt_buf
), "%s",
1140 vty_out(vty
, " %-25s", rt_buf
);
1143 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
1145 /* If there are multiple export RTs we break here and show only
1152 vty_out(vty
, "%-37s", vrf_id_to_name(vpn
->tenant_vrf_id
));
1155 char vni_str
[VNI_STR_LEN
];
1157 json_object_object_add(json_vni
, "exportRTs", json_export_rtl
);
1158 snprintf(vni_str
, sizeof(vni_str
), "%u", vpn
->vni
);
1159 json_object_object_add(json
, vni_str
, json_vni
);
1165 static int bgp_show_ethernet_vpn(struct vty
*vty
, struct prefix_rd
*prd
,
1166 enum bgp_show_type type
, void *output_arg
,
1167 int option
, bool use_json
)
1169 afi_t afi
= AFI_L2VPN
;
1171 struct bgp_table
*table
;
1172 struct bgp_dest
*dest
;
1173 struct bgp_dest
*rm
;
1174 struct bgp_path_info
*pi
;
1177 char rd_str
[RD_ADDRSTRLEN
];
1180 char router_id
[BUFSIZ
] = {0};
1182 unsigned long output_count
= 0;
1183 unsigned long total_count
= 0;
1184 json_object
*json
= NULL
;
1185 json_object
*json_array
= NULL
;
1186 json_object
*json_prefix_info
= NULL
;
1188 memset(rd_str
, 0, RD_ADDRSTRLEN
);
1190 bgp
= bgp_get_evpn();
1193 vty_out(vty
, "No BGP process is configured\n");
1195 vty_out(vty
, "{}\n");
1200 json
= json_object_new_object();
1202 for (dest
= bgp_table_top(bgp
->rib
[afi
][SAFI_EVPN
]); dest
;
1203 dest
= bgp_route_next(dest
)) {
1205 json_object
*json_nroute
= NULL
;
1206 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
1208 if (prd
&& memcmp(p
->u
.val
, prd
->val
, 8) != 0)
1211 table
= bgp_dest_get_bgp_table_info(dest
);
1216 tbl_ver
= table
->version
;
1218 for (rm
= bgp_table_top(table
); rm
; rm
= bgp_route_next(rm
)) {
1219 pi
= bgp_dest_get_bgp_path_info(rm
);
1224 for (; pi
; pi
= pi
->next
) {
1226 if (type
== bgp_show_type_neighbor
) {
1227 struct peer
*peer
= output_arg
;
1229 if (peer_cmp(peer
, pi
->peer
) != 0)
1232 if (type
== bgp_show_type_lcommunity_exact
) {
1233 struct lcommunity
*lcom
= output_arg
;
1235 if (!pi
->attr
->lcommunity
||
1237 pi
->attr
->lcommunity
, lcom
))
1240 if (type
== bgp_show_type_lcommunity
) {
1241 struct lcommunity
*lcom
= output_arg
;
1243 if (!pi
->attr
->lcommunity
||
1245 pi
->attr
->lcommunity
, lcom
))
1248 if (type
== bgp_show_type_community
) {
1249 struct community
*com
= output_arg
;
1251 if (!pi
->attr
->community
||
1253 pi
->attr
->community
, com
))
1256 if (type
== bgp_show_type_community_exact
) {
1257 struct community
*com
= output_arg
;
1259 if (!pi
->attr
->community
||
1261 pi
->attr
->community
, com
))
1266 json_object_int_add(
1267 json
, "bgpTableVersion",
1269 json_object_string_add(
1276 sizeof(router_id
)));
1277 json_object_int_add(
1280 bgp
->default_local_pref
);
1281 json_object_int_add(
1285 if (option
== SHOW_DISPLAY_TAGS
)
1290 == SHOW_DISPLAY_OVERLAY
)
1294 bgp_evpn_show_route_header(vty
, bgp
, tbl_ver
, NULL
);
1302 json_object_new_object();
1303 bgp_evpn_show_route_rd_header(
1304 vty
, dest
, json_nroute
, rd_str
,
1308 if (use_json
&& !json_array
)
1309 json_array
= json_object_new_array();
1311 if (option
== SHOW_DISPLAY_TAGS
)
1313 vty
, bgp_dest_get_prefix(rm
),
1314 pi
, no_display
, SAFI_EVPN
,
1316 else if (option
== SHOW_DISPLAY_OVERLAY
)
1317 route_vty_out_overlay(
1318 vty
, bgp_dest_get_prefix(rm
),
1319 pi
, no_display
, json_array
);
1322 bgp_dest_get_prefix(rm
),
1323 pi
, no_display
, SAFI_EVPN
,
1331 if (use_json
&& json_array
) {
1332 const struct prefix
*p
=
1333 bgp_dest_get_prefix(rm
);
1335 json_prefix_info
= json_object_new_object();
1337 json_object_string_add(
1338 json_prefix_info
, "prefix",
1339 prefix2str((struct prefix_evpn
*)p
, buf
,
1342 json_object_int_add(json_prefix_info
,
1343 "prefixLen", p
->prefixlen
);
1345 json_object_object_add(json_prefix_info
,
1346 "paths", json_array
);
1347 json_object_object_add(json_nroute
, buf
,
1353 if (use_json
&& json_nroute
)
1354 json_object_object_add(json
, rd_str
, json_nroute
);
1358 json_object_int_add(json
, "numPrefix", output_count
);
1359 json_object_int_add(json
, "totalPrefix", total_count
);
1360 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
1361 json
, JSON_C_TO_STRING_PRETTY
));
1362 json_object_free(json
);
1364 if (output_count
== 0)
1365 vty_out(vty
, "No prefixes displayed, %ld exist\n",
1369 "\nDisplayed %ld out of %ld total prefixes\n",
1370 output_count
, total_count
);
1375 DEFUN(show_ip_bgp_l2vpn_evpn
,
1376 show_ip_bgp_l2vpn_evpn_cmd
,
1377 "show [ip] bgp l2vpn evpn [json]",
1378 SHOW_STR IP_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR JSON_STR
)
1380 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 0,
1381 use_json(argc
, argv
));
1384 DEFUN(show_ip_bgp_l2vpn_evpn_rd
,
1385 show_ip_bgp_l2vpn_evpn_rd_cmd
,
1386 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN [json]",
1392 "Display information for a route distinguisher\n"
1393 "VPN Route Distinguisher\n" JSON_STR
)
1395 int idx_ext_community
= 0;
1397 struct prefix_rd prd
;
1399 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1401 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1403 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1406 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 0,
1407 use_json(argc
, argv
));
1410 DEFUN(show_ip_bgp_l2vpn_evpn_all_tags
,
1411 show_ip_bgp_l2vpn_evpn_all_tags_cmd
,
1412 "show [ip] bgp l2vpn evpn all tags",
1418 "Display information about all EVPN NLRIs\n"
1419 "Display BGP tags for prefixes\n")
1421 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
, 1,
1425 DEFUN(show_ip_bgp_l2vpn_evpn_rd_tags
,
1426 show_ip_bgp_l2vpn_evpn_rd_tags_cmd
,
1427 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN tags",
1433 "Display information for a route distinguisher\n"
1434 "VPN Route Distinguisher\n" "Display BGP tags for prefixes\n")
1436 int idx_ext_community
= 0;
1438 struct prefix_rd prd
;
1440 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1442 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1444 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1447 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
, 1,
1451 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_routes
,
1452 show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
,
1453 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1459 "Detailed information on TCP and BGP neighbor connections\n"
1460 "IPv4 Neighbor to display information about\n"
1461 "IPv6 Neighbor to display information about\n"
1462 "Neighbor on BGP configured interface\n"
1463 "Display routes learned from neighbor\n" JSON_STR
)
1467 char *peerstr
= NULL
;
1468 bool uj
= use_json(argc
, argv
);
1469 afi_t afi
= AFI_L2VPN
;
1470 safi_t safi
= SAFI_EVPN
;
1471 struct bgp
*bgp
= NULL
;
1473 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1476 vty_out(vty
, "No index\n");
1480 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1481 argv_find(argv
, argc
, "neighbors", &idx
);
1482 peerstr
= argv
[++idx
]->arg
;
1484 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1487 json_object
*json_no
= NULL
;
1488 json_no
= json_object_new_object();
1489 json_object_string_add(json_no
, "warning",
1490 "Malformed address");
1491 vty_out(vty
, "%s\n",
1492 json_object_to_json_string(json_no
));
1493 json_object_free(json_no
);
1495 vty_out(vty
, "Malformed address: %s\n",
1499 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1501 json_object
*json_no
= NULL
;
1502 json_no
= json_object_new_object();
1503 json_object_string_add(
1505 "No such neighbor or address family");
1506 vty_out(vty
, "%s\n",
1507 json_object_to_json_string(json_no
));
1508 json_object_free(json_no
);
1510 vty_out(vty
, "%% No such neighbor or address family\n");
1514 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_neighbor
, peer
, 0,
1518 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_routes
,
1519 show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
,
1520 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> routes [json]",
1526 "Display information for a route distinguisher\n"
1527 "VPN Route Distinguisher\n"
1528 "Detailed information on TCP and BGP neighbor connections\n"
1529 "IPv4 Neighbor to display information about\n"
1530 "IPv6 Neighbor to display information about\n"
1531 "Neighbor on BGP configured interface\n"
1532 "Display routes learned from neighbor\n" JSON_STR
)
1534 int idx_ext_community
= 0;
1538 char *peerstr
= NULL
;
1539 struct prefix_rd prd
;
1540 bool uj
= use_json(argc
, argv
);
1541 afi_t afi
= AFI_L2VPN
;
1542 safi_t safi
= SAFI_EVPN
;
1543 struct bgp
*bgp
= NULL
;
1545 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1548 vty_out(vty
, "No index\n");
1552 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1553 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1556 json_object
*json_no
= NULL
;
1557 json_no
= json_object_new_object();
1558 json_object_string_add(json_no
, "warning",
1559 "Malformed Route Distinguisher");
1560 vty_out(vty
, "%s\n",
1561 json_object_to_json_string(json_no
));
1562 json_object_free(json_no
);
1564 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1568 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1569 argv_find(argv
, argc
, "neighbors", &idx
);
1570 peerstr
= argv
[++idx
]->arg
;
1572 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1575 json_object
*json_no
= NULL
;
1576 json_no
= json_object_new_object();
1577 json_object_string_add(json_no
, "warning",
1578 "Malformed address");
1579 vty_out(vty
, "%s\n",
1580 json_object_to_json_string(json_no
));
1581 json_object_free(json_no
);
1583 vty_out(vty
, "Malformed address: %s\n",
1587 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1589 json_object
*json_no
= NULL
;
1590 json_no
= json_object_new_object();
1591 json_object_string_add(
1593 "No such neighbor or address family");
1594 vty_out(vty
, "%s\n",
1595 json_object_to_json_string(json_no
));
1596 json_object_free(json_no
);
1598 vty_out(vty
, "%% No such neighbor or address family\n");
1602 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_neighbor
, peer
, 0,
1606 DEFUN(show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes
,
1607 show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
,
1608 "show [ip] bgp l2vpn evpn neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1614 "Detailed information on TCP and BGP neighbor connections\n"
1615 "IPv4 Neighbor to display information about\n"
1616 "IPv6 Neighbor to display information about\n"
1617 "Neighbor on BGP configured interface\n"
1618 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1622 bool uj
= use_json(argc
, argv
);
1623 struct bgp
*bgp
= NULL
;
1624 afi_t afi
= AFI_L2VPN
;
1625 safi_t safi
= SAFI_EVPN
;
1626 char *peerstr
= NULL
;
1631 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1634 vty_out(vty
, "No index\n");
1638 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1639 argv_find(argv
, argc
, "neighbors", &idx
);
1640 peerstr
= argv
[++idx
]->arg
;
1642 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1645 json_object
*json_no
= NULL
;
1646 json_no
= json_object_new_object();
1647 json_object_string_add(json_no
, "warning",
1648 "Malformed address");
1649 vty_out(vty
, "%s\n",
1650 json_object_to_json_string(json_no
));
1651 json_object_free(json_no
);
1653 vty_out(vty
, "Malformed address: %s\n",
1657 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1659 json_object
*json_no
= NULL
;
1660 json_no
= json_object_new_object();
1661 json_object_string_add(
1663 "No such neighbor or address family");
1664 vty_out(vty
, "%s\n",
1665 json_object_to_json_string(json_no
));
1666 json_object_free(json_no
);
1668 vty_out(vty
, "%% No such neighbor or address family\n");
1672 return show_adj_route_vpn(vty
, peer
, NULL
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1675 DEFUN(show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes
,
1676 show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
,
1677 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN neighbors <A.B.C.D|X:X::X:X|WORD> advertised-routes [json]",
1683 "Display information for a route distinguisher\n"
1684 "VPN Route Distinguisher\n"
1685 "Detailed information on TCP and BGP neighbor connections\n"
1686 "IPv4 Neighbor to display information about\n"
1687 "IPv6 Neighbor to display information about\n"
1688 "Neighbor on BGP configured interface\n"
1689 "Display the routes advertised to a BGP neighbor\n" JSON_STR
)
1691 int idx_ext_community
= 0;
1695 struct prefix_rd prd
;
1696 struct bgp
*bgp
= NULL
;
1697 bool uj
= use_json(argc
, argv
);
1698 char *peerstr
= NULL
;
1699 afi_t afi
= AFI_L2VPN
;
1700 safi_t safi
= SAFI_EVPN
;
1708 bgp_vty_find_and_parse_afi_safi_bgp(vty
, argv
, argc
, &idx
, &afi
, &safi
,
1711 vty_out(vty
, "No index\n");
1715 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1717 /* neighbors <A.B.C.D|X:X::X:X|WORD> */
1718 argv_find(argv
, argc
, "neighbors", &idx
);
1719 peerstr
= argv
[++idx
]->arg
;
1721 peer
= peer_lookup_in_view(vty
, bgp
, peerstr
, uj
);
1724 json_object
*json_no
= NULL
;
1725 json_no
= json_object_new_object();
1726 json_object_string_add(json_no
, "warning",
1727 "Malformed address");
1728 vty_out(vty
, "%s\n",
1729 json_object_to_json_string(json_no
));
1730 json_object_free(json_no
);
1732 vty_out(vty
, "Malformed address: %s\n",
1736 if (!peer
|| !peer
->afc
[AFI_L2VPN
][SAFI_EVPN
]) {
1738 json_object
*json_no
= NULL
;
1739 json_no
= json_object_new_object();
1740 json_object_string_add(
1742 "No such neighbor or address family");
1743 vty_out(vty
, "%s\n",
1744 json_object_to_json_string(json_no
));
1745 json_object_free(json_no
);
1747 vty_out(vty
, "%% No such neighbor or address family\n");
1751 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1754 json_object
*json_no
= NULL
;
1755 json_no
= json_object_new_object();
1756 json_object_string_add(json_no
, "warning",
1757 "Malformed Route Distinguisher");
1758 vty_out(vty
, "%s\n",
1759 json_object_to_json_string(json_no
));
1760 json_object_free(json_no
);
1762 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1766 return show_adj_route_vpn(vty
, peer
, &prd
, AFI_L2VPN
, SAFI_EVPN
, uj
);
1769 DEFUN(show_ip_bgp_l2vpn_evpn_all_overlay
,
1770 show_ip_bgp_l2vpn_evpn_all_overlay_cmd
,
1771 "show [ip] bgp l2vpn evpn all overlay [json]",
1777 "Display information about all EVPN NLRIs\n"
1778 "Display BGP Overlay Information for prefixes\n"
1781 return bgp_show_ethernet_vpn(vty
, NULL
, bgp_show_type_normal
, NULL
,
1782 SHOW_DISPLAY_OVERLAY
,
1783 use_json(argc
, argv
));
1786 DEFUN(show_ip_bgp_evpn_rd_overlay
,
1787 show_ip_bgp_evpn_rd_overlay_cmd
,
1788 "show [ip] bgp l2vpn evpn rd ASN:NN_OR_IP-ADDRESS:NN overlay",
1794 "Display information for a route distinguisher\n"
1795 "VPN Route Distinguisher\n"
1796 "Display BGP Overlay Information for prefixes\n")
1798 int idx_ext_community
= 0;
1800 struct prefix_rd prd
;
1802 argv_find(argv
, argc
, "ASN:NN_OR_IP-ADDRESS:NN", &idx_ext_community
);
1804 ret
= str2prefix_rd(argv
[idx_ext_community
]->arg
, &prd
);
1806 vty_out(vty
, "%% Malformed Route Distinguisher\n");
1809 return bgp_show_ethernet_vpn(vty
, &prd
, bgp_show_type_normal
, NULL
,
1810 SHOW_DISPLAY_OVERLAY
,
1811 use_json(argc
, argv
));
1814 DEFUN(show_bgp_l2vpn_evpn_com
,
1815 show_bgp_l2vpn_evpn_com_cmd
,
1816 "show bgp l2vpn evpn \
1817 <community AA:NN|large-community AA:BB:CC> \
1818 [exact-match] [json]",
1823 "Display routes matching the community\n"
1824 "Community number where AA and NN are (0-65535)\n"
1825 "Display routes matching the large-community\n"
1826 "List of large-community numbers\n"
1827 "Exact match of the communities\n"
1832 const char *clist_number_or_name
;
1833 int show_type
= bgp_show_type_normal
;
1834 struct community
*com
;
1835 struct lcommunity
*lcom
;
1837 if (argv_find(argv
, argc
, "large-community", &idx
)) {
1838 clist_number_or_name
= argv
[++idx
]->arg
;
1839 show_type
= bgp_show_type_lcommunity
;
1841 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1842 show_type
= bgp_show_type_lcommunity_exact
;
1844 lcom
= lcommunity_str2com(clist_number_or_name
);
1846 vty_out(vty
, "%% Large-community malformed\n");
1850 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, lcom
,
1851 SHOW_DISPLAY_STANDARD
,
1852 use_json(argc
, argv
));
1854 lcommunity_free(&lcom
);
1855 } else if (argv_find(argv
, argc
, "community", &idx
)) {
1856 clist_number_or_name
= argv
[++idx
]->arg
;
1857 show_type
= bgp_show_type_community
;
1859 if (++idx
< argc
&& strmatch(argv
[idx
]->text
, "exact-match"))
1860 show_type
= bgp_show_type_community_exact
;
1862 com
= community_str2com(clist_number_or_name
);
1865 vty_out(vty
, "%% Community malformed: %s\n",
1866 clist_number_or_name
);
1870 ret
= bgp_show_ethernet_vpn(vty
, NULL
, show_type
, com
,
1871 SHOW_DISPLAY_STANDARD
,
1872 use_json(argc
, argv
));
1873 community_free(&com
);
1879 /* For testing purpose, static route of EVPN RT-5. */
1880 DEFUN(evpnrt5_network
,
1881 evpnrt5_network_cmd
,
1882 "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]",
1883 "Specify a network to announce via BGP\n"
1886 "Specify Route Distinguisher\n"
1887 "VPN Route Distinguisher\n"
1889 "Ethernet Tag Value\n"
1892 "Ethernet Segment Identifier\n"
1893 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1895 "Gateway IP ( A.B.C.D )\n"
1896 "Gateway IPv6 ( X:X::X:X )\n"
1897 "Router Mac Ext Comm\n"
1898 "Router Mac address Value ( aa:bb:cc:dd:ee:ff format)\n"
1899 "Route-map to modify the attributes\n"
1900 "Name of the route map\n")
1902 int idx_ipv4_prefixlen
= 1;
1903 int idx_route_distinguisher
= 3;
1908 int idx_routermac
= 13;
1910 return bgp_static_set_safi(
1911 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1912 argv
[idx_route_distinguisher
]->arg
, argv
[idx_label
]->arg
, NULL
,
1913 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1914 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
,
1915 argv
[idx_routermac
]->arg
);
1918 /* For testing purpose, static route of EVPN RT-5. */
1919 DEFUN(no_evpnrt5_network
,
1920 no_evpnrt5_network_cmd
,
1921 "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>",
1923 "Specify a network to announce via BGP\n"
1926 "Specify Route Distinguisher\n"
1927 "VPN Route Distinguisher\n"
1929 "Ethernet Tag Value\n"
1932 "Ethernet Segment Identifier\n"
1933 "ESI value ( 00:11:22:33:44:55:66:77:88:99 format) \n"
1934 "Gateway IP\n" "Gateway IP ( A.B.C.D )\n" "Gateway IPv6 ( X:X::X:X )\n")
1936 int idx_ipv4_prefixlen
= 2;
1937 int idx_ext_community
= 4;
1942 return bgp_static_unset_safi(
1943 AFI_L2VPN
, SAFI_EVPN
, vty
, argv
[idx_ipv4_prefixlen
]->arg
,
1944 argv
[idx_ext_community
]->arg
, argv
[idx_label
]->arg
,
1945 BGP_EVPN_IP_PREFIX_ROUTE
, argv
[idx_esi
]->arg
,
1946 argv
[idx_gwip
]->arg
, argv
[idx_ethtag
]->arg
);
1949 static void evpn_import_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1951 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->import_rtl
);
1954 static void evpn_export_rt_delete_auto(struct bgp
*bgp
, struct bgpevpn
*vpn
)
1956 evpn_rt_delete_auto(bgp
, vpn
->vni
, vpn
->export_rtl
);
1960 * Configure the Import RTs for a VNI (vty handler). Caller expected to
1961 * check that this is a change.
1963 static void evpn_configure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1964 struct ecommunity
*ecomadd
)
1966 /* If the VNI is "live", we need to uninstall routes using the current
1967 * import RT(s) first before we update the import RT, and subsequently
1970 if (is_vni_live(vpn
))
1971 bgp_evpn_uninstall_routes(bgp
, vpn
);
1973 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
1974 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
1976 /* If the auto route-target is in use we must remove it */
1977 evpn_import_rt_delete_auto(bgp
, vpn
);
1979 /* Add new RT and rebuild the RT to VNI mapping */
1980 listnode_add_sort(vpn
->import_rtl
, ecomadd
);
1982 SET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
1983 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
1985 /* Install routes that match new import RT */
1986 if (is_vni_live(vpn
))
1987 bgp_evpn_install_routes(bgp
, vpn
);
1991 * Unconfigure Import RT(s) for a VNI (vty handler).
1993 static void evpn_unconfigure_import_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
1994 struct ecommunity
*ecomdel
)
1996 struct listnode
*node
, *nnode
, *node_to_del
;
1997 struct ecommunity
*ecom
;
1999 /* Along the lines of "configure" except we have to reset to the
2002 if (is_vni_live(vpn
))
2003 bgp_evpn_uninstall_routes(bgp
, vpn
);
2005 /* Cleanup the RT to VNI mapping and get rid of existing import RT. */
2006 bgp_evpn_unmap_vni_from_its_rts(bgp
, vpn
);
2008 /* Delete all import RTs */
2009 if (ecomdel
== NULL
) {
2010 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2011 ecommunity_free(&ecom
);
2012 list_delete_node(vpn
->import_rtl
, node
);
2016 /* Delete a specific import RT */
2020 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
, ecom
)) {
2021 if (ecommunity_match(ecom
, ecomdel
)) {
2022 ecommunity_free(&ecom
);
2029 list_delete_node(vpn
->import_rtl
, node_to_del
);
2032 assert(vpn
->import_rtl
);
2033 /* Reset to auto RT - this also rebuilds the RT to VNI mapping */
2034 if (list_isempty(vpn
->import_rtl
)) {
2035 UNSET_FLAG(vpn
->flags
, VNI_FLAG_IMPRT_CFGD
);
2036 bgp_evpn_derive_auto_rt_import(bgp
, vpn
);
2038 /* Rebuild the RT to VNI mapping */
2040 bgp_evpn_map_vni_to_its_rts(bgp
, vpn
);
2042 /* Install routes that match new import RT */
2043 if (is_vni_live(vpn
))
2044 bgp_evpn_install_routes(bgp
, vpn
);
2048 * Configure the Export RT for a VNI (vty handler). Caller expected to
2049 * check that this is a change. Note that only a single export RT is
2050 * allowed for a VNI and any change to configuration is implemented as
2051 * a "replace" (similar to other configuration).
2053 static void evpn_configure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2054 struct ecommunity
*ecomadd
)
2056 /* If the auto route-target is in use we must remove it */
2057 evpn_export_rt_delete_auto(bgp
, vpn
);
2059 listnode_add_sort(vpn
->export_rtl
, ecomadd
);
2060 SET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2062 if (is_vni_live(vpn
))
2063 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2067 * Unconfigure the Export RT for a VNI (vty handler)
2069 static void evpn_unconfigure_export_rt(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2070 struct ecommunity
*ecomdel
)
2072 struct listnode
*node
, *nnode
, *node_to_del
;
2073 struct ecommunity
*ecom
;
2075 /* Delete all export RTs */
2076 if (ecomdel
== NULL
) {
2077 /* Reset to default and process all routes. */
2078 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2079 ecommunity_free(&ecom
);
2080 list_delete_node(vpn
->export_rtl
, node
);
2084 /* Delete a specific export RT */
2088 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
, ecom
)) {
2089 if (ecommunity_match(ecom
, ecomdel
)) {
2090 ecommunity_free(&ecom
);
2097 list_delete_node(vpn
->export_rtl
, node_to_del
);
2100 assert(vpn
->export_rtl
);
2101 if (list_isempty(vpn
->export_rtl
)) {
2102 UNSET_FLAG(vpn
->flags
, VNI_FLAG_EXPRT_CFGD
);
2103 bgp_evpn_derive_auto_rt_export(bgp
, vpn
);
2106 if (is_vni_live(vpn
))
2107 bgp_evpn_handle_export_rt_change(bgp
, vpn
);
2111 * Configure RD for VRF
2113 static void evpn_configure_vrf_rd(struct bgp
*bgp_vrf
, struct prefix_rd
*rd
)
2115 /* If we have already advertise type-5 routes with a diffrent RD, we
2116 * have to delete and withdraw them firs
2118 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2121 memcpy(&bgp_vrf
->vrf_prd
, rd
, sizeof(struct prefix_rd
));
2122 SET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2124 /* We have a new RD for VRF.
2125 * Advertise all type-5 routes again with the new RD
2127 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2131 * Unconfigure RD for VRF
2133 static void evpn_unconfigure_vrf_rd(struct bgp
*bgp_vrf
)
2135 /* If we have already advertise type-5 routes with a diffrent RD, we
2136 * have to delete and withdraw them firs
2138 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 1);
2140 /* fall back to default RD */
2141 bgp_evpn_derive_auto_rd_for_vrf(bgp_vrf
);
2142 UNSET_FLAG(bgp_vrf
->vrf_flags
, BGP_VRF_RD_CFGD
);
2144 /* We have a new RD for VRF.
2145 * Advertise all type-5 routes again with the new RD
2147 bgp_evpn_handle_vrf_rd_change(bgp_vrf
, 0);
2151 * Configure RD for a VNI (vty handler)
2153 static void evpn_configure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2154 struct prefix_rd
*rd
)
2156 /* If the VNI is "live", we need to delete and withdraw this VNI's
2157 * local routes with the prior RD first. Then, after updating RD,
2158 * need to re-advertise.
2160 if (is_vni_live(vpn
))
2161 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2164 memcpy(&vpn
->prd
, rd
, sizeof(struct prefix_rd
));
2165 SET_FLAG(vpn
->flags
, VNI_FLAG_RD_CFGD
);
2167 if (is_vni_live(vpn
))
2168 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2172 * Unconfigure RD for a VNI (vty handler)
2174 static void evpn_unconfigure_rd(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2176 /* If the VNI is "live", we need to delete and withdraw this VNI's
2177 * local routes with the prior RD first. Then, after resetting RD
2178 * to automatic value, need to re-advertise.
2180 if (is_vni_live(vpn
))
2181 bgp_evpn_handle_rd_change(bgp
, vpn
, 1);
2183 /* reset RD to default */
2184 bgp_evpn_derive_auto_rd(bgp
, vpn
);
2186 if (is_vni_live(vpn
))
2187 bgp_evpn_handle_rd_change(bgp
, vpn
, 0);
2191 * Create VNI, if not already present (VTY handler). Mark as configured.
2193 static struct bgpevpn
*evpn_create_update_vni(struct bgp
*bgp
, vni_t vni
)
2195 struct bgpevpn
*vpn
;
2196 struct in_addr mcast_grp
= {INADDR_ANY
};
2201 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2203 /* Check if this L2VNI is already configured as L3VNI */
2204 if (bgp_evpn_lookup_l3vni_l2vni_table(vni
)) {
2207 "%u: Failed to create L2VNI %u, it is configured as L3VNI",
2212 /* tenant vrf will be updated when we get local_vni_add from
2215 vpn
= bgp_evpn_new(bgp
, vni
, bgp
->router_id
, 0, mcast_grp
);
2219 "%u: Failed to allocate VNI entry for VNI %u - at Config",
2225 /* Mark as configured. */
2226 SET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2231 * Delete VNI. If VNI does not exist in the system (i.e., just
2232 * configuration), all that is needed is to free it. Otherwise,
2233 * any parameters configured for the VNI need to be reset (with
2234 * appropriate action) and the VNI marked as unconfigured; the
2235 * VNI will continue to exist, purely as a "learnt" entity.
2237 static void evpn_delete_vni(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2239 assert(bgp
->vnihash
);
2241 if (!is_vni_live(vpn
)) {
2242 bgp_evpn_free(bgp
, vpn
);
2246 /* We need to take the unconfigure action for each parameter of this VNI
2247 * that is configured. Some optimization is possible, but not worth the
2248 * additional code for an operation that should be pretty rare.
2250 UNSET_FLAG(vpn
->flags
, VNI_FLAG_CFGD
);
2252 /* First, deal with the export side - RD and export RT changes. */
2253 if (is_rd_configured(vpn
))
2254 evpn_unconfigure_rd(bgp
, vpn
);
2255 if (is_export_rt_configured(vpn
))
2256 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
2258 /* Next, deal with the import side. */
2259 if (is_import_rt_configured(vpn
))
2260 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
2264 * Display import RT mapping to VRFs (vty handler)
2265 * bgp_evpn: evpn bgp instance
2267 static void evpn_show_vrf_import_rts(struct vty
*vty
, struct bgp
*bgp_evpn
,
2275 hash_iterate(bgp_evpn
->vrf_import_rt_hash
,
2276 (void (*)(struct hash_bucket
*,
2277 void *))show_vrf_import_rt_entry
,
2282 * Display import RT mapping to VNIs (vty handler)
2284 static void evpn_show_import_rts(struct vty
*vty
, struct bgp
*bgp
,
2293 bgp
->import_rt_hash
,
2294 (void (*)(struct hash_bucket
*, void *))show_import_rt_entry
,
2299 * Display EVPN routes for all VNIs - vty handler.
2301 static void evpn_show_routes_vni_all(struct vty
*vty
, struct bgp
*bgp
,
2302 struct in_addr vtep_ip
, json_object
*json
,
2306 struct vni_walk_ctx wctx
;
2308 num_vnis
= hashcount(bgp
->vnihash
);
2311 memset(&wctx
, 0, sizeof(struct vni_walk_ctx
));
2314 wctx
.vtep_ip
= vtep_ip
;
2316 wctx
.detail
= detail
;
2317 hash_iterate(bgp
->vnihash
, (void (*)(struct hash_bucket
*,
2318 void *))show_vni_routes_hash
,
2323 * Display EVPN routes for a VNI -- for specific type-3 route (vty handler).
2325 static void evpn_show_route_vni_multicast(struct vty
*vty
, struct bgp
*bgp
,
2326 vni_t vni
, struct in_addr orig_ip
,
2329 struct bgpevpn
*vpn
;
2330 struct prefix_evpn p
;
2331 struct bgp_dest
*dest
;
2332 struct bgp_path_info
*pi
;
2333 uint32_t path_cnt
= 0;
2336 json_object
*json_paths
= NULL
;
2342 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2344 vty_out(vty
, "VNI not found\n");
2348 /* See if route exists. */
2349 build_evpn_type3_prefix(&p
, orig_ip
);
2350 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2351 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2353 vty_out(vty
, "%% Network not in table\n");
2358 json_paths
= json_object_new_array();
2360 /* Prefix and num paths displayed once per prefix. */
2361 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2363 /* Display each path for this prefix. */
2364 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2365 json_object
*json_path
= NULL
;
2368 json_path
= json_object_new_array();
2370 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
, json_path
);
2373 json_object_array_add(json_paths
, json_path
);
2380 json_object_object_add(json
, "paths", json_paths
);
2382 json_object_int_add(json
, "numPaths", path_cnt
);
2384 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2390 * Display EVPN routes for a VNI -- for specific MAC and/or IP (vty handler).
2391 * By definition, only matching type-2 route will be displayed.
2393 static void evpn_show_route_vni_macip(struct vty
*vty
, struct bgp
*bgp
,
2394 vni_t vni
, struct ethaddr
*mac
,
2395 struct ipaddr
*ip
, json_object
*json
)
2397 struct bgpevpn
*vpn
;
2398 struct prefix_evpn p
;
2399 struct bgp_dest
*dest
;
2400 struct bgp_path_info
*pi
;
2401 uint32_t path_cnt
= 0;
2404 json_object
*json_paths
= NULL
;
2410 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2413 vty_out(vty
, "VNI not found\n");
2417 /* See if route exists. Look for both non-sticky and sticky. */
2418 build_evpn_type2_prefix(&p
, mac
, ip
);
2419 dest
= bgp_node_lookup(vpn
->route_table
, (struct prefix
*)&p
);
2420 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2422 vty_out(vty
, "%% Network not in table\n");
2427 json_paths
= json_object_new_array();
2429 /* Prefix and num paths displayed once per prefix. */
2430 route_vty_out_detail_header(vty
, bgp
, dest
, NULL
, afi
, safi
, json
);
2432 /* Display each path for this prefix. */
2433 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2434 json_object
*json_path
= NULL
;
2437 json_path
= json_object_new_array();
2439 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
, json_path
);
2442 json_object_array_add(json_paths
, json_path
);
2449 json_object_object_add(json
, "paths", json_paths
);
2451 json_object_int_add(json
, "numPaths", path_cnt
);
2453 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2458 /* Disaplay EVPN routes for a ESI - VTY handler */
2459 static void evpn_show_routes_esi(struct vty
*vty
, struct bgp
*bgp
,
2460 esi_t
*esi
, json_object
*json
)
2462 struct bgp_evpn_es
*es
= NULL
;
2465 es
= bgp_evpn_es_find(esi
);
2468 vty_out(vty
, "ESI not found\n");
2472 show_esi_routes(bgp
, es
, vty
, json
);
2476 * Display EVPN routes for a VNI - vty handler.
2477 * If 'type' is non-zero, only routes matching that type are shown.
2478 * If the vtep_ip is non zero, only routes behind that vtep are shown
2480 static void evpn_show_routes_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2481 int type
, struct in_addr vtep_ip
,
2484 struct bgpevpn
*vpn
;
2487 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2490 vty_out(vty
, "VNI not found\n");
2494 /* Walk this VNI's route table and display appropriate routes. */
2495 show_vni_routes(bgp
, vpn
, type
, vty
, vtep_ip
, json
, 0);
2499 * Display BGP EVPN routing table -- for specific RD and MAC and/or
2500 * IP (vty handler). By definition, only matching type-2 route will be
2503 static void evpn_show_route_rd_macip(struct vty
*vty
, struct bgp
*bgp
,
2504 struct prefix_rd
*prd
, struct ethaddr
*mac
,
2505 struct ipaddr
*ip
, json_object
*json
)
2507 struct prefix_evpn p
;
2508 struct bgp_dest
*dest
;
2509 struct bgp_path_info
*pi
;
2512 uint32_t path_cnt
= 0;
2513 json_object
*json_paths
= NULL
;
2514 char prefix_str
[BUFSIZ
];
2519 /* See if route exists. Look for both non-sticky and sticky. */
2520 build_evpn_type2_prefix(&p
, mac
, ip
);
2521 dest
= bgp_afi_node_lookup(bgp
->rib
[afi
][safi
], afi
, safi
,
2522 (struct prefix
*)&p
, prd
);
2523 if (!dest
|| !bgp_dest_has_bgp_path_info_data(dest
)) {
2525 vty_out(vty
, "%% Network not in table\n");
2529 prefix2str(&p
, prefix_str
, sizeof(prefix_str
));
2531 /* Prefix and num paths displayed once per prefix. */
2532 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
, safi
, json
);
2535 json_paths
= json_object_new_array();
2537 /* Display each path for this prefix. */
2538 for (pi
= bgp_dest_get_bgp_path_info(dest
); pi
; pi
= pi
->next
) {
2539 json_object
*json_path
= NULL
;
2542 json_path
= json_object_new_array();
2544 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
, json_path
);
2547 json_object_array_add(json_paths
, json_path
);
2552 if (json
&& path_cnt
) {
2554 json_object_object_add(json
, prefix_str
, json_paths
);
2555 json_object_int_add(json
, "numPaths", path_cnt
);
2557 vty_out(vty
, "\nDisplayed %u paths for requested prefix\n",
2563 * Display BGP EVPN routing table -- for specific RD (vty handler)
2564 * If 'type' is non-zero, only routes matching that type are shown.
2566 static void evpn_show_route_rd(struct vty
*vty
, struct bgp
*bgp
,
2567 struct prefix_rd
*prd
, int type
,
2570 struct bgp_dest
*rd_dest
;
2571 struct bgp_table
*table
;
2572 struct bgp_dest
*dest
;
2573 struct bgp_path_info
*pi
;
2577 uint32_t prefix_cnt
, path_cnt
;
2578 char rd_str
[RD_ADDRSTRLEN
];
2579 json_object
*json_rd
= NULL
;
2580 int add_rd_to_json
= 0;
2584 prefix_cnt
= path_cnt
= 0;
2586 prefix_rd2str(prd
, rd_str
, sizeof(rd_str
));
2588 rd_dest
= bgp_node_lookup(bgp
->rib
[afi
][safi
], (struct prefix
*)prd
);
2592 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2597 json_rd
= json_object_new_object();
2598 json_object_string_add(json_rd
, "rd", rd_str
);
2601 /* Display all prefixes with this RD. */
2602 for (dest
= bgp_table_top(table
); dest
; dest
= bgp_route_next(dest
)) {
2603 const struct prefix_evpn
*evp
=
2604 (const struct prefix_evpn
*)bgp_dest_get_prefix(dest
);
2605 json_object
*json_prefix
= NULL
;
2606 json_object
*json_paths
= NULL
;
2607 char prefix_str
[BUFSIZ
];
2608 int add_prefix_to_json
= 0;
2610 prefix2str((struct prefix_evpn
*)evp
, prefix_str
,
2611 sizeof(prefix_str
));
2613 if (type
&& evp
->prefix
.route_type
!= type
)
2617 json_prefix
= json_object_new_object();
2619 pi
= bgp_dest_get_bgp_path_info(dest
);
2621 /* RD header and legend - once overall. */
2622 if (rd_header
&& !json
) {
2624 "EVPN type-1 prefix: [1]:[ESI]:[EthTag]:[IPlen]:[VTEP-IP]\n");
2626 "EVPN type-2 prefix: [2]:[EthTag]:[MAClen]:[MAC]\n");
2628 "EVPN type-3 prefix: [3]:[EthTag]:[IPlen]:[OrigIP]\n");
2630 "EVPN type-4 prefix: [4]:[ESI]:[IPlen]:[OrigIP]\n");
2632 "EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]\n\n");
2636 /* Prefix and num paths displayed once per prefix. */
2637 route_vty_out_detail_header(vty
, bgp
, dest
, prd
, afi
,
2644 json_paths
= json_object_new_array();
2646 /* Display each path for this prefix. */
2647 for (; pi
; pi
= pi
->next
) {
2648 json_object
*json_path
= NULL
;
2651 json_path
= json_object_new_array();
2653 route_vty_out_detail(vty
, bgp
, dest
, pi
, afi
, safi
,
2657 json_object_array_add(json_paths
, json_path
);
2660 add_prefix_to_json
= 1;
2665 if (add_prefix_to_json
) {
2666 json_object_object_add(json_prefix
, "paths",
2668 json_object_object_add(json_rd
, prefix_str
,
2671 json_object_free(json_paths
);
2672 json_object_free(json_prefix
);
2681 json_object_object_add(json
, rd_str
, json_rd
);
2683 json_object_free(json_rd
);
2687 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2688 json_object_int_add(json
, "numPaths", path_cnt
);
2690 if (prefix_cnt
== 0)
2691 vty_out(vty
, "No prefixes exist with this RD%s\n",
2692 type
? " (of requested type)" : "");
2695 "\nDisplayed %u prefixes (%u paths) with this RD%s\n",
2696 prefix_cnt
, path_cnt
,
2697 type
? " (of requested type)" : "");
2702 * Display BGP EVPN routing table - all routes (vty handler).
2703 * If 'type' is non-zero, only routes matching that type are shown.
2705 static void evpn_show_all_routes(struct vty
*vty
, struct bgp
*bgp
, int type
,
2706 json_object
*json
, int detail
)
2708 struct bgp_dest
*rd_dest
;
2709 struct bgp_table
*table
;
2710 struct bgp_dest
*dest
;
2711 struct bgp_path_info
*pi
;
2712 int header
= detail
? 0 : 1;
2716 uint32_t prefix_cnt
, path_cnt
;
2720 prefix_cnt
= path_cnt
= 0;
2722 /* EVPN routing table is a 2-level table with the first level being
2725 for (rd_dest
= bgp_table_top(bgp
->rib
[afi
][safi
]); rd_dest
;
2726 rd_dest
= bgp_route_next(rd_dest
)) {
2727 char rd_str
[RD_ADDRSTRLEN
];
2728 json_object
*json_rd
= NULL
; /* contains routes for an RD */
2729 int add_rd_to_json
= 0;
2731 const struct prefix
*rd_destp
= bgp_dest_get_prefix(rd_dest
);
2733 table
= bgp_dest_get_bgp_table_info(rd_dest
);
2737 tbl_ver
= table
->version
;
2738 prefix_rd2str((struct prefix_rd
*)rd_destp
, rd_str
,
2742 json_rd
= json_object_new_object();
2746 /* Display all prefixes for an RD */
2747 for (dest
= bgp_table_top(table
); dest
;
2748 dest
= bgp_route_next(dest
)) {
2749 json_object
*json_prefix
=
2750 NULL
; /* contains prefix under a RD */
2751 json_object
*json_paths
=
2752 NULL
; /* array of paths under a prefix*/
2753 const struct prefix_evpn
*evp
=
2754 (const struct prefix_evpn
*)bgp_dest_get_prefix(
2756 char prefix_str
[BUFSIZ
];
2757 int add_prefix_to_json
= 0;
2758 const struct prefix
*p
= bgp_dest_get_prefix(dest
);
2760 prefix2str((struct prefix_evpn
*)p
, prefix_str
,
2761 sizeof(prefix_str
));
2763 if (type
&& evp
->prefix
.route_type
!= type
)
2766 pi
= bgp_dest_get_bgp_path_info(dest
);
2768 /* Overall header/legend displayed once. */
2770 bgp_evpn_show_route_header(vty
, bgp
,
2775 "%19s Extended Community\n"
2780 /* RD header - per RD. */
2782 bgp_evpn_show_route_rd_header(
2783 vty
, rd_dest
, json_rd
, rd_str
,
2792 json_prefix
= json_object_new_object();
2793 json_paths
= json_object_new_array();
2794 json_object_string_add(json_prefix
, "prefix",
2796 json_object_int_add(json_prefix
, "prefixLen",
2800 /* Prefix and num paths displayed once per prefix. */
2802 route_vty_out_detail_header(
2804 (struct prefix_rd
*)rd_destp
, AFI_L2VPN
,
2805 SAFI_EVPN
, json_prefix
);
2807 /* For EVPN, the prefix is displayed for each path (to
2809 * with code that already exists).
2811 for (; pi
; pi
= pi
->next
) {
2812 json_object
*json_path
= NULL
;
2814 add_prefix_to_json
= 1;
2818 json_path
= json_object_new_array();
2821 route_vty_out_detail(
2822 vty
, bgp
, dest
, pi
, AFI_L2VPN
,
2823 SAFI_EVPN
, json_path
);
2825 route_vty_out(vty
, p
, pi
, 0, SAFI_EVPN
,
2829 json_object_array_add(json_paths
,
2834 if (add_prefix_to_json
) {
2835 json_object_object_add(json_prefix
,
2838 json_object_object_add(json_rd
,
2842 json_object_free(json_prefix
);
2843 json_object_free(json_paths
);
2852 json_object_object_add(json
, rd_str
, json_rd
);
2854 json_object_free(json_rd
);
2861 json_object_int_add(json
, "numPrefix", prefix_cnt
);
2862 json_object_int_add(json
, "numPaths", path_cnt
);
2864 if (prefix_cnt
== 0) {
2865 vty_out(vty
, "No EVPN prefixes %sexist\n",
2866 type
? "(of requested type) " : "");
2868 vty_out(vty
, "\nDisplayed %u prefixes (%u paths)%s\n",
2869 prefix_cnt
, path_cnt
,
2870 type
? " (of requested type)" : "");
2876 * Display specified VNI (vty handler)
2878 static void evpn_show_vni(struct vty
*vty
, struct bgp
*bgp
, vni_t vni
,
2882 struct bgpevpn
*vpn
;
2884 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
2887 display_vni(vty
, vpn
, json
);
2889 struct bgp
*bgp_temp
;
2890 struct listnode
*node
= NULL
;
2892 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
2893 if (bgp_temp
->l3vni
== vni
) {
2895 display_l3vni(vty
, bgp_temp
, json
);
2902 vty_out(vty
, "{}\n");
2904 vty_out(vty
, "VNI not found\n");
2911 * Display a VNI (upon user query).
2913 static void evpn_show_all_vnis(struct vty
*vty
, struct bgp
*bgp
,
2917 struct bgp
*bgp_temp
= NULL
;
2918 struct listnode
*node
;
2922 vty_out(vty
, "Flags: * - Kernel\n");
2923 vty_out(vty
, " %-10s %-4s %-21s %-25s %-25s %-37s\n", "VNI",
2924 "Type", "RD", "Import RT", "Export RT", "Tenant VRF");
2927 /* print all L2 VNIS */
2930 hash_iterate(bgp
->vnihash
,
2931 (void (*)(struct hash_bucket
*, void *))show_vni_entry
,
2934 /* print all L3 VNIs */
2935 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
))
2936 show_l3vni_entry(vty
, bgp_temp
, json
);
2940 * evpn - enable advertisement of svi MAC-IP
2942 static void evpn_set_advertise_svi_macip(struct bgp
*bgp
, struct bgpevpn
*vpn
,
2946 if (set
&& bgp
->evpn_info
->advertise_svi_macip
)
2948 else if (!set
&& !bgp
->evpn_info
->advertise_svi_macip
)
2951 bgp
->evpn_info
->advertise_svi_macip
= set
;
2952 bgp_zebra_advertise_svi_macip(bgp
,
2953 bgp
->evpn_info
->advertise_svi_macip
, 0);
2955 if (set
&& vpn
->advertise_svi_macip
)
2957 else if (!set
&& !vpn
->advertise_svi_macip
)
2960 vpn
->advertise_svi_macip
= set
;
2961 bgp_zebra_advertise_svi_macip(bgp
, vpn
->advertise_svi_macip
,
2967 * evpn - enable advertisement of default g/w
2969 static void evpn_set_advertise_default_gw(struct bgp
*bgp
, struct bgpevpn
*vpn
)
2972 if (bgp
->advertise_gw_macip
)
2975 bgp
->advertise_gw_macip
= 1;
2976 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
2978 if (vpn
->advertise_gw_macip
)
2981 vpn
->advertise_gw_macip
= 1;
2982 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
2989 * evpn - disable advertisement of default g/w
2991 static void evpn_unset_advertise_default_gw(struct bgp
*bgp
,
2992 struct bgpevpn
*vpn
)
2995 if (!bgp
->advertise_gw_macip
)
2998 bgp
->advertise_gw_macip
= 0;
2999 bgp_zebra_advertise_gw_macip(bgp
, bgp
->advertise_gw_macip
, 0);
3001 if (!vpn
->advertise_gw_macip
)
3004 vpn
->advertise_gw_macip
= 0;
3005 bgp_zebra_advertise_gw_macip(bgp
, vpn
->advertise_gw_macip
,
3012 * evpn - enable advertisement of default g/w
3014 static void evpn_process_default_originate_cmd(struct bgp
*bgp_vrf
,
3015 afi_t afi
, bool add
)
3017 safi_t safi
= SAFI_UNICAST
; /* ipv4/ipv6 unicast */
3020 /* bail if we are already advertising default route */
3021 if (evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3025 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3026 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3027 else if (afi
== AFI_IP6
)
3028 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3029 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3031 /* bail out if we havent advertised the default route */
3032 if (!evpn_default_originate_set(bgp_vrf
, afi
, safi
))
3035 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3036 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
);
3037 else if (afi
== AFI_IP6
)
3038 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3039 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
);
3042 bgp_evpn_install_uninstall_default_route(bgp_vrf
, afi
, safi
, add
);
3046 * evpn - enable advertisement of default g/w
3048 static void evpn_set_advertise_subnet(struct bgp
*bgp
,
3049 struct bgpevpn
*vpn
)
3051 if (vpn
->advertise_subnet
)
3054 vpn
->advertise_subnet
= 1;
3055 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3059 * evpn - disable advertisement of default g/w
3061 static void evpn_unset_advertise_subnet(struct bgp
*bgp
, struct bgpevpn
*vpn
)
3063 if (!vpn
->advertise_subnet
)
3066 vpn
->advertise_subnet
= 0;
3067 bgp_zebra_advertise_subnet(bgp
, vpn
->advertise_subnet
, vpn
->vni
);
3071 * EVPN (VNI advertisement) enabled. Register with zebra.
3073 static void evpn_set_advertise_all_vni(struct bgp
*bgp
)
3075 bgp
->advertise_all_vni
= 1;
3077 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3081 * EVPN (VNI advertisement) disabled. De-register with zebra. Cleanup VNI
3082 * cache, EVPN routes (delete and withdraw from peers).
3084 static void evpn_unset_advertise_all_vni(struct bgp
*bgp
)
3086 bgp
->advertise_all_vni
= 0;
3087 bgp_set_evpn(bgp_get_default());
3088 bgp_zebra_advertise_all_vni(bgp
, bgp
->advertise_all_vni
);
3089 bgp_evpn_cleanup_on_disable(bgp
);
3093 * EVPN - use RFC8365 to auto-derive RT
3095 static void evpn_set_advertise_autort_rfc8365(struct bgp
*bgp
)
3097 bgp
->advertise_autort_rfc8365
= 1;
3098 bgp_evpn_handle_autort_change(bgp
);
3102 * EVPN - don't use RFC8365 to auto-derive RT
3104 static void evpn_unset_advertise_autort_rfc8365(struct bgp
*bgp
)
3106 bgp
->advertise_autort_rfc8365
= 0;
3107 bgp_evpn_handle_autort_change(bgp
);
3110 static void write_vni_config(struct vty
*vty
, struct bgpevpn
*vpn
)
3112 char buf1
[RD_ADDRSTRLEN
];
3114 struct listnode
*node
, *nnode
;
3115 struct ecommunity
*ecom
;
3117 if (is_vni_configured(vpn
)) {
3118 vty_out(vty
, " vni %d\n", vpn
->vni
);
3119 if (is_rd_configured(vpn
))
3120 vty_out(vty
, " rd %s\n",
3121 prefix_rd2str(&vpn
->prd
, buf1
, sizeof(buf1
)));
3123 if (is_import_rt_configured(vpn
)) {
3124 for (ALL_LIST_ELEMENTS(vpn
->import_rtl
, node
, nnode
,
3126 ecom_str
= ecommunity_ecom2str(
3127 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3128 vty_out(vty
, " route-target import %s\n",
3130 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3134 if (is_export_rt_configured(vpn
)) {
3135 for (ALL_LIST_ELEMENTS(vpn
->export_rtl
, node
, nnode
,
3137 ecom_str
= ecommunity_ecom2str(
3138 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
3139 vty_out(vty
, " route-target export %s\n",
3141 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
3145 if (vpn
->advertise_gw_macip
)
3146 vty_out(vty
, " advertise-default-gw\n");
3148 if (vpn
->advertise_svi_macip
)
3149 vty_out(vty
, " advertise-svi-ip\n");
3151 if (vpn
->advertise_subnet
)
3152 vty_out(vty
, " advertise-subnet\n");
3154 vty_out(vty
, " exit-vni\n");
3158 #ifndef VTYSH_EXTRACT_PL
3159 #include "bgpd/bgp_evpn_vty_clippy.c"
3162 DEFPY(bgp_evpn_flood_control
,
3163 bgp_evpn_flood_control_cmd
,
3164 "[no$no] flooding <disable$disable|head-end-replication$her>",
3166 "Specify handling for BUM packets\n"
3167 "Do not flood any BUM packets\n"
3168 "Flood BUM packets using head-end replication\n")
3170 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3171 enum vxlan_flood_control flood_ctrl
;
3177 flood_ctrl
= VXLAN_FLOOD_DISABLED
;
3179 flood_ctrl
= VXLAN_FLOOD_HEAD_END_REPL
;
3183 if (bgp
->vxlan_flood_ctrl
== flood_ctrl
)
3186 bgp
->vxlan_flood_ctrl
= flood_ctrl
;
3187 bgp_evpn_flood_control_change(bgp
);
3192 DEFUN (bgp_evpn_advertise_default_gw_vni
,
3193 bgp_evpn_advertise_default_gw_vni_cmd
,
3194 "advertise-default-gw",
3195 "Advertise default g/w mac-ip routes in EVPN for a VNI\n")
3197 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3198 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3203 evpn_set_advertise_default_gw(bgp
, vpn
);
3208 DEFUN (no_bgp_evpn_advertise_default_vni_gw
,
3209 no_bgp_evpn_advertise_default_gw_vni_cmd
,
3210 "no advertise-default-gw",
3212 "Withdraw default g/w mac-ip routes from EVPN for a VNI\n")
3214 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3215 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3220 evpn_unset_advertise_default_gw(bgp
, vpn
);
3226 DEFUN (bgp_evpn_advertise_default_gw
,
3227 bgp_evpn_advertise_default_gw_cmd
,
3228 "advertise-default-gw",
3229 "Advertise All default g/w mac-ip routes in EVPN\n")
3231 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3236 if (!EVPN_ENABLED(bgp
)) {
3238 "This command is only supported under the EVPN VRF\n");
3242 evpn_set_advertise_default_gw(bgp
, NULL
);
3247 DEFUN (no_bgp_evpn_advertise_default_gw
,
3248 no_bgp_evpn_advertise_default_gw_cmd
,
3249 "no advertise-default-gw",
3251 "Withdraw All default g/w mac-ip routes from EVPN\n")
3253 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3258 if (!EVPN_ENABLED(bgp
)) {
3260 "This command is only supported under the EVPN VRF\n");
3264 evpn_unset_advertise_default_gw(bgp
, NULL
);
3269 DEFUN (bgp_evpn_advertise_all_vni
,
3270 bgp_evpn_advertise_all_vni_cmd
,
3271 "advertise-all-vni",
3272 "Advertise All local VNIs\n")
3274 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3275 struct bgp
*bgp_evpn
= NULL
;
3280 bgp_evpn
= bgp_get_evpn();
3281 if (bgp_evpn
&& bgp_evpn
!= bgp
) {
3282 vty_out(vty
, "%% Please unconfigure EVPN in VRF %s\n",
3284 return CMD_WARNING_CONFIG_FAILED
;
3287 evpn_set_advertise_all_vni(bgp
);
3291 DEFUN (no_bgp_evpn_advertise_all_vni
,
3292 no_bgp_evpn_advertise_all_vni_cmd
,
3293 "no advertise-all-vni",
3295 "Advertise All local VNIs\n")
3297 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3301 evpn_unset_advertise_all_vni(bgp
);
3305 DEFUN (bgp_evpn_advertise_autort_rfc8365
,
3306 bgp_evpn_advertise_autort_rfc8365_cmd
,
3307 "autort rfc8365-compatible",
3308 "Auto-derivation of RT\n"
3309 "Auto-derivation of RT using RFC8365\n")
3311 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3315 evpn_set_advertise_autort_rfc8365(bgp
);
3319 DEFUN (no_bgp_evpn_advertise_autort_rfc8365
,
3320 no_bgp_evpn_advertise_autort_rfc8365_cmd
,
3321 "no autort rfc8365-compatible",
3323 "Auto-derivation of RT\n"
3324 "Auto-derivation of RT using RFC8365\n")
3326 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3330 evpn_unset_advertise_autort_rfc8365(bgp
);
3334 DEFUN (bgp_evpn_default_originate
,
3335 bgp_evpn_default_originate_cmd
,
3336 "default-originate <ipv4 | ipv6>",
3337 "originate a default route\n"
3338 "ipv4 address family\n"
3339 "ipv6 address family\n")
3343 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3347 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3348 evpn_process_default_originate_cmd(bgp_vrf
, afi
, true);
3352 DEFUN (no_bgp_evpn_default_originate
,
3353 no_bgp_evpn_default_originate_cmd
,
3354 "no default-originate <ipv4 | ipv6>",
3356 "withdraw a default route\n"
3357 "ipv4 address family\n"
3358 "ipv6 address family\n")
3362 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3366 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3367 evpn_process_default_originate_cmd(bgp_vrf
, afi
, false);
3371 DEFPY (dup_addr_detection
,
3372 dup_addr_detection_cmd
,
3373 "dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val]",
3374 "Duplicate address detection\n"
3375 "Max allowed moves before address detected as duplicate\n"
3376 "Num of max allowed moves (2-1000) default 5\n"
3377 "Duplicate address detection time\n"
3378 "Time in seconds (2-1800) default 180\n")
3380 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3385 if (!EVPN_ENABLED(bgp_vrf
)) {
3387 "This command is only supported under the EVPN VRF\n");
3391 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3394 bgp_vrf
->evpn_info
->dad_time
= time_val
;
3396 bgp_vrf
->evpn_info
->dad_max_moves
= max_moves_val
;
3398 bgp_zebra_dup_addr_detection(bgp_vrf
);
3403 DEFPY (dup_addr_detection_auto_recovery
,
3404 dup_addr_detection_auto_recovery_cmd
,
3405 "dup-addr-detection freeze <permanent |(30-3600)$freeze_time_val>",
3406 "Duplicate address detection\n"
3407 "Duplicate address detection freeze\n"
3408 "Duplicate address detection permanent freeze\n"
3409 "Duplicate address detection freeze time (30-3600)\n")
3411 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3412 uint32_t freeze_time
= freeze_time_val
;
3417 if (!EVPN_ENABLED(bgp_vrf
)) {
3419 "This command is only supported under the EVPN VRF\n");
3423 bgp_vrf
->evpn_info
->dup_addr_detect
= true;
3424 bgp_vrf
->evpn_info
->dad_freeze
= true;
3425 bgp_vrf
->evpn_info
->dad_freeze_time
= freeze_time
;
3427 bgp_zebra_dup_addr_detection(bgp_vrf
);
3432 DEFPY (no_dup_addr_detection
,
3433 no_dup_addr_detection_cmd
,
3434 "no dup-addr-detection [max-moves (2-1000)$max_moves_val time (2-1800)$time_val | freeze <permanent$permanent_val | (30-3600)$freeze_time_val>]",
3436 "Duplicate address detection\n"
3437 "Max allowed moves before address detected as duplicate\n"
3438 "Num of max allowed moves (2-1000) default 5\n"
3439 "Duplicate address detection time\n"
3440 "Time in seconds (2-1800) default 180\n"
3441 "Duplicate address detection freeze\n"
3442 "Duplicate address detection permanent freeze\n"
3443 "Duplicate address detection freeze time (30-3600)\n")
3445 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
3446 uint32_t max_moves
= (uint32_t)max_moves_val
;
3447 uint32_t freeze_time
= (uint32_t)freeze_time_val
;
3452 if (!EVPN_ENABLED(bgp_vrf
)) {
3454 "This command is only supported under the EVPN VRF\n");
3459 if (!bgp_vrf
->evpn_info
->dup_addr_detect
)
3461 /* Reset all parameters to default. */
3462 bgp_vrf
->evpn_info
->dup_addr_detect
= false;
3463 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3464 bgp_vrf
->evpn_info
->dad_max_moves
= EVPN_DAD_DEFAULT_MAX_MOVES
;
3465 bgp_vrf
->evpn_info
->dad_freeze
= false;
3466 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3469 if (bgp_vrf
->evpn_info
->dad_max_moves
!= max_moves
) {
3471 "%% Value does not match with config\n");
3474 bgp_vrf
->evpn_info
->dad_max_moves
=
3475 EVPN_DAD_DEFAULT_MAX_MOVES
;
3479 if (bgp_vrf
->evpn_info
->dad_time
!= time_val
) {
3481 "%% Value does not match with config\n");
3484 bgp_vrf
->evpn_info
->dad_time
= EVPN_DAD_DEFAULT_TIME
;
3488 if (bgp_vrf
->evpn_info
->dad_freeze_time
3491 "%% Value does not match with config\n");
3494 bgp_vrf
->evpn_info
->dad_freeze_time
= 0;
3495 bgp_vrf
->evpn_info
->dad_freeze
= false;
3498 if (permanent_val
) {
3499 if (bgp_vrf
->evpn_info
->dad_freeze_time
) {
3501 "%% Value does not match with config\n");
3504 bgp_vrf
->evpn_info
->dad_freeze
= false;
3508 bgp_zebra_dup_addr_detection(bgp_vrf
);
3513 DEFPY(bgp_evpn_advertise_svi_ip
,
3514 bgp_evpn_advertise_svi_ip_cmd
,
3515 "[no$no] advertise-svi-ip",
3517 "Advertise svi mac-ip routes in EVPN\n")
3519 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3524 if (!EVPN_ENABLED(bgp
)) {
3526 "This command is only supported under EVPN VRF\n");
3531 evpn_set_advertise_svi_macip(bgp
, NULL
, 0);
3533 evpn_set_advertise_svi_macip(bgp
, NULL
, 1);
3538 DEFPY(bgp_evpn_advertise_svi_ip_vni
,
3539 bgp_evpn_advertise_svi_ip_vni_cmd
,
3540 "[no$no] advertise-svi-ip",
3542 "Advertise svi mac-ip routes in EVPN for a VNI\n")
3544 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3545 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3551 evpn_set_advertise_svi_macip(bgp
, vpn
, 0);
3553 evpn_set_advertise_svi_macip(bgp
, vpn
, 1);
3558 DEFUN_HIDDEN (bgp_evpn_advertise_vni_subnet
,
3559 bgp_evpn_advertise_vni_subnet_cmd
,
3561 "Advertise the subnet corresponding to VNI\n")
3563 struct bgp
*bgp_vrf
= NULL
;
3564 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3565 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3570 bgp_vrf
= bgp_lookup_by_vrf_id(vpn
->tenant_vrf_id
);
3574 evpn_set_advertise_subnet(bgp
, vpn
);
3578 DEFUN_HIDDEN (no_bgp_evpn_advertise_vni_subnet
,
3579 no_bgp_evpn_advertise_vni_subnet_cmd
,
3580 "no advertise-subnet",
3582 "Advertise All local VNIs\n")
3584 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
3585 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
3590 evpn_unset_advertise_subnet(bgp
, vpn
);
3594 DEFUN (bgp_evpn_advertise_type5
,
3595 bgp_evpn_advertise_type5_cmd
,
3596 "advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
" [route-map WORD]",
3597 "Advertise prefix routes\n"
3600 "route-map for filtering specific routes\n"
3601 "Name of the route map\n")
3603 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3610 int rmap_changed
= 0;
3612 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3613 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3614 ret
= argv_find(argv
, argc
, "route-map", &idx_rmap
);
3616 if (!bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3618 else if (strcmp(argv
[idx_rmap
+ 1]->arg
,
3619 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
)
3622 } else if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3626 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3628 "%%only ipv4 or ipv6 address families are supported");
3632 if (safi
!= SAFI_UNICAST
) {
3634 "%%only ipv4 unicast or ipv6 unicast are supported");
3638 if (afi
== AFI_IP
) {
3640 /* if we are already advertising ipv4 prefix as type-5
3643 if (!rmap_changed
&&
3644 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3645 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
))
3647 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3648 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3651 /* if we are already advertising ipv6 prefix as type-5
3654 if (!rmap_changed
&&
3655 CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3656 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
))
3658 SET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3659 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3663 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3664 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3665 XFREE(MTYPE_ROUTE_MAP_NAME
,
3666 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3667 route_map_counter_decrement(
3668 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3669 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3670 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3674 /* set the route-map for advertise command */
3675 if (ret
&& argv
[idx_rmap
+ 1]->arg
) {
3676 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
=
3677 XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[idx_rmap
+ 1]->arg
);
3678 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
=
3679 route_map_lookup_by_name(argv
[idx_rmap
+ 1]->arg
);
3680 route_map_counter_increment(
3681 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
);
3684 /* advertise type-5 routes */
3685 if (advertise_type5_routes(bgp_vrf
, afi
))
3686 bgp_evpn_advertise_type5_routes(bgp_vrf
, afi
, safi
);
3690 DEFUN (no_bgp_evpn_advertise_type5
,
3691 no_bgp_evpn_advertise_type5_cmd
,
3692 "no advertise " BGP_AFI_CMD_STR
"" BGP_SAFI_CMD_STR
,
3694 "Advertise prefix routes\n"
3698 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3704 argv_find_and_parse_afi(argv
, argc
, &idx_afi
, &afi
);
3705 argv_find_and_parse_safi(argv
, argc
, &idx_safi
, &safi
);
3707 if (!(afi
== AFI_IP
|| afi
== AFI_IP6
)) {
3709 "%%only ipv4 or ipv6 address families are supported");
3713 if (safi
!= SAFI_UNICAST
) {
3715 "%%only ipv4 unicast or ipv6 unicast are supported");
3719 if (afi
== AFI_IP
) {
3721 /* if we are not advertising ipv4 prefix as type-5
3724 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3725 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
3726 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3727 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3728 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
);
3732 /* if we are not advertising ipv6 prefix as type-5
3735 if (CHECK_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3736 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
3737 bgp_evpn_withdraw_type5_routes(bgp_vrf
, afi
, safi
);
3738 UNSET_FLAG(bgp_vrf
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
3739 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
);
3743 /* clear the route-map information for advertise ipv4/ipv6 unicast */
3744 if (bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
) {
3745 XFREE(MTYPE_ROUTE_MAP_NAME
,
3746 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
);
3747 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].name
= NULL
;
3748 bgp_vrf
->adv_cmd_rmap
[afi
][safi
].map
= NULL
;
3754 DEFPY (bgp_evpn_use_es_l3nhg
,
3755 bgp_evpn_use_es_l3nhg_cmd
,
3756 "[no$no] use-es-l3nhg",
3758 "use L3 nexthop group for host routes with ES destination\n")
3760 bgp_mh_info
->host_routes_use_l3nhg
= no
? false :true;
3764 DEFPY (bgp_evpn_ead_evi_rx_disable
,
3765 bgp_evpn_ead_evi_rx_disable_cmd
,
3766 "[no$no] disable-ead-evi-rx",
3768 "Activate PE on EAD-ES even if EAD-EVI is not received\n")
3770 bgp_mh_info
->ead_evi_rx
= no
? true :false;
3774 DEFPY (bgp_evpn_ead_evi_tx_disable
,
3775 bgp_evpn_ead_evi_tx_disable_cmd
,
3776 "[no$no] disable-ead-evi-tx",
3778 "Don't advertise EAD-EVI for local ESs\n")
3780 bgp_mh_info
->ead_evi_tx
= no
? true :false;
3784 DEFPY (bgp_evpn_advertise_pip_ip_mac
,
3785 bgp_evpn_advertise_pip_ip_mac_cmd
,
3786 "[no$no] advertise-pip [ip <A.B.C.D> [mac <X:X:X:X:X:X|X:X:X:X:X:X/M>]]",
3788 "evpn system primary IP\n"
3791 MAC_STR MAC_STR MAC_STR
)
3793 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
); /* bgp vrf instance */
3794 struct bgp
*bgp_evpn
= NULL
;
3796 if (EVPN_ENABLED(bgp_vrf
)) {
3798 "This command is supported under L3VNI BGP EVPN VRF\n");
3799 return CMD_WARNING_CONFIG_FAILED
;
3801 bgp_evpn
= bgp_get_evpn();
3804 /* pip is already enabled */
3805 if (argc
== 1 && bgp_vrf
->evpn_info
->advertise_pip
)
3808 bgp_vrf
->evpn_info
->advertise_pip
= true;
3809 if (ip
.s_addr
!= INADDR_ANY
) {
3810 /* Already configured with same IP */
3811 if (IPV4_ADDR_SAME(&ip
,
3812 &bgp_vrf
->evpn_info
->pip_ip_static
))
3815 bgp_vrf
->evpn_info
->pip_ip_static
= ip
;
3816 bgp_vrf
->evpn_info
->pip_ip
= ip
;
3818 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
3820 /* default instance router-id assignemt */
3822 bgp_vrf
->evpn_info
->pip_ip
=
3823 bgp_evpn
->router_id
;
3826 if (!is_zero_mac(&mac
->eth_addr
)) {
3827 /* Already configured with same MAC */
3828 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3829 &mac
->eth_addr
, ETH_ALEN
) == 0)
3832 memcpy(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3833 &mac
->eth_addr
, ETH_ALEN
);
3834 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3835 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3838 /* Copy zebra sys mac */
3839 if (!is_zero_mac(&bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3840 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3841 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3846 if (!bgp_vrf
->evpn_info
->advertise_pip
)
3848 /* Disable PIP feature */
3849 bgp_vrf
->evpn_info
->advertise_pip
= false;
3850 /* copy anycast mac */
3851 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3852 &bgp_vrf
->rmac
, ETH_ALEN
);
3854 /* remove MAC-IP option retain PIP knob. */
3855 if ((ip
.s_addr
!= INADDR_ANY
) &&
3856 !IPV4_ADDR_SAME(&ip
,
3857 &bgp_vrf
->evpn_info
->pip_ip_static
)) {
3859 "%% BGP EVPN PIP IP does not match\n");
3860 return CMD_WARNING_CONFIG_FAILED
;
3863 if (!is_zero_mac(&mac
->eth_addr
) &&
3864 memcmp(&bgp_vrf
->evpn_info
->pip_rmac_static
,
3865 &mac
->eth_addr
, ETH_ALEN
) != 0) {
3867 "%% BGP EVPN PIP MAC does not match\n");
3868 return CMD_WARNING_CONFIG_FAILED
;
3870 /* pip_rmac can carry vrr_rmac reset only if it matches
3871 * with static value.
3873 if (memcmp(&bgp_vrf
->evpn_info
->pip_rmac
,
3874 &bgp_vrf
->evpn_info
->pip_rmac_static
,
3876 /* Copy zebra sys mac */
3878 &bgp_vrf
->evpn_info
->pip_rmac_zebra
))
3879 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3880 &bgp_vrf
->evpn_info
->pip_rmac_zebra
,
3883 /* copy anycast mac */
3884 memcpy(&bgp_vrf
->evpn_info
->pip_rmac
,
3885 &bgp_vrf
->rmac
, ETH_ALEN
);
3889 /* reset user configured sys MAC */
3890 memset(&bgp_vrf
->evpn_info
->pip_rmac_static
, 0, ETH_ALEN
);
3891 /* reset user configured sys IP */
3892 bgp_vrf
->evpn_info
->pip_ip_static
.s_addr
= INADDR_ANY
;
3893 /* Assign default PIP IP (bgp instance router-id) */
3895 bgp_vrf
->evpn_info
->pip_ip
= bgp_evpn
->router_id
;
3897 bgp_vrf
->evpn_info
->pip_ip
.s_addr
= INADDR_ANY
;
3900 if (is_evpn_enabled()) {
3901 struct listnode
*node
= NULL
;
3902 struct bgpevpn
*vpn
= NULL
;
3905 * At this point if bgp_evpn is NULL and evpn is enabled
3906 * something stupid has gone wrong
3910 update_advertise_vrf_routes(bgp_vrf
);
3912 /* Update (svi) type-2 routes */
3913 for (ALL_LIST_ELEMENTS_RO(bgp_vrf
->l2vnis
, node
, vpn
)) {
3914 if (!bgp_evpn_is_svi_macip_enabled(vpn
))
3916 update_routes_for_vni(bgp_evpn
, vpn
);
3924 * Display VNI information - for all or a specific VNI
3926 DEFUN(show_bgp_l2vpn_evpn_vni
,
3927 show_bgp_l2vpn_evpn_vni_cmd
,
3928 "show bgp l2vpn evpn vni [" CMD_VNI_RANGE
"] [json]",
3937 struct bgp
*bgp_evpn
;
3941 json_object
*json
= NULL
;
3942 uint32_t num_l2vnis
= 0;
3943 uint32_t num_l3vnis
= 0;
3944 uint32_t num_vnis
= 0;
3945 struct listnode
*node
= NULL
;
3946 struct bgp
*bgp_temp
= NULL
;
3948 uj
= use_json(argc
, argv
);
3950 bgp_evpn
= bgp_get_evpn();
3954 if (!argv_find(argv
, argc
, "evpn", &idx
))
3958 json
= json_object_new_object();
3960 if ((uj
&& argc
== ((idx
+ 1) + 2)) || (!uj
&& argc
== (idx
+ 1) + 1)) {
3962 num_l2vnis
= hashcount(bgp_evpn
->vnihash
);
3964 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp_temp
)) {
3965 if (bgp_temp
->l3vni
)
3968 num_vnis
= num_l2vnis
+ num_l3vnis
;
3970 json_object_string_add(json
, "advertiseGatewayMacip",
3971 bgp_evpn
->advertise_gw_macip
3974 json_object_string_add(json
, "advertiseSviMacIp",
3975 bgp_evpn
->evpn_info
->advertise_svi_macip
3976 ? "Enabled" : "Disabled");
3977 json_object_string_add(json
, "advertiseAllVnis",
3978 is_evpn_enabled() ? "Enabled"
3980 json_object_string_add(
3982 bgp_evpn
->vxlan_flood_ctrl
3983 == VXLAN_FLOOD_HEAD_END_REPL
3984 ? "Head-end replication"
3986 json_object_int_add(json
, "numVnis", num_vnis
);
3987 json_object_int_add(json
, "numL2Vnis", num_l2vnis
);
3988 json_object_int_add(json
, "numL3Vnis", num_l3vnis
);
3990 vty_out(vty
, "Advertise Gateway Macip: %s\n",
3991 bgp_evpn
->advertise_gw_macip
? "Enabled"
3993 vty_out(vty
, "Advertise SVI Macip: %s\n",
3994 bgp_evpn
->evpn_info
->advertise_svi_macip
? "Enabled"
3996 vty_out(vty
, "Advertise All VNI flag: %s\n",
3997 is_evpn_enabled() ? "Enabled" : "Disabled");
3998 vty_out(vty
, "BUM flooding: %s\n",
3999 bgp_evpn
->vxlan_flood_ctrl
4000 == VXLAN_FLOOD_HEAD_END_REPL
4001 ? "Head-end replication"
4003 vty_out(vty
, "Number of L2 VNIs: %u\n", num_l2vnis
);
4004 vty_out(vty
, "Number of L3 VNIs: %u\n", num_l3vnis
);
4006 evpn_show_all_vnis(vty
, bgp_evpn
, json
);
4010 if (!argv_find(argv
, argc
, "vni", &vni_idx
))
4013 /* Display specific VNI */
4014 vni
= strtoul(argv
[vni_idx
+ 1]->arg
, NULL
, 10);
4015 evpn_show_vni(vty
, bgp_evpn
, vni
, json
);
4019 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4020 json
, JSON_C_TO_STRING_PRETTY
));
4021 json_object_free(json
);
4027 DEFPY(show_bgp_l2vpn_evpn_es_evi
,
4028 show_bgp_l2vpn_evpn_es_evi_cmd
,
4029 "show bgp l2vpn evpn es-evi [vni (1-16777215)$vni] [json$uj] [detail$detail]",
4035 "VxLAN Network Identifier\n"
4038 "Detailed information\n")
4041 bgp_evpn_es_evi_show_vni(vty
, vni
, !!uj
, !!detail
);
4043 bgp_evpn_es_evi_show(vty
, !!uj
, !!detail
);
4048 DEFPY(show_bgp_l2vpn_evpn_es
,
4049 show_bgp_l2vpn_evpn_es_cmd
,
4050 "show bgp l2vpn evpn es [NAME$esi_str|detail$detail] [json$uj]",
4055 "Ethernet Segment\n"
4057 "Detailed information\n"
4063 if (!str_to_esi(esi_str
, &esi
)) {
4064 vty_out(vty
, "%%Malformed ESI\n");
4067 bgp_evpn_es_show_esi(vty
, &esi
, uj
);
4070 bgp_evpn_es_show(vty
, uj
, !!detail
);
4076 DEFPY(show_bgp_l2vpn_evpn_es_vrf
, show_bgp_l2vpn_evpn_es_vrf_cmd
,
4077 "show bgp l2vpn evpn es-vrf [NAME$esi_str] [json$uj]",
4078 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4079 "Ethernet Segment\n"
4085 if (!str_to_esi(esi_str
, &esi
)) {
4086 vty_out(vty
, "%%Malformed ESI\n");
4089 bgp_evpn_es_vrf_show_esi(vty
, &esi
, uj
);
4092 bgp_evpn_es_vrf_show(vty
, uj
, NULL
);
4099 * Display EVPN neighbor summary.
4101 DEFUN(show_bgp_l2vpn_evpn_summary
,
4102 show_bgp_l2vpn_evpn_summary_cmd
,
4103 "show bgp [vrf VRFNAME] l2vpn evpn summary [established|failed] [wide] [json]",
4110 "Summary of BGP neighbor status\n"
4111 "Show only sessions in Established state\n"
4112 "Show only sessions not in Established state\n"
4113 "Increase table width for longer output\n"
4119 uint8_t show_flags
= 0;
4121 if (argv_find(argv
, argc
, "vrf", &idx_vrf
))
4122 vrf
= argv
[++idx_vrf
]->arg
;
4124 if (argv_find(argv
, argc
, "failed", &idx
))
4125 SET_FLAG(show_flags
, BGP_SHOW_OPT_FAILED
);
4127 if (argv_find(argv
, argc
, "established", &idx
))
4128 SET_FLAG(show_flags
, BGP_SHOW_OPT_ESTABLISHED
);
4130 if (argv_find(argv
, argc
, "wide", &idx
))
4131 SET_FLAG(show_flags
, BGP_SHOW_OPT_WIDE
);
4133 if (use_json(argc
, argv
))
4134 SET_FLAG(show_flags
, BGP_SHOW_OPT_JSON
);
4136 return bgp_show_summary_vty(vty
, vrf
, AFI_L2VPN
, SAFI_EVPN
, show_flags
);
4139 int bgp_evpn_cli_parse_type(int *type
, struct cmd_token
**argv
, int argc
)
4143 if (argv_find(argv
, argc
, "type", &type_idx
)) {
4144 /* Specific type is requested */
4145 if ((strncmp(argv
[type_idx
+ 1]->arg
, "ma", 2) == 0)
4146 || (strmatch(argv
[type_idx
+ 1]->arg
, "2")))
4147 *type
= BGP_EVPN_MAC_IP_ROUTE
;
4148 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "mu", 2) == 0)
4149 || (strmatch(argv
[type_idx
+ 1]->arg
, "3")))
4150 *type
= BGP_EVPN_IMET_ROUTE
;
4151 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "es", 2) == 0)
4152 || (strmatch(argv
[type_idx
+ 1]->arg
, "4")))
4153 *type
= BGP_EVPN_ES_ROUTE
;
4154 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "ea", 2) == 0)
4155 || (strmatch(argv
[type_idx
+ 1]->arg
, "1")))
4156 *type
= BGP_EVPN_AD_ROUTE
;
4157 else if ((strncmp(argv
[type_idx
+ 1]->arg
, "p", 1) == 0)
4158 || (strmatch(argv
[type_idx
+ 1]->arg
, "5")))
4159 *type
= BGP_EVPN_IP_PREFIX_ROUTE
;
4168 * Display global EVPN routing table.
4170 DEFUN(show_bgp_l2vpn_evpn_route
,
4171 show_bgp_l2vpn_evpn_route_cmd
,
4172 "show bgp l2vpn evpn route [detail] [type "EVPN_TYPE_ALL_LIST
"] [json]",
4178 "Display Detailed Information\n"
4180 EVPN_TYPE_ALL_LIST_HELP_STR
4187 json_object
*json
= NULL
;
4189 uj
= use_json(argc
, argv
);
4191 bgp
= bgp_get_evpn();
4196 json
= json_object_new_object();
4198 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4201 if (argv_find(argv
, argc
, "detail", &detail
))
4204 evpn_show_all_routes(vty
, bgp
, type
, json
, detail
);
4207 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4208 json
, JSON_C_TO_STRING_PRETTY
));
4209 json_object_free(json
);
4215 * Display global EVPN routing table for specific RD.
4217 DEFUN(show_bgp_l2vpn_evpn_route_rd
,
4218 show_bgp_l2vpn_evpn_route_rd_cmd
,
4219 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type "EVPN_TYPE_ALL_LIST
"] [json]",
4225 EVPN_RT_DIST_HELP_STR
4226 EVPN_ASN_IP_HELP_STR
4228 EVPN_TYPE_ALL_LIST_HELP_STR
4233 struct prefix_rd prd
;
4237 json_object
*json
= NULL
;
4239 bgp
= bgp_get_evpn();
4243 /* check if we need json output */
4244 uj
= use_json(argc
, argv
);
4246 json
= json_object_new_object();
4249 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4250 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4253 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4258 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4261 evpn_show_route_rd(vty
, bgp
, &prd
, type
, json
);
4264 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4265 json
, JSON_C_TO_STRING_PRETTY
));
4266 json_object_free(json
);
4273 * Display global EVPN routing table for specific RD and MACIP.
4275 DEFUN(show_bgp_l2vpn_evpn_route_rd_macip
,
4276 show_bgp_l2vpn_evpn_route_rd_macip_cmd
,
4277 "show bgp l2vpn evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD] [json]",
4283 EVPN_RT_DIST_HELP_STR
4284 EVPN_ASN_IP_HELP_STR
4286 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4288 "IP address (IPv4 or IPv6)\n"
4293 struct prefix_rd prd
;
4300 json_object
*json
= NULL
;
4302 memset(&mac
, 0, sizeof(struct ethaddr
));
4303 memset(&ip
, 0, sizeof(struct ipaddr
));
4305 bgp
= bgp_get_evpn();
4309 /* check if we need json output */
4310 uj
= use_json(argc
, argv
);
4312 json
= json_object_new_object();
4315 if (argv_find(argv
, argc
, "rd", &rd_idx
)) {
4316 ret
= str2prefix_rd(argv
[rd_idx
+ 1]->arg
, &prd
);
4318 vty_out(vty
, "%% Malformed Route Distinguisher\n");
4324 if (argv_find(argv
, argc
, "mac", &mac_idx
)) {
4325 if (!prefix_str2mac(argv
[mac_idx
+ 1]->arg
, &mac
)) {
4326 vty_out(vty
, "%% Malformed MAC address\n");
4331 /* get the ip if specified */
4332 if (argv_find(argv
, argc
, "ip", &ip_idx
)) {
4333 if (str2ipaddr(argv
[ip_idx
+ 1]->arg
, &ip
) != 0) {
4334 vty_out(vty
, "%% Malformed IP address\n");
4339 evpn_show_route_rd_macip(vty
, bgp
, &prd
, &mac
, &ip
, json
);
4342 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4343 json
, JSON_C_TO_STRING_PRETTY
));
4344 json_object_free(json
);
4350 /* Display per ESI routing table */
4351 DEFUN(show_bgp_l2vpn_evpn_route_esi
,
4352 show_bgp_l2vpn_evpn_route_esi_cmd
,
4353 "show bgp l2vpn evpn route esi ESI [json]",
4359 "Ethernet Segment Identifier\n"
4365 struct bgp
*bgp
= NULL
;
4366 json_object
*json
= NULL
;
4368 memset(&esi
, 0, sizeof(esi
));
4369 bgp
= bgp_get_evpn();
4373 uj
= use_json(argc
, argv
);
4375 json
= json_object_new_object();
4377 /* get the ESI - ESI-ID is at argv[6] */
4378 if (!str_to_esi(argv
[6]->arg
, &esi
)) {
4379 vty_out(vty
, "%% Malformed ESI\n");
4383 evpn_show_routes_esi(vty
, bgp
, &esi
, json
);
4386 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4387 json
, JSON_C_TO_STRING_PRETTY
));
4388 json_object_free(json
);
4396 * Display per-VNI EVPN routing table.
4398 DEFUN(show_bgp_l2vpn_evpn_route_vni
, show_bgp_l2vpn_evpn_route_vni_cmd
,
4399 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" [<type <ead|1|macip|2|multicast|3> | vtep A.B.C.D>] [json]",
4405 "VXLAN Network Identifier\n"
4408 EVPN_TYPE_1_HELP_STR
4409 EVPN_TYPE_1_HELP_STR
4410 EVPN_TYPE_2_HELP_STR
4411 EVPN_TYPE_2_HELP_STR
4412 EVPN_TYPE_3_HELP_STR
4413 EVPN_TYPE_3_HELP_STR
4415 "Remote VTEP IP address\n"
4420 struct in_addr vtep_ip
;
4425 json_object
*json
= NULL
;
4427 bgp
= bgp_get_evpn();
4431 /* check if we need json output */
4432 uj
= use_json(argc
, argv
);
4434 json
= json_object_new_object();
4436 if (!argv_find(argv
, argc
, "evpn", &idx
))
4441 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4443 if (bgp_evpn_cli_parse_type(&type
, argv
, argc
) < 0)
4446 if (argv_find(argv
, argc
, "vtep", &vtep_idx
)) {
4447 if (!inet_aton(argv
[vtep_idx
+ 1]->arg
, &vtep_ip
)) {
4448 vty_out(vty
, "%% Malformed VTEP IP address\n");
4453 evpn_show_routes_vni(vty
, bgp
, vni
, type
, vtep_ip
, json
);
4456 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4457 json
, JSON_C_TO_STRING_PRETTY
));
4458 json_object_free(json
);
4465 * Display per-VNI EVPN routing table for specific MACIP.
4467 DEFUN(show_bgp_l2vpn_evpn_route_vni_macip
,
4468 show_bgp_l2vpn_evpn_route_vni_macip_cmd
,
4469 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD] [json]",
4475 "VXLAN Network Identifier\n"
4478 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4480 "IP address (IPv4 or IPv6)\n"
4489 json_object
*json
= NULL
;
4491 bgp
= bgp_get_evpn();
4495 /* check if we need json output */
4496 uj
= use_json(argc
, argv
);
4498 json
= json_object_new_object();
4500 if (!argv_find(argv
, argc
, "evpn", &idx
))
4504 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4507 if (!prefix_str2mac(argv
[idx
+ 5]->arg
, &mac
)) {
4508 vty_out(vty
, "%% Malformed MAC address\n");
4513 memset(&ip
, 0, sizeof(ip
));
4514 if ((!uj
&& ((argc
== (idx
+ 1 + 7)) && argv
[idx
+ 7]->arg
!= NULL
))
4516 && ((argc
== (idx
+ 1 + 8)) && argv
[idx
+ 7]->arg
!= NULL
))) {
4517 if (str2ipaddr(argv
[idx
+ 7]->arg
, &ip
) != 0) {
4518 vty_out(vty
, "%% Malformed IP address\n");
4523 evpn_show_route_vni_macip(vty
, bgp
, vni
, &mac
, &ip
, json
);
4526 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4527 json
, JSON_C_TO_STRING_PRETTY
));
4528 json_object_free(json
);
4535 * Display per-VNI EVPN routing table for specific multicast IP (remote VTEP).
4537 DEFUN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4538 show_bgp_l2vpn_evpn_route_vni_multicast_cmd
,
4539 "show bgp l2vpn evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D [json]",
4545 "VXLAN Network Identifier\n"
4547 EVPN_TYPE_3_HELP_STR
4548 "Originating Router IP address\n"
4554 struct in_addr orig_ip
;
4557 json_object
*json
= NULL
;
4559 bgp
= bgp_get_evpn();
4563 /* check if we need json output */
4564 uj
= use_json(argc
, argv
);
4566 json
= json_object_new_object();
4568 if (!argv_find(argv
, argc
, "evpn", &idx
))
4572 vni
= strtoul(argv
[idx
+ 3]->arg
, NULL
, 10);
4575 ret
= inet_aton(argv
[idx
+ 5]->arg
, &orig_ip
);
4577 vty_out(vty
, "%% Malformed Originating Router IP address\n");
4581 evpn_show_route_vni_multicast(vty
, bgp
, vni
, orig_ip
, json
);
4584 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4585 json
, JSON_C_TO_STRING_PRETTY
));
4586 json_object_free(json
);
4593 * Display per-VNI EVPN routing table - for all VNIs.
4595 DEFUN(show_bgp_l2vpn_evpn_route_vni_all
,
4596 show_bgp_l2vpn_evpn_route_vni_all_cmd
,
4597 "show bgp l2vpn evpn route vni all [detail] [vtep A.B.C.D] [json]",
4603 "VXLAN Network Identifier\n"
4605 "Print Detailed Output\n"
4607 "Remote VTEP IP address\n"
4611 struct in_addr vtep_ip
;
4614 json_object
*json
= NULL
;
4615 /* Detail Adjust. Adjust indexes according to detail option */
4618 bgp
= bgp_get_evpn();
4622 /* check if we need json output */
4623 uj
= use_json(argc
, argv
);
4625 json
= json_object_new_object();
4627 if (!argv_find(argv
, argc
, "evpn", &idx
))
4630 if (argv_find(argv
, argc
, "detail", &da
))
4633 /* vtep-ip position depends on detail option */
4635 if ((!uj
&& (argc
== (idx
+ 1 + 5 + da
) && argv
[idx
+ 5 + da
]->arg
))
4637 && (argc
== (idx
+ 1 + 6 + da
) && argv
[idx
+ 5 + da
]->arg
))) {
4638 if (!inet_aton(argv
[idx
+ 5 + da
]->arg
, &vtep_ip
)) {
4639 vty_out(vty
, "%% Malformed VTEP IP address\n");
4644 evpn_show_routes_vni_all(vty
, bgp
, vtep_ip
, json
, da
);
4647 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4648 json
, JSON_C_TO_STRING_PRETTY
));
4649 json_object_free(json
);
4656 show_bgp_l2vpn_evpn_route_mac_ip_es
,
4657 show_bgp_l2vpn_evpn_route_mac_ip_es_cmd
,
4658 "show bgp l2vpn evpn route mac-ip-es [NAME$esi_str|detail$detail] [json$uj]",
4659 SHOW_STR BGP_STR L2VPN_HELP_STR EVPN_HELP_STR
4660 "EVPN route information\n"
4661 "MAC IP routes linked to the ES\n"
4663 "Detailed information\n" JSON_STR
)
4667 json_object
*json
= NULL
;
4670 if (!str_to_esi(esi_str
, &esi
)) {
4671 vty_out(vty
, "%%Malformed ESI\n");
4680 json
= json_object_new_object();
4681 bgp_evpn_show_routes_mac_ip_es(vty
, esi_p
, json
, !!detail
);
4683 vty_out(vty
, "%s\n",
4684 json_object_to_json_string_ext(
4685 json
, JSON_C_TO_STRING_PRETTY
));
4686 json_object_free(json
);
4693 * Display EVPN import route-target hash table
4695 DEFUN(show_bgp_l2vpn_evpn_vrf_import_rt
,
4696 show_bgp_l2vpn_evpn_vrf_import_rt_cmd
,
4697 "show bgp l2vpn evpn vrf-import-rt [json]",
4702 "Show vrf import route target\n"
4706 struct bgp
*bgp_evpn
= NULL
;
4707 json_object
*json
= NULL
;
4709 bgp_evpn
= bgp_get_evpn();
4713 uj
= use_json(argc
, argv
);
4715 json
= json_object_new_object();
4717 evpn_show_vrf_import_rts(vty
, bgp_evpn
, json
);
4720 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4721 json
, JSON_C_TO_STRING_PRETTY
));
4722 json_object_free(json
);
4729 * Display EVPN import route-target hash table
4731 DEFUN(show_bgp_l2vpn_evpn_import_rt
,
4732 show_bgp_l2vpn_evpn_import_rt_cmd
,
4733 "show bgp l2vpn evpn import-rt [json]",
4738 "Show import route target\n"
4743 json_object
*json
= NULL
;
4745 bgp
= bgp_get_evpn();
4749 uj
= use_json(argc
, argv
);
4751 json
= json_object_new_object();
4753 evpn_show_import_rts(vty
, bgp
, json
);
4756 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
4757 json
, JSON_C_TO_STRING_PRETTY
));
4758 json_object_free(json
);
4764 DEFPY_HIDDEN(test_es_add
,
4766 "[no$no] test es NAME$esi_str [state NAME$state_str]",
4769 "Ethernet-segment\n"
4770 "Ethernet-Segment Identifier\n"
4778 struct in_addr vtep_ip
;
4781 bgp
= bgp_get_evpn();
4783 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4787 if (!str_to_esi(esi_str
, &esi
)) {
4788 vty_out(vty
, "%%Malformed ESI\n");
4793 ret
= bgp_evpn_local_es_del(bgp
, &esi
);
4795 vty_out(vty
, "%%Failed to delete ES\n");
4799 if (state_str
&& !strcmp(state_str
, "up"))
4803 vtep_ip
= bgp
->router_id
;
4805 ret
= bgp_evpn_local_es_add(bgp
, &esi
, vtep_ip
, oper_up
,
4806 EVPN_MH_DF_PREF_MIN
, false);
4808 vty_out(vty
, "%%Failed to add ES\n");
4815 DEFPY_HIDDEN(test_es_vni_add
,
4816 test_es_vni_add_cmd
,
4817 "[no$no] test es NAME$esi_str vni (1-16777215)$vni",
4820 "Ethernet-segment\n"
4821 "Ethernet-Segment Identifier\n"
4830 bgp
= bgp_get_evpn();
4832 vty_out(vty
, "%%EVPN BGP instance not yet created\n");
4836 if (!str_to_esi(esi_str
, &esi
)) {
4837 vty_out(vty
, "%%Malformed ESI\n");
4842 ret
= bgp_evpn_local_es_evi_del(bgp
, &esi
, vni
);
4844 vty_out(vty
, "%%Failed to deref ES VNI\n");
4848 ret
= bgp_evpn_local_es_evi_add(bgp
, &esi
, vni
);
4850 vty_out(vty
, "%%Failed to ref ES VNI\n");
4857 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_vni
, show_bgp_evpn_vni_cmd
,
4858 "show bgp evpn vni [" CMD_VNI_RANGE
"]", SHOW_STR BGP_STR EVPN_HELP_STR
4862 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_summary
, show_bgp_evpn_summary_cmd
,
4863 "show bgp evpn summary [json]", SHOW_STR BGP_STR EVPN_HELP_STR
4864 "Summary of BGP neighbor status\n" JSON_STR
)
4866 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route
, show_bgp_evpn_route_cmd
,
4867 "show bgp evpn route [detail] [type <macip|2|multicast|3>]",
4868 SHOW_STR BGP_STR EVPN_HELP_STR
4870 "Display Detailed Information\n"
4872 EVPN_TYPE_2_HELP_STR
4873 EVPN_TYPE_2_HELP_STR
4874 EVPN_TYPE_3_HELP_STR
4875 EVPN_TYPE_3_HELP_STR
)
4878 show_bgp_l2vpn_evpn_route_rd
, show_bgp_evpn_route_rd_cmd
,
4879 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN [type <macip|2|multicast|3>]",
4880 SHOW_STR BGP_STR EVPN_HELP_STR
4882 EVPN_RT_DIST_HELP_STR
4883 EVPN_ASN_IP_HELP_STR
4885 EVPN_TYPE_2_HELP_STR
4886 EVPN_TYPE_2_HELP_STR
4887 EVPN_TYPE_3_HELP_STR
4888 EVPN_TYPE_3_HELP_STR
)
4891 show_bgp_l2vpn_evpn_route_rd_macip
, show_bgp_evpn_route_rd_macip_cmd
,
4892 "show bgp evpn route rd ASN:NN_OR_IP-ADDRESS:NN mac WORD [ip WORD]",
4893 SHOW_STR BGP_STR EVPN_HELP_STR
4895 EVPN_RT_DIST_HELP_STR
4896 EVPN_ASN_IP_HELP_STR
4898 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4900 "IP address (IPv4 or IPv6)\n")
4903 show_bgp_l2vpn_evpn_route_vni
, show_bgp_evpn_route_vni_cmd
,
4904 "show bgp evpn route vni " CMD_VNI_RANGE
" [<type <macip|2|multicast|3> | vtep A.B.C.D>]",
4905 SHOW_STR BGP_STR EVPN_HELP_STR
4907 "VXLAN Network Identifier\n"
4910 EVPN_TYPE_2_HELP_STR
4911 EVPN_TYPE_2_HELP_STR
4912 EVPN_TYPE_3_HELP_STR
4913 EVPN_TYPE_3_HELP_STR
4915 "Remote VTEP IP address\n")
4917 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_macip
,
4918 show_bgp_evpn_route_vni_macip_cmd
,
4919 "show bgp evpn route vni " CMD_VNI_RANGE
" mac WORD [ip WORD]",
4920 SHOW_STR BGP_STR EVPN_HELP_STR
4922 "VXLAN Network Identifier\n"
4925 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
4927 "IP address (IPv4 or IPv6)\n")
4929 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_multicast
,
4930 show_bgp_evpn_route_vni_multicast_cmd
,
4931 "show bgp evpn route vni " CMD_VNI_RANGE
" multicast A.B.C.D",
4932 SHOW_STR BGP_STR EVPN_HELP_STR
4934 "VXLAN Network Identifier\n"
4936 EVPN_TYPE_3_HELP_STR
4937 "Originating Router IP address\n")
4939 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_route_vni_all
, show_bgp_evpn_route_vni_all_cmd
,
4940 "show bgp evpn route vni all [detail] [vtep A.B.C.D]",
4941 SHOW_STR BGP_STR EVPN_HELP_STR
4943 "VXLAN Network Identifier\n"
4945 "Print Detailed Output\n"
4947 "Remote VTEP IP address\n")
4949 ALIAS_HIDDEN(show_bgp_l2vpn_evpn_import_rt
, show_bgp_evpn_import_rt_cmd
,
4950 "show bgp evpn import-rt",
4951 SHOW_STR BGP_STR EVPN_HELP_STR
"Show import route target\n")
4953 DEFUN_NOSH (bgp_evpn_vni
,
4955 "vni " CMD_VNI_RANGE
,
4956 "VXLAN Network Identifier\n"
4960 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4961 struct bgpevpn
*vpn
;
4966 vni
= strtoul(argv
[1]->arg
, NULL
, 10);
4968 /* Create VNI, or mark as configured. */
4969 vpn
= evpn_create_update_vni(bgp
, vni
);
4971 vty_out(vty
, "%% Failed to create VNI \n");
4975 VTY_PUSH_CONTEXT_SUB(BGP_EVPN_VNI_NODE
, vpn
);
4979 DEFUN (no_bgp_evpn_vni
,
4980 no_bgp_evpn_vni_cmd
,
4981 "no vni " CMD_VNI_RANGE
,
4983 "VXLAN Network Identifier\n"
4987 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
4988 struct bgpevpn
*vpn
;
4993 vni
= strtoul(argv
[2]->arg
, NULL
, 10);
4995 /* Check if we should disallow. */
4996 vpn
= bgp_evpn_lookup_vni(bgp
, vni
);
4998 vty_out(vty
, "%% Specified VNI does not exist\n");
5001 if (!is_vni_configured(vpn
)) {
5002 vty_out(vty
, "%% Specified VNI is not configured\n");
5006 evpn_delete_vni(bgp
, vpn
);
5010 DEFUN_NOSH (exit_vni
,
5013 "Exit from VNI mode\n")
5015 if (vty
->node
== BGP_EVPN_VNI_NODE
)
5016 vty
->node
= BGP_EVPN_NODE
;
5020 DEFUN (bgp_evpn_vrf_rd
,
5021 bgp_evpn_vrf_rd_cmd
,
5022 "rd ASN:NN_OR_IP-ADDRESS:NN",
5023 EVPN_RT_DIST_HELP_STR
5024 EVPN_ASN_IP_HELP_STR
)
5027 struct prefix_rd prd
;
5028 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5033 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5035 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5039 /* If same as existing value, there is nothing more to do. */
5040 if (bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
))
5043 /* Configure or update the RD. */
5044 evpn_configure_vrf_rd(bgp_vrf
, &prd
);
5048 DEFUN (no_bgp_evpn_vrf_rd
,
5049 no_bgp_evpn_vrf_rd_cmd
,
5050 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5052 EVPN_RT_DIST_HELP_STR
5053 EVPN_ASN_IP_HELP_STR
)
5056 struct prefix_rd prd
;
5057 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5062 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5064 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5068 /* Check if we should disallow. */
5069 if (!is_vrf_rd_configured(bgp_vrf
)) {
5070 vty_out(vty
, "%% RD is not configured for this VRF\n");
5074 if (!bgp_evpn_vrf_rd_matches_existing(bgp_vrf
, &prd
)) {
5076 "%% RD specified does not match configuration for this VRF\n");
5080 evpn_unconfigure_vrf_rd(bgp_vrf
);
5084 DEFUN (no_bgp_evpn_vrf_rd_without_val
,
5085 no_bgp_evpn_vrf_rd_without_val_cmd
,
5088 EVPN_RT_DIST_HELP_STR
)
5090 struct bgp
*bgp_vrf
= VTY_GET_CONTEXT(bgp
);
5095 /* Check if we should disallow. */
5096 if (!is_vrf_rd_configured(bgp_vrf
)) {
5097 vty_out(vty
, "%% RD is not configured for this VRF\n");
5101 evpn_unconfigure_vrf_rd(bgp_vrf
);
5105 DEFUN (bgp_evpn_vni_rd
,
5106 bgp_evpn_vni_rd_cmd
,
5107 "rd ASN:NN_OR_IP-ADDRESS:NN",
5108 EVPN_RT_DIST_HELP_STR
5109 EVPN_ASN_IP_HELP_STR
)
5111 struct prefix_rd prd
;
5112 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5113 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5119 if (!EVPN_ENABLED(bgp
)) {
5121 "This command is only supported under EVPN VRF\n");
5125 ret
= str2prefix_rd(argv
[1]->arg
, &prd
);
5127 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5131 /* If same as existing value, there is nothing more to do. */
5132 if (bgp_evpn_rd_matches_existing(vpn
, &prd
))
5135 /* Configure or update the RD. */
5136 evpn_configure_rd(bgp
, vpn
, &prd
);
5140 DEFUN (no_bgp_evpn_vni_rd
,
5141 no_bgp_evpn_vni_rd_cmd
,
5142 "no rd ASN:NN_OR_IP-ADDRESS:NN",
5144 EVPN_RT_DIST_HELP_STR
5145 EVPN_ASN_IP_HELP_STR
)
5147 struct prefix_rd prd
;
5148 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5149 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5155 if (!EVPN_ENABLED(bgp
)) {
5157 "This command is only supported under EVPN VRF\n");
5161 ret
= str2prefix_rd(argv
[2]->arg
, &prd
);
5163 vty_out(vty
, "%% Malformed Route Distinguisher\n");
5167 /* Check if we should disallow. */
5168 if (!is_rd_configured(vpn
)) {
5169 vty_out(vty
, "%% RD is not configured for this VNI\n");
5173 if (!bgp_evpn_rd_matches_existing(vpn
, &prd
)) {
5175 "%% RD specified does not match configuration for this VNI\n");
5179 evpn_unconfigure_rd(bgp
, vpn
);
5183 DEFUN (no_bgp_evpn_vni_rd_without_val
,
5184 no_bgp_evpn_vni_rd_without_val_cmd
,
5187 EVPN_RT_DIST_HELP_STR
)
5189 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5190 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5195 if (!EVPN_ENABLED(bgp
)) {
5197 "This command is only supported under EVPN VRF\n");
5201 /* Check if we should disallow. */
5202 if (!is_rd_configured(vpn
)) {
5203 vty_out(vty
, "%% RD is not configured for this VNI\n");
5207 evpn_unconfigure_rd(bgp
, vpn
);
5212 * Loop over all extended-communities in the route-target list rtl and
5213 * return 1 if we find ecomtarget
5215 static int bgp_evpn_rt_matches_existing(struct list
*rtl
,
5216 struct ecommunity
*ecomtarget
)
5218 struct listnode
*node
, *nnode
;
5219 struct ecommunity
*ecom
;
5221 for (ALL_LIST_ELEMENTS(rtl
, node
, nnode
, ecom
)) {
5222 if (ecommunity_match(ecom
, ecomtarget
))
5229 /* display L3VNI related info for a VRF instance */
5230 DEFUN (show_bgp_vrf_l3vni_info
,
5231 show_bgp_vrf_l3vni_info_cmd
,
5232 "show bgp vrf VRFNAME vni [json]",
5240 char buf
[ETHER_ADDR_STRLEN
];
5241 char buf1
[INET6_ADDRSTRLEN
];
5242 char originator_ip
[BUFSIZ
] = {0};
5244 const char *name
= NULL
;
5245 struct bgp
*bgp
= NULL
;
5246 struct listnode
*node
= NULL
;
5247 struct bgpevpn
*vpn
= NULL
;
5248 struct ecommunity
*ecom
= NULL
;
5249 json_object
*json
= NULL
;
5250 json_object
*json_vnis
= NULL
;
5251 json_object
*json_export_rts
= NULL
;
5252 json_object
*json_import_rts
= NULL
;
5253 bool uj
= use_json(argc
, argv
);
5256 json
= json_object_new_object();
5257 json_vnis
= json_object_new_array();
5258 json_export_rts
= json_object_new_array();
5259 json_import_rts
= json_object_new_array();
5262 name
= argv
[idx_vrf
]->arg
;
5263 bgp
= bgp_lookup_by_name(name
);
5266 vty_out(vty
, "BGP instance for VRF %s not found", name
);
5268 json_object_string_add(json
, "warning",
5269 "BGP instance not found");
5270 vty_out(vty
, "%s\n", json_object_to_json_string(json
));
5271 json_object_free(json
);
5277 vty_out(vty
, "BGP VRF: %s\n", name
);
5278 vty_out(vty
, " Local-Ip: %pI4\n", &bgp
->originator_ip
);
5279 vty_out(vty
, " L3-VNI: %u\n", bgp
->l3vni
);
5280 vty_out(vty
, " Rmac: %s\n",
5281 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5282 vty_out(vty
, " VNI Filter: %s\n",
5283 CHECK_FLAG(bgp
->vrf_flags
,
5284 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5285 ? "prefix-routes-only"
5287 vty_out(vty
, " L2-VNI List:\n");
5289 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5290 vty_out(vty
, "%u ", vpn
->vni
);
5292 vty_out(vty
, " Export-RTs:\n");
5294 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5295 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5297 vty_out(vty
, " Import-RTs:\n");
5299 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5300 vty_out(vty
, "%s ", ecommunity_str(ecom
));
5302 vty_out(vty
, " RD: %s\n",
5303 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5305 json_object_string_add(json
, "vrf", name
);
5306 json_object_string_add(json
, "local-ip",
5307 inet_ntop(AF_INET
, &bgp
->originator_ip
,
5309 sizeof(originator_ip
)));
5310 json_object_int_add(json
, "l3vni", bgp
->l3vni
);
5311 json_object_string_add(
5313 prefix_mac2str(&bgp
->rmac
, buf
, sizeof(buf
)));
5314 json_object_string_add(
5316 CHECK_FLAG(bgp
->vrf_flags
,
5317 BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY
)
5318 ? "prefix-routes-only"
5320 /* list of l2vnis */
5321 for (ALL_LIST_ELEMENTS_RO(bgp
->l2vnis
, node
, vpn
))
5322 json_object_array_add(json_vnis
,
5323 json_object_new_int(vpn
->vni
));
5324 json_object_object_add(json
, "l2vnis", json_vnis
);
5327 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_export_rtl
, node
, ecom
))
5328 json_object_array_add(
5330 json_object_new_string(ecommunity_str(ecom
)));
5331 json_object_object_add(json
, "export-rts", json_export_rts
);
5334 for (ALL_LIST_ELEMENTS_RO(bgp
->vrf_import_rtl
, node
, ecom
))
5335 json_object_array_add(
5337 json_object_new_string(ecommunity_str(ecom
)));
5338 json_object_object_add(json
, "import-rts", json_import_rts
);
5339 json_object_string_add(
5341 prefix_rd2str(&bgp
->vrf_prd
, buf1
, RD_ADDRSTRLEN
));
5345 vty_out(vty
, "%s\n", json_object_to_json_string_ext(
5346 json
, JSON_C_TO_STRING_PRETTY
));
5347 json_object_free(json
);
5352 /* import/export rt for l3vni-vrf */
5353 DEFUN (bgp_evpn_vrf_rt
,
5354 bgp_evpn_vrf_rt_cmd
,
5355 "route-target <both|import|export> RT",
5357 "import and export\n"
5360 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5363 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5364 struct ecommunity
*ecomadd
= NULL
;
5369 if (!strcmp(argv
[1]->arg
, "import"))
5370 rt_type
= RT_TYPE_IMPORT
;
5371 else if (!strcmp(argv
[1]->arg
, "export"))
5372 rt_type
= RT_TYPE_EXPORT
;
5373 else if (!strcmp(argv
[1]->arg
, "both"))
5374 rt_type
= RT_TYPE_BOTH
;
5376 vty_out(vty
, "%% Invalid Route Target type\n");
5380 /* Add/update the import route-target */
5381 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5382 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5383 ECOMMUNITY_ROUTE_TARGET
, 0);
5385 vty_out(vty
, "%% Malformed Route Target list\n");
5388 ecommunity_str(ecomadd
);
5390 /* Do nothing if we already have this import route-target */
5391 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
, ecomadd
))
5392 bgp_evpn_configure_import_rt_for_vrf(bgp
, ecomadd
);
5395 /* Add/update the export route-target */
5396 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5397 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5398 ECOMMUNITY_ROUTE_TARGET
, 0);
5400 vty_out(vty
, "%% Malformed Route Target list\n");
5403 ecommunity_str(ecomadd
);
5405 /* Do nothing if we already have this export route-target */
5406 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
, ecomadd
))
5407 bgp_evpn_configure_export_rt_for_vrf(bgp
, ecomadd
);
5413 DEFUN (no_bgp_evpn_vrf_rt
,
5414 no_bgp_evpn_vrf_rt_cmd
,
5415 "no route-target <both|import|export> RT",
5418 "import and export\n"
5421 EVPN_ASN_IP_HELP_STR
)
5423 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5424 int rt_type
, found_ecomdel
;
5425 struct ecommunity
*ecomdel
= NULL
;
5430 if (!strcmp(argv
[2]->arg
, "import"))
5431 rt_type
= RT_TYPE_IMPORT
;
5432 else if (!strcmp(argv
[2]->arg
, "export"))
5433 rt_type
= RT_TYPE_EXPORT
;
5434 else if (!strcmp(argv
[2]->arg
, "both"))
5435 rt_type
= RT_TYPE_BOTH
;
5437 vty_out(vty
, "%% Invalid Route Target type\n");
5441 if (rt_type
== RT_TYPE_IMPORT
) {
5442 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5444 "%% Import RT is not configured for this VRF\n");
5447 } else if (rt_type
== RT_TYPE_EXPORT
) {
5448 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5450 "%% Export RT is not configured for this VRF\n");
5453 } else if (rt_type
== RT_TYPE_BOTH
) {
5454 if (!CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)
5455 && !CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5457 "%% Import/Export RT is not configured for this VRF\n");
5462 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5464 vty_out(vty
, "%% Malformed Route Target list\n");
5467 ecommunity_str(ecomdel
);
5469 if (rt_type
== RT_TYPE_IMPORT
) {
5470 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5472 ecommunity_free(&ecomdel
);
5474 "%% RT specified does not match configuration for this VRF\n");
5477 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5478 } else if (rt_type
== RT_TYPE_EXPORT
) {
5479 if (!bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5481 ecommunity_free(&ecomdel
);
5483 "%% RT specified does not match configuration for this VRF\n");
5486 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5487 } else if (rt_type
== RT_TYPE_BOTH
) {
5490 if (bgp_evpn_rt_matches_existing(bgp
->vrf_import_rtl
,
5492 bgp_evpn_unconfigure_import_rt_for_vrf(bgp
, ecomdel
);
5496 if (bgp_evpn_rt_matches_existing(bgp
->vrf_export_rtl
,
5498 bgp_evpn_unconfigure_export_rt_for_vrf(bgp
, ecomdel
);
5502 if (!found_ecomdel
) {
5503 ecommunity_free(&ecomdel
);
5505 "%% RT specified does not match configuration for this VRF\n");
5510 ecommunity_free(&ecomdel
);
5514 DEFUN (bgp_evpn_vni_rt
,
5515 bgp_evpn_vni_rt_cmd
,
5516 "route-target <both|import|export> RT",
5518 "import and export\n"
5521 "Route target (A.B.C.D:MN|EF:OPQR|GHJK:MN)\n")
5523 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5524 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5526 struct ecommunity
*ecomadd
= NULL
;
5531 if (!EVPN_ENABLED(bgp
)) {
5533 "This command is only supported under EVPN VRF\n");
5537 if (!strcmp(argv
[1]->text
, "import"))
5538 rt_type
= RT_TYPE_IMPORT
;
5539 else if (!strcmp(argv
[1]->text
, "export"))
5540 rt_type
= RT_TYPE_EXPORT
;
5541 else if (!strcmp(argv
[1]->text
, "both"))
5542 rt_type
= RT_TYPE_BOTH
;
5544 vty_out(vty
, "%% Invalid Route Target type\n");
5548 /* Add/update the import route-target */
5549 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_IMPORT
) {
5550 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5551 ECOMMUNITY_ROUTE_TARGET
, 0);
5553 vty_out(vty
, "%% Malformed Route Target list\n");
5556 ecommunity_str(ecomadd
);
5558 /* Do nothing if we already have this import route-target */
5559 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomadd
))
5560 evpn_configure_import_rt(bgp
, vpn
, ecomadd
);
5563 /* Add/update the export route-target */
5564 if (rt_type
== RT_TYPE_BOTH
|| rt_type
== RT_TYPE_EXPORT
) {
5565 ecomadd
= ecommunity_str2com(argv
[2]->arg
,
5566 ECOMMUNITY_ROUTE_TARGET
, 0);
5568 vty_out(vty
, "%% Malformed Route Target list\n");
5571 ecommunity_str(ecomadd
);
5573 /* Do nothing if we already have this export route-target */
5574 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomadd
))
5575 evpn_configure_export_rt(bgp
, vpn
, ecomadd
);
5581 DEFUN (no_bgp_evpn_vni_rt
,
5582 no_bgp_evpn_vni_rt_cmd
,
5583 "no route-target <both|import|export> RT",
5586 "import and export\n"
5589 EVPN_ASN_IP_HELP_STR
)
5591 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5592 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5593 int rt_type
, found_ecomdel
;
5594 struct ecommunity
*ecomdel
= NULL
;
5599 if (!EVPN_ENABLED(bgp
)) {
5601 "This command is only supported under EVPN VRF\n");
5605 if (!strcmp(argv
[2]->text
, "import"))
5606 rt_type
= RT_TYPE_IMPORT
;
5607 else if (!strcmp(argv
[2]->text
, "export"))
5608 rt_type
= RT_TYPE_EXPORT
;
5609 else if (!strcmp(argv
[2]->text
, "both"))
5610 rt_type
= RT_TYPE_BOTH
;
5612 vty_out(vty
, "%% Invalid Route Target type\n");
5616 /* The user did "no route-target import", check to see if there are any
5617 * import route-targets configured. */
5618 if (rt_type
== RT_TYPE_IMPORT
) {
5619 if (!is_import_rt_configured(vpn
)) {
5621 "%% Import RT is not configured for this VNI\n");
5624 } else if (rt_type
== RT_TYPE_EXPORT
) {
5625 if (!is_export_rt_configured(vpn
)) {
5627 "%% Export RT is not configured for this VNI\n");
5630 } else if (rt_type
== RT_TYPE_BOTH
) {
5631 if (!is_import_rt_configured(vpn
)
5632 && !is_export_rt_configured(vpn
)) {
5634 "%% Import/Export RT is not configured for this VNI\n");
5639 ecomdel
= ecommunity_str2com(argv
[3]->arg
, ECOMMUNITY_ROUTE_TARGET
, 0);
5641 vty_out(vty
, "%% Malformed Route Target list\n");
5644 ecommunity_str(ecomdel
);
5646 if (rt_type
== RT_TYPE_IMPORT
) {
5647 if (!bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5649 "%% RT specified does not match configuration for this VNI\n");
5652 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5653 } else if (rt_type
== RT_TYPE_EXPORT
) {
5654 if (!bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5656 "%% RT specified does not match configuration for this VNI\n");
5659 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5660 } else if (rt_type
== RT_TYPE_BOTH
) {
5663 if (bgp_evpn_rt_matches_existing(vpn
->import_rtl
, ecomdel
)) {
5664 evpn_unconfigure_import_rt(bgp
, vpn
, ecomdel
);
5668 if (bgp_evpn_rt_matches_existing(vpn
->export_rtl
, ecomdel
)) {
5669 evpn_unconfigure_export_rt(bgp
, vpn
, ecomdel
);
5673 if (!found_ecomdel
) {
5675 "%% RT specified does not match configuration for this VNI\n");
5683 DEFUN (no_bgp_evpn_vni_rt_without_val
,
5684 no_bgp_evpn_vni_rt_without_val_cmd
,
5685 "no route-target <import|export>",
5691 struct bgp
*bgp
= VTY_GET_CONTEXT(bgp
);
5692 VTY_DECLVAR_CONTEXT_SUB(bgpevpn
, vpn
);
5698 if (!EVPN_ENABLED(bgp
)) {
5700 "This command is only supported under EVPN VRF\n");
5704 if (!strcmp(argv
[2]->text
, "import")) {
5705 rt_type
= RT_TYPE_IMPORT
;
5706 } else if (!strcmp(argv
[2]->text
, "export")) {
5707 rt_type
= RT_TYPE_EXPORT
;
5709 vty_out(vty
, "%% Invalid Route Target type\n");
5713 /* Check if we should disallow. */
5714 if (rt_type
== RT_TYPE_IMPORT
) {
5715 if (!is_import_rt_configured(vpn
)) {
5717 "%% Import RT is not configured for this VNI\n");
5721 if (!is_export_rt_configured(vpn
)) {
5723 "%% Export RT is not configured for this VNI\n");
5728 /* Unconfigure the RT. */
5729 if (rt_type
== RT_TYPE_IMPORT
)
5730 evpn_unconfigure_import_rt(bgp
, vpn
, NULL
);
5732 evpn_unconfigure_export_rt(bgp
, vpn
, NULL
);
5736 static int vni_cmp(const void **a
, const void **b
)
5738 const struct bgpevpn
*first
= *a
;
5739 const struct bgpevpn
*secnd
= *b
;
5741 return secnd
->vni
- first
->vni
;
5745 * Output EVPN configuration information.
5747 void bgp_config_write_evpn_info(struct vty
*vty
, struct bgp
*bgp
, afi_t afi
,
5750 char buf1
[RD_ADDRSTRLEN
];
5751 char buf2
[INET6_ADDRSTRLEN
];
5753 if (bgp
->advertise_all_vni
)
5754 vty_out(vty
, " advertise-all-vni\n");
5757 struct list
*vnilist
= hash_to_list(bgp
->vnihash
);
5758 struct listnode
*ln
;
5759 struct bgpevpn
*data
;
5761 list_sort(vnilist
, vni_cmp
);
5762 for (ALL_LIST_ELEMENTS_RO(vnilist
, ln
, data
))
5763 write_vni_config(vty
, data
);
5765 list_delete(&vnilist
);
5768 if (bgp
->advertise_autort_rfc8365
)
5769 vty_out(vty
, " autort rfc8365-compatible\n");
5771 if (bgp
->advertise_gw_macip
)
5772 vty_out(vty
, " advertise-default-gw\n");
5774 if (bgp
->evpn_info
->advertise_svi_macip
)
5775 vty_out(vty
, " advertise-svi-ip\n");
5777 if (bgp_mh_info
->host_routes_use_l3nhg
!=
5778 BGP_EVPN_MH_USE_ES_L3NHG_DEF
) {
5779 if (bgp_mh_info
->host_routes_use_l3nhg
)
5780 vty_out(vty
, " use-es-l3nhg\n");
5782 vty_out(vty
, " no use-es-l3nhg\n");
5785 if (bgp_mh_info
->ead_evi_rx
!= BGP_EVPN_MH_EAD_EVI_RX_DEF
) {
5786 if (bgp_mh_info
->ead_evi_rx
)
5787 vty_out(vty
, " no disable-ead-evi-rx\n");
5789 vty_out(vty
, " disable-ead-evi-rx\n");
5792 if (bgp_mh_info
->ead_evi_tx
!= BGP_EVPN_MH_EAD_EVI_TX_DEF
) {
5793 if (bgp_mh_info
->ead_evi_tx
)
5794 vty_out(vty
, " no disable-ead-evi-tx\n");
5796 vty_out(vty
, " disable-ead-evi-tx\n");
5799 if (!bgp
->evpn_info
->dup_addr_detect
)
5800 vty_out(vty
, " no dup-addr-detection\n");
5802 if (bgp
->evpn_info
->dad_max_moves
!=
5803 EVPN_DAD_DEFAULT_MAX_MOVES
||
5804 bgp
->evpn_info
->dad_time
!= EVPN_DAD_DEFAULT_TIME
)
5805 vty_out(vty
, " dup-addr-detection max-moves %u time %u\n",
5806 bgp
->evpn_info
->dad_max_moves
,
5807 bgp
->evpn_info
->dad_time
);
5809 if (bgp
->evpn_info
->dad_freeze
) {
5810 if (bgp
->evpn_info
->dad_freeze_time
)
5812 " dup-addr-detection freeze %u\n",
5813 bgp
->evpn_info
->dad_freeze_time
);
5816 " dup-addr-detection freeze permanent\n");
5819 if (bgp
->vxlan_flood_ctrl
== VXLAN_FLOOD_DISABLED
)
5820 vty_out(vty
, " flooding disable\n");
5822 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5823 BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST
)) {
5824 if (bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
)
5825 vty_out(vty
, " advertise ipv4 unicast route-map %s\n",
5826 bgp
->adv_cmd_rmap
[AFI_IP
][SAFI_UNICAST
].name
);
5828 vty_out(vty
, " advertise ipv4 unicast\n");
5831 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5832 BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST
)) {
5833 if (bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
)
5834 vty_out(vty
, " advertise ipv6 unicast route-map %s\n",
5835 bgp
->adv_cmd_rmap
[AFI_IP6
][SAFI_UNICAST
].name
);
5837 vty_out(vty
, " advertise ipv6 unicast\n");
5840 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5841 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV4
))
5842 vty_out(vty
, " default-originate ipv4\n");
5844 if (CHECK_FLAG(bgp
->af_flags
[AFI_L2VPN
][SAFI_EVPN
],
5845 BGP_L2VPN_EVPN_DEFAULT_ORIGINATE_IPV6
))
5846 vty_out(vty
, " default-originate ipv6\n");
5848 if (bgp
->inst_type
== BGP_INSTANCE_TYPE_VRF
) {
5849 if (!bgp
->evpn_info
->advertise_pip
)
5850 vty_out(vty
, " no advertise-pip\n");
5851 if (bgp
->evpn_info
->advertise_pip
) {
5852 if (bgp
->evpn_info
->pip_ip_static
.s_addr
5854 vty_out(vty
, " advertise-pip ip %s",
5856 &bgp
->evpn_info
->pip_ip_static
,
5857 buf2
, INET_ADDRSTRLEN
));
5859 bgp
->evpn_info
->pip_rmac_static
))) {
5860 char buf
[ETHER_ADDR_STRLEN
];
5862 vty_out(vty
, " mac %s",
5872 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_RD_CFGD
))
5873 vty_out(vty
, " rd %s\n",
5874 prefix_rd2str(&bgp
->vrf_prd
, buf1
, sizeof(buf1
)));
5876 /* import route-target */
5877 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_IMPORT_RT_CFGD
)) {
5879 struct listnode
*node
, *nnode
;
5880 struct ecommunity
*ecom
;
5882 for (ALL_LIST_ELEMENTS(bgp
->vrf_import_rtl
, node
, nnode
,
5884 ecom_str
= ecommunity_ecom2str(
5885 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5886 vty_out(vty
, " route-target import %s\n", ecom_str
);
5887 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5891 /* export route-target */
5892 if (CHECK_FLAG(bgp
->vrf_flags
, BGP_VRF_EXPORT_RT_CFGD
)) {
5894 struct listnode
*node
, *nnode
;
5895 struct ecommunity
*ecom
;
5897 for (ALL_LIST_ELEMENTS(bgp
->vrf_export_rtl
, node
, nnode
,
5899 ecom_str
= ecommunity_ecom2str(
5900 ecom
, ECOMMUNITY_FORMAT_ROUTE_MAP
, 0);
5901 vty_out(vty
, " route-target export %s\n", ecom_str
);
5902 XFREE(MTYPE_ECOMMUNITY_STR
, ecom_str
);
5907 void bgp_ethernetvpn_init(void)
5909 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_cmd
);
5910 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_cmd
);
5911 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_tags_cmd
);
5912 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_rd_tags_cmd
);
5913 install_element(VIEW_NODE
,
5914 &show_ip_bgp_l2vpn_evpn_neighbor_routes_cmd
);
5915 install_element(VIEW_NODE
,
5916 &show_ip_bgp_l2vpn_evpn_rd_neighbor_routes_cmd
);
5919 &show_ip_bgp_l2vpn_evpn_neighbor_advertised_routes_cmd
);
5922 &show_ip_bgp_l2vpn_evpn_rd_neighbor_advertised_routes_cmd
);
5923 install_element(VIEW_NODE
, &show_ip_bgp_evpn_rd_overlay_cmd
);
5924 install_element(VIEW_NODE
, &show_ip_bgp_l2vpn_evpn_all_overlay_cmd
);
5925 install_element(BGP_EVPN_NODE
, &no_evpnrt5_network_cmd
);
5926 install_element(BGP_EVPN_NODE
, &evpnrt5_network_cmd
);
5927 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_all_vni_cmd
);
5928 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_all_vni_cmd
);
5929 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_autort_rfc8365_cmd
);
5930 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_autort_rfc8365_cmd
);
5931 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_default_gw_cmd
);
5932 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_default_gw_cmd
);
5933 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_svi_ip_cmd
);
5934 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_type5_cmd
);
5935 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_advertise_type5_cmd
);
5936 install_element(BGP_EVPN_NODE
, &bgp_evpn_default_originate_cmd
);
5937 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_default_originate_cmd
);
5938 install_element(BGP_EVPN_NODE
, &dup_addr_detection_cmd
);
5939 install_element(BGP_EVPN_NODE
, &dup_addr_detection_auto_recovery_cmd
);
5940 install_element(BGP_EVPN_NODE
, &no_dup_addr_detection_cmd
);
5941 install_element(BGP_EVPN_NODE
, &bgp_evpn_flood_control_cmd
);
5942 install_element(BGP_EVPN_NODE
, &bgp_evpn_advertise_pip_ip_mac_cmd
);
5943 install_element(BGP_EVPN_NODE
, &bgp_evpn_use_es_l3nhg_cmd
);
5944 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_rx_disable_cmd
);
5945 install_element(BGP_EVPN_NODE
, &bgp_evpn_ead_evi_tx_disable_cmd
);
5948 install_element(BGP_EVPN_NODE
, &test_es_add_cmd
);
5949 install_element(BGP_EVPN_NODE
, &test_es_vni_add_cmd
);
5951 /* "show bgp l2vpn evpn" commands. */
5952 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_cmd
);
5953 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_evi_cmd
);
5954 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_es_vrf_cmd
);
5955 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vni_cmd
);
5956 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_summary_cmd
);
5957 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_cmd
);
5958 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_cmd
);
5959 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_rd_macip_cmd
);
5960 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_esi_cmd
);
5961 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_cmd
);
5962 install_element(VIEW_NODE
,
5963 &show_bgp_l2vpn_evpn_route_vni_multicast_cmd
);
5964 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_macip_cmd
);
5965 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_vni_all_cmd
);
5966 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_route_mac_ip_es_cmd
);
5967 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_import_rt_cmd
);
5968 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_vrf_import_rt_cmd
);
5970 /* "show bgp evpn" commands. */
5971 install_element(VIEW_NODE
, &show_bgp_evpn_vni_cmd
);
5972 install_element(VIEW_NODE
, &show_bgp_evpn_summary_cmd
);
5973 install_element(VIEW_NODE
, &show_bgp_evpn_route_cmd
);
5974 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_cmd
);
5975 install_element(VIEW_NODE
, &show_bgp_evpn_route_rd_macip_cmd
);
5976 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_cmd
);
5977 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_multicast_cmd
);
5978 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_macip_cmd
);
5979 install_element(VIEW_NODE
, &show_bgp_evpn_route_vni_all_cmd
);
5980 install_element(VIEW_NODE
, &show_bgp_evpn_import_rt_cmd
);
5981 install_element(VIEW_NODE
, &show_bgp_vrf_l3vni_info_cmd
);
5982 install_element(VIEW_NODE
, &show_bgp_l2vpn_evpn_com_cmd
);
5984 install_element(BGP_EVPN_NODE
, &bgp_evpn_vni_cmd
);
5985 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vni_cmd
);
5986 install_element(BGP_EVPN_VNI_NODE
, &exit_vni_cmd
);
5987 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rd_cmd
);
5988 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_cmd
);
5989 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rd_without_val_cmd
);
5990 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_vni_rt_cmd
);
5991 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_cmd
);
5992 install_element(BGP_EVPN_VNI_NODE
, &no_bgp_evpn_vni_rt_without_val_cmd
);
5993 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rd_cmd
);
5994 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rd_cmd
);
5995 install_element(BGP_NODE
, &no_bgp_evpn_vrf_rd_without_val_cmd
);
5996 install_element(BGP_EVPN_NODE
, &bgp_evpn_vrf_rt_cmd
);
5997 install_element(BGP_EVPN_NODE
, &no_bgp_evpn_vrf_rt_cmd
);
5998 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_svi_ip_vni_cmd
);
5999 install_element(BGP_EVPN_VNI_NODE
,
6000 &bgp_evpn_advertise_default_gw_vni_cmd
);
6001 install_element(BGP_EVPN_VNI_NODE
,
6002 &no_bgp_evpn_advertise_default_gw_vni_cmd
);
6003 install_element(BGP_EVPN_VNI_NODE
, &bgp_evpn_advertise_vni_subnet_cmd
);
6004 install_element(BGP_EVPN_VNI_NODE
,
6005 &no_bgp_evpn_advertise_vni_subnet_cmd
);