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
), 1 /*pretty*/));
427 vty_out(vty
, ", weight %u", nexthop
->weight
);
429 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
430 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
432 for (i
= 1; i
< nexthop
->backup_num
; i
++)
433 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
437 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
438 struct json_object
*json
)
440 struct bgp_zebra_opaque bzo
= {};
441 struct ospf_zebra_opaque ozo
= {};
447 case ZEBRA_ROUTE_SHARP
:
449 json_object_string_add(json
, "opaque",
450 (char *)re
->opaque
->data
);
452 vty_out(vty
, " Opaque Data: %s",
453 (char *)re
->opaque
->data
);
456 case ZEBRA_ROUTE_BGP
:
457 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
460 json_object_string_add(json
, "asPath", bzo
.aspath
);
461 json_object_string_add(json
, "communities",
463 json_object_string_add(json
, "largeCommunities",
465 json_object_string_add(json
, "selectionReason",
466 bzo
.selection_reason
);
468 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
470 if (bzo
.community
[0] != '\0')
471 vty_out(vty
, " Communities : %s\n",
474 if (bzo
.lcommunity
[0] != '\0')
475 vty_out(vty
, " Large-Communities: %s\n",
478 vty_out(vty
, " Selection reason : %s\n",
479 bzo
.selection_reason
);
482 case ZEBRA_ROUTE_OSPF
:
483 case ZEBRA_ROUTE_OSPF6
:
484 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
487 json_object_string_add(json
, "ospfPathType",
489 if (ozo
.area_id
[0] != '\0')
490 json_object_string_add(json
, "ospfAreaId",
492 if (ozo
.tag
[0] != '\0')
493 json_object_string_add(json
, "ospfTag",
496 vty_out(vty
, " OSPF path type : %s\n",
498 if (ozo
.area_id
[0] != '\0')
499 vty_out(vty
, " OSPF area ID : %s\n",
501 if (ozo
.tag
[0] != '\0')
502 vty_out(vty
, " OSPF tag : %s\n",
511 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
515 cur
= monotime(NULL
);
518 frrtime_to_interval(cur
, buf
, bufsize
);
521 /* New RIB. Detailed information for IPv4 route. */
522 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
523 int mcast
, bool use_fib
, bool show_ng
)
525 struct route_entry
*re
;
526 struct nexthop
*nexthop
;
527 char buf
[SRCDEST2STR_BUFFER
];
528 struct zebra_vrf
*zvrf
;
531 dest
= rib_dest_from_rnode(rn
);
533 RNODE_FOREACH_RE (rn
, re
) {
535 * If re not selected for forwarding, skip re
536 * for "show ip/ipv6 fib <prefix>"
538 if (use_fib
&& re
!= dest
->selected_fib
)
541 const char *mcast_info
= "";
543 struct rib_table_info
*info
=
544 srcdest_rnode_table_info(rn
);
545 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
546 ? " using Multicast RIB"
547 : " using Unicast RIB";
550 vty_out(vty
, "Routing entry for %s%s\n",
551 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
552 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
554 vty_out(vty
, "[%d]", re
->instance
);
556 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
559 vty_out(vty
, ", tag %u", re
->tag
);
560 #if defined(SUPPORT_REALMS)
561 if (re
->tag
> 0 && re
->tag
<= 255)
562 vty_out(vty
, "(realm)");
566 vty_out(vty
, ", mtu %u", re
->mtu
);
567 if (re
->vrf_id
!= VRF_DEFAULT
) {
568 zvrf
= vrf_info_lookup(re
->vrf_id
);
569 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
571 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
572 vty_out(vty
, ", best");
575 uptime2str(re
->uptime
, buf
, sizeof(buf
));
577 vty_out(vty
, " Last update %s ago\n", buf
);
580 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
581 if (re
->nhe_installed_id
!= 0
582 && re
->nhe_id
!= re
->nhe_installed_id
)
584 " Installed Nexthop Group ID: %u\n",
585 re
->nhe_installed_id
);
588 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
589 /* Use helper to format each nexthop */
590 show_nexthop_detail_helper(vty
, re
, nexthop
,
591 false /*not backup*/);
594 /* Include backup(s), if present */
595 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
596 show_nh_backup_helper(vty
, re
, nexthop
);
598 zebra_show_ip_route_opaque(vty
, re
, NULL
);
604 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
605 struct route_entry
*re
, json_object
*json
,
606 bool is_fib
, bool show_ng
)
608 const struct nexthop
*nexthop
;
610 char buf
[SRCDEST2STR_BUFFER
];
611 json_object
*json_nexthops
= NULL
;
612 json_object
*json_nexthop
= NULL
;
613 json_object
*json_route
= NULL
;
614 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
615 const struct nexthop_group
*nhg
;
616 char up_str
[MONOTIME_STRLEN
];
618 bool nhg_from_backup
= false;
620 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
622 /* If showing fib information, use the fib view of the
626 nhg
= rib_get_fib_nhg(re
);
628 nhg
= &(re
->nhe
->nhg
);
631 json_route
= json_object_new_object();
632 json_nexthops
= json_object_new_array();
634 json_object_string_add(json_route
, "prefix",
635 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
636 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
637 json_object_string_add(json_route
, "protocol",
638 zebra_route_string(re
->type
));
641 json_object_int_add(json_route
, "instance",
644 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
645 json_object_string_add(json_route
, "vrfName",
646 vrf_id_to_name(re
->vrf_id
));
648 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
649 json_object_boolean_true_add(json_route
, "selected");
651 if (dest
->selected_fib
== re
)
652 json_object_boolean_true_add(json_route
,
655 json_object_int_add(json_route
, "distance",
657 json_object_int_add(json_route
, "metric", re
->metric
);
659 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
660 json_object_boolean_true_add(json_route
, "installed");
662 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
663 json_object_boolean_true_add(json_route
, "failed");
665 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
666 json_object_boolean_true_add(json_route
, "queued");
668 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
669 json_object_boolean_true_add(json_route
, "trapped");
671 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
672 json_object_boolean_true_add(json_route
, "offloaded");
674 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
675 json_object_boolean_false_add(json_route
, "offloaded");
678 json_object_int_add(json_route
, "tag", re
->tag
);
681 json_object_int_add(json_route
, "table", re
->table
);
683 json_object_int_add(json_route
, "internalStatus",
685 json_object_int_add(json_route
, "internalFlags",
687 json_object_int_add(json_route
, "internalNextHopNum",
688 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
689 json_object_int_add(json_route
, "internalNextHopActiveNum",
690 nexthop_group_active_nexthop_num(
692 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
694 if (re
->nhe_installed_id
!= 0)
695 json_object_int_add(json_route
,
696 "installedNexthopGroupId",
697 re
->nhe_installed_id
);
699 json_object_string_add(json_route
, "uptime", up_str
);
701 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
702 json_nexthop
= json_object_new_object();
703 show_nexthop_json_helper(json_nexthop
,
706 json_object_array_add(json_nexthops
,
710 json_object_object_add(json_route
, "nexthops", json_nexthops
);
712 /* If there are backup nexthops, include them */
714 nhg
= rib_get_fib_backup_nhg(re
);
716 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
718 if (nhg
&& nhg
->nexthop
) {
719 json_nexthops
= json_object_new_array();
721 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
722 json_nexthop
= json_object_new_object();
724 show_nexthop_json_helper(json_nexthop
,
726 json_object_array_add(json_nexthops
,
730 json_object_object_add(json_route
, "backupNexthops",
733 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
735 json_object_array_add(json
, json_route
);
739 /* Prefix information, and first nexthop. If we're showing 'fib',
740 * and there are no installed primary nexthops, see if there are any
741 * backup nexthops and start with those.
743 if (is_fib
&& nhg
->nexthop
== NULL
) {
744 nhg
= rib_get_fib_backup_nhg(re
);
745 nhg_from_backup
= true;
748 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
750 len
+= vty_out(vty
, "[%d]", re
->instance
);
751 if (nhg_from_backup
&& nhg
->nexthop
) {
754 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
755 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
756 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
760 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
761 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
762 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
765 /* Distance and metric display. */
766 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
767 (re
->distance
|| re
->metric
)) ||
768 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
769 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
773 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
775 /* Nexthop information. */
776 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
779 } else if (nhg_from_backup
) {
780 vty_out(vty
, " b%c%*c",
781 re_status_output_char(re
, nexthop
, is_fib
),
782 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
784 vty_out(vty
, " %c%*c",
785 re_status_output_char(re
, nexthop
, is_fib
),
786 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
789 show_route_nexthop_helper(vty
, re
, nexthop
);
790 vty_out(vty
, ", %s\n", up_str
);
793 /* If we only had backup nexthops, we're done */
797 /* Check for backup nexthop info if present */
799 nhg
= rib_get_fib_backup_nhg(re
);
801 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
806 /* Print backup info */
807 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
811 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
813 /* TODO -- it'd be nice to be able to include
814 * the entire list of backups, *and* include the
815 * real installation state.
817 vty_out(vty
, " b%c %*c",
818 (star_p
? '*' : ' '),
819 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
820 show_route_nexthop_helper(vty
, re
, nexthop
);
826 static void vty_show_ip_route_detail_json(struct vty
*vty
,
827 struct route_node
*rn
, bool use_fib
)
829 json_object
*json
= NULL
;
830 json_object
*json_prefix
= NULL
;
831 struct route_entry
*re
;
835 dest
= rib_dest_from_rnode(rn
);
837 json
= json_object_new_object();
838 json_prefix
= json_object_new_array();
840 RNODE_FOREACH_RE (rn
, re
) {
842 * If re not selected for forwarding, skip re
843 * for "show ip/ipv6 fib <prefix> json"
845 if (use_fib
&& re
!= dest
->selected_fib
)
847 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
850 prefix2str(&rn
->p
, buf
, sizeof(buf
));
851 json_object_object_add(json
, buf
, json_prefix
);
855 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
856 struct route_table
*table
, afi_t afi
,
857 bool use_fib
, route_tag_t tag
,
858 const struct prefix
*longer_prefix_p
,
859 bool supernets_only
, int type
,
860 unsigned short ospf_instance_id
, bool use_json
,
861 uint32_t tableid
, bool show_ng
,
862 struct route_show_ctx
*ctx
)
864 struct route_node
*rn
;
865 struct route_entry
*re
;
868 json_object
*json
= NULL
;
869 json_object
*json_prefix
= NULL
;
874 * ctx->multi indicates if we are dumping multiple tables or vrfs.
876 * => display the common header at most once
877 * => add newline at each call except first
878 * => always display the VRF and table
880 * => display the common header if at least one entry is found
881 * => display the VRF and table if specific
885 json
= json_object_new_object();
887 /* Show all routes. */
888 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
889 dest
= rib_dest_from_rnode(rn
);
891 RNODE_FOREACH_RE (rn
, re
) {
892 if (use_fib
&& re
!= dest
->selected_fib
)
895 if (tag
&& re
->tag
!= tag
)
899 && !prefix_match(longer_prefix_p
, &rn
->p
))
902 /* This can only be true when the afi is IPv4 */
903 if (supernets_only
) {
904 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
906 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
909 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
912 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
916 if (type
&& re
->type
!= type
)
920 && (re
->type
!= ZEBRA_ROUTE_OSPF
921 || re
->instance
!= ospf_instance_id
))
926 json_prefix
= json_object_new_array();
928 if (!ctx
->header_done
) {
931 SHOW_ROUTE_V4_HEADER
);
934 SHOW_ROUTE_V6_HEADER
);
936 if (ctx
->multi
&& ctx
->header_done
)
938 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
941 vty_out(vty
, "VRF %s:\n",
945 "VRF %s table %u:\n",
949 ctx
->header_done
= true;
953 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
958 prefix2str(&rn
->p
, buf
, sizeof(buf
));
959 json_object_object_add(json
, buf
, json_prefix
);
968 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
969 afi_t afi
, bool use_fib
, bool use_json
,
971 const struct prefix
*longer_prefix_p
,
972 bool supernets_only
, int type
,
973 unsigned short ospf_instance_id
, bool show_ng
,
974 struct route_show_ctx
*ctx
)
976 struct zebra_router_table
*zrt
;
977 struct rib_table_info
*info
;
979 RB_FOREACH (zrt
, zebra_router_table_head
,
981 info
= route_table_get_info(zrt
->table
);
983 if (zvrf
!= info
->zvrf
)
985 if (zrt
->afi
!= afi
||
986 zrt
->safi
!= SAFI_UNICAST
)
989 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
990 use_fib
, use_json
, tag
, longer_prefix_p
,
991 supernets_only
, type
, ospf_instance_id
,
992 zrt
->tableid
, show_ng
, ctx
);
996 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
997 safi_t safi
, bool use_fib
, bool use_json
,
999 const struct prefix
*longer_prefix_p
,
1000 bool supernets_only
, int type
,
1001 unsigned short ospf_instance_id
, uint32_t tableid
,
1002 bool show_ng
, struct route_show_ctx
*ctx
)
1004 struct route_table
*table
;
1005 struct zebra_vrf
*zvrf
= NULL
;
1007 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1009 vty_out(vty
, "{}\n");
1011 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1015 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1017 vty_out(vty
, "{}\n");
1019 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1024 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1026 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1029 vty_out(vty
, "{}\n");
1033 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1034 longer_prefix_p
, supernets_only
, type
,
1035 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1042 "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]",
1046 "IP nexthop tracking table\n"
1047 "IP import check tracking table\n"
1053 VRF_ALL_CMD_HELP_STR
1054 "Show Multicast (MRIB) NHT state\n"
1057 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1058 vrf_id_t vrf_id
= VRF_DEFAULT
;
1059 struct prefix prefix
, *p
= NULL
;
1060 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1061 bool uj
= use_json(argc
, argv
);
1062 json_object
*json
= NULL
;
1063 json_object
*json_vrf
= NULL
;
1064 json_object
*json_nexthop
= NULL
;
1067 json
= json_object_new_object();
1071 struct zebra_vrf
*zvrf
;
1073 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1074 if ((zvrf
= vrf
->info
) != NULL
) {
1076 json_vrf
= json_object_new_object();
1077 json_nexthop
= json_object_new_object();
1078 json_object_object_add(json
,
1081 json_object_object_add(json_vrf
,
1087 vty_out(vty
, "\nVRF %s:\n",
1090 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1091 vty
, NULL
, json_nexthop
);
1096 vty_json(vty
, json
);
1101 VRF_GET_ID(vrf_id
, vrf_name
, false);
1103 memset(&prefix
, 0, sizeof(prefix
));
1105 p
= sockunion2hostprefix(addr
, &prefix
);
1108 json_object_free(json
);
1114 json_vrf
= json_object_new_object();
1115 json_nexthop
= json_object_new_object();
1117 json_object_object_add(json
, vrf_name
, json_vrf
);
1119 json_object_object_add(json
, "default", json_vrf
);
1121 json_object_object_add(json_vrf
,
1122 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1126 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1129 vty_json(vty
, json
);
1134 DEFUN (ip_nht_default_route
,
1135 ip_nht_default_route_cmd
,
1136 "ip nht resolve-via-default",
1138 "Filter Next Hop tracking route resolution\n"
1139 "Resolve via default route\n")
1141 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1146 if (zvrf
->zebra_rnh_ip_default_route
)
1149 zvrf
->zebra_rnh_ip_default_route
= true;
1151 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1155 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1156 json_object
*json_nhe_hdr
)
1158 struct nexthop
*nexthop
= NULL
;
1159 struct nhg_connected
*rb_node_dep
= NULL
;
1160 struct nexthop_group
*backup_nhg
;
1161 char up_str
[MONOTIME_STRLEN
];
1162 char time_left
[MONOTIME_STRLEN
];
1163 json_object
*json_dependants
= NULL
;
1164 json_object
*json_depends
= NULL
;
1165 json_object
*json_nexthop_array
= NULL
;
1166 json_object
*json_nexthops
= NULL
;
1167 json_object
*json
= NULL
;
1168 json_object
*json_backup_nexthop_array
= NULL
;
1169 json_object
*json_backup_nexthops
= NULL
;
1172 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1175 json
= json_object_new_object();
1178 json_object_string_add(json
, "type",
1179 zebra_route_string(nhe
->type
));
1180 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1181 if (thread_is_scheduled(nhe
->timer
))
1182 json_object_string_add(
1183 json
, "timeToDeletion",
1184 thread_timer_to_hhmmss(time_left
,
1187 json_object_string_add(json
, "uptime", up_str
);
1188 json_object_string_add(json
, "vrf",
1189 vrf_id_to_name(nhe
->vrf_id
));
1192 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1193 zebra_route_string(nhe
->type
));
1194 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1195 if (thread_is_scheduled(nhe
->timer
))
1196 vty_out(vty
, " Time to Deletion: %s",
1197 thread_timer_to_hhmmss(time_left
,
1202 vty_out(vty
, " Uptime: %s\n", up_str
);
1203 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1206 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1208 json_object_boolean_true_add(json
, "valid");
1210 vty_out(vty
, " Valid");
1212 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1214 json_object_boolean_true_add(json
, "installed");
1216 vty_out(vty
, ", Installed");
1223 json_object_int_add(json
, "interfaceIndex",
1226 vty_out(vty
, " Interface Index: %d\n",
1230 if (!zebra_nhg_depends_is_empty(nhe
)) {
1232 json_depends
= json_object_new_array();
1234 vty_out(vty
, " Depends:");
1235 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1237 json_object_array_add(
1239 json_object_new_int(
1240 rb_node_dep
->nhe
->id
));
1242 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1247 json_object_object_add(json
, "depends", json_depends
);
1250 /* Output nexthops */
1252 json_nexthop_array
= json_object_new_array();
1255 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1256 if (json_nexthop_array
) {
1257 json_nexthops
= json_object_new_object();
1258 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1260 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1263 /* Make recursive nexthops a bit more clear */
1265 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1268 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1269 if (CHECK_FLAG(nexthop
->flags
,
1270 NEXTHOP_FLAG_HAS_BACKUP
)) {
1272 json_object_int_add(
1273 json_nexthops
, "backup",
1274 nexthop
->backup_idx
[0]);
1276 vty_out(vty
, " [backup %d]",
1277 nexthop
->backup_idx
[0]);
1283 json_object_array_add(json_nexthop_array
,
1290 /* TODO -- print more useful backup info */
1291 if (CHECK_FLAG(nexthop
->flags
,
1292 NEXTHOP_FLAG_HAS_BACKUP
)) {
1295 vty_out(vty
, "[backup");
1296 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1298 nexthop
->backup_idx
[i
]);
1303 json_object_array_add(json_nexthop_array
,
1309 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1311 /* Output backup nexthops (if any) */
1312 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1315 json_backup_nexthop_array
= json_object_new_array();
1317 vty_out(vty
, " Backups:\n");
1319 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1320 if (json_backup_nexthop_array
) {
1321 json_backup_nexthops
= json_object_new_object();
1322 show_nexthop_json_helper(json_backup_nexthops
,
1324 json_object_array_add(json_backup_nexthop_array
,
1325 json_backup_nexthops
);
1328 if (!CHECK_FLAG(nexthop
->flags
,
1329 NEXTHOP_FLAG_RECURSIVE
))
1332 /* Make recursive nexthops a bit more
1336 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1342 json_object_object_add(json
, "backupNexthops",
1343 json_backup_nexthop_array
);
1346 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1348 json_dependants
= json_object_new_array();
1350 vty_out(vty
, " Dependents:");
1351 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1354 json_object_array_add(
1356 json_object_new_int(
1357 rb_node_dep
->nhe
->id
));
1359 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1362 json_object_object_add(json
, "dependents",
1368 if (nhe
->nhg
.nhgr
.buckets
) {
1370 json_object_int_add(json
, "buckets",
1371 nhe
->nhg
.nhgr
.buckets
);
1372 json_object_int_add(json
, "idleTimer",
1373 nhe
->nhg
.nhgr
.idle_timer
);
1374 json_object_int_add(json
, "unbalancedTimer",
1375 nhe
->nhg
.nhgr
.unbalanced_timer
);
1376 json_object_int_add(json
, "unbalancedTime",
1377 nhe
->nhg
.nhgr
.unbalanced_time
);
1380 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1382 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1383 nhe
->nhg
.nhgr
.unbalanced_timer
,
1384 nhe
->nhg
.nhgr
.unbalanced_time
);
1389 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1392 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1395 struct nhg_hash_entry
*nhe
= NULL
;
1397 nhe
= zebra_nhg_lookup_id(id
);
1400 show_nexthop_group_out(vty
, nhe
, json
);
1403 vty_json(vty
, json
);
1405 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1411 vty_json(vty
, json
);
1416 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1418 struct nhe_show_context
{
1426 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1428 struct nhe_show_context
*ctx
= arg
;
1429 struct nhg_hash_entry
*nhe
;
1431 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1433 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1436 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1439 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1442 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1445 return HASHWALK_CONTINUE
;
1448 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1449 struct zebra_vrf
*zvrf
, afi_t afi
,
1450 int type
, json_object
*json
)
1452 struct nhe_show_context ctx
;
1456 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1460 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1463 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1465 struct zebra_if
*zebra_if
= NULL
;
1466 struct nhg_connected
*rb_node_dep
= NULL
;
1468 zebra_if
= ifp
->info
;
1470 if (!if_nhg_dependents_is_empty(ifp
)) {
1471 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1473 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1476 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1481 DEFPY (show_interface_nexthop_group
,
1482 show_interface_nexthop_group_cmd
,
1483 "show interface [IFNAME$if_name] nexthop-group",
1485 "Interface status and configuration\n"
1487 "Show Nexthop Groups\n")
1489 struct vrf
*vrf
= NULL
;
1490 struct interface
*ifp
= NULL
;
1493 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1495 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1497 if_nexthop_group_dump_vty(vty
, ifp
);
1501 FOR_ALL_INTERFACES (vrf
, ifp
)
1502 if_nexthop_group_dump_vty(vty
, ifp
);
1508 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1515 DEFPY(show_nexthop_group
,
1516 show_nexthop_group_cmd
,
1517 "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]",
1519 "Show Nexthop Groups\n"
1521 "Nexthop Group ID\n"
1522 "Show Singleton Nexthop-Groups\n"
1525 "Kernel (not installed via the zebra RIB)\n"
1526 "Zebra (implicitly created by zebra)\n"
1527 "Border Gateway Protocol (BGP)\n"
1528 "Super Happy Advanced Routing Protocol (SHARP)\n"
1529 VRF_FULL_CMD_HELP_STR
1533 struct zebra_vrf
*zvrf
= NULL
;
1534 afi_t afi
= AFI_UNSPEC
;
1536 bool uj
= use_json(argc
, argv
);
1537 json_object
*json
= NULL
;
1538 json_object
*json_vrf
= NULL
;
1541 json
= json_object_new_object();
1544 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1552 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1555 type
= ZEBRA_ROUTE_NHG
;
1559 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1561 vty_json(vty
, json
);
1564 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1571 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1572 struct zebra_vrf
*zvrf
;
1578 json_vrf
= json_object_new_object();
1580 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1582 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1585 json_object_object_add(json
, vrf
->name
,
1590 vty_json(vty
, json
);
1596 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1598 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1602 vty_json(vty
, json
);
1604 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1609 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1612 vty_json(vty
, json
);
1617 DEFPY_HIDDEN(nexthop_group_use_enable
,
1618 nexthop_group_use_enable_cmd
,
1619 "[no] zebra nexthop kernel enable",
1622 "Nexthop configuration \n"
1623 "Configure use of kernel nexthops\n"
1624 "Enable kernel nexthops\n")
1626 zebra_nhg_enable_kernel_nexthops(!no
);
1630 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1631 "[no] zebra nexthop proto only",
1633 "Nexthop configuration\n"
1634 "Configure exclusive use of proto nexthops\n"
1635 "Only use proto nexthops\n")
1637 zebra_nhg_set_proto_nexthops_only(!no
);
1641 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1642 backup_nexthop_recursive_use_enable_cmd
,
1643 "[no] zebra nexthop resolve-via-backup",
1646 "Nexthop configuration \n"
1647 "Configure use of backup nexthops in recursive resolution\n")
1649 zebra_nhg_set_recursive_use_backups(!no
);
1653 DEFUN (no_ip_nht_default_route
,
1654 no_ip_nht_default_route_cmd
,
1655 "no ip nht resolve-via-default",
1658 "Filter Next Hop tracking route resolution\n"
1659 "Resolve via default route\n")
1661 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1666 if (!zvrf
->zebra_rnh_ip_default_route
)
1669 zvrf
->zebra_rnh_ip_default_route
= false;
1670 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1674 DEFUN (ipv6_nht_default_route
,
1675 ipv6_nht_default_route_cmd
,
1676 "ipv6 nht resolve-via-default",
1678 "Filter Next Hop tracking route resolution\n"
1679 "Resolve via default route\n")
1681 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1686 if (zvrf
->zebra_rnh_ipv6_default_route
)
1689 zvrf
->zebra_rnh_ipv6_default_route
= true;
1690 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1694 DEFUN (no_ipv6_nht_default_route
,
1695 no_ipv6_nht_default_route_cmd
,
1696 "no ipv6 nht resolve-via-default",
1699 "Filter Next Hop tracking route resolution\n"
1700 "Resolve via default route\n")
1702 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1707 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1710 zvrf
->zebra_rnh_ipv6_default_route
= false;
1711 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1715 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1716 "[no] ip nht hide-backup-events",
1719 "Nexthop-tracking configuration\n"
1720 "Hide notification about backup nexthops\n")
1722 rnh_set_hide_backups(!no
);
1730 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1731 [vrf <NAME$vrf_name|all$vrf_all>]\
1734 |A.B.C.D/M$prefix longer-prefixes\
1735 |supernets-only$supernets_only\
1738 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1739 |ospf$type_str (1-65535)$ospf_instance_id\
1741 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1742 [vrf <NAME$vrf_name|all$vrf_all>]\
1745 |X:X::X:X/M$prefix longer-prefixes\
1747 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1749 [<json$json|nexthop-group$ng>]",
1752 "IP forwarding table\n"
1753 "IP routing table\n"
1754 "Table to display\n"
1755 "The table number to display\n"
1757 VRF_FULL_CMD_HELP_STR
1758 "Show only routes with tag\n"
1760 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1761 "Show route matching the specified Network/Mask pair only\n"
1762 "Show supernet entries only\n"
1763 FRR_IP_REDIST_HELP_STR_ZEBRA
1764 "Open Shortest Path First (OSPFv2)\n"
1767 "IP forwarding table\n"
1768 "IP routing table\n"
1769 "Table to display\n"
1770 "The table number to display\n"
1772 VRF_FULL_CMD_HELP_STR
1773 "Show only routes with tag\n"
1776 "Show route matching the specified Network/Mask pair only\n"
1777 FRR_IP6_REDIST_HELP_STR_ZEBRA
1779 "Nexthop Group Information\n")
1781 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1784 struct zebra_vrf
*zvrf
;
1785 struct route_show_ctx ctx
= {
1786 .multi
= vrf_all
|| table_all
,
1789 if (!vrf_is_backend_netns()) {
1790 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1792 vty_out(vty
, "{}\n");
1794 vty_out(vty
, "Linux vrf backend already points to table id\n");
1795 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1801 type
= proto_redistnum(afi
, type_str
);
1803 vty_out(vty
, "Unknown route type\n");
1809 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1810 if ((zvrf
= vrf
->info
) == NULL
1811 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1815 do_show_ip_route_all(
1816 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1817 prefix_str
? prefix
: NULL
,
1818 !!supernets_only
, type
,
1819 ospf_instance_id
, !!ng
, &ctx
);
1822 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1824 prefix_str
? prefix
: NULL
,
1825 !!supernets_only
, type
,
1826 ospf_instance_id
, table
, !!ng
, &ctx
);
1829 vrf_id_t vrf_id
= VRF_DEFAULT
;
1832 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1833 vrf
= vrf_lookup_by_id(vrf_id
);
1842 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1843 prefix_str
? prefix
: NULL
,
1844 !!supernets_only
, type
,
1845 ospf_instance_id
, !!ng
, &ctx
);
1847 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1849 prefix_str
? prefix
: NULL
,
1850 !!supernets_only
, type
,
1851 ospf_instance_id
, table
, !!ng
, &ctx
);
1857 ALIAS_HIDDEN (show_route
,
1859 "show <ip$ipv4|ipv6$ipv6> ro",
1863 "IP routing table\n");
1866 DEFPY (show_route_detail
,
1867 show_route_detail_cmd
,
1870 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1875 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1881 [json$json] [nexthop-group$ng]",
1884 "IP forwarding table\n"
1885 "IP routing table\n"
1886 VRF_FULL_CMD_HELP_STR
1887 "Network in the IP routing table to display\n"
1888 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1890 "IPv6 forwarding table\n"
1891 "IPv6 routing table\n"
1892 VRF_FULL_CMD_HELP_STR
1896 "Nexthop Group Information\n")
1898 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1899 struct route_table
*table
;
1901 struct route_node
*rn
;
1902 bool use_fib
= !!fib
;
1904 bool network_found
= false;
1905 bool show_ng
= !!ng
;
1908 prefix_str
= address_str
;
1909 if (str2prefix(prefix_str
, &p
) < 0) {
1910 vty_out(vty
, "%% Malformed address\n");
1916 struct zebra_vrf
*zvrf
;
1918 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1919 if ((zvrf
= vrf
->info
) == NULL
1920 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1923 rn
= route_node_match(table
, &p
);
1926 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1927 route_unlock_node(rn
);
1931 dest
= rib_dest_from_rnode(rn
);
1932 if (use_fib
&& !dest
->selected_fib
) {
1933 route_unlock_node(rn
);
1937 network_found
= true;
1939 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1941 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1944 route_unlock_node(rn
);
1947 if (!network_found
) {
1949 vty_out(vty
, "{}\n");
1953 "%% Network not in FIB\n");
1956 "%% Network not in RIB\n");
1961 vrf_id_t vrf_id
= VRF_DEFAULT
;
1964 VRF_GET_ID(vrf_id
, vrf_name
, false);
1966 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1970 rn
= route_node_match(table
, &p
);
1972 dest
= rib_dest_from_rnode(rn
);
1974 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1975 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1977 vty_out(vty
, "{}\n");
1981 "%% Network not in FIB\n");
1984 "%% Network not in table\n");
1987 route_unlock_node(rn
);
1992 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1994 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1996 route_unlock_node(rn
);
2002 DEFPY (show_route_summary
,
2003 show_route_summary_cmd
,
2004 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2005 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2009 "IP routing table\n"
2010 VRF_FULL_CMD_HELP_STR
2011 "Summary of all routes\n"
2012 "Table to display summary for\n"
2013 "The table number\n"
2017 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2018 struct route_table
*table
;
2019 bool uj
= use_json(argc
, argv
);
2023 struct zebra_vrf
*zvrf
;
2025 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2026 if ((zvrf
= vrf
->info
) == NULL
)
2030 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2033 table
= zebra_vrf_lookup_table_with_table_id(
2034 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2041 vty_show_ip_route_summary_prefix(vty
, table
,
2044 vty_show_ip_route_summary(vty
, table
, uj
);
2047 vrf_id_t vrf_id
= VRF_DEFAULT
;
2050 VRF_GET_ID(vrf_id
, vrf_name
, false);
2053 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2055 table
= zebra_vrf_lookup_table_with_table_id(
2056 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2061 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2063 vty_show_ip_route_summary(vty
, table
, uj
);
2069 DEFUN_HIDDEN (show_route_zebra_dump
,
2070 show_route_zebra_dump_cmd
,
2071 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2081 struct route_table
*table
;
2082 const char *vrf_name
= NULL
;
2085 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2087 if (argv_find(argv
, argc
, "vrf", &idx
))
2088 vrf_name
= argv
[++idx
]->arg
;
2092 struct zebra_vrf
*zvrf
;
2094 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2097 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2100 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2101 show_ip_route_dump_vty(vty
, table
);
2104 vrf_id_t vrf_id
= VRF_DEFAULT
;
2106 VRF_GET_ID(vrf_id
, vrf_name
, true);
2108 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2112 show_ip_route_dump_vty(vty
, table
);
2118 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2119 struct route_entry
*re
, unsigned int num
)
2122 char buf
[SRCDEST2STR_BUFFER
];
2124 vty_out(vty
, " Nexthop %u:\n", num
);
2125 vty_out(vty
, " type: %u\n", nexthop
->type
);
2126 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2127 switch (nexthop
->type
) {
2128 case NEXTHOP_TYPE_IPV4
:
2129 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2130 vty_out(vty
, " ip address: %s\n",
2131 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2133 vty_out(vty
, " afi: ipv4\n");
2135 if (nexthop
->ifindex
) {
2136 vty_out(vty
, " interface index: %d\n",
2138 vty_out(vty
, " interface name: %s\n",
2139 ifindex2ifname(nexthop
->ifindex
,
2143 if (nexthop
->src
.ipv4
.s_addr
2144 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2146 vty_out(vty
, " source: %s\n", buf
);
2148 case NEXTHOP_TYPE_IPV6
:
2149 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2150 vty_out(vty
, " ip: %s\n",
2151 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2153 vty_out(vty
, " afi: ipv6\n");
2155 if (nexthop
->ifindex
) {
2156 vty_out(vty
, " interface index: %d\n",
2158 vty_out(vty
, " interface name: %s\n",
2159 ifindex2ifname(nexthop
->ifindex
,
2163 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2164 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2166 vty_out(vty
, " source: %s\n", buf
);
2169 case NEXTHOP_TYPE_IFINDEX
:
2171 " Nexthop is an interface (directly connected).\n");
2172 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2173 vty_out(vty
, " interface name: %s\n",
2174 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2176 case NEXTHOP_TYPE_BLACKHOLE
:
2177 vty_out(vty
, " Nexthop type is blackhole.\n");
2179 switch (nexthop
->bh_type
) {
2180 case BLACKHOLE_REJECT
:
2181 vty_out(vty
, " Blackhole type: reject\n");
2183 case BLACKHOLE_ADMINPROHIB
:
2185 " Blackhole type: admin-prohibited\n");
2187 case BLACKHOLE_NULL
:
2188 vty_out(vty
, " Blackhole type: NULL0\n");
2190 case BLACKHOLE_UNSPEC
:
2197 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2199 struct route_node
*rn
;
2200 struct route_entry
*re
;
2201 char buf
[SRCDEST2STR_BUFFER
];
2206 struct nexthop
*nexthop
= NULL
;
2207 int nexthop_num
= 0;
2209 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2210 vty_out(vty
, "----------------------------\n");
2212 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2213 RNODE_FOREACH_RE (rn
, re
) {
2214 vty_out(vty
, "Route: %s\n",
2215 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2216 vty_out(vty
, " protocol: %s\n",
2217 zebra_route_string(re
->type
));
2218 vty_out(vty
, " instance: %u\n", re
->instance
);
2219 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2220 vty_out(vty
, " VRF name: %s\n",
2221 vrf_id_to_name(re
->vrf_id
));
2222 vty_out(vty
, " flags: %u\n", re
->flags
);
2224 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2225 vty_out(vty
, " distance: %u\n", re
->distance
);
2226 vty_out(vty
, " metric: %u\n", re
->metric
);
2229 vty_out(vty
, " tag: %u\n", re
->tag
);
2231 uptime
= monotime(&tv
);
2232 uptime
-= re
->uptime
;
2233 gmtime_r(&uptime
, &tm
);
2235 if (uptime
< ONE_DAY_SECOND
)
2236 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2237 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2238 else if (uptime
< ONE_WEEK_SECOND
)
2239 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2240 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2242 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2244 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2247 vty_out(vty
, " status: %u\n", re
->status
);
2248 vty_out(vty
, " nexthop_num: %u\n",
2249 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2250 vty_out(vty
, " nexthop_active_num: %u\n",
2251 nexthop_group_active_nexthop_num(
2253 vty_out(vty
, " table: %u\n", re
->table
);
2254 vty_out(vty
, " uptime: %s\n", time
);
2256 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2258 show_ip_route_nht_dump(vty
, nexthop
, re
,
2268 static void vty_show_ip_route_summary(struct vty
*vty
,
2269 struct route_table
*table
, bool use_json
)
2271 struct route_node
*rn
;
2272 struct route_entry
*re
;
2273 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2274 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2275 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2276 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2277 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2278 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2281 json_object
*json_route_summary
= NULL
;
2282 json_object
*json_route_routes
= NULL
;
2284 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2285 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2286 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2287 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2290 json_route_summary
= json_object_new_object();
2291 json_route_routes
= json_object_new_array();
2292 json_object_object_add(json_route_summary
, "routes",
2296 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2297 RNODE_FOREACH_RE (rn
, re
) {
2298 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2299 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2301 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2303 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2305 rib_cnt
[re
->type
]++;
2307 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2308 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2311 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2313 fib_cnt
[re
->type
]++;
2316 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2318 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2320 trap_cnt
[re
->type
]++;
2323 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2325 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2327 offload_cnt
[re
->type
]++;
2332 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2334 zvrf_name(((struct rib_table_info
*)
2335 route_table_get_info(table
))
2338 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2339 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2340 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2341 if (i
== ZEBRA_ROUTE_BGP
) {
2343 json_object
*json_route_ebgp
=
2344 json_object_new_object();
2346 json_object_int_add(
2347 json_route_ebgp
, "fib",
2348 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2349 json_object_int_add(
2350 json_route_ebgp
, "rib",
2351 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2352 json_object_int_add(
2353 json_route_ebgp
, "fibOffLoaded",
2354 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2355 json_object_int_add(
2356 json_route_ebgp
, "fibTrapped",
2357 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2359 json_object_string_add(json_route_ebgp
,
2361 json_object_array_add(json_route_routes
,
2364 json_object
*json_route_ibgp
=
2365 json_object_new_object();
2367 json_object_int_add(
2368 json_route_ibgp
, "fib",
2369 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2370 json_object_int_add(
2371 json_route_ibgp
, "rib",
2372 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2373 json_object_int_add(
2374 json_route_ibgp
, "fibOffLoaded",
2375 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2376 json_object_int_add(
2377 json_route_ibgp
, "fibTrapped",
2378 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2379 json_object_string_add(json_route_ibgp
,
2381 json_object_array_add(json_route_routes
,
2384 vty_out(vty
, "%-20s %-20d %-20d \n",
2386 rib_cnt
[ZEBRA_ROUTE_BGP
],
2387 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2388 vty_out(vty
, "%-20s %-20d %-20d \n",
2390 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2391 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2395 json_object
*json_route_type
=
2396 json_object_new_object();
2398 json_object_int_add(json_route_type
,
2400 json_object_int_add(json_route_type
,
2403 json_object_int_add(json_route_type
,
2406 json_object_int_add(json_route_type
,
2409 json_object_string_add(
2410 json_route_type
, "type",
2411 zebra_route_string(i
));
2412 json_object_array_add(json_route_routes
,
2415 vty_out(vty
, "%-20s %-20d %-20d \n",
2416 zebra_route_string(i
),
2417 rib_cnt
[i
], fib_cnt
[i
]);
2423 json_object_int_add(json_route_summary
, "routesTotal",
2424 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2425 json_object_int_add(json_route_summary
, "routesTotalFib",
2426 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2428 vty_json(vty
, json_route_summary
);
2430 vty_out(vty
, "------\n");
2431 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2432 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2438 * Implementation of the ip route summary prefix command.
2440 * This command prints the primary prefixes that have been installed by various
2441 * protocols on the box.
2444 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2445 struct route_table
*table
,
2448 struct route_node
*rn
;
2449 struct route_entry
*re
;
2450 struct nexthop
*nexthop
;
2451 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2452 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2453 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2454 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2457 json_object
*json_route_summary
= NULL
;
2458 json_object
*json_route_routes
= NULL
;
2460 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2461 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2464 json_route_summary
= json_object_new_object();
2465 json_route_routes
= json_object_new_array();
2466 json_object_object_add(json_route_summary
, "prefixRoutes",
2470 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2471 RNODE_FOREACH_RE (rn
, re
) {
2474 * In case of ECMP, count only once.
2477 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2478 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2479 fib_cnt
[re
->type
]++;
2481 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2482 nexthop
= nexthop
->next
) {
2484 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2485 rib_cnt
[re
->type
]++;
2486 if (re
->type
== ZEBRA_ROUTE_BGP
2487 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2488 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2489 if (CHECK_FLAG(re
->status
,
2490 ROUTE_ENTRY_INSTALLED
))
2491 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2497 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2498 "Prefix Routes", "FIB",
2499 zvrf_name(((struct rib_table_info
*)
2500 route_table_get_info(table
))
2503 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2504 if (rib_cnt
[i
] > 0) {
2505 if (i
== ZEBRA_ROUTE_BGP
) {
2507 json_object
*json_route_ebgp
=
2508 json_object_new_object();
2510 json_object_int_add(
2511 json_route_ebgp
, "fib",
2512 fib_cnt
[ZEBRA_ROUTE_BGP
]
2513 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2514 json_object_int_add(
2515 json_route_ebgp
, "rib",
2516 rib_cnt
[ZEBRA_ROUTE_BGP
]
2517 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2518 json_object_string_add(json_route_ebgp
,
2520 json_object_array_add(json_route_routes
,
2523 json_object
*json_route_ibgp
=
2524 json_object_new_object();
2526 json_object_int_add(
2527 json_route_ibgp
, "fib",
2528 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2529 json_object_int_add(
2530 json_route_ibgp
, "rib",
2531 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2532 json_object_string_add(json_route_ibgp
,
2534 json_object_array_add(json_route_routes
,
2537 vty_out(vty
, "%-20s %-20d %-20d \n",
2539 rib_cnt
[ZEBRA_ROUTE_BGP
]
2540 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2541 fib_cnt
[ZEBRA_ROUTE_BGP
]
2542 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2543 vty_out(vty
, "%-20s %-20d %-20d \n",
2545 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2546 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2550 json_object
*json_route_type
=
2551 json_object_new_object();
2553 json_object_int_add(json_route_type
,
2555 json_object_int_add(json_route_type
,
2557 json_object_string_add(
2558 json_route_type
, "type",
2559 zebra_route_string(i
));
2560 json_object_array_add(json_route_routes
,
2563 vty_out(vty
, "%-20s %-20d %-20d \n",
2564 zebra_route_string(i
),
2565 rib_cnt
[i
], fib_cnt
[i
]);
2571 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2572 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2573 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2574 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2576 vty_json(vty
, json_route_summary
);
2578 vty_out(vty
, "------\n");
2579 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2580 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2585 DEFUN (allow_external_route_update
,
2586 allow_external_route_update_cmd
,
2587 "allow-external-route-update",
2588 "Allow FRR routes to be overwritten by external processes\n")
2590 zrouter
.allow_delete
= true;
2595 DEFUN (no_allow_external_route_update
,
2596 no_allow_external_route_update_cmd
,
2597 "no allow-external-route-update",
2599 "Allow FRR routes to be overwritten by external processes\n")
2601 zrouter
.allow_delete
= false;
2614 struct zebra_vrf
*zvrf
;
2616 if (vrf_is_backend_netns())
2617 vty_out(vty
, "netns-based vrfs\n");
2619 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2620 if (!(zvrf
= vrf
->info
))
2622 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2625 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2626 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2627 vty_out(vty
, "inactive");
2628 else if (zvrf_ns_name(zvrf
))
2629 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2630 zvrf_ns_name(zvrf
));
2632 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2634 if (vrf_is_user_cfged(vrf
))
2635 vty_out(vty
, " (configured)");
2642 DEFPY (evpn_mh_mac_holdtime
,
2643 evpn_mh_mac_holdtime_cmd
,
2644 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2649 "Duration in seconds\n")
2651 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2655 DEFPY (evpn_mh_neigh_holdtime
,
2656 evpn_mh_neigh_holdtime_cmd
,
2657 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2661 "Neighbor entry hold time\n"
2662 "Duration in seconds\n")
2665 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2669 DEFPY (evpn_mh_startup_delay
,
2670 evpn_mh_startup_delay_cmd
,
2671 "[no] evpn mh startup-delay(0-3600)$duration",
2676 "duration in seconds\n")
2679 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2683 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2684 "[no$no] evpn mh redirect-off",
2688 "ES bond redirect for fast-failover off\n")
2692 redirect_off
= no
? false : true;
2694 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2697 DEFUN (default_vrf_vni_mapping
,
2698 default_vrf_vni_mapping_cmd
,
2699 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2700 "VNI corresponding to the DEFAULT VRF\n"
2702 "Prefix routes only \n")
2704 char xpath
[XPATH_MAXLEN
];
2705 struct zebra_vrf
*zvrf
= NULL
;
2708 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2715 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2717 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2719 snprintf(xpath
, sizeof(xpath
),
2720 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2722 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2725 snprintf(xpath
, sizeof(xpath
),
2726 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2728 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2731 return nb_cli_apply_changes(vty
, NULL
);
2734 DEFUN (no_default_vrf_vni_mapping
,
2735 no_default_vrf_vni_mapping_cmd
,
2736 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2738 "VNI corresponding to DEFAULT VRF\n"
2740 "Prefix routes only \n")
2742 char xpath
[XPATH_MAXLEN
];
2744 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2745 struct zebra_vrf
*zvrf
= NULL
;
2747 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2754 if (zvrf
->l3vni
!= vni
) {
2755 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2760 snprintf(xpath
, sizeof(xpath
),
2761 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2763 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2766 snprintf(xpath
, sizeof(xpath
),
2767 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2769 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2772 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2774 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2776 return nb_cli_apply_changes(vty
, NULL
);
2779 DEFUN (vrf_vni_mapping
,
2780 vrf_vni_mapping_cmd
,
2781 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2782 "VNI corresponding to tenant VRF\n"
2784 "prefix-routes-only\n")
2788 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2796 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2797 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2801 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2802 NB_OP_MODIFY
, "true");
2804 return nb_cli_apply_changes(vty
, NULL
);
2807 DEFUN (no_vrf_vni_mapping
,
2808 no_vrf_vni_mapping_cmd
,
2809 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2811 "VNI corresponding to tenant VRF\n"
2813 "prefix-routes-only\n")
2817 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2818 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2826 if (zvrf
->l3vni
!= vni
) {
2827 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2832 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2836 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2837 NB_OP_DESTROY
, "true");
2839 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2841 return nb_cli_apply_changes(vty
, NULL
);
2845 DEFPY (show_vrf_vni
,
2847 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2849 VRF_FULL_CMD_HELP_STR
2854 struct zebra_vrf
*zvrf
;
2855 json_object
*json
= NULL
;
2856 json_object
*json_vrfs
= NULL
;
2857 bool uj
= use_json(argc
, argv
);
2858 bool use_vrf
= false;
2861 json
= json_object_new_object();
2863 /* show vrf vni used to display across all vrfs
2864 * This is enhanced to support only for specific
2867 if (vrf_all
|| !vrf_name
) {
2868 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2879 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2880 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2883 json_vrfs
= json_object_new_array();
2886 vty_json(vty
, json
);
2888 vty_out(vty
, "%% VRF does not exist\n");
2895 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2900 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2902 } else if (vrf_name
) {
2903 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2906 vty_json(vty
, json
);
2909 "%% VRF '%s' specified does not exist\n",
2916 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2917 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2920 json_vrfs
= json_object_new_array();
2922 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2926 json_object_object_add(json
, "vrfs", json_vrfs
);
2927 vty_json(vty
, json
);
2933 DEFUN (show_evpn_global
,
2934 show_evpn_global_cmd
,
2940 bool uj
= use_json(argc
, argv
);
2942 zebra_vxlan_print_evpn(vty
, uj
);
2946 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2947 SHOW_STR IP_STR
"neighbors\n")
2950 zebra_neigh_show(vty
);
2955 DEFPY(show_evpn_l2_nh
,
2956 show_evpn_l2_nh_cmd
,
2957 "show evpn l2-nh [json$json]",
2965 zebra_evpn_l2_nh_show(vty
, uj
);
2972 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2975 "Ethernet Segment\n"
2977 "Detailed information\n"
2984 if (!str_to_esi(esi_str
, &esi
)) {
2985 vty_out(vty
, "%% Malformed ESI\n");
2988 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2991 zebra_evpn_es_show_detail(vty
, uj
);
2993 zebra_evpn_es_show(vty
, uj
);
2999 DEFPY(show_evpn_es_evi
,
3000 show_evpn_es_evi_cmd
,
3001 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3004 "Ethernet Segment per EVI\n"
3005 "VxLAN Network Identifier\n"
3007 "Detailed information\n"
3014 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3016 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3021 DEFPY(show_evpn_access_vlan
,
3022 show_evpn_access_vlan_cmd
,
3023 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3028 "Detailed information\n"
3034 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3037 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3039 zebra_evpn_acc_vl_show(vty
, uj
);
3045 DEFUN (show_evpn_vni
,
3047 "show evpn vni [json]",
3050 "VxLAN Network Identifier\n"
3053 struct zebra_vrf
*zvrf
;
3054 bool uj
= use_json(argc
, argv
);
3056 zvrf
= zebra_vrf_get_evpn();
3057 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3061 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3062 "show evpn vni detail [json]",
3065 "VxLAN Network Identifier\n"
3066 "Detailed Information On Each VNI\n"
3069 struct zebra_vrf
*zvrf
;
3070 bool uj
= use_json(argc
, argv
);
3072 zvrf
= zebra_vrf_get_evpn();
3073 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3077 DEFUN (show_evpn_vni_vni
,
3078 show_evpn_vni_vni_cmd
,
3079 "show evpn vni " CMD_VNI_RANGE
"[json]",
3082 "VxLAN Network Identifier\n"
3086 struct zebra_vrf
*zvrf
;
3088 bool uj
= use_json(argc
, argv
);
3090 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3091 zvrf
= zebra_vrf_get_evpn();
3092 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3096 DEFUN (show_evpn_rmac_vni_mac
,
3097 show_evpn_rmac_vni_mac_cmd
,
3098 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3105 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3110 bool uj
= use_json(argc
, argv
);
3112 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3113 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3114 vty_out(vty
, "%% Malformed MAC address\n");
3117 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3121 DEFUN (show_evpn_rmac_vni
,
3122 show_evpn_rmac_vni_cmd
,
3123 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3132 bool uj
= use_json(argc
, argv
);
3134 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3135 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3140 DEFUN (show_evpn_rmac_vni_all
,
3141 show_evpn_rmac_vni_all_cmd
,
3142 "show evpn rmac vni all [json]",
3150 bool uj
= use_json(argc
, argv
);
3152 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3157 DEFUN (show_evpn_nh_vni_ip
,
3158 show_evpn_nh_vni_ip_cmd
,
3159 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3166 "Host address (ipv4 or ipv6)\n"
3171 bool uj
= use_json(argc
, argv
);
3173 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3174 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3176 vty_out(vty
, "%% Malformed Neighbor address\n");
3179 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3184 DEFUN (show_evpn_nh_vni
,
3185 show_evpn_nh_vni_cmd
,
3186 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3195 bool uj
= use_json(argc
, argv
);
3197 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3198 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3203 DEFUN (show_evpn_nh_vni_all
,
3204 show_evpn_nh_vni_all_cmd
,
3205 "show evpn next-hops vni all [json]",
3213 bool uj
= use_json(argc
, argv
);
3215 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3220 DEFUN (show_evpn_mac_vni
,
3221 show_evpn_mac_vni_cmd
,
3222 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3226 "VxLAN Network Identifier\n"
3230 struct zebra_vrf
*zvrf
;
3232 bool uj
= use_json(argc
, argv
);
3234 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3235 zvrf
= zebra_vrf_get_evpn();
3236 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3240 DEFPY (show_evpn_mac_vni_detail
,
3241 show_evpn_mac_vni_detail_cmd
,
3242 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3246 "VXLAN Network Identifier\n"
3248 "Detailed Information On Each VNI MAC\n"
3251 struct zebra_vrf
*zvrf
;
3252 bool uj
= use_json(argc
, argv
);
3254 zvrf
= zebra_vrf_get_evpn();
3255 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3259 DEFUN (show_evpn_mac_vni_all
,
3260 show_evpn_mac_vni_all_cmd
,
3261 "show evpn mac vni all [json]",
3265 "VxLAN Network Identifier\n"
3269 struct zebra_vrf
*zvrf
;
3270 bool uj
= use_json(argc
, argv
);
3272 zvrf
= zebra_vrf_get_evpn();
3273 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3277 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3278 "show evpn mac vni all detail [json]",
3282 "VxLAN Network Identifier\n"
3284 "Detailed Information On Each VNI MAC\n"
3287 struct zebra_vrf
*zvrf
;
3288 bool uj
= use_json(argc
, argv
);
3290 zvrf
= zebra_vrf_get_evpn();
3291 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3295 DEFUN (show_evpn_mac_vni_all_vtep
,
3296 show_evpn_mac_vni_all_vtep_cmd
,
3297 "show evpn mac vni all vtep A.B.C.D [json]",
3301 "VxLAN Network Identifier\n"
3304 "Remote VTEP IP address\n"
3307 struct zebra_vrf
*zvrf
;
3308 struct in_addr vtep_ip
;
3309 bool uj
= use_json(argc
, argv
);
3311 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3313 vty_out(vty
, "%% Malformed VTEP IP address\n");
3316 zvrf
= zebra_vrf_get_evpn();
3317 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3323 DEFUN (show_evpn_mac_vni_mac
,
3324 show_evpn_mac_vni_mac_cmd
,
3325 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3329 "VxLAN Network Identifier\n"
3332 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3336 struct zebra_vrf
*zvrf
;
3339 bool uj
= use_json(argc
, argv
);
3341 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3342 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3343 vty_out(vty
, "%% Malformed MAC address\n");
3346 zvrf
= zebra_vrf_get_evpn();
3347 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3351 DEFUN (show_evpn_mac_vni_vtep
,
3352 show_evpn_mac_vni_vtep_cmd
,
3353 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3357 "VxLAN Network Identifier\n"
3360 "Remote VTEP IP address\n"
3363 struct zebra_vrf
*zvrf
;
3365 struct in_addr vtep_ip
;
3366 bool uj
= use_json(argc
, argv
);
3368 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3369 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3371 vty_out(vty
, "%% Malformed VTEP IP address\n");
3375 zvrf
= zebra_vrf_get_evpn();
3376 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3380 DEFPY (show_evpn_mac_vni_all_dad
,
3381 show_evpn_mac_vni_all_dad_cmd
,
3382 "show evpn mac vni all duplicate [json]",
3386 "VxLAN Network Identifier\n"
3388 "Duplicate address list\n"
3391 struct zebra_vrf
*zvrf
;
3392 bool uj
= use_json(argc
, argv
);
3394 zvrf
= zebra_vrf_get_evpn();
3395 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3400 DEFPY (show_evpn_mac_vni_dad
,
3401 show_evpn_mac_vni_dad_cmd
,
3402 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3406 "VxLAN Network Identifier\n"
3408 "Duplicate address list\n"
3411 struct zebra_vrf
*zvrf
;
3412 bool uj
= use_json(argc
, argv
);
3414 zvrf
= zebra_vrf_get_evpn();
3416 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3421 DEFPY (show_evpn_neigh_vni_dad
,
3422 show_evpn_neigh_vni_dad_cmd
,
3423 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3426 "ARP and ND cache\n"
3427 "VxLAN Network Identifier\n"
3429 "Duplicate address list\n"
3432 struct zebra_vrf
*zvrf
;
3433 bool uj
= use_json(argc
, argv
);
3435 zvrf
= zebra_vrf_get_evpn();
3436 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3440 DEFPY (show_evpn_neigh_vni_all_dad
,
3441 show_evpn_neigh_vni_all_dad_cmd
,
3442 "show evpn arp-cache vni all duplicate [json]",
3445 "ARP and ND cache\n"
3446 "VxLAN Network Identifier\n"
3448 "Duplicate address list\n"
3451 struct zebra_vrf
*zvrf
;
3452 bool uj
= use_json(argc
, argv
);
3454 zvrf
= zebra_vrf_get_evpn();
3455 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3460 DEFUN (show_evpn_neigh_vni
,
3461 show_evpn_neigh_vni_cmd
,
3462 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3465 "ARP and ND cache\n"
3466 "VxLAN Network Identifier\n"
3470 struct zebra_vrf
*zvrf
;
3472 bool uj
= use_json(argc
, argv
);
3474 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3475 zvrf
= zebra_vrf_get_evpn();
3476 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3480 DEFUN (show_evpn_neigh_vni_all
,
3481 show_evpn_neigh_vni_all_cmd
,
3482 "show evpn arp-cache vni all [json]",
3485 "ARP and ND cache\n"
3486 "VxLAN Network Identifier\n"
3490 struct zebra_vrf
*zvrf
;
3491 bool uj
= use_json(argc
, argv
);
3493 zvrf
= zebra_vrf_get_evpn();
3494 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3498 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3499 "show evpn arp-cache vni all detail [json]",
3502 "ARP and ND cache\n"
3503 "VxLAN Network Identifier\n"
3505 "Neighbor details for all vnis in detail\n" JSON_STR
)
3507 struct zebra_vrf
*zvrf
;
3508 bool uj
= use_json(argc
, argv
);
3510 zvrf
= zebra_vrf_get_evpn();
3511 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3515 DEFUN (show_evpn_neigh_vni_neigh
,
3516 show_evpn_neigh_vni_neigh_cmd
,
3517 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3520 "ARP and ND cache\n"
3521 "VxLAN Network Identifier\n"
3524 "Neighbor address (IPv4 or IPv6 address)\n"
3527 struct zebra_vrf
*zvrf
;
3530 bool uj
= use_json(argc
, argv
);
3532 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3533 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3535 vty_out(vty
, "%% Malformed Neighbor address\n");
3538 zvrf
= zebra_vrf_get_evpn();
3539 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3543 DEFUN (show_evpn_neigh_vni_vtep
,
3544 show_evpn_neigh_vni_vtep_cmd
,
3545 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3548 "ARP and ND cache\n"
3549 "VxLAN Network Identifier\n"
3552 "Remote VTEP IP address\n"
3555 struct zebra_vrf
*zvrf
;
3557 struct in_addr vtep_ip
;
3558 bool uj
= use_json(argc
, argv
);
3560 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3561 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3563 vty_out(vty
, "%% Malformed VTEP IP address\n");
3567 zvrf
= zebra_vrf_get_evpn();
3568 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3572 /* policy routing contexts */
3573 DEFUN (show_pbr_ipset
,
3575 "show pbr ipset [WORD]",
3577 "Policy-Based Routing\n"
3578 "IPset Context information\n"
3579 "IPset Name information\n")
3583 found
= argv_find(argv
, argc
, "WORD", &idx
);
3585 zebra_pbr_show_ipset_list(vty
, NULL
);
3587 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3591 /* policy routing contexts */
3592 DEFUN (show_pbr_iptable
,
3593 show_pbr_iptable_cmd
,
3594 "show pbr iptable [WORD]",
3596 "Policy-Based Routing\n"
3597 "IPtable Context information\n"
3598 "IPtable Name information\n")
3603 found
= argv_find(argv
, argc
, "WORD", &idx
);
3605 zebra_pbr_show_iptable(vty
, NULL
);
3607 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3611 /* policy routing contexts */
3612 DEFPY (show_pbr_rule
,
3616 "Policy-Based Routing\n"
3619 zebra_pbr_show_rule(vty
);
3623 DEFPY (pbr_nexthop_resolve
,
3624 pbr_nexthop_resolve_cmd
,
3625 "[no$no] pbr nexthop-resolve",
3627 "Policy Based Routing\n"
3628 "Resolve nexthop for dataplane programming\n")
3630 zebra_pbr_expand_action_update(!no
);
3634 DEFPY (clear_evpn_dup_addr
,
3635 clear_evpn_dup_addr_cmd
,
3636 "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>]>",
3639 "Duplicate address \n"
3640 "VxLAN Network Identifier\n"
3644 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3649 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3650 int ret
= CMD_SUCCESS
;
3652 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3653 *yang_dup_mac
= NULL
;
3658 yang_dup
= yang_data_new(
3659 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3662 yang_dup
= yang_data_new_uint32(
3663 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3665 if (!is_zero_mac(&mac
->eth_addr
)) {
3666 yang_dup_mac
= yang_data_new_mac(
3667 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3670 listnode_add(input
, yang_dup_mac
);
3672 if (sockunion_family(ip
) == AF_INET
) {
3673 host_ip
.ipa_type
= IPADDR_V4
;
3674 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3676 host_ip
.ipa_type
= IPADDR_V6
;
3677 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3678 sizeof(struct in6_addr
));
3681 yang_dup_ip
= yang_data_new_ip(
3682 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3686 listnode_add(input
, yang_dup_ip
);
3691 listnode_add(input
, yang_dup
);
3692 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3696 list_delete(&input
);
3701 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3702 evpn_accept_bgp_seq_cmd
,
3703 "evpn accept-bgp-seq",
3705 "Accept all sequence numbers from BGP\n")
3707 zebra_vxlan_set_accept_bgp_seq(true);
3711 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3712 no_evpn_accept_bgp_seq_cmd
,
3713 "no evpn accept-bgp-seq",
3716 "Accept all sequence numbers from BGP\n")
3718 zebra_vxlan_set_accept_bgp_seq(false);
3722 /* Static ip route configuration write function. */
3723 static int zebra_ip_config(struct vty
*vty
)
3727 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3732 DEFUN (ip_zebra_import_table_distance
,
3733 ip_zebra_import_table_distance_cmd
,
3734 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3736 "import routes from non-main kernel table\n"
3737 "kernel routing table id\n"
3738 "Distance for imported routes\n"
3739 "Default distance value\n"
3740 "route-map for filtering\n"
3743 uint32_t table_id
= 0;
3745 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3746 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3748 strmatch(argv
[argc
- 2]->text
, "route-map")
3749 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3753 if (argc
== 7 || (argc
== 5 && !rmap
))
3754 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3756 if (!is_zebra_valid_kernel_table(table_id
)) {
3758 "Invalid routing table ID, %d. Must be in range 1-252\n",
3761 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3765 if (is_zebra_main_routing_table(table_id
)) {
3767 "Invalid routing table ID, %d. Must be non-default table\n",
3770 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3774 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3777 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3782 DEFUN_HIDDEN (zebra_packet_process
,
3783 zebra_packet_process_cmd
,
3784 "zebra zapi-packets (1-10000)",
3787 "Number of packets to process before relinquishing thread\n")
3789 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3791 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3792 memory_order_relaxed
);
3797 DEFUN_HIDDEN (no_zebra_packet_process
,
3798 no_zebra_packet_process_cmd
,
3799 "no zebra zapi-packets [(1-10000)]",
3803 "Number of packets to process before relinquishing thread\n")
3805 atomic_store_explicit(&zrouter
.packets_to_process
,
3806 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3807 memory_order_relaxed
);
3812 DEFUN_HIDDEN (zebra_workqueue_timer
,
3813 zebra_workqueue_timer_cmd
,
3814 "zebra work-queue (0-10000)",
3817 "Time in milliseconds\n")
3819 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3820 zrouter
.ribq
->spec
.hold
= timer
;
3825 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3826 no_zebra_workqueue_timer_cmd
,
3827 "no zebra work-queue [(0-10000)]",
3831 "Time in milliseconds\n")
3833 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3838 DEFUN (no_ip_zebra_import_table
,
3839 no_ip_zebra_import_table_cmd
,
3840 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3843 "import routes from non-main kernel table\n"
3844 "kernel routing table id\n"
3845 "Distance for imported routes\n"
3846 "Default distance value\n"
3847 "route-map for filtering\n"
3850 uint32_t table_id
= 0;
3851 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3853 if (!is_zebra_valid_kernel_table(table_id
)) {
3855 "Invalid routing table ID. Must be in range 1-252\n");
3859 if (is_zebra_main_routing_table(table_id
)) {
3861 "Invalid routing table ID, %d. Must be non-default table\n",
3866 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3869 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3872 DEFPY (zebra_nexthop_group_keep
,
3873 zebra_nexthop_group_keep_cmd
,
3874 "[no] zebra nexthop-group keep (1-3600)",
3878 "How long to keep\n"
3879 "Time in seconds from 1-3600\n")
3882 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3884 zrouter
.nhg_keep
= keep
;
3889 static int config_write_protocol(struct vty
*vty
)
3891 if (zrouter
.allow_delete
)
3892 vty_out(vty
, "allow-external-route-update\n");
3894 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3895 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3897 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3898 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3900 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3901 vty_out(vty
, "zebra zapi-packets %u\n",
3902 zrouter
.packets_to_process
);
3904 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3906 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3907 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3908 ipv4_multicast_mode
== MCAST_URIB_ONLY
3910 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3912 : ipv4_multicast_mode
3913 == MCAST_MIX_MRIB_FIRST
3915 : ipv4_multicast_mode
3916 == MCAST_MIX_DISTANCE
3920 /* Include dataplane info */
3921 dplane_config_write_helper(vty
);
3923 zebra_evpn_mh_config_write(vty
);
3925 zebra_pbr_config_write(vty
);
3927 if (!zebra_vxlan_get_accept_bgp_seq())
3928 vty_out(vty
, "no evpn accept-bgp-seq\n");
3930 /* Include nexthop-group config */
3931 if (!zebra_nhg_kernel_nexthops_enabled())
3932 vty_out(vty
, "no zebra nexthop kernel enable\n");
3934 if (zebra_nhg_proto_nexthops_only())
3935 vty_out(vty
, "zebra nexthop proto only\n");
3937 if (!zebra_nhg_recursive_use_backups())
3938 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3940 if (rnh_get_hide_backups())
3941 vty_out(vty
, "ip nht hide-backup-events\n");
3944 /* Include netlink info */
3945 netlink_config_write_helper(vty
);
3946 #endif /* HAVE_NETLINK */
3958 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3961 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3962 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3963 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3964 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3965 ttable_add_row(table
, "v6 Forwarding|%s",
3966 ipforward_ipv6() ? "On" : "Off");
3967 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3968 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3969 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3973 if (!vrf_is_backend_netns())
3974 ttable_add_row(table
, "VRF|l3mdev Available");
3976 ttable_add_row(table
, "VRF|Namespaces");
3978 ttable_add_row(table
, "VRF|Not Available");
3981 ttable_add_row(table
, "ASIC offload|%s",
3982 zrouter
.asic_offloaded
? "Used" : "Unavailable");
3985 * Do not display this unless someone is actually using it
3987 * Why this distinction? I think this is effectively dead code
3988 * and should not be exposed. Maybe someone proves me wrong.
3990 if (zrouter
.asic_notification_nexthop_control
)
3991 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
3993 ttable_add_row(table
, "RA|%s",
3994 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
3995 ttable_add_row(table
, "RFC 5549|%s",
3996 rtadv_get_interfaces_configured_from_bgp()
3998 : "BGP is not using");
4000 ttable_add_row(table
, "Kernel NHG|%s",
4001 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4003 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4004 zrouter
.allow_delete
? "Yes" : "No");
4005 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4006 zrouter
.all_linkdownv4
? "On" : "Off");
4007 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4008 zrouter
.default_linkdownv4
? "On" : "Off");
4009 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4010 zrouter
.all_linkdownv6
? "On" : "Off");
4011 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4012 zrouter
.default_linkdownv6
? "On" : "Off");
4014 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4015 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4016 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4017 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4018 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4019 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4020 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4021 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4023 out
= ttable_dump(table
, "\n");
4024 vty_out(vty
, "%s\n", out
);
4025 XFREE(MTYPE_TMP
, out
);
4029 " Route Route Neighbor LSP LSP\n");
4031 "VRF Installs Removals Updates Installs Removals\n");
4033 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4034 struct zebra_vrf
*zvrf
= vrf
->info
;
4036 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4037 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4038 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4039 zvrf
->lsp_removals
);
4045 DEFUN (ip_forwarding
,
4049 "Turn on IP forwarding\n")
4055 ret
= ipforward_on();
4058 vty_out(vty
, "Can't turn on IP forwarding\n");
4059 return CMD_WARNING_CONFIG_FAILED
;
4065 DEFUN (no_ip_forwarding
,
4066 no_ip_forwarding_cmd
,
4070 "Turn off IP forwarding\n")
4076 ret
= ipforward_off();
4079 vty_out(vty
, "Can't turn off IP forwarding\n");
4080 return CMD_WARNING_CONFIG_FAILED
;
4086 /* Only display ip forwarding is enabled or not. */
4087 DEFUN (show_ip_forwarding
,
4088 show_ip_forwarding_cmd
,
4089 "show ip forwarding",
4092 "IP forwarding status\n")
4099 vty_out(vty
, "IP forwarding is off\n");
4101 vty_out(vty
, "IP forwarding is on\n");
4105 /* Only display ipv6 forwarding is enabled or not. */
4106 DEFUN (show_ipv6_forwarding
,
4107 show_ipv6_forwarding_cmd
,
4108 "show ipv6 forwarding",
4110 "IPv6 information\n"
4111 "Forwarding status\n")
4115 ret
= ipforward_ipv6();
4119 vty_out(vty
, "ipv6 forwarding is unknown\n");
4122 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4125 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4128 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4134 DEFUN (ipv6_forwarding
,
4135 ipv6_forwarding_cmd
,
4138 "Turn on IPv6 forwarding\n")
4142 ret
= ipforward_ipv6();
4144 ret
= ipforward_ipv6_on();
4147 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4148 return CMD_WARNING_CONFIG_FAILED
;
4154 DEFUN (no_ipv6_forwarding
,
4155 no_ipv6_forwarding_cmd
,
4156 "no ipv6 forwarding",
4159 "Turn off IPv6 forwarding\n")
4163 ret
= ipforward_ipv6();
4165 ret
= ipforward_ipv6_off();
4168 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4169 return CMD_WARNING_CONFIG_FAILED
;
4175 /* Display dataplane info */
4176 DEFUN (show_dataplane
,
4178 "show zebra dplane [detailed]",
4181 "Zebra dataplane information\n"
4182 "Detailed output\n")
4185 bool detailed
= false;
4187 if (argv_find(argv
, argc
, "detailed", &idx
))
4190 return dplane_show_helper(vty
, detailed
);
4193 /* Display dataplane providers info */
4194 DEFUN (show_dataplane_providers
,
4195 show_dataplane_providers_cmd
,
4196 "show zebra dplane providers [detailed]",
4199 "Zebra dataplane information\n"
4200 "Zebra dataplane provider information\n"
4201 "Detailed output\n")
4204 bool detailed
= false;
4206 if (argv_find(argv
, argc
, "detailed", &idx
))
4209 return dplane_show_provs_helper(vty
, detailed
);
4212 /* Configure dataplane incoming queue limit */
4213 DEFUN (zebra_dplane_queue_limit
,
4214 zebra_dplane_queue_limit_cmd
,
4215 "zebra dplane limit (0-10000)",
4218 "Limit incoming queued updates\n"
4219 "Number of queued updates\n")
4223 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4225 dplane_set_in_queue_limit(limit
, true);
4230 /* Reset dataplane queue limit to default value */
4231 DEFUN (no_zebra_dplane_queue_limit
,
4232 no_zebra_dplane_queue_limit_cmd
,
4233 "no zebra dplane limit [(0-10000)]",
4237 "Limit incoming queued updates\n"
4238 "Number of queued updates\n")
4240 dplane_set_in_queue_limit(0, false);
4245 DEFUN (zebra_show_routing_tables_summary
,
4246 zebra_show_routing_tables_summary_cmd
,
4247 "show zebra router table summary",
4250 "The Zebra Router Information\n"
4251 "Table Information about this Zebra Router\n"
4252 "Summary Information\n")
4254 zebra_router_show_table_summary(vty
);
4259 /* Table configuration write function. */
4260 static int config_write_table(struct vty
*vty
)
4265 /* IPForwarding configuration write function. */
4266 static int config_write_forwarding(struct vty
*vty
)
4269 vty_out(vty
, "no ip forwarding\n");
4270 if (!ipforward_ipv6())
4271 vty_out(vty
, "no ipv6 forwarding\n");
4272 vty_out(vty
, "!\n");
4276 DEFUN_HIDDEN (show_frr
,
4282 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4283 vty_out(vty
, ".............................7777:..............................................\n");
4284 vty_out(vty
, ".............................777777,............................................\n");
4285 vty_out(vty
, "... .........................77777777,..........................................\n");
4286 vty_out(vty
, "............................=7777777777:........................................\n");
4287 vty_out(vty
, "........................:7777777777777777,......................................\n");
4288 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4289 vty_out(vty
, "...................I7777777777+.................................................\n");
4290 vty_out(vty
, "................,777777777?............ .......................................\n");
4291 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4292 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4293 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4294 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4295 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4296 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4297 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4298 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4299 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4300 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4301 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4302 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4303 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4304 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4305 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4306 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4307 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4308 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4309 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4310 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4311 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4312 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4313 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4314 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4315 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4316 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4317 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4318 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4319 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4320 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4321 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4322 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4323 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4324 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4325 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4326 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4327 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4328 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4329 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4330 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4331 vty_out(vty
, "................................~77777777...............=777777.................\n");
4332 vty_out(vty
, ".....................................:=?I................~777777................\n");
4333 vty_out(vty
, "..........................................................:777777,..............\n");
4334 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4340 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4341 zebra_kernel_netlink_batch_tx_buf_cmd
,
4342 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4344 "Zebra kernel interface\n"
4345 "Set Netlink parameters\n"
4346 "Set batch buffer size and send threshold\n"
4347 "Size of the buffer\n"
4350 uint32_t bufsize
= 0, threshold
= 0;
4352 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4353 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4355 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4360 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4361 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4362 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4364 "Zebra kernel interface\n"
4365 "Set Netlink parameters\n"
4366 "Set batch buffer size and send threshold\n"
4367 "Size of the buffer\n"
4370 netlink_set_batch_buffer_size(0, 0, false);
4375 DEFPY (zebra_protodown_bit
,
4376 zebra_protodown_bit_cmd
,
4377 "zebra protodown reason-bit (0-31)$bit",
4379 "Protodown Configuration\n"
4380 "Reason Bit used in the kernel for application\n"
4381 "Reason Bit range\n")
4383 if_netlink_set_frr_protodown_r_bit(bit
);
4387 DEFPY (no_zebra_protodown_bit
,
4388 no_zebra_protodown_bit_cmd
,
4389 "no zebra protodown reason-bit [(0-31)$bit]",
4392 "Protodown Configuration\n"
4393 "Reason Bit used in the kernel for setting protodown\n"
4394 "Reason Bit Range\n")
4396 if_netlink_unset_frr_protodown_r_bit();
4400 #endif /* HAVE_NETLINK */
4402 DEFUN(ip_table_range
, ip_table_range_cmd
,
4403 "[no] ip table range (1-4294967295) (1-4294967295)",
4405 "table configuration\n"
4406 "Configure table range\n"
4407 "Start Routing Table\n"
4408 "End Routing Table\n")
4410 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4415 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4417 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4421 if (strmatch(argv
[0]->text
, "no"))
4422 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4424 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4427 #ifdef HAVE_SCRIPTING
4429 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4430 "zebra on-rib-process script SCRIPT",
4432 "on_rib_process_dplane_results hook call\n"
4434 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4437 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4440 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4441 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4443 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4444 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4449 #endif /* HAVE_SCRIPTING */
4451 /* IP node for static routes. */
4452 static int zebra_ip_config(struct vty
*vty
);
4453 static struct cmd_node ip_node
= {
4454 .name
= "static ip",
4457 .config_write
= zebra_ip_config
,
4459 static int config_write_protocol(struct vty
*vty
);
4460 static struct cmd_node protocol_node
= {
4462 .node
= PROTOCOL_NODE
,
4464 .config_write
= config_write_protocol
,
4466 /* table node for routing tables. */
4467 static int config_write_table(struct vty
*vty
);
4468 static struct cmd_node table_node
= {
4472 .config_write
= config_write_table
,
4474 static int config_write_forwarding(struct vty
*vty
);
4475 static struct cmd_node forwarding_node
= {
4476 .name
= "forwarding",
4477 .node
= FORWARDING_NODE
,
4479 .config_write
= config_write_forwarding
,
4483 void zebra_vty_init(void)
4485 /* Install configuration write function. */
4486 install_node(&table_node
);
4487 install_node(&forwarding_node
);
4489 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4490 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4491 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4492 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4494 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4495 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4496 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4499 zebra_route_map_init();
4501 zebra_affinity_map_init();
4503 install_node(&ip_node
);
4504 install_node(&protocol_node
);
4506 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4507 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4509 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4510 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4512 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4513 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4514 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4515 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4516 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4517 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4518 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4519 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4520 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4521 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4523 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4524 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4526 install_element(VIEW_NODE
, &show_vrf_cmd
);
4527 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4528 install_element(VIEW_NODE
, &show_route_cmd
);
4529 install_element(VIEW_NODE
, &show_ro_cmd
);
4530 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4531 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4532 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4534 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4535 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4537 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4538 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4539 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4540 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4541 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4542 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4543 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4544 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4545 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4547 install_element(VIEW_NODE
, &show_frr_cmd
);
4548 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4549 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4550 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4551 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4552 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4553 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4554 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4555 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4556 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4557 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4558 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4574 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4575 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4576 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4577 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4578 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4579 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4580 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4582 install_element(VIEW_NODE
, &show_neigh_cmd
);
4584 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4585 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4586 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4587 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4588 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4590 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4591 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4592 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4593 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4594 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4595 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4596 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4597 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4599 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4600 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4601 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4602 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4604 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4605 install_element(VRF_NODE
, &ip_table_range_cmd
);
4608 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4609 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4610 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4611 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4612 #endif /* HAVE_NETLINK */
4614 #ifdef HAVE_SCRIPTING
4615 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4616 #endif /* HAVE_SCRIPTING */
4618 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);