2 * Copyright (C) 2002 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "srcdest_table.h"
36 #include "termtable.h"
37 #include "affinitymap.h"
39 #include "zebra/zebra_router.h"
40 #include "zebra/zserv.h"
41 #include "zebra/zebra_vrf.h"
42 #include "zebra/zebra_mpls.h"
43 #include "zebra/zebra_rnh.h"
44 #include "zebra/redistribute.h"
45 #include "zebra/zebra_affinitymap.h"
46 #include "zebra/zebra_routemap.h"
48 #include "lib/route_opaque.h"
49 #include "zebra/zebra_vxlan.h"
50 #include "zebra/zebra_evpn_mh.h"
51 #include "zebra/zebra_vty_clippy.c"
52 #include "zebra/zserv.h"
53 #include "zebra/router-id.h"
54 #include "zebra/ipforward.h"
55 #include "zebra/zebra_vxlan_private.h"
56 #include "zebra/zebra_pbr.h"
57 #include "zebra/zebra_nhg.h"
58 #include "zebra/zebra_evpn_mh.h"
59 #include "zebra/interface.h"
60 #include "northbound_cli.h"
61 #include "zebra/zebra_nb.h"
62 #include "zebra/kernel_netlink.h"
63 #include "zebra/if_netlink.h"
64 #include "zebra/table_manager.h"
65 #include "zebra/zebra_script.h"
66 #include "zebra/rtadv.h"
67 #include "zebra/zebra_neigh.h"
69 /* context to manage dumps in multiple tables or vrfs */
70 struct route_show_ctx
{
71 bool multi
; /* dump multiple tables or vrf */
72 bool header_done
; /* common header already displayed */
75 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
76 safi_t safi
, bool use_fib
, bool use_json
,
78 const struct prefix
*longer_prefix_p
,
79 bool supernets_only
, int type
,
80 unsigned short ospf_instance_id
, uint32_t tableid
,
81 bool show_ng
, struct route_show_ctx
*ctx
);
82 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
83 int mcast
, bool use_fib
, bool show_ng
);
84 static void vty_show_ip_route_summary(struct vty
*vty
,
85 struct route_table
*table
, bool use_json
);
86 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
87 struct route_table
*table
,
89 /* Helper api to format a nexthop in the 'detailed' output path. */
90 static void show_nexthop_detail_helper(struct vty
*vty
,
91 const struct route_entry
*re
,
92 const struct nexthop
*nexthop
,
95 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
96 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
97 struct route_entry
*re
, unsigned int num
);
99 DEFUN (ip_multicast_mode
,
100 ip_multicast_mode_cmd
,
101 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
103 "Multicast options\n"
104 "RPF lookup behavior\n"
105 "Lookup in unicast RIB only\n"
106 "Lookup in multicast RIB only\n"
107 "Try multicast RIB first, fall back to unicast RIB\n"
108 "Lookup both, use entry with lower distance\n"
109 "Lookup both, use entry with longer prefix\n")
111 char *mode
= argv
[3]->text
;
113 if (strmatch(mode
, "urib-only"))
114 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
115 else if (strmatch(mode
, "mrib-only"))
116 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
117 else if (strmatch(mode
, "mrib-then-urib"))
118 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
119 else if (strmatch(mode
, "lower-distance"))
120 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
121 else if (strmatch(mode
, "longer-prefix"))
122 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
124 vty_out(vty
, "Invalid mode specified\n");
125 return CMD_WARNING_CONFIG_FAILED
;
131 DEFUN (no_ip_multicast_mode
,
132 no_ip_multicast_mode_cmd
,
133 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
136 "Multicast options\n"
137 "RPF lookup behavior\n"
138 "Lookup in unicast RIB only\n"
139 "Lookup in multicast RIB only\n"
140 "Try multicast RIB first, fall back to unicast RIB\n"
141 "Lookup both, use entry with lower distance\n"
142 "Lookup both, use entry with longer prefix\n")
144 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
151 "show ip rpf [json]",
154 "Display RPF information for multicast source\n"
157 bool uj
= use_json(argc
, argv
);
158 struct route_show_ctx ctx
= {
162 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
163 false, uj
, 0, NULL
, false, 0, 0, 0, false,
167 DEFUN (show_ip_rpf_addr
,
168 show_ip_rpf_addr_cmd
,
169 "show ip rpf A.B.C.D",
172 "Display RPF information for multicast source\n"
173 "IP multicast source address (e.g. 10.0.0.0)\n")
177 struct route_node
*rn
;
178 struct route_entry
*re
;
181 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
183 vty_out(vty
, "%% Malformed address\n");
187 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
190 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
192 vty_out(vty
, "%% No match for RPF lookup\n");
197 static char re_status_output_char(const struct route_entry
*re
,
198 const struct nexthop
*nhop
,
201 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
205 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
206 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
207 /* More-specific test for 'fib' output */
209 star_p
= !!CHECK_FLAG(nhop
->flags
,
215 if (zrouter
.asic_offloaded
&&
216 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
219 if (zrouter
.asic_offloaded
220 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
223 if (zrouter
.asic_offloaded
224 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
227 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
236 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
237 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
243 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
250 * Show backup nexthop info, in the 'detailed' output path
252 static void show_nh_backup_helper(struct vty
*vty
,
253 const struct route_entry
*re
,
254 const struct nexthop
*nexthop
)
256 const struct nexthop
*start
, *backup
, *temp
;
259 /* Double-check that there _is_ a backup */
260 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
261 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
262 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
265 /* Locate the backup nexthop(s) */
266 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
267 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
268 /* Format the backup(s) (indented) */
270 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
271 backup
= backup
->next
;
276 /* It's possible for backups to be recursive too,
277 * so walk the recursive resolution list if present.
282 show_nexthop_detail_helper(vty
, re
, backup
,
286 if (backup
->resolved
&& temp
== backup
)
287 backup
= backup
->resolved
;
289 backup
= nexthop_next(backup
);
291 if (backup
== temp
->next
)
299 * Helper api to format output for a nexthop, used in the 'detailed'
302 static void show_nexthop_detail_helper(struct vty
*vty
,
303 const struct route_entry
*re
,
304 const struct nexthop
*nexthop
,
308 char buf
[MPLS_LABEL_STRLEN
];
313 nexthop
->rparent
? " " : "");
315 vty_out(vty
, " %c%s",
316 re_status_output_char(re
, nexthop
, false),
317 nexthop
->rparent
? " " : "");
319 switch (nexthop
->type
) {
320 case NEXTHOP_TYPE_IPV4
:
321 case NEXTHOP_TYPE_IPV4_IFINDEX
:
322 vty_out(vty
, " %pI4",
323 &nexthop
->gate
.ipv4
);
324 if (nexthop
->ifindex
)
325 vty_out(vty
, ", via %s",
330 case NEXTHOP_TYPE_IPV6
:
331 case NEXTHOP_TYPE_IPV6_IFINDEX
:
333 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
335 if (nexthop
->ifindex
)
336 vty_out(vty
, ", via %s",
342 case NEXTHOP_TYPE_IFINDEX
:
343 vty_out(vty
, " directly connected, %s",
344 ifindex2ifname(nexthop
->ifindex
,
347 case NEXTHOP_TYPE_BLACKHOLE
:
348 vty_out(vty
, " unreachable");
349 switch (nexthop
->bh_type
) {
350 case BLACKHOLE_REJECT
:
351 vty_out(vty
, " (ICMP unreachable)");
353 case BLACKHOLE_ADMINPROHIB
:
355 " (ICMP admin-prohibited)");
358 vty_out(vty
, " (blackhole)");
360 case BLACKHOLE_UNSPEC
:
366 if (re
->vrf_id
!= nexthop
->vrf_id
) {
367 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
369 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
372 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
373 vty_out(vty
, " (duplicate nexthop removed)");
375 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
376 vty_out(vty
, " inactive");
378 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
379 vty_out(vty
, " onlink");
381 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
382 vty_out(vty
, " linkdown");
384 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
385 vty_out(vty
, " (recursive)");
387 /* Source specified? */
388 switch (nexthop
->type
) {
389 case NEXTHOP_TYPE_IPV4
:
390 case NEXTHOP_TYPE_IPV4_IFINDEX
:
391 if (nexthop
->src
.ipv4
.s_addr
) {
392 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
393 addrstr
, sizeof(addrstr
)))
394 vty_out(vty
, ", src %s",
399 case NEXTHOP_TYPE_IPV6
:
400 case NEXTHOP_TYPE_IPV6_IFINDEX
:
401 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
403 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
404 addrstr
, sizeof(addrstr
)))
405 vty_out(vty
, ", src %s",
410 case NEXTHOP_TYPE_IFINDEX
:
411 case NEXTHOP_TYPE_BLACKHOLE
:
416 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
418 /* Label information */
419 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
420 vty_out(vty
, ", label %s",
421 mpls_label2str(nexthop
->nh_label
->num_labels
,
422 nexthop
->nh_label
->label
, buf
,
423 sizeof(buf
), nexthop
->nh_label_type
,
428 vty_out(vty
, ", weight %u", nexthop
->weight
);
430 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
431 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
433 for (i
= 1; i
< nexthop
->backup_num
; i
++)
434 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
438 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
439 struct json_object
*json
)
441 struct bgp_zebra_opaque bzo
= {};
442 struct ospf_zebra_opaque ozo
= {};
448 case ZEBRA_ROUTE_SHARP
:
450 json_object_string_add(json
, "opaque",
451 (char *)re
->opaque
->data
);
453 vty_out(vty
, " Opaque Data: %s",
454 (char *)re
->opaque
->data
);
457 case ZEBRA_ROUTE_BGP
:
458 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
461 json_object_string_add(json
, "asPath", bzo
.aspath
);
462 json_object_string_add(json
, "communities",
464 json_object_string_add(json
, "largeCommunities",
466 json_object_string_add(json
, "selectionReason",
467 bzo
.selection_reason
);
469 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
471 if (bzo
.community
[0] != '\0')
472 vty_out(vty
, " Communities : %s\n",
475 if (bzo
.lcommunity
[0] != '\0')
476 vty_out(vty
, " Large-Communities: %s\n",
479 vty_out(vty
, " Selection reason : %s\n",
480 bzo
.selection_reason
);
483 case ZEBRA_ROUTE_OSPF
:
484 case ZEBRA_ROUTE_OSPF6
:
485 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
488 json_object_string_add(json
, "ospfPathType",
490 if (ozo
.area_id
[0] != '\0')
491 json_object_string_add(json
, "ospfAreaId",
493 if (ozo
.tag
[0] != '\0')
494 json_object_string_add(json
, "ospfTag",
497 vty_out(vty
, " OSPF path type : %s\n",
499 if (ozo
.area_id
[0] != '\0')
500 vty_out(vty
, " OSPF area ID : %s\n",
502 if (ozo
.tag
[0] != '\0')
503 vty_out(vty
, " OSPF tag : %s\n",
512 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
516 cur
= monotime(NULL
);
519 frrtime_to_interval(cur
, buf
, bufsize
);
522 /* New RIB. Detailed information for IPv4 route. */
523 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
524 int mcast
, bool use_fib
, bool show_ng
)
526 struct route_entry
*re
;
527 struct nexthop
*nexthop
;
528 char buf
[SRCDEST2STR_BUFFER
];
529 struct zebra_vrf
*zvrf
;
532 dest
= rib_dest_from_rnode(rn
);
534 RNODE_FOREACH_RE (rn
, re
) {
536 * If re not selected for forwarding, skip re
537 * for "show ip/ipv6 fib <prefix>"
539 if (use_fib
&& re
!= dest
->selected_fib
)
542 const char *mcast_info
= "";
544 struct rib_table_info
*info
=
545 srcdest_rnode_table_info(rn
);
546 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
547 ? " using Multicast RIB"
548 : " using Unicast RIB";
551 vty_out(vty
, "Routing entry for %s%s\n",
552 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
553 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
555 vty_out(vty
, "[%d]", re
->instance
);
557 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
560 vty_out(vty
, ", tag %u", re
->tag
);
561 #if defined(SUPPORT_REALMS)
562 if (re
->tag
> 0 && re
->tag
<= 255)
563 vty_out(vty
, "(realm)");
567 vty_out(vty
, ", mtu %u", re
->mtu
);
568 if (re
->vrf_id
!= VRF_DEFAULT
) {
569 zvrf
= vrf_info_lookup(re
->vrf_id
);
570 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
572 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
573 vty_out(vty
, ", best");
576 uptime2str(re
->uptime
, buf
, sizeof(buf
));
578 vty_out(vty
, " Last update %s ago\n", buf
);
581 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
582 if (re
->nhe_installed_id
!= 0
583 && re
->nhe_id
!= re
->nhe_installed_id
)
585 " Installed Nexthop Group ID: %u\n",
586 re
->nhe_installed_id
);
589 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
590 /* Use helper to format each nexthop */
591 show_nexthop_detail_helper(vty
, re
, nexthop
,
592 false /*not backup*/);
595 /* Include backup(s), if present */
596 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
597 show_nh_backup_helper(vty
, re
, nexthop
);
599 zebra_show_ip_route_opaque(vty
, re
, NULL
);
605 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
606 struct route_entry
*re
, json_object
*json
,
607 bool is_fib
, bool show_ng
)
609 const struct nexthop
*nexthop
;
611 char buf
[SRCDEST2STR_BUFFER
];
612 json_object
*json_nexthops
= NULL
;
613 json_object
*json_nexthop
= NULL
;
614 json_object
*json_route
= NULL
;
615 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
616 const struct nexthop_group
*nhg
;
617 char up_str
[MONOTIME_STRLEN
];
619 bool nhg_from_backup
= false;
621 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
623 /* If showing fib information, use the fib view of the
627 nhg
= rib_get_fib_nhg(re
);
629 nhg
= &(re
->nhe
->nhg
);
632 json_route
= json_object_new_object();
633 json_nexthops
= json_object_new_array();
635 json_object_string_add(json_route
, "prefix",
636 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
637 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
638 json_object_string_add(json_route
, "protocol",
639 zebra_route_string(re
->type
));
642 json_object_int_add(json_route
, "instance",
645 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
646 json_object_string_add(json_route
, "vrfName",
647 vrf_id_to_name(re
->vrf_id
));
649 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
650 json_object_boolean_true_add(json_route
, "selected");
652 if (dest
->selected_fib
== re
)
653 json_object_boolean_true_add(json_route
,
656 json_object_int_add(json_route
, "distance",
658 json_object_int_add(json_route
, "metric", re
->metric
);
660 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
661 json_object_boolean_true_add(json_route
, "installed");
663 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
664 json_object_boolean_true_add(json_route
, "failed");
666 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
667 json_object_boolean_true_add(json_route
, "queued");
669 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
670 json_object_boolean_true_add(json_route
, "trapped");
672 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
673 json_object_boolean_true_add(json_route
, "offloaded");
675 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
676 json_object_boolean_false_add(json_route
, "offloaded");
679 json_object_int_add(json_route
, "tag", re
->tag
);
682 json_object_int_add(json_route
, "table", re
->table
);
684 json_object_int_add(json_route
, "internalStatus",
686 json_object_int_add(json_route
, "internalFlags",
688 json_object_int_add(json_route
, "internalNextHopNum",
689 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
690 json_object_int_add(json_route
, "internalNextHopActiveNum",
691 nexthop_group_active_nexthop_num(
693 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
695 if (re
->nhe_installed_id
!= 0)
696 json_object_int_add(json_route
,
697 "installedNexthopGroupId",
698 re
->nhe_installed_id
);
700 json_object_string_add(json_route
, "uptime", up_str
);
702 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
703 json_nexthop
= json_object_new_object();
704 show_nexthop_json_helper(json_nexthop
,
707 json_object_array_add(json_nexthops
,
711 json_object_object_add(json_route
, "nexthops", json_nexthops
);
713 /* If there are backup nexthops, include them */
715 nhg
= rib_get_fib_backup_nhg(re
);
717 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
719 if (nhg
&& nhg
->nexthop
) {
720 json_nexthops
= json_object_new_array();
722 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
723 json_nexthop
= json_object_new_object();
725 show_nexthop_json_helper(json_nexthop
,
727 json_object_array_add(json_nexthops
,
731 json_object_object_add(json_route
, "backupNexthops",
734 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
736 json_object_array_add(json
, json_route
);
740 /* Prefix information, and first nexthop. If we're showing 'fib',
741 * and there are no installed primary nexthops, see if there are any
742 * backup nexthops and start with those.
744 if (is_fib
&& nhg
->nexthop
== NULL
) {
745 nhg
= rib_get_fib_backup_nhg(re
);
746 nhg_from_backup
= true;
749 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
751 len
+= vty_out(vty
, "[%d]", re
->instance
);
752 if (nhg_from_backup
&& nhg
->nexthop
) {
755 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
756 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
757 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
761 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
762 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
763 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
766 /* Distance and metric display. */
767 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
768 (re
->distance
|| re
->metric
)) ||
769 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
770 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
774 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
776 /* Nexthop information. */
777 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
780 } else if (nhg_from_backup
) {
781 vty_out(vty
, " b%c%*c",
782 re_status_output_char(re
, nexthop
, is_fib
),
783 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
785 vty_out(vty
, " %c%*c",
786 re_status_output_char(re
, nexthop
, is_fib
),
787 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
790 show_route_nexthop_helper(vty
, re
, nexthop
);
791 vty_out(vty
, ", %s\n", up_str
);
794 /* If we only had backup nexthops, we're done */
798 /* Check for backup nexthop info if present */
800 nhg
= rib_get_fib_backup_nhg(re
);
802 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
807 /* Print backup info */
808 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
812 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
814 /* TODO -- it'd be nice to be able to include
815 * the entire list of backups, *and* include the
816 * real installation state.
818 vty_out(vty
, " b%c %*c",
819 (star_p
? '*' : ' '),
820 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
821 show_route_nexthop_helper(vty
, re
, nexthop
);
827 static void vty_show_ip_route_detail_json(struct vty
*vty
,
828 struct route_node
*rn
, bool use_fib
)
830 json_object
*json
= NULL
;
831 json_object
*json_prefix
= NULL
;
832 struct route_entry
*re
;
836 dest
= rib_dest_from_rnode(rn
);
838 json
= json_object_new_object();
839 json_prefix
= json_object_new_array();
841 RNODE_FOREACH_RE (rn
, re
) {
843 * If re not selected for forwarding, skip re
844 * for "show ip/ipv6 fib <prefix> json"
846 if (use_fib
&& re
!= dest
->selected_fib
)
848 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
851 prefix2str(&rn
->p
, buf
, sizeof(buf
));
852 json_object_object_add(json
, buf
, json_prefix
);
856 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
857 struct route_table
*table
, afi_t afi
,
858 bool use_fib
, route_tag_t tag
,
859 const struct prefix
*longer_prefix_p
,
860 bool supernets_only
, int type
,
861 unsigned short ospf_instance_id
, bool use_json
,
862 uint32_t tableid
, bool show_ng
,
863 struct route_show_ctx
*ctx
)
865 struct route_node
*rn
;
866 struct route_entry
*re
;
869 json_object
*json
= NULL
;
870 json_object
*json_prefix
= NULL
;
875 * ctx->multi indicates if we are dumping multiple tables or vrfs.
877 * => display the common header at most once
878 * => add newline at each call except first
879 * => always display the VRF and table
881 * => display the common header if at least one entry is found
882 * => display the VRF and table if specific
886 json
= json_object_new_object();
888 /* Show all routes. */
889 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
890 dest
= rib_dest_from_rnode(rn
);
892 RNODE_FOREACH_RE (rn
, re
) {
893 if (use_fib
&& re
!= dest
->selected_fib
)
896 if (tag
&& re
->tag
!= tag
)
900 && !prefix_match(longer_prefix_p
, &rn
->p
))
903 /* This can only be true when the afi is IPv4 */
904 if (supernets_only
) {
905 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
907 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
910 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
913 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
917 if (type
&& re
->type
!= type
)
921 && (re
->type
!= ZEBRA_ROUTE_OSPF
922 || re
->instance
!= ospf_instance_id
))
927 json_prefix
= json_object_new_array();
929 if (!ctx
->header_done
) {
932 SHOW_ROUTE_V4_HEADER
);
935 SHOW_ROUTE_V6_HEADER
);
937 if (ctx
->multi
&& ctx
->header_done
)
939 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
942 vty_out(vty
, "VRF %s:\n",
946 "VRF %s table %u:\n",
950 ctx
->header_done
= true;
954 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
959 prefix2str(&rn
->p
, buf
, sizeof(buf
));
960 json_object_object_add(json
, buf
, json_prefix
);
969 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
970 afi_t afi
, bool use_fib
, bool use_json
,
972 const struct prefix
*longer_prefix_p
,
973 bool supernets_only
, int type
,
974 unsigned short ospf_instance_id
, bool show_ng
,
975 struct route_show_ctx
*ctx
)
977 struct zebra_router_table
*zrt
;
978 struct rib_table_info
*info
;
980 RB_FOREACH (zrt
, zebra_router_table_head
,
982 info
= route_table_get_info(zrt
->table
);
984 if (zvrf
!= info
->zvrf
)
986 if (zrt
->afi
!= afi
||
987 zrt
->safi
!= SAFI_UNICAST
)
990 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
991 use_fib
, use_json
, tag
, longer_prefix_p
,
992 supernets_only
, type
, ospf_instance_id
,
993 zrt
->tableid
, show_ng
, ctx
);
997 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
998 safi_t safi
, bool use_fib
, bool use_json
,
1000 const struct prefix
*longer_prefix_p
,
1001 bool supernets_only
, int type
,
1002 unsigned short ospf_instance_id
, uint32_t tableid
,
1003 bool show_ng
, struct route_show_ctx
*ctx
)
1005 struct route_table
*table
;
1006 struct zebra_vrf
*zvrf
= NULL
;
1008 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1010 vty_out(vty
, "{}\n");
1012 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1016 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1018 vty_out(vty
, "{}\n");
1020 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1025 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1027 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1030 vty_out(vty
, "{}\n");
1034 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1035 longer_prefix_p
, supernets_only
, type
,
1036 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1043 "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
1047 "IP nexthop tracking table\n"
1048 "IP import check tracking table\n"
1054 VRF_ALL_CMD_HELP_STR
1055 "Show Multicast (MRIB) NHT state\n"
1058 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1059 vrf_id_t vrf_id
= VRF_DEFAULT
;
1060 struct prefix prefix
, *p
= NULL
;
1061 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1062 bool uj
= use_json(argc
, argv
);
1063 json_object
*json
= NULL
;
1064 json_object
*json_vrf
= NULL
;
1065 json_object
*json_nexthop
= NULL
;
1068 json
= json_object_new_object();
1072 struct zebra_vrf
*zvrf
;
1074 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1075 if ((zvrf
= vrf
->info
) != NULL
) {
1077 json_vrf
= json_object_new_object();
1078 json_nexthop
= json_object_new_object();
1079 json_object_object_add(json
,
1082 json_object_object_add(json_vrf
,
1088 vty_out(vty
, "\nVRF %s:\n",
1091 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1092 vty
, NULL
, json_nexthop
);
1097 vty_json(vty
, json
);
1102 VRF_GET_ID(vrf_id
, vrf_name
, false);
1104 memset(&prefix
, 0, sizeof(prefix
));
1106 p
= sockunion2hostprefix(addr
, &prefix
);
1109 json_object_free(json
);
1115 json_vrf
= json_object_new_object();
1116 json_nexthop
= json_object_new_object();
1118 json_object_object_add(json
, vrf_name
, json_vrf
);
1120 json_object_object_add(json
, "default", json_vrf
);
1122 json_object_object_add(json_vrf
,
1123 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1127 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1130 vty_json(vty
, json
);
1135 DEFUN (ip_nht_default_route
,
1136 ip_nht_default_route_cmd
,
1137 "ip nht resolve-via-default",
1139 "Filter Next Hop tracking route resolution\n"
1140 "Resolve via default route\n")
1142 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1147 if (zvrf
->zebra_rnh_ip_default_route
)
1150 zvrf
->zebra_rnh_ip_default_route
= true;
1152 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1156 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1157 json_object
*json_nhe_hdr
)
1159 struct nexthop
*nexthop
= NULL
;
1160 struct nhg_connected
*rb_node_dep
= NULL
;
1161 struct nexthop_group
*backup_nhg
;
1162 char up_str
[MONOTIME_STRLEN
];
1163 char time_left
[MONOTIME_STRLEN
];
1164 json_object
*json_dependants
= NULL
;
1165 json_object
*json_depends
= NULL
;
1166 json_object
*json_nexthop_array
= NULL
;
1167 json_object
*json_nexthops
= NULL
;
1168 json_object
*json
= NULL
;
1169 json_object
*json_backup_nexthop_array
= NULL
;
1170 json_object
*json_backup_nexthops
= NULL
;
1173 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1176 json
= json_object_new_object();
1179 json_object_string_add(json
, "type",
1180 zebra_route_string(nhe
->type
));
1181 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1182 if (thread_is_scheduled(nhe
->timer
))
1183 json_object_string_add(
1184 json
, "timeToDeletion",
1185 thread_timer_to_hhmmss(time_left
,
1188 json_object_string_add(json
, "uptime", up_str
);
1189 json_object_string_add(json
, "vrf",
1190 vrf_id_to_name(nhe
->vrf_id
));
1193 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1194 zebra_route_string(nhe
->type
));
1195 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1196 if (thread_is_scheduled(nhe
->timer
))
1197 vty_out(vty
, " Time to Deletion: %s",
1198 thread_timer_to_hhmmss(time_left
,
1203 vty_out(vty
, " Uptime: %s\n", up_str
);
1204 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1207 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1209 json_object_boolean_true_add(json
, "valid");
1211 vty_out(vty
, " Valid");
1213 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1215 json_object_boolean_true_add(json
, "installed");
1217 vty_out(vty
, ", Installed");
1224 json_object_int_add(json
, "interfaceIndex",
1227 vty_out(vty
, " Interface Index: %d\n",
1231 if (!zebra_nhg_depends_is_empty(nhe
)) {
1233 json_depends
= json_object_new_array();
1235 vty_out(vty
, " Depends:");
1236 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1238 json_object_array_add(
1240 json_object_new_int(
1241 rb_node_dep
->nhe
->id
));
1243 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1248 json_object_object_add(json
, "depends", json_depends
);
1251 /* Output nexthops */
1253 json_nexthop_array
= json_object_new_array();
1256 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1257 if (json_nexthop_array
) {
1258 json_nexthops
= json_object_new_object();
1259 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1261 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1264 /* Make recursive nexthops a bit more clear */
1266 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1269 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1270 if (CHECK_FLAG(nexthop
->flags
,
1271 NEXTHOP_FLAG_HAS_BACKUP
)) {
1273 json_object_int_add(
1274 json_nexthops
, "backup",
1275 nexthop
->backup_idx
[0]);
1277 vty_out(vty
, " [backup %d]",
1278 nexthop
->backup_idx
[0]);
1284 json_object_array_add(json_nexthop_array
,
1291 /* TODO -- print more useful backup info */
1292 if (CHECK_FLAG(nexthop
->flags
,
1293 NEXTHOP_FLAG_HAS_BACKUP
)) {
1296 vty_out(vty
, "[backup");
1297 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1299 nexthop
->backup_idx
[i
]);
1304 json_object_array_add(json_nexthop_array
,
1310 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1312 /* Output backup nexthops (if any) */
1313 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1316 json_backup_nexthop_array
= json_object_new_array();
1318 vty_out(vty
, " Backups:\n");
1320 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1321 if (json_backup_nexthop_array
) {
1322 json_backup_nexthops
= json_object_new_object();
1323 show_nexthop_json_helper(json_backup_nexthops
,
1325 json_object_array_add(json_backup_nexthop_array
,
1326 json_backup_nexthops
);
1329 if (!CHECK_FLAG(nexthop
->flags
,
1330 NEXTHOP_FLAG_RECURSIVE
))
1333 /* Make recursive nexthops a bit more
1337 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1343 json_object_object_add(json
, "backupNexthops",
1344 json_backup_nexthop_array
);
1347 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1349 json_dependants
= json_object_new_array();
1351 vty_out(vty
, " Dependents:");
1352 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1355 json_object_array_add(
1357 json_object_new_int(
1358 rb_node_dep
->nhe
->id
));
1360 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1363 json_object_object_add(json
, "dependents",
1369 if (nhe
->nhg
.nhgr
.buckets
) {
1371 json_object_int_add(json
, "buckets",
1372 nhe
->nhg
.nhgr
.buckets
);
1373 json_object_int_add(json
, "idleTimer",
1374 nhe
->nhg
.nhgr
.idle_timer
);
1375 json_object_int_add(json
, "unbalancedTimer",
1376 nhe
->nhg
.nhgr
.unbalanced_timer
);
1377 json_object_int_add(json
, "unbalancedTime",
1378 nhe
->nhg
.nhgr
.unbalanced_time
);
1381 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1383 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1384 nhe
->nhg
.nhgr
.unbalanced_timer
,
1385 nhe
->nhg
.nhgr
.unbalanced_time
);
1390 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1393 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1396 struct nhg_hash_entry
*nhe
= NULL
;
1398 nhe
= zebra_nhg_lookup_id(id
);
1401 show_nexthop_group_out(vty
, nhe
, json
);
1404 vty_json(vty
, json
);
1406 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1412 vty_json(vty
, json
);
1417 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1419 struct nhe_show_context
{
1427 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1429 struct nhe_show_context
*ctx
= arg
;
1430 struct nhg_hash_entry
*nhe
;
1432 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1434 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1437 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1440 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1443 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1446 return HASHWALK_CONTINUE
;
1449 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1450 struct zebra_vrf
*zvrf
, afi_t afi
,
1451 int type
, json_object
*json
)
1453 struct nhe_show_context ctx
;
1457 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1461 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1464 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1466 struct zebra_if
*zebra_if
= NULL
;
1467 struct nhg_connected
*rb_node_dep
= NULL
;
1469 zebra_if
= ifp
->info
;
1471 if (!if_nhg_dependents_is_empty(ifp
)) {
1472 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1474 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1477 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1482 DEFPY (show_interface_nexthop_group
,
1483 show_interface_nexthop_group_cmd
,
1484 "show interface [IFNAME$if_name] nexthop-group",
1486 "Interface status and configuration\n"
1488 "Show Nexthop Groups\n")
1490 struct vrf
*vrf
= NULL
;
1491 struct interface
*ifp
= NULL
;
1494 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1496 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1498 if_nexthop_group_dump_vty(vty
, ifp
);
1502 FOR_ALL_INTERFACES (vrf
, ifp
)
1503 if_nexthop_group_dump_vty(vty
, ifp
);
1509 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1516 DEFPY(show_nexthop_group
,
1517 show_nexthop_group_cmd
,
1518 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]",
1520 "Show Nexthop Groups\n"
1522 "Nexthop Group ID\n"
1523 "Show Singleton Nexthop-Groups\n"
1526 "Kernel (not installed via the zebra RIB)\n"
1527 "Zebra (implicitly created by zebra)\n"
1528 "Border Gateway Protocol (BGP)\n"
1529 "Super Happy Advanced Routing Protocol (SHARP)\n"
1530 VRF_FULL_CMD_HELP_STR
1534 struct zebra_vrf
*zvrf
= NULL
;
1535 afi_t afi
= AFI_UNSPEC
;
1537 bool uj
= use_json(argc
, argv
);
1538 json_object
*json
= NULL
;
1539 json_object
*json_vrf
= NULL
;
1542 json
= json_object_new_object();
1545 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1553 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1556 type
= ZEBRA_ROUTE_NHG
;
1560 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1562 vty_json(vty
, json
);
1565 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1572 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1573 struct zebra_vrf
*zvrf
;
1579 json_vrf
= json_object_new_object();
1581 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1583 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1586 json_object_object_add(json
, vrf
->name
,
1591 vty_json(vty
, json
);
1597 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1599 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1603 vty_json(vty
, json
);
1605 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1610 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1613 vty_json(vty
, json
);
1618 DEFPY_HIDDEN(nexthop_group_use_enable
,
1619 nexthop_group_use_enable_cmd
,
1620 "[no] zebra nexthop kernel enable",
1623 "Nexthop configuration \n"
1624 "Configure use of kernel nexthops\n"
1625 "Enable kernel nexthops\n")
1627 zebra_nhg_enable_kernel_nexthops(!no
);
1631 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1632 "[no] zebra nexthop proto only",
1634 "Nexthop configuration\n"
1635 "Configure exclusive use of proto nexthops\n"
1636 "Only use proto nexthops\n")
1638 zebra_nhg_set_proto_nexthops_only(!no
);
1642 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1643 backup_nexthop_recursive_use_enable_cmd
,
1644 "[no] zebra nexthop resolve-via-backup",
1647 "Nexthop configuration \n"
1648 "Configure use of backup nexthops in recursive resolution\n")
1650 zebra_nhg_set_recursive_use_backups(!no
);
1654 DEFUN (no_ip_nht_default_route
,
1655 no_ip_nht_default_route_cmd
,
1656 "no ip nht resolve-via-default",
1659 "Filter Next Hop tracking route resolution\n"
1660 "Resolve via default route\n")
1662 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1667 if (!zvrf
->zebra_rnh_ip_default_route
)
1670 zvrf
->zebra_rnh_ip_default_route
= false;
1671 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1675 DEFUN (ipv6_nht_default_route
,
1676 ipv6_nht_default_route_cmd
,
1677 "ipv6 nht resolve-via-default",
1679 "Filter Next Hop tracking route resolution\n"
1680 "Resolve via default route\n")
1682 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1687 if (zvrf
->zebra_rnh_ipv6_default_route
)
1690 zvrf
->zebra_rnh_ipv6_default_route
= true;
1691 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1695 DEFUN (no_ipv6_nht_default_route
,
1696 no_ipv6_nht_default_route_cmd
,
1697 "no ipv6 nht resolve-via-default",
1700 "Filter Next Hop tracking route resolution\n"
1701 "Resolve via default route\n")
1703 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1708 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1711 zvrf
->zebra_rnh_ipv6_default_route
= false;
1712 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1716 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1717 "[no] ip nht hide-backup-events",
1720 "Nexthop-tracking configuration\n"
1721 "Hide notification about backup nexthops\n")
1723 rnh_set_hide_backups(!no
);
1731 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1732 [vrf <NAME$vrf_name|all$vrf_all>]\
1735 |A.B.C.D/M$prefix longer-prefixes\
1736 |supernets-only$supernets_only\
1739 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1740 |ospf$type_str (1-65535)$ospf_instance_id\
1742 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1743 [vrf <NAME$vrf_name|all$vrf_all>]\
1746 |X:X::X:X/M$prefix longer-prefixes\
1748 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1750 [<json$json|nexthop-group$ng>]",
1753 "IP forwarding table\n"
1754 "IP routing table\n"
1755 "Table to display\n"
1756 "The table number to display\n"
1758 VRF_FULL_CMD_HELP_STR
1759 "Show only routes with tag\n"
1761 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1762 "Show route matching the specified Network/Mask pair only\n"
1763 "Show supernet entries only\n"
1764 FRR_IP_REDIST_HELP_STR_ZEBRA
1765 "Open Shortest Path First (OSPFv2)\n"
1768 "IP forwarding table\n"
1769 "IP routing table\n"
1770 "Table to display\n"
1771 "The table number to display\n"
1773 VRF_FULL_CMD_HELP_STR
1774 "Show only routes with tag\n"
1777 "Show route matching the specified Network/Mask pair only\n"
1778 FRR_IP6_REDIST_HELP_STR_ZEBRA
1780 "Nexthop Group Information\n")
1782 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1785 struct zebra_vrf
*zvrf
;
1786 struct route_show_ctx ctx
= {
1787 .multi
= vrf_all
|| table_all
,
1790 if (!vrf_is_backend_netns()) {
1791 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1793 vty_out(vty
, "{}\n");
1795 vty_out(vty
, "Linux vrf backend already points to table id\n");
1796 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1802 type
= proto_redistnum(afi
, type_str
);
1804 vty_out(vty
, "Unknown route type\n");
1810 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1811 if ((zvrf
= vrf
->info
) == NULL
1812 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1816 do_show_ip_route_all(
1817 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1818 prefix_str
? prefix
: NULL
,
1819 !!supernets_only
, type
,
1820 ospf_instance_id
, !!ng
, &ctx
);
1823 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1825 prefix_str
? prefix
: NULL
,
1826 !!supernets_only
, type
,
1827 ospf_instance_id
, table
, !!ng
, &ctx
);
1830 vrf_id_t vrf_id
= VRF_DEFAULT
;
1833 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1834 vrf
= vrf_lookup_by_id(vrf_id
);
1843 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1844 prefix_str
? prefix
: NULL
,
1845 !!supernets_only
, type
,
1846 ospf_instance_id
, !!ng
, &ctx
);
1848 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1850 prefix_str
? prefix
: NULL
,
1851 !!supernets_only
, type
,
1852 ospf_instance_id
, table
, !!ng
, &ctx
);
1858 ALIAS_HIDDEN (show_route
,
1860 "show <ip$ipv4|ipv6$ipv6> ro",
1864 "IP routing table\n");
1867 DEFPY (show_route_detail
,
1868 show_route_detail_cmd
,
1871 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1876 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1882 [json$json] [nexthop-group$ng]",
1885 "IP forwarding table\n"
1886 "IP routing table\n"
1887 VRF_FULL_CMD_HELP_STR
1888 "Network in the IP routing table to display\n"
1889 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1891 "IPv6 forwarding table\n"
1892 "IPv6 routing table\n"
1893 VRF_FULL_CMD_HELP_STR
1897 "Nexthop Group Information\n")
1899 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1900 struct route_table
*table
;
1902 struct route_node
*rn
;
1903 bool use_fib
= !!fib
;
1905 bool network_found
= false;
1906 bool show_ng
= !!ng
;
1909 prefix_str
= address_str
;
1910 if (str2prefix(prefix_str
, &p
) < 0) {
1911 vty_out(vty
, "%% Malformed address\n");
1917 struct zebra_vrf
*zvrf
;
1919 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1920 if ((zvrf
= vrf
->info
) == NULL
1921 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1924 rn
= route_node_match(table
, &p
);
1927 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1928 route_unlock_node(rn
);
1932 dest
= rib_dest_from_rnode(rn
);
1933 if (use_fib
&& !dest
->selected_fib
) {
1934 route_unlock_node(rn
);
1938 network_found
= true;
1940 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1942 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1945 route_unlock_node(rn
);
1948 if (!network_found
) {
1950 vty_out(vty
, "{}\n");
1954 "%% Network not in FIB\n");
1957 "%% Network not in RIB\n");
1962 vrf_id_t vrf_id
= VRF_DEFAULT
;
1965 VRF_GET_ID(vrf_id
, vrf_name
, false);
1967 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1971 rn
= route_node_match(table
, &p
);
1973 dest
= rib_dest_from_rnode(rn
);
1975 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1976 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1978 vty_out(vty
, "{}\n");
1982 "%% Network not in FIB\n");
1985 "%% Network not in table\n");
1988 route_unlock_node(rn
);
1993 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1995 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1997 route_unlock_node(rn
);
2003 DEFPY (show_route_summary
,
2004 show_route_summary_cmd
,
2005 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2006 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2010 "IP routing table\n"
2011 VRF_FULL_CMD_HELP_STR
2012 "Summary of all routes\n"
2013 "Table to display summary for\n"
2014 "The table number\n"
2018 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2019 struct route_table
*table
;
2020 bool uj
= use_json(argc
, argv
);
2024 struct zebra_vrf
*zvrf
;
2026 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2027 if ((zvrf
= vrf
->info
) == NULL
)
2031 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2034 table
= zebra_vrf_lookup_table_with_table_id(
2035 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2042 vty_show_ip_route_summary_prefix(vty
, table
,
2045 vty_show_ip_route_summary(vty
, table
, uj
);
2048 vrf_id_t vrf_id
= VRF_DEFAULT
;
2051 VRF_GET_ID(vrf_id
, vrf_name
, false);
2054 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2056 table
= zebra_vrf_lookup_table_with_table_id(
2057 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2062 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2064 vty_show_ip_route_summary(vty
, table
, uj
);
2070 DEFUN_HIDDEN (show_route_zebra_dump
,
2071 show_route_zebra_dump_cmd
,
2072 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2082 struct route_table
*table
;
2083 const char *vrf_name
= NULL
;
2086 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2088 if (argv_find(argv
, argc
, "vrf", &idx
))
2089 vrf_name
= argv
[++idx
]->arg
;
2093 struct zebra_vrf
*zvrf
;
2095 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2098 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2101 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2102 show_ip_route_dump_vty(vty
, table
);
2105 vrf_id_t vrf_id
= VRF_DEFAULT
;
2107 VRF_GET_ID(vrf_id
, vrf_name
, true);
2109 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2113 show_ip_route_dump_vty(vty
, table
);
2119 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2120 struct route_entry
*re
, unsigned int num
)
2123 char buf
[SRCDEST2STR_BUFFER
];
2125 vty_out(vty
, " Nexthop %u:\n", num
);
2126 vty_out(vty
, " type: %u\n", nexthop
->type
);
2127 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2128 switch (nexthop
->type
) {
2129 case NEXTHOP_TYPE_IPV4
:
2130 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2131 vty_out(vty
, " ip address: %s\n",
2132 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2134 vty_out(vty
, " afi: ipv4\n");
2136 if (nexthop
->ifindex
) {
2137 vty_out(vty
, " interface index: %d\n",
2139 vty_out(vty
, " interface name: %s\n",
2140 ifindex2ifname(nexthop
->ifindex
,
2144 if (nexthop
->src
.ipv4
.s_addr
2145 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2147 vty_out(vty
, " source: %s\n", buf
);
2149 case NEXTHOP_TYPE_IPV6
:
2150 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2151 vty_out(vty
, " ip: %s\n",
2152 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2154 vty_out(vty
, " afi: ipv6\n");
2156 if (nexthop
->ifindex
) {
2157 vty_out(vty
, " interface index: %d\n",
2159 vty_out(vty
, " interface name: %s\n",
2160 ifindex2ifname(nexthop
->ifindex
,
2164 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2165 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2167 vty_out(vty
, " source: %s\n", buf
);
2170 case NEXTHOP_TYPE_IFINDEX
:
2172 " Nexthop is an interface (directly connected).\n");
2173 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2174 vty_out(vty
, " interface name: %s\n",
2175 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2177 case NEXTHOP_TYPE_BLACKHOLE
:
2178 vty_out(vty
, " Nexthop type is blackhole.\n");
2180 switch (nexthop
->bh_type
) {
2181 case BLACKHOLE_REJECT
:
2182 vty_out(vty
, " Blackhole type: reject\n");
2184 case BLACKHOLE_ADMINPROHIB
:
2186 " Blackhole type: admin-prohibited\n");
2188 case BLACKHOLE_NULL
:
2189 vty_out(vty
, " Blackhole type: NULL0\n");
2191 case BLACKHOLE_UNSPEC
:
2198 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2200 struct route_node
*rn
;
2201 struct route_entry
*re
;
2202 char buf
[SRCDEST2STR_BUFFER
];
2207 struct nexthop
*nexthop
= NULL
;
2208 int nexthop_num
= 0;
2210 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2211 vty_out(vty
, "----------------------------\n");
2213 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2214 RNODE_FOREACH_RE (rn
, re
) {
2215 vty_out(vty
, "Route: %s\n",
2216 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2217 vty_out(vty
, " protocol: %s\n",
2218 zebra_route_string(re
->type
));
2219 vty_out(vty
, " instance: %u\n", re
->instance
);
2220 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2221 vty_out(vty
, " VRF name: %s\n",
2222 vrf_id_to_name(re
->vrf_id
));
2223 vty_out(vty
, " flags: %u\n", re
->flags
);
2225 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2226 vty_out(vty
, " distance: %u\n", re
->distance
);
2227 vty_out(vty
, " metric: %u\n", re
->metric
);
2230 vty_out(vty
, " tag: %u\n", re
->tag
);
2232 uptime
= monotime(&tv
);
2233 uptime
-= re
->uptime
;
2234 gmtime_r(&uptime
, &tm
);
2236 if (uptime
< ONE_DAY_SECOND
)
2237 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2238 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2239 else if (uptime
< ONE_WEEK_SECOND
)
2240 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2241 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2243 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2245 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2248 vty_out(vty
, " status: %u\n", re
->status
);
2249 vty_out(vty
, " nexthop_num: %u\n",
2250 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2251 vty_out(vty
, " nexthop_active_num: %u\n",
2252 nexthop_group_active_nexthop_num(
2254 vty_out(vty
, " table: %u\n", re
->table
);
2255 vty_out(vty
, " uptime: %s\n", time
);
2257 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2259 show_ip_route_nht_dump(vty
, nexthop
, re
,
2269 static void vty_show_ip_route_summary(struct vty
*vty
,
2270 struct route_table
*table
, bool use_json
)
2272 struct route_node
*rn
;
2273 struct route_entry
*re
;
2274 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2275 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2276 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2277 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2278 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2279 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2282 json_object
*json_route_summary
= NULL
;
2283 json_object
*json_route_routes
= NULL
;
2285 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2286 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2287 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2288 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2291 json_route_summary
= json_object_new_object();
2292 json_route_routes
= json_object_new_array();
2293 json_object_object_add(json_route_summary
, "routes",
2297 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2298 RNODE_FOREACH_RE (rn
, re
) {
2299 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2300 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2302 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2304 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2306 rib_cnt
[re
->type
]++;
2308 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2309 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2312 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2314 fib_cnt
[re
->type
]++;
2317 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2319 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2321 trap_cnt
[re
->type
]++;
2324 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2326 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2328 offload_cnt
[re
->type
]++;
2333 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2335 zvrf_name(((struct rib_table_info
*)
2336 route_table_get_info(table
))
2339 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2340 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2341 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2342 if (i
== ZEBRA_ROUTE_BGP
) {
2344 json_object
*json_route_ebgp
=
2345 json_object_new_object();
2347 json_object_int_add(
2348 json_route_ebgp
, "fib",
2349 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2350 json_object_int_add(
2351 json_route_ebgp
, "rib",
2352 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2353 json_object_int_add(
2354 json_route_ebgp
, "fibOffLoaded",
2355 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2356 json_object_int_add(
2357 json_route_ebgp
, "fibTrapped",
2358 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2360 json_object_string_add(json_route_ebgp
,
2362 json_object_array_add(json_route_routes
,
2365 json_object
*json_route_ibgp
=
2366 json_object_new_object();
2368 json_object_int_add(
2369 json_route_ibgp
, "fib",
2370 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2371 json_object_int_add(
2372 json_route_ibgp
, "rib",
2373 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2374 json_object_int_add(
2375 json_route_ibgp
, "fibOffLoaded",
2376 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2377 json_object_int_add(
2378 json_route_ibgp
, "fibTrapped",
2379 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2380 json_object_string_add(json_route_ibgp
,
2382 json_object_array_add(json_route_routes
,
2385 vty_out(vty
, "%-20s %-20d %-20d \n",
2387 rib_cnt
[ZEBRA_ROUTE_BGP
],
2388 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2389 vty_out(vty
, "%-20s %-20d %-20d \n",
2391 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2392 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2396 json_object
*json_route_type
=
2397 json_object_new_object();
2399 json_object_int_add(json_route_type
,
2401 json_object_int_add(json_route_type
,
2404 json_object_int_add(json_route_type
,
2407 json_object_int_add(json_route_type
,
2410 json_object_string_add(
2411 json_route_type
, "type",
2412 zebra_route_string(i
));
2413 json_object_array_add(json_route_routes
,
2416 vty_out(vty
, "%-20s %-20d %-20d \n",
2417 zebra_route_string(i
),
2418 rib_cnt
[i
], fib_cnt
[i
]);
2424 json_object_int_add(json_route_summary
, "routesTotal",
2425 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2426 json_object_int_add(json_route_summary
, "routesTotalFib",
2427 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2429 vty_json(vty
, json_route_summary
);
2431 vty_out(vty
, "------\n");
2432 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2433 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2439 * Implementation of the ip route summary prefix command.
2441 * This command prints the primary prefixes that have been installed by various
2442 * protocols on the box.
2445 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2446 struct route_table
*table
,
2449 struct route_node
*rn
;
2450 struct route_entry
*re
;
2451 struct nexthop
*nexthop
;
2452 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2453 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2454 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2455 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2458 json_object
*json_route_summary
= NULL
;
2459 json_object
*json_route_routes
= NULL
;
2461 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2462 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2465 json_route_summary
= json_object_new_object();
2466 json_route_routes
= json_object_new_array();
2467 json_object_object_add(json_route_summary
, "prefixRoutes",
2471 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2472 RNODE_FOREACH_RE (rn
, re
) {
2475 * In case of ECMP, count only once.
2478 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2479 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2480 fib_cnt
[re
->type
]++;
2482 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2483 nexthop
= nexthop
->next
) {
2485 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2486 rib_cnt
[re
->type
]++;
2487 if (re
->type
== ZEBRA_ROUTE_BGP
2488 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2489 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2490 if (CHECK_FLAG(re
->status
,
2491 ROUTE_ENTRY_INSTALLED
))
2492 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2498 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2499 "Prefix Routes", "FIB",
2500 zvrf_name(((struct rib_table_info
*)
2501 route_table_get_info(table
))
2504 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2505 if (rib_cnt
[i
] > 0) {
2506 if (i
== ZEBRA_ROUTE_BGP
) {
2508 json_object
*json_route_ebgp
=
2509 json_object_new_object();
2511 json_object_int_add(
2512 json_route_ebgp
, "fib",
2513 fib_cnt
[ZEBRA_ROUTE_BGP
]
2514 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2515 json_object_int_add(
2516 json_route_ebgp
, "rib",
2517 rib_cnt
[ZEBRA_ROUTE_BGP
]
2518 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2519 json_object_string_add(json_route_ebgp
,
2521 json_object_array_add(json_route_routes
,
2524 json_object
*json_route_ibgp
=
2525 json_object_new_object();
2527 json_object_int_add(
2528 json_route_ibgp
, "fib",
2529 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2530 json_object_int_add(
2531 json_route_ibgp
, "rib",
2532 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2533 json_object_string_add(json_route_ibgp
,
2535 json_object_array_add(json_route_routes
,
2538 vty_out(vty
, "%-20s %-20d %-20d \n",
2540 rib_cnt
[ZEBRA_ROUTE_BGP
]
2541 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2542 fib_cnt
[ZEBRA_ROUTE_BGP
]
2543 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2544 vty_out(vty
, "%-20s %-20d %-20d \n",
2546 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2547 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2551 json_object
*json_route_type
=
2552 json_object_new_object();
2554 json_object_int_add(json_route_type
,
2556 json_object_int_add(json_route_type
,
2558 json_object_string_add(
2559 json_route_type
, "type",
2560 zebra_route_string(i
));
2561 json_object_array_add(json_route_routes
,
2564 vty_out(vty
, "%-20s %-20d %-20d \n",
2565 zebra_route_string(i
),
2566 rib_cnt
[i
], fib_cnt
[i
]);
2572 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2573 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2574 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2575 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2577 vty_json(vty
, json_route_summary
);
2579 vty_out(vty
, "------\n");
2580 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2581 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2586 DEFUN (allow_external_route_update
,
2587 allow_external_route_update_cmd
,
2588 "allow-external-route-update",
2589 "Allow FRR routes to be overwritten by external processes\n")
2591 zrouter
.allow_delete
= true;
2596 DEFUN (no_allow_external_route_update
,
2597 no_allow_external_route_update_cmd
,
2598 "no allow-external-route-update",
2600 "Allow FRR routes to be overwritten by external processes\n")
2602 zrouter
.allow_delete
= false;
2615 struct zebra_vrf
*zvrf
;
2617 if (vrf_is_backend_netns())
2618 vty_out(vty
, "netns-based vrfs\n");
2620 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2621 if (!(zvrf
= vrf
->info
))
2623 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2626 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2627 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2628 vty_out(vty
, "inactive");
2629 else if (zvrf_ns_name(zvrf
))
2630 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2631 zvrf_ns_name(zvrf
));
2633 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2635 if (vrf_is_user_cfged(vrf
))
2636 vty_out(vty
, " (configured)");
2643 DEFPY (evpn_mh_mac_holdtime
,
2644 evpn_mh_mac_holdtime_cmd
,
2645 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2650 "Duration in seconds\n")
2652 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2656 DEFPY (evpn_mh_neigh_holdtime
,
2657 evpn_mh_neigh_holdtime_cmd
,
2658 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2662 "Neighbor entry hold time\n"
2663 "Duration in seconds\n")
2666 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2670 DEFPY (evpn_mh_startup_delay
,
2671 evpn_mh_startup_delay_cmd
,
2672 "[no] evpn mh startup-delay(0-3600)$duration",
2677 "duration in seconds\n")
2680 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2684 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2685 "[no$no] evpn mh redirect-off",
2689 "ES bond redirect for fast-failover off\n")
2693 redirect_off
= no
? false : true;
2695 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2698 DEFUN (default_vrf_vni_mapping
,
2699 default_vrf_vni_mapping_cmd
,
2700 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2701 "VNI corresponding to the DEFAULT VRF\n"
2703 "Prefix routes only \n")
2705 char xpath
[XPATH_MAXLEN
];
2706 struct zebra_vrf
*zvrf
= NULL
;
2709 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2716 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2718 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2720 snprintf(xpath
, sizeof(xpath
),
2721 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2723 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2726 snprintf(xpath
, sizeof(xpath
),
2727 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2729 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2732 return nb_cli_apply_changes(vty
, NULL
);
2735 DEFUN (no_default_vrf_vni_mapping
,
2736 no_default_vrf_vni_mapping_cmd
,
2737 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2739 "VNI corresponding to DEFAULT VRF\n"
2741 "Prefix routes only \n")
2743 char xpath
[XPATH_MAXLEN
];
2745 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2746 struct zebra_vrf
*zvrf
= NULL
;
2748 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2755 if (zvrf
->l3vni
!= vni
) {
2756 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2761 snprintf(xpath
, sizeof(xpath
),
2762 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2764 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2767 snprintf(xpath
, sizeof(xpath
),
2768 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2770 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2773 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2775 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2777 return nb_cli_apply_changes(vty
, NULL
);
2780 DEFUN (vrf_vni_mapping
,
2781 vrf_vni_mapping_cmd
,
2782 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2783 "VNI corresponding to tenant VRF\n"
2785 "prefix-routes-only\n")
2789 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2797 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2798 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2802 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2803 NB_OP_MODIFY
, "true");
2805 return nb_cli_apply_changes(vty
, NULL
);
2808 DEFUN (no_vrf_vni_mapping
,
2809 no_vrf_vni_mapping_cmd
,
2810 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2812 "VNI corresponding to tenant VRF\n"
2814 "prefix-routes-only\n")
2818 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2819 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2827 if (zvrf
->l3vni
!= vni
) {
2828 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2833 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2837 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2838 NB_OP_DESTROY
, "true");
2840 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2842 return nb_cli_apply_changes(vty
, NULL
);
2846 DEFPY (show_vrf_vni
,
2848 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2850 VRF_FULL_CMD_HELP_STR
2855 struct zebra_vrf
*zvrf
;
2856 json_object
*json
= NULL
;
2857 json_object
*json_vrfs
= NULL
;
2858 bool uj
= use_json(argc
, argv
);
2859 bool use_vrf
= false;
2862 json
= json_object_new_object();
2864 /* show vrf vni used to display across all vrfs
2865 * This is enhanced to support only for specific
2868 if (vrf_all
|| !vrf_name
) {
2869 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2880 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2881 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2884 json_vrfs
= json_object_new_array();
2887 vty_json(vty
, json
);
2889 vty_out(vty
, "%% VRF does not exist\n");
2896 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2901 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2903 } else if (vrf_name
) {
2904 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2907 vty_json(vty
, json
);
2910 "%% VRF '%s' specified does not exist\n",
2917 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2918 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2921 json_vrfs
= json_object_new_array();
2923 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2927 json_object_object_add(json
, "vrfs", json_vrfs
);
2928 vty_json(vty
, json
);
2934 DEFUN (show_evpn_global
,
2935 show_evpn_global_cmd
,
2941 bool uj
= use_json(argc
, argv
);
2943 zebra_vxlan_print_evpn(vty
, uj
);
2947 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2948 SHOW_STR IP_STR
"neighbors\n")
2951 zebra_neigh_show(vty
);
2956 DEFPY(show_evpn_l2_nh
,
2957 show_evpn_l2_nh_cmd
,
2958 "show evpn l2-nh [json$json]",
2966 zebra_evpn_l2_nh_show(vty
, uj
);
2973 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2976 "Ethernet Segment\n"
2978 "Detailed information\n"
2985 if (!str_to_esi(esi_str
, &esi
)) {
2986 vty_out(vty
, "%% Malformed ESI\n");
2989 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2992 zebra_evpn_es_show_detail(vty
, uj
);
2994 zebra_evpn_es_show(vty
, uj
);
3000 DEFPY(show_evpn_es_evi
,
3001 show_evpn_es_evi_cmd
,
3002 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3005 "Ethernet Segment per EVI\n"
3006 "VxLAN Network Identifier\n"
3008 "Detailed information\n"
3015 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3017 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3022 DEFPY(show_evpn_access_vlan
, show_evpn_access_vlan_cmd
,
3023 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3029 "Detailed information\n" JSON_STR
)
3033 if (if_name
&& vid
) {
3036 struct interface
*ifp
;
3038 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3040 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
3042 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
,
3050 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
3055 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3057 zebra_evpn_acc_vl_show(vty
, uj
);
3063 DEFUN (show_evpn_vni
,
3065 "show evpn vni [json]",
3068 "VxLAN Network Identifier\n"
3071 struct zebra_vrf
*zvrf
;
3072 bool uj
= use_json(argc
, argv
);
3074 zvrf
= zebra_vrf_get_evpn();
3075 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3079 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3080 "show evpn vni detail [json]",
3083 "VxLAN Network Identifier\n"
3084 "Detailed Information On Each VNI\n"
3087 struct zebra_vrf
*zvrf
;
3088 bool uj
= use_json(argc
, argv
);
3090 zvrf
= zebra_vrf_get_evpn();
3091 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3095 DEFUN (show_evpn_vni_vni
,
3096 show_evpn_vni_vni_cmd
,
3097 "show evpn vni " CMD_VNI_RANGE
"[json]",
3100 "VxLAN Network Identifier\n"
3104 struct zebra_vrf
*zvrf
;
3106 bool uj
= use_json(argc
, argv
);
3108 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3109 zvrf
= zebra_vrf_get_evpn();
3110 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3114 DEFUN (show_evpn_rmac_vni_mac
,
3115 show_evpn_rmac_vni_mac_cmd
,
3116 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3123 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3128 bool uj
= use_json(argc
, argv
);
3130 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3131 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3132 vty_out(vty
, "%% Malformed MAC address\n");
3135 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3139 DEFUN (show_evpn_rmac_vni
,
3140 show_evpn_rmac_vni_cmd
,
3141 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3150 bool uj
= use_json(argc
, argv
);
3152 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3153 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3158 DEFUN (show_evpn_rmac_vni_all
,
3159 show_evpn_rmac_vni_all_cmd
,
3160 "show evpn rmac vni all [json]",
3168 bool uj
= use_json(argc
, argv
);
3170 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3175 DEFUN (show_evpn_nh_vni_ip
,
3176 show_evpn_nh_vni_ip_cmd
,
3177 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3184 "Host address (ipv4 or ipv6)\n"
3189 bool uj
= use_json(argc
, argv
);
3191 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3192 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3194 vty_out(vty
, "%% Malformed Neighbor address\n");
3197 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3202 DEFUN_HIDDEN (show_evpn_nh_svd_ip
,
3203 show_evpn_nh_svd_ip_cmd
,
3204 "show evpn next-hops svd ip WORD [json]",
3208 "Single Vxlan Device\n"
3210 "Host address (ipv4 or ipv6)\n"
3214 bool uj
= use_json(argc
, argv
);
3216 if (str2ipaddr(argv
[5]->arg
, &ip
) != 0) {
3218 vty_out(vty
, "%% Malformed Neighbor address\n");
3221 zebra_vxlan_print_specific_nh_l3vni(vty
, 0, &ip
, uj
);
3226 DEFUN (show_evpn_nh_vni
,
3227 show_evpn_nh_vni_cmd
,
3228 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3237 bool uj
= use_json(argc
, argv
);
3239 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3240 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3245 DEFUN_HIDDEN (show_evpn_nh_svd
,
3246 show_evpn_nh_svd_cmd
,
3247 "show evpn next-hops svd [json]",
3251 "Single Vxlan Device\n"
3254 bool uj
= use_json(argc
, argv
);
3256 zebra_vxlan_print_nh_svd(vty
, uj
);
3261 DEFUN (show_evpn_nh_vni_all
,
3262 show_evpn_nh_vni_all_cmd
,
3263 "show evpn next-hops vni all [json]",
3271 bool uj
= use_json(argc
, argv
);
3273 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3278 DEFUN (show_evpn_mac_vni
,
3279 show_evpn_mac_vni_cmd
,
3280 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3284 "VxLAN Network Identifier\n"
3288 struct zebra_vrf
*zvrf
;
3290 bool uj
= use_json(argc
, argv
);
3292 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3293 zvrf
= zebra_vrf_get_evpn();
3294 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3298 DEFPY (show_evpn_mac_vni_detail
,
3299 show_evpn_mac_vni_detail_cmd
,
3300 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3304 "VXLAN Network Identifier\n"
3306 "Detailed Information On Each VNI MAC\n"
3309 struct zebra_vrf
*zvrf
;
3310 bool uj
= use_json(argc
, argv
);
3312 zvrf
= zebra_vrf_get_evpn();
3313 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3317 DEFUN (show_evpn_mac_vni_all
,
3318 show_evpn_mac_vni_all_cmd
,
3319 "show evpn mac vni all [json]",
3323 "VxLAN Network Identifier\n"
3327 struct zebra_vrf
*zvrf
;
3328 bool uj
= use_json(argc
, argv
);
3330 zvrf
= zebra_vrf_get_evpn();
3331 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3335 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3336 "show evpn mac vni all detail [json]",
3340 "VxLAN Network Identifier\n"
3342 "Detailed Information On Each VNI MAC\n"
3345 struct zebra_vrf
*zvrf
;
3346 bool uj
= use_json(argc
, argv
);
3348 zvrf
= zebra_vrf_get_evpn();
3349 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3353 DEFUN (show_evpn_mac_vni_all_vtep
,
3354 show_evpn_mac_vni_all_vtep_cmd
,
3355 "show evpn mac vni all vtep A.B.C.D [json]",
3359 "VxLAN Network Identifier\n"
3362 "Remote VTEP IP address\n"
3365 struct zebra_vrf
*zvrf
;
3366 struct in_addr vtep_ip
;
3367 bool uj
= use_json(argc
, argv
);
3369 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3371 vty_out(vty
, "%% Malformed VTEP IP address\n");
3374 zvrf
= zebra_vrf_get_evpn();
3375 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3381 DEFUN (show_evpn_mac_vni_mac
,
3382 show_evpn_mac_vni_mac_cmd
,
3383 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3387 "VxLAN Network Identifier\n"
3390 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3394 struct zebra_vrf
*zvrf
;
3397 bool uj
= use_json(argc
, argv
);
3399 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3400 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3401 vty_out(vty
, "%% Malformed MAC address\n");
3404 zvrf
= zebra_vrf_get_evpn();
3405 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3409 DEFUN (show_evpn_mac_vni_vtep
,
3410 show_evpn_mac_vni_vtep_cmd
,
3411 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3415 "VxLAN Network Identifier\n"
3418 "Remote VTEP IP address\n"
3421 struct zebra_vrf
*zvrf
;
3423 struct in_addr vtep_ip
;
3424 bool uj
= use_json(argc
, argv
);
3426 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3427 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3429 vty_out(vty
, "%% Malformed VTEP IP address\n");
3433 zvrf
= zebra_vrf_get_evpn();
3434 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3438 DEFPY (show_evpn_mac_vni_all_dad
,
3439 show_evpn_mac_vni_all_dad_cmd
,
3440 "show evpn mac vni all duplicate [json]",
3444 "VxLAN Network Identifier\n"
3446 "Duplicate address list\n"
3449 struct zebra_vrf
*zvrf
;
3450 bool uj
= use_json(argc
, argv
);
3452 zvrf
= zebra_vrf_get_evpn();
3453 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3458 DEFPY (show_evpn_mac_vni_dad
,
3459 show_evpn_mac_vni_dad_cmd
,
3460 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3464 "VxLAN Network Identifier\n"
3466 "Duplicate address list\n"
3469 struct zebra_vrf
*zvrf
;
3470 bool uj
= use_json(argc
, argv
);
3472 zvrf
= zebra_vrf_get_evpn();
3474 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3479 DEFPY (show_evpn_neigh_vni_dad
,
3480 show_evpn_neigh_vni_dad_cmd
,
3481 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3484 "ARP and ND cache\n"
3485 "VxLAN Network Identifier\n"
3487 "Duplicate address list\n"
3490 struct zebra_vrf
*zvrf
;
3491 bool uj
= use_json(argc
, argv
);
3493 zvrf
= zebra_vrf_get_evpn();
3494 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3498 DEFPY (show_evpn_neigh_vni_all_dad
,
3499 show_evpn_neigh_vni_all_dad_cmd
,
3500 "show evpn arp-cache vni all duplicate [json]",
3503 "ARP and ND cache\n"
3504 "VxLAN Network Identifier\n"
3506 "Duplicate address list\n"
3509 struct zebra_vrf
*zvrf
;
3510 bool uj
= use_json(argc
, argv
);
3512 zvrf
= zebra_vrf_get_evpn();
3513 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3518 DEFUN (show_evpn_neigh_vni
,
3519 show_evpn_neigh_vni_cmd
,
3520 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3523 "ARP and ND cache\n"
3524 "VxLAN Network Identifier\n"
3528 struct zebra_vrf
*zvrf
;
3530 bool uj
= use_json(argc
, argv
);
3532 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3533 zvrf
= zebra_vrf_get_evpn();
3534 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3538 DEFUN (show_evpn_neigh_vni_all
,
3539 show_evpn_neigh_vni_all_cmd
,
3540 "show evpn arp-cache vni all [json]",
3543 "ARP and ND cache\n"
3544 "VxLAN Network Identifier\n"
3548 struct zebra_vrf
*zvrf
;
3549 bool uj
= use_json(argc
, argv
);
3551 zvrf
= zebra_vrf_get_evpn();
3552 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3556 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3557 "show evpn arp-cache vni all detail [json]",
3560 "ARP and ND cache\n"
3561 "VxLAN Network Identifier\n"
3563 "Neighbor details for all vnis in detail\n" JSON_STR
)
3565 struct zebra_vrf
*zvrf
;
3566 bool uj
= use_json(argc
, argv
);
3568 zvrf
= zebra_vrf_get_evpn();
3569 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3573 DEFUN (show_evpn_neigh_vni_neigh
,
3574 show_evpn_neigh_vni_neigh_cmd
,
3575 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3578 "ARP and ND cache\n"
3579 "VxLAN Network Identifier\n"
3582 "Neighbor address (IPv4 or IPv6 address)\n"
3585 struct zebra_vrf
*zvrf
;
3588 bool uj
= use_json(argc
, argv
);
3590 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3591 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3593 vty_out(vty
, "%% Malformed Neighbor address\n");
3596 zvrf
= zebra_vrf_get_evpn();
3597 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3601 DEFUN (show_evpn_neigh_vni_vtep
,
3602 show_evpn_neigh_vni_vtep_cmd
,
3603 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3606 "ARP and ND cache\n"
3607 "VxLAN Network Identifier\n"
3610 "Remote VTEP IP address\n"
3613 struct zebra_vrf
*zvrf
;
3615 struct in_addr vtep_ip
;
3616 bool uj
= use_json(argc
, argv
);
3618 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3619 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3621 vty_out(vty
, "%% Malformed VTEP IP address\n");
3625 zvrf
= zebra_vrf_get_evpn();
3626 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3630 /* policy routing contexts */
3631 DEFUN (show_pbr_ipset
,
3633 "show pbr ipset [WORD]",
3635 "Policy-Based Routing\n"
3636 "IPset Context information\n"
3637 "IPset Name information\n")
3641 found
= argv_find(argv
, argc
, "WORD", &idx
);
3643 zebra_pbr_show_ipset_list(vty
, NULL
);
3645 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3649 /* policy routing contexts */
3650 DEFUN (show_pbr_iptable
,
3651 show_pbr_iptable_cmd
,
3652 "show pbr iptable [WORD]",
3654 "Policy-Based Routing\n"
3655 "IPtable Context information\n"
3656 "IPtable Name information\n")
3661 found
= argv_find(argv
, argc
, "WORD", &idx
);
3663 zebra_pbr_show_iptable(vty
, NULL
);
3665 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3669 /* policy routing contexts */
3670 DEFPY (show_pbr_rule
,
3674 "Policy-Based Routing\n"
3677 zebra_pbr_show_rule(vty
);
3681 DEFPY (pbr_nexthop_resolve
,
3682 pbr_nexthop_resolve_cmd
,
3683 "[no$no] pbr nexthop-resolve",
3685 "Policy Based Routing\n"
3686 "Resolve nexthop for dataplane programming\n")
3688 zebra_pbr_expand_action_update(!no
);
3692 DEFPY (clear_evpn_dup_addr
,
3693 clear_evpn_dup_addr_cmd
,
3694 "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>]>",
3697 "Duplicate address \n"
3698 "VxLAN Network Identifier\n"
3702 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3707 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3708 int ret
= CMD_SUCCESS
;
3710 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3711 *yang_dup_mac
= NULL
;
3716 yang_dup
= yang_data_new(
3717 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3720 yang_dup
= yang_data_new_uint32(
3721 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3723 if (!is_zero_mac(&mac
->eth_addr
)) {
3724 yang_dup_mac
= yang_data_new_mac(
3725 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3728 listnode_add(input
, yang_dup_mac
);
3730 if (sockunion_family(ip
) == AF_INET
) {
3731 host_ip
.ipa_type
= IPADDR_V4
;
3732 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3734 host_ip
.ipa_type
= IPADDR_V6
;
3735 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3736 sizeof(struct in6_addr
));
3739 yang_dup_ip
= yang_data_new_ip(
3740 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3744 listnode_add(input
, yang_dup_ip
);
3749 listnode_add(input
, yang_dup
);
3750 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3754 list_delete(&input
);
3759 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3760 evpn_accept_bgp_seq_cmd
,
3761 "evpn accept-bgp-seq",
3763 "Accept all sequence numbers from BGP\n")
3765 zebra_vxlan_set_accept_bgp_seq(true);
3769 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3770 no_evpn_accept_bgp_seq_cmd
,
3771 "no evpn accept-bgp-seq",
3774 "Accept all sequence numbers from BGP\n")
3776 zebra_vxlan_set_accept_bgp_seq(false);
3780 /* Static ip route configuration write function. */
3781 static int zebra_ip_config(struct vty
*vty
)
3785 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3790 DEFUN (ip_zebra_import_table_distance
,
3791 ip_zebra_import_table_distance_cmd
,
3792 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3794 "import routes from non-main kernel table\n"
3795 "kernel routing table id\n"
3796 "Distance for imported routes\n"
3797 "Default distance value\n"
3798 "route-map for filtering\n"
3801 uint32_t table_id
= 0;
3803 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3804 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3806 strmatch(argv
[argc
- 2]->text
, "route-map")
3807 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3811 if (argc
== 7 || (argc
== 5 && !rmap
))
3812 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3814 if (!is_zebra_valid_kernel_table(table_id
)) {
3816 "Invalid routing table ID, %d. Must be in range 1-252\n",
3819 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3823 if (is_zebra_main_routing_table(table_id
)) {
3825 "Invalid routing table ID, %d. Must be non-default table\n",
3828 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3832 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3835 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3840 DEFUN_HIDDEN (zebra_packet_process
,
3841 zebra_packet_process_cmd
,
3842 "zebra zapi-packets (1-10000)",
3845 "Number of packets to process before relinquishing thread\n")
3847 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3849 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3850 memory_order_relaxed
);
3855 DEFUN_HIDDEN (no_zebra_packet_process
,
3856 no_zebra_packet_process_cmd
,
3857 "no zebra zapi-packets [(1-10000)]",
3861 "Number of packets to process before relinquishing thread\n")
3863 atomic_store_explicit(&zrouter
.packets_to_process
,
3864 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3865 memory_order_relaxed
);
3870 DEFUN_HIDDEN (zebra_workqueue_timer
,
3871 zebra_workqueue_timer_cmd
,
3872 "zebra work-queue (0-10000)",
3875 "Time in milliseconds\n")
3877 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3878 zrouter
.ribq
->spec
.hold
= timer
;
3883 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3884 no_zebra_workqueue_timer_cmd
,
3885 "no zebra work-queue [(0-10000)]",
3889 "Time in milliseconds\n")
3891 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3896 DEFUN (no_ip_zebra_import_table
,
3897 no_ip_zebra_import_table_cmd
,
3898 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3901 "import routes from non-main kernel table\n"
3902 "kernel routing table id\n"
3903 "Distance for imported routes\n"
3904 "Default distance value\n"
3905 "route-map for filtering\n"
3908 uint32_t table_id
= 0;
3909 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3911 if (!is_zebra_valid_kernel_table(table_id
)) {
3913 "Invalid routing table ID. Must be in range 1-252\n");
3917 if (is_zebra_main_routing_table(table_id
)) {
3919 "Invalid routing table ID, %d. Must be non-default table\n",
3924 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3927 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3930 DEFPY (zebra_nexthop_group_keep
,
3931 zebra_nexthop_group_keep_cmd
,
3932 "[no] zebra nexthop-group keep (1-3600)",
3936 "How long to keep\n"
3937 "Time in seconds from 1-3600\n")
3940 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3942 zrouter
.nhg_keep
= keep
;
3947 static int config_write_protocol(struct vty
*vty
)
3949 if (zrouter
.allow_delete
)
3950 vty_out(vty
, "allow-external-route-update\n");
3952 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3953 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3955 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3956 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3958 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3959 vty_out(vty
, "zebra zapi-packets %u\n",
3960 zrouter
.packets_to_process
);
3962 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3964 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3965 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3966 ipv4_multicast_mode
== MCAST_URIB_ONLY
3968 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3970 : ipv4_multicast_mode
3971 == MCAST_MIX_MRIB_FIRST
3973 : ipv4_multicast_mode
3974 == MCAST_MIX_DISTANCE
3978 /* Include dataplane info */
3979 dplane_config_write_helper(vty
);
3981 zebra_evpn_mh_config_write(vty
);
3983 zebra_pbr_config_write(vty
);
3985 if (!zebra_vxlan_get_accept_bgp_seq())
3986 vty_out(vty
, "no evpn accept-bgp-seq\n");
3988 /* Include nexthop-group config */
3989 if (!zebra_nhg_kernel_nexthops_enabled())
3990 vty_out(vty
, "no zebra nexthop kernel enable\n");
3992 if (zebra_nhg_proto_nexthops_only())
3993 vty_out(vty
, "zebra nexthop proto only\n");
3995 if (!zebra_nhg_recursive_use_backups())
3996 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3998 if (rnh_get_hide_backups())
3999 vty_out(vty
, "ip nht hide-backup-events\n");
4002 /* Include netlink info */
4003 netlink_config_write_helper(vty
);
4004 #endif /* HAVE_NETLINK */
4016 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4019 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4020 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4021 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4022 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4023 ttable_add_row(table
, "v6 Forwarding|%s",
4024 ipforward_ipv6() ? "On" : "Off");
4025 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4026 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4027 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4031 if (!vrf_is_backend_netns())
4032 ttable_add_row(table
, "VRF|l3mdev Available");
4034 ttable_add_row(table
, "VRF|Namespaces");
4036 ttable_add_row(table
, "VRF|Not Available");
4039 ttable_add_row(table
, "ASIC offload|%s",
4040 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4043 * Do not display this unless someone is actually using it
4045 * Why this distinction? I think this is effectively dead code
4046 * and should not be exposed. Maybe someone proves me wrong.
4048 if (zrouter
.asic_notification_nexthop_control
)
4049 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4051 ttable_add_row(table
, "RA|%s",
4052 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4053 ttable_add_row(table
, "RFC 5549|%s",
4054 rtadv_get_interfaces_configured_from_bgp()
4056 : "BGP is not using");
4058 ttable_add_row(table
, "Kernel NHG|%s",
4059 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4061 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4062 zrouter
.allow_delete
? "Yes" : "No");
4063 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4064 zrouter
.all_linkdownv4
? "On" : "Off");
4065 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4066 zrouter
.default_linkdownv4
? "On" : "Off");
4067 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4068 zrouter
.all_linkdownv6
? "On" : "Off");
4069 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4070 zrouter
.default_linkdownv6
? "On" : "Off");
4072 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4073 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4074 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4075 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4076 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4077 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4078 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4079 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4081 out
= ttable_dump(table
, "\n");
4082 vty_out(vty
, "%s\n", out
);
4083 XFREE(MTYPE_TMP
, out
);
4087 " Route Route Neighbor LSP LSP\n");
4089 "VRF Installs Removals Updates Installs Removals\n");
4091 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4092 struct zebra_vrf
*zvrf
= vrf
->info
;
4094 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4095 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4096 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4097 zvrf
->lsp_removals
);
4103 DEFUN (ip_forwarding
,
4107 "Turn on IP forwarding\n")
4113 ret
= ipforward_on();
4116 vty_out(vty
, "Can't turn on IP forwarding\n");
4117 return CMD_WARNING_CONFIG_FAILED
;
4123 DEFUN (no_ip_forwarding
,
4124 no_ip_forwarding_cmd
,
4128 "Turn off IP forwarding\n")
4134 ret
= ipforward_off();
4137 vty_out(vty
, "Can't turn off IP forwarding\n");
4138 return CMD_WARNING_CONFIG_FAILED
;
4144 /* Only display ip forwarding is enabled or not. */
4145 DEFUN (show_ip_forwarding
,
4146 show_ip_forwarding_cmd
,
4147 "show ip forwarding",
4150 "IP forwarding status\n")
4157 vty_out(vty
, "IP forwarding is off\n");
4159 vty_out(vty
, "IP forwarding is on\n");
4163 /* Only display ipv6 forwarding is enabled or not. */
4164 DEFUN (show_ipv6_forwarding
,
4165 show_ipv6_forwarding_cmd
,
4166 "show ipv6 forwarding",
4168 "IPv6 information\n"
4169 "Forwarding status\n")
4173 ret
= ipforward_ipv6();
4177 vty_out(vty
, "ipv6 forwarding is unknown\n");
4180 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4183 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4186 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4192 DEFUN (ipv6_forwarding
,
4193 ipv6_forwarding_cmd
,
4196 "Turn on IPv6 forwarding\n")
4200 ret
= ipforward_ipv6();
4202 ret
= ipforward_ipv6_on();
4205 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4206 return CMD_WARNING_CONFIG_FAILED
;
4212 DEFUN (no_ipv6_forwarding
,
4213 no_ipv6_forwarding_cmd
,
4214 "no ipv6 forwarding",
4217 "Turn off IPv6 forwarding\n")
4221 ret
= ipforward_ipv6();
4223 ret
= ipforward_ipv6_off();
4226 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4227 return CMD_WARNING_CONFIG_FAILED
;
4233 /* Display dataplane info */
4234 DEFUN (show_dataplane
,
4236 "show zebra dplane [detailed]",
4239 "Zebra dataplane information\n"
4240 "Detailed output\n")
4243 bool detailed
= false;
4245 if (argv_find(argv
, argc
, "detailed", &idx
))
4248 return dplane_show_helper(vty
, detailed
);
4251 /* Display dataplane providers info */
4252 DEFUN (show_dataplane_providers
,
4253 show_dataplane_providers_cmd
,
4254 "show zebra dplane providers [detailed]",
4257 "Zebra dataplane information\n"
4258 "Zebra dataplane provider information\n"
4259 "Detailed output\n")
4262 bool detailed
= false;
4264 if (argv_find(argv
, argc
, "detailed", &idx
))
4267 return dplane_show_provs_helper(vty
, detailed
);
4270 /* Configure dataplane incoming queue limit */
4271 DEFUN (zebra_dplane_queue_limit
,
4272 zebra_dplane_queue_limit_cmd
,
4273 "zebra dplane limit (0-10000)",
4276 "Limit incoming queued updates\n"
4277 "Number of queued updates\n")
4281 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4283 dplane_set_in_queue_limit(limit
, true);
4288 /* Reset dataplane queue limit to default value */
4289 DEFUN (no_zebra_dplane_queue_limit
,
4290 no_zebra_dplane_queue_limit_cmd
,
4291 "no zebra dplane limit [(0-10000)]",
4295 "Limit incoming queued updates\n"
4296 "Number of queued updates\n")
4298 dplane_set_in_queue_limit(0, false);
4303 DEFUN (zebra_show_routing_tables_summary
,
4304 zebra_show_routing_tables_summary_cmd
,
4305 "show zebra router table summary",
4308 "The Zebra Router Information\n"
4309 "Table Information about this Zebra Router\n"
4310 "Summary Information\n")
4312 zebra_router_show_table_summary(vty
);
4317 /* Table configuration write function. */
4318 static int config_write_table(struct vty
*vty
)
4323 /* IPForwarding configuration write function. */
4324 static int config_write_forwarding(struct vty
*vty
)
4327 vty_out(vty
, "no ip forwarding\n");
4328 if (!ipforward_ipv6())
4329 vty_out(vty
, "no ipv6 forwarding\n");
4330 vty_out(vty
, "!\n");
4334 DEFUN_HIDDEN (show_frr
,
4340 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4341 vty_out(vty
, ".............................7777:..............................................\n");
4342 vty_out(vty
, ".............................777777,............................................\n");
4343 vty_out(vty
, "... .........................77777777,..........................................\n");
4344 vty_out(vty
, "............................=7777777777:........................................\n");
4345 vty_out(vty
, "........................:7777777777777777,......................................\n");
4346 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4347 vty_out(vty
, "...................I7777777777+.................................................\n");
4348 vty_out(vty
, "................,777777777?............ .......................................\n");
4349 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4350 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4351 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4352 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4353 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4354 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4355 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4356 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4357 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4358 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4359 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4360 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4361 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4362 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4363 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4364 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4365 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4366 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4367 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4368 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4369 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4370 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4371 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4372 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4373 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4374 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4375 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4376 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4377 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4378 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4379 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4380 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4381 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4382 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4383 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4384 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4385 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4386 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4387 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4388 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4389 vty_out(vty
, "................................~77777777...............=777777.................\n");
4390 vty_out(vty
, ".....................................:=?I................~777777................\n");
4391 vty_out(vty
, "..........................................................:777777,..............\n");
4392 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4398 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4399 zebra_kernel_netlink_batch_tx_buf_cmd
,
4400 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4402 "Zebra kernel interface\n"
4403 "Set Netlink parameters\n"
4404 "Set batch buffer size and send threshold\n"
4405 "Size of the buffer\n"
4408 uint32_t bufsize
= 0, threshold
= 0;
4410 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4411 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4413 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4418 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4419 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4420 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4422 "Zebra kernel interface\n"
4423 "Set Netlink parameters\n"
4424 "Set batch buffer size and send threshold\n"
4425 "Size of the buffer\n"
4428 netlink_set_batch_buffer_size(0, 0, false);
4433 DEFPY (zebra_protodown_bit
,
4434 zebra_protodown_bit_cmd
,
4435 "zebra protodown reason-bit (0-31)$bit",
4437 "Protodown Configuration\n"
4438 "Reason Bit used in the kernel for application\n"
4439 "Reason Bit range\n")
4441 if_netlink_set_frr_protodown_r_bit(bit
);
4445 DEFPY (no_zebra_protodown_bit
,
4446 no_zebra_protodown_bit_cmd
,
4447 "no zebra protodown reason-bit [(0-31)$bit]",
4450 "Protodown Configuration\n"
4451 "Reason Bit used in the kernel for setting protodown\n"
4452 "Reason Bit Range\n")
4454 if_netlink_unset_frr_protodown_r_bit();
4458 #endif /* HAVE_NETLINK */
4460 DEFUN(ip_table_range
, ip_table_range_cmd
,
4461 "[no] ip table range (1-4294967295) (1-4294967295)",
4463 "table configuration\n"
4464 "Configure table range\n"
4465 "Start Routing Table\n"
4466 "End Routing Table\n")
4468 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4473 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4475 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4479 if (strmatch(argv
[0]->text
, "no"))
4480 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4482 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4485 #ifdef HAVE_SCRIPTING
4487 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4488 "zebra on-rib-process script SCRIPT",
4490 "on_rib_process_dplane_results hook call\n"
4492 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4495 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4498 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4499 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4501 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4502 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4507 #endif /* HAVE_SCRIPTING */
4509 /* IP node for static routes. */
4510 static int zebra_ip_config(struct vty
*vty
);
4511 static struct cmd_node ip_node
= {
4512 .name
= "static ip",
4515 .config_write
= zebra_ip_config
,
4517 static int config_write_protocol(struct vty
*vty
);
4518 static struct cmd_node protocol_node
= {
4520 .node
= PROTOCOL_NODE
,
4522 .config_write
= config_write_protocol
,
4524 /* table node for routing tables. */
4525 static int config_write_table(struct vty
*vty
);
4526 static struct cmd_node table_node
= {
4530 .config_write
= config_write_table
,
4532 static int config_write_forwarding(struct vty
*vty
);
4533 static struct cmd_node forwarding_node
= {
4534 .name
= "forwarding",
4535 .node
= FORWARDING_NODE
,
4537 .config_write
= config_write_forwarding
,
4541 void zebra_vty_init(void)
4543 /* Install configuration write function. */
4544 install_node(&table_node
);
4545 install_node(&forwarding_node
);
4547 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4548 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4549 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4550 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4552 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4553 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4554 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4557 zebra_route_map_init();
4559 zebra_affinity_map_init();
4561 install_node(&ip_node
);
4562 install_node(&protocol_node
);
4564 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4565 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4567 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4568 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4570 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4571 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4572 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4573 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4574 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4575 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4576 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4577 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4578 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4579 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4581 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4582 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4584 install_element(VIEW_NODE
, &show_vrf_cmd
);
4585 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4586 install_element(VIEW_NODE
, &show_route_cmd
);
4587 install_element(VIEW_NODE
, &show_ro_cmd
);
4588 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4589 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4590 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4592 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4593 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4595 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4596 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4597 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4598 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4599 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4600 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4601 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4602 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4603 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4605 install_element(VIEW_NODE
, &show_frr_cmd
);
4606 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4607 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4608 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4609 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4610 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4611 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4612 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4613 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4614 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4615 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4616 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4617 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4618 install_element(VIEW_NODE
, &show_evpn_nh_svd_ip_cmd
);
4619 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4620 install_element(VIEW_NODE
, &show_evpn_nh_svd_cmd
);
4621 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4622 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4623 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4624 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4625 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4626 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4627 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4628 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4629 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4630 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4631 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4632 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4633 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4634 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4635 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4636 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4637 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4638 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4639 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4640 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4642 install_element(VIEW_NODE
, &show_neigh_cmd
);
4644 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4645 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4646 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4647 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4648 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4650 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4651 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4652 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4653 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4654 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4655 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4656 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4657 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4659 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4660 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4661 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4662 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4664 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4665 install_element(VRF_NODE
, &ip_table_range_cmd
);
4668 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4669 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4670 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4671 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4672 #endif /* HAVE_NETLINK */
4674 #ifdef HAVE_SCRIPTING
4675 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4676 #endif /* HAVE_SCRIPTING */
4678 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);