2 * Copyright (C) 2002 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra 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 * GNU Zebra 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
34 #include "srcdest_table.h"
36 #include "termtable.h"
37 #include "affinitymap.h"
39 #include "zebra/zebra_router.h"
40 #include "zebra/zserv.h"
41 #include "zebra/zebra_vrf.h"
42 #include "zebra/zebra_mpls.h"
43 #include "zebra/zebra_rnh.h"
44 #include "zebra/redistribute.h"
45 #include "zebra/zebra_affinitymap.h"
46 #include "zebra/zebra_routemap.h"
48 #include "lib/route_opaque.h"
49 #include "zebra/zebra_vxlan.h"
50 #include "zebra/zebra_evpn_mh.h"
51 #include "zebra/zebra_vty_clippy.c"
52 #include "zebra/zserv.h"
53 #include "zebra/router-id.h"
54 #include "zebra/ipforward.h"
55 #include "zebra/zebra_vxlan_private.h"
56 #include "zebra/zebra_pbr.h"
57 #include "zebra/zebra_nhg.h"
58 #include "zebra/zebra_evpn_mh.h"
59 #include "zebra/interface.h"
60 #include "northbound_cli.h"
61 #include "zebra/zebra_nb.h"
62 #include "zebra/kernel_netlink.h"
63 #include "zebra/if_netlink.h"
64 #include "zebra/table_manager.h"
65 #include "zebra/zebra_script.h"
66 #include "zebra/rtadv.h"
67 #include "zebra/zebra_neigh.h"
69 /* context to manage dumps in multiple tables or vrfs */
70 struct route_show_ctx
{
71 bool multi
; /* dump multiple tables or vrf */
72 bool header_done
; /* common header already displayed */
75 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
76 safi_t safi
, bool use_fib
, bool use_json
,
78 const struct prefix
*longer_prefix_p
,
79 bool supernets_only
, int type
,
80 unsigned short ospf_instance_id
, uint32_t tableid
,
81 bool show_ng
, struct route_show_ctx
*ctx
);
82 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
83 int mcast
, bool use_fib
, bool show_ng
);
84 static void vty_show_ip_route_summary(struct vty
*vty
,
85 struct route_table
*table
, bool use_json
);
86 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
87 struct route_table
*table
,
89 /* Helper api to format a nexthop in the 'detailed' output path. */
90 static void show_nexthop_detail_helper(struct vty
*vty
,
91 const struct route_entry
*re
,
92 const struct nexthop
*nexthop
,
95 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
96 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
97 struct route_entry
*re
, unsigned int num
);
99 DEFUN (ip_multicast_mode
,
100 ip_multicast_mode_cmd
,
101 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
103 "Multicast options\n"
104 "RPF lookup behavior\n"
105 "Lookup in unicast RIB only\n"
106 "Lookup in multicast RIB only\n"
107 "Try multicast RIB first, fall back to unicast RIB\n"
108 "Lookup both, use entry with lower distance\n"
109 "Lookup both, use entry with longer prefix\n")
111 char *mode
= argv
[3]->text
;
113 if (strmatch(mode
, "urib-only"))
114 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
115 else if (strmatch(mode
, "mrib-only"))
116 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
117 else if (strmatch(mode
, "mrib-then-urib"))
118 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
119 else if (strmatch(mode
, "lower-distance"))
120 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
121 else if (strmatch(mode
, "longer-prefix"))
122 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
124 vty_out(vty
, "Invalid mode specified\n");
125 return CMD_WARNING_CONFIG_FAILED
;
131 DEFUN (no_ip_multicast_mode
,
132 no_ip_multicast_mode_cmd
,
133 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
136 "Multicast options\n"
137 "RPF lookup behavior\n"
138 "Lookup in unicast RIB only\n"
139 "Lookup in multicast RIB only\n"
140 "Try multicast RIB first, fall back to unicast RIB\n"
141 "Lookup both, use entry with lower distance\n"
142 "Lookup both, use entry with longer prefix\n")
144 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
151 "show [ip$ip|ipv6$ipv6] rpf [json]",
155 "Display RPF information for multicast source\n"
158 bool uj
= use_json(argc
, argv
);
159 struct route_show_ctx ctx
= {
163 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, ip
? AFI_IP
: AFI_IP6
,
164 SAFI_MULTICAST
, false, uj
, 0, NULL
, false, 0, 0,
168 DEFPY (show_ip_rpf_addr
,
169 show_ip_rpf_addr_cmd
,
170 "show ip rpf A.B.C.D$address",
173 "Display RPF information for multicast source\n"
174 "IP multicast source address (e.g. 10.0.0.0)\n")
176 struct route_node
*rn
;
177 struct route_entry
*re
;
179 re
= rib_match_multicast(AFI_IP
, VRF_DEFAULT
, (union g_addr
*)&address
,
183 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
185 vty_out(vty
, "%% No match for RPF lookup\n");
190 DEFPY (show_ipv6_rpf_addr
,
191 show_ipv6_rpf_addr_cmd
,
192 "show ipv6 rpf X:X::X:X$address",
195 "Display RPF information for multicast source\n"
196 "IPv6 multicast source address\n")
198 struct route_node
*rn
;
199 struct route_entry
*re
;
201 re
= rib_match_multicast(AFI_IP6
, VRF_DEFAULT
, (union g_addr
*)&address
,
205 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
207 vty_out(vty
, "%% No match for RPF lookup\n");
212 static char re_status_output_char(const struct route_entry
*re
,
213 const struct nexthop
*nhop
,
216 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
220 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
221 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
222 /* More-specific test for 'fib' output */
224 star_p
= !!CHECK_FLAG(nhop
->flags
,
230 if (zrouter
.asic_offloaded
&&
231 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
234 if (zrouter
.asic_offloaded
235 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
238 if (zrouter
.asic_offloaded
239 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
242 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
251 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
252 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
258 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
265 * Show backup nexthop info, in the 'detailed' output path
267 static void show_nh_backup_helper(struct vty
*vty
,
268 const struct route_entry
*re
,
269 const struct nexthop
*nexthop
)
271 const struct nexthop
*start
, *backup
, *temp
;
274 /* Double-check that there _is_ a backup */
275 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
276 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
277 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
280 /* Locate the backup nexthop(s) */
281 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
282 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
283 /* Format the backup(s) (indented) */
285 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
286 backup
= backup
->next
;
291 /* It's possible for backups to be recursive too,
292 * so walk the recursive resolution list if present.
297 show_nexthop_detail_helper(vty
, re
, backup
,
301 if (backup
->resolved
&& temp
== backup
)
302 backup
= backup
->resolved
;
304 backup
= nexthop_next(backup
);
306 if (backup
== temp
->next
)
314 * Helper api to format output for a nexthop, used in the 'detailed'
317 static void show_nexthop_detail_helper(struct vty
*vty
,
318 const struct route_entry
*re
,
319 const struct nexthop
*nexthop
,
323 char buf
[MPLS_LABEL_STRLEN
];
328 nexthop
->rparent
? " " : "");
330 vty_out(vty
, " %c%s",
331 re_status_output_char(re
, nexthop
, false),
332 nexthop
->rparent
? " " : "");
334 switch (nexthop
->type
) {
335 case NEXTHOP_TYPE_IPV4
:
336 case NEXTHOP_TYPE_IPV4_IFINDEX
:
337 vty_out(vty
, " %pI4",
338 &nexthop
->gate
.ipv4
);
339 if (nexthop
->ifindex
)
340 vty_out(vty
, ", via %s",
345 case NEXTHOP_TYPE_IPV6
:
346 case NEXTHOP_TYPE_IPV6_IFINDEX
:
348 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
350 if (nexthop
->ifindex
)
351 vty_out(vty
, ", via %s",
357 case NEXTHOP_TYPE_IFINDEX
:
358 vty_out(vty
, " directly connected, %s",
359 ifindex2ifname(nexthop
->ifindex
,
362 case NEXTHOP_TYPE_BLACKHOLE
:
363 vty_out(vty
, " unreachable");
364 switch (nexthop
->bh_type
) {
365 case BLACKHOLE_REJECT
:
366 vty_out(vty
, " (ICMP unreachable)");
368 case BLACKHOLE_ADMINPROHIB
:
370 " (ICMP admin-prohibited)");
373 vty_out(vty
, " (blackhole)");
375 case BLACKHOLE_UNSPEC
:
381 if (re
->vrf_id
!= nexthop
->vrf_id
) {
382 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
384 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
387 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
388 vty_out(vty
, " (duplicate nexthop removed)");
390 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
391 vty_out(vty
, " inactive");
393 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
394 vty_out(vty
, " onlink");
396 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
397 vty_out(vty
, " linkdown");
399 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
400 vty_out(vty
, " (recursive)");
402 /* Source specified? */
403 switch (nexthop
->type
) {
404 case NEXTHOP_TYPE_IPV4
:
405 case NEXTHOP_TYPE_IPV4_IFINDEX
:
406 if (nexthop
->src
.ipv4
.s_addr
) {
407 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
408 addrstr
, sizeof(addrstr
)))
409 vty_out(vty
, ", src %s",
414 case NEXTHOP_TYPE_IPV6
:
415 case NEXTHOP_TYPE_IPV6_IFINDEX
:
416 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
418 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
419 addrstr
, sizeof(addrstr
)))
420 vty_out(vty
, ", src %s",
425 case NEXTHOP_TYPE_IFINDEX
:
426 case NEXTHOP_TYPE_BLACKHOLE
:
431 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
433 /* Label information */
434 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
435 vty_out(vty
, ", label %s",
436 mpls_label2str(nexthop
->nh_label
->num_labels
,
437 nexthop
->nh_label
->label
, buf
,
438 sizeof(buf
), nexthop
->nh_label_type
,
443 vty_out(vty
, ", weight %u", nexthop
->weight
);
445 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
446 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
448 for (i
= 1; i
< nexthop
->backup_num
; i
++)
449 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
453 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
454 struct json_object
*json
)
456 struct bgp_zebra_opaque bzo
= {};
457 struct ospf_zebra_opaque ozo
= {};
463 case ZEBRA_ROUTE_SHARP
:
465 json_object_string_add(json
, "opaque",
466 (char *)re
->opaque
->data
);
468 vty_out(vty
, " Opaque Data: %s",
469 (char *)re
->opaque
->data
);
472 case ZEBRA_ROUTE_BGP
:
473 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
476 json_object_string_add(json
, "asPath", bzo
.aspath
);
477 json_object_string_add(json
, "communities",
479 json_object_string_add(json
, "largeCommunities",
481 json_object_string_add(json
, "selectionReason",
482 bzo
.selection_reason
);
484 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
486 if (bzo
.community
[0] != '\0')
487 vty_out(vty
, " Communities : %s\n",
490 if (bzo
.lcommunity
[0] != '\0')
491 vty_out(vty
, " Large-Communities: %s\n",
494 vty_out(vty
, " Selection reason : %s\n",
495 bzo
.selection_reason
);
498 case ZEBRA_ROUTE_OSPF
:
499 case ZEBRA_ROUTE_OSPF6
:
500 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
503 json_object_string_add(json
, "ospfPathType",
505 if (ozo
.area_id
[0] != '\0')
506 json_object_string_add(json
, "ospfAreaId",
508 if (ozo
.tag
[0] != '\0')
509 json_object_string_add(json
, "ospfTag",
512 vty_out(vty
, " OSPF path type : %s\n",
514 if (ozo
.area_id
[0] != '\0')
515 vty_out(vty
, " OSPF area ID : %s\n",
517 if (ozo
.tag
[0] != '\0')
518 vty_out(vty
, " OSPF tag : %s\n",
527 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
531 cur
= monotime(NULL
);
534 frrtime_to_interval(cur
, buf
, bufsize
);
537 /* New RIB. Detailed information for IPv4 route. */
538 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
539 int mcast
, bool use_fib
, bool show_ng
)
541 struct route_entry
*re
;
542 struct nexthop
*nexthop
;
543 char buf
[SRCDEST2STR_BUFFER
];
544 struct zebra_vrf
*zvrf
;
547 dest
= rib_dest_from_rnode(rn
);
549 RNODE_FOREACH_RE (rn
, re
) {
551 * If re not selected for forwarding, skip re
552 * for "show ip/ipv6 fib <prefix>"
554 if (use_fib
&& re
!= dest
->selected_fib
)
557 const char *mcast_info
= "";
559 struct rib_table_info
*info
=
560 srcdest_rnode_table_info(rn
);
561 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
562 ? " using Multicast RIB"
563 : " using Unicast RIB";
566 vty_out(vty
, "Routing entry for %s%s\n",
567 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
568 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
570 vty_out(vty
, "[%d]", re
->instance
);
572 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
575 vty_out(vty
, ", tag %u", re
->tag
);
576 #if defined(SUPPORT_REALMS)
577 if (re
->tag
> 0 && re
->tag
<= 255)
578 vty_out(vty
, "(realm)");
582 vty_out(vty
, ", mtu %u", re
->mtu
);
583 if (re
->vrf_id
!= VRF_DEFAULT
) {
584 zvrf
= vrf_info_lookup(re
->vrf_id
);
585 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
587 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
588 vty_out(vty
, ", best");
591 uptime2str(re
->uptime
, buf
, sizeof(buf
));
593 vty_out(vty
, " Last update %s ago\n", buf
);
596 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
597 if (re
->nhe_installed_id
!= 0
598 && re
->nhe_id
!= re
->nhe_installed_id
)
600 " Installed Nexthop Group ID: %u\n",
601 re
->nhe_installed_id
);
604 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
605 /* Use helper to format each nexthop */
606 show_nexthop_detail_helper(vty
, re
, nexthop
,
607 false /*not backup*/);
610 /* Include backup(s), if present */
611 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
612 show_nh_backup_helper(vty
, re
, nexthop
);
614 zebra_show_ip_route_opaque(vty
, re
, NULL
);
620 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
621 struct route_entry
*re
, json_object
*json
,
622 bool is_fib
, bool show_ng
)
624 const struct nexthop
*nexthop
;
626 char buf
[SRCDEST2STR_BUFFER
];
627 json_object
*json_nexthops
= NULL
;
628 json_object
*json_nexthop
= NULL
;
629 json_object
*json_route
= NULL
;
630 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
631 const struct nexthop_group
*nhg
;
632 char up_str
[MONOTIME_STRLEN
];
634 bool nhg_from_backup
= false;
636 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
638 /* If showing fib information, use the fib view of the
642 nhg
= rib_get_fib_nhg(re
);
644 nhg
= &(re
->nhe
->nhg
);
647 json_route
= json_object_new_object();
648 json_nexthops
= json_object_new_array();
650 json_object_string_add(json_route
, "prefix",
651 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
652 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
653 json_object_string_add(json_route
, "protocol",
654 zebra_route_string(re
->type
));
657 json_object_int_add(json_route
, "instance",
660 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
661 json_object_string_add(json_route
, "vrfName",
662 vrf_id_to_name(re
->vrf_id
));
664 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
665 json_object_boolean_true_add(json_route
, "selected");
667 if (dest
->selected_fib
== re
)
668 json_object_boolean_true_add(json_route
,
671 json_object_int_add(json_route
, "distance",
673 json_object_int_add(json_route
, "metric", re
->metric
);
675 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
676 json_object_boolean_true_add(json_route
, "installed");
678 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
679 json_object_boolean_true_add(json_route
, "failed");
681 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
682 json_object_boolean_true_add(json_route
, "queued");
684 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
685 json_object_boolean_true_add(json_route
, "trapped");
687 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
688 json_object_boolean_true_add(json_route
, "offloaded");
690 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
691 json_object_boolean_false_add(json_route
, "offloaded");
694 json_object_int_add(json_route
, "tag", re
->tag
);
697 json_object_int_add(json_route
, "table", re
->table
);
699 json_object_int_add(json_route
, "internalStatus",
701 json_object_int_add(json_route
, "internalFlags",
703 json_object_int_add(json_route
, "internalNextHopNum",
704 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
705 json_object_int_add(json_route
, "internalNextHopActiveNum",
706 nexthop_group_active_nexthop_num(
708 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
710 if (re
->nhe_installed_id
!= 0)
711 json_object_int_add(json_route
,
712 "installedNexthopGroupId",
713 re
->nhe_installed_id
);
715 json_object_string_add(json_route
, "uptime", up_str
);
717 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
718 json_nexthop
= json_object_new_object();
719 show_nexthop_json_helper(json_nexthop
,
722 json_object_array_add(json_nexthops
,
726 json_object_object_add(json_route
, "nexthops", json_nexthops
);
728 /* If there are backup nexthops, include them */
730 nhg
= rib_get_fib_backup_nhg(re
);
732 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
734 if (nhg
&& nhg
->nexthop
) {
735 json_nexthops
= json_object_new_array();
737 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
738 json_nexthop
= json_object_new_object();
740 show_nexthop_json_helper(json_nexthop
,
742 json_object_array_add(json_nexthops
,
746 json_object_object_add(json_route
, "backupNexthops",
749 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
751 json_object_array_add(json
, json_route
);
755 /* Prefix information, and first nexthop. If we're showing 'fib',
756 * and there are no installed primary nexthops, see if there are any
757 * backup nexthops and start with those.
759 if (is_fib
&& nhg
->nexthop
== NULL
) {
760 nhg
= rib_get_fib_backup_nhg(re
);
761 nhg_from_backup
= true;
764 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
766 len
+= vty_out(vty
, "[%d]", re
->instance
);
767 if (nhg_from_backup
&& nhg
->nexthop
) {
770 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
771 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
772 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
776 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
777 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
778 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
781 /* Distance and metric display. */
782 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
783 (re
->distance
|| re
->metric
)) ||
784 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
785 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
789 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
791 /* Nexthop information. */
792 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
795 } else if (nhg_from_backup
) {
796 vty_out(vty
, " b%c%*c",
797 re_status_output_char(re
, nexthop
, is_fib
),
798 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
800 vty_out(vty
, " %c%*c",
801 re_status_output_char(re
, nexthop
, is_fib
),
802 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
805 show_route_nexthop_helper(vty
, re
, nexthop
);
806 vty_out(vty
, ", %s\n", up_str
);
809 /* If we only had backup nexthops, we're done */
813 /* Check for backup nexthop info if present */
815 nhg
= rib_get_fib_backup_nhg(re
);
817 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
822 /* Print backup info */
823 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
827 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
829 /* TODO -- it'd be nice to be able to include
830 * the entire list of backups, *and* include the
831 * real installation state.
833 vty_out(vty
, " b%c %*c",
834 (star_p
? '*' : ' '),
835 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
836 show_route_nexthop_helper(vty
, re
, nexthop
);
842 static void vty_show_ip_route_detail_json(struct vty
*vty
,
843 struct route_node
*rn
, bool use_fib
)
845 json_object
*json
= NULL
;
846 json_object
*json_prefix
= NULL
;
847 struct route_entry
*re
;
851 dest
= rib_dest_from_rnode(rn
);
853 json
= json_object_new_object();
854 json_prefix
= json_object_new_array();
856 RNODE_FOREACH_RE (rn
, re
) {
858 * If re not selected for forwarding, skip re
859 * for "show ip/ipv6 fib <prefix> json"
861 if (use_fib
&& re
!= dest
->selected_fib
)
863 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
866 prefix2str(&rn
->p
, buf
, sizeof(buf
));
867 json_object_object_add(json
, buf
, json_prefix
);
871 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
872 struct route_table
*table
, afi_t afi
,
873 bool use_fib
, route_tag_t tag
,
874 const struct prefix
*longer_prefix_p
,
875 bool supernets_only
, int type
,
876 unsigned short ospf_instance_id
, bool use_json
,
877 uint32_t tableid
, bool show_ng
,
878 struct route_show_ctx
*ctx
)
880 struct route_node
*rn
;
881 struct route_entry
*re
;
884 json_object
*json
= NULL
;
885 json_object
*json_prefix
= NULL
;
890 * ctx->multi indicates if we are dumping multiple tables or vrfs.
892 * => display the common header at most once
893 * => add newline at each call except first
894 * => always display the VRF and table
896 * => display the common header if at least one entry is found
897 * => display the VRF and table if specific
901 json
= json_object_new_object();
903 /* Show all routes. */
904 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
905 dest
= rib_dest_from_rnode(rn
);
907 RNODE_FOREACH_RE (rn
, re
) {
908 if (use_fib
&& re
!= dest
->selected_fib
)
911 if (tag
&& re
->tag
!= tag
)
915 && !prefix_match(longer_prefix_p
, &rn
->p
))
918 /* This can only be true when the afi is IPv4 */
919 if (supernets_only
) {
920 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
922 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
925 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
928 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
932 if (type
&& re
->type
!= type
)
936 && (re
->type
!= ZEBRA_ROUTE_OSPF
937 || re
->instance
!= ospf_instance_id
))
942 json_prefix
= json_object_new_array();
944 if (!ctx
->header_done
) {
947 SHOW_ROUTE_V4_HEADER
);
950 SHOW_ROUTE_V6_HEADER
);
952 if (ctx
->multi
&& ctx
->header_done
)
954 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
957 vty_out(vty
, "VRF %s:\n",
961 "VRF %s table %u:\n",
965 ctx
->header_done
= true;
969 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
974 prefix2str(&rn
->p
, buf
, sizeof(buf
));
975 json_object_object_add(json
, buf
, json_prefix
);
984 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
985 afi_t afi
, bool use_fib
, bool use_json
,
987 const struct prefix
*longer_prefix_p
,
988 bool supernets_only
, int type
,
989 unsigned short ospf_instance_id
, bool show_ng
,
990 struct route_show_ctx
*ctx
)
992 struct zebra_router_table
*zrt
;
993 struct rib_table_info
*info
;
995 RB_FOREACH (zrt
, zebra_router_table_head
,
997 info
= route_table_get_info(zrt
->table
);
999 if (zvrf
!= info
->zvrf
)
1001 if (zrt
->afi
!= afi
||
1002 zrt
->safi
!= SAFI_UNICAST
)
1005 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1006 use_fib
, use_json
, tag
, longer_prefix_p
,
1007 supernets_only
, type
, ospf_instance_id
,
1008 zrt
->tableid
, show_ng
, ctx
);
1012 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1013 safi_t safi
, bool use_fib
, bool use_json
,
1015 const struct prefix
*longer_prefix_p
,
1016 bool supernets_only
, int type
,
1017 unsigned short ospf_instance_id
, uint32_t tableid
,
1018 bool show_ng
, struct route_show_ctx
*ctx
)
1020 struct route_table
*table
;
1021 struct zebra_vrf
*zvrf
= NULL
;
1023 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1025 vty_out(vty
, "{}\n");
1027 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1031 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1033 vty_out(vty
, "{}\n");
1035 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1040 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1042 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1045 vty_out(vty
, "{}\n");
1049 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1050 longer_prefix_p
, supernets_only
, type
,
1051 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1058 "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
1062 "IP nexthop tracking table\n"
1063 "IP import check tracking table\n"
1069 VRF_ALL_CMD_HELP_STR
1070 "Show Multicast (MRIB) NHT state\n"
1073 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1074 vrf_id_t vrf_id
= VRF_DEFAULT
;
1075 struct prefix prefix
, *p
= NULL
;
1076 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1077 bool uj
= use_json(argc
, argv
);
1078 json_object
*json
= NULL
;
1079 json_object
*json_vrf
= NULL
;
1080 json_object
*json_nexthop
= NULL
;
1083 json
= json_object_new_object();
1087 struct zebra_vrf
*zvrf
;
1089 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1090 if ((zvrf
= vrf
->info
) != NULL
) {
1092 json_vrf
= json_object_new_object();
1093 json_nexthop
= json_object_new_object();
1094 json_object_object_add(json
,
1097 json_object_object_add(json_vrf
,
1103 vty_out(vty
, "\nVRF %s:\n",
1106 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1107 vty
, NULL
, json_nexthop
);
1112 vty_json(vty
, json
);
1117 VRF_GET_ID(vrf_id
, vrf_name
, false);
1119 memset(&prefix
, 0, sizeof(prefix
));
1121 p
= sockunion2hostprefix(addr
, &prefix
);
1124 json_object_free(json
);
1130 json_vrf
= json_object_new_object();
1131 json_nexthop
= json_object_new_object();
1133 json_object_object_add(json
, vrf_name
, json_vrf
);
1135 json_object_object_add(json
, "default", json_vrf
);
1137 json_object_object_add(json_vrf
,
1138 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1142 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1145 vty_json(vty
, json
);
1150 DEFUN (ip_nht_default_route
,
1151 ip_nht_default_route_cmd
,
1152 "ip nht resolve-via-default",
1154 "Filter Next Hop tracking route resolution\n"
1155 "Resolve via default route\n")
1157 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1162 if (zvrf
->zebra_rnh_ip_default_route
)
1165 zvrf
->zebra_rnh_ip_default_route
= true;
1167 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1171 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1172 json_object
*json_nhe_hdr
)
1174 struct nexthop
*nexthop
= NULL
;
1175 struct nhg_connected
*rb_node_dep
= NULL
;
1176 struct nexthop_group
*backup_nhg
;
1177 char up_str
[MONOTIME_STRLEN
];
1178 char time_left
[MONOTIME_STRLEN
];
1179 json_object
*json_dependants
= NULL
;
1180 json_object
*json_depends
= NULL
;
1181 json_object
*json_nexthop_array
= NULL
;
1182 json_object
*json_nexthops
= NULL
;
1183 json_object
*json
= NULL
;
1184 json_object
*json_backup_nexthop_array
= NULL
;
1185 json_object
*json_backup_nexthops
= NULL
;
1188 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1191 json
= json_object_new_object();
1194 json_object_string_add(json
, "type",
1195 zebra_route_string(nhe
->type
));
1196 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1197 if (thread_is_scheduled(nhe
->timer
))
1198 json_object_string_add(
1199 json
, "timeToDeletion",
1200 thread_timer_to_hhmmss(time_left
,
1203 json_object_string_add(json
, "uptime", up_str
);
1204 json_object_string_add(json
, "vrf",
1205 vrf_id_to_name(nhe
->vrf_id
));
1208 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1209 zebra_route_string(nhe
->type
));
1210 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1211 if (thread_is_scheduled(nhe
->timer
))
1212 vty_out(vty
, " Time to Deletion: %s",
1213 thread_timer_to_hhmmss(time_left
,
1218 vty_out(vty
, " Uptime: %s\n", up_str
);
1219 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1222 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1224 json_object_boolean_true_add(json
, "valid");
1226 vty_out(vty
, " Valid");
1228 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1230 json_object_boolean_true_add(json
, "installed");
1232 vty_out(vty
, ", Installed");
1239 json_object_int_add(json
, "interfaceIndex",
1242 vty_out(vty
, " Interface Index: %d\n",
1246 if (!zebra_nhg_depends_is_empty(nhe
)) {
1248 json_depends
= json_object_new_array();
1250 vty_out(vty
, " Depends:");
1251 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1253 json_object_array_add(
1255 json_object_new_int(
1256 rb_node_dep
->nhe
->id
));
1258 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1263 json_object_object_add(json
, "depends", json_depends
);
1266 /* Output nexthops */
1268 json_nexthop_array
= json_object_new_array();
1271 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1272 if (json_nexthop_array
) {
1273 json_nexthops
= json_object_new_object();
1274 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1276 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1279 /* Make recursive nexthops a bit more clear */
1281 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1284 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1285 if (CHECK_FLAG(nexthop
->flags
,
1286 NEXTHOP_FLAG_HAS_BACKUP
)) {
1288 json_object_int_add(
1289 json_nexthops
, "backup",
1290 nexthop
->backup_idx
[0]);
1292 vty_out(vty
, " [backup %d]",
1293 nexthop
->backup_idx
[0]);
1299 json_object_array_add(json_nexthop_array
,
1306 /* TODO -- print more useful backup info */
1307 if (CHECK_FLAG(nexthop
->flags
,
1308 NEXTHOP_FLAG_HAS_BACKUP
)) {
1311 vty_out(vty
, "[backup");
1312 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1314 nexthop
->backup_idx
[i
]);
1319 json_object_array_add(json_nexthop_array
,
1325 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1327 /* Output backup nexthops (if any) */
1328 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1331 json_backup_nexthop_array
= json_object_new_array();
1333 vty_out(vty
, " Backups:\n");
1335 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1336 if (json_backup_nexthop_array
) {
1337 json_backup_nexthops
= json_object_new_object();
1338 show_nexthop_json_helper(json_backup_nexthops
,
1340 json_object_array_add(json_backup_nexthop_array
,
1341 json_backup_nexthops
);
1344 if (!CHECK_FLAG(nexthop
->flags
,
1345 NEXTHOP_FLAG_RECURSIVE
))
1348 /* Make recursive nexthops a bit more
1352 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1358 json_object_object_add(json
, "backupNexthops",
1359 json_backup_nexthop_array
);
1362 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1364 json_dependants
= json_object_new_array();
1366 vty_out(vty
, " Dependents:");
1367 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1370 json_object_array_add(
1372 json_object_new_int(
1373 rb_node_dep
->nhe
->id
));
1375 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1378 json_object_object_add(json
, "dependents",
1384 if (nhe
->nhg
.nhgr
.buckets
) {
1386 json_object_int_add(json
, "buckets",
1387 nhe
->nhg
.nhgr
.buckets
);
1388 json_object_int_add(json
, "idleTimer",
1389 nhe
->nhg
.nhgr
.idle_timer
);
1390 json_object_int_add(json
, "unbalancedTimer",
1391 nhe
->nhg
.nhgr
.unbalanced_timer
);
1392 json_object_int_add(json
, "unbalancedTime",
1393 nhe
->nhg
.nhgr
.unbalanced_time
);
1396 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1398 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1399 nhe
->nhg
.nhgr
.unbalanced_timer
,
1400 nhe
->nhg
.nhgr
.unbalanced_time
);
1405 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1408 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1411 struct nhg_hash_entry
*nhe
= NULL
;
1413 nhe
= zebra_nhg_lookup_id(id
);
1416 show_nexthop_group_out(vty
, nhe
, json
);
1419 vty_json(vty
, json
);
1421 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1427 vty_json(vty
, json
);
1432 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1434 struct nhe_show_context
{
1442 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1444 struct nhe_show_context
*ctx
= arg
;
1445 struct nhg_hash_entry
*nhe
;
1447 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1449 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1452 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1455 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1458 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1461 return HASHWALK_CONTINUE
;
1464 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1465 struct zebra_vrf
*zvrf
, afi_t afi
,
1466 int type
, json_object
*json
)
1468 struct nhe_show_context ctx
;
1472 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1476 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1479 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1481 struct zebra_if
*zebra_if
= NULL
;
1482 struct nhg_connected
*rb_node_dep
= NULL
;
1484 zebra_if
= ifp
->info
;
1486 if (!if_nhg_dependents_is_empty(ifp
)) {
1487 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1489 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1492 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1497 DEFPY (show_interface_nexthop_group
,
1498 show_interface_nexthop_group_cmd
,
1499 "show interface [IFNAME$if_name] nexthop-group",
1501 "Interface status and configuration\n"
1503 "Show Nexthop Groups\n")
1505 struct vrf
*vrf
= NULL
;
1506 struct interface
*ifp
= NULL
;
1509 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1511 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1513 if_nexthop_group_dump_vty(vty
, ifp
);
1517 FOR_ALL_INTERFACES (vrf
, ifp
)
1518 if_nexthop_group_dump_vty(vty
, ifp
);
1524 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1531 DEFPY(show_nexthop_group
,
1532 show_nexthop_group_cmd
,
1533 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]",
1535 "Show Nexthop Groups\n"
1537 "Nexthop Group ID\n"
1538 "Show Singleton Nexthop-Groups\n"
1541 "Kernel (not installed via the zebra RIB)\n"
1542 "Zebra (implicitly created by zebra)\n"
1543 "Border Gateway Protocol (BGP)\n"
1544 "Super Happy Advanced Routing Protocol (SHARP)\n"
1545 VRF_FULL_CMD_HELP_STR
1549 struct zebra_vrf
*zvrf
= NULL
;
1550 afi_t afi
= AFI_UNSPEC
;
1552 bool uj
= use_json(argc
, argv
);
1553 json_object
*json
= NULL
;
1554 json_object
*json_vrf
= NULL
;
1557 json
= json_object_new_object();
1560 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1568 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1571 type
= ZEBRA_ROUTE_NHG
;
1575 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1577 vty_json(vty
, json
);
1580 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1587 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1588 struct zebra_vrf
*zvrf
;
1594 json_vrf
= json_object_new_object();
1596 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1598 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1601 json_object_object_add(json
, vrf
->name
,
1606 vty_json(vty
, json
);
1612 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1614 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1618 vty_json(vty
, json
);
1620 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1625 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1628 vty_json(vty
, json
);
1633 DEFPY_HIDDEN(nexthop_group_use_enable
,
1634 nexthop_group_use_enable_cmd
,
1635 "[no] zebra nexthop kernel enable",
1638 "Nexthop configuration \n"
1639 "Configure use of kernel nexthops\n"
1640 "Enable kernel nexthops\n")
1642 zebra_nhg_enable_kernel_nexthops(!no
);
1646 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1647 "[no] zebra nexthop proto only",
1649 "Nexthop configuration\n"
1650 "Configure exclusive use of proto nexthops\n"
1651 "Only use proto nexthops\n")
1653 zebra_nhg_set_proto_nexthops_only(!no
);
1657 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1658 backup_nexthop_recursive_use_enable_cmd
,
1659 "[no] zebra nexthop resolve-via-backup",
1662 "Nexthop configuration \n"
1663 "Configure use of backup nexthops in recursive resolution\n")
1665 zebra_nhg_set_recursive_use_backups(!no
);
1669 DEFUN (no_ip_nht_default_route
,
1670 no_ip_nht_default_route_cmd
,
1671 "no ip nht resolve-via-default",
1674 "Filter Next Hop tracking route resolution\n"
1675 "Resolve via default route\n")
1677 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1682 if (!zvrf
->zebra_rnh_ip_default_route
)
1685 zvrf
->zebra_rnh_ip_default_route
= false;
1686 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1690 DEFUN (ipv6_nht_default_route
,
1691 ipv6_nht_default_route_cmd
,
1692 "ipv6 nht resolve-via-default",
1694 "Filter Next Hop tracking route resolution\n"
1695 "Resolve via default route\n")
1697 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1702 if (zvrf
->zebra_rnh_ipv6_default_route
)
1705 zvrf
->zebra_rnh_ipv6_default_route
= true;
1706 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1710 DEFUN (no_ipv6_nht_default_route
,
1711 no_ipv6_nht_default_route_cmd
,
1712 "no ipv6 nht resolve-via-default",
1715 "Filter Next Hop tracking route resolution\n"
1716 "Resolve via default route\n")
1718 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1723 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1726 zvrf
->zebra_rnh_ipv6_default_route
= false;
1727 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1731 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1732 "[no] ip nht hide-backup-events",
1735 "Nexthop-tracking configuration\n"
1736 "Hide notification about backup nexthops\n")
1738 rnh_set_hide_backups(!no
);
1746 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1747 [vrf <NAME$vrf_name|all$vrf_all>]\
1750 |A.B.C.D/M$prefix longer-prefixes\
1751 |supernets-only$supernets_only\
1754 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1755 |ospf$type_str (1-65535)$ospf_instance_id\
1757 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1758 [vrf <NAME$vrf_name|all$vrf_all>]\
1761 |X:X::X:X/M$prefix longer-prefixes\
1763 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1765 [<json$json|nexthop-group$ng>]",
1768 "IP forwarding table\n"
1769 "IP routing table\n"
1770 "Table to display\n"
1771 "The table number to display\n"
1773 VRF_FULL_CMD_HELP_STR
1774 "Show only routes with tag\n"
1776 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1777 "Show route matching the specified Network/Mask pair only\n"
1778 "Show supernet entries only\n"
1779 FRR_IP_REDIST_HELP_STR_ZEBRA
1780 "Open Shortest Path First (OSPFv2)\n"
1783 "IP forwarding table\n"
1784 "IP routing table\n"
1785 "Table to display\n"
1786 "The table number to display\n"
1788 VRF_FULL_CMD_HELP_STR
1789 "Show only routes with tag\n"
1792 "Show route matching the specified Network/Mask pair only\n"
1793 FRR_IP6_REDIST_HELP_STR_ZEBRA
1795 "Nexthop Group Information\n")
1797 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1800 struct zebra_vrf
*zvrf
;
1801 struct route_show_ctx ctx
= {
1802 .multi
= vrf_all
|| table_all
,
1805 if (!vrf_is_backend_netns()) {
1806 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1808 vty_out(vty
, "{}\n");
1810 vty_out(vty
, "Linux vrf backend already points to table id\n");
1811 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1817 type
= proto_redistnum(afi
, type_str
);
1819 vty_out(vty
, "Unknown route type\n");
1825 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1826 if ((zvrf
= vrf
->info
) == NULL
1827 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1831 do_show_ip_route_all(
1832 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1833 prefix_str
? prefix
: NULL
,
1834 !!supernets_only
, type
,
1835 ospf_instance_id
, !!ng
, &ctx
);
1838 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1840 prefix_str
? prefix
: NULL
,
1841 !!supernets_only
, type
,
1842 ospf_instance_id
, table
, !!ng
, &ctx
);
1845 vrf_id_t vrf_id
= VRF_DEFAULT
;
1848 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1849 vrf
= vrf_lookup_by_id(vrf_id
);
1858 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1859 prefix_str
? prefix
: NULL
,
1860 !!supernets_only
, type
,
1861 ospf_instance_id
, !!ng
, &ctx
);
1863 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1865 prefix_str
? prefix
: NULL
,
1866 !!supernets_only
, type
,
1867 ospf_instance_id
, table
, !!ng
, &ctx
);
1873 ALIAS_HIDDEN (show_route
,
1875 "show <ip$ipv4|ipv6$ipv6> ro",
1879 "IP routing table\n");
1882 DEFPY (show_route_detail
,
1883 show_route_detail_cmd
,
1886 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1891 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1897 [json$json] [nexthop-group$ng]",
1900 "IP forwarding table\n"
1901 "IP routing table\n"
1902 VRF_FULL_CMD_HELP_STR
1903 "Network in the IP routing table to display\n"
1904 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1906 "IPv6 forwarding table\n"
1907 "IPv6 routing table\n"
1908 VRF_FULL_CMD_HELP_STR
1912 "Nexthop Group Information\n")
1914 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1915 struct route_table
*table
;
1917 struct route_node
*rn
;
1918 bool use_fib
= !!fib
;
1920 bool network_found
= false;
1921 bool show_ng
= !!ng
;
1924 prefix_str
= address_str
;
1925 if (str2prefix(prefix_str
, &p
) < 0) {
1926 vty_out(vty
, "%% Malformed address\n");
1932 struct zebra_vrf
*zvrf
;
1934 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1935 if ((zvrf
= vrf
->info
) == NULL
1936 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1939 rn
= route_node_match(table
, &p
);
1942 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1943 route_unlock_node(rn
);
1947 dest
= rib_dest_from_rnode(rn
);
1948 if (use_fib
&& !dest
->selected_fib
) {
1949 route_unlock_node(rn
);
1953 network_found
= true;
1955 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1957 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1960 route_unlock_node(rn
);
1963 if (!network_found
) {
1965 vty_out(vty
, "{}\n");
1969 "%% Network not in FIB\n");
1972 "%% Network not in RIB\n");
1977 vrf_id_t vrf_id
= VRF_DEFAULT
;
1980 VRF_GET_ID(vrf_id
, vrf_name
, false);
1982 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1986 rn
= route_node_match(table
, &p
);
1988 dest
= rib_dest_from_rnode(rn
);
1990 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1991 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1993 vty_out(vty
, "{}\n");
1997 "%% Network not in FIB\n");
2000 "%% Network not in table\n");
2003 route_unlock_node(rn
);
2008 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2010 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2012 route_unlock_node(rn
);
2018 DEFPY (show_route_summary
,
2019 show_route_summary_cmd
,
2020 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2021 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2025 "IP routing table\n"
2026 VRF_FULL_CMD_HELP_STR
2027 "Summary of all routes\n"
2028 "Table to display summary for\n"
2029 "The table number\n"
2033 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2034 struct route_table
*table
;
2035 bool uj
= use_json(argc
, argv
);
2039 struct zebra_vrf
*zvrf
;
2041 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2042 if ((zvrf
= vrf
->info
) == NULL
)
2046 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2049 table
= zebra_vrf_lookup_table_with_table_id(
2050 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2057 vty_show_ip_route_summary_prefix(vty
, table
,
2060 vty_show_ip_route_summary(vty
, table
, uj
);
2063 vrf_id_t vrf_id
= VRF_DEFAULT
;
2066 VRF_GET_ID(vrf_id
, vrf_name
, false);
2069 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2071 table
= zebra_vrf_lookup_table_with_table_id(
2072 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2077 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2079 vty_show_ip_route_summary(vty
, table
, uj
);
2085 DEFUN_HIDDEN (show_route_zebra_dump
,
2086 show_route_zebra_dump_cmd
,
2087 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2097 struct route_table
*table
;
2098 const char *vrf_name
= NULL
;
2101 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2103 if (argv_find(argv
, argc
, "vrf", &idx
))
2104 vrf_name
= argv
[++idx
]->arg
;
2108 struct zebra_vrf
*zvrf
;
2110 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2113 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2116 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2117 show_ip_route_dump_vty(vty
, table
);
2120 vrf_id_t vrf_id
= VRF_DEFAULT
;
2122 VRF_GET_ID(vrf_id
, vrf_name
, true);
2124 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2128 show_ip_route_dump_vty(vty
, table
);
2134 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2135 struct route_entry
*re
, unsigned int num
)
2138 char buf
[SRCDEST2STR_BUFFER
];
2140 vty_out(vty
, " Nexthop %u:\n", num
);
2141 vty_out(vty
, " type: %u\n", nexthop
->type
);
2142 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2143 switch (nexthop
->type
) {
2144 case NEXTHOP_TYPE_IPV4
:
2145 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2146 vty_out(vty
, " ip address: %s\n",
2147 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2149 vty_out(vty
, " afi: ipv4\n");
2151 if (nexthop
->ifindex
) {
2152 vty_out(vty
, " interface index: %d\n",
2154 vty_out(vty
, " interface name: %s\n",
2155 ifindex2ifname(nexthop
->ifindex
,
2159 if (nexthop
->src
.ipv4
.s_addr
2160 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2162 vty_out(vty
, " source: %s\n", buf
);
2164 case NEXTHOP_TYPE_IPV6
:
2165 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2166 vty_out(vty
, " ip: %s\n",
2167 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2169 vty_out(vty
, " afi: ipv6\n");
2171 if (nexthop
->ifindex
) {
2172 vty_out(vty
, " interface index: %d\n",
2174 vty_out(vty
, " interface name: %s\n",
2175 ifindex2ifname(nexthop
->ifindex
,
2179 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2180 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2182 vty_out(vty
, " source: %s\n", buf
);
2185 case NEXTHOP_TYPE_IFINDEX
:
2187 " Nexthop is an interface (directly connected).\n");
2188 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2189 vty_out(vty
, " interface name: %s\n",
2190 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2192 case NEXTHOP_TYPE_BLACKHOLE
:
2193 vty_out(vty
, " Nexthop type is blackhole.\n");
2195 switch (nexthop
->bh_type
) {
2196 case BLACKHOLE_REJECT
:
2197 vty_out(vty
, " Blackhole type: reject\n");
2199 case BLACKHOLE_ADMINPROHIB
:
2201 " Blackhole type: admin-prohibited\n");
2203 case BLACKHOLE_NULL
:
2204 vty_out(vty
, " Blackhole type: NULL0\n");
2206 case BLACKHOLE_UNSPEC
:
2213 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2215 struct route_node
*rn
;
2216 struct route_entry
*re
;
2217 char buf
[SRCDEST2STR_BUFFER
];
2222 struct nexthop
*nexthop
= NULL
;
2223 int nexthop_num
= 0;
2225 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2226 vty_out(vty
, "----------------------------\n");
2228 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2229 RNODE_FOREACH_RE (rn
, re
) {
2230 vty_out(vty
, "Route: %s\n",
2231 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2232 vty_out(vty
, " protocol: %s\n",
2233 zebra_route_string(re
->type
));
2234 vty_out(vty
, " instance: %u\n", re
->instance
);
2235 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2236 vty_out(vty
, " VRF name: %s\n",
2237 vrf_id_to_name(re
->vrf_id
));
2238 vty_out(vty
, " flags: %u\n", re
->flags
);
2240 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2241 vty_out(vty
, " distance: %u\n", re
->distance
);
2242 vty_out(vty
, " metric: %u\n", re
->metric
);
2245 vty_out(vty
, " tag: %u\n", re
->tag
);
2247 uptime
= monotime(&tv
);
2248 uptime
-= re
->uptime
;
2249 gmtime_r(&uptime
, &tm
);
2251 if (uptime
< ONE_DAY_SECOND
)
2252 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2253 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2254 else if (uptime
< ONE_WEEK_SECOND
)
2255 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2256 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2258 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2260 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2263 vty_out(vty
, " status: %u\n", re
->status
);
2264 vty_out(vty
, " nexthop_num: %u\n",
2265 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2266 vty_out(vty
, " nexthop_active_num: %u\n",
2267 nexthop_group_active_nexthop_num(
2269 vty_out(vty
, " table: %u\n", re
->table
);
2270 vty_out(vty
, " uptime: %s\n", time
);
2272 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2274 show_ip_route_nht_dump(vty
, nexthop
, re
,
2284 static void vty_show_ip_route_summary(struct vty
*vty
,
2285 struct route_table
*table
, bool use_json
)
2287 struct route_node
*rn
;
2288 struct route_entry
*re
;
2289 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2290 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2291 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2292 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2293 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2294 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2297 json_object
*json_route_summary
= NULL
;
2298 json_object
*json_route_routes
= NULL
;
2300 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2301 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2302 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2303 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2306 json_route_summary
= json_object_new_object();
2307 json_route_routes
= json_object_new_array();
2308 json_object_object_add(json_route_summary
, "routes",
2312 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2313 RNODE_FOREACH_RE (rn
, re
) {
2314 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2315 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2317 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2319 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2321 rib_cnt
[re
->type
]++;
2323 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2324 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2327 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2329 fib_cnt
[re
->type
]++;
2332 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2334 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2336 trap_cnt
[re
->type
]++;
2339 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2341 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2343 offload_cnt
[re
->type
]++;
2348 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2350 zvrf_name(((struct rib_table_info
*)
2351 route_table_get_info(table
))
2354 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2355 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2356 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2357 if (i
== ZEBRA_ROUTE_BGP
) {
2359 json_object
*json_route_ebgp
=
2360 json_object_new_object();
2362 json_object_int_add(
2363 json_route_ebgp
, "fib",
2364 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2365 json_object_int_add(
2366 json_route_ebgp
, "rib",
2367 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2368 json_object_int_add(
2369 json_route_ebgp
, "fibOffLoaded",
2370 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2371 json_object_int_add(
2372 json_route_ebgp
, "fibTrapped",
2373 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2375 json_object_string_add(json_route_ebgp
,
2377 json_object_array_add(json_route_routes
,
2380 json_object
*json_route_ibgp
=
2381 json_object_new_object();
2383 json_object_int_add(
2384 json_route_ibgp
, "fib",
2385 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2386 json_object_int_add(
2387 json_route_ibgp
, "rib",
2388 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2389 json_object_int_add(
2390 json_route_ibgp
, "fibOffLoaded",
2391 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2392 json_object_int_add(
2393 json_route_ibgp
, "fibTrapped",
2394 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2395 json_object_string_add(json_route_ibgp
,
2397 json_object_array_add(json_route_routes
,
2400 vty_out(vty
, "%-20s %-20d %-20d \n",
2402 rib_cnt
[ZEBRA_ROUTE_BGP
],
2403 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2404 vty_out(vty
, "%-20s %-20d %-20d \n",
2406 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2407 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2411 json_object
*json_route_type
=
2412 json_object_new_object();
2414 json_object_int_add(json_route_type
,
2416 json_object_int_add(json_route_type
,
2419 json_object_int_add(json_route_type
,
2422 json_object_int_add(json_route_type
,
2425 json_object_string_add(
2426 json_route_type
, "type",
2427 zebra_route_string(i
));
2428 json_object_array_add(json_route_routes
,
2431 vty_out(vty
, "%-20s %-20d %-20d \n",
2432 zebra_route_string(i
),
2433 rib_cnt
[i
], fib_cnt
[i
]);
2439 json_object_int_add(json_route_summary
, "routesTotal",
2440 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2441 json_object_int_add(json_route_summary
, "routesTotalFib",
2442 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2444 vty_json(vty
, json_route_summary
);
2446 vty_out(vty
, "------\n");
2447 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2448 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2454 * Implementation of the ip route summary prefix command.
2456 * This command prints the primary prefixes that have been installed by various
2457 * protocols on the box.
2460 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2461 struct route_table
*table
,
2464 struct route_node
*rn
;
2465 struct route_entry
*re
;
2466 struct nexthop
*nexthop
;
2467 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2468 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2469 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2470 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2473 json_object
*json_route_summary
= NULL
;
2474 json_object
*json_route_routes
= NULL
;
2476 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2477 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2480 json_route_summary
= json_object_new_object();
2481 json_route_routes
= json_object_new_array();
2482 json_object_object_add(json_route_summary
, "prefixRoutes",
2486 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2487 RNODE_FOREACH_RE (rn
, re
) {
2490 * In case of ECMP, count only once.
2493 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2494 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2495 fib_cnt
[re
->type
]++;
2497 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2498 nexthop
= nexthop
->next
) {
2500 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2501 rib_cnt
[re
->type
]++;
2502 if (re
->type
== ZEBRA_ROUTE_BGP
2503 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2504 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2505 if (CHECK_FLAG(re
->status
,
2506 ROUTE_ENTRY_INSTALLED
))
2507 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2513 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2514 "Prefix Routes", "FIB",
2515 zvrf_name(((struct rib_table_info
*)
2516 route_table_get_info(table
))
2519 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2520 if (rib_cnt
[i
] > 0) {
2521 if (i
== ZEBRA_ROUTE_BGP
) {
2523 json_object
*json_route_ebgp
=
2524 json_object_new_object();
2526 json_object_int_add(
2527 json_route_ebgp
, "fib",
2528 fib_cnt
[ZEBRA_ROUTE_BGP
]
2529 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2530 json_object_int_add(
2531 json_route_ebgp
, "rib",
2532 rib_cnt
[ZEBRA_ROUTE_BGP
]
2533 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2534 json_object_string_add(json_route_ebgp
,
2536 json_object_array_add(json_route_routes
,
2539 json_object
*json_route_ibgp
=
2540 json_object_new_object();
2542 json_object_int_add(
2543 json_route_ibgp
, "fib",
2544 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2545 json_object_int_add(
2546 json_route_ibgp
, "rib",
2547 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2548 json_object_string_add(json_route_ibgp
,
2550 json_object_array_add(json_route_routes
,
2553 vty_out(vty
, "%-20s %-20d %-20d \n",
2555 rib_cnt
[ZEBRA_ROUTE_BGP
]
2556 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2557 fib_cnt
[ZEBRA_ROUTE_BGP
]
2558 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2559 vty_out(vty
, "%-20s %-20d %-20d \n",
2561 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2562 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2566 json_object
*json_route_type
=
2567 json_object_new_object();
2569 json_object_int_add(json_route_type
,
2571 json_object_int_add(json_route_type
,
2573 json_object_string_add(
2574 json_route_type
, "type",
2575 zebra_route_string(i
));
2576 json_object_array_add(json_route_routes
,
2579 vty_out(vty
, "%-20s %-20d %-20d \n",
2580 zebra_route_string(i
),
2581 rib_cnt
[i
], fib_cnt
[i
]);
2587 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2588 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2589 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2590 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2592 vty_json(vty
, json_route_summary
);
2594 vty_out(vty
, "------\n");
2595 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2596 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2601 DEFUN (allow_external_route_update
,
2602 allow_external_route_update_cmd
,
2603 "allow-external-route-update",
2604 "Allow FRR routes to be overwritten by external processes\n")
2606 zrouter
.allow_delete
= true;
2611 DEFUN (no_allow_external_route_update
,
2612 no_allow_external_route_update_cmd
,
2613 "no allow-external-route-update",
2615 "Allow FRR routes to be overwritten by external processes\n")
2617 zrouter
.allow_delete
= false;
2630 struct zebra_vrf
*zvrf
;
2632 if (vrf_is_backend_netns())
2633 vty_out(vty
, "netns-based vrfs\n");
2635 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2636 if (!(zvrf
= vrf
->info
))
2638 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2641 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2642 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2643 vty_out(vty
, "inactive");
2644 else if (zvrf_ns_name(zvrf
))
2645 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2646 zvrf_ns_name(zvrf
));
2648 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2650 if (vrf_is_user_cfged(vrf
))
2651 vty_out(vty
, " (configured)");
2658 DEFPY (evpn_mh_mac_holdtime
,
2659 evpn_mh_mac_holdtime_cmd
,
2660 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2665 "Duration in seconds\n")
2667 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2671 DEFPY (evpn_mh_neigh_holdtime
,
2672 evpn_mh_neigh_holdtime_cmd
,
2673 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2677 "Neighbor entry hold time\n"
2678 "Duration in seconds\n")
2681 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2685 DEFPY (evpn_mh_startup_delay
,
2686 evpn_mh_startup_delay_cmd
,
2687 "[no] evpn mh startup-delay(0-3600)$duration",
2692 "duration in seconds\n")
2695 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2699 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2700 "[no$no] evpn mh redirect-off",
2704 "ES bond redirect for fast-failover off\n")
2708 redirect_off
= no
? false : true;
2710 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2713 DEFUN (default_vrf_vni_mapping
,
2714 default_vrf_vni_mapping_cmd
,
2715 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2716 "VNI corresponding to the DEFAULT VRF\n"
2718 "Prefix routes only \n")
2720 char xpath
[XPATH_MAXLEN
];
2721 struct zebra_vrf
*zvrf
= NULL
;
2724 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2731 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2733 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2735 snprintf(xpath
, sizeof(xpath
),
2736 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2738 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2741 snprintf(xpath
, sizeof(xpath
),
2742 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2744 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2747 return nb_cli_apply_changes(vty
, NULL
);
2750 DEFUN (no_default_vrf_vni_mapping
,
2751 no_default_vrf_vni_mapping_cmd
,
2752 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2754 "VNI corresponding to DEFAULT VRF\n"
2756 "Prefix routes only \n")
2758 char xpath
[XPATH_MAXLEN
];
2760 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2761 struct zebra_vrf
*zvrf
= NULL
;
2763 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2770 if (zvrf
->l3vni
!= vni
) {
2771 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2776 snprintf(xpath
, sizeof(xpath
),
2777 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2779 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2782 snprintf(xpath
, sizeof(xpath
),
2783 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2785 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2788 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2790 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2792 return nb_cli_apply_changes(vty
, NULL
);
2795 DEFUN (vrf_vni_mapping
,
2796 vrf_vni_mapping_cmd
,
2797 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2798 "VNI corresponding to tenant VRF\n"
2800 "prefix-routes-only\n")
2804 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2812 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2813 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2817 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2818 NB_OP_MODIFY
, "true");
2820 return nb_cli_apply_changes(vty
, NULL
);
2823 DEFUN (no_vrf_vni_mapping
,
2824 no_vrf_vni_mapping_cmd
,
2825 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2827 "VNI corresponding to tenant VRF\n"
2829 "prefix-routes-only\n")
2833 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2834 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2842 if (zvrf
->l3vni
!= vni
) {
2843 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2848 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2852 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2853 NB_OP_DESTROY
, "true");
2855 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2857 return nb_cli_apply_changes(vty
, NULL
);
2861 DEFPY (show_vrf_vni
,
2863 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2865 VRF_FULL_CMD_HELP_STR
2870 struct zebra_vrf
*zvrf
;
2871 json_object
*json
= NULL
;
2872 json_object
*json_vrfs
= NULL
;
2873 bool uj
= use_json(argc
, argv
);
2874 bool use_vrf
= false;
2877 json
= json_object_new_object();
2879 /* show vrf vni used to display across all vrfs
2880 * This is enhanced to support only for specific
2883 if (vrf_all
|| !vrf_name
) {
2884 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2895 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2896 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2899 json_vrfs
= json_object_new_array();
2902 vty_json(vty
, json
);
2904 vty_out(vty
, "%% VRF does not exist\n");
2911 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2916 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2918 } else if (vrf_name
) {
2919 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2922 vty_json(vty
, json
);
2925 "%% VRF '%s' specified does not exist\n",
2932 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2933 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2936 json_vrfs
= json_object_new_array();
2938 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2942 json_object_object_add(json
, "vrfs", json_vrfs
);
2943 vty_json(vty
, json
);
2949 DEFUN (show_evpn_global
,
2950 show_evpn_global_cmd
,
2956 bool uj
= use_json(argc
, argv
);
2958 zebra_vxlan_print_evpn(vty
, uj
);
2962 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2963 SHOW_STR IP_STR
"neighbors\n")
2966 zebra_neigh_show(vty
);
2971 DEFPY(show_evpn_l2_nh
,
2972 show_evpn_l2_nh_cmd
,
2973 "show evpn l2-nh [json$json]",
2981 zebra_evpn_l2_nh_show(vty
, uj
);
2988 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2991 "Ethernet Segment\n"
2993 "Detailed information\n"
3000 if (!str_to_esi(esi_str
, &esi
)) {
3001 vty_out(vty
, "%% Malformed ESI\n");
3004 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3007 zebra_evpn_es_show_detail(vty
, uj
);
3009 zebra_evpn_es_show(vty
, uj
);
3015 DEFPY(show_evpn_es_evi
,
3016 show_evpn_es_evi_cmd
,
3017 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3020 "Ethernet Segment per EVI\n"
3021 "VxLAN Network Identifier\n"
3023 "Detailed information\n"
3030 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3032 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3037 DEFPY(show_evpn_access_vlan
, show_evpn_access_vlan_cmd
,
3038 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3044 "Detailed information\n" JSON_STR
)
3048 if (if_name
&& vid
) {
3051 struct interface
*ifp
;
3053 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3055 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
3057 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
,
3065 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
3070 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3072 zebra_evpn_acc_vl_show(vty
, uj
);
3078 DEFUN (show_evpn_vni
,
3080 "show evpn vni [json]",
3083 "VxLAN Network Identifier\n"
3086 struct zebra_vrf
*zvrf
;
3087 bool uj
= use_json(argc
, argv
);
3089 zvrf
= zebra_vrf_get_evpn();
3090 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3094 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3095 "show evpn vni detail [json]",
3098 "VxLAN Network Identifier\n"
3099 "Detailed Information On Each VNI\n"
3102 struct zebra_vrf
*zvrf
;
3103 bool uj
= use_json(argc
, argv
);
3105 zvrf
= zebra_vrf_get_evpn();
3106 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3110 DEFUN (show_evpn_vni_vni
,
3111 show_evpn_vni_vni_cmd
,
3112 "show evpn vni " CMD_VNI_RANGE
"[json]",
3115 "VxLAN Network Identifier\n"
3119 struct zebra_vrf
*zvrf
;
3121 bool uj
= use_json(argc
, argv
);
3123 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3124 zvrf
= zebra_vrf_get_evpn();
3125 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3129 DEFUN (show_evpn_rmac_vni_mac
,
3130 show_evpn_rmac_vni_mac_cmd
,
3131 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3138 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3143 bool uj
= use_json(argc
, argv
);
3145 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3146 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3147 vty_out(vty
, "%% Malformed MAC address\n");
3150 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3154 DEFUN (show_evpn_rmac_vni
,
3155 show_evpn_rmac_vni_cmd
,
3156 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3165 bool uj
= use_json(argc
, argv
);
3167 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3168 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3173 DEFUN (show_evpn_rmac_vni_all
,
3174 show_evpn_rmac_vni_all_cmd
,
3175 "show evpn rmac vni all [json]",
3183 bool uj
= use_json(argc
, argv
);
3185 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3190 DEFUN (show_evpn_nh_vni_ip
,
3191 show_evpn_nh_vni_ip_cmd
,
3192 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3199 "Host address (ipv4 or ipv6)\n"
3204 bool uj
= use_json(argc
, argv
);
3206 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3207 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3209 vty_out(vty
, "%% Malformed Neighbor address\n");
3212 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3217 DEFUN_HIDDEN (show_evpn_nh_svd_ip
,
3218 show_evpn_nh_svd_ip_cmd
,
3219 "show evpn next-hops svd ip WORD [json]",
3223 "Single Vxlan Device\n"
3225 "Host address (ipv4 or ipv6)\n"
3229 bool uj
= use_json(argc
, argv
);
3231 if (str2ipaddr(argv
[5]->arg
, &ip
) != 0) {
3233 vty_out(vty
, "%% Malformed Neighbor address\n");
3236 zebra_vxlan_print_specific_nh_l3vni(vty
, 0, &ip
, uj
);
3241 DEFUN (show_evpn_nh_vni
,
3242 show_evpn_nh_vni_cmd
,
3243 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3252 bool uj
= use_json(argc
, argv
);
3254 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3255 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3260 DEFUN_HIDDEN (show_evpn_nh_svd
,
3261 show_evpn_nh_svd_cmd
,
3262 "show evpn next-hops svd [json]",
3266 "Single Vxlan Device\n"
3269 bool uj
= use_json(argc
, argv
);
3271 zebra_vxlan_print_nh_svd(vty
, uj
);
3276 DEFUN (show_evpn_nh_vni_all
,
3277 show_evpn_nh_vni_all_cmd
,
3278 "show evpn next-hops vni all [json]",
3286 bool uj
= use_json(argc
, argv
);
3288 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3293 DEFUN (show_evpn_mac_vni
,
3294 show_evpn_mac_vni_cmd
,
3295 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3299 "VxLAN Network Identifier\n"
3303 struct zebra_vrf
*zvrf
;
3305 bool uj
= use_json(argc
, argv
);
3307 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3308 zvrf
= zebra_vrf_get_evpn();
3309 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3313 DEFPY (show_evpn_mac_vni_detail
,
3314 show_evpn_mac_vni_detail_cmd
,
3315 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3319 "VXLAN Network Identifier\n"
3321 "Detailed Information On Each VNI MAC\n"
3324 struct zebra_vrf
*zvrf
;
3325 bool uj
= use_json(argc
, argv
);
3327 zvrf
= zebra_vrf_get_evpn();
3328 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3332 DEFUN (show_evpn_mac_vni_all
,
3333 show_evpn_mac_vni_all_cmd
,
3334 "show evpn mac vni all [json]",
3338 "VxLAN Network Identifier\n"
3342 struct zebra_vrf
*zvrf
;
3343 bool uj
= use_json(argc
, argv
);
3345 zvrf
= zebra_vrf_get_evpn();
3346 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3350 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3351 "show evpn mac vni all detail [json]",
3355 "VxLAN Network Identifier\n"
3357 "Detailed Information On Each VNI MAC\n"
3360 struct zebra_vrf
*zvrf
;
3361 bool uj
= use_json(argc
, argv
);
3363 zvrf
= zebra_vrf_get_evpn();
3364 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3368 DEFUN (show_evpn_mac_vni_all_vtep
,
3369 show_evpn_mac_vni_all_vtep_cmd
,
3370 "show evpn mac vni all vtep A.B.C.D [json]",
3374 "VxLAN Network Identifier\n"
3377 "Remote VTEP IP address\n"
3380 struct zebra_vrf
*zvrf
;
3381 struct in_addr vtep_ip
;
3382 bool uj
= use_json(argc
, argv
);
3384 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3386 vty_out(vty
, "%% Malformed VTEP IP address\n");
3389 zvrf
= zebra_vrf_get_evpn();
3390 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3396 DEFUN (show_evpn_mac_vni_mac
,
3397 show_evpn_mac_vni_mac_cmd
,
3398 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3402 "VxLAN Network Identifier\n"
3405 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3409 struct zebra_vrf
*zvrf
;
3412 bool uj
= use_json(argc
, argv
);
3414 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3415 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3416 vty_out(vty
, "%% Malformed MAC address\n");
3419 zvrf
= zebra_vrf_get_evpn();
3420 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3424 DEFUN (show_evpn_mac_vni_vtep
,
3425 show_evpn_mac_vni_vtep_cmd
,
3426 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3430 "VxLAN Network Identifier\n"
3433 "Remote VTEP IP address\n"
3436 struct zebra_vrf
*zvrf
;
3438 struct in_addr vtep_ip
;
3439 bool uj
= use_json(argc
, argv
);
3441 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3442 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3444 vty_out(vty
, "%% Malformed VTEP IP address\n");
3448 zvrf
= zebra_vrf_get_evpn();
3449 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3453 DEFPY (show_evpn_mac_vni_all_dad
,
3454 show_evpn_mac_vni_all_dad_cmd
,
3455 "show evpn mac vni all duplicate [json]",
3459 "VxLAN Network Identifier\n"
3461 "Duplicate address list\n"
3464 struct zebra_vrf
*zvrf
;
3465 bool uj
= use_json(argc
, argv
);
3467 zvrf
= zebra_vrf_get_evpn();
3468 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3473 DEFPY (show_evpn_mac_vni_dad
,
3474 show_evpn_mac_vni_dad_cmd
,
3475 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3479 "VxLAN Network Identifier\n"
3481 "Duplicate address list\n"
3484 struct zebra_vrf
*zvrf
;
3485 bool uj
= use_json(argc
, argv
);
3487 zvrf
= zebra_vrf_get_evpn();
3489 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3494 DEFPY (show_evpn_neigh_vni_dad
,
3495 show_evpn_neigh_vni_dad_cmd
,
3496 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3499 "ARP and ND cache\n"
3500 "VxLAN Network Identifier\n"
3502 "Duplicate address list\n"
3505 struct zebra_vrf
*zvrf
;
3506 bool uj
= use_json(argc
, argv
);
3508 zvrf
= zebra_vrf_get_evpn();
3509 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3513 DEFPY (show_evpn_neigh_vni_all_dad
,
3514 show_evpn_neigh_vni_all_dad_cmd
,
3515 "show evpn arp-cache vni all duplicate [json]",
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3521 "Duplicate address list\n"
3524 struct zebra_vrf
*zvrf
;
3525 bool uj
= use_json(argc
, argv
);
3527 zvrf
= zebra_vrf_get_evpn();
3528 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3533 DEFUN (show_evpn_neigh_vni
,
3534 show_evpn_neigh_vni_cmd
,
3535 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3538 "ARP and ND cache\n"
3539 "VxLAN Network Identifier\n"
3543 struct zebra_vrf
*zvrf
;
3545 bool uj
= use_json(argc
, argv
);
3547 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3548 zvrf
= zebra_vrf_get_evpn();
3549 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3553 DEFUN (show_evpn_neigh_vni_all
,
3554 show_evpn_neigh_vni_all_cmd
,
3555 "show evpn arp-cache vni all [json]",
3558 "ARP and ND cache\n"
3559 "VxLAN Network Identifier\n"
3563 struct zebra_vrf
*zvrf
;
3564 bool uj
= use_json(argc
, argv
);
3566 zvrf
= zebra_vrf_get_evpn();
3567 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3571 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3572 "show evpn arp-cache vni all detail [json]",
3575 "ARP and ND cache\n"
3576 "VxLAN Network Identifier\n"
3578 "Neighbor details for all vnis in detail\n" JSON_STR
)
3580 struct zebra_vrf
*zvrf
;
3581 bool uj
= use_json(argc
, argv
);
3583 zvrf
= zebra_vrf_get_evpn();
3584 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3588 DEFUN (show_evpn_neigh_vni_neigh
,
3589 show_evpn_neigh_vni_neigh_cmd
,
3590 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3593 "ARP and ND cache\n"
3594 "VxLAN Network Identifier\n"
3597 "Neighbor address (IPv4 or IPv6 address)\n"
3600 struct zebra_vrf
*zvrf
;
3603 bool uj
= use_json(argc
, argv
);
3605 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3606 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3608 vty_out(vty
, "%% Malformed Neighbor address\n");
3611 zvrf
= zebra_vrf_get_evpn();
3612 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3616 DEFUN (show_evpn_neigh_vni_vtep
,
3617 show_evpn_neigh_vni_vtep_cmd
,
3618 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3621 "ARP and ND cache\n"
3622 "VxLAN Network Identifier\n"
3625 "Remote VTEP IP address\n"
3628 struct zebra_vrf
*zvrf
;
3630 struct in_addr vtep_ip
;
3631 bool uj
= use_json(argc
, argv
);
3633 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3634 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3636 vty_out(vty
, "%% Malformed VTEP IP address\n");
3640 zvrf
= zebra_vrf_get_evpn();
3641 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3645 /* policy routing contexts */
3646 DEFUN (show_pbr_ipset
,
3648 "show pbr ipset [WORD]",
3650 "Policy-Based Routing\n"
3651 "IPset Context information\n"
3652 "IPset Name information\n")
3656 found
= argv_find(argv
, argc
, "WORD", &idx
);
3658 zebra_pbr_show_ipset_list(vty
, NULL
);
3660 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3664 /* policy routing contexts */
3665 DEFUN (show_pbr_iptable
,
3666 show_pbr_iptable_cmd
,
3667 "show pbr iptable [WORD]",
3669 "Policy-Based Routing\n"
3670 "IPtable Context information\n"
3671 "IPtable Name information\n")
3676 found
= argv_find(argv
, argc
, "WORD", &idx
);
3678 zebra_pbr_show_iptable(vty
, NULL
);
3680 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3684 /* policy routing contexts */
3685 DEFPY (show_pbr_rule
,
3689 "Policy-Based Routing\n"
3692 zebra_pbr_show_rule(vty
);
3696 DEFPY (pbr_nexthop_resolve
,
3697 pbr_nexthop_resolve_cmd
,
3698 "[no$no] pbr nexthop-resolve",
3700 "Policy Based Routing\n"
3701 "Resolve nexthop for dataplane programming\n")
3703 zebra_pbr_expand_action_update(!no
);
3707 DEFPY (clear_evpn_dup_addr
,
3708 clear_evpn_dup_addr_cmd
,
3709 "clear evpn dup-addr vni <all$vni_all |" CMD_VNI_RANGE
"$vni [mac X:X:X:X:X:X | ip <A.B.C.D|X:X::X:X>]>",
3712 "Duplicate address \n"
3713 "VxLAN Network Identifier\n"
3717 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3722 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3723 int ret
= CMD_SUCCESS
;
3725 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3726 *yang_dup_mac
= NULL
;
3731 yang_dup
= yang_data_new(
3732 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3735 yang_dup
= yang_data_new_uint32(
3736 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3738 if (!is_zero_mac(&mac
->eth_addr
)) {
3739 yang_dup_mac
= yang_data_new_mac(
3740 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3743 listnode_add(input
, yang_dup_mac
);
3745 if (sockunion_family(ip
) == AF_INET
) {
3746 host_ip
.ipa_type
= IPADDR_V4
;
3747 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3749 host_ip
.ipa_type
= IPADDR_V6
;
3750 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3751 sizeof(struct in6_addr
));
3754 yang_dup_ip
= yang_data_new_ip(
3755 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3759 listnode_add(input
, yang_dup_ip
);
3764 listnode_add(input
, yang_dup
);
3765 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3769 list_delete(&input
);
3774 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3775 evpn_accept_bgp_seq_cmd
,
3776 "evpn accept-bgp-seq",
3778 "Accept all sequence numbers from BGP\n")
3780 zebra_vxlan_set_accept_bgp_seq(true);
3784 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3785 no_evpn_accept_bgp_seq_cmd
,
3786 "no evpn accept-bgp-seq",
3789 "Accept all sequence numbers from BGP\n")
3791 zebra_vxlan_set_accept_bgp_seq(false);
3795 /* Static ip route configuration write function. */
3796 static int zebra_ip_config(struct vty
*vty
)
3800 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3805 DEFUN (ip_zebra_import_table_distance
,
3806 ip_zebra_import_table_distance_cmd
,
3807 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3809 "import routes from non-main kernel table\n"
3810 "kernel routing table id\n"
3811 "Distance for imported routes\n"
3812 "Default distance value\n"
3813 "route-map for filtering\n"
3816 uint32_t table_id
= 0;
3818 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3819 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3821 strmatch(argv
[argc
- 2]->text
, "route-map")
3822 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3826 if (argc
== 7 || (argc
== 5 && !rmap
))
3827 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3829 if (!is_zebra_valid_kernel_table(table_id
)) {
3831 "Invalid routing table ID, %d. Must be in range 1-252\n",
3834 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3838 if (is_zebra_main_routing_table(table_id
)) {
3840 "Invalid routing table ID, %d. Must be non-default table\n",
3843 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3847 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3850 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3855 DEFUN_HIDDEN (zebra_packet_process
,
3856 zebra_packet_process_cmd
,
3857 "zebra zapi-packets (1-10000)",
3860 "Number of packets to process before relinquishing thread\n")
3862 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3864 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3865 memory_order_relaxed
);
3870 DEFUN_HIDDEN (no_zebra_packet_process
,
3871 no_zebra_packet_process_cmd
,
3872 "no zebra zapi-packets [(1-10000)]",
3876 "Number of packets to process before relinquishing thread\n")
3878 atomic_store_explicit(&zrouter
.packets_to_process
,
3879 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3880 memory_order_relaxed
);
3885 DEFUN_HIDDEN (zebra_workqueue_timer
,
3886 zebra_workqueue_timer_cmd
,
3887 "zebra work-queue (0-10000)",
3890 "Time in milliseconds\n")
3892 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3893 zrouter
.ribq
->spec
.hold
= timer
;
3898 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3899 no_zebra_workqueue_timer_cmd
,
3900 "no zebra work-queue [(0-10000)]",
3904 "Time in milliseconds\n")
3906 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3911 DEFUN (no_ip_zebra_import_table
,
3912 no_ip_zebra_import_table_cmd
,
3913 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3916 "import routes from non-main kernel table\n"
3917 "kernel routing table id\n"
3918 "Distance for imported routes\n"
3919 "Default distance value\n"
3920 "route-map for filtering\n"
3923 uint32_t table_id
= 0;
3924 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3926 if (!is_zebra_valid_kernel_table(table_id
)) {
3928 "Invalid routing table ID. Must be in range 1-252\n");
3932 if (is_zebra_main_routing_table(table_id
)) {
3934 "Invalid routing table ID, %d. Must be non-default table\n",
3939 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3942 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3945 DEFPY (zebra_nexthop_group_keep
,
3946 zebra_nexthop_group_keep_cmd
,
3947 "[no] zebra nexthop-group keep (1-3600)",
3951 "How long to keep\n"
3952 "Time in seconds from 1-3600\n")
3955 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3957 zrouter
.nhg_keep
= keep
;
3962 static int config_write_protocol(struct vty
*vty
)
3964 if (zrouter
.allow_delete
)
3965 vty_out(vty
, "allow-external-route-update\n");
3967 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3968 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3970 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3971 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3973 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3974 vty_out(vty
, "zebra zapi-packets %u\n",
3975 zrouter
.packets_to_process
);
3977 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3979 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3980 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3981 ipv4_multicast_mode
== MCAST_URIB_ONLY
3983 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3985 : ipv4_multicast_mode
3986 == MCAST_MIX_MRIB_FIRST
3988 : ipv4_multicast_mode
3989 == MCAST_MIX_DISTANCE
3993 /* Include dataplane info */
3994 dplane_config_write_helper(vty
);
3996 zebra_evpn_mh_config_write(vty
);
3998 zebra_pbr_config_write(vty
);
4000 if (!zebra_vxlan_get_accept_bgp_seq())
4001 vty_out(vty
, "no evpn accept-bgp-seq\n");
4003 /* Include nexthop-group config */
4004 if (!zebra_nhg_kernel_nexthops_enabled())
4005 vty_out(vty
, "no zebra nexthop kernel enable\n");
4007 if (zebra_nhg_proto_nexthops_only())
4008 vty_out(vty
, "zebra nexthop proto only\n");
4010 if (!zebra_nhg_recursive_use_backups())
4011 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
4013 if (rnh_get_hide_backups())
4014 vty_out(vty
, "ip nht hide-backup-events\n");
4017 /* Include netlink info */
4018 netlink_config_write_helper(vty
);
4019 #endif /* HAVE_NETLINK */
4031 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4034 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4035 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4036 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4037 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4038 ttable_add_row(table
, "v6 Forwarding|%s",
4039 ipforward_ipv6() ? "On" : "Off");
4040 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4041 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4042 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4046 if (!vrf_is_backend_netns())
4047 ttable_add_row(table
, "VRF|l3mdev Available");
4049 ttable_add_row(table
, "VRF|Namespaces");
4051 ttable_add_row(table
, "VRF|Not Available");
4054 ttable_add_row(table
, "ASIC offload|%s",
4055 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4058 * Do not display this unless someone is actually using it
4060 * Why this distinction? I think this is effectively dead code
4061 * and should not be exposed. Maybe someone proves me wrong.
4063 if (zrouter
.asic_notification_nexthop_control
)
4064 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4066 ttable_add_row(table
, "RA|%s",
4067 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4068 ttable_add_row(table
, "RFC 5549|%s",
4069 rtadv_get_interfaces_configured_from_bgp()
4071 : "BGP is not using");
4073 ttable_add_row(table
, "Kernel NHG|%s",
4074 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4076 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4077 zrouter
.allow_delete
? "Yes" : "No");
4078 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4079 zrouter
.all_linkdownv4
? "On" : "Off");
4080 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4081 zrouter
.default_linkdownv4
? "On" : "Off");
4082 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4083 zrouter
.all_linkdownv6
? "On" : "Off");
4084 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4085 zrouter
.default_linkdownv6
? "On" : "Off");
4087 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4088 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4089 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4090 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4091 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4092 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4093 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4094 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4096 out
= ttable_dump(table
, "\n");
4097 vty_out(vty
, "%s\n", out
);
4098 XFREE(MTYPE_TMP
, out
);
4102 " Route Route Neighbor LSP LSP\n");
4104 "VRF Installs Removals Updates Installs Removals\n");
4106 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4107 struct zebra_vrf
*zvrf
= vrf
->info
;
4109 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4110 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4111 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4112 zvrf
->lsp_removals
);
4118 DEFUN (ip_forwarding
,
4122 "Turn on IP forwarding\n")
4128 ret
= ipforward_on();
4131 vty_out(vty
, "Can't turn on IP forwarding\n");
4132 return CMD_WARNING_CONFIG_FAILED
;
4138 DEFUN (no_ip_forwarding
,
4139 no_ip_forwarding_cmd
,
4143 "Turn off IP forwarding\n")
4149 ret
= ipforward_off();
4152 vty_out(vty
, "Can't turn off IP forwarding\n");
4153 return CMD_WARNING_CONFIG_FAILED
;
4159 /* Only display ip forwarding is enabled or not. */
4160 DEFUN (show_ip_forwarding
,
4161 show_ip_forwarding_cmd
,
4162 "show ip forwarding",
4165 "IP forwarding status\n")
4172 vty_out(vty
, "IP forwarding is off\n");
4174 vty_out(vty
, "IP forwarding is on\n");
4178 /* Only display ipv6 forwarding is enabled or not. */
4179 DEFUN (show_ipv6_forwarding
,
4180 show_ipv6_forwarding_cmd
,
4181 "show ipv6 forwarding",
4183 "IPv6 information\n"
4184 "Forwarding status\n")
4188 ret
= ipforward_ipv6();
4192 vty_out(vty
, "ipv6 forwarding is unknown\n");
4195 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4198 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4201 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4207 DEFUN (ipv6_forwarding
,
4208 ipv6_forwarding_cmd
,
4211 "Turn on IPv6 forwarding\n")
4215 ret
= ipforward_ipv6();
4217 ret
= ipforward_ipv6_on();
4220 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4221 return CMD_WARNING_CONFIG_FAILED
;
4227 DEFUN (no_ipv6_forwarding
,
4228 no_ipv6_forwarding_cmd
,
4229 "no ipv6 forwarding",
4232 "Turn off IPv6 forwarding\n")
4236 ret
= ipforward_ipv6();
4238 ret
= ipforward_ipv6_off();
4241 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4242 return CMD_WARNING_CONFIG_FAILED
;
4248 /* Display dataplane info */
4249 DEFUN (show_dataplane
,
4251 "show zebra dplane [detailed]",
4254 "Zebra dataplane information\n"
4255 "Detailed output\n")
4258 bool detailed
= false;
4260 if (argv_find(argv
, argc
, "detailed", &idx
))
4263 return dplane_show_helper(vty
, detailed
);
4266 /* Display dataplane providers info */
4267 DEFUN (show_dataplane_providers
,
4268 show_dataplane_providers_cmd
,
4269 "show zebra dplane providers [detailed]",
4272 "Zebra dataplane information\n"
4273 "Zebra dataplane provider information\n"
4274 "Detailed output\n")
4277 bool detailed
= false;
4279 if (argv_find(argv
, argc
, "detailed", &idx
))
4282 return dplane_show_provs_helper(vty
, detailed
);
4285 /* Configure dataplane incoming queue limit */
4286 DEFUN (zebra_dplane_queue_limit
,
4287 zebra_dplane_queue_limit_cmd
,
4288 "zebra dplane limit (0-10000)",
4291 "Limit incoming queued updates\n"
4292 "Number of queued updates\n")
4296 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4298 dplane_set_in_queue_limit(limit
, true);
4303 /* Reset dataplane queue limit to default value */
4304 DEFUN (no_zebra_dplane_queue_limit
,
4305 no_zebra_dplane_queue_limit_cmd
,
4306 "no zebra dplane limit [(0-10000)]",
4310 "Limit incoming queued updates\n"
4311 "Number of queued updates\n")
4313 dplane_set_in_queue_limit(0, false);
4318 DEFUN (zebra_show_routing_tables_summary
,
4319 zebra_show_routing_tables_summary_cmd
,
4320 "show zebra router table summary",
4323 "The Zebra Router Information\n"
4324 "Table Information about this Zebra Router\n"
4325 "Summary Information\n")
4327 zebra_router_show_table_summary(vty
);
4332 /* Table configuration write function. */
4333 static int config_write_table(struct vty
*vty
)
4338 /* IPForwarding configuration write function. */
4339 static int config_write_forwarding(struct vty
*vty
)
4342 vty_out(vty
, "no ip forwarding\n");
4343 if (!ipforward_ipv6())
4344 vty_out(vty
, "no ipv6 forwarding\n");
4345 vty_out(vty
, "!\n");
4349 DEFUN_HIDDEN (show_frr
,
4355 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4356 vty_out(vty
, ".............................7777:..............................................\n");
4357 vty_out(vty
, ".............................777777,............................................\n");
4358 vty_out(vty
, "... .........................77777777,..........................................\n");
4359 vty_out(vty
, "............................=7777777777:........................................\n");
4360 vty_out(vty
, "........................:7777777777777777,......................................\n");
4361 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4362 vty_out(vty
, "...................I7777777777+.................................................\n");
4363 vty_out(vty
, "................,777777777?............ .......................................\n");
4364 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4365 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4366 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4367 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4368 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4369 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4370 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4371 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4372 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4373 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4374 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4375 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4376 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4377 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4378 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4379 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4380 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4381 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4382 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4383 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4384 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4385 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4386 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4387 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4388 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4389 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4390 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4391 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4392 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4393 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4394 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4395 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4396 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4397 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4398 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4399 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4400 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4401 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4402 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4403 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4404 vty_out(vty
, "................................~77777777...............=777777.................\n");
4405 vty_out(vty
, ".....................................:=?I................~777777................\n");
4406 vty_out(vty
, "..........................................................:777777,..............\n");
4407 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4413 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4414 zebra_kernel_netlink_batch_tx_buf_cmd
,
4415 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4417 "Zebra kernel interface\n"
4418 "Set Netlink parameters\n"
4419 "Set batch buffer size and send threshold\n"
4420 "Size of the buffer\n"
4423 uint32_t bufsize
= 0, threshold
= 0;
4425 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4426 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4428 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4433 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4434 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4435 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4437 "Zebra kernel interface\n"
4438 "Set Netlink parameters\n"
4439 "Set batch buffer size and send threshold\n"
4440 "Size of the buffer\n"
4443 netlink_set_batch_buffer_size(0, 0, false);
4448 DEFPY (zebra_protodown_bit
,
4449 zebra_protodown_bit_cmd
,
4450 "zebra protodown reason-bit (0-31)$bit",
4452 "Protodown Configuration\n"
4453 "Reason Bit used in the kernel for application\n"
4454 "Reason Bit range\n")
4456 if_netlink_set_frr_protodown_r_bit(bit
);
4460 DEFPY (no_zebra_protodown_bit
,
4461 no_zebra_protodown_bit_cmd
,
4462 "no zebra protodown reason-bit [(0-31)$bit]",
4465 "Protodown Configuration\n"
4466 "Reason Bit used in the kernel for setting protodown\n"
4467 "Reason Bit Range\n")
4469 if_netlink_unset_frr_protodown_r_bit();
4473 #endif /* HAVE_NETLINK */
4475 DEFUN(ip_table_range
, ip_table_range_cmd
,
4476 "[no] ip table range (1-4294967295) (1-4294967295)",
4478 "table configuration\n"
4479 "Configure table range\n"
4480 "Start Routing Table\n"
4481 "End Routing Table\n")
4483 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4488 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4490 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4494 if (strmatch(argv
[0]->text
, "no"))
4495 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4497 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4500 #ifdef HAVE_SCRIPTING
4502 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4503 "zebra on-rib-process script SCRIPT",
4505 "on_rib_process_dplane_results hook call\n"
4507 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4510 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4513 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4514 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4516 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4517 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4522 #endif /* HAVE_SCRIPTING */
4524 /* IP node for static routes. */
4525 static int zebra_ip_config(struct vty
*vty
);
4526 static struct cmd_node ip_node
= {
4527 .name
= "static ip",
4530 .config_write
= zebra_ip_config
,
4532 static int config_write_protocol(struct vty
*vty
);
4533 static struct cmd_node protocol_node
= {
4535 .node
= PROTOCOL_NODE
,
4537 .config_write
= config_write_protocol
,
4539 /* table node for routing tables. */
4540 static int config_write_table(struct vty
*vty
);
4541 static struct cmd_node table_node
= {
4545 .config_write
= config_write_table
,
4547 static int config_write_forwarding(struct vty
*vty
);
4548 static struct cmd_node forwarding_node
= {
4549 .name
= "forwarding",
4550 .node
= FORWARDING_NODE
,
4552 .config_write
= config_write_forwarding
,
4556 void zebra_vty_init(void)
4558 /* Install configuration write function. */
4559 install_node(&table_node
);
4560 install_node(&forwarding_node
);
4562 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4563 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4564 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4565 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4567 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4568 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4569 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4572 zebra_route_map_init();
4574 zebra_affinity_map_init();
4576 install_node(&ip_node
);
4577 install_node(&protocol_node
);
4579 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4580 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4582 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4583 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4585 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4586 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4587 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4588 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4589 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4590 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4591 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4592 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4593 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4594 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4596 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4597 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4599 install_element(VIEW_NODE
, &show_vrf_cmd
);
4600 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4601 install_element(VIEW_NODE
, &show_route_cmd
);
4602 install_element(VIEW_NODE
, &show_ro_cmd
);
4603 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4604 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4605 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4607 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4608 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4609 install_element(VIEW_NODE
, &show_ipv6_rpf_addr_cmd
);
4611 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4612 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4613 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4614 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4615 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4616 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4617 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4618 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4619 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4621 install_element(VIEW_NODE
, &show_frr_cmd
);
4622 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4623 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4624 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4625 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4626 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4627 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4628 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4629 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4630 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4631 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4632 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4633 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4634 install_element(VIEW_NODE
, &show_evpn_nh_svd_ip_cmd
);
4635 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4636 install_element(VIEW_NODE
, &show_evpn_nh_svd_cmd
);
4637 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4638 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4639 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4640 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4641 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4642 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4643 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4644 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4645 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4646 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4647 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4648 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4649 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4650 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4651 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4652 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4653 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4654 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4655 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4656 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4658 install_element(VIEW_NODE
, &show_neigh_cmd
);
4660 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4661 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4662 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4663 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4664 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4666 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4667 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4668 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4669 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4670 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4671 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4672 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4673 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4675 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4676 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4677 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4678 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4680 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4681 install_element(VRF_NODE
, &ip_table_range_cmd
);
4684 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4685 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4686 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4687 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4688 #endif /* HAVE_NETLINK */
4690 #ifdef HAVE_SCRIPTING
4691 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4692 #endif /* HAVE_SCRIPTING */
4694 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);