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
,
636 case NEXTHOP_TYPE_BLACKHOLE
:
637 vty_out(vty
, " unreachable");
638 switch (nexthop
->bh_type
) {
639 case BLACKHOLE_REJECT
:
640 vty_out(vty
, " (ICMP unreachable)");
642 case BLACKHOLE_ADMINPROHIB
:
643 vty_out(vty
, " (ICMP admin-prohibited)");
646 vty_out(vty
, " (blackhole)");
648 case BLACKHOLE_UNSPEC
:
654 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
655 vty_out(vty
, " (vrf %s)", vrf_id_to_name(nexthop
->vrf_id
));
657 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
658 vty_out(vty
, " inactive");
660 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
661 vty_out(vty
, " onlink");
663 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
664 vty_out(vty
, " linkdown");
666 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
667 vty_out(vty
, " (recursive)");
669 switch (nexthop
->type
) {
670 case NEXTHOP_TYPE_IPV4
:
671 case NEXTHOP_TYPE_IPV4_IFINDEX
:
672 if (nexthop
->src
.ipv4
.s_addr
) {
673 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
675 vty_out(vty
, ", src %s", buf
);
676 /* SR-TE information */
677 if (nexthop
->srte_color
)
678 vty_out(vty
, ", SR-TE color %u",
679 nexthop
->srte_color
);
682 case NEXTHOP_TYPE_IPV6
:
683 case NEXTHOP_TYPE_IPV6_IFINDEX
:
684 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
685 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
687 vty_out(vty
, ", src %s", buf
);
694 /* Label information */
695 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
696 vty_out(vty
, ", label %s",
697 mpls_label2str(nexthop
->nh_label
->num_labels
,
698 nexthop
->nh_label
->label
, buf
,
702 if (nexthop
->nh_srv6
) {
703 seg6local_context2str(buf
, sizeof(buf
),
704 &nexthop
->nh_srv6
->seg6local_ctx
,
705 nexthop
->nh_srv6
->seg6local_action
);
706 vty_out(vty
, ", seg6local %s %s", seg6local_action2str(
707 nexthop
->nh_srv6
->seg6local_action
), buf
);
709 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
711 vty_out(vty
, ", seg6 %s", buf
);
715 vty_out(vty
, ", weight %u", nexthop
->weight
);
717 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
718 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
720 for (i
= 1; i
< nexthop
->backup_num
; i
++)
721 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
726 * Render a nexthop into a json object; the caller allocates and owns
727 * the json object memory.
729 static void show_nexthop_json_helper(json_object
*json_nexthop
,
730 const struct nexthop
*nexthop
,
731 const struct route_entry
*re
)
733 char buf
[SRCDEST2STR_BUFFER
];
734 json_object
*json_labels
= NULL
;
735 json_object
*json_backups
= NULL
;
736 json_object
*json_seg6local
= NULL
;
737 json_object
*json_seg6
= NULL
;
740 json_object_int_add(json_nexthop
, "flags",
743 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
744 json_object_boolean_true_add(json_nexthop
,
747 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
748 json_object_boolean_true_add(json_nexthop
,
751 switch (nexthop
->type
) {
752 case NEXTHOP_TYPE_IPV4
:
753 case NEXTHOP_TYPE_IPV4_IFINDEX
:
754 json_object_string_addf(json_nexthop
, "ip", "%pI4",
755 &nexthop
->gate
.ipv4
);
756 json_object_string_add(json_nexthop
, "afi",
759 if (nexthop
->ifindex
) {
760 json_object_int_add(json_nexthop
,
763 json_object_string_add(
764 json_nexthop
, "interfaceName",
770 case NEXTHOP_TYPE_IPV6
:
771 case NEXTHOP_TYPE_IPV6_IFINDEX
:
772 json_object_string_addf(json_nexthop
, "ip", "%pI6",
773 &nexthop
->gate
.ipv6
);
774 json_object_string_add(json_nexthop
, "afi",
777 if (nexthop
->ifindex
) {
778 json_object_int_add(json_nexthop
,
781 json_object_string_add(
782 json_nexthop
, "interfaceName",
789 case NEXTHOP_TYPE_IFINDEX
:
790 json_object_boolean_true_add(
791 json_nexthop
, "directlyConnected");
792 json_object_int_add(json_nexthop
,
795 json_object_string_add(
796 json_nexthop
, "interfaceName",
797 ifindex2ifname(nexthop
->ifindex
,
800 case NEXTHOP_TYPE_BLACKHOLE
:
801 json_object_boolean_true_add(json_nexthop
,
803 switch (nexthop
->bh_type
) {
804 case BLACKHOLE_REJECT
:
805 json_object_boolean_true_add(
806 json_nexthop
, "reject");
808 case BLACKHOLE_ADMINPROHIB
:
809 json_object_boolean_true_add(
814 json_object_boolean_true_add(
815 json_nexthop
, "blackhole");
817 case BLACKHOLE_UNSPEC
:
823 /* This nexthop is a resolver for the parent nexthop.
824 * Set resolver flag for better clarity and delimiter
825 * in flat list of nexthops in json.
827 if (nexthop
->rparent
)
828 json_object_boolean_true_add(json_nexthop
, "resolver");
830 if (nexthop
->vrf_id
!= re
->vrf_id
)
831 json_object_string_add(json_nexthop
, "vrf",
832 vrf_id_to_name(nexthop
->vrf_id
));
834 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
835 json_object_boolean_true_add(json_nexthop
,
838 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
839 json_object_boolean_true_add(json_nexthop
,
842 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
843 json_object_boolean_true_add(json_nexthop
,
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
)
1484 struct nexthop
*nexthop
= NULL
;
1485 struct nhg_connected
*rb_node_dep
= NULL
;
1486 struct nexthop_group
*backup_nhg
;
1487 char up_str
[MONOTIME_STRLEN
];
1488 char time_left
[MONOTIME_STRLEN
];
1490 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1492 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
, zebra_route_string(nhe
->type
));
1493 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1494 if (thread_is_scheduled(nhe
->timer
))
1495 vty_out(vty
, " Time to Deletion: %s",
1496 thread_timer_to_hhmmss(time_left
, sizeof(time_left
),
1500 vty_out(vty
, " Uptime: %s\n", up_str
);
1501 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1504 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1505 vty_out(vty
, " Valid");
1506 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
))
1507 vty_out(vty
, ", Installed");
1511 vty_out(vty
, " Interface Index: %d\n", nhe
->ifp
->ifindex
);
1513 if (!zebra_nhg_depends_is_empty(nhe
)) {
1514 vty_out(vty
, " Depends:");
1515 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1516 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1521 /* Output nexthops */
1522 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1523 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1526 /* Make recursive nexthops a bit more clear */
1529 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1531 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1532 if (CHECK_FLAG(nexthop
->flags
,
1533 NEXTHOP_FLAG_HAS_BACKUP
))
1534 vty_out(vty
, " [backup %d]",
1535 nexthop
->backup_idx
[0]);
1541 /* TODO -- print more useful backup info */
1542 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
1545 vty_out(vty
, "[backup");
1546 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1547 vty_out(vty
, " %d", nexthop
->backup_idx
[i
]);
1555 /* Output backup nexthops (if any) */
1556 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1558 vty_out(vty
, " Backups:\n");
1560 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1561 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1564 /* Make recursive nexthops a bit more clear */
1567 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1572 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1573 vty_out(vty
, " Dependents:");
1574 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1576 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1581 if (nhe
->nhg
.nhgr
.buckets
)
1583 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
"\n",
1584 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1585 nhe
->nhg
.nhgr
.unbalanced_timer
,
1586 nhe
->nhg
.nhgr
.unbalanced_time
);
1589 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
)
1591 struct nhg_hash_entry
*nhe
= NULL
;
1593 nhe
= zebra_nhg_lookup_id(id
);
1596 show_nexthop_group_out(vty
, nhe
);
1598 vty_out(vty
, "Nexthop Group ID: %u does not exist\n", id
);
1604 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1606 struct nhe_show_context
{
1613 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1615 struct nhe_show_context
*ctx
= arg
;
1616 struct nhg_hash_entry
*nhe
;
1618 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1620 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1623 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1626 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1629 show_nexthop_group_out(ctx
->vty
, nhe
);
1632 return HASHWALK_CONTINUE
;
1635 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1636 struct zebra_vrf
*zvrf
, afi_t afi
,
1639 struct nhe_show_context ctx
;
1643 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1646 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1649 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1651 struct zebra_if
*zebra_if
= NULL
;
1652 struct nhg_connected
*rb_node_dep
= NULL
;
1654 zebra_if
= ifp
->info
;
1656 if (!if_nhg_dependents_is_empty(ifp
)) {
1657 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1659 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1662 show_nexthop_group_out(vty
, rb_node_dep
->nhe
);
1667 DEFPY (show_interface_nexthop_group
,
1668 show_interface_nexthop_group_cmd
,
1669 "show interface [IFNAME$if_name] nexthop-group",
1671 "Interface status and configuration\n"
1673 "Show Nexthop Groups\n")
1675 struct vrf
*vrf
= NULL
;
1676 struct interface
*ifp
= NULL
;
1679 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1681 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1683 if_nexthop_group_dump_vty(vty
, ifp
);
1687 FOR_ALL_INTERFACES (vrf
, ifp
)
1688 if_nexthop_group_dump_vty(vty
, ifp
);
1694 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1701 DEFPY (show_nexthop_group
,
1702 show_nexthop_group_cmd
,
1703 "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>]>",
1705 "Show Nexthop Groups\n"
1707 "Nexthop Group ID\n"
1708 "Show Singleton Nexthop-Groups\n"
1711 "Kernel (not installed via the zebra RIB)\n"
1712 "Zebra (implicitly created by zebra)\n"
1713 "Border Gateway Protocol (BGP)\n"
1714 "Super Happy Advanced Routing Protocol (SHARP)\n"
1715 VRF_FULL_CMD_HELP_STR
)
1718 struct zebra_vrf
*zvrf
= NULL
;
1719 afi_t afi
= AFI_UNSPEC
;
1723 return show_nexthop_group_id_cmd_helper(vty
, id
);
1731 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1734 type
= ZEBRA_ROUTE_NHG
;
1738 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1740 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1747 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1748 struct zebra_vrf
*zvrf
;
1754 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1755 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1762 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1764 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1767 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1772 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1777 DEFPY_HIDDEN(nexthop_group_use_enable
,
1778 nexthop_group_use_enable_cmd
,
1779 "[no] zebra nexthop kernel enable",
1782 "Nexthop configuration \n"
1783 "Configure use of kernel nexthops\n"
1784 "Enable kernel nexthops\n")
1786 zebra_nhg_enable_kernel_nexthops(!no
);
1790 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1791 "[no] zebra nexthop proto only",
1793 "Nexthop configuration\n"
1794 "Configure exclusive use of proto nexthops\n"
1795 "Only use proto nexthops\n")
1797 zebra_nhg_set_proto_nexthops_only(!no
);
1801 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1802 backup_nexthop_recursive_use_enable_cmd
,
1803 "[no] zebra nexthop resolve-via-backup",
1806 "Nexthop configuration \n"
1807 "Configure use of backup nexthops in recursive resolution\n")
1809 zebra_nhg_set_recursive_use_backups(!no
);
1813 DEFUN (no_ip_nht_default_route
,
1814 no_ip_nht_default_route_cmd
,
1815 "no ip nht resolve-via-default",
1818 "Filter Next Hop tracking route resolution\n"
1819 "Resolve via default route\n")
1821 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1826 if (!zvrf
->zebra_rnh_ip_default_route
)
1829 zvrf
->zebra_rnh_ip_default_route
= false;
1830 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1834 DEFUN (ipv6_nht_default_route
,
1835 ipv6_nht_default_route_cmd
,
1836 "ipv6 nht resolve-via-default",
1838 "Filter Next Hop tracking route resolution\n"
1839 "Resolve via default route\n")
1841 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1846 if (zvrf
->zebra_rnh_ipv6_default_route
)
1849 zvrf
->zebra_rnh_ipv6_default_route
= true;
1850 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1854 DEFUN (no_ipv6_nht_default_route
,
1855 no_ipv6_nht_default_route_cmd
,
1856 "no ipv6 nht resolve-via-default",
1859 "Filter Next Hop tracking route resolution\n"
1860 "Resolve via default route\n")
1862 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1867 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1870 zvrf
->zebra_rnh_ipv6_default_route
= false;
1871 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1875 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1876 "[no] ip nht hide-backup-events",
1879 "Nexthop-tracking configuration\n"
1880 "Hide notification about backup nexthops\n")
1882 rnh_set_hide_backups(!no
);
1890 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1891 [vrf <NAME$vrf_name|all$vrf_all>]\
1894 |A.B.C.D/M$prefix longer-prefixes\
1895 |supernets-only$supernets_only\
1898 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1899 |ospf$type_str (1-65535)$ospf_instance_id\
1901 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1902 [vrf <NAME$vrf_name|all$vrf_all>]\
1905 |X:X::X:X/M$prefix longer-prefixes\
1907 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1909 [<json$json|nexthop-group$ng>]",
1912 "IP forwarding table\n"
1913 "IP routing table\n"
1914 "Table to display\n"
1915 "The table number to display\n"
1917 VRF_FULL_CMD_HELP_STR
1918 "Show only routes with tag\n"
1920 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1921 "Show route matching the specified Network/Mask pair only\n"
1922 "Show supernet entries only\n"
1923 FRR_IP_REDIST_HELP_STR_ZEBRA
1924 "Open Shortest Path First (OSPFv2)\n"
1927 "IP forwarding table\n"
1928 "IP routing table\n"
1929 "Table to display\n"
1930 "The table number to display\n"
1932 VRF_FULL_CMD_HELP_STR
1933 "Show only routes with tag\n"
1936 "Show route matching the specified Network/Mask pair only\n"
1937 FRR_IP6_REDIST_HELP_STR_ZEBRA
1939 "Nexthop Group Information\n")
1941 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1944 struct zebra_vrf
*zvrf
;
1945 struct route_show_ctx ctx
= {
1946 .multi
= vrf_all
|| table_all
,
1949 if (!vrf_is_backend_netns()) {
1950 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1952 vty_out(vty
, "{}\n");
1954 vty_out(vty
, "Linux vrf backend already points to table id\n");
1955 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1961 type
= proto_redistnum(afi
, type_str
);
1963 vty_out(vty
, "Unknown route type\n");
1969 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1970 if ((zvrf
= vrf
->info
) == NULL
1971 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1975 do_show_ip_route_all(
1976 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1977 prefix_str
? prefix
: NULL
,
1978 !!supernets_only
, type
,
1979 ospf_instance_id
, !!ng
, &ctx
);
1982 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1984 prefix_str
? prefix
: NULL
,
1985 !!supernets_only
, type
,
1986 ospf_instance_id
, table
, !!ng
, &ctx
);
1989 vrf_id_t vrf_id
= VRF_DEFAULT
;
1992 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1993 vrf
= vrf_lookup_by_id(vrf_id
);
2002 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
2003 prefix_str
? prefix
: NULL
,
2004 !!supernets_only
, type
,
2005 ospf_instance_id
, !!ng
, &ctx
);
2007 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
2009 prefix_str
? prefix
: NULL
,
2010 !!supernets_only
, type
,
2011 ospf_instance_id
, table
, !!ng
, &ctx
);
2017 ALIAS_HIDDEN (show_route
,
2019 "show <ip$ipv4|ipv6$ipv6> ro",
2023 "IP routing table\n");
2026 DEFPY (show_route_detail
,
2027 show_route_detail_cmd
,
2030 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2035 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
2041 [json$json] [nexthop-group$ng]",
2044 "IPv6 forwarding table\n"
2045 "IP routing table\n"
2046 VRF_FULL_CMD_HELP_STR
2047 "Network in the IP routing table to display\n"
2048 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2050 "IPv6 forwarding table\n"
2051 "IPv6 routing table\n"
2052 VRF_FULL_CMD_HELP_STR
2056 "Nexthop Group Information\n")
2058 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2059 struct route_table
*table
;
2061 struct route_node
*rn
;
2062 bool use_fib
= !!fib
;
2064 bool network_found
= false;
2065 bool show_ng
= !!ng
;
2068 prefix_str
= address_str
;
2069 if (str2prefix(prefix_str
, &p
) < 0) {
2070 vty_out(vty
, "%% Malformed address\n");
2076 struct zebra_vrf
*zvrf
;
2078 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2079 if ((zvrf
= vrf
->info
) == NULL
2080 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2083 rn
= route_node_match(table
, &p
);
2086 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2087 route_unlock_node(rn
);
2091 dest
= rib_dest_from_rnode(rn
);
2092 if (use_fib
&& !dest
->selected_fib
) {
2093 route_unlock_node(rn
);
2097 network_found
= true;
2099 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2101 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
2104 route_unlock_node(rn
);
2107 if (!network_found
) {
2109 vty_out(vty
, "{}\n");
2113 "%% Network not in FIB\n");
2116 "%% Network not in RIB\n");
2121 vrf_id_t vrf_id
= VRF_DEFAULT
;
2124 VRF_GET_ID(vrf_id
, vrf_name
, false);
2126 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2130 rn
= route_node_match(table
, &p
);
2132 dest
= rib_dest_from_rnode(rn
);
2134 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
2135 (use_fib
&& dest
&& !dest
->selected_fib
)) {
2137 vty_out(vty
, "{}\n");
2141 "%% Network not in FIB\n");
2144 "%% Network not in table\n");
2147 route_unlock_node(rn
);
2152 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2154 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2156 route_unlock_node(rn
);
2162 DEFPY (show_route_summary
,
2163 show_route_summary_cmd
,
2164 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2165 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2169 "IP routing table\n"
2170 VRF_FULL_CMD_HELP_STR
2171 "Summary of all routes\n"
2172 "Table to display summary for\n"
2173 "The table number\n"
2177 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2178 struct route_table
*table
;
2179 bool uj
= use_json(argc
, argv
);
2183 struct zebra_vrf
*zvrf
;
2185 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2186 if ((zvrf
= vrf
->info
) == NULL
)
2190 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2193 table
= zebra_vrf_lookup_table_with_table_id(
2194 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2201 vty_show_ip_route_summary_prefix(vty
, table
,
2204 vty_show_ip_route_summary(vty
, table
, uj
);
2207 vrf_id_t vrf_id
= VRF_DEFAULT
;
2210 VRF_GET_ID(vrf_id
, vrf_name
, false);
2213 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2215 table
= zebra_vrf_lookup_table_with_table_id(
2216 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2221 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2223 vty_show_ip_route_summary(vty
, table
, uj
);
2229 DEFUN_HIDDEN (show_route_zebra_dump
,
2230 show_route_zebra_dump_cmd
,
2231 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2241 struct route_table
*table
;
2242 const char *vrf_name
= NULL
;
2245 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2247 if (argv_find(argv
, argc
, "vrf", &idx
))
2248 vrf_name
= argv
[++idx
]->arg
;
2252 struct zebra_vrf
*zvrf
;
2254 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2257 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2260 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2261 show_ip_route_dump_vty(vty
, table
);
2264 vrf_id_t vrf_id
= VRF_DEFAULT
;
2266 VRF_GET_ID(vrf_id
, vrf_name
, true);
2268 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2272 show_ip_route_dump_vty(vty
, table
);
2278 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2279 struct route_entry
*re
, unsigned int num
)
2282 char buf
[SRCDEST2STR_BUFFER
];
2284 vty_out(vty
, " Nexthop %u:\n", num
);
2285 vty_out(vty
, " type: %u\n", nexthop
->type
);
2286 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2287 switch (nexthop
->type
) {
2288 case NEXTHOP_TYPE_IPV4
:
2289 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2290 vty_out(vty
, " ip address: %s\n",
2291 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2293 vty_out(vty
, " afi: ipv4\n");
2295 if (nexthop
->ifindex
) {
2296 vty_out(vty
, " interface index: %d\n",
2298 vty_out(vty
, " interface name: %s\n",
2299 ifindex2ifname(nexthop
->ifindex
,
2303 if (nexthop
->src
.ipv4
.s_addr
2304 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2306 vty_out(vty
, " source: %s\n", buf
);
2308 case NEXTHOP_TYPE_IPV6
:
2309 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2310 vty_out(vty
, " ip: %s\n",
2311 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2313 vty_out(vty
, " afi: ipv6\n");
2315 if (nexthop
->ifindex
) {
2316 vty_out(vty
, " interface index: %d\n",
2318 vty_out(vty
, " interface name: %s\n",
2319 ifindex2ifname(nexthop
->ifindex
,
2323 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2324 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2326 vty_out(vty
, " source: %s\n", buf
);
2329 case NEXTHOP_TYPE_IFINDEX
:
2331 " Nexthop is an interface (directly connected).\n");
2332 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2333 vty_out(vty
, " interface name: %s\n",
2334 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2336 case NEXTHOP_TYPE_BLACKHOLE
:
2337 vty_out(vty
, " Nexthop type is blackhole.\n");
2339 switch (nexthop
->bh_type
) {
2340 case BLACKHOLE_REJECT
:
2341 vty_out(vty
, " Blackhole type: reject\n");
2343 case BLACKHOLE_ADMINPROHIB
:
2345 " Blackhole type: admin-prohibited\n");
2347 case BLACKHOLE_NULL
:
2348 vty_out(vty
, " Blackhole type: NULL0\n");
2350 case BLACKHOLE_UNSPEC
:
2357 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2359 struct route_node
*rn
;
2360 struct route_entry
*re
;
2361 char buf
[SRCDEST2STR_BUFFER
];
2366 struct nexthop
*nexthop
= NULL
;
2367 int nexthop_num
= 0;
2369 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2370 vty_out(vty
, "----------------------------\n");
2372 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2373 RNODE_FOREACH_RE (rn
, re
) {
2374 vty_out(vty
, "Route: %s\n",
2375 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2376 vty_out(vty
, " protocol: %s\n",
2377 zebra_route_string(re
->type
));
2378 vty_out(vty
, " instance: %u\n", re
->instance
);
2379 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2380 vty_out(vty
, " VRF name: %s\n",
2381 vrf_id_to_name(re
->vrf_id
));
2382 vty_out(vty
, " flags: %u\n", re
->flags
);
2384 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2385 vty_out(vty
, " distance: %u\n", re
->distance
);
2386 vty_out(vty
, " metric: %u\n", re
->metric
);
2389 vty_out(vty
, " tag: %u\n", re
->tag
);
2391 uptime
= monotime(&tv
);
2392 uptime
-= re
->uptime
;
2393 gmtime_r(&uptime
, &tm
);
2395 if (uptime
< ONE_DAY_SECOND
)
2396 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2397 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2398 else if (uptime
< ONE_WEEK_SECOND
)
2399 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2400 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2402 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2404 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2407 vty_out(vty
, " status: %u\n", re
->status
);
2408 vty_out(vty
, " nexthop_num: %u\n",
2409 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2410 vty_out(vty
, " nexthop_active_num: %u\n",
2411 nexthop_group_active_nexthop_num(
2413 vty_out(vty
, " table: %u\n", re
->table
);
2414 vty_out(vty
, " uptime: %s\n", time
);
2416 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2418 show_ip_route_nht_dump(vty
, nexthop
, re
,
2428 static void vty_show_ip_route_summary(struct vty
*vty
,
2429 struct route_table
*table
, bool use_json
)
2431 struct route_node
*rn
;
2432 struct route_entry
*re
;
2433 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2434 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2435 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2436 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2437 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2438 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2441 json_object
*json_route_summary
= NULL
;
2442 json_object
*json_route_routes
= NULL
;
2444 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2445 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2446 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2447 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2450 json_route_summary
= json_object_new_object();
2451 json_route_routes
= json_object_new_array();
2452 json_object_object_add(json_route_summary
, "routes",
2456 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2457 RNODE_FOREACH_RE (rn
, re
) {
2458 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2459 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2461 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2463 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2465 rib_cnt
[re
->type
]++;
2467 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2468 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2471 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2473 fib_cnt
[re
->type
]++;
2476 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2478 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2480 trap_cnt
[re
->type
]++;
2483 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2485 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2487 offload_cnt
[re
->type
]++;
2492 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2494 zvrf_name(((struct rib_table_info
*)
2495 route_table_get_info(table
))
2498 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2499 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2500 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2501 if (i
== ZEBRA_ROUTE_BGP
) {
2503 json_object
*json_route_ebgp
=
2504 json_object_new_object();
2506 json_object_int_add(
2507 json_route_ebgp
, "fib",
2508 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2509 json_object_int_add(
2510 json_route_ebgp
, "rib",
2511 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2512 json_object_int_add(
2513 json_route_ebgp
, "fibOffLoaded",
2514 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2515 json_object_int_add(
2516 json_route_ebgp
, "fibTrapped",
2517 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2519 json_object_string_add(json_route_ebgp
,
2521 json_object_array_add(json_route_routes
,
2524 json_object
*json_route_ibgp
=
2525 json_object_new_object();
2527 json_object_int_add(
2528 json_route_ibgp
, "fib",
2529 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2530 json_object_int_add(
2531 json_route_ibgp
, "rib",
2532 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2533 json_object_int_add(
2534 json_route_ibgp
, "fibOffLoaded",
2535 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2536 json_object_int_add(
2537 json_route_ibgp
, "fibTrapped",
2538 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2539 json_object_string_add(json_route_ibgp
,
2541 json_object_array_add(json_route_routes
,
2544 vty_out(vty
, "%-20s %-20d %-20d \n",
2546 rib_cnt
[ZEBRA_ROUTE_BGP
],
2547 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2548 vty_out(vty
, "%-20s %-20d %-20d \n",
2550 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2551 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2555 json_object
*json_route_type
=
2556 json_object_new_object();
2558 json_object_int_add(json_route_type
,
2560 json_object_int_add(json_route_type
,
2563 json_object_int_add(json_route_type
,
2566 json_object_int_add(json_route_type
,
2569 json_object_string_add(
2570 json_route_type
, "type",
2571 zebra_route_string(i
));
2572 json_object_array_add(json_route_routes
,
2575 vty_out(vty
, "%-20s %-20d %-20d \n",
2576 zebra_route_string(i
),
2577 rib_cnt
[i
], fib_cnt
[i
]);
2583 json_object_int_add(json_route_summary
, "routesTotal",
2584 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2585 json_object_int_add(json_route_summary
, "routesTotalFib",
2586 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2588 vty_json(vty
, json_route_summary
);
2590 vty_out(vty
, "------\n");
2591 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2592 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2598 * Implementation of the ip route summary prefix command.
2600 * This command prints the primary prefixes that have been installed by various
2601 * protocols on the box.
2604 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2605 struct route_table
*table
,
2608 struct route_node
*rn
;
2609 struct route_entry
*re
;
2610 struct nexthop
*nexthop
;
2611 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2612 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2613 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2614 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2617 json_object
*json_route_summary
= NULL
;
2618 json_object
*json_route_routes
= NULL
;
2620 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2621 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2624 json_route_summary
= json_object_new_object();
2625 json_route_routes
= json_object_new_array();
2626 json_object_object_add(json_route_summary
, "prefixRoutes",
2630 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2631 RNODE_FOREACH_RE (rn
, re
) {
2634 * In case of ECMP, count only once.
2637 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2638 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2639 fib_cnt
[re
->type
]++;
2641 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2642 nexthop
= nexthop
->next
) {
2644 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2645 rib_cnt
[re
->type
]++;
2646 if (re
->type
== ZEBRA_ROUTE_BGP
2647 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2648 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2649 if (CHECK_FLAG(re
->status
,
2650 ROUTE_ENTRY_INSTALLED
))
2651 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2657 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2658 "Prefix Routes", "FIB",
2659 zvrf_name(((struct rib_table_info
*)
2660 route_table_get_info(table
))
2663 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2664 if (rib_cnt
[i
] > 0) {
2665 if (i
== ZEBRA_ROUTE_BGP
) {
2667 json_object
*json_route_ebgp
=
2668 json_object_new_object();
2670 json_object_int_add(
2671 json_route_ebgp
, "fib",
2672 fib_cnt
[ZEBRA_ROUTE_BGP
]
2673 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2674 json_object_int_add(
2675 json_route_ebgp
, "rib",
2676 rib_cnt
[ZEBRA_ROUTE_BGP
]
2677 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2678 json_object_string_add(json_route_ebgp
,
2680 json_object_array_add(json_route_routes
,
2683 json_object
*json_route_ibgp
=
2684 json_object_new_object();
2686 json_object_int_add(
2687 json_route_ibgp
, "fib",
2688 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2689 json_object_int_add(
2690 json_route_ibgp
, "rib",
2691 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2692 json_object_string_add(json_route_ibgp
,
2694 json_object_array_add(json_route_routes
,
2697 vty_out(vty
, "%-20s %-20d %-20d \n",
2699 rib_cnt
[ZEBRA_ROUTE_BGP
]
2700 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2701 fib_cnt
[ZEBRA_ROUTE_BGP
]
2702 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2703 vty_out(vty
, "%-20s %-20d %-20d \n",
2705 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2706 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2710 json_object
*json_route_type
=
2711 json_object_new_object();
2713 json_object_int_add(json_route_type
,
2715 json_object_int_add(json_route_type
,
2717 json_object_string_add(
2718 json_route_type
, "type",
2719 zebra_route_string(i
));
2720 json_object_array_add(json_route_routes
,
2723 vty_out(vty
, "%-20s %-20d %-20d \n",
2724 zebra_route_string(i
),
2725 rib_cnt
[i
], fib_cnt
[i
]);
2731 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2732 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2733 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2734 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2736 vty_json(vty
, json_route_summary
);
2738 vty_out(vty
, "------\n");
2739 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2740 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2745 DEFUN (allow_external_route_update
,
2746 allow_external_route_update_cmd
,
2747 "allow-external-route-update",
2748 "Allow FRR routes to be overwritten by external processes\n")
2750 zrouter
.allow_delete
= true;
2755 DEFUN (no_allow_external_route_update
,
2756 no_allow_external_route_update_cmd
,
2757 "no allow-external-route-update",
2759 "Allow FRR routes to be overwritten by external processes\n")
2761 zrouter
.allow_delete
= false;
2774 struct zebra_vrf
*zvrf
;
2776 if (vrf_is_backend_netns())
2777 vty_out(vty
, "netns-based vrfs\n");
2779 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2780 if (!(zvrf
= vrf
->info
))
2782 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2785 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2786 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2787 vty_out(vty
, "inactive");
2788 else if (zvrf_ns_name(zvrf
))
2789 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2790 zvrf_ns_name(zvrf
));
2792 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2794 if (vrf_is_user_cfged(vrf
))
2795 vty_out(vty
, " (configured)");
2802 DEFPY (evpn_mh_mac_holdtime
,
2803 evpn_mh_mac_holdtime_cmd
,
2804 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2809 "Duration in seconds\n")
2811 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2815 DEFPY (evpn_mh_neigh_holdtime
,
2816 evpn_mh_neigh_holdtime_cmd
,
2817 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2821 "Neighbor entry hold time\n"
2822 "Duration in seconds\n")
2825 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2829 DEFPY (evpn_mh_startup_delay
,
2830 evpn_mh_startup_delay_cmd
,
2831 "[no] evpn mh startup-delay(0-3600)$duration",
2836 "duration in seconds\n")
2839 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2843 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2844 "[no$no] evpn mh redirect-off",
2848 "ES bond redirect for fast-failover off\n")
2852 redirect_off
= no
? false : true;
2854 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2857 DEFUN (default_vrf_vni_mapping
,
2858 default_vrf_vni_mapping_cmd
,
2859 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2860 "VNI corresponding to the DEFAULT VRF\n"
2862 "Prefix routes only \n")
2864 char xpath
[XPATH_MAXLEN
];
2865 struct zebra_vrf
*zvrf
= NULL
;
2868 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2875 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2877 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2879 snprintf(xpath
, sizeof(xpath
),
2880 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2882 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2885 snprintf(xpath
, sizeof(xpath
),
2886 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2888 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2891 return nb_cli_apply_changes(vty
, NULL
);
2894 DEFUN (no_default_vrf_vni_mapping
,
2895 no_default_vrf_vni_mapping_cmd
,
2896 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2898 "VNI corresponding to DEFAULT VRF\n"
2900 "Prefix routes only \n")
2902 char xpath
[XPATH_MAXLEN
];
2904 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2905 struct zebra_vrf
*zvrf
= NULL
;
2907 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2914 if (zvrf
->l3vni
!= vni
) {
2915 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2920 snprintf(xpath
, sizeof(xpath
),
2921 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2923 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2926 snprintf(xpath
, sizeof(xpath
),
2927 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2929 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2932 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2934 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2936 return nb_cli_apply_changes(vty
, NULL
);
2939 DEFUN (vrf_vni_mapping
,
2940 vrf_vni_mapping_cmd
,
2941 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2942 "VNI corresponding to tenant VRF\n"
2944 "prefix-routes-only\n")
2948 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2956 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2957 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2961 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2962 NB_OP_MODIFY
, "true");
2964 return nb_cli_apply_changes(vty
, NULL
);
2967 DEFUN (no_vrf_vni_mapping
,
2968 no_vrf_vni_mapping_cmd
,
2969 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2971 "VNI corresponding to tenant VRF\n"
2973 "prefix-routes-only\n")
2977 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2978 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2986 if (zvrf
->l3vni
!= vni
) {
2987 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2992 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2996 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2997 NB_OP_DESTROY
, "true");
2999 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
3001 return nb_cli_apply_changes(vty
, NULL
);
3005 DEFUN (show_vrf_vni
,
3007 "show vrf vni [json]",
3014 struct zebra_vrf
*zvrf
;
3015 json_object
*json
= NULL
;
3016 json_object
*json_vrfs
= NULL
;
3017 bool uj
= use_json(argc
, argv
);
3020 json
= json_object_new_object();
3021 json_vrfs
= json_object_new_array();
3025 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
3026 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
3028 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3033 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
3037 json_object_object_add(json
, "vrfs", json_vrfs
);
3038 vty_json(vty
, json
);
3044 DEFUN (show_evpn_global
,
3045 show_evpn_global_cmd
,
3051 bool uj
= use_json(argc
, argv
);
3053 zebra_vxlan_print_evpn(vty
, uj
);
3057 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
3058 SHOW_STR IP_STR
"neighbors\n")
3061 zebra_neigh_show(vty
);
3066 DEFPY(show_evpn_l2_nh
,
3067 show_evpn_l2_nh_cmd
,
3068 "show evpn l2-nh [json$json]",
3076 zebra_evpn_l2_nh_show(vty
, uj
);
3083 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3086 "Ethernet Segment\n"
3088 "Detailed information\n"
3095 if (!str_to_esi(esi_str
, &esi
)) {
3096 vty_out(vty
, "%% Malformed ESI\n");
3099 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3102 zebra_evpn_es_show_detail(vty
, uj
);
3104 zebra_evpn_es_show(vty
, uj
);
3110 DEFPY(show_evpn_es_evi
,
3111 show_evpn_es_evi_cmd
,
3112 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3115 "Ethernet Segment per EVI\n"
3116 "VxLAN Network Identifier\n"
3118 "Detailed information\n"
3125 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3127 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3132 DEFPY(show_evpn_access_vlan
,
3133 show_evpn_access_vlan_cmd
,
3134 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3139 "Detailed information\n"
3145 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3148 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3150 zebra_evpn_acc_vl_show(vty
, uj
);
3156 DEFUN (show_evpn_vni
,
3158 "show evpn vni [json]",
3161 "VxLAN Network Identifier\n"
3164 struct zebra_vrf
*zvrf
;
3165 bool uj
= use_json(argc
, argv
);
3167 zvrf
= zebra_vrf_get_evpn();
3168 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3172 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3173 "show evpn vni detail [json]",
3176 "VxLAN Network Identifier\n"
3177 "Detailed Information On Each VNI\n"
3180 struct zebra_vrf
*zvrf
;
3181 bool uj
= use_json(argc
, argv
);
3183 zvrf
= zebra_vrf_get_evpn();
3184 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3188 DEFUN (show_evpn_vni_vni
,
3189 show_evpn_vni_vni_cmd
,
3190 "show evpn vni " CMD_VNI_RANGE
"[json]",
3193 "VxLAN Network Identifier\n"
3197 struct zebra_vrf
*zvrf
;
3199 bool uj
= use_json(argc
, argv
);
3201 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3202 zvrf
= zebra_vrf_get_evpn();
3203 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3207 DEFUN (show_evpn_rmac_vni_mac
,
3208 show_evpn_rmac_vni_mac_cmd
,
3209 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3216 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3221 bool uj
= use_json(argc
, argv
);
3223 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3224 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3225 vty_out(vty
, "%% Malformed MAC address\n");
3228 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3232 DEFUN (show_evpn_rmac_vni
,
3233 show_evpn_rmac_vni_cmd
,
3234 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3243 bool uj
= use_json(argc
, argv
);
3245 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3246 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3251 DEFUN (show_evpn_rmac_vni_all
,
3252 show_evpn_rmac_vni_all_cmd
,
3253 "show evpn rmac vni all [json]",
3261 bool uj
= use_json(argc
, argv
);
3263 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3268 DEFUN (show_evpn_nh_vni_ip
,
3269 show_evpn_nh_vni_ip_cmd
,
3270 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3277 "Host address (ipv4 or ipv6)\n"
3282 bool uj
= use_json(argc
, argv
);
3284 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3285 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3287 vty_out(vty
, "%% Malformed Neighbor address\n");
3290 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3295 DEFUN (show_evpn_nh_vni
,
3296 show_evpn_nh_vni_cmd
,
3297 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3306 bool uj
= use_json(argc
, argv
);
3308 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3309 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3314 DEFUN (show_evpn_nh_vni_all
,
3315 show_evpn_nh_vni_all_cmd
,
3316 "show evpn next-hops vni all [json]",
3324 bool uj
= use_json(argc
, argv
);
3326 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3331 DEFUN (show_evpn_mac_vni
,
3332 show_evpn_mac_vni_cmd
,
3333 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3337 "VxLAN Network Identifier\n"
3341 struct zebra_vrf
*zvrf
;
3343 bool uj
= use_json(argc
, argv
);
3345 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3346 zvrf
= zebra_vrf_get_evpn();
3347 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3351 DEFUN (show_evpn_mac_vni_all
,
3352 show_evpn_mac_vni_all_cmd
,
3353 "show evpn mac vni all [json]",
3357 "VxLAN Network Identifier\n"
3361 struct zebra_vrf
*zvrf
;
3362 bool uj
= use_json(argc
, argv
);
3364 zvrf
= zebra_vrf_get_evpn();
3365 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3369 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3370 "show evpn mac vni all detail [json]",
3374 "VxLAN Network Identifier\n"
3376 "Detailed Information On Each VNI MAC\n"
3379 struct zebra_vrf
*zvrf
;
3380 bool uj
= use_json(argc
, argv
);
3382 zvrf
= zebra_vrf_get_evpn();
3383 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3387 DEFUN (show_evpn_mac_vni_all_vtep
,
3388 show_evpn_mac_vni_all_vtep_cmd
,
3389 "show evpn mac vni all vtep A.B.C.D [json]",
3393 "VxLAN Network Identifier\n"
3396 "Remote VTEP IP address\n"
3399 struct zebra_vrf
*zvrf
;
3400 struct in_addr vtep_ip
;
3401 bool uj
= use_json(argc
, argv
);
3403 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3405 vty_out(vty
, "%% Malformed VTEP IP address\n");
3408 zvrf
= zebra_vrf_get_evpn();
3409 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3415 DEFUN (show_evpn_mac_vni_mac
,
3416 show_evpn_mac_vni_mac_cmd
,
3417 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3421 "VxLAN Network Identifier\n"
3424 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3428 struct zebra_vrf
*zvrf
;
3431 bool uj
= use_json(argc
, argv
);
3433 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3434 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3435 vty_out(vty
, "%% Malformed MAC address\n");
3438 zvrf
= zebra_vrf_get_evpn();
3439 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3443 DEFUN (show_evpn_mac_vni_vtep
,
3444 show_evpn_mac_vni_vtep_cmd
,
3445 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3449 "VxLAN Network Identifier\n"
3452 "Remote VTEP IP address\n"
3455 struct zebra_vrf
*zvrf
;
3457 struct in_addr vtep_ip
;
3458 bool uj
= use_json(argc
, argv
);
3460 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3461 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3463 vty_out(vty
, "%% Malformed VTEP IP address\n");
3467 zvrf
= zebra_vrf_get_evpn();
3468 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3472 DEFPY (show_evpn_mac_vni_all_dad
,
3473 show_evpn_mac_vni_all_dad_cmd
,
3474 "show evpn mac vni all duplicate [json]",
3478 "VxLAN Network Identifier\n"
3480 "Duplicate address list\n"
3483 struct zebra_vrf
*zvrf
;
3484 bool uj
= use_json(argc
, argv
);
3486 zvrf
= zebra_vrf_get_evpn();
3487 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3492 DEFPY (show_evpn_mac_vni_dad
,
3493 show_evpn_mac_vni_dad_cmd
,
3494 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3498 "VxLAN Network Identifier\n"
3500 "Duplicate address list\n"
3503 struct zebra_vrf
*zvrf
;
3504 bool uj
= use_json(argc
, argv
);
3506 zvrf
= zebra_vrf_get_evpn();
3508 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3513 DEFPY (show_evpn_neigh_vni_dad
,
3514 show_evpn_neigh_vni_dad_cmd
,
3515 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3518 "ARP and ND cache\n"
3519 "VxLAN Network Identifier\n"
3521 "Duplicate address list\n"
3524 struct zebra_vrf
*zvrf
;
3525 bool uj
= use_json(argc
, argv
);
3527 zvrf
= zebra_vrf_get_evpn();
3528 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3532 DEFPY (show_evpn_neigh_vni_all_dad
,
3533 show_evpn_neigh_vni_all_dad_cmd
,
3534 "show evpn arp-cache vni all duplicate [json]",
3537 "ARP and ND cache\n"
3538 "VxLAN Network Identifier\n"
3540 "Duplicate address list\n"
3543 struct zebra_vrf
*zvrf
;
3544 bool uj
= use_json(argc
, argv
);
3546 zvrf
= zebra_vrf_get_evpn();
3547 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3552 DEFUN (show_evpn_neigh_vni
,
3553 show_evpn_neigh_vni_cmd
,
3554 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3557 "ARP and ND cache\n"
3558 "VxLAN Network Identifier\n"
3562 struct zebra_vrf
*zvrf
;
3564 bool uj
= use_json(argc
, argv
);
3566 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3567 zvrf
= zebra_vrf_get_evpn();
3568 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3572 DEFUN (show_evpn_neigh_vni_all
,
3573 show_evpn_neigh_vni_all_cmd
,
3574 "show evpn arp-cache vni all [json]",
3577 "ARP and ND cache\n"
3578 "VxLAN Network Identifier\n"
3582 struct zebra_vrf
*zvrf
;
3583 bool uj
= use_json(argc
, argv
);
3585 zvrf
= zebra_vrf_get_evpn();
3586 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3590 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3591 "show evpn arp-cache vni all detail [json]",
3594 "ARP and ND cache\n"
3595 "VxLAN Network Identifier\n"
3597 "Neighbor details for all vnis in detail\n" JSON_STR
)
3599 struct zebra_vrf
*zvrf
;
3600 bool uj
= use_json(argc
, argv
);
3602 zvrf
= zebra_vrf_get_evpn();
3603 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3607 DEFUN (show_evpn_neigh_vni_neigh
,
3608 show_evpn_neigh_vni_neigh_cmd
,
3609 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3612 "ARP and ND cache\n"
3613 "VxLAN Network Identifier\n"
3616 "Neighbor address (IPv4 or IPv6 address)\n"
3619 struct zebra_vrf
*zvrf
;
3622 bool uj
= use_json(argc
, argv
);
3624 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3625 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3627 vty_out(vty
, "%% Malformed Neighbor address\n");
3630 zvrf
= zebra_vrf_get_evpn();
3631 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3635 DEFUN (show_evpn_neigh_vni_vtep
,
3636 show_evpn_neigh_vni_vtep_cmd
,
3637 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3640 "ARP and ND cache\n"
3641 "VxLAN Network Identifier\n"
3644 "Remote VTEP IP address\n"
3647 struct zebra_vrf
*zvrf
;
3649 struct in_addr vtep_ip
;
3650 bool uj
= use_json(argc
, argv
);
3652 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3653 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3655 vty_out(vty
, "%% Malformed VTEP IP address\n");
3659 zvrf
= zebra_vrf_get_evpn();
3660 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3664 /* policy routing contexts */
3665 DEFUN (show_pbr_ipset
,
3667 "show pbr ipset [WORD]",
3669 "Policy-Based Routing\n"
3670 "IPset Context information\n"
3671 "IPset Name information\n")
3675 found
= argv_find(argv
, argc
, "WORD", &idx
);
3677 zebra_pbr_show_ipset_list(vty
, NULL
);
3679 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3683 /* policy routing contexts */
3684 DEFUN (show_pbr_iptable
,
3685 show_pbr_iptable_cmd
,
3686 "show pbr iptable [WORD]",
3688 "Policy-Based Routing\n"
3689 "IPtable Context information\n"
3690 "IPtable Name information\n")
3695 found
= argv_find(argv
, argc
, "WORD", &idx
);
3697 zebra_pbr_show_iptable(vty
, NULL
);
3699 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3703 /* policy routing contexts */
3704 DEFPY (show_pbr_rule
,
3708 "Policy-Based Routing\n"
3711 zebra_pbr_show_rule(vty
);
3715 DEFPY (pbr_nexthop_resolve
,
3716 pbr_nexthop_resolve_cmd
,
3717 "[no$no] pbr nexthop-resolve",
3719 "Policy Based Routing\n"
3720 "Resolve nexthop for dataplane programming\n")
3722 zebra_pbr_expand_action_update(!no
);
3726 DEFPY (clear_evpn_dup_addr
,
3727 clear_evpn_dup_addr_cmd
,
3728 "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>]>",
3731 "Duplicate address \n"
3732 "VxLAN Network Identifier\n"
3736 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3741 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3742 int ret
= CMD_SUCCESS
;
3744 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3745 *yang_dup_mac
= NULL
;
3750 yang_dup
= yang_data_new(
3751 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3754 yang_dup
= yang_data_new_uint32(
3755 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3757 if (!is_zero_mac(&mac
->eth_addr
)) {
3758 yang_dup_mac
= yang_data_new_mac(
3759 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3762 listnode_add(input
, yang_dup_mac
);
3764 if (sockunion_family(ip
) == AF_INET
) {
3765 host_ip
.ipa_type
= IPADDR_V4
;
3766 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3768 host_ip
.ipa_type
= IPADDR_V6
;
3769 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3770 sizeof(struct in6_addr
));
3773 yang_dup_ip
= yang_data_new_ip(
3774 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3778 listnode_add(input
, yang_dup_ip
);
3783 listnode_add(input
, yang_dup
);
3784 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3788 list_delete(&input
);
3793 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3794 evpn_accept_bgp_seq_cmd
,
3795 "evpn accept-bgp-seq",
3797 "Accept all sequence numbers from BGP\n")
3799 zebra_vxlan_set_accept_bgp_seq(true);
3803 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3804 no_evpn_accept_bgp_seq_cmd
,
3805 "no evpn accept-bgp-seq",
3808 "Accept all sequence numbers from BGP\n")
3810 zebra_vxlan_set_accept_bgp_seq(false);
3814 /* Static ip route configuration write function. */
3815 static int zebra_ip_config(struct vty
*vty
)
3819 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3824 DEFUN (ip_zebra_import_table_distance
,
3825 ip_zebra_import_table_distance_cmd
,
3826 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3828 "import routes from non-main kernel table\n"
3829 "kernel routing table id\n"
3830 "Distance for imported routes\n"
3831 "Default distance value\n"
3832 "route-map for filtering\n"
3835 uint32_t table_id
= 0;
3837 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3838 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3840 strmatch(argv
[argc
- 2]->text
, "route-map")
3841 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3845 if (argc
== 7 || (argc
== 5 && !rmap
))
3846 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3848 if (!is_zebra_valid_kernel_table(table_id
)) {
3850 "Invalid routing table ID, %d. Must be in range 1-252\n",
3853 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3857 if (is_zebra_main_routing_table(table_id
)) {
3859 "Invalid routing table ID, %d. Must be non-default table\n",
3862 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3866 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3869 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3874 DEFUN_HIDDEN (zebra_packet_process
,
3875 zebra_packet_process_cmd
,
3876 "zebra zapi-packets (1-10000)",
3879 "Number of packets to process before relinquishing thread\n")
3881 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3883 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3884 memory_order_relaxed
);
3889 DEFUN_HIDDEN (no_zebra_packet_process
,
3890 no_zebra_packet_process_cmd
,
3891 "no zebra zapi-packets [(1-10000)]",
3895 "Number of packets to process before relinquishing thread\n")
3897 atomic_store_explicit(&zrouter
.packets_to_process
,
3898 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3899 memory_order_relaxed
);
3904 DEFUN_HIDDEN (zebra_workqueue_timer
,
3905 zebra_workqueue_timer_cmd
,
3906 "zebra work-queue (0-10000)",
3909 "Time in milliseconds\n")
3911 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3912 zrouter
.ribq
->spec
.hold
= timer
;
3917 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3918 no_zebra_workqueue_timer_cmd
,
3919 "no zebra work-queue [(0-10000)]",
3923 "Time in milliseconds\n")
3925 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3930 DEFUN (no_ip_zebra_import_table
,
3931 no_ip_zebra_import_table_cmd
,
3932 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3935 "import routes from non-main kernel table\n"
3936 "kernel routing table id\n"
3937 "Distance for imported routes\n"
3938 "Default distance value\n"
3939 "route-map for filtering\n"
3942 uint32_t table_id
= 0;
3943 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3945 if (!is_zebra_valid_kernel_table(table_id
)) {
3947 "Invalid routing table ID. Must be in range 1-252\n");
3951 if (is_zebra_main_routing_table(table_id
)) {
3953 "Invalid routing table ID, %d. Must be non-default table\n",
3958 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3961 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3964 DEFPY (zebra_nexthop_group_keep
,
3965 zebra_nexthop_group_keep_cmd
,
3966 "[no] zebra nexthop-group keep (1-3600)",
3970 "How long to keep\n"
3971 "Time in seconds from 1-3600\n")
3974 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3976 zrouter
.nhg_keep
= keep
;
3981 static int config_write_protocol(struct vty
*vty
)
3983 if (zrouter
.allow_delete
)
3984 vty_out(vty
, "allow-external-route-update\n");
3986 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3987 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3989 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3990 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3992 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3993 vty_out(vty
, "zebra zapi-packets %u\n",
3994 zrouter
.packets_to_process
);
3996 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3998 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3999 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
4000 ipv4_multicast_mode
== MCAST_URIB_ONLY
4002 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
4004 : ipv4_multicast_mode
4005 == MCAST_MIX_MRIB_FIRST
4007 : ipv4_multicast_mode
4008 == MCAST_MIX_DISTANCE
4012 /* Include dataplane info */
4013 dplane_config_write_helper(vty
);
4015 zebra_evpn_mh_config_write(vty
);
4017 zebra_pbr_config_write(vty
);
4019 if (!zebra_vxlan_get_accept_bgp_seq())
4020 vty_out(vty
, "no evpn accept-bgp-seq\n");
4022 /* Include nexthop-group config */
4023 if (!zebra_nhg_kernel_nexthops_enabled())
4024 vty_out(vty
, "no zebra nexthop kernel enable\n");
4026 if (zebra_nhg_proto_nexthops_only())
4027 vty_out(vty
, "zebra nexthop proto only\n");
4029 if (!zebra_nhg_recursive_use_backups())
4030 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
4032 if (rnh_get_hide_backups())
4033 vty_out(vty
, "ip nht hide-backup-events\n");
4036 /* Include netlink info */
4037 netlink_config_write_helper(vty
);
4038 #endif /* HAVE_NETLINK */
4050 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4053 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4054 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4055 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4056 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4057 ttable_add_row(table
, "v6 Forwarding|%s",
4058 ipforward_ipv6() ? "On" : "Off");
4059 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4060 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4061 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4065 if (!vrf_is_backend_netns())
4066 ttable_add_row(table
, "VRF|l3mdev Available");
4068 ttable_add_row(table
, "VRF|Namespaces");
4070 ttable_add_row(table
, "VRF|Not Available");
4073 ttable_add_row(table
, "ASIC offload|%s",
4074 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4077 * Do not display this unless someone is actually using it
4079 * Why this distinction? I think this is effectively dead code
4080 * and should not be exposed. Maybe someone proves me wrong.
4082 if (zrouter
.asic_notification_nexthop_control
)
4083 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4085 ttable_add_row(table
, "RA|%s",
4086 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4087 ttable_add_row(table
, "RFC 5549|%s",
4088 rtadv_get_interfaces_configured_from_bgp()
4090 : "BGP is not using");
4092 ttable_add_row(table
, "Kernel NHG|%s",
4093 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4095 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4096 zrouter
.allow_delete
? "Yes" : "No");
4097 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4098 zrouter
.all_linkdownv4
? "On" : "Off");
4099 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4100 zrouter
.default_linkdownv4
? "On" : "Off");
4101 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4102 zrouter
.all_linkdownv6
? "On" : "Off");
4103 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4104 zrouter
.default_linkdownv6
? "On" : "Off");
4106 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4107 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4108 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4109 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4110 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4111 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4112 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4113 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4115 out
= ttable_dump(table
, "\n");
4116 vty_out(vty
, "%s\n", out
);
4117 XFREE(MTYPE_TMP
, out
);
4121 " Route Route Neighbor LSP LSP\n");
4123 "VRF Installs Removals Updates Installs Removals\n");
4125 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4126 struct zebra_vrf
*zvrf
= vrf
->info
;
4128 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4129 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4130 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4131 zvrf
->lsp_removals
);
4137 DEFUN (ip_forwarding
,
4141 "Turn on IP forwarding\n")
4147 ret
= ipforward_on();
4150 vty_out(vty
, "Can't turn on IP forwarding\n");
4151 return CMD_WARNING_CONFIG_FAILED
;
4157 DEFUN (no_ip_forwarding
,
4158 no_ip_forwarding_cmd
,
4162 "Turn off IP forwarding\n")
4168 ret
= ipforward_off();
4171 vty_out(vty
, "Can't turn off IP forwarding\n");
4172 return CMD_WARNING_CONFIG_FAILED
;
4178 /* Only display ip forwarding is enabled or not. */
4179 DEFUN (show_ip_forwarding
,
4180 show_ip_forwarding_cmd
,
4181 "show ip forwarding",
4184 "IP forwarding status\n")
4191 vty_out(vty
, "IP forwarding is off\n");
4193 vty_out(vty
, "IP forwarding is on\n");
4197 /* Only display ipv6 forwarding is enabled or not. */
4198 DEFUN (show_ipv6_forwarding
,
4199 show_ipv6_forwarding_cmd
,
4200 "show ipv6 forwarding",
4202 "IPv6 information\n"
4203 "Forwarding status\n")
4207 ret
= ipforward_ipv6();
4211 vty_out(vty
, "ipv6 forwarding is unknown\n");
4214 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4217 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4220 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4226 DEFUN (ipv6_forwarding
,
4227 ipv6_forwarding_cmd
,
4230 "Turn on IPv6 forwarding\n")
4234 ret
= ipforward_ipv6();
4236 ret
= ipforward_ipv6_on();
4239 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4240 return CMD_WARNING_CONFIG_FAILED
;
4246 DEFUN (no_ipv6_forwarding
,
4247 no_ipv6_forwarding_cmd
,
4248 "no ipv6 forwarding",
4251 "Turn off IPv6 forwarding\n")
4255 ret
= ipforward_ipv6();
4257 ret
= ipforward_ipv6_off();
4260 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4261 return CMD_WARNING_CONFIG_FAILED
;
4267 /* Display dataplane info */
4268 DEFUN (show_dataplane
,
4270 "show zebra dplane [detailed]",
4273 "Zebra dataplane information\n"
4274 "Detailed output\n")
4277 bool detailed
= false;
4279 if (argv_find(argv
, argc
, "detailed", &idx
))
4282 return dplane_show_helper(vty
, detailed
);
4285 /* Display dataplane providers info */
4286 DEFUN (show_dataplane_providers
,
4287 show_dataplane_providers_cmd
,
4288 "show zebra dplane providers [detailed]",
4291 "Zebra dataplane information\n"
4292 "Zebra dataplane provider information\n"
4293 "Detailed output\n")
4296 bool detailed
= false;
4298 if (argv_find(argv
, argc
, "detailed", &idx
))
4301 return dplane_show_provs_helper(vty
, detailed
);
4304 /* Configure dataplane incoming queue limit */
4305 DEFUN (zebra_dplane_queue_limit
,
4306 zebra_dplane_queue_limit_cmd
,
4307 "zebra dplane limit (0-10000)",
4310 "Limit incoming queued updates\n"
4311 "Number of queued updates\n")
4315 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4317 dplane_set_in_queue_limit(limit
, true);
4322 /* Reset dataplane queue limit to default value */
4323 DEFUN (no_zebra_dplane_queue_limit
,
4324 no_zebra_dplane_queue_limit_cmd
,
4325 "no zebra dplane limit [(0-10000)]",
4329 "Limit incoming queued updates\n"
4330 "Number of queued updates\n")
4332 dplane_set_in_queue_limit(0, false);
4337 DEFUN (zebra_show_routing_tables_summary
,
4338 zebra_show_routing_tables_summary_cmd
,
4339 "show zebra router table summary",
4342 "The Zebra Router Information\n"
4343 "Table Information about this Zebra Router\n"
4344 "Summary Information\n")
4346 zebra_router_show_table_summary(vty
);
4351 /* Table configuration write function. */
4352 static int config_write_table(struct vty
*vty
)
4357 /* IPForwarding configuration write function. */
4358 static int config_write_forwarding(struct vty
*vty
)
4361 vty_out(vty
, "no ip forwarding\n");
4362 if (!ipforward_ipv6())
4363 vty_out(vty
, "no ipv6 forwarding\n");
4364 vty_out(vty
, "!\n");
4368 DEFUN_HIDDEN (show_frr
,
4374 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4375 vty_out(vty
, ".............................7777:..............................................\n");
4376 vty_out(vty
, ".............................777777,............................................\n");
4377 vty_out(vty
, "... .........................77777777,..........................................\n");
4378 vty_out(vty
, "............................=7777777777:........................................\n");
4379 vty_out(vty
, "........................:7777777777777777,......................................\n");
4380 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4381 vty_out(vty
, "...................I7777777777+.................................................\n");
4382 vty_out(vty
, "................,777777777?............ .......................................\n");
4383 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4384 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4385 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4386 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4387 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4388 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4389 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4390 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4391 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4392 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4393 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4394 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4395 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4396 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4397 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4398 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4399 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4400 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4401 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4402 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4403 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4404 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4405 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4406 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4407 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4408 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4409 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4410 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4411 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4412 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4413 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4414 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4415 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4416 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4417 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4418 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4419 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4420 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4421 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4422 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4423 vty_out(vty
, "................................~77777777...............=777777.................\n");
4424 vty_out(vty
, ".....................................:=?I................~777777................\n");
4425 vty_out(vty
, "..........................................................:777777,..............\n");
4426 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4432 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4433 zebra_kernel_netlink_batch_tx_buf_cmd
,
4434 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4436 "Zebra kernel interface\n"
4437 "Set Netlink parameters\n"
4438 "Set batch buffer size and send threshold\n"
4439 "Size of the buffer\n"
4442 uint32_t bufsize
= 0, threshold
= 0;
4444 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4445 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4447 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4452 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4453 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4454 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4456 "Zebra kernel interface\n"
4457 "Set Netlink parameters\n"
4458 "Set batch buffer size and send threshold\n"
4459 "Size of the buffer\n"
4462 netlink_set_batch_buffer_size(0, 0, false);
4467 DEFPY (zebra_protodown_bit
,
4468 zebra_protodown_bit_cmd
,
4469 "zebra protodown reason-bit (0-31)$bit",
4471 "Protodown Configuration\n"
4472 "Reason Bit used in the kernel for application\n"
4473 "Reason Bit range\n")
4475 if_netlink_set_frr_protodown_r_bit(bit
);
4479 DEFPY (no_zebra_protodown_bit
,
4480 no_zebra_protodown_bit_cmd
,
4481 "no zebra protodown reason-bit [(0-31)$bit]",
4484 "Protodown Configuration\n"
4485 "Reason Bit used in the kernel for setting protodown\n"
4486 "Reason Bit Range\n")
4488 if_netlink_unset_frr_protodown_r_bit();
4492 #endif /* HAVE_NETLINK */
4494 DEFUN(ip_table_range
, ip_table_range_cmd
,
4495 "[no] ip table range (1-4294967295) (1-4294967295)",
4497 "table configuration\n"
4498 "Configure table range\n"
4499 "Start Routing Table\n"
4500 "End Routing Table\n")
4502 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4507 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4509 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4513 if (strmatch(argv
[0]->text
, "no"))
4514 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4516 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4519 #ifdef HAVE_SCRIPTING
4521 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4522 "zebra on-rib-process script SCRIPT",
4524 "on_rib_process_dplane_results hook call\n"
4526 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4529 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4532 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4533 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4535 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4536 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4541 #endif /* HAVE_SCRIPTING */
4543 /* IP node for static routes. */
4544 static int zebra_ip_config(struct vty
*vty
);
4545 static struct cmd_node ip_node
= {
4546 .name
= "static ip",
4549 .config_write
= zebra_ip_config
,
4551 static int config_write_protocol(struct vty
*vty
);
4552 static struct cmd_node protocol_node
= {
4554 .node
= PROTOCOL_NODE
,
4556 .config_write
= config_write_protocol
,
4558 /* table node for routing tables. */
4559 static int config_write_table(struct vty
*vty
);
4560 static struct cmd_node table_node
= {
4564 .config_write
= config_write_table
,
4566 static int config_write_forwarding(struct vty
*vty
);
4567 static struct cmd_node forwarding_node
= {
4568 .name
= "forwarding",
4569 .node
= FORWARDING_NODE
,
4571 .config_write
= config_write_forwarding
,
4575 void zebra_vty_init(void)
4577 /* Install configuration write function. */
4578 install_node(&table_node
);
4579 install_node(&forwarding_node
);
4581 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4582 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4583 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4584 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4586 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4587 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4588 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4591 zebra_route_map_init();
4593 install_node(&ip_node
);
4594 install_node(&protocol_node
);
4596 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4597 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4599 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4600 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4602 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4603 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4604 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4605 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4606 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4607 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4608 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4609 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4610 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4611 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4613 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4614 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4616 install_element(VIEW_NODE
, &show_vrf_cmd
);
4617 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4618 install_element(VIEW_NODE
, &show_route_cmd
);
4619 install_element(VIEW_NODE
, &show_ro_cmd
);
4620 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4621 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4622 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4624 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4625 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4627 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4628 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4629 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4630 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4631 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4632 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4633 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4634 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4635 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4637 install_element(VIEW_NODE
, &show_frr_cmd
);
4638 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4639 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4640 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4641 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4642 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4643 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4644 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4645 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4646 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4647 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4648 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4649 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4650 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4651 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4652 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4653 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4654 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4655 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4656 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4657 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4658 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4659 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4660 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4661 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4662 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4663 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4664 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4665 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4666 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4667 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4668 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4669 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4671 install_element(VIEW_NODE
, &show_neigh_cmd
);
4673 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4674 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4675 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4676 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4677 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4679 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4680 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4681 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4682 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4683 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4684 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4685 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4686 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4688 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4689 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4690 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4691 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4693 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4694 install_element(VRF_NODE
, &ip_table_range_cmd
);
4697 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4698 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4699 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4700 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4701 #endif /* HAVE_NETLINK */
4703 #ifdef HAVE_SCRIPTING
4704 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4705 #endif /* HAVE_SCRIPTING */
4707 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);