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
))
231 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
232 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
238 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
245 * Show backup nexthop info, in the 'detailed' output path
247 static void show_nh_backup_helper(struct vty
*vty
,
248 const struct route_entry
*re
,
249 const struct nexthop
*nexthop
)
251 const struct nexthop
*start
, *backup
, *temp
;
254 /* Double-check that there _is_ a backup */
255 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
256 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
257 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
260 /* Locate the backup nexthop(s) */
261 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
262 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
263 /* Format the backup(s) (indented) */
265 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
266 backup
= backup
->next
;
271 /* It's possible for backups to be recursive too,
272 * so walk the recursive resolution list if present.
277 show_nexthop_detail_helper(vty
, re
, backup
,
281 if (backup
->resolved
&& temp
== backup
)
282 backup
= backup
->resolved
;
284 backup
= nexthop_next(backup
);
286 if (backup
== temp
->next
)
294 * Helper api to format output for a nexthop, used in the 'detailed'
297 static void show_nexthop_detail_helper(struct vty
*vty
,
298 const struct route_entry
*re
,
299 const struct nexthop
*nexthop
,
303 char buf
[MPLS_LABEL_STRLEN
];
308 nexthop
->rparent
? " " : "");
310 vty_out(vty
, " %c%s",
311 re_status_output_char(re
, nexthop
, false),
312 nexthop
->rparent
? " " : "");
314 switch (nexthop
->type
) {
315 case NEXTHOP_TYPE_IPV4
:
316 case NEXTHOP_TYPE_IPV4_IFINDEX
:
317 vty_out(vty
, " %pI4",
318 &nexthop
->gate
.ipv4
);
319 if (nexthop
->ifindex
)
320 vty_out(vty
, ", via %s",
325 case NEXTHOP_TYPE_IPV6
:
326 case NEXTHOP_TYPE_IPV6_IFINDEX
:
328 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
330 if (nexthop
->ifindex
)
331 vty_out(vty
, ", via %s",
337 case NEXTHOP_TYPE_IFINDEX
:
338 vty_out(vty
, " directly connected, %s",
339 ifindex2ifname(nexthop
->ifindex
,
342 case NEXTHOP_TYPE_BLACKHOLE
:
343 vty_out(vty
, " unreachable");
344 switch (nexthop
->bh_type
) {
345 case BLACKHOLE_REJECT
:
346 vty_out(vty
, " (ICMP unreachable)");
348 case BLACKHOLE_ADMINPROHIB
:
350 " (ICMP admin-prohibited)");
353 vty_out(vty
, " (blackhole)");
355 case BLACKHOLE_UNSPEC
:
361 if (re
->vrf_id
!= nexthop
->vrf_id
) {
362 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
364 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
367 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
368 vty_out(vty
, " (duplicate nexthop removed)");
370 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
371 vty_out(vty
, " inactive");
373 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
374 vty_out(vty
, " onlink");
376 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
377 vty_out(vty
, " linkdown");
379 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
380 vty_out(vty
, " (recursive)");
382 /* Source specified? */
383 switch (nexthop
->type
) {
384 case NEXTHOP_TYPE_IPV4
:
385 case NEXTHOP_TYPE_IPV4_IFINDEX
:
386 if (nexthop
->src
.ipv4
.s_addr
) {
387 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
388 addrstr
, sizeof(addrstr
)))
389 vty_out(vty
, ", src %s",
394 case NEXTHOP_TYPE_IPV6
:
395 case NEXTHOP_TYPE_IPV6_IFINDEX
:
396 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
398 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
399 addrstr
, sizeof(addrstr
)))
400 vty_out(vty
, ", src %s",
410 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
412 /* Label information */
413 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
414 vty_out(vty
, ", label %s",
415 mpls_label2str(nexthop
->nh_label
->num_labels
,
416 nexthop
->nh_label
->label
, buf
,
417 sizeof(buf
), 1 /*pretty*/));
421 vty_out(vty
, ", weight %u", nexthop
->weight
);
423 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
424 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
426 for (i
= 1; i
< nexthop
->backup_num
; i
++)
427 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
431 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
432 struct json_object
*json
)
434 struct bgp_zebra_opaque bzo
= {};
435 struct ospf_zebra_opaque ozo
= {};
441 case ZEBRA_ROUTE_SHARP
:
443 json_object_string_add(json
, "opaque",
444 (char *)re
->opaque
->data
);
446 vty_out(vty
, " Opaque Data: %s",
447 (char *)re
->opaque
->data
);
450 case ZEBRA_ROUTE_BGP
:
451 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
454 json_object_string_add(json
, "asPath", bzo
.aspath
);
455 json_object_string_add(json
, "communities",
457 json_object_string_add(json
, "largeCommunities",
459 json_object_string_add(json
, "selectionReason",
460 bzo
.selection_reason
);
462 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
464 if (bzo
.community
[0] != '\0')
465 vty_out(vty
, " Communities : %s\n",
468 if (bzo
.lcommunity
[0] != '\0')
469 vty_out(vty
, " Large-Communities: %s\n",
472 vty_out(vty
, " Selection reason : %s\n",
473 bzo
.selection_reason
);
476 case ZEBRA_ROUTE_OSPF
:
477 case ZEBRA_ROUTE_OSPF6
:
478 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
481 json_object_string_add(json
, "ospfPathType",
483 if (ozo
.area_id
[0] != '\0')
484 json_object_string_add(json
, "ospfAreaId",
486 if (ozo
.tag
[0] != '\0')
487 json_object_string_add(json
, "ospfTag",
490 vty_out(vty
, " OSPF path type : %s\n",
492 if (ozo
.area_id
[0] != '\0')
493 vty_out(vty
, " OSPF area ID : %s\n",
495 if (ozo
.tag
[0] != '\0')
496 vty_out(vty
, " OSPF tag : %s\n",
505 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
509 cur
= monotime(NULL
);
512 frrtime_to_interval(cur
, buf
, bufsize
);
515 /* New RIB. Detailed information for IPv4 route. */
516 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
517 int mcast
, bool use_fib
, bool show_ng
)
519 struct route_entry
*re
;
520 struct nexthop
*nexthop
;
521 char buf
[SRCDEST2STR_BUFFER
];
522 struct zebra_vrf
*zvrf
;
525 dest
= rib_dest_from_rnode(rn
);
527 RNODE_FOREACH_RE (rn
, re
) {
529 * If re not selected for forwarding, skip re
530 * for "show ip/ipv6 fib <prefix>"
532 if (use_fib
&& re
!= dest
->selected_fib
)
535 const char *mcast_info
= "";
537 struct rib_table_info
*info
=
538 srcdest_rnode_table_info(rn
);
539 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
540 ? " using Multicast RIB"
541 : " using Unicast RIB";
544 vty_out(vty
, "Routing entry for %s%s\n",
545 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
546 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
548 vty_out(vty
, "[%d]", re
->instance
);
550 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
553 vty_out(vty
, ", tag %u", re
->tag
);
554 #if defined(SUPPORT_REALMS)
555 if (re
->tag
> 0 && re
->tag
<= 255)
556 vty_out(vty
, "(realm)");
560 vty_out(vty
, ", mtu %u", re
->mtu
);
561 if (re
->vrf_id
!= VRF_DEFAULT
) {
562 zvrf
= vrf_info_lookup(re
->vrf_id
);
563 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
565 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
566 vty_out(vty
, ", best");
569 uptime2str(re
->uptime
, buf
, sizeof(buf
));
571 vty_out(vty
, " Last update %s ago\n", buf
);
574 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
575 if (re
->nhe_installed_id
!= 0
576 && re
->nhe_id
!= re
->nhe_installed_id
)
578 " Installed Nexthop Group ID: %u\n",
579 re
->nhe_installed_id
);
582 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
583 /* Use helper to format each nexthop */
584 show_nexthop_detail_helper(vty
, re
, nexthop
,
585 false /*not backup*/);
588 /* Include backup(s), if present */
589 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
590 show_nh_backup_helper(vty
, re
, nexthop
);
592 zebra_show_ip_route_opaque(vty
, re
, NULL
);
599 * Helper for nexthop output, used in the 'show ip route' path
601 static void show_route_nexthop_helper(struct vty
*vty
,
602 const struct route_entry
*re
,
603 const struct nexthop
*nexthop
)
605 char buf
[MPLS_LABEL_STRLEN
];
608 switch (nexthop
->type
) {
609 case NEXTHOP_TYPE_IPV4
:
610 case NEXTHOP_TYPE_IPV4_IFINDEX
:
611 vty_out(vty
, " via %pI4", &nexthop
->gate
.ipv4
);
612 if (nexthop
->ifindex
)
614 ifindex2ifname(nexthop
->ifindex
,
617 case NEXTHOP_TYPE_IPV6
:
618 case NEXTHOP_TYPE_IPV6_IFINDEX
:
619 vty_out(vty
, " via %s",
620 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
622 if (nexthop
->ifindex
)
624 ifindex2ifname(nexthop
->ifindex
,
628 case NEXTHOP_TYPE_IFINDEX
:
629 vty_out(vty
, " is directly connected, %s",
630 ifindex2ifname(nexthop
->ifindex
,
633 case NEXTHOP_TYPE_BLACKHOLE
:
634 vty_out(vty
, " unreachable");
635 switch (nexthop
->bh_type
) {
636 case BLACKHOLE_REJECT
:
637 vty_out(vty
, " (ICMP unreachable)");
639 case BLACKHOLE_ADMINPROHIB
:
640 vty_out(vty
, " (ICMP admin-prohibited)");
643 vty_out(vty
, " (blackhole)");
645 case BLACKHOLE_UNSPEC
:
651 if ((re
== NULL
|| (nexthop
->vrf_id
!= re
->vrf_id
)))
652 vty_out(vty
, " (vrf %s)", vrf_id_to_name(nexthop
->vrf_id
));
654 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
655 vty_out(vty
, " inactive");
657 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
658 vty_out(vty
, " onlink");
660 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
661 vty_out(vty
, " linkdown");
663 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
664 vty_out(vty
, " (recursive)");
666 switch (nexthop
->type
) {
667 case NEXTHOP_TYPE_IPV4
:
668 case NEXTHOP_TYPE_IPV4_IFINDEX
:
669 if (nexthop
->src
.ipv4
.s_addr
) {
670 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
672 vty_out(vty
, ", src %s", buf
);
673 /* SR-TE information */
674 if (nexthop
->srte_color
)
675 vty_out(vty
, ", SR-TE color %u",
676 nexthop
->srte_color
);
679 case NEXTHOP_TYPE_IPV6
:
680 case NEXTHOP_TYPE_IPV6_IFINDEX
:
681 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
682 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
684 vty_out(vty
, ", src %s", buf
);
691 /* Label information */
692 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
693 vty_out(vty
, ", label %s",
694 mpls_label2str(nexthop
->nh_label
->num_labels
,
695 nexthop
->nh_label
->label
, buf
,
699 if (nexthop
->nh_srv6
) {
700 seg6local_context2str(buf
, sizeof(buf
),
701 &nexthop
->nh_srv6
->seg6local_ctx
,
702 nexthop
->nh_srv6
->seg6local_action
);
703 vty_out(vty
, ", seg6local %s %s", seg6local_action2str(
704 nexthop
->nh_srv6
->seg6local_action
), buf
);
706 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
708 vty_out(vty
, ", seg6 %s", buf
);
712 vty_out(vty
, ", weight %u", nexthop
->weight
);
714 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
715 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
717 for (i
= 1; i
< nexthop
->backup_num
; i
++)
718 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
723 * Render a nexthop into a json object; the caller allocates and owns
724 * the json object memory.
726 static void show_nexthop_json_helper(json_object
*json_nexthop
,
727 const struct nexthop
*nexthop
,
728 const struct route_entry
*re
)
730 char buf
[SRCDEST2STR_BUFFER
];
731 json_object
*json_labels
= NULL
;
732 json_object
*json_backups
= NULL
;
733 json_object
*json_seg6local
= NULL
;
734 json_object
*json_seg6
= NULL
;
737 json_object_int_add(json_nexthop
, "flags",
740 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
741 json_object_boolean_true_add(json_nexthop
,
744 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
))
745 json_object_boolean_true_add(json_nexthop
,
748 switch (nexthop
->type
) {
749 case NEXTHOP_TYPE_IPV4
:
750 case NEXTHOP_TYPE_IPV4_IFINDEX
:
751 json_object_string_addf(json_nexthop
, "ip", "%pI4",
752 &nexthop
->gate
.ipv4
);
753 json_object_string_add(json_nexthop
, "afi",
756 if (nexthop
->ifindex
) {
757 json_object_int_add(json_nexthop
,
760 json_object_string_add(
761 json_nexthop
, "interfaceName",
767 case NEXTHOP_TYPE_IPV6
:
768 case NEXTHOP_TYPE_IPV6_IFINDEX
:
769 json_object_string_addf(json_nexthop
, "ip", "%pI6",
770 &nexthop
->gate
.ipv6
);
771 json_object_string_add(json_nexthop
, "afi",
774 if (nexthop
->ifindex
) {
775 json_object_int_add(json_nexthop
,
778 json_object_string_add(
779 json_nexthop
, "interfaceName",
786 case NEXTHOP_TYPE_IFINDEX
:
787 json_object_boolean_true_add(
788 json_nexthop
, "directlyConnected");
789 json_object_int_add(json_nexthop
,
792 json_object_string_add(
793 json_nexthop
, "interfaceName",
794 ifindex2ifname(nexthop
->ifindex
,
797 case NEXTHOP_TYPE_BLACKHOLE
:
798 json_object_boolean_true_add(json_nexthop
,
800 switch (nexthop
->bh_type
) {
801 case BLACKHOLE_REJECT
:
802 json_object_boolean_true_add(
803 json_nexthop
, "reject");
805 case BLACKHOLE_ADMINPROHIB
:
806 json_object_boolean_true_add(
811 json_object_boolean_true_add(
812 json_nexthop
, "blackhole");
814 case BLACKHOLE_UNSPEC
:
820 /* This nexthop is a resolver for the parent nexthop.
821 * Set resolver flag for better clarity and delimiter
822 * in flat list of nexthops in json.
824 if (nexthop
->rparent
)
825 json_object_boolean_true_add(json_nexthop
, "resolver");
827 if (nexthop
->vrf_id
!= re
->vrf_id
)
828 json_object_string_add(json_nexthop
, "vrf",
829 vrf_id_to_name(nexthop
->vrf_id
));
831 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
832 json_object_boolean_true_add(json_nexthop
,
835 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
836 json_object_boolean_true_add(json_nexthop
,
839 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
840 json_object_boolean_true_add(json_nexthop
,
843 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
844 json_object_boolean_true_add(json_nexthop
, "linkDown");
846 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
847 json_object_boolean_true_add(json_nexthop
,
850 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
851 json_backups
= json_object_new_array();
852 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
853 json_object_array_add(
855 json_object_new_int(nexthop
->backup_idx
[i
]));
858 json_object_object_add(json_nexthop
, "backupIndex",
862 switch (nexthop
->type
) {
863 case NEXTHOP_TYPE_IPV4
:
864 case NEXTHOP_TYPE_IPV4_IFINDEX
:
865 if (nexthop
->src
.ipv4
.s_addr
) {
866 if (inet_ntop(AF_INET
,
867 &nexthop
->src
.ipv4
, buf
,
869 json_object_string_add(
870 json_nexthop
, "source",
874 case NEXTHOP_TYPE_IPV6
:
875 case NEXTHOP_TYPE_IPV6_IFINDEX
:
876 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
878 if (inet_ntop(AF_INET6
,
879 &nexthop
->src
.ipv6
, buf
,
881 json_object_string_add(
882 json_nexthop
, "source",
890 if (nexthop
->nh_label
891 && nexthop
->nh_label
->num_labels
) {
892 json_labels
= json_object_new_array();
894 for (int label_index
= 0;
896 < nexthop
->nh_label
->num_labels
;
898 json_object_array_add(
901 nexthop
->nh_label
->label
904 json_object_object_add(json_nexthop
, "labels",
909 json_object_int_add(json_nexthop
, "weight",
912 if (nexthop
->srte_color
)
913 json_object_int_add(json_nexthop
, "srteColor",
914 nexthop
->srte_color
);
916 if (nexthop
->nh_srv6
) {
917 json_seg6local
= json_object_new_object();
918 json_object_string_add(
919 json_seg6local
, "action", seg6local_action2str(
920 nexthop
->nh_srv6
->seg6local_action
));
921 json_object_object_add(json_nexthop
, "seg6local",
924 json_seg6
= json_object_new_object();
925 inet_ntop(AF_INET6
, &nexthop
->nh_srv6
->seg6_segs
, buf
,
927 json_object_string_add(json_seg6
, "segs", buf
);
928 json_object_object_add(json_nexthop
, "seg6", json_seg6
);
932 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
933 struct route_entry
*re
, json_object
*json
,
934 bool is_fib
, bool show_ng
)
936 const struct nexthop
*nexthop
;
938 char buf
[SRCDEST2STR_BUFFER
];
939 json_object
*json_nexthops
= NULL
;
940 json_object
*json_nexthop
= NULL
;
941 json_object
*json_route
= NULL
;
942 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
943 const struct nexthop_group
*nhg
;
944 char up_str
[MONOTIME_STRLEN
];
946 bool nhg_from_backup
= false;
948 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
950 /* If showing fib information, use the fib view of the
954 nhg
= rib_get_fib_nhg(re
);
956 nhg
= &(re
->nhe
->nhg
);
959 json_route
= json_object_new_object();
960 json_nexthops
= json_object_new_array();
962 json_object_string_add(json_route
, "prefix",
963 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
964 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
965 json_object_string_add(json_route
, "protocol",
966 zebra_route_string(re
->type
));
969 json_object_int_add(json_route
, "instance",
972 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
973 json_object_string_add(json_route
, "vrfName",
974 vrf_id_to_name(re
->vrf_id
));
976 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
977 json_object_boolean_true_add(json_route
, "selected");
979 if (dest
->selected_fib
== re
)
980 json_object_boolean_true_add(json_route
,
983 json_object_int_add(json_route
, "distance",
985 json_object_int_add(json_route
, "metric", re
->metric
);
987 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
988 json_object_boolean_true_add(json_route
, "installed");
990 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
991 json_object_boolean_true_add(json_route
, "failed");
993 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
994 json_object_boolean_true_add(json_route
, "queued");
996 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
997 json_object_boolean_true_add(json_route
, "trapped");
999 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
1000 json_object_boolean_true_add(json_route
, "offloaded");
1002 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
1003 json_object_boolean_false_add(json_route
, "offloaded");
1006 json_object_int_add(json_route
, "tag", re
->tag
);
1009 json_object_int_add(json_route
, "table", re
->table
);
1011 json_object_int_add(json_route
, "internalStatus",
1013 json_object_int_add(json_route
, "internalFlags",
1015 json_object_int_add(json_route
, "internalNextHopNum",
1016 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
1017 json_object_int_add(json_route
, "internalNextHopActiveNum",
1018 nexthop_group_active_nexthop_num(
1020 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
1022 if (re
->nhe_installed_id
!= 0)
1023 json_object_int_add(json_route
,
1024 "installedNexthopGroupId",
1025 re
->nhe_installed_id
);
1027 json_object_string_add(json_route
, "uptime", up_str
);
1029 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1030 json_nexthop
= json_object_new_object();
1031 show_nexthop_json_helper(json_nexthop
,
1034 json_object_array_add(json_nexthops
,
1038 json_object_object_add(json_route
, "nexthops", json_nexthops
);
1040 /* If there are backup nexthops, include them */
1042 nhg
= rib_get_fib_backup_nhg(re
);
1044 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1046 if (nhg
&& nhg
->nexthop
) {
1047 json_nexthops
= json_object_new_array();
1049 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1050 json_nexthop
= json_object_new_object();
1052 show_nexthop_json_helper(json_nexthop
,
1054 json_object_array_add(json_nexthops
,
1058 json_object_object_add(json_route
, "backupNexthops",
1061 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
1063 json_object_array_add(json
, json_route
);
1067 /* Prefix information, and first nexthop. If we're showing 'fib',
1068 * and there are no installed primary nexthops, see if there are any
1069 * backup nexthops and start with those.
1071 if (is_fib
&& nhg
->nexthop
== NULL
) {
1072 nhg
= rib_get_fib_backup_nhg(re
);
1073 nhg_from_backup
= true;
1076 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
1078 len
+= vty_out(vty
, "[%d]", re
->instance
);
1079 if (nhg_from_backup
&& nhg
->nexthop
) {
1082 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1083 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1084 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1088 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
1089 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
1090 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
1093 /* Distance and metric display. */
1094 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
1095 (re
->distance
|| re
->metric
)) ||
1096 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
1097 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
1101 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
1103 /* Nexthop information. */
1104 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1107 } else if (nhg_from_backup
) {
1108 vty_out(vty
, " b%c%*c",
1109 re_status_output_char(re
, nexthop
, is_fib
),
1110 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1112 vty_out(vty
, " %c%*c",
1113 re_status_output_char(re
, nexthop
, is_fib
),
1114 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1117 show_route_nexthop_helper(vty
, re
, nexthop
);
1118 vty_out(vty
, ", %s\n", up_str
);
1121 /* If we only had backup nexthops, we're done */
1122 if (nhg_from_backup
)
1125 /* Check for backup nexthop info if present */
1127 nhg
= rib_get_fib_backup_nhg(re
);
1129 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
1134 /* Print backup info */
1135 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
1136 bool star_p
= false;
1139 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1141 /* TODO -- it'd be nice to be able to include
1142 * the entire list of backups, *and* include the
1143 * real installation state.
1145 vty_out(vty
, " b%c %*c",
1146 (star_p
? '*' : ' '),
1147 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
1148 show_route_nexthop_helper(vty
, re
, nexthop
);
1154 static void vty_show_ip_route_detail_json(struct vty
*vty
,
1155 struct route_node
*rn
, bool use_fib
)
1157 json_object
*json
= NULL
;
1158 json_object
*json_prefix
= NULL
;
1159 struct route_entry
*re
;
1163 dest
= rib_dest_from_rnode(rn
);
1165 json
= json_object_new_object();
1166 json_prefix
= json_object_new_array();
1168 RNODE_FOREACH_RE (rn
, re
) {
1170 * If re not selected for forwarding, skip re
1171 * for "show ip/ipv6 fib <prefix> json"
1173 if (use_fib
&& re
!= dest
->selected_fib
)
1175 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
1178 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1179 json_object_object_add(json
, buf
, json_prefix
);
1180 vty_json(vty
, json
);
1183 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1184 struct route_table
*table
, afi_t afi
,
1185 bool use_fib
, route_tag_t tag
,
1186 const struct prefix
*longer_prefix_p
,
1187 bool supernets_only
, int type
,
1188 unsigned short ospf_instance_id
, bool use_json
,
1189 uint32_t tableid
, bool show_ng
,
1190 struct route_show_ctx
*ctx
)
1192 struct route_node
*rn
;
1193 struct route_entry
*re
;
1196 json_object
*json
= NULL
;
1197 json_object
*json_prefix
= NULL
;
1202 * ctx->multi indicates if we are dumping multiple tables or vrfs.
1204 * => display the common header at most once
1205 * => add newline at each call except first
1206 * => always display the VRF and table
1208 * => display the common header if at least one entry is found
1209 * => display the VRF and table if specific
1213 json
= json_object_new_object();
1215 /* Show all routes. */
1216 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
1217 dest
= rib_dest_from_rnode(rn
);
1219 RNODE_FOREACH_RE (rn
, re
) {
1220 if (use_fib
&& re
!= dest
->selected_fib
)
1223 if (tag
&& re
->tag
!= tag
)
1227 && !prefix_match(longer_prefix_p
, &rn
->p
))
1230 /* This can only be true when the afi is IPv4 */
1231 if (supernets_only
) {
1232 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
1234 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
1237 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
1240 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
1244 if (type
&& re
->type
!= type
)
1247 if (ospf_instance_id
1248 && (re
->type
!= ZEBRA_ROUTE_OSPF
1249 || re
->instance
!= ospf_instance_id
))
1254 json_prefix
= json_object_new_array();
1256 if (!ctx
->header_done
) {
1259 SHOW_ROUTE_V4_HEADER
);
1262 SHOW_ROUTE_V6_HEADER
);
1264 if (ctx
->multi
&& ctx
->header_done
)
1266 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
1269 vty_out(vty
, "VRF %s:\n",
1273 "VRF %s table %u:\n",
1277 ctx
->header_done
= true;
1281 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
1286 prefix2str(&rn
->p
, buf
, sizeof(buf
));
1287 json_object_object_add(json
, buf
, json_prefix
);
1293 vty_json(vty
, json
);
1296 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
1297 afi_t afi
, bool use_fib
, bool use_json
,
1299 const struct prefix
*longer_prefix_p
,
1300 bool supernets_only
, int type
,
1301 unsigned short ospf_instance_id
, bool show_ng
,
1302 struct route_show_ctx
*ctx
)
1304 struct zebra_router_table
*zrt
;
1305 struct rib_table_info
*info
;
1307 RB_FOREACH (zrt
, zebra_router_table_head
,
1309 info
= route_table_get_info(zrt
->table
);
1311 if (zvrf
!= info
->zvrf
)
1313 if (zrt
->afi
!= afi
||
1314 zrt
->safi
!= SAFI_UNICAST
)
1317 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1318 use_fib
, use_json
, tag
, longer_prefix_p
,
1319 supernets_only
, type
, ospf_instance_id
,
1320 zrt
->tableid
, show_ng
, ctx
);
1324 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
1325 safi_t safi
, bool use_fib
, bool use_json
,
1327 const struct prefix
*longer_prefix_p
,
1328 bool supernets_only
, int type
,
1329 unsigned short ospf_instance_id
, uint32_t tableid
,
1330 bool show_ng
, struct route_show_ctx
*ctx
)
1332 struct route_table
*table
;
1333 struct zebra_vrf
*zvrf
= NULL
;
1335 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1337 vty_out(vty
, "{}\n");
1339 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1343 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1345 vty_out(vty
, "{}\n");
1347 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1352 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1354 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1357 vty_out(vty
, "{}\n");
1361 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1362 longer_prefix_p
, supernets_only
, type
,
1363 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1370 "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]",
1374 "IP nexthop tracking table\n"
1375 "IP import check tracking table\n"
1381 VRF_ALL_CMD_HELP_STR
1382 "Show Multicast (MRIB) NHT state\n")
1384 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1385 vrf_id_t vrf_id
= VRF_DEFAULT
;
1386 struct prefix prefix
, *p
= NULL
;
1387 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1391 struct zebra_vrf
*zvrf
;
1393 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
)
1394 if ((zvrf
= vrf
->info
) != NULL
) {
1395 vty_out(vty
, "\nVRF %s:\n", zvrf_name(zvrf
));
1396 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1402 VRF_GET_ID(vrf_id
, vrf_name
, false);
1404 memset(&prefix
, 0, sizeof(prefix
));
1406 p
= sockunion2hostprefix(addr
, &prefix
);
1411 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
);
1415 DEFUN (ip_nht_default_route
,
1416 ip_nht_default_route_cmd
,
1417 "ip nht resolve-via-default",
1419 "Filter Next Hop tracking route resolution\n"
1420 "Resolve via default route\n")
1422 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1427 if (zvrf
->zebra_rnh_ip_default_route
)
1430 zvrf
->zebra_rnh_ip_default_route
= true;
1432 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1436 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
)
1438 struct nexthop
*nexthop
= NULL
;
1439 struct nhg_connected
*rb_node_dep
= NULL
;
1440 struct nexthop_group
*backup_nhg
;
1441 char up_str
[MONOTIME_STRLEN
];
1442 char time_left
[MONOTIME_STRLEN
];
1444 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1446 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
, zebra_route_string(nhe
->type
));
1447 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1448 if (thread_is_scheduled(nhe
->timer
))
1449 vty_out(vty
, " Time to Deletion: %s",
1450 thread_timer_to_hhmmss(time_left
, sizeof(time_left
),
1454 vty_out(vty
, " Uptime: %s\n", up_str
);
1455 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1458 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1459 vty_out(vty
, " Valid");
1460 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
))
1461 vty_out(vty
, ", Installed");
1465 vty_out(vty
, " Interface Index: %d\n", nhe
->ifp
->ifindex
);
1467 if (!zebra_nhg_depends_is_empty(nhe
)) {
1468 vty_out(vty
, " Depends:");
1469 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1470 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1475 /* Output nexthops */
1476 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1477 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1480 /* Make recursive nexthops a bit more clear */
1483 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1485 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1486 if (CHECK_FLAG(nexthop
->flags
,
1487 NEXTHOP_FLAG_HAS_BACKUP
))
1488 vty_out(vty
, " [backup %d]",
1489 nexthop
->backup_idx
[0]);
1495 /* TODO -- print more useful backup info */
1496 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
1499 vty_out(vty
, "[backup");
1500 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1501 vty_out(vty
, " %d", nexthop
->backup_idx
[i
]);
1509 /* Output backup nexthops (if any) */
1510 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1512 vty_out(vty
, " Backups:\n");
1514 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1515 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1518 /* Make recursive nexthops a bit more clear */
1521 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1526 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1527 vty_out(vty
, " Dependents:");
1528 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1530 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1535 if (nhe
->nhg
.nhgr
.buckets
)
1537 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
"\n",
1538 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1539 nhe
->nhg
.nhgr
.unbalanced_timer
,
1540 nhe
->nhg
.nhgr
.unbalanced_time
);
1543 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
)
1545 struct nhg_hash_entry
*nhe
= NULL
;
1547 nhe
= zebra_nhg_lookup_id(id
);
1550 show_nexthop_group_out(vty
, nhe
);
1552 vty_out(vty
, "Nexthop Group ID: %u does not exist\n", id
);
1558 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1560 struct nhe_show_context
{
1567 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1569 struct nhe_show_context
*ctx
= arg
;
1570 struct nhg_hash_entry
*nhe
;
1572 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1574 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1577 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1580 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1583 show_nexthop_group_out(ctx
->vty
, nhe
);
1586 return HASHWALK_CONTINUE
;
1589 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1590 struct zebra_vrf
*zvrf
, afi_t afi
,
1593 struct nhe_show_context ctx
;
1597 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1600 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1603 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1605 struct zebra_if
*zebra_if
= NULL
;
1606 struct nhg_connected
*rb_node_dep
= NULL
;
1608 zebra_if
= ifp
->info
;
1610 if (!if_nhg_dependents_is_empty(ifp
)) {
1611 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1613 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1616 show_nexthop_group_out(vty
, rb_node_dep
->nhe
);
1621 DEFPY (show_interface_nexthop_group
,
1622 show_interface_nexthop_group_cmd
,
1623 "show interface [IFNAME$if_name] nexthop-group",
1625 "Interface status and configuration\n"
1627 "Show Nexthop Groups\n")
1629 struct vrf
*vrf
= NULL
;
1630 struct interface
*ifp
= NULL
;
1633 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1635 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1637 if_nexthop_group_dump_vty(vty
, ifp
);
1641 FOR_ALL_INTERFACES (vrf
, ifp
)
1642 if_nexthop_group_dump_vty(vty
, ifp
);
1648 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1655 DEFPY (show_nexthop_group
,
1656 show_nexthop_group_cmd
,
1657 "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>]>",
1659 "Show Nexthop Groups\n"
1661 "Nexthop Group ID\n"
1662 "Show Singleton Nexthop-Groups\n"
1665 "Kernel (not installed via the zebra RIB)\n"
1666 "Zebra (implicitly created by zebra)\n"
1667 "Border Gateway Protocol (BGP)\n"
1668 "Super Happy Advanced Routing Protocol (SHARP)\n"
1669 VRF_FULL_CMD_HELP_STR
)
1672 struct zebra_vrf
*zvrf
= NULL
;
1673 afi_t afi
= AFI_UNSPEC
;
1677 return show_nexthop_group_id_cmd_helper(vty
, id
);
1685 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1688 type
= ZEBRA_ROUTE_NHG
;
1692 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1694 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1701 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1702 struct zebra_vrf
*zvrf
;
1708 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1709 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1716 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1718 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1721 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1726 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
);
1731 DEFPY_HIDDEN(nexthop_group_use_enable
,
1732 nexthop_group_use_enable_cmd
,
1733 "[no] zebra nexthop kernel enable",
1736 "Nexthop configuration \n"
1737 "Configure use of kernel nexthops\n"
1738 "Enable kernel nexthops\n")
1740 zebra_nhg_enable_kernel_nexthops(!no
);
1744 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1745 "[no] zebra nexthop proto only",
1747 "Nexthop configuration\n"
1748 "Configure exclusive use of proto nexthops\n"
1749 "Only use proto nexthops\n")
1751 zebra_nhg_set_proto_nexthops_only(!no
);
1755 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1756 backup_nexthop_recursive_use_enable_cmd
,
1757 "[no] zebra nexthop resolve-via-backup",
1760 "Nexthop configuration \n"
1761 "Configure use of backup nexthops in recursive resolution\n")
1763 zebra_nhg_set_recursive_use_backups(!no
);
1767 DEFUN (no_ip_nht_default_route
,
1768 no_ip_nht_default_route_cmd
,
1769 "no ip nht resolve-via-default",
1772 "Filter Next Hop tracking route resolution\n"
1773 "Resolve via default route\n")
1775 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1780 if (!zvrf
->zebra_rnh_ip_default_route
)
1783 zvrf
->zebra_rnh_ip_default_route
= false;
1784 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1788 DEFUN (ipv6_nht_default_route
,
1789 ipv6_nht_default_route_cmd
,
1790 "ipv6 nht resolve-via-default",
1792 "Filter Next Hop tracking route resolution\n"
1793 "Resolve via default route\n")
1795 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1800 if (zvrf
->zebra_rnh_ipv6_default_route
)
1803 zvrf
->zebra_rnh_ipv6_default_route
= true;
1804 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1808 DEFUN (no_ipv6_nht_default_route
,
1809 no_ipv6_nht_default_route_cmd
,
1810 "no ipv6 nht resolve-via-default",
1813 "Filter Next Hop tracking route resolution\n"
1814 "Resolve via default route\n")
1816 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1821 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1824 zvrf
->zebra_rnh_ipv6_default_route
= false;
1825 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1829 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1830 "[no] ip nht hide-backup-events",
1833 "Nexthop-tracking configuration\n"
1834 "Hide notification about backup nexthops\n")
1836 rnh_set_hide_backups(!no
);
1844 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1845 [vrf <NAME$vrf_name|all$vrf_all>]\
1848 |A.B.C.D/M$prefix longer-prefixes\
1849 |supernets-only$supernets_only\
1852 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1853 |ospf$type_str (1-65535)$ospf_instance_id\
1855 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1856 [vrf <NAME$vrf_name|all$vrf_all>]\
1859 |X:X::X:X/M$prefix longer-prefixes\
1861 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1863 [<json$json|nexthop-group$ng>]",
1866 "IP forwarding table\n"
1867 "IP routing table\n"
1868 "Table to display\n"
1869 "The table number to display\n"
1871 VRF_FULL_CMD_HELP_STR
1872 "Show only routes with tag\n"
1874 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1875 "Show route matching the specified Network/Mask pair only\n"
1876 "Show supernet entries only\n"
1877 FRR_IP_REDIST_HELP_STR_ZEBRA
1878 "Open Shortest Path First (OSPFv2)\n"
1881 "IP forwarding table\n"
1882 "IP routing table\n"
1883 "Table to display\n"
1884 "The table number to display\n"
1886 VRF_FULL_CMD_HELP_STR
1887 "Show only routes with tag\n"
1890 "Show route matching the specified Network/Mask pair only\n"
1891 FRR_IP6_REDIST_HELP_STR_ZEBRA
1893 "Nexthop Group Information\n")
1895 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1898 struct zebra_vrf
*zvrf
;
1899 struct route_show_ctx ctx
= {
1900 .multi
= vrf_all
|| table_all
,
1903 if (!vrf_is_backend_netns()) {
1904 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1906 vty_out(vty
, "{}\n");
1908 vty_out(vty
, "Linux vrf backend already points to table id\n");
1909 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1915 type
= proto_redistnum(afi
, type_str
);
1917 vty_out(vty
, "Unknown route type\n");
1923 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1924 if ((zvrf
= vrf
->info
) == NULL
1925 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1929 do_show_ip_route_all(
1930 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1931 prefix_str
? prefix
: NULL
,
1932 !!supernets_only
, type
,
1933 ospf_instance_id
, !!ng
, &ctx
);
1936 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1938 prefix_str
? prefix
: NULL
,
1939 !!supernets_only
, type
,
1940 ospf_instance_id
, table
, !!ng
, &ctx
);
1943 vrf_id_t vrf_id
= VRF_DEFAULT
;
1946 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1947 vrf
= vrf_lookup_by_id(vrf_id
);
1956 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1957 prefix_str
? prefix
: NULL
,
1958 !!supernets_only
, type
,
1959 ospf_instance_id
, !!ng
, &ctx
);
1961 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1963 prefix_str
? prefix
: NULL
,
1964 !!supernets_only
, type
,
1965 ospf_instance_id
, table
, !!ng
, &ctx
);
1971 ALIAS_HIDDEN (show_route
,
1973 "show <ip$ipv4|ipv6$ipv6> ro",
1977 "IP routing table\n");
1980 DEFPY (show_route_detail
,
1981 show_route_detail_cmd
,
1984 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1989 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1995 [json$json] [nexthop-group$ng]",
1998 "IPv6 forwarding table\n"
1999 "IP routing table\n"
2000 VRF_FULL_CMD_HELP_STR
2001 "Network in the IP routing table to display\n"
2002 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
2004 "IPv6 forwarding table\n"
2005 "IPv6 routing table\n"
2006 VRF_FULL_CMD_HELP_STR
2010 "Nexthop Group Information\n")
2012 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2013 struct route_table
*table
;
2015 struct route_node
*rn
;
2016 bool use_fib
= !!fib
;
2018 bool network_found
= false;
2019 bool show_ng
= !!ng
;
2022 prefix_str
= address_str
;
2023 if (str2prefix(prefix_str
, &p
) < 0) {
2024 vty_out(vty
, "%% Malformed address\n");
2030 struct zebra_vrf
*zvrf
;
2032 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2033 if ((zvrf
= vrf
->info
) == NULL
2034 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
2037 rn
= route_node_match(table
, &p
);
2040 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
2041 route_unlock_node(rn
);
2045 dest
= rib_dest_from_rnode(rn
);
2046 if (use_fib
&& !dest
->selected_fib
) {
2047 route_unlock_node(rn
);
2051 network_found
= true;
2053 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2055 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
2058 route_unlock_node(rn
);
2061 if (!network_found
) {
2063 vty_out(vty
, "{}\n");
2067 "%% Network not in FIB\n");
2070 "%% Network not in RIB\n");
2075 vrf_id_t vrf_id
= VRF_DEFAULT
;
2078 VRF_GET_ID(vrf_id
, vrf_name
, false);
2080 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2084 rn
= route_node_match(table
, &p
);
2086 dest
= rib_dest_from_rnode(rn
);
2088 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
2089 (use_fib
&& dest
&& !dest
->selected_fib
)) {
2091 vty_out(vty
, "{}\n");
2095 "%% Network not in FIB\n");
2098 "%% Network not in table\n");
2101 route_unlock_node(rn
);
2106 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
2108 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
2110 route_unlock_node(rn
);
2116 DEFPY (show_route_summary
,
2117 show_route_summary_cmd
,
2118 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2119 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2123 "IP routing table\n"
2124 VRF_FULL_CMD_HELP_STR
2125 "Summary of all routes\n"
2126 "Table to display summary for\n"
2127 "The table number\n"
2131 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2132 struct route_table
*table
;
2133 bool uj
= use_json(argc
, argv
);
2137 struct zebra_vrf
*zvrf
;
2139 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2140 if ((zvrf
= vrf
->info
) == NULL
)
2144 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2147 table
= zebra_vrf_lookup_table_with_table_id(
2148 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2155 vty_show_ip_route_summary_prefix(vty
, table
,
2158 vty_show_ip_route_summary(vty
, table
, uj
);
2161 vrf_id_t vrf_id
= VRF_DEFAULT
;
2164 VRF_GET_ID(vrf_id
, vrf_name
, false);
2167 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2169 table
= zebra_vrf_lookup_table_with_table_id(
2170 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2175 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2177 vty_show_ip_route_summary(vty
, table
, uj
);
2183 DEFUN_HIDDEN (show_route_zebra_dump
,
2184 show_route_zebra_dump_cmd
,
2185 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2195 struct route_table
*table
;
2196 const char *vrf_name
= NULL
;
2199 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2201 if (argv_find(argv
, argc
, "vrf", &idx
))
2202 vrf_name
= argv
[++idx
]->arg
;
2206 struct zebra_vrf
*zvrf
;
2208 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2211 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2214 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2215 show_ip_route_dump_vty(vty
, table
);
2218 vrf_id_t vrf_id
= VRF_DEFAULT
;
2220 VRF_GET_ID(vrf_id
, vrf_name
, true);
2222 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2226 show_ip_route_dump_vty(vty
, table
);
2232 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2233 struct route_entry
*re
, unsigned int num
)
2236 char buf
[SRCDEST2STR_BUFFER
];
2238 vty_out(vty
, " Nexthop %u:\n", num
);
2239 vty_out(vty
, " type: %u\n", nexthop
->type
);
2240 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2241 switch (nexthop
->type
) {
2242 case NEXTHOP_TYPE_IPV4
:
2243 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2244 vty_out(vty
, " ip address: %s\n",
2245 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2247 vty_out(vty
, " afi: ipv4\n");
2249 if (nexthop
->ifindex
) {
2250 vty_out(vty
, " interface index: %d\n",
2252 vty_out(vty
, " interface name: %s\n",
2253 ifindex2ifname(nexthop
->ifindex
,
2257 if (nexthop
->src
.ipv4
.s_addr
2258 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2260 vty_out(vty
, " source: %s\n", buf
);
2262 case NEXTHOP_TYPE_IPV6
:
2263 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2264 vty_out(vty
, " ip: %s\n",
2265 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2267 vty_out(vty
, " afi: ipv6\n");
2269 if (nexthop
->ifindex
) {
2270 vty_out(vty
, " interface index: %d\n",
2272 vty_out(vty
, " interface name: %s\n",
2273 ifindex2ifname(nexthop
->ifindex
,
2277 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2278 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2280 vty_out(vty
, " source: %s\n", buf
);
2283 case NEXTHOP_TYPE_IFINDEX
:
2285 " Nexthop is an interface (directly connected).\n");
2286 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2287 vty_out(vty
, " interface name: %s\n",
2288 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2290 case NEXTHOP_TYPE_BLACKHOLE
:
2291 vty_out(vty
, " Nexthop type is blackhole.\n");
2293 switch (nexthop
->bh_type
) {
2294 case BLACKHOLE_REJECT
:
2295 vty_out(vty
, " Blackhole type: reject\n");
2297 case BLACKHOLE_ADMINPROHIB
:
2299 " Blackhole type: admin-prohibited\n");
2301 case BLACKHOLE_NULL
:
2302 vty_out(vty
, " Blackhole type: NULL0\n");
2304 case BLACKHOLE_UNSPEC
:
2311 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2313 struct route_node
*rn
;
2314 struct route_entry
*re
;
2315 char buf
[SRCDEST2STR_BUFFER
];
2320 struct nexthop
*nexthop
= NULL
;
2321 int nexthop_num
= 0;
2323 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2324 vty_out(vty
, "----------------------------\n");
2326 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2327 RNODE_FOREACH_RE (rn
, re
) {
2328 vty_out(vty
, "Route: %s\n",
2329 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2330 vty_out(vty
, " protocol: %s\n",
2331 zebra_route_string(re
->type
));
2332 vty_out(vty
, " instance: %u\n", re
->instance
);
2333 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2334 vty_out(vty
, " VRF name: %s\n",
2335 vrf_id_to_name(re
->vrf_id
));
2336 vty_out(vty
, " flags: %u\n", re
->flags
);
2338 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2339 vty_out(vty
, " distance: %u\n", re
->distance
);
2340 vty_out(vty
, " metric: %u\n", re
->metric
);
2343 vty_out(vty
, " tag: %u\n", re
->tag
);
2345 uptime
= monotime(&tv
);
2346 uptime
-= re
->uptime
;
2347 gmtime_r(&uptime
, &tm
);
2349 if (uptime
< ONE_DAY_SECOND
)
2350 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2351 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2352 else if (uptime
< ONE_WEEK_SECOND
)
2353 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2354 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2356 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2358 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2361 vty_out(vty
, " status: %u\n", re
->status
);
2362 vty_out(vty
, " nexthop_num: %u\n",
2363 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2364 vty_out(vty
, " nexthop_active_num: %u\n",
2365 nexthop_group_active_nexthop_num(
2367 vty_out(vty
, " table: %u\n", re
->table
);
2368 vty_out(vty
, " uptime: %s\n", time
);
2370 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2372 show_ip_route_nht_dump(vty
, nexthop
, re
,
2382 static void vty_show_ip_route_summary(struct vty
*vty
,
2383 struct route_table
*table
, bool use_json
)
2385 struct route_node
*rn
;
2386 struct route_entry
*re
;
2387 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2388 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2389 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2390 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2391 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2392 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2395 json_object
*json_route_summary
= NULL
;
2396 json_object
*json_route_routes
= NULL
;
2398 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2399 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2400 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2401 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2404 json_route_summary
= json_object_new_object();
2405 json_route_routes
= json_object_new_array();
2406 json_object_object_add(json_route_summary
, "routes",
2410 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2411 RNODE_FOREACH_RE (rn
, re
) {
2412 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2413 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2415 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2417 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2419 rib_cnt
[re
->type
]++;
2421 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2422 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2425 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2427 fib_cnt
[re
->type
]++;
2430 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2432 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2434 trap_cnt
[re
->type
]++;
2437 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2439 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2441 offload_cnt
[re
->type
]++;
2446 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2448 zvrf_name(((struct rib_table_info
*)
2449 route_table_get_info(table
))
2452 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2453 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2454 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2455 if (i
== ZEBRA_ROUTE_BGP
) {
2457 json_object
*json_route_ebgp
=
2458 json_object_new_object();
2460 json_object_int_add(
2461 json_route_ebgp
, "fib",
2462 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2463 json_object_int_add(
2464 json_route_ebgp
, "rib",
2465 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2466 json_object_int_add(
2467 json_route_ebgp
, "fibOffLoaded",
2468 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2469 json_object_int_add(
2470 json_route_ebgp
, "fibTrapped",
2471 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2473 json_object_string_add(json_route_ebgp
,
2475 json_object_array_add(json_route_routes
,
2478 json_object
*json_route_ibgp
=
2479 json_object_new_object();
2481 json_object_int_add(
2482 json_route_ibgp
, "fib",
2483 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2484 json_object_int_add(
2485 json_route_ibgp
, "rib",
2486 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2487 json_object_int_add(
2488 json_route_ibgp
, "fibOffLoaded",
2489 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2490 json_object_int_add(
2491 json_route_ibgp
, "fibTrapped",
2492 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2493 json_object_string_add(json_route_ibgp
,
2495 json_object_array_add(json_route_routes
,
2498 vty_out(vty
, "%-20s %-20d %-20d \n",
2500 rib_cnt
[ZEBRA_ROUTE_BGP
],
2501 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2502 vty_out(vty
, "%-20s %-20d %-20d \n",
2504 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2505 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2509 json_object
*json_route_type
=
2510 json_object_new_object();
2512 json_object_int_add(json_route_type
,
2514 json_object_int_add(json_route_type
,
2517 json_object_int_add(json_route_type
,
2520 json_object_int_add(json_route_type
,
2523 json_object_string_add(
2524 json_route_type
, "type",
2525 zebra_route_string(i
));
2526 json_object_array_add(json_route_routes
,
2529 vty_out(vty
, "%-20s %-20d %-20d \n",
2530 zebra_route_string(i
),
2531 rib_cnt
[i
], fib_cnt
[i
]);
2537 json_object_int_add(json_route_summary
, "routesTotal",
2538 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2539 json_object_int_add(json_route_summary
, "routesTotalFib",
2540 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2542 vty_json(vty
, json_route_summary
);
2544 vty_out(vty
, "------\n");
2545 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2546 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2552 * Implementation of the ip route summary prefix command.
2554 * This command prints the primary prefixes that have been installed by various
2555 * protocols on the box.
2558 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2559 struct route_table
*table
,
2562 struct route_node
*rn
;
2563 struct route_entry
*re
;
2564 struct nexthop
*nexthop
;
2565 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2566 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2567 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2568 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2571 json_object
*json_route_summary
= NULL
;
2572 json_object
*json_route_routes
= NULL
;
2574 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2575 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2578 json_route_summary
= json_object_new_object();
2579 json_route_routes
= json_object_new_array();
2580 json_object_object_add(json_route_summary
, "prefixRoutes",
2584 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2585 RNODE_FOREACH_RE (rn
, re
) {
2588 * In case of ECMP, count only once.
2591 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2592 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2593 fib_cnt
[re
->type
]++;
2595 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2596 nexthop
= nexthop
->next
) {
2598 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2599 rib_cnt
[re
->type
]++;
2600 if (re
->type
== ZEBRA_ROUTE_BGP
2601 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2602 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2603 if (CHECK_FLAG(re
->status
,
2604 ROUTE_ENTRY_INSTALLED
))
2605 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2611 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2612 "Prefix Routes", "FIB",
2613 zvrf_name(((struct rib_table_info
*)
2614 route_table_get_info(table
))
2617 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2618 if (rib_cnt
[i
] > 0) {
2619 if (i
== ZEBRA_ROUTE_BGP
) {
2621 json_object
*json_route_ebgp
=
2622 json_object_new_object();
2624 json_object_int_add(
2625 json_route_ebgp
, "fib",
2626 fib_cnt
[ZEBRA_ROUTE_BGP
]
2627 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2628 json_object_int_add(
2629 json_route_ebgp
, "rib",
2630 rib_cnt
[ZEBRA_ROUTE_BGP
]
2631 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2632 json_object_string_add(json_route_ebgp
,
2634 json_object_array_add(json_route_routes
,
2637 json_object
*json_route_ibgp
=
2638 json_object_new_object();
2640 json_object_int_add(
2641 json_route_ibgp
, "fib",
2642 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2643 json_object_int_add(
2644 json_route_ibgp
, "rib",
2645 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2646 json_object_string_add(json_route_ibgp
,
2648 json_object_array_add(json_route_routes
,
2651 vty_out(vty
, "%-20s %-20d %-20d \n",
2653 rib_cnt
[ZEBRA_ROUTE_BGP
]
2654 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2655 fib_cnt
[ZEBRA_ROUTE_BGP
]
2656 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2657 vty_out(vty
, "%-20s %-20d %-20d \n",
2659 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2660 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2664 json_object
*json_route_type
=
2665 json_object_new_object();
2667 json_object_int_add(json_route_type
,
2669 json_object_int_add(json_route_type
,
2671 json_object_string_add(
2672 json_route_type
, "type",
2673 zebra_route_string(i
));
2674 json_object_array_add(json_route_routes
,
2677 vty_out(vty
, "%-20s %-20d %-20d \n",
2678 zebra_route_string(i
),
2679 rib_cnt
[i
], fib_cnt
[i
]);
2685 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2686 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2687 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2688 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2690 vty_json(vty
, json_route_summary
);
2692 vty_out(vty
, "------\n");
2693 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2694 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2699 DEFUN (allow_external_route_update
,
2700 allow_external_route_update_cmd
,
2701 "allow-external-route-update",
2702 "Allow FRR routes to be overwritten by external processes\n")
2704 zrouter
.allow_delete
= true;
2709 DEFUN (no_allow_external_route_update
,
2710 no_allow_external_route_update_cmd
,
2711 "no allow-external-route-update",
2713 "Allow FRR routes to be overwritten by external processes\n")
2715 zrouter
.allow_delete
= false;
2728 struct zebra_vrf
*zvrf
;
2730 if (vrf_is_backend_netns())
2731 vty_out(vty
, "netns-based vrfs\n");
2733 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2734 if (!(zvrf
= vrf
->info
))
2736 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2739 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2740 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2741 vty_out(vty
, "inactive");
2742 else if (zvrf_ns_name(zvrf
))
2743 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2744 zvrf_ns_name(zvrf
));
2746 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2748 if (vrf_is_user_cfged(vrf
))
2749 vty_out(vty
, " (configured)");
2756 DEFPY (evpn_mh_mac_holdtime
,
2757 evpn_mh_mac_holdtime_cmd
,
2758 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2763 "Duration in seconds\n")
2765 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2769 DEFPY (evpn_mh_neigh_holdtime
,
2770 evpn_mh_neigh_holdtime_cmd
,
2771 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2775 "Neighbor entry hold time\n"
2776 "Duration in seconds\n")
2779 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2783 DEFPY (evpn_mh_startup_delay
,
2784 evpn_mh_startup_delay_cmd
,
2785 "[no] evpn mh startup-delay(0-3600)$duration",
2790 "duration in seconds\n")
2793 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2797 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2798 "[no$no] evpn mh redirect-off",
2802 "ES bond redirect for fast-failover off\n")
2806 redirect_off
= no
? false : true;
2808 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2811 DEFUN (default_vrf_vni_mapping
,
2812 default_vrf_vni_mapping_cmd
,
2813 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2814 "VNI corresponding to the DEFAULT VRF\n"
2816 "Prefix routes only \n")
2818 char xpath
[XPATH_MAXLEN
];
2819 struct zebra_vrf
*zvrf
= NULL
;
2822 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2829 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2831 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2833 snprintf(xpath
, sizeof(xpath
),
2834 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2836 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2839 snprintf(xpath
, sizeof(xpath
),
2840 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2842 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2845 return nb_cli_apply_changes(vty
, NULL
);
2848 DEFUN (no_default_vrf_vni_mapping
,
2849 no_default_vrf_vni_mapping_cmd
,
2850 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2852 "VNI corresponding to DEFAULT VRF\n"
2854 "Prefix routes only \n")
2856 char xpath
[XPATH_MAXLEN
];
2858 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2859 struct zebra_vrf
*zvrf
= NULL
;
2861 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2868 if (zvrf
->l3vni
!= vni
) {
2869 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2874 snprintf(xpath
, sizeof(xpath
),
2875 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2877 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2880 snprintf(xpath
, sizeof(xpath
),
2881 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2883 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2886 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2888 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2890 return nb_cli_apply_changes(vty
, NULL
);
2893 DEFUN (vrf_vni_mapping
,
2894 vrf_vni_mapping_cmd
,
2895 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2896 "VNI corresponding to tenant VRF\n"
2898 "prefix-routes-only\n")
2902 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2910 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2911 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2915 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2916 NB_OP_MODIFY
, "true");
2918 return nb_cli_apply_changes(vty
, NULL
);
2921 DEFUN (no_vrf_vni_mapping
,
2922 no_vrf_vni_mapping_cmd
,
2923 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2925 "VNI corresponding to tenant VRF\n"
2927 "prefix-routes-only\n")
2931 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2932 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2940 if (zvrf
->l3vni
!= vni
) {
2941 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2946 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2950 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2951 NB_OP_DESTROY
, "true");
2953 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2955 return nb_cli_apply_changes(vty
, NULL
);
2959 DEFUN (show_vrf_vni
,
2961 "show vrf vni [json]",
2968 struct zebra_vrf
*zvrf
;
2969 json_object
*json
= NULL
;
2970 json_object
*json_vrfs
= NULL
;
2971 bool uj
= use_json(argc
, argv
);
2974 json
= json_object_new_object();
2975 json_vrfs
= json_object_new_array();
2979 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n", "VRF",
2980 "VNI", "VxLAN IF", "L3-SVI", "State", "Rmac");
2982 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2987 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2991 json_object_object_add(json
, "vrfs", json_vrfs
);
2992 vty_json(vty
, json
);
2998 DEFUN (show_evpn_global
,
2999 show_evpn_global_cmd
,
3005 bool uj
= use_json(argc
, argv
);
3007 zebra_vxlan_print_evpn(vty
, uj
);
3011 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
3012 SHOW_STR IP_STR
"neighbors\n")
3015 zebra_neigh_show(vty
);
3020 DEFPY(show_evpn_l2_nh
,
3021 show_evpn_l2_nh_cmd
,
3022 "show evpn l2-nh [json$json]",
3030 zebra_evpn_l2_nh_show(vty
, uj
);
3037 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
3040 "Ethernet Segment\n"
3042 "Detailed information\n"
3049 if (!str_to_esi(esi_str
, &esi
)) {
3050 vty_out(vty
, "%% Malformed ESI\n");
3053 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
3056 zebra_evpn_es_show_detail(vty
, uj
);
3058 zebra_evpn_es_show(vty
, uj
);
3064 DEFPY(show_evpn_es_evi
,
3065 show_evpn_es_evi_cmd
,
3066 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3069 "Ethernet Segment per EVI\n"
3070 "VxLAN Network Identifier\n"
3072 "Detailed information\n"
3079 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3081 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3086 DEFPY(show_evpn_access_vlan
,
3087 show_evpn_access_vlan_cmd
,
3088 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3093 "Detailed information\n"
3099 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3102 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3104 zebra_evpn_acc_vl_show(vty
, uj
);
3110 DEFUN (show_evpn_vni
,
3112 "show evpn vni [json]",
3115 "VxLAN Network Identifier\n"
3118 struct zebra_vrf
*zvrf
;
3119 bool uj
= use_json(argc
, argv
);
3121 zvrf
= zebra_vrf_get_evpn();
3122 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3126 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3127 "show evpn vni detail [json]",
3130 "VxLAN Network Identifier\n"
3131 "Detailed Information On Each VNI\n"
3134 struct zebra_vrf
*zvrf
;
3135 bool uj
= use_json(argc
, argv
);
3137 zvrf
= zebra_vrf_get_evpn();
3138 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3142 DEFUN (show_evpn_vni_vni
,
3143 show_evpn_vni_vni_cmd
,
3144 "show evpn vni " CMD_VNI_RANGE
"[json]",
3147 "VxLAN Network Identifier\n"
3151 struct zebra_vrf
*zvrf
;
3153 bool uj
= use_json(argc
, argv
);
3155 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3156 zvrf
= zebra_vrf_get_evpn();
3157 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3161 DEFUN (show_evpn_rmac_vni_mac
,
3162 show_evpn_rmac_vni_mac_cmd
,
3163 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3170 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3175 bool uj
= use_json(argc
, argv
);
3177 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3178 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3179 vty_out(vty
, "%% Malformed MAC address\n");
3182 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3186 DEFUN (show_evpn_rmac_vni
,
3187 show_evpn_rmac_vni_cmd
,
3188 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3197 bool uj
= use_json(argc
, argv
);
3199 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3200 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3205 DEFUN (show_evpn_rmac_vni_all
,
3206 show_evpn_rmac_vni_all_cmd
,
3207 "show evpn rmac vni all [json]",
3215 bool uj
= use_json(argc
, argv
);
3217 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3222 DEFUN (show_evpn_nh_vni_ip
,
3223 show_evpn_nh_vni_ip_cmd
,
3224 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3231 "Host address (ipv4 or ipv6)\n"
3236 bool uj
= use_json(argc
, argv
);
3238 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3239 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3241 vty_out(vty
, "%% Malformed Neighbor address\n");
3244 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3249 DEFUN (show_evpn_nh_vni
,
3250 show_evpn_nh_vni_cmd
,
3251 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3260 bool uj
= use_json(argc
, argv
);
3262 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3263 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3268 DEFUN (show_evpn_nh_vni_all
,
3269 show_evpn_nh_vni_all_cmd
,
3270 "show evpn next-hops vni all [json]",
3278 bool uj
= use_json(argc
, argv
);
3280 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3285 DEFUN (show_evpn_mac_vni
,
3286 show_evpn_mac_vni_cmd
,
3287 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3291 "VxLAN Network Identifier\n"
3295 struct zebra_vrf
*zvrf
;
3297 bool uj
= use_json(argc
, argv
);
3299 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3300 zvrf
= zebra_vrf_get_evpn();
3301 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
);
3305 DEFUN (show_evpn_mac_vni_all
,
3306 show_evpn_mac_vni_all_cmd
,
3307 "show evpn mac vni all [json]",
3311 "VxLAN Network Identifier\n"
3315 struct zebra_vrf
*zvrf
;
3316 bool uj
= use_json(argc
, argv
);
3318 zvrf
= zebra_vrf_get_evpn();
3319 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3323 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3324 "show evpn mac vni all detail [json]",
3328 "VxLAN Network Identifier\n"
3330 "Detailed Information On Each VNI MAC\n"
3333 struct zebra_vrf
*zvrf
;
3334 bool uj
= use_json(argc
, argv
);
3336 zvrf
= zebra_vrf_get_evpn();
3337 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3341 DEFUN (show_evpn_mac_vni_all_vtep
,
3342 show_evpn_mac_vni_all_vtep_cmd
,
3343 "show evpn mac vni all vtep A.B.C.D [json]",
3347 "VxLAN Network Identifier\n"
3350 "Remote VTEP IP address\n"
3353 struct zebra_vrf
*zvrf
;
3354 struct in_addr vtep_ip
;
3355 bool uj
= use_json(argc
, argv
);
3357 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3359 vty_out(vty
, "%% Malformed VTEP IP address\n");
3362 zvrf
= zebra_vrf_get_evpn();
3363 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3369 DEFUN (show_evpn_mac_vni_mac
,
3370 show_evpn_mac_vni_mac_cmd
,
3371 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3375 "VxLAN Network Identifier\n"
3378 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3382 struct zebra_vrf
*zvrf
;
3385 bool uj
= use_json(argc
, argv
);
3387 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3388 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3389 vty_out(vty
, "%% Malformed MAC address\n");
3392 zvrf
= zebra_vrf_get_evpn();
3393 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3397 DEFUN (show_evpn_mac_vni_vtep
,
3398 show_evpn_mac_vni_vtep_cmd
,
3399 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3403 "VxLAN Network Identifier\n"
3406 "Remote VTEP IP address\n"
3409 struct zebra_vrf
*zvrf
;
3411 struct in_addr vtep_ip
;
3412 bool uj
= use_json(argc
, argv
);
3414 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3415 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3417 vty_out(vty
, "%% Malformed VTEP IP address\n");
3421 zvrf
= zebra_vrf_get_evpn();
3422 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3426 DEFPY (show_evpn_mac_vni_all_dad
,
3427 show_evpn_mac_vni_all_dad_cmd
,
3428 "show evpn mac vni all duplicate [json]",
3432 "VxLAN Network Identifier\n"
3434 "Duplicate address list\n"
3437 struct zebra_vrf
*zvrf
;
3438 bool uj
= use_json(argc
, argv
);
3440 zvrf
= zebra_vrf_get_evpn();
3441 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3446 DEFPY (show_evpn_mac_vni_dad
,
3447 show_evpn_mac_vni_dad_cmd
,
3448 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3452 "VxLAN Network Identifier\n"
3454 "Duplicate address list\n"
3457 struct zebra_vrf
*zvrf
;
3458 bool uj
= use_json(argc
, argv
);
3460 zvrf
= zebra_vrf_get_evpn();
3462 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3467 DEFPY (show_evpn_neigh_vni_dad
,
3468 show_evpn_neigh_vni_dad_cmd
,
3469 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3472 "ARP and ND cache\n"
3473 "VxLAN Network Identifier\n"
3475 "Duplicate address list\n"
3478 struct zebra_vrf
*zvrf
;
3479 bool uj
= use_json(argc
, argv
);
3481 zvrf
= zebra_vrf_get_evpn();
3482 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3486 DEFPY (show_evpn_neigh_vni_all_dad
,
3487 show_evpn_neigh_vni_all_dad_cmd
,
3488 "show evpn arp-cache vni all duplicate [json]",
3491 "ARP and ND cache\n"
3492 "VxLAN Network Identifier\n"
3494 "Duplicate address list\n"
3497 struct zebra_vrf
*zvrf
;
3498 bool uj
= use_json(argc
, argv
);
3500 zvrf
= zebra_vrf_get_evpn();
3501 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3506 DEFUN (show_evpn_neigh_vni
,
3507 show_evpn_neigh_vni_cmd
,
3508 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3511 "ARP and ND cache\n"
3512 "VxLAN Network Identifier\n"
3516 struct zebra_vrf
*zvrf
;
3518 bool uj
= use_json(argc
, argv
);
3520 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3521 zvrf
= zebra_vrf_get_evpn();
3522 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3526 DEFUN (show_evpn_neigh_vni_all
,
3527 show_evpn_neigh_vni_all_cmd
,
3528 "show evpn arp-cache vni all [json]",
3531 "ARP and ND cache\n"
3532 "VxLAN Network Identifier\n"
3536 struct zebra_vrf
*zvrf
;
3537 bool uj
= use_json(argc
, argv
);
3539 zvrf
= zebra_vrf_get_evpn();
3540 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3544 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3545 "show evpn arp-cache vni all detail [json]",
3548 "ARP and ND cache\n"
3549 "VxLAN Network Identifier\n"
3551 "Neighbor details for all vnis in detail\n" JSON_STR
)
3553 struct zebra_vrf
*zvrf
;
3554 bool uj
= use_json(argc
, argv
);
3556 zvrf
= zebra_vrf_get_evpn();
3557 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3561 DEFUN (show_evpn_neigh_vni_neigh
,
3562 show_evpn_neigh_vni_neigh_cmd
,
3563 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3566 "ARP and ND cache\n"
3567 "VxLAN Network Identifier\n"
3570 "Neighbor address (IPv4 or IPv6 address)\n"
3573 struct zebra_vrf
*zvrf
;
3576 bool uj
= use_json(argc
, argv
);
3578 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3579 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3581 vty_out(vty
, "%% Malformed Neighbor address\n");
3584 zvrf
= zebra_vrf_get_evpn();
3585 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3589 DEFUN (show_evpn_neigh_vni_vtep
,
3590 show_evpn_neigh_vni_vtep_cmd
,
3591 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3594 "ARP and ND cache\n"
3595 "VxLAN Network Identifier\n"
3598 "Remote VTEP IP address\n"
3601 struct zebra_vrf
*zvrf
;
3603 struct in_addr vtep_ip
;
3604 bool uj
= use_json(argc
, argv
);
3606 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3607 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3609 vty_out(vty
, "%% Malformed VTEP IP address\n");
3613 zvrf
= zebra_vrf_get_evpn();
3614 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3618 /* policy routing contexts */
3619 DEFUN (show_pbr_ipset
,
3621 "show pbr ipset [WORD]",
3623 "Policy-Based Routing\n"
3624 "IPset Context information\n"
3625 "IPset Name information\n")
3629 found
= argv_find(argv
, argc
, "WORD", &idx
);
3631 zebra_pbr_show_ipset_list(vty
, NULL
);
3633 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3637 /* policy routing contexts */
3638 DEFUN (show_pbr_iptable
,
3639 show_pbr_iptable_cmd
,
3640 "show pbr iptable [WORD]",
3642 "Policy-Based Routing\n"
3643 "IPtable Context information\n"
3644 "IPtable Name information\n")
3649 found
= argv_find(argv
, argc
, "WORD", &idx
);
3651 zebra_pbr_show_iptable(vty
, NULL
);
3653 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3657 /* policy routing contexts */
3658 DEFPY (show_pbr_rule
,
3662 "Policy-Based Routing\n"
3665 zebra_pbr_show_rule(vty
);
3669 DEFPY (pbr_nexthop_resolve
,
3670 pbr_nexthop_resolve_cmd
,
3671 "[no$no] pbr nexthop-resolve",
3673 "Policy Based Routing\n"
3674 "Resolve nexthop for dataplane programming\n")
3676 zebra_pbr_expand_action_update(!no
);
3680 DEFPY (clear_evpn_dup_addr
,
3681 clear_evpn_dup_addr_cmd
,
3682 "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>]>",
3685 "Duplicate address \n"
3686 "VxLAN Network Identifier\n"
3690 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3695 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3696 int ret
= CMD_SUCCESS
;
3698 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3699 *yang_dup_mac
= NULL
;
3704 yang_dup
= yang_data_new(
3705 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3708 yang_dup
= yang_data_new_uint32(
3709 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3711 if (!is_zero_mac(&mac
->eth_addr
)) {
3712 yang_dup_mac
= yang_data_new_mac(
3713 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3716 listnode_add(input
, yang_dup_mac
);
3718 if (sockunion_family(ip
) == AF_INET
) {
3719 host_ip
.ipa_type
= IPADDR_V4
;
3720 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3722 host_ip
.ipa_type
= IPADDR_V6
;
3723 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3724 sizeof(struct in6_addr
));
3727 yang_dup_ip
= yang_data_new_ip(
3728 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3732 listnode_add(input
, yang_dup_ip
);
3737 listnode_add(input
, yang_dup
);
3738 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3742 list_delete(&input
);
3747 /* Static ip route configuration write function. */
3748 static int zebra_ip_config(struct vty
*vty
)
3752 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3757 DEFUN (ip_zebra_import_table_distance
,
3758 ip_zebra_import_table_distance_cmd
,
3759 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3761 "import routes from non-main kernel table\n"
3762 "kernel routing table id\n"
3763 "Distance for imported routes\n"
3764 "Default distance value\n"
3765 "route-map for filtering\n"
3768 uint32_t table_id
= 0;
3770 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3771 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3773 strmatch(argv
[argc
- 2]->text
, "route-map")
3774 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3778 if (argc
== 7 || (argc
== 5 && !rmap
))
3779 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3781 if (!is_zebra_valid_kernel_table(table_id
)) {
3783 "Invalid routing table ID, %d. Must be in range 1-252\n",
3786 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3790 if (is_zebra_main_routing_table(table_id
)) {
3792 "Invalid routing table ID, %d. Must be non-default table\n",
3795 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3799 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3802 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3807 DEFUN_HIDDEN (zebra_packet_process
,
3808 zebra_packet_process_cmd
,
3809 "zebra zapi-packets (1-10000)",
3812 "Number of packets to process before relinquishing thread\n")
3814 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3816 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3817 memory_order_relaxed
);
3822 DEFUN_HIDDEN (no_zebra_packet_process
,
3823 no_zebra_packet_process_cmd
,
3824 "no zebra zapi-packets [(1-10000)]",
3828 "Number of packets to process before relinquishing thread\n")
3830 atomic_store_explicit(&zrouter
.packets_to_process
,
3831 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3832 memory_order_relaxed
);
3837 DEFUN_HIDDEN (zebra_workqueue_timer
,
3838 zebra_workqueue_timer_cmd
,
3839 "zebra work-queue (0-10000)",
3842 "Time in milliseconds\n")
3844 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3845 zrouter
.ribq
->spec
.hold
= timer
;
3850 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3851 no_zebra_workqueue_timer_cmd
,
3852 "no zebra work-queue [(0-10000)]",
3856 "Time in milliseconds\n")
3858 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3863 DEFUN (no_ip_zebra_import_table
,
3864 no_ip_zebra_import_table_cmd
,
3865 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3868 "import routes from non-main kernel table\n"
3869 "kernel routing table id\n"
3870 "Distance for imported routes\n"
3871 "Default distance value\n"
3872 "route-map for filtering\n"
3875 uint32_t table_id
= 0;
3876 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3878 if (!is_zebra_valid_kernel_table(table_id
)) {
3880 "Invalid routing table ID. Must be in range 1-252\n");
3884 if (is_zebra_main_routing_table(table_id
)) {
3886 "Invalid routing table ID, %d. Must be non-default table\n",
3891 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3894 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3897 DEFPY (zebra_nexthop_group_keep
,
3898 zebra_nexthop_group_keep_cmd
,
3899 "[no] zebra nexthop-group keep (1-3600)",
3903 "How long to keep\n"
3904 "Time in seconds from 1-3600\n")
3907 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3909 zrouter
.nhg_keep
= keep
;
3914 static int config_write_protocol(struct vty
*vty
)
3916 if (zrouter
.allow_delete
)
3917 vty_out(vty
, "allow-external-route-update\n");
3919 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3920 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3922 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3923 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3925 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3926 vty_out(vty
, "zebra zapi-packets %u\n",
3927 zrouter
.packets_to_process
);
3929 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3931 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3932 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3933 ipv4_multicast_mode
== MCAST_URIB_ONLY
3935 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3937 : ipv4_multicast_mode
3938 == MCAST_MIX_MRIB_FIRST
3940 : ipv4_multicast_mode
3941 == MCAST_MIX_DISTANCE
3945 /* Include dataplane info */
3946 dplane_config_write_helper(vty
);
3948 zebra_evpn_mh_config_write(vty
);
3950 zebra_pbr_config_write(vty
);
3952 /* Include nexthop-group config */
3953 if (!zebra_nhg_kernel_nexthops_enabled())
3954 vty_out(vty
, "no zebra nexthop kernel enable\n");
3956 if (zebra_nhg_proto_nexthops_only())
3957 vty_out(vty
, "zebra nexthop proto only\n");
3959 if (!zebra_nhg_recursive_use_backups())
3960 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3962 if (rnh_get_hide_backups())
3963 vty_out(vty
, "ip nht hide-backup-events\n");
3966 /* Include netlink info */
3967 netlink_config_write_helper(vty
);
3968 #endif /* HAVE_NETLINK */
3980 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3983 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3984 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3985 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3986 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3987 ttable_add_row(table
, "v6 Forwarding|%s",
3988 ipforward_ipv6() ? "On" : "Off");
3989 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3990 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3991 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3995 if (!vrf_is_backend_netns())
3996 ttable_add_row(table
, "VRF|l3mdev Available");
3998 ttable_add_row(table
, "VRF|Namespaces");
4000 ttable_add_row(table
, "VRF|Not Available");
4003 ttable_add_row(table
, "ASIC offload|%s",
4004 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4006 ttable_add_row(table
, "RA|%s",
4007 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4008 ttable_add_row(table
, "RFC 5549|%s",
4009 rtadv_get_interfaces_configured_from_bgp()
4011 : "BGP is not using");
4013 ttable_add_row(table
, "Kernel NHG|%s",
4014 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4016 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4017 zrouter
.allow_delete
? "Yes" : "No");
4018 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4019 zrouter
.all_linkdownv4
? "On" : "Off");
4020 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4021 zrouter
.default_linkdownv4
? "On" : "Off");
4022 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4023 zrouter
.all_linkdownv6
? "On" : "Off");
4024 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4025 zrouter
.default_linkdownv6
? "On" : "Off");
4027 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4028 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4029 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4030 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4031 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4032 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4033 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4034 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4036 out
= ttable_dump(table
, "\n");
4037 vty_out(vty
, "%s\n", out
);
4038 XFREE(MTYPE_TMP
, out
);
4042 " Route Route Neighbor LSP LSP\n");
4044 "VRF Installs Removals Updates Installs Removals\n");
4046 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4047 struct zebra_vrf
*zvrf
= vrf
->info
;
4049 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4050 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4051 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4052 zvrf
->lsp_removals
);
4058 DEFUN (ip_forwarding
,
4062 "Turn on IP forwarding\n")
4068 ret
= ipforward_on();
4071 vty_out(vty
, "Can't turn on IP forwarding\n");
4072 return CMD_WARNING_CONFIG_FAILED
;
4078 DEFUN (no_ip_forwarding
,
4079 no_ip_forwarding_cmd
,
4083 "Turn off IP forwarding\n")
4089 ret
= ipforward_off();
4092 vty_out(vty
, "Can't turn off IP forwarding\n");
4093 return CMD_WARNING_CONFIG_FAILED
;
4099 /* Only display ip forwarding is enabled or not. */
4100 DEFUN (show_ip_forwarding
,
4101 show_ip_forwarding_cmd
,
4102 "show ip forwarding",
4105 "IP forwarding status\n")
4112 vty_out(vty
, "IP forwarding is off\n");
4114 vty_out(vty
, "IP forwarding is on\n");
4118 /* Only display ipv6 forwarding is enabled or not. */
4119 DEFUN (show_ipv6_forwarding
,
4120 show_ipv6_forwarding_cmd
,
4121 "show ipv6 forwarding",
4123 "IPv6 information\n"
4124 "Forwarding status\n")
4128 ret
= ipforward_ipv6();
4132 vty_out(vty
, "ipv6 forwarding is unknown\n");
4135 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4138 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4141 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4147 DEFUN (ipv6_forwarding
,
4148 ipv6_forwarding_cmd
,
4151 "Turn on IPv6 forwarding\n")
4155 ret
= ipforward_ipv6();
4157 ret
= ipforward_ipv6_on();
4160 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4161 return CMD_WARNING_CONFIG_FAILED
;
4167 DEFUN (no_ipv6_forwarding
,
4168 no_ipv6_forwarding_cmd
,
4169 "no ipv6 forwarding",
4172 "Turn off IPv6 forwarding\n")
4176 ret
= ipforward_ipv6();
4178 ret
= ipforward_ipv6_off();
4181 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4182 return CMD_WARNING_CONFIG_FAILED
;
4188 /* Display dataplane info */
4189 DEFUN (show_dataplane
,
4191 "show zebra dplane [detailed]",
4194 "Zebra dataplane information\n"
4195 "Detailed output\n")
4198 bool detailed
= false;
4200 if (argv_find(argv
, argc
, "detailed", &idx
))
4203 return dplane_show_helper(vty
, detailed
);
4206 /* Display dataplane providers info */
4207 DEFUN (show_dataplane_providers
,
4208 show_dataplane_providers_cmd
,
4209 "show zebra dplane providers [detailed]",
4212 "Zebra dataplane information\n"
4213 "Zebra dataplane provider information\n"
4214 "Detailed output\n")
4217 bool detailed
= false;
4219 if (argv_find(argv
, argc
, "detailed", &idx
))
4222 return dplane_show_provs_helper(vty
, detailed
);
4225 /* Configure dataplane incoming queue limit */
4226 DEFUN (zebra_dplane_queue_limit
,
4227 zebra_dplane_queue_limit_cmd
,
4228 "zebra dplane limit (0-10000)",
4231 "Limit incoming queued updates\n"
4232 "Number of queued updates\n")
4236 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4238 dplane_set_in_queue_limit(limit
, true);
4243 /* Reset dataplane queue limit to default value */
4244 DEFUN (no_zebra_dplane_queue_limit
,
4245 no_zebra_dplane_queue_limit_cmd
,
4246 "no zebra dplane limit [(0-10000)]",
4250 "Limit incoming queued updates\n"
4251 "Number of queued updates\n")
4253 dplane_set_in_queue_limit(0, false);
4258 DEFUN (zebra_show_routing_tables_summary
,
4259 zebra_show_routing_tables_summary_cmd
,
4260 "show zebra router table summary",
4263 "The Zebra Router Information\n"
4264 "Table Information about this Zebra Router\n"
4265 "Summary Information\n")
4267 zebra_router_show_table_summary(vty
);
4272 /* Table configuration write function. */
4273 static int config_write_table(struct vty
*vty
)
4278 /* IPForwarding configuration write function. */
4279 static int config_write_forwarding(struct vty
*vty
)
4282 vty_out(vty
, "no ip forwarding\n");
4283 if (!ipforward_ipv6())
4284 vty_out(vty
, "no ipv6 forwarding\n");
4285 vty_out(vty
, "!\n");
4289 DEFUN_HIDDEN (show_frr
,
4295 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4296 vty_out(vty
, ".............................7777:..............................................\n");
4297 vty_out(vty
, ".............................777777,............................................\n");
4298 vty_out(vty
, "... .........................77777777,..........................................\n");
4299 vty_out(vty
, "............................=7777777777:........................................\n");
4300 vty_out(vty
, "........................:7777777777777777,......................................\n");
4301 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4302 vty_out(vty
, "...................I7777777777+.................................................\n");
4303 vty_out(vty
, "................,777777777?............ .......................................\n");
4304 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4305 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4306 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4307 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4308 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4309 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4310 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4311 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4312 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4313 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4314 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4315 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4316 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4317 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4318 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4319 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4320 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4321 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4322 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4323 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4324 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4325 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4326 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4327 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4328 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4329 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4330 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4331 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4332 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4333 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4334 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4335 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4336 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4337 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4338 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4339 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4340 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4341 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4342 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4343 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4344 vty_out(vty
, "................................~77777777...............=777777.................\n");
4345 vty_out(vty
, ".....................................:=?I................~777777................\n");
4346 vty_out(vty
, "..........................................................:777777,..............\n");
4347 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4353 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4354 zebra_kernel_netlink_batch_tx_buf_cmd
,
4355 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4357 "Zebra kernel interface\n"
4358 "Set Netlink parameters\n"
4359 "Set batch buffer size and send threshold\n"
4360 "Size of the buffer\n"
4363 uint32_t bufsize
= 0, threshold
= 0;
4365 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4366 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4368 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4373 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4374 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4375 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4377 "Zebra kernel interface\n"
4378 "Set Netlink parameters\n"
4379 "Set batch buffer size and send threshold\n"
4380 "Size of the buffer\n"
4383 netlink_set_batch_buffer_size(0, 0, false);
4388 DEFPY (zebra_protodown_bit
,
4389 zebra_protodown_bit_cmd
,
4390 "zebra protodown reason-bit (0-31)$bit",
4392 "Protodown Configuration\n"
4393 "Reason Bit used in the kernel for application\n"
4394 "Reason Bit range\n")
4396 if_netlink_set_frr_protodown_r_bit(bit
);
4400 DEFPY (no_zebra_protodown_bit
,
4401 no_zebra_protodown_bit_cmd
,
4402 "no zebra protodown reason-bit [(0-31)$bit]",
4405 "Protodown Configuration\n"
4406 "Reason Bit used in the kernel for setting protodown\n"
4407 "Reason Bit Range\n")
4409 if_netlink_unset_frr_protodown_r_bit();
4413 #endif /* HAVE_NETLINK */
4415 DEFUN(ip_table_range
, ip_table_range_cmd
,
4416 "[no] ip table range (1-4294967295) (1-4294967295)",
4418 "table configuration\n"
4419 "Configure table range\n"
4420 "Start Routing Table\n"
4421 "End Routing Table\n")
4423 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4428 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4430 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4434 if (strmatch(argv
[0]->text
, "no"))
4435 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4437 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4440 #ifdef HAVE_SCRIPTING
4442 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4443 "zebra on-rib-process script SCRIPT",
4445 "on_rib_process_dplane_results hook call\n"
4447 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4450 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4453 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4454 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4456 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4457 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4462 #endif /* HAVE_SCRIPTING */
4464 /* IP node for static routes. */
4465 static int zebra_ip_config(struct vty
*vty
);
4466 static struct cmd_node ip_node
= {
4467 .name
= "static ip",
4470 .config_write
= zebra_ip_config
,
4472 static int config_write_protocol(struct vty
*vty
);
4473 static struct cmd_node protocol_node
= {
4475 .node
= PROTOCOL_NODE
,
4477 .config_write
= config_write_protocol
,
4479 /* table node for routing tables. */
4480 static int config_write_table(struct vty
*vty
);
4481 static struct cmd_node table_node
= {
4485 .config_write
= config_write_table
,
4487 static int config_write_forwarding(struct vty
*vty
);
4488 static struct cmd_node forwarding_node
= {
4489 .name
= "forwarding",
4490 .node
= FORWARDING_NODE
,
4492 .config_write
= config_write_forwarding
,
4496 void zebra_vty_init(void)
4498 /* Install configuration write function. */
4499 install_node(&table_node
);
4500 install_node(&forwarding_node
);
4502 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4503 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4504 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4505 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4507 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4508 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4509 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4512 zebra_route_map_init();
4514 install_node(&ip_node
);
4515 install_node(&protocol_node
);
4517 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4518 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4520 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4521 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4523 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4524 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4525 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4526 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4527 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4528 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4529 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4530 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4531 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4532 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4534 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4535 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4537 install_element(VIEW_NODE
, &show_vrf_cmd
);
4538 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4539 install_element(VIEW_NODE
, &show_route_cmd
);
4540 install_element(VIEW_NODE
, &show_ro_cmd
);
4541 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4542 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4543 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4545 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4546 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4548 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4549 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4550 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4551 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4552 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4553 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4554 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4555 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4556 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4558 install_element(VIEW_NODE
, &show_frr_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4574 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4575 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4576 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4577 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4578 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4579 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4580 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4581 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4582 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4583 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4584 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4585 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4586 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4587 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4588 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4590 install_element(VIEW_NODE
, &show_neigh_cmd
);
4592 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4593 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4594 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4595 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4596 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4598 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4599 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4600 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4601 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4602 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4603 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4604 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4605 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4607 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4608 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4609 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4610 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4612 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4613 install_element(VRF_NODE
, &ip_table_range_cmd
);
4616 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4617 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4618 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4619 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4620 #endif /* HAVE_NETLINK */
4622 #ifdef HAVE_SCRIPTING
4623 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4624 #endif /* HAVE_SCRIPTING */
4626 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);