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"
38 #include "zebra/zebra_router.h"
39 #include "zebra/zserv.h"
40 #include "zebra/zebra_vrf.h"
41 #include "zebra/zebra_mpls.h"
42 #include "zebra/zebra_rnh.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/zebra_routemap.h"
46 #include "lib/route_opaque.h"
47 #include "zebra/zebra_vxlan.h"
48 #include "zebra/zebra_evpn_mh.h"
49 #include "zebra/zebra_vty_clippy.c"
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_pbr.h"
55 #include "zebra/zebra_nhg.h"
56 #include "zebra/zebra_evpn_mh.h"
57 #include "zebra/interface.h"
58 #include "northbound_cli.h"
59 #include "zebra/zebra_nb.h"
60 #include "zebra/kernel_netlink.h"
61 #include "zebra/if_netlink.h"
62 #include "zebra/table_manager.h"
63 #include "zebra/zebra_script.h"
64 #include "zebra/rtadv.h"
65 #include "zebra/zebra_neigh.h"
67 /* context to manage dumps in multiple tables or vrfs */
68 struct route_show_ctx
{
69 bool multi
; /* dump multiple tables or vrf */
70 bool header_done
; /* common header already displayed */
73 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
74 safi_t safi
, bool use_fib
, bool use_json
,
76 const struct prefix
*longer_prefix_p
,
77 bool supernets_only
, int type
,
78 unsigned short ospf_instance_id
, uint32_t tableid
,
79 bool show_ng
, struct route_show_ctx
*ctx
);
80 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
81 int mcast
, bool use_fib
, bool show_ng
);
82 static void vty_show_ip_route_summary(struct vty
*vty
,
83 struct route_table
*table
, bool use_json
);
84 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
85 struct route_table
*table
,
87 /* Helper api to format a nexthop in the 'detailed' output path. */
88 static void show_nexthop_detail_helper(struct vty
*vty
,
89 const struct route_entry
*re
,
90 const struct nexthop
*nexthop
,
93 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
94 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
95 struct route_entry
*re
, unsigned int num
);
97 DEFUN (ip_multicast_mode
,
98 ip_multicast_mode_cmd
,
99 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
101 "Multicast options\n"
102 "RPF lookup behavior\n"
103 "Lookup in unicast RIB only\n"
104 "Lookup in multicast RIB only\n"
105 "Try multicast RIB first, fall back to unicast RIB\n"
106 "Lookup both, use entry with lower distance\n"
107 "Lookup both, use entry with longer prefix\n")
109 char *mode
= argv
[3]->text
;
111 if (strmatch(mode
, "urib-only"))
112 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
113 else if (strmatch(mode
, "mrib-only"))
114 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
115 else if (strmatch(mode
, "mrib-then-urib"))
116 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
117 else if (strmatch(mode
, "lower-distance"))
118 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
119 else if (strmatch(mode
, "longer-prefix"))
120 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
122 vty_out(vty
, "Invalid mode specified\n");
123 return CMD_WARNING_CONFIG_FAILED
;
129 DEFUN (no_ip_multicast_mode
,
130 no_ip_multicast_mode_cmd
,
131 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
134 "Multicast options\n"
135 "RPF lookup behavior\n"
136 "Lookup in unicast RIB only\n"
137 "Lookup in multicast RIB only\n"
138 "Try multicast RIB first, fall back to unicast RIB\n"
139 "Lookup both, use entry with lower distance\n"
140 "Lookup both, use entry with longer prefix\n")
142 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
149 "show ip rpf [json]",
152 "Display RPF information for multicast source\n"
155 bool uj
= use_json(argc
, argv
);
156 struct route_show_ctx ctx
= {
160 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
161 false, uj
, 0, NULL
, false, 0, 0, 0, false,
165 DEFUN (show_ip_rpf_addr
,
166 show_ip_rpf_addr_cmd
,
167 "show ip rpf A.B.C.D",
170 "Display RPF information for multicast source\n"
171 "IP multicast source address (e.g. 10.0.0.0)\n")
175 struct route_node
*rn
;
176 struct route_entry
*re
;
179 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
181 vty_out(vty
, "%% Malformed address\n");
185 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
188 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
190 vty_out(vty
, "%% No match for RPF lookup\n");
195 static char re_status_output_char(const struct route_entry
*re
,
196 const struct nexthop
*nhop
,
199 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
203 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
204 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
205 /* More-specific test for 'fib' output */
207 star_p
= !!CHECK_FLAG(nhop
->flags
,
213 if (zrouter
.asic_offloaded
&&
214 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
217 if (zrouter
.asic_offloaded
218 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
221 if (zrouter
.asic_offloaded
222 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
225 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
234 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
235 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
241 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
248 * Show backup nexthop info, in the 'detailed' output path
250 static void show_nh_backup_helper(struct vty
*vty
,
251 const struct route_entry
*re
,
252 const struct nexthop
*nexthop
)
254 const struct nexthop
*start
, *backup
, *temp
;
257 /* Double-check that there _is_ a backup */
258 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
259 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
260 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
263 /* Locate the backup nexthop(s) */
264 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
265 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
266 /* Format the backup(s) (indented) */
268 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
269 backup
= backup
->next
;
274 /* It's possible for backups to be recursive too,
275 * so walk the recursive resolution list if present.
280 show_nexthop_detail_helper(vty
, re
, backup
,
284 if (backup
->resolved
&& temp
== backup
)
285 backup
= backup
->resolved
;
287 backup
= nexthop_next(backup
);
289 if (backup
== temp
->next
)
297 * Helper api to format output for a nexthop, used in the 'detailed'
300 static void show_nexthop_detail_helper(struct vty
*vty
,
301 const struct route_entry
*re
,
302 const struct nexthop
*nexthop
,
306 char buf
[MPLS_LABEL_STRLEN
];
311 nexthop
->rparent
? " " : "");
313 vty_out(vty
, " %c%s",
314 re_status_output_char(re
, nexthop
, false),
315 nexthop
->rparent
? " " : "");
317 switch (nexthop
->type
) {
318 case NEXTHOP_TYPE_IPV4
:
319 case NEXTHOP_TYPE_IPV4_IFINDEX
:
320 vty_out(vty
, " %pI4",
321 &nexthop
->gate
.ipv4
);
322 if (nexthop
->ifindex
)
323 vty_out(vty
, ", via %s",
328 case NEXTHOP_TYPE_IPV6
:
329 case NEXTHOP_TYPE_IPV6_IFINDEX
:
331 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
333 if (nexthop
->ifindex
)
334 vty_out(vty
, ", via %s",
340 case NEXTHOP_TYPE_IFINDEX
:
341 vty_out(vty
, " directly connected, %s",
342 ifindex2ifname(nexthop
->ifindex
,
345 case NEXTHOP_TYPE_BLACKHOLE
:
346 vty_out(vty
, " unreachable");
347 switch (nexthop
->bh_type
) {
348 case BLACKHOLE_REJECT
:
349 vty_out(vty
, " (ICMP unreachable)");
351 case BLACKHOLE_ADMINPROHIB
:
353 " (ICMP admin-prohibited)");
356 vty_out(vty
, " (blackhole)");
358 case BLACKHOLE_UNSPEC
:
364 if (re
->vrf_id
!= nexthop
->vrf_id
) {
365 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
367 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
370 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
371 vty_out(vty
, " (duplicate nexthop removed)");
373 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
374 vty_out(vty
, " inactive");
376 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
377 vty_out(vty
, " onlink");
379 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
380 vty_out(vty
, " linkdown");
382 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
383 vty_out(vty
, " (recursive)");
385 /* Source specified? */
386 switch (nexthop
->type
) {
387 case NEXTHOP_TYPE_IPV4
:
388 case NEXTHOP_TYPE_IPV4_IFINDEX
:
389 if (nexthop
->src
.ipv4
.s_addr
) {
390 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
391 addrstr
, sizeof(addrstr
)))
392 vty_out(vty
, ", src %s",
397 case NEXTHOP_TYPE_IPV6
:
398 case NEXTHOP_TYPE_IPV6_IFINDEX
:
399 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
401 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
402 addrstr
, sizeof(addrstr
)))
403 vty_out(vty
, ", src %s",
413 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
415 /* Label information */
416 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
417 vty_out(vty
, ", label %s",
418 mpls_label2str(nexthop
->nh_label
->num_labels
,
419 nexthop
->nh_label
->label
, buf
,
420 sizeof(buf
), 1 /*pretty*/));
424 vty_out(vty
, ", weight %u", nexthop
->weight
);
426 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
427 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
429 for (i
= 1; i
< nexthop
->backup_num
; i
++)
430 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
434 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
435 struct json_object
*json
)
437 struct bgp_zebra_opaque bzo
= {};
438 struct ospf_zebra_opaque ozo
= {};
444 case ZEBRA_ROUTE_SHARP
:
446 json_object_string_add(json
, "opaque",
447 (char *)re
->opaque
->data
);
449 vty_out(vty
, " Opaque Data: %s",
450 (char *)re
->opaque
->data
);
453 case ZEBRA_ROUTE_BGP
:
454 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
457 json_object_string_add(json
, "asPath", bzo
.aspath
);
458 json_object_string_add(json
, "communities",
460 json_object_string_add(json
, "largeCommunities",
462 json_object_string_add(json
, "selectionReason",
463 bzo
.selection_reason
);
465 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
467 if (bzo
.community
[0] != '\0')
468 vty_out(vty
, " Communities : %s\n",
471 if (bzo
.lcommunity
[0] != '\0')
472 vty_out(vty
, " Large-Communities: %s\n",
475 vty_out(vty
, " Selection reason : %s\n",
476 bzo
.selection_reason
);
479 case ZEBRA_ROUTE_OSPF
:
480 case ZEBRA_ROUTE_OSPF6
:
481 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
484 json_object_string_add(json
, "ospfPathType",
486 if (ozo
.area_id
[0] != '\0')
487 json_object_string_add(json
, "ospfAreaId",
489 if (ozo
.tag
[0] != '\0')
490 json_object_string_add(json
, "ospfTag",
493 vty_out(vty
, " OSPF path type : %s\n",
495 if (ozo
.area_id
[0] != '\0')
496 vty_out(vty
, " OSPF area ID : %s\n",
498 if (ozo
.tag
[0] != '\0')
499 vty_out(vty
, " OSPF tag : %s\n",
508 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
512 cur
= monotime(NULL
);
515 frrtime_to_interval(cur
, buf
, bufsize
);
518 /* New RIB. Detailed information for IPv4 route. */
519 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
520 int mcast
, bool use_fib
, bool show_ng
)
522 struct route_entry
*re
;
523 struct nexthop
*nexthop
;
524 char buf
[SRCDEST2STR_BUFFER
];
525 struct zebra_vrf
*zvrf
;
528 dest
= rib_dest_from_rnode(rn
);
530 RNODE_FOREACH_RE (rn
, re
) {
532 * If re not selected for forwarding, skip re
533 * for "show ip/ipv6 fib <prefix>"
535 if (use_fib
&& re
!= dest
->selected_fib
)
538 const char *mcast_info
= "";
540 struct rib_table_info
*info
=
541 srcdest_rnode_table_info(rn
);
542 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
543 ? " using Multicast RIB"
544 : " using Unicast RIB";
547 vty_out(vty
, "Routing entry for %s%s\n",
548 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
549 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
551 vty_out(vty
, "[%d]", re
->instance
);
553 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
556 vty_out(vty
, ", tag %u", re
->tag
);
557 #if defined(SUPPORT_REALMS)
558 if (re
->tag
> 0 && re
->tag
<= 255)
559 vty_out(vty
, "(realm)");
563 vty_out(vty
, ", mtu %u", re
->mtu
);
564 if (re
->vrf_id
!= VRF_DEFAULT
) {
565 zvrf
= vrf_info_lookup(re
->vrf_id
);
566 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
568 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
569 vty_out(vty
, ", best");
572 uptime2str(re
->uptime
, buf
, sizeof(buf
));
574 vty_out(vty
, " Last update %s ago\n", buf
);
577 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
578 if (re
->nhe_installed_id
!= 0
579 && re
->nhe_id
!= re
->nhe_installed_id
)
581 " Installed Nexthop Group ID: %u\n",
582 re
->nhe_installed_id
);
585 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
586 /* Use helper to format each nexthop */
587 show_nexthop_detail_helper(vty
, re
, nexthop
,
588 false /*not backup*/);
591 /* Include backup(s), if present */
592 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
593 show_nh_backup_helper(vty
, re
, nexthop
);
595 zebra_show_ip_route_opaque(vty
, re
, NULL
);
602 * Helper for nexthop output, used in the 'show ip route' path
604 static void show_route_nexthop_helper(struct vty
*vty
,
605 const struct route_entry
*re
,
606 const struct nexthop
*nexthop
)
608 char buf
[MPLS_LABEL_STRLEN
];
611 switch (nexthop
->type
) {
612 case NEXTHOP_TYPE_IPV4
:
613 case NEXTHOP_TYPE_IPV4_IFINDEX
:
614 vty_out(vty
, " via %pI4", &nexthop
->gate
.ipv4
);
615 if (nexthop
->ifindex
)
617 ifindex2ifname(nexthop
->ifindex
,
620 case NEXTHOP_TYPE_IPV6
:
621 case NEXTHOP_TYPE_IPV6_IFINDEX
:
622 vty_out(vty
, " via %s",
623 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
625 if (nexthop
->ifindex
)
627 ifindex2ifname(nexthop
->ifindex
,
631 case NEXTHOP_TYPE_IFINDEX
:
632 vty_out(vty
, " is directly connected, %s",
633 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
635 case NEXTHOP_TYPE_BLACKHOLE
:
636 vty_out(vty
, " unreachable");
637 switch (nexthop
->bh_type
) {
638 case BLACKHOLE_REJECT
:
639 vty_out(vty
, " (ICMP unreachable)");
641 case BLACKHOLE_ADMINPROHIB
:
642 vty_out(vty
, " (ICMP admin-prohibited)");
645 vty_out(vty
, " (blackhole)");
647 case BLACKHOLE_UNSPEC
:
653 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
654 vty_out(vty
, " (vrf %s)", vrf_id_to_name(nexthop
->vrf_id
));
656 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
657 vty_out(vty
, " inactive");
659 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
660 vty_out(vty
, " onlink");
662 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
663 vty_out(vty
, " linkdown");
665 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
666 vty_out(vty
, " (recursive)");
668 switch (nexthop
->type
) {
669 case NEXTHOP_TYPE_IPV4
:
670 case NEXTHOP_TYPE_IPV4_IFINDEX
:
671 if (nexthop
->src
.ipv4
.s_addr
) {
672 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
674 vty_out(vty
, ", src %s", buf
);
675 /* SR-TE information */
676 if (nexthop
->srte_color
)
677 vty_out(vty
, ", SR-TE color %u",
678 nexthop
->srte_color
);
681 case NEXTHOP_TYPE_IPV6
:
682 case NEXTHOP_TYPE_IPV6_IFINDEX
:
683 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
684 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
686 vty_out(vty
, ", src %s", buf
);
693 /* Label information */
694 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
695 vty_out(vty
, ", label %s",
696 mpls_label2str(nexthop
->nh_label
->num_labels
,
697 nexthop
->nh_label
->label
, buf
,
701 if (nexthop
->nh_srv6
) {
702 seg6local_context2str(buf
, sizeof(buf
),
703 &nexthop
->nh_srv6
->seg6local_ctx
,
704 nexthop
->nh_srv6
->seg6local_action
);
705 vty_out(vty
, ", seg6local %s %s",
706 seg6local_action2str(
707 nexthop
->nh_srv6
->seg6local_action
),
710 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
712 vty_out(vty
, ", seg6 %s", buf
);
716 vty_out(vty
, ", weight %u", nexthop
->weight
);
718 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
719 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
721 for (i
= 1; i
< nexthop
->backup_num
; i
++)
722 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
728 * Render a nexthop into a json object; the caller allocates and owns
729 * the json object memory.
731 static void show_nexthop_json_helper(json_object
*json_nexthop
,
732 const struct nexthop
*nexthop
,
733 const struct route_entry
*re
)
735 char buf
[SRCDEST2STR_BUFFER
];
736 json_object
*json_labels
= NULL
;
737 json_object
*json_backups
= NULL
;
738 json_object
*json_seg6local
= NULL
;
739 json_object
*json_seg6
= NULL
;
742 json_object_int_add(json_nexthop
, "flags",
745 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
746 json_object_boolean_true_add(json_nexthop
,
749 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
750 json_object_boolean_true_add(json_nexthop
,
753 switch (nexthop
->type
) {
754 case NEXTHOP_TYPE_IPV4
:
755 case NEXTHOP_TYPE_IPV4_IFINDEX
:
756 json_object_string_addf(json_nexthop
, "ip", "%pI4",
757 &nexthop
->gate
.ipv4
);
758 json_object_string_add(json_nexthop
, "afi",
761 if (nexthop
->ifindex
) {
762 json_object_int_add(json_nexthop
,
765 json_object_string_add(
766 json_nexthop
, "interfaceName",
772 case NEXTHOP_TYPE_IPV6
:
773 case NEXTHOP_TYPE_IPV6_IFINDEX
:
774 json_object_string_addf(json_nexthop
, "ip", "%pI6",
775 &nexthop
->gate
.ipv6
);
776 json_object_string_add(json_nexthop
, "afi",
779 if (nexthop
->ifindex
) {
780 json_object_int_add(json_nexthop
,
783 json_object_string_add(
784 json_nexthop
, "interfaceName",
791 case NEXTHOP_TYPE_IFINDEX
:
792 json_object_boolean_true_add(
793 json_nexthop
, "directlyConnected");
794 json_object_int_add(json_nexthop
,
797 json_object_string_add(
798 json_nexthop
, "interfaceName",
799 ifindex2ifname(nexthop
->ifindex
,
802 case NEXTHOP_TYPE_BLACKHOLE
:
803 json_object_boolean_true_add(json_nexthop
,
805 switch (nexthop
->bh_type
) {
806 case BLACKHOLE_REJECT
:
807 json_object_boolean_true_add(
808 json_nexthop
, "reject");
810 case BLACKHOLE_ADMINPROHIB
:
811 json_object_boolean_true_add(json_nexthop
,
815 json_object_boolean_true_add(
816 json_nexthop
, "blackhole");
818 case BLACKHOLE_UNSPEC
:
824 /* This nexthop is a resolver for the parent nexthop.
825 * Set resolver flag for better clarity and delimiter
826 * in flat list of nexthops in json.
828 if (nexthop
->rparent
)
829 json_object_boolean_true_add(json_nexthop
, "resolver");
831 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
832 json_object_string_add(json_nexthop
, "vrf",
833 vrf_id_to_name(nexthop
->vrf_id
));
835 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
836 json_object_boolean_true_add(json_nexthop
,
839 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
840 json_object_boolean_true_add(json_nexthop
,
843 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
844 json_object_boolean_true_add(json_nexthop
, "onLink");
846 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
847 json_object_boolean_true_add(json_nexthop
, "linkDown");
849 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
850 json_object_boolean_true_add(json_nexthop
,
853 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
854 json_backups
= json_object_new_array();
855 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
856 json_object_array_add(
858 json_object_new_int(nexthop
->backup_idx
[i
]));
861 json_object_object_add(json_nexthop
, "backupIndex",
865 switch (nexthop
->type
) {
866 case NEXTHOP_TYPE_IPV4
:
867 case NEXTHOP_TYPE_IPV4_IFINDEX
:
868 if (nexthop
->src
.ipv4
.s_addr
) {
869 if (inet_ntop(AF_INET
,
870 &nexthop
->src
.ipv4
, buf
,
872 json_object_string_add(
873 json_nexthop
, "source",
877 case NEXTHOP_TYPE_IPV6
:
878 case NEXTHOP_TYPE_IPV6_IFINDEX
:
879 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
881 if (inet_ntop(AF_INET6
,
882 &nexthop
->src
.ipv6
, buf
,
884 json_object_string_add(
885 json_nexthop
, "source",
893 if (nexthop
->nh_label
894 && nexthop
->nh_label
->num_labels
) {
895 json_labels
= json_object_new_array();
897 for (int label_index
= 0;
899 < nexthop
->nh_label
->num_labels
;
901 json_object_array_add(
904 nexthop
->nh_label
->label
907 json_object_object_add(json_nexthop
, "labels",
912 json_object_int_add(json_nexthop
, "weight",
915 if (nexthop
->srte_color
)
916 json_object_int_add(json_nexthop
, "srteColor",
917 nexthop
->srte_color
);
919 if (nexthop
->nh_srv6
) {
920 json_seg6local
= json_object_new_object();
921 json_object_string_add(
922 json_seg6local
, "action", seg6local_action2str(
923 nexthop
->nh_srv6
->seg6local_action
));
924 json_object_object_add(json_nexthop
, "seg6local",
927 json_seg6
= json_object_new_object();
928 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
930 json_object_string_add(json_seg6
, "segs", buf
);
931 json_object_object_add(json_nexthop
, "seg6", json_seg6
);
935 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
936 struct route_entry
*re
, json_object
*json
,
937 bool is_fib
, bool show_ng
)
939 const struct nexthop
*nexthop
;
941 char buf
[SRCDEST2STR_BUFFER
];
942 json_object
*json_nexthops
= NULL
;
943 json_object
*json_nexthop
= NULL
;
944 json_object
*json_route
= NULL
;
945 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
946 const struct nexthop_group
*nhg
;
947 char up_str
[MONOTIME_STRLEN
];
949 bool nhg_from_backup
= false;
951 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
953 /* If showing fib information, use the fib view of the
957 nhg
= rib_get_fib_nhg(re
);
959 nhg
= &(re
->nhe
->nhg
);
962 json_route
= json_object_new_object();
963 json_nexthops
= json_object_new_array();
965 json_object_string_add(json_route
, "prefix",
966 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
967 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
968 json_object_string_add(json_route
, "protocol",
969 zebra_route_string(re
->type
));
972 json_object_int_add(json_route
, "instance",
975 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
976 json_object_string_add(json_route
, "vrfName",
977 vrf_id_to_name(re
->vrf_id
));
979 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
980 json_object_boolean_true_add(json_route
, "selected");
982 if (dest
->selected_fib
== re
)
983 json_object_boolean_true_add(json_route
,
986 json_object_int_add(json_route
, "distance",
988 json_object_int_add(json_route
, "metric", re
->metric
);
990 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
991 json_object_boolean_true_add(json_route
, "installed");
993 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
994 json_object_boolean_true_add(json_route
, "failed");
996 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
997 json_object_boolean_true_add(json_route
, "queued");
999 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
1000 json_object_boolean_true_add(json_route
, "trapped");
1002 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
1003 json_object_boolean_true_add(json_route
, "offloaded");
1005 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
1006 json_object_boolean_false_add(json_route
, "offloaded");
1009 json_object_int_add(json_route
, "tag", re
->tag
);
1012 json_object_int_add(json_route
, "table", re
->table
);
1014 json_object_int_add(json_route
, "internalStatus",
1016 json_object_int_add(json_route
, "internalFlags",
1018 json_object_int_add(json_route
, "internalNextHopNum",
1019 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
1020 json_object_int_add(json_route
, "internalNextHopActiveNum",
1021 nexthop_group_active_nexthop_num(
1023 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
1025 if (re
->nhe_installed_id
!= 0)
1026 json_object_int_add(json_route
,
1027 "installedNexthopGroupId",
1028 re
->nhe_installed_id
);
1030 json_object_string_add(json_route
, "uptime", up_str
);
1032 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1033 json_nexthop
= json_object_new_object();
1034 show_nexthop_json_helper(json_nexthop
,
1037 json_object_array_add(json_nexthops
,
1041 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1043 /* If there are backup nexthops, include them */
1045 nhg
= rib_get_fib_backup_nhg(re
);
1047 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1049 if (nhg
&& nhg
->nexthop
) {
1050 json_nexthops
= json_object_new_array();
1052 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1053 json_nexthop
= json_object_new_object();
1055 show_nexthop_json_helper(json_nexthop
,
1057 json_object_array_add(json_nexthops
,
1061 json_object_object_add(json_route
, "backupNexthops",
1064 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
1066 json_object_array_add(json
, json_route
);
1070 /* Prefix information, and first nexthop. If we're showing 'fib',
1071 * and there are no installed primary nexthops, see if there are any
1072 * backup nexthops and start with those.
1074 if (is_fib
&& nhg
->nexthop
== NULL
) {
1075 nhg
= rib_get_fib_backup_nhg(re
);
1076 nhg_from_backup
= true;
1079 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1081 len
+= vty_out(vty
, "[%d]", re
->instance
);
1082 if (nhg_from_backup
&& nhg
->nexthop
) {
1085 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1086 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1087 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1091 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1092 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1093 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1096 /* Distance and metric display. */
1097 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
1098 (re
->distance
|| re
->metric
)) ||
1099 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
1100 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1104 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
1106 /* Nexthop information. */
1107 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1110 } else if (nhg_from_backup
) {
1111 vty_out(vty
, " b%c%*c",
1112 re_status_output_char(re
, nexthop
, is_fib
),
1113 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1115 vty_out(vty
, " %c%*c",
1116 re_status_output_char(re
, nexthop
, is_fib
),
1117 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1120 show_route_nexthop_helper(vty
, re
, nexthop
);
1121 vty_out(vty
, ", %s\n", up_str
);
1124 /* If we only had backup nexthops, we're done */
1125 if (nhg_from_backup
)
1128 /* Check for backup nexthop info if present */
1130 nhg
= rib_get_fib_backup_nhg(re
);
1132 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1137 /* Print backup info */
1138 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1139 bool star_p
= false;
1142 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1144 /* TODO -- it'd be nice to be able to include
1145 * the entire list of backups, *and* include the
1146 * real installation state.
1148 vty_out(vty
, " b%c %*c",
1149 (star_p
? '*' : ' '),
1150 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1151 show_route_nexthop_helper(vty
, re
, nexthop
);
1157 static void vty_show_ip_route_detail_json(struct vty
*vty
,
1158 struct route_node
*rn
, bool use_fib
)
1160 json_object
*json
= NULL
;
1161 json_object
*json_prefix
= NULL
;
1162 struct route_entry
*re
;
1166 dest
= rib_dest_from_rnode(rn
);
1168 json
= json_object_new_object();
1169 json_prefix
= json_object_new_array();
1171 RNODE_FOREACH_RE (rn
, re
) {
1173 * If re not selected for forwarding, skip re
1174 * for "show ip/ipv6 fib <prefix> json"
1176 if (use_fib
&& re
!= dest
->selected_fib
)
1178 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
1181 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1182 json_object_object_add(json
, buf
, json_prefix
);
1183 vty_json(vty
, json
);
1186 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1187 struct route_table
*table
, afi_t afi
,
1188 bool use_fib
, route_tag_t tag
,
1189 const struct prefix
*longer_prefix_p
,
1190 bool supernets_only
, int type
,
1191 unsigned short ospf_instance_id
, bool use_json
,
1192 uint32_t tableid
, bool show_ng
,
1193 struct route_show_ctx
*ctx
)
1195 struct route_node
*rn
;
1196 struct route_entry
*re
;
1199 json_object
*json
= NULL
;
1200 json_object
*json_prefix
= NULL
;
1205 * ctx->multi indicates if we are dumping multiple tables or vrfs.
1207 * => display the common header at most once
1208 * => add newline at each call except first
1209 * => always display the VRF and table
1211 * => display the common header if at least one entry is found
1212 * => display the VRF and table if specific
1216 json
= json_object_new_object();
1218 /* Show all routes. */
1219 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
1220 dest
= rib_dest_from_rnode(rn
);
1222 RNODE_FOREACH_RE (rn
, re
) {
1223 if (use_fib
&& re
!= dest
->selected_fib
)
1226 if (tag
&& re
->tag
!= tag
)
1230 && !prefix_match(longer_prefix_p
, &rn
->p
))
1233 /* This can only be true when the afi is IPv4 */
1234 if (supernets_only
) {
1235 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1237 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1240 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1243 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1247 if (type
&& re
->type
!= type
)
1250 if (ospf_instance_id
1251 && (re
->type
!= ZEBRA_ROUTE_OSPF
1252 || re
->instance
!= ospf_instance_id
))
1257 json_prefix
= json_object_new_array();
1259 if (!ctx
->header_done
) {
1262 SHOW_ROUTE_V4_HEADER
);
1265 SHOW_ROUTE_V6_HEADER
);
1267 if (ctx
->multi
&& ctx
->header_done
)
1269 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
1272 vty_out(vty
, "VRF %s:\n",
1276 "VRF %s table %u:\n",
1280 ctx
->header_done
= true;
1284 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
1289 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1290 json_object_object_add(json
, buf
, json_prefix
);
1296 vty_json(vty
, json
);
1299 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1300 afi_t afi
, bool use_fib
, bool use_json
,
1302 const struct prefix
*longer_prefix_p
,
1303 bool supernets_only
, int type
,
1304 unsigned short ospf_instance_id
, bool show_ng
,
1305 struct route_show_ctx
*ctx
)
1307 struct zebra_router_table
*zrt
;
1308 struct rib_table_info
*info
;
1310 RB_FOREACH (zrt
, zebra_router_table_head
,
1312 info
= route_table_get_info(zrt
->table
);
1314 if (zvrf
!= info
->zvrf
)
1316 if (zrt
->afi
!= afi
||
1317 zrt
->safi
!= SAFI_UNICAST
)
1320 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1321 use_fib
, use_json
, tag
, longer_prefix_p
,
1322 supernets_only
, type
, ospf_instance_id
,
1323 zrt
->tableid
, show_ng
, ctx
);
1327 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1328 safi_t safi
, bool use_fib
, bool use_json
,
1330 const struct prefix
*longer_prefix_p
,
1331 bool supernets_only
, int type
,
1332 unsigned short ospf_instance_id
, uint32_t tableid
,
1333 bool show_ng
, struct route_show_ctx
*ctx
)
1335 struct route_table
*table
;
1336 struct zebra_vrf
*zvrf
= NULL
;
1338 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1340 vty_out(vty
, "{}\n");
1342 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1346 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1348 vty_out(vty
, "{}\n");
1350 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1355 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1357 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1360 vty_out(vty
, "{}\n");
1364 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1365 longer_prefix_p
, supernets_only
, type
,
1366 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1373 "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]",
1377 "IP nexthop tracking table\n"
1378 "IP import check tracking table\n"
1384 VRF_ALL_CMD_HELP_STR
1385 "Show Multicast (MRIB) NHT state\n"
1388 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1389 vrf_id_t vrf_id
= VRF_DEFAULT
;
1390 struct prefix prefix
, *p
= NULL
;
1391 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1392 bool uj
= use_json(argc
, argv
);
1393 json_object
*json
= NULL
;
1394 json_object
*json_vrf
= NULL
;
1395 json_object
*json_nexthop
= NULL
;
1398 json
= json_object_new_object();
1402 struct zebra_vrf
*zvrf
;
1404 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1405 if ((zvrf
= vrf
->info
) != NULL
) {
1407 json_vrf
= json_object_new_object();
1408 json_nexthop
= json_object_new_object();
1409 json_object_object_add(json
,
1412 json_object_object_add(json_vrf
,
1416 vty_out(vty
, "\nVRF %s:\n",
1419 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1420 vty
, NULL
, json_nexthop
);
1425 vty_json(vty
, json
);
1430 VRF_GET_ID(vrf_id
, vrf_name
, false);
1432 memset(&prefix
, 0, sizeof(prefix
));
1434 p
= sockunion2hostprefix(addr
, &prefix
);
1437 json_object_free(json
);
1443 json_vrf
= json_object_new_object();
1444 json_nexthop
= json_object_new_object();
1446 json_object_object_add(json
, vrf_name
, json_vrf
);
1448 json_object_object_add(json
, "default", json_vrf
);
1450 json_object_object_add(json_vrf
, "nexthops", json_nexthop
);
1453 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1456 vty_json(vty
, json
);
1461 DEFUN (ip_nht_default_route
,
1462 ip_nht_default_route_cmd
,
1463 "ip nht resolve-via-default",
1465 "Filter Next Hop tracking route resolution\n"
1466 "Resolve via default route\n")
1468 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1473 if (zvrf
->zebra_rnh_ip_default_route
)
1476 zvrf
->zebra_rnh_ip_default_route
= true;
1478 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1482 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1483 json_object
*json_nhe_hdr
)
1485 struct nexthop
*nexthop
= NULL
;
1486 struct nhg_connected
*rb_node_dep
= NULL
;
1487 struct nexthop_group
*backup_nhg
;
1488 char up_str
[MONOTIME_STRLEN
];
1489 char time_left
[MONOTIME_STRLEN
];
1490 json_object
*json_dependants
= NULL
;
1491 json_object
*json_depends
= NULL
;
1492 json_object
*json_nexthop_array
= NULL
;
1493 json_object
*json_nexthops
= NULL
;
1494 json_object
*json
= NULL
;
1495 json_object
*json_backup_nexthop_array
= NULL
;
1496 json_object
*json_backup_nexthops
= NULL
;
1499 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1502 json
= json_object_new_object();
1505 json_object_string_add(json
, "type",
1506 zebra_route_string(nhe
->type
));
1507 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1508 if (thread_is_scheduled(nhe
->timer
))
1509 json_object_string_add(
1510 json
, "timeToDeletion",
1511 thread_timer_to_hhmmss(time_left
,
1514 json_object_string_add(json
, "uptime", up_str
);
1515 json_object_string_add(json
, "vrf",
1516 vrf_id_to_name(nhe
->vrf_id
));
1519 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1520 zebra_route_string(nhe
->type
));
1521 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1522 if (thread_is_scheduled(nhe
->timer
))
1523 vty_out(vty
, " Time to Deletion: %s",
1524 thread_timer_to_hhmmss(time_left
,
1529 vty_out(vty
, " Uptime: %s\n", up_str
);
1530 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1533 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1535 json_object_boolean_true_add(json
, "valid");
1537 vty_out(vty
, " Valid");
1539 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1541 json_object_boolean_true_add(json
, "installed");
1543 vty_out(vty
, ", Installed");
1550 json_object_int_add(json
, "interfaceIndex",
1553 vty_out(vty
, " Interface Index: %d\n",
1557 if (!zebra_nhg_depends_is_empty(nhe
)) {
1559 json_depends
= json_object_new_array();
1561 vty_out(vty
, " Depends:");
1562 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1564 json_object_array_add(
1566 json_object_new_int(
1567 rb_node_dep
->nhe
->id
));
1569 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1574 json_object_object_add(json
, "depends", json_depends
);
1577 /* Output nexthops */
1579 json_nexthop_array
= json_object_new_array();
1582 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1583 if (json_nexthop_array
) {
1584 json_nexthops
= json_object_new_object();
1585 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1587 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1590 /* Make recursive nexthops a bit more clear */
1592 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1595 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1596 if (CHECK_FLAG(nexthop
->flags
,
1597 NEXTHOP_FLAG_HAS_BACKUP
)) {
1599 json_object_int_add(
1600 json_nexthops
, "backup",
1601 nexthop
->backup_idx
[0]);
1603 vty_out(vty
, " [backup %d]",
1604 nexthop
->backup_idx
[0]);
1610 json_object_array_add(json_nexthop_array
,
1617 /* TODO -- print more useful backup info */
1618 if (CHECK_FLAG(nexthop
->flags
,
1619 NEXTHOP_FLAG_HAS_BACKUP
)) {
1622 vty_out(vty
, "[backup");
1623 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1625 nexthop
->backup_idx
[i
]);
1630 json_object_array_add(json_nexthop_array
,
1636 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1638 /* Output backup nexthops (if any) */
1639 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1642 json_backup_nexthop_array
= json_object_new_array();
1644 vty_out(vty
, " Backups:\n");
1646 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1647 if (json_backup_nexthop_array
) {
1648 json_backup_nexthops
= json_object_new_object();
1649 show_nexthop_json_helper(json_backup_nexthops
,
1651 json_object_array_add(json_backup_nexthop_array
,
1652 json_backup_nexthops
);
1655 if (!CHECK_FLAG(nexthop
->flags
,
1656 NEXTHOP_FLAG_RECURSIVE
))
1659 /* Make recursive nexthops a bit more
1663 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1669 json_object_object_add(json
, "backupNexthops",
1670 json_backup_nexthop_array
);
1673 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1675 json_dependants
= json_object_new_array();
1677 vty_out(vty
, " Dependents:");
1678 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1681 json_object_array_add(
1683 json_object_new_int(
1684 rb_node_dep
->nhe
->id
));
1686 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1689 json_object_object_add(json
, "dependents",
1695 if (nhe
->nhg
.nhgr
.buckets
) {
1697 json_object_int_add(json
, "buckets",
1698 nhe
->nhg
.nhgr
.buckets
);
1699 json_object_int_add(json
, "idleTimer",
1700 nhe
->nhg
.nhgr
.idle_timer
);
1701 json_object_int_add(json
, "unbalancedTimer",
1702 nhe
->nhg
.nhgr
.unbalanced_timer
);
1703 json_object_int_add(json
, "unbalancedTime",
1704 nhe
->nhg
.nhgr
.unbalanced_time
);
1707 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1709 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1710 nhe
->nhg
.nhgr
.unbalanced_timer
,
1711 nhe
->nhg
.nhgr
.unbalanced_time
);
1716 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1719 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1722 struct nhg_hash_entry
*nhe
= NULL
;
1724 nhe
= zebra_nhg_lookup_id(id
);
1727 show_nexthop_group_out(vty
, nhe
, json
);
1730 vty_json(vty
, json
);
1732 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1738 vty_json(vty
, json
);
1743 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1745 struct nhe_show_context
{
1753 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1755 struct nhe_show_context
*ctx
= arg
;
1756 struct nhg_hash_entry
*nhe
;
1758 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1760 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1763 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1766 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1769 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1772 return HASHWALK_CONTINUE
;
1775 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1776 struct zebra_vrf
*zvrf
, afi_t afi
,
1777 int type
, json_object
*json
)
1779 struct nhe_show_context ctx
;
1783 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1787 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1790 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1792 struct zebra_if
*zebra_if
= NULL
;
1793 struct nhg_connected
*rb_node_dep
= NULL
;
1795 zebra_if
= ifp
->info
;
1797 if (!if_nhg_dependents_is_empty(ifp
)) {
1798 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1800 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1803 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1808 DEFPY (show_interface_nexthop_group
,
1809 show_interface_nexthop_group_cmd
,
1810 "show interface [IFNAME$if_name] nexthop-group",
1812 "Interface status and configuration\n"
1814 "Show Nexthop Groups\n")
1816 struct vrf
*vrf
= NULL
;
1817 struct interface
*ifp
= NULL
;
1820 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1822 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1824 if_nexthop_group_dump_vty(vty
, ifp
);
1828 FOR_ALL_INTERFACES (vrf
, ifp
)
1829 if_nexthop_group_dump_vty(vty
, ifp
);
1835 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1842 DEFPY(show_nexthop_group
,
1843 show_nexthop_group_cmd
,
1844 "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]",
1846 "Show Nexthop Groups\n"
1848 "Nexthop Group ID\n"
1849 "Show Singleton Nexthop-Groups\n"
1852 "Kernel (not installed via the zebra RIB)\n"
1853 "Zebra (implicitly created by zebra)\n"
1854 "Border Gateway Protocol (BGP)\n"
1855 "Super Happy Advanced Routing Protocol (SHARP)\n"
1856 VRF_FULL_CMD_HELP_STR
1860 struct zebra_vrf
*zvrf
= NULL
;
1861 afi_t afi
= AFI_UNSPEC
;
1863 bool uj
= use_json(argc
, argv
);
1864 json_object
*json
= NULL
;
1865 json_object
*json_vrf
= NULL
;
1868 json
= json_object_new_object();
1871 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1879 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1882 type
= ZEBRA_ROUTE_NHG
;
1886 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1888 vty_json(vty
, json
);
1891 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1898 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1899 struct zebra_vrf
*zvrf
;
1905 json_vrf
= json_object_new_object();
1907 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1909 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1912 json_object_object_add(json
, vrf
->name
,
1917 vty_json(vty
, json
);
1923 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1925 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1929 vty_json(vty
, json
);
1931 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1936 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1939 vty_json(vty
, json
);
1944 DEFPY_HIDDEN(nexthop_group_use_enable
,
1945 nexthop_group_use_enable_cmd
,
1946 "[no] zebra nexthop kernel enable",
1949 "Nexthop configuration \n"
1950 "Configure use of kernel nexthops\n"
1951 "Enable kernel nexthops\n")
1953 zebra_nhg_enable_kernel_nexthops(!no
);
1957 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1958 "[no] zebra nexthop proto only",
1960 "Nexthop configuration\n"
1961 "Configure exclusive use of proto nexthops\n"
1962 "Only use proto nexthops\n")
1964 zebra_nhg_set_proto_nexthops_only(!no
);
1968 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1969 backup_nexthop_recursive_use_enable_cmd
,
1970 "[no] zebra nexthop resolve-via-backup",
1973 "Nexthop configuration \n"
1974 "Configure use of backup nexthops in recursive resolution\n")
1976 zebra_nhg_set_recursive_use_backups(!no
);
1980 DEFUN (no_ip_nht_default_route
,
1981 no_ip_nht_default_route_cmd
,
1982 "no ip nht resolve-via-default",
1985 "Filter Next Hop tracking route resolution\n"
1986 "Resolve via default route\n")
1988 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1993 if (!zvrf
->zebra_rnh_ip_default_route
)
1996 zvrf
->zebra_rnh_ip_default_route
= false;
1997 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
2001 DEFUN (ipv6_nht_default_route
,
2002 ipv6_nht_default_route_cmd
,
2003 "ipv6 nht resolve-via-default",
2005 "Filter Next Hop tracking route resolution\n"
2006 "Resolve via default route\n")
2008 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2013 if (zvrf
->zebra_rnh_ipv6_default_route
)
2016 zvrf
->zebra_rnh_ipv6_default_route
= true;
2017 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
2021 DEFUN (no_ipv6_nht_default_route
,
2022 no_ipv6_nht_default_route_cmd
,
2023 "no ipv6 nht resolve-via-default",
2026 "Filter Next Hop tracking route resolution\n"
2027 "Resolve via default route\n")
2029 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2034 if (!zvrf
->zebra_rnh_ipv6_default_route
)
2037 zvrf
->zebra_rnh_ipv6_default_route
= false;
2038 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
2042 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
2043 "[no] ip nht hide-backup-events",
2046 "Nexthop-tracking configuration\n"
2047 "Hide notification about backup nexthops\n")
2049 rnh_set_hide_backups(!no
);
2057 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
2058 [vrf <NAME$vrf_name|all$vrf_all>]\
2061 |A.B.C.D/M$prefix longer-prefixes\
2062 |supernets-only$supernets_only\
2065 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
2066 |ospf$type_str (1-65535)$ospf_instance_id\
2068 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
2069 [vrf <NAME$vrf_name|all$vrf_all>]\
2072 |X:X::X:X/M$prefix longer-prefixes\
2074 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
2076 [<json$json|nexthop-group$ng>]",
2079 "IP forwarding table\n"
2080 "IP routing table\n"
2081 "Table to display\n"
2082 "The table number to display\n"
2084 VRF_FULL_CMD_HELP_STR
2085 "Show only routes with tag\n"
2087 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2088 "Show route matching the specified Network/Mask pair only\n"
2089 "Show supernet entries only\n"
2090 FRR_IP_REDIST_HELP_STR_ZEBRA
2091 "Open Shortest Path First (OSPFv2)\n"
2094 "IP forwarding table\n"
2095 "IP routing table\n"
2096 "Table to display\n"
2097 "The table number to display\n"
2099 VRF_FULL_CMD_HELP_STR
2100 "Show only routes with tag\n"
2103 "Show route matching the specified Network/Mask pair only\n"
2104 FRR_IP6_REDIST_HELP_STR_ZEBRA
2106 "Nexthop Group Information\n")
2108 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2111 struct zebra_vrf
*zvrf
;
2112 struct route_show_ctx ctx
= {
2113 .multi
= vrf_all
|| table_all
,
2116 if (!vrf_is_backend_netns()) {
2117 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
2119 vty_out(vty
, "{}\n");
2121 vty_out(vty
, "Linux vrf backend already points to table id\n");
2122 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
2128 type
= proto_redistnum(afi
, type_str
);
2130 vty_out(vty
, "Unknown route type\n");
2136 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2137 if ((zvrf
= vrf
->info
) == NULL
2138 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2142 do_show_ip_route_all(
2143 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
2144 prefix_str
? prefix
: NULL
,
2145 !!supernets_only
, type
,
2146 ospf_instance_id
, !!ng
, &ctx
);
2149 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
2151 prefix_str
? prefix
: NULL
,
2152 !!supernets_only
, type
,
2153 ospf_instance_id
, table
, !!ng
, &ctx
);
2156 vrf_id_t vrf_id
= VRF_DEFAULT
;
2159 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
2160 vrf
= vrf_lookup_by_id(vrf_id
);
2169 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
2170 prefix_str
? prefix
: NULL
,
2171 !!supernets_only
, type
,
2172 ospf_instance_id
, !!ng
, &ctx
);
2174 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
2176 prefix_str
? prefix
: NULL
,
2177 !!supernets_only
, type
,
2178 ospf_instance_id
, table
, !!ng
, &ctx
);
2184 ALIAS_HIDDEN (show_route
,
2186 "show <ip$ipv4|ipv6$ipv6> ro",
2190 "IP routing table\n");
2193 DEFPY (show_route_detail
,
2194 show_route_detail_cmd
,
2197 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2202 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2208 [json$json] [nexthop-group$ng]",
2211 "IP forwarding table\n"
2212 "IP routing table\n"
2213 VRF_FULL_CMD_HELP_STR
2214 "Network in the IP routing table to display\n"
2215 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2217 "IPv6 forwarding table\n"
2218 "IPv6 routing table\n"
2219 VRF_FULL_CMD_HELP_STR
2223 "Nexthop Group Information\n")
2225 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2226 struct route_table
*table
;
2228 struct route_node
*rn
;
2229 bool use_fib
= !!fib
;
2231 bool network_found
= false;
2232 bool show_ng
= !!ng
;
2235 prefix_str
= address_str
;
2236 if (str2prefix(prefix_str
, &p
) < 0) {
2237 vty_out(vty
, "%% Malformed address\n");
2243 struct zebra_vrf
*zvrf
;
2245 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2246 if ((zvrf
= vrf
->info
) == NULL
2247 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2250 rn
= route_node_match(table
, &p
);
2253 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2254 route_unlock_node(rn
);
2258 dest
= rib_dest_from_rnode(rn
);
2259 if (use_fib
&& !dest
->selected_fib
) {
2260 route_unlock_node(rn
);
2264 network_found
= true;
2266 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2268 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
2271 route_unlock_node(rn
);
2274 if (!network_found
) {
2276 vty_out(vty
, "{}\n");
2280 "%% Network not in FIB\n");
2283 "%% Network not in RIB\n");
2288 vrf_id_t vrf_id
= VRF_DEFAULT
;
2291 VRF_GET_ID(vrf_id
, vrf_name
, false);
2293 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2297 rn
= route_node_match(table
, &p
);
2299 dest
= rib_dest_from_rnode(rn
);
2301 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
2302 (use_fib
&& dest
&& !dest
->selected_fib
)) {
2304 vty_out(vty
, "{}\n");
2308 "%% Network not in FIB\n");
2311 "%% Network not in table\n");
2314 route_unlock_node(rn
);
2319 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2321 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2323 route_unlock_node(rn
);
2329 DEFPY (show_route_summary
,
2330 show_route_summary_cmd
,
2331 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2332 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2336 "IP routing table\n"
2337 VRF_FULL_CMD_HELP_STR
2338 "Summary of all routes\n"
2339 "Table to display summary for\n"
2340 "The table number\n"
2344 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2345 struct route_table
*table
;
2346 bool uj
= use_json(argc
, argv
);
2350 struct zebra_vrf
*zvrf
;
2352 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2353 if ((zvrf
= vrf
->info
) == NULL
)
2357 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2360 table
= zebra_vrf_lookup_table_with_table_id(
2361 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2368 vty_show_ip_route_summary_prefix(vty
, table
,
2371 vty_show_ip_route_summary(vty
, table
, uj
);
2374 vrf_id_t vrf_id
= VRF_DEFAULT
;
2377 VRF_GET_ID(vrf_id
, vrf_name
, false);
2380 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2382 table
= zebra_vrf_lookup_table_with_table_id(
2383 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2388 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2390 vty_show_ip_route_summary(vty
, table
, uj
);
2396 DEFUN_HIDDEN (show_route_zebra_dump
,
2397 show_route_zebra_dump_cmd
,
2398 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2408 struct route_table
*table
;
2409 const char *vrf_name
= NULL
;
2412 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2414 if (argv_find(argv
, argc
, "vrf", &idx
))
2415 vrf_name
= argv
[++idx
]->arg
;
2419 struct zebra_vrf
*zvrf
;
2421 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2424 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2427 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2428 show_ip_route_dump_vty(vty
, table
);
2431 vrf_id_t vrf_id
= VRF_DEFAULT
;
2433 VRF_GET_ID(vrf_id
, vrf_name
, true);
2435 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2439 show_ip_route_dump_vty(vty
, table
);
2445 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2446 struct route_entry
*re
, unsigned int num
)
2449 char buf
[SRCDEST2STR_BUFFER
];
2451 vty_out(vty
, " Nexthop %u:\n", num
);
2452 vty_out(vty
, " type: %u\n", nexthop
->type
);
2453 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2454 switch (nexthop
->type
) {
2455 case NEXTHOP_TYPE_IPV4
:
2456 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2457 vty_out(vty
, " ip address: %s\n",
2458 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2460 vty_out(vty
, " afi: ipv4\n");
2462 if (nexthop
->ifindex
) {
2463 vty_out(vty
, " interface index: %d\n",
2465 vty_out(vty
, " interface name: %s\n",
2466 ifindex2ifname(nexthop
->ifindex
,
2470 if (nexthop
->src
.ipv4
.s_addr
2471 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2473 vty_out(vty
, " source: %s\n", buf
);
2475 case NEXTHOP_TYPE_IPV6
:
2476 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2477 vty_out(vty
, " ip: %s\n",
2478 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2480 vty_out(vty
, " afi: ipv6\n");
2482 if (nexthop
->ifindex
) {
2483 vty_out(vty
, " interface index: %d\n",
2485 vty_out(vty
, " interface name: %s\n",
2486 ifindex2ifname(nexthop
->ifindex
,
2490 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2491 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2493 vty_out(vty
, " source: %s\n", buf
);
2496 case NEXTHOP_TYPE_IFINDEX
:
2498 " Nexthop is an interface (directly connected).\n");
2499 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2500 vty_out(vty
, " interface name: %s\n",
2501 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2503 case NEXTHOP_TYPE_BLACKHOLE
:
2504 vty_out(vty
, " Nexthop type is blackhole.\n");
2506 switch (nexthop
->bh_type
) {
2507 case BLACKHOLE_REJECT
:
2508 vty_out(vty
, " Blackhole type: reject\n");
2510 case BLACKHOLE_ADMINPROHIB
:
2512 " Blackhole type: admin-prohibited\n");
2514 case BLACKHOLE_NULL
:
2515 vty_out(vty
, " Blackhole type: NULL0\n");
2517 case BLACKHOLE_UNSPEC
:
2524 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2526 struct route_node
*rn
;
2527 struct route_entry
*re
;
2528 char buf
[SRCDEST2STR_BUFFER
];
2533 struct nexthop
*nexthop
= NULL
;
2534 int nexthop_num
= 0;
2536 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2537 vty_out(vty
, "----------------------------\n");
2539 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2540 RNODE_FOREACH_RE (rn
, re
) {
2541 vty_out(vty
, "Route: %s\n",
2542 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2543 vty_out(vty
, " protocol: %s\n",
2544 zebra_route_string(re
->type
));
2545 vty_out(vty
, " instance: %u\n", re
->instance
);
2546 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2547 vty_out(vty
, " VRF name: %s\n",
2548 vrf_id_to_name(re
->vrf_id
));
2549 vty_out(vty
, " flags: %u\n", re
->flags
);
2551 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2552 vty_out(vty
, " distance: %u\n", re
->distance
);
2553 vty_out(vty
, " metric: %u\n", re
->metric
);
2556 vty_out(vty
, " tag: %u\n", re
->tag
);
2558 uptime
= monotime(&tv
);
2559 uptime
-= re
->uptime
;
2560 gmtime_r(&uptime
, &tm
);
2562 if (uptime
< ONE_DAY_SECOND
)
2563 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2564 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2565 else if (uptime
< ONE_WEEK_SECOND
)
2566 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2567 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2569 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2571 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2574 vty_out(vty
, " status: %u\n", re
->status
);
2575 vty_out(vty
, " nexthop_num: %u\n",
2576 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2577 vty_out(vty
, " nexthop_active_num: %u\n",
2578 nexthop_group_active_nexthop_num(
2580 vty_out(vty
, " table: %u\n", re
->table
);
2581 vty_out(vty
, " uptime: %s\n", time
);
2583 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2585 show_ip_route_nht_dump(vty
, nexthop
, re
,
2595 static void vty_show_ip_route_summary(struct vty
*vty
,
2596 struct route_table
*table
, bool use_json
)
2598 struct route_node
*rn
;
2599 struct route_entry
*re
;
2600 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2601 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2602 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2603 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2604 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2605 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2608 json_object
*json_route_summary
= NULL
;
2609 json_object
*json_route_routes
= NULL
;
2611 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2612 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2613 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2614 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2617 json_route_summary
= json_object_new_object();
2618 json_route_routes
= json_object_new_array();
2619 json_object_object_add(json_route_summary
, "routes",
2623 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2624 RNODE_FOREACH_RE (rn
, re
) {
2625 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2626 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2628 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2630 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2632 rib_cnt
[re
->type
]++;
2634 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2635 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2638 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2640 fib_cnt
[re
->type
]++;
2643 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2645 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2647 trap_cnt
[re
->type
]++;
2650 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2652 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2654 offload_cnt
[re
->type
]++;
2659 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2661 zvrf_name(((struct rib_table_info
*)
2662 route_table_get_info(table
))
2665 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2666 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2667 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2668 if (i
== ZEBRA_ROUTE_BGP
) {
2670 json_object
*json_route_ebgp
=
2671 json_object_new_object();
2673 json_object_int_add(
2674 json_route_ebgp
, "fib",
2675 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2676 json_object_int_add(
2677 json_route_ebgp
, "rib",
2678 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2679 json_object_int_add(
2680 json_route_ebgp
, "fibOffLoaded",
2681 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2682 json_object_int_add(
2683 json_route_ebgp
, "fibTrapped",
2684 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2686 json_object_string_add(json_route_ebgp
,
2688 json_object_array_add(json_route_routes
,
2691 json_object
*json_route_ibgp
=
2692 json_object_new_object();
2694 json_object_int_add(
2695 json_route_ibgp
, "fib",
2696 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2697 json_object_int_add(
2698 json_route_ibgp
, "rib",
2699 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2700 json_object_int_add(
2701 json_route_ibgp
, "fibOffLoaded",
2702 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2703 json_object_int_add(
2704 json_route_ibgp
, "fibTrapped",
2705 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2706 json_object_string_add(json_route_ibgp
,
2708 json_object_array_add(json_route_routes
,
2711 vty_out(vty
, "%-20s %-20d %-20d \n",
2713 rib_cnt
[ZEBRA_ROUTE_BGP
],
2714 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2715 vty_out(vty
, "%-20s %-20d %-20d \n",
2717 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2718 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2722 json_object
*json_route_type
=
2723 json_object_new_object();
2725 json_object_int_add(json_route_type
,
2727 json_object_int_add(json_route_type
,
2730 json_object_int_add(json_route_type
,
2733 json_object_int_add(json_route_type
,
2736 json_object_string_add(
2737 json_route_type
, "type",
2738 zebra_route_string(i
));
2739 json_object_array_add(json_route_routes
,
2742 vty_out(vty
, "%-20s %-20d %-20d \n",
2743 zebra_route_string(i
),
2744 rib_cnt
[i
], fib_cnt
[i
]);
2750 json_object_int_add(json_route_summary
, "routesTotal",
2751 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2752 json_object_int_add(json_route_summary
, "routesTotalFib",
2753 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2755 vty_json(vty
, json_route_summary
);
2757 vty_out(vty
, "------\n");
2758 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2759 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2765 * Implementation of the ip route summary prefix command.
2767 * This command prints the primary prefixes that have been installed by various
2768 * protocols on the box.
2771 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2772 struct route_table
*table
,
2775 struct route_node
*rn
;
2776 struct route_entry
*re
;
2777 struct nexthop
*nexthop
;
2778 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2779 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2780 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2781 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2784 json_object
*json_route_summary
= NULL
;
2785 json_object
*json_route_routes
= NULL
;
2787 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2788 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2791 json_route_summary
= json_object_new_object();
2792 json_route_routes
= json_object_new_array();
2793 json_object_object_add(json_route_summary
, "prefixRoutes",
2797 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2798 RNODE_FOREACH_RE (rn
, re
) {
2801 * In case of ECMP, count only once.
2804 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2805 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2806 fib_cnt
[re
->type
]++;
2808 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2809 nexthop
= nexthop
->next
) {
2811 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2812 rib_cnt
[re
->type
]++;
2813 if (re
->type
== ZEBRA_ROUTE_BGP
2814 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2815 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2816 if (CHECK_FLAG(re
->status
,
2817 ROUTE_ENTRY_INSTALLED
))
2818 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2824 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2825 "Prefix Routes", "FIB",
2826 zvrf_name(((struct rib_table_info
*)
2827 route_table_get_info(table
))
2830 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2831 if (rib_cnt
[i
] > 0) {
2832 if (i
== ZEBRA_ROUTE_BGP
) {
2834 json_object
*json_route_ebgp
=
2835 json_object_new_object();
2837 json_object_int_add(
2838 json_route_ebgp
, "fib",
2839 fib_cnt
[ZEBRA_ROUTE_BGP
]
2840 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2841 json_object_int_add(
2842 json_route_ebgp
, "rib",
2843 rib_cnt
[ZEBRA_ROUTE_BGP
]
2844 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2845 json_object_string_add(json_route_ebgp
,
2847 json_object_array_add(json_route_routes
,
2850 json_object
*json_route_ibgp
=
2851 json_object_new_object();
2853 json_object_int_add(
2854 json_route_ibgp
, "fib",
2855 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2856 json_object_int_add(
2857 json_route_ibgp
, "rib",
2858 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2859 json_object_string_add(json_route_ibgp
,
2861 json_object_array_add(json_route_routes
,
2864 vty_out(vty
, "%-20s %-20d %-20d \n",
2866 rib_cnt
[ZEBRA_ROUTE_BGP
]
2867 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2868 fib_cnt
[ZEBRA_ROUTE_BGP
]
2869 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2870 vty_out(vty
, "%-20s %-20d %-20d \n",
2872 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2873 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2877 json_object
*json_route_type
=
2878 json_object_new_object();
2880 json_object_int_add(json_route_type
,
2882 json_object_int_add(json_route_type
,
2884 json_object_string_add(
2885 json_route_type
, "type",
2886 zebra_route_string(i
));
2887 json_object_array_add(json_route_routes
,
2890 vty_out(vty
, "%-20s %-20d %-20d \n",
2891 zebra_route_string(i
),
2892 rib_cnt
[i
], fib_cnt
[i
]);
2898 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2899 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2900 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2901 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2903 vty_json(vty
, json_route_summary
);
2905 vty_out(vty
, "------\n");
2906 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2907 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2912 DEFUN (allow_external_route_update
,
2913 allow_external_route_update_cmd
,
2914 "allow-external-route-update",
2915 "Allow FRR routes to be overwritten by external processes\n")
2917 zrouter
.allow_delete
= true;
2922 DEFUN (no_allow_external_route_update
,
2923 no_allow_external_route_update_cmd
,
2924 "no allow-external-route-update",
2926 "Allow FRR routes to be overwritten by external processes\n")
2928 zrouter
.allow_delete
= false;
2941 struct zebra_vrf
*zvrf
;
2943 if (vrf_is_backend_netns())
2944 vty_out(vty
, "netns-based vrfs\n");
2946 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2947 if (!(zvrf
= vrf
->info
))
2949 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2952 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2953 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2954 vty_out(vty
, "inactive");
2955 else if (zvrf_ns_name(zvrf
))
2956 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2957 zvrf_ns_name(zvrf
));
2959 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2961 if (vrf_is_user_cfged(vrf
))
2962 vty_out(vty
, " (configured)");
2969 DEFPY (evpn_mh_mac_holdtime
,
2970 evpn_mh_mac_holdtime_cmd
,
2971 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2976 "Duration in seconds\n")
2978 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2982 DEFPY (evpn_mh_neigh_holdtime
,
2983 evpn_mh_neigh_holdtime_cmd
,
2984 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2988 "Neighbor entry hold time\n"
2989 "Duration in seconds\n")
2992 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2996 DEFPY (evpn_mh_startup_delay
,
2997 evpn_mh_startup_delay_cmd
,
2998 "[no] evpn mh startup-delay(0-3600)$duration",
3003 "duration in seconds\n")
3006 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
3010 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
3011 "[no$no] evpn mh redirect-off",
3015 "ES bond redirect for fast-failover off\n")
3019 redirect_off
= no
? false : true;
3021 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
3024 DEFUN (default_vrf_vni_mapping
,
3025 default_vrf_vni_mapping_cmd
,
3026 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
3027 "VNI corresponding to the DEFAULT VRF\n"
3029 "Prefix routes only \n")
3031 char xpath
[XPATH_MAXLEN
];
3032 struct zebra_vrf
*zvrf
= NULL
;
3035 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3042 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
3044 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
3046 snprintf(xpath
, sizeof(xpath
),
3047 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
3049 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
3052 snprintf(xpath
, sizeof(xpath
),
3053 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
3055 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
3058 return nb_cli_apply_changes(vty
, NULL
);
3061 DEFUN (no_default_vrf_vni_mapping
,
3062 no_default_vrf_vni_mapping_cmd
,
3063 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
3065 "VNI corresponding to DEFAULT VRF\n"
3067 "Prefix routes only \n")
3069 char xpath
[XPATH_MAXLEN
];
3071 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3072 struct zebra_vrf
*zvrf
= NULL
;
3074 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
3081 if (zvrf
->l3vni
!= vni
) {
3082 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
3087 snprintf(xpath
, sizeof(xpath
),
3088 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
3090 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
3093 snprintf(xpath
, sizeof(xpath
),
3094 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
3096 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
3099 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
3101 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
3103 return nb_cli_apply_changes(vty
, NULL
);
3106 DEFUN (vrf_vni_mapping
,
3107 vrf_vni_mapping_cmd
,
3108 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
3109 "VNI corresponding to tenant VRF\n"
3111 "prefix-routes-only\n")
3115 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
3123 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
3124 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
3128 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
3129 NB_OP_MODIFY
, "true");
3131 return nb_cli_apply_changes(vty
, NULL
);
3134 DEFUN (no_vrf_vni_mapping
,
3135 no_vrf_vni_mapping_cmd
,
3136 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
3138 "VNI corresponding to tenant VRF\n"
3140 "prefix-routes-only\n")
3144 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
3145 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
3153 if (zvrf
->l3vni
!= vni
) {
3154 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
3159 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
3163 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
3164 NB_OP_DESTROY
, "true");
3166 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
3168 return nb_cli_apply_changes(vty
, NULL
);
3172 DEFPY (show_vrf_vni
,
3174 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
3176 VRF_FULL_CMD_HELP_STR
3181 struct zebra_vrf
*zvrf
;
3182 json_object
*json
= NULL
;
3183 json_object
*json_vrfs
= NULL
;
3184 bool uj
= use_json(argc
, argv
);
3185 bool use_vrf
= false;
3188 json
= json_object_new_object();
3190 /* show vrf vni used to display across all vrfs
3191 * This is enhanced to support only for specific
3194 if (vrf_all
|| !vrf_name
) {
3195 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3206 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
3207 "VRF", "VNI", "VxLAN IF", "L3-SVI",
3210 json_vrfs
= json_object_new_array();
3213 vty_json(vty
, json
);
3215 vty_out(vty
, "%% VRF does not exist\n");
3222 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3227 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3229 } else if (vrf_name
) {
3230 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
3233 vty_json(vty
, json
);
3236 "%% VRF '%s' specified does not exist\n",
3243 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
3244 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
3247 json_vrfs
= json_object_new_array();
3249 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3253 json_object_object_add(json
, "vrfs", json_vrfs
);
3254 vty_json(vty
, json
);
3260 DEFUN (show_evpn_global
,
3261 show_evpn_global_cmd
,
3267 bool uj
= use_json(argc
, argv
);
3269 zebra_vxlan_print_evpn(vty
, uj
);
3273 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
3274 SHOW_STR IP_STR
"neighbors\n")
3277 zebra_neigh_show(vty
);
3282 DEFPY(show_evpn_l2_nh
,
3283 show_evpn_l2_nh_cmd
,
3284 "show evpn l2-nh [json$json]",
3292 zebra_evpn_l2_nh_show(vty
, uj
);
3299 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3302 "Ethernet Segment\n"
3304 "Detailed information\n"
3311 if (!str_to_esi(esi_str
, &esi
)) {
3312 vty_out(vty
, "%% Malformed ESI\n");
3315 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3318 zebra_evpn_es_show_detail(vty
, uj
);
3320 zebra_evpn_es_show(vty
, uj
);
3326 DEFPY(show_evpn_es_evi
,
3327 show_evpn_es_evi_cmd
,
3328 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3331 "Ethernet Segment per EVI\n"
3332 "VxLAN Network Identifier\n"
3334 "Detailed information\n"
3341 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3343 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3348 DEFPY(show_evpn_access_vlan
,
3349 show_evpn_access_vlan_cmd
,
3350 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3355 "Detailed information\n"
3361 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3364 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3366 zebra_evpn_acc_vl_show(vty
, uj
);
3372 DEFUN (show_evpn_vni
,
3374 "show evpn vni [json]",
3377 "VxLAN Network Identifier\n"
3380 struct zebra_vrf
*zvrf
;
3381 bool uj
= use_json(argc
, argv
);
3383 zvrf
= zebra_vrf_get_evpn();
3384 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3388 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3389 "show evpn vni detail [json]",
3392 "VxLAN Network Identifier\n"
3393 "Detailed Information On Each VNI\n"
3396 struct zebra_vrf
*zvrf
;
3397 bool uj
= use_json(argc
, argv
);
3399 zvrf
= zebra_vrf_get_evpn();
3400 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3404 DEFUN (show_evpn_vni_vni
,
3405 show_evpn_vni_vni_cmd
,
3406 "show evpn vni " CMD_VNI_RANGE
"[json]",
3409 "VxLAN Network Identifier\n"
3413 struct zebra_vrf
*zvrf
;
3415 bool uj
= use_json(argc
, argv
);
3417 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3418 zvrf
= zebra_vrf_get_evpn();
3419 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3423 DEFUN (show_evpn_rmac_vni_mac
,
3424 show_evpn_rmac_vni_mac_cmd
,
3425 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3432 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3437 bool uj
= use_json(argc
, argv
);
3439 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3440 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3441 vty_out(vty
, "%% Malformed MAC address\n");
3444 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3448 DEFUN (show_evpn_rmac_vni
,
3449 show_evpn_rmac_vni_cmd
,
3450 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3459 bool uj
= use_json(argc
, argv
);
3461 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3462 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3467 DEFUN (show_evpn_rmac_vni_all
,
3468 show_evpn_rmac_vni_all_cmd
,
3469 "show evpn rmac vni all [json]",
3477 bool uj
= use_json(argc
, argv
);
3479 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3484 DEFUN (show_evpn_nh_vni_ip
,
3485 show_evpn_nh_vni_ip_cmd
,
3486 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3493 "Host address (ipv4 or ipv6)\n"
3498 bool uj
= use_json(argc
, argv
);
3500 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3501 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3503 vty_out(vty
, "%% Malformed Neighbor address\n");
3506 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3511 DEFUN (show_evpn_nh_vni
,
3512 show_evpn_nh_vni_cmd
,
3513 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3522 bool uj
= use_json(argc
, argv
);
3524 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3525 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3530 DEFUN (show_evpn_nh_vni_all
,
3531 show_evpn_nh_vni_all_cmd
,
3532 "show evpn next-hops vni all [json]",
3540 bool uj
= use_json(argc
, argv
);
3542 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3547 DEFUN (show_evpn_mac_vni
,
3548 show_evpn_mac_vni_cmd
,
3549 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3553 "VxLAN Network Identifier\n"
3557 struct zebra_vrf
*zvrf
;
3559 bool uj
= use_json(argc
, argv
);
3561 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3562 zvrf
= zebra_vrf_get_evpn();
3563 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3567 DEFPY (show_evpn_mac_vni_detail
,
3568 show_evpn_mac_vni_detail_cmd
,
3569 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3573 "VXLAN Network Identifier\n"
3575 "Detailed Information On Each VNI MAC\n"
3578 struct zebra_vrf
*zvrf
;
3579 bool uj
= use_json(argc
, argv
);
3581 zvrf
= zebra_vrf_get_evpn();
3582 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3586 DEFUN (show_evpn_mac_vni_all
,
3587 show_evpn_mac_vni_all_cmd
,
3588 "show evpn mac vni all [json]",
3592 "VxLAN Network Identifier\n"
3596 struct zebra_vrf
*zvrf
;
3597 bool uj
= use_json(argc
, argv
);
3599 zvrf
= zebra_vrf_get_evpn();
3600 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3604 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3605 "show evpn mac vni all detail [json]",
3609 "VxLAN Network Identifier\n"
3611 "Detailed Information On Each VNI MAC\n"
3614 struct zebra_vrf
*zvrf
;
3615 bool uj
= use_json(argc
, argv
);
3617 zvrf
= zebra_vrf_get_evpn();
3618 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3622 DEFUN (show_evpn_mac_vni_all_vtep
,
3623 show_evpn_mac_vni_all_vtep_cmd
,
3624 "show evpn mac vni all vtep A.B.C.D [json]",
3628 "VxLAN Network Identifier\n"
3631 "Remote VTEP IP address\n"
3634 struct zebra_vrf
*zvrf
;
3635 struct in_addr vtep_ip
;
3636 bool uj
= use_json(argc
, argv
);
3638 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3640 vty_out(vty
, "%% Malformed VTEP IP address\n");
3643 zvrf
= zebra_vrf_get_evpn();
3644 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3650 DEFUN (show_evpn_mac_vni_mac
,
3651 show_evpn_mac_vni_mac_cmd
,
3652 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3656 "VxLAN Network Identifier\n"
3659 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3663 struct zebra_vrf
*zvrf
;
3666 bool uj
= use_json(argc
, argv
);
3668 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3669 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3670 vty_out(vty
, "%% Malformed MAC address\n");
3673 zvrf
= zebra_vrf_get_evpn();
3674 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3678 DEFUN (show_evpn_mac_vni_vtep
,
3679 show_evpn_mac_vni_vtep_cmd
,
3680 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3684 "VxLAN Network Identifier\n"
3687 "Remote VTEP IP address\n"
3690 struct zebra_vrf
*zvrf
;
3692 struct in_addr vtep_ip
;
3693 bool uj
= use_json(argc
, argv
);
3695 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3696 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3698 vty_out(vty
, "%% Malformed VTEP IP address\n");
3702 zvrf
= zebra_vrf_get_evpn();
3703 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3707 DEFPY (show_evpn_mac_vni_all_dad
,
3708 show_evpn_mac_vni_all_dad_cmd
,
3709 "show evpn mac vni all duplicate [json]",
3713 "VxLAN Network Identifier\n"
3715 "Duplicate address list\n"
3718 struct zebra_vrf
*zvrf
;
3719 bool uj
= use_json(argc
, argv
);
3721 zvrf
= zebra_vrf_get_evpn();
3722 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3727 DEFPY (show_evpn_mac_vni_dad
,
3728 show_evpn_mac_vni_dad_cmd
,
3729 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3733 "VxLAN Network Identifier\n"
3735 "Duplicate address list\n"
3738 struct zebra_vrf
*zvrf
;
3739 bool uj
= use_json(argc
, argv
);
3741 zvrf
= zebra_vrf_get_evpn();
3743 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3748 DEFPY (show_evpn_neigh_vni_dad
,
3749 show_evpn_neigh_vni_dad_cmd
,
3750 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3753 "ARP and ND cache\n"
3754 "VxLAN Network Identifier\n"
3756 "Duplicate address list\n"
3759 struct zebra_vrf
*zvrf
;
3760 bool uj
= use_json(argc
, argv
);
3762 zvrf
= zebra_vrf_get_evpn();
3763 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3767 DEFPY (show_evpn_neigh_vni_all_dad
,
3768 show_evpn_neigh_vni_all_dad_cmd
,
3769 "show evpn arp-cache vni all duplicate [json]",
3772 "ARP and ND cache\n"
3773 "VxLAN Network Identifier\n"
3775 "Duplicate address list\n"
3778 struct zebra_vrf
*zvrf
;
3779 bool uj
= use_json(argc
, argv
);
3781 zvrf
= zebra_vrf_get_evpn();
3782 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3787 DEFUN (show_evpn_neigh_vni
,
3788 show_evpn_neigh_vni_cmd
,
3789 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3792 "ARP and ND cache\n"
3793 "VxLAN Network Identifier\n"
3797 struct zebra_vrf
*zvrf
;
3799 bool uj
= use_json(argc
, argv
);
3801 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3802 zvrf
= zebra_vrf_get_evpn();
3803 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3807 DEFUN (show_evpn_neigh_vni_all
,
3808 show_evpn_neigh_vni_all_cmd
,
3809 "show evpn arp-cache vni all [json]",
3812 "ARP and ND cache\n"
3813 "VxLAN Network Identifier\n"
3817 struct zebra_vrf
*zvrf
;
3818 bool uj
= use_json(argc
, argv
);
3820 zvrf
= zebra_vrf_get_evpn();
3821 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3825 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3826 "show evpn arp-cache vni all detail [json]",
3829 "ARP and ND cache\n"
3830 "VxLAN Network Identifier\n"
3832 "Neighbor details for all vnis in detail\n" JSON_STR
)
3834 struct zebra_vrf
*zvrf
;
3835 bool uj
= use_json(argc
, argv
);
3837 zvrf
= zebra_vrf_get_evpn();
3838 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3842 DEFUN (show_evpn_neigh_vni_neigh
,
3843 show_evpn_neigh_vni_neigh_cmd
,
3844 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3847 "ARP and ND cache\n"
3848 "VxLAN Network Identifier\n"
3851 "Neighbor address (IPv4 or IPv6 address)\n"
3854 struct zebra_vrf
*zvrf
;
3857 bool uj
= use_json(argc
, argv
);
3859 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3860 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3862 vty_out(vty
, "%% Malformed Neighbor address\n");
3865 zvrf
= zebra_vrf_get_evpn();
3866 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3870 DEFUN (show_evpn_neigh_vni_vtep
,
3871 show_evpn_neigh_vni_vtep_cmd
,
3872 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3875 "ARP and ND cache\n"
3876 "VxLAN Network Identifier\n"
3879 "Remote VTEP IP address\n"
3882 struct zebra_vrf
*zvrf
;
3884 struct in_addr vtep_ip
;
3885 bool uj
= use_json(argc
, argv
);
3887 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3888 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3890 vty_out(vty
, "%% Malformed VTEP IP address\n");
3894 zvrf
= zebra_vrf_get_evpn();
3895 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3899 /* policy routing contexts */
3900 DEFUN (show_pbr_ipset
,
3902 "show pbr ipset [WORD]",
3904 "Policy-Based Routing\n"
3905 "IPset Context information\n"
3906 "IPset Name information\n")
3910 found
= argv_find(argv
, argc
, "WORD", &idx
);
3912 zebra_pbr_show_ipset_list(vty
, NULL
);
3914 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3918 /* policy routing contexts */
3919 DEFUN (show_pbr_iptable
,
3920 show_pbr_iptable_cmd
,
3921 "show pbr iptable [WORD]",
3923 "Policy-Based Routing\n"
3924 "IPtable Context information\n"
3925 "IPtable Name information\n")
3930 found
= argv_find(argv
, argc
, "WORD", &idx
);
3932 zebra_pbr_show_iptable(vty
, NULL
);
3934 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3938 /* policy routing contexts */
3939 DEFPY (show_pbr_rule
,
3943 "Policy-Based Routing\n"
3946 zebra_pbr_show_rule(vty
);
3950 DEFPY (pbr_nexthop_resolve
,
3951 pbr_nexthop_resolve_cmd
,
3952 "[no$no] pbr nexthop-resolve",
3954 "Policy Based Routing\n"
3955 "Resolve nexthop for dataplane programming\n")
3957 zebra_pbr_expand_action_update(!no
);
3961 DEFPY (clear_evpn_dup_addr
,
3962 clear_evpn_dup_addr_cmd
,
3963 "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>]>",
3966 "Duplicate address \n"
3967 "VxLAN Network Identifier\n"
3971 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3976 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3977 int ret
= CMD_SUCCESS
;
3979 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3980 *yang_dup_mac
= NULL
;
3985 yang_dup
= yang_data_new(
3986 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3989 yang_dup
= yang_data_new_uint32(
3990 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3992 if (!is_zero_mac(&mac
->eth_addr
)) {
3993 yang_dup_mac
= yang_data_new_mac(
3994 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3997 listnode_add(input
, yang_dup_mac
);
3999 if (sockunion_family(ip
) == AF_INET
) {
4000 host_ip
.ipa_type
= IPADDR_V4
;
4001 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
4003 host_ip
.ipa_type
= IPADDR_V6
;
4004 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
4005 sizeof(struct in6_addr
));
4008 yang_dup_ip
= yang_data_new_ip(
4009 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
4013 listnode_add(input
, yang_dup_ip
);
4018 listnode_add(input
, yang_dup
);
4019 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
4023 list_delete(&input
);
4028 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
4029 evpn_accept_bgp_seq_cmd
,
4030 "evpn accept-bgp-seq",
4032 "Accept all sequence numbers from BGP\n")
4034 zebra_vxlan_set_accept_bgp_seq(true);
4038 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
4039 no_evpn_accept_bgp_seq_cmd
,
4040 "no evpn accept-bgp-seq",
4043 "Accept all sequence numbers from BGP\n")
4045 zebra_vxlan_set_accept_bgp_seq(false);
4049 /* Static ip route configuration write function. */
4050 static int zebra_ip_config(struct vty
*vty
)
4054 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
4059 DEFUN (ip_zebra_import_table_distance
,
4060 ip_zebra_import_table_distance_cmd
,
4061 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
4063 "import routes from non-main kernel table\n"
4064 "kernel routing table id\n"
4065 "Distance for imported routes\n"
4066 "Default distance value\n"
4067 "route-map for filtering\n"
4070 uint32_t table_id
= 0;
4072 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
4073 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
4075 strmatch(argv
[argc
- 2]->text
, "route-map")
4076 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
4080 if (argc
== 7 || (argc
== 5 && !rmap
))
4081 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
4083 if (!is_zebra_valid_kernel_table(table_id
)) {
4085 "Invalid routing table ID, %d. Must be in range 1-252\n",
4088 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
4092 if (is_zebra_main_routing_table(table_id
)) {
4094 "Invalid routing table ID, %d. Must be non-default table\n",
4097 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
4101 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
4104 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
4109 DEFUN_HIDDEN (zebra_packet_process
,
4110 zebra_packet_process_cmd
,
4111 "zebra zapi-packets (1-10000)",
4114 "Number of packets to process before relinquishing thread\n")
4116 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
4118 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
4119 memory_order_relaxed
);
4124 DEFUN_HIDDEN (no_zebra_packet_process
,
4125 no_zebra_packet_process_cmd
,
4126 "no zebra zapi-packets [(1-10000)]",
4130 "Number of packets to process before relinquishing thread\n")
4132 atomic_store_explicit(&zrouter
.packets_to_process
,
4133 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
4134 memory_order_relaxed
);
4139 DEFUN_HIDDEN (zebra_workqueue_timer
,
4140 zebra_workqueue_timer_cmd
,
4141 "zebra work-queue (0-10000)",
4144 "Time in milliseconds\n")
4146 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
4147 zrouter
.ribq
->spec
.hold
= timer
;
4152 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
4153 no_zebra_workqueue_timer_cmd
,
4154 "no zebra work-queue [(0-10000)]",
4158 "Time in milliseconds\n")
4160 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
4165 DEFUN (no_ip_zebra_import_table
,
4166 no_ip_zebra_import_table_cmd
,
4167 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
4170 "import routes from non-main kernel table\n"
4171 "kernel routing table id\n"
4172 "Distance for imported routes\n"
4173 "Default distance value\n"
4174 "route-map for filtering\n"
4177 uint32_t table_id
= 0;
4178 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
4180 if (!is_zebra_valid_kernel_table(table_id
)) {
4182 "Invalid routing table ID. Must be in range 1-252\n");
4186 if (is_zebra_main_routing_table(table_id
)) {
4188 "Invalid routing table ID, %d. Must be non-default table\n",
4193 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
4196 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
4199 DEFPY (zebra_nexthop_group_keep
,
4200 zebra_nexthop_group_keep_cmd
,
4201 "[no] zebra nexthop-group keep (1-3600)",
4205 "How long to keep\n"
4206 "Time in seconds from 1-3600\n")
4209 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
4211 zrouter
.nhg_keep
= keep
;
4216 static int config_write_protocol(struct vty
*vty
)
4218 if (zrouter
.allow_delete
)
4219 vty_out(vty
, "allow-external-route-update\n");
4221 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
4222 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
4224 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
4225 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
4227 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
4228 vty_out(vty
, "zebra zapi-packets %u\n",
4229 zrouter
.packets_to_process
);
4231 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
4233 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
4234 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
4235 ipv4_multicast_mode
== MCAST_URIB_ONLY
4237 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
4239 : ipv4_multicast_mode
4240 == MCAST_MIX_MRIB_FIRST
4242 : ipv4_multicast_mode
4243 == MCAST_MIX_DISTANCE
4247 /* Include dataplane info */
4248 dplane_config_write_helper(vty
);
4250 zebra_evpn_mh_config_write(vty
);
4252 zebra_pbr_config_write(vty
);
4254 if (!zebra_vxlan_get_accept_bgp_seq())
4255 vty_out(vty
, "no evpn accept-bgp-seq\n");
4257 /* Include nexthop-group config */
4258 if (!zebra_nhg_kernel_nexthops_enabled())
4259 vty_out(vty
, "no zebra nexthop kernel enable\n");
4261 if (zebra_nhg_proto_nexthops_only())
4262 vty_out(vty
, "zebra nexthop proto only\n");
4264 if (!zebra_nhg_recursive_use_backups())
4265 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
4267 if (rnh_get_hide_backups())
4268 vty_out(vty
, "ip nht hide-backup-events\n");
4271 /* Include netlink info */
4272 netlink_config_write_helper(vty
);
4273 #endif /* HAVE_NETLINK */
4285 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4288 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4289 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4290 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4291 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4292 ttable_add_row(table
, "v6 Forwarding|%s",
4293 ipforward_ipv6() ? "On" : "Off");
4294 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4295 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4296 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4300 if (!vrf_is_backend_netns())
4301 ttable_add_row(table
, "VRF|l3mdev Available");
4303 ttable_add_row(table
, "VRF|Namespaces");
4305 ttable_add_row(table
, "VRF|Not Available");
4308 ttable_add_row(table
, "ASIC offload|%s",
4309 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4312 * Do not display this unless someone is actually using it
4314 * Why this distinction? I think this is effectively dead code
4315 * and should not be exposed. Maybe someone proves me wrong.
4317 if (zrouter
.asic_notification_nexthop_control
)
4318 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4320 ttable_add_row(table
, "RA|%s",
4321 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4322 ttable_add_row(table
, "RFC 5549|%s",
4323 rtadv_get_interfaces_configured_from_bgp()
4325 : "BGP is not using");
4327 ttable_add_row(table
, "Kernel NHG|%s",
4328 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4330 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4331 zrouter
.allow_delete
? "Yes" : "No");
4332 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4333 zrouter
.all_linkdownv4
? "On" : "Off");
4334 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4335 zrouter
.default_linkdownv4
? "On" : "Off");
4336 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4337 zrouter
.all_linkdownv6
? "On" : "Off");
4338 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4339 zrouter
.default_linkdownv6
? "On" : "Off");
4341 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4342 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4343 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4344 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4345 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4346 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4347 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4348 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4350 out
= ttable_dump(table
, "\n");
4351 vty_out(vty
, "%s\n", out
);
4352 XFREE(MTYPE_TMP
, out
);
4356 " Route Route Neighbor LSP LSP\n");
4358 "VRF Installs Removals Updates Installs Removals\n");
4360 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4361 struct zebra_vrf
*zvrf
= vrf
->info
;
4363 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4364 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4365 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4366 zvrf
->lsp_removals
);
4372 DEFUN (ip_forwarding
,
4376 "Turn on IP forwarding\n")
4382 ret
= ipforward_on();
4385 vty_out(vty
, "Can't turn on IP forwarding\n");
4386 return CMD_WARNING_CONFIG_FAILED
;
4392 DEFUN (no_ip_forwarding
,
4393 no_ip_forwarding_cmd
,
4397 "Turn off IP forwarding\n")
4403 ret
= ipforward_off();
4406 vty_out(vty
, "Can't turn off IP forwarding\n");
4407 return CMD_WARNING_CONFIG_FAILED
;
4413 /* Only display ip forwarding is enabled or not. */
4414 DEFUN (show_ip_forwarding
,
4415 show_ip_forwarding_cmd
,
4416 "show ip forwarding",
4419 "IP forwarding status\n")
4426 vty_out(vty
, "IP forwarding is off\n");
4428 vty_out(vty
, "IP forwarding is on\n");
4432 /* Only display ipv6 forwarding is enabled or not. */
4433 DEFUN (show_ipv6_forwarding
,
4434 show_ipv6_forwarding_cmd
,
4435 "show ipv6 forwarding",
4437 "IPv6 information\n"
4438 "Forwarding status\n")
4442 ret
= ipforward_ipv6();
4446 vty_out(vty
, "ipv6 forwarding is unknown\n");
4449 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4452 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4455 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4461 DEFUN (ipv6_forwarding
,
4462 ipv6_forwarding_cmd
,
4465 "Turn on IPv6 forwarding\n")
4469 ret
= ipforward_ipv6();
4471 ret
= ipforward_ipv6_on();
4474 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4475 return CMD_WARNING_CONFIG_FAILED
;
4481 DEFUN (no_ipv6_forwarding
,
4482 no_ipv6_forwarding_cmd
,
4483 "no ipv6 forwarding",
4486 "Turn off IPv6 forwarding\n")
4490 ret
= ipforward_ipv6();
4492 ret
= ipforward_ipv6_off();
4495 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4496 return CMD_WARNING_CONFIG_FAILED
;
4502 /* Display dataplane info */
4503 DEFUN (show_dataplane
,
4505 "show zebra dplane [detailed]",
4508 "Zebra dataplane information\n"
4509 "Detailed output\n")
4512 bool detailed
= false;
4514 if (argv_find(argv
, argc
, "detailed", &idx
))
4517 return dplane_show_helper(vty
, detailed
);
4520 /* Display dataplane providers info */
4521 DEFUN (show_dataplane_providers
,
4522 show_dataplane_providers_cmd
,
4523 "show zebra dplane providers [detailed]",
4526 "Zebra dataplane information\n"
4527 "Zebra dataplane provider information\n"
4528 "Detailed output\n")
4531 bool detailed
= false;
4533 if (argv_find(argv
, argc
, "detailed", &idx
))
4536 return dplane_show_provs_helper(vty
, detailed
);
4539 /* Configure dataplane incoming queue limit */
4540 DEFUN (zebra_dplane_queue_limit
,
4541 zebra_dplane_queue_limit_cmd
,
4542 "zebra dplane limit (0-10000)",
4545 "Limit incoming queued updates\n"
4546 "Number of queued updates\n")
4550 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4552 dplane_set_in_queue_limit(limit
, true);
4557 /* Reset dataplane queue limit to default value */
4558 DEFUN (no_zebra_dplane_queue_limit
,
4559 no_zebra_dplane_queue_limit_cmd
,
4560 "no zebra dplane limit [(0-10000)]",
4564 "Limit incoming queued updates\n"
4565 "Number of queued updates\n")
4567 dplane_set_in_queue_limit(0, false);
4572 DEFUN (zebra_show_routing_tables_summary
,
4573 zebra_show_routing_tables_summary_cmd
,
4574 "show zebra router table summary",
4577 "The Zebra Router Information\n"
4578 "Table Information about this Zebra Router\n"
4579 "Summary Information\n")
4581 zebra_router_show_table_summary(vty
);
4586 /* Table configuration write function. */
4587 static int config_write_table(struct vty
*vty
)
4592 /* IPForwarding configuration write function. */
4593 static int config_write_forwarding(struct vty
*vty
)
4596 vty_out(vty
, "no ip forwarding\n");
4597 if (!ipforward_ipv6())
4598 vty_out(vty
, "no ipv6 forwarding\n");
4599 vty_out(vty
, "!\n");
4603 DEFUN_HIDDEN (show_frr
,
4609 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4610 vty_out(vty
, ".............................7777:..............................................\n");
4611 vty_out(vty
, ".............................777777,............................................\n");
4612 vty_out(vty
, "... .........................77777777,..........................................\n");
4613 vty_out(vty
, "............................=7777777777:........................................\n");
4614 vty_out(vty
, "........................:7777777777777777,......................................\n");
4615 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4616 vty_out(vty
, "...................I7777777777+.................................................\n");
4617 vty_out(vty
, "................,777777777?............ .......................................\n");
4618 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4619 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4620 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4621 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4622 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4623 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4624 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4625 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4626 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4627 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4628 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4629 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4630 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4631 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4632 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4633 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4634 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4635 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4636 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4637 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4638 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4639 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4640 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4641 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4642 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4643 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4644 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4645 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4646 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4647 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4648 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4649 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4650 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4651 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4652 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4653 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4654 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4655 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4656 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4657 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4658 vty_out(vty
, "................................~77777777...............=777777.................\n");
4659 vty_out(vty
, ".....................................:=?I................~777777................\n");
4660 vty_out(vty
, "..........................................................:777777,..............\n");
4661 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4667 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4668 zebra_kernel_netlink_batch_tx_buf_cmd
,
4669 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4671 "Zebra kernel interface\n"
4672 "Set Netlink parameters\n"
4673 "Set batch buffer size and send threshold\n"
4674 "Size of the buffer\n"
4677 uint32_t bufsize
= 0, threshold
= 0;
4679 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4680 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4682 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4687 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4688 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4689 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4691 "Zebra kernel interface\n"
4692 "Set Netlink parameters\n"
4693 "Set batch buffer size and send threshold\n"
4694 "Size of the buffer\n"
4697 netlink_set_batch_buffer_size(0, 0, false);
4702 DEFPY (zebra_protodown_bit
,
4703 zebra_protodown_bit_cmd
,
4704 "zebra protodown reason-bit (0-31)$bit",
4706 "Protodown Configuration\n"
4707 "Reason Bit used in the kernel for application\n"
4708 "Reason Bit range\n")
4710 if_netlink_set_frr_protodown_r_bit(bit
);
4714 DEFPY (no_zebra_protodown_bit
,
4715 no_zebra_protodown_bit_cmd
,
4716 "no zebra protodown reason-bit [(0-31)$bit]",
4719 "Protodown Configuration\n"
4720 "Reason Bit used in the kernel for setting protodown\n"
4721 "Reason Bit Range\n")
4723 if_netlink_unset_frr_protodown_r_bit();
4727 #endif /* HAVE_NETLINK */
4729 DEFUN(ip_table_range
, ip_table_range_cmd
,
4730 "[no] ip table range (1-4294967295) (1-4294967295)",
4732 "table configuration\n"
4733 "Configure table range\n"
4734 "Start Routing Table\n"
4735 "End Routing Table\n")
4737 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4742 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4744 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4748 if (strmatch(argv
[0]->text
, "no"))
4749 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4751 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4754 #ifdef HAVE_SCRIPTING
4756 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4757 "zebra on-rib-process script SCRIPT",
4759 "on_rib_process_dplane_results hook call\n"
4761 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4764 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4767 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4768 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4770 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4771 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4776 #endif /* HAVE_SCRIPTING */
4778 /* IP node for static routes. */
4779 static int zebra_ip_config(struct vty
*vty
);
4780 static struct cmd_node ip_node
= {
4781 .name
= "static ip",
4784 .config_write
= zebra_ip_config
,
4786 static int config_write_protocol(struct vty
*vty
);
4787 static struct cmd_node protocol_node
= {
4789 .node
= PROTOCOL_NODE
,
4791 .config_write
= config_write_protocol
,
4793 /* table node for routing tables. */
4794 static int config_write_table(struct vty
*vty
);
4795 static struct cmd_node table_node
= {
4799 .config_write
= config_write_table
,
4801 static int config_write_forwarding(struct vty
*vty
);
4802 static struct cmd_node forwarding_node
= {
4803 .name
= "forwarding",
4804 .node
= FORWARDING_NODE
,
4806 .config_write
= config_write_forwarding
,
4810 void zebra_vty_init(void)
4812 /* Install configuration write function. */
4813 install_node(&table_node
);
4814 install_node(&forwarding_node
);
4816 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4817 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4818 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4819 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4821 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4822 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4823 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4826 zebra_route_map_init();
4828 install_node(&ip_node
);
4829 install_node(&protocol_node
);
4831 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4832 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4834 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4835 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4837 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4838 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4839 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4840 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4841 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4842 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4843 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4844 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4845 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4846 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4848 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4849 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4851 install_element(VIEW_NODE
, &show_vrf_cmd
);
4852 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4853 install_element(VIEW_NODE
, &show_route_cmd
);
4854 install_element(VIEW_NODE
, &show_ro_cmd
);
4855 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4856 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4857 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4859 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4860 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4862 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4863 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4864 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4865 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4866 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4867 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4868 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4869 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4870 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4872 install_element(VIEW_NODE
, &show_frr_cmd
);
4873 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4874 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4875 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4876 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4877 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4878 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4879 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4880 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4881 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4882 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4883 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4884 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4885 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4886 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4887 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4888 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4889 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4890 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4891 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4892 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4893 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4894 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4895 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4896 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4897 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4898 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4899 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4900 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4901 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4902 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4903 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4904 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4905 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4907 install_element(VIEW_NODE
, &show_neigh_cmd
);
4909 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4910 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4911 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4912 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4913 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4915 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4916 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4917 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4918 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4919 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4920 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4921 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4922 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4924 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4925 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4926 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4927 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4929 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4930 install_element(VRF_NODE
, &ip_table_range_cmd
);
4933 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4934 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4935 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4936 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4937 #endif /* HAVE_NETLINK */
4939 #ifdef HAVE_SCRIPTING
4940 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4941 #endif /* HAVE_SCRIPTING */
4943 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);