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_routemap.h"
47 #include "lib/route_opaque.h"
48 #include "zebra/zebra_vxlan.h"
49 #include "zebra/zebra_evpn_mh.h"
50 #include "zebra/zebra_vty_clippy.c"
51 #include "zebra/zserv.h"
52 #include "zebra/router-id.h"
53 #include "zebra/ipforward.h"
54 #include "zebra/zebra_vxlan_private.h"
55 #include "zebra/zebra_pbr.h"
56 #include "zebra/zebra_nhg.h"
57 #include "zebra/zebra_evpn_mh.h"
58 #include "zebra/interface.h"
59 #include "northbound_cli.h"
60 #include "zebra/zebra_nb.h"
61 #include "zebra/kernel_netlink.h"
62 #include "zebra/if_netlink.h"
63 #include "zebra/table_manager.h"
64 #include "zebra/zebra_script.h"
65 #include "zebra/rtadv.h"
66 #include "zebra/zebra_neigh.h"
68 /* context to manage dumps in multiple tables or vrfs */
69 struct route_show_ctx
{
70 bool multi
; /* dump multiple tables or vrf */
71 bool header_done
; /* common header already displayed */
74 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
75 safi_t safi
, bool use_fib
, bool use_json
,
77 const struct prefix
*longer_prefix_p
,
78 bool supernets_only
, int type
,
79 unsigned short ospf_instance_id
, uint32_t tableid
,
80 bool show_ng
, struct route_show_ctx
*ctx
);
81 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
82 int mcast
, bool use_fib
, bool show_ng
);
83 static void vty_show_ip_route_summary(struct vty
*vty
,
84 struct route_table
*table
, bool use_json
);
85 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
86 struct route_table
*table
,
88 /* Helper api to format a nexthop in the 'detailed' output path. */
89 static void show_nexthop_detail_helper(struct vty
*vty
,
90 const struct route_entry
*re
,
91 const struct nexthop
*nexthop
,
94 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
95 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
96 struct route_entry
*re
, unsigned int num
);
98 DEFUN (ip_multicast_mode
,
99 ip_multicast_mode_cmd
,
100 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
102 "Multicast options\n"
103 "RPF lookup behavior\n"
104 "Lookup in unicast RIB only\n"
105 "Lookup in multicast RIB only\n"
106 "Try multicast RIB first, fall back to unicast RIB\n"
107 "Lookup both, use entry with lower distance\n"
108 "Lookup both, use entry with longer prefix\n")
110 char *mode
= argv
[3]->text
;
112 if (strmatch(mode
, "urib-only"))
113 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
114 else if (strmatch(mode
, "mrib-only"))
115 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
116 else if (strmatch(mode
, "mrib-then-urib"))
117 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
118 else if (strmatch(mode
, "lower-distance"))
119 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
120 else if (strmatch(mode
, "longer-prefix"))
121 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
123 vty_out(vty
, "Invalid mode specified\n");
124 return CMD_WARNING_CONFIG_FAILED
;
130 DEFUN (no_ip_multicast_mode
,
131 no_ip_multicast_mode_cmd
,
132 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
135 "Multicast options\n"
136 "RPF lookup behavior\n"
137 "Lookup in unicast RIB only\n"
138 "Lookup in multicast RIB only\n"
139 "Try multicast RIB first, fall back to unicast RIB\n"
140 "Lookup both, use entry with lower distance\n"
141 "Lookup both, use entry with longer prefix\n")
143 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
150 "show ip rpf [json]",
153 "Display RPF information for multicast source\n"
156 bool uj
= use_json(argc
, argv
);
157 struct route_show_ctx ctx
= {
161 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
162 false, uj
, 0, NULL
, false, 0, 0, 0, false,
166 DEFUN (show_ip_rpf_addr
,
167 show_ip_rpf_addr_cmd
,
168 "show ip rpf A.B.C.D",
171 "Display RPF information for multicast source\n"
172 "IP multicast source address (e.g. 10.0.0.0)\n")
176 struct route_node
*rn
;
177 struct route_entry
*re
;
180 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
182 vty_out(vty
, "%% Malformed address\n");
186 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
189 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
191 vty_out(vty
, "%% No match for RPF lookup\n");
196 static char re_status_output_char(const struct route_entry
*re
,
197 const struct nexthop
*nhop
,
200 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
204 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
205 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
206 /* More-specific test for 'fib' output */
208 star_p
= !!CHECK_FLAG(nhop
->flags
,
214 if (zrouter
.asic_offloaded
&&
215 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
218 if (zrouter
.asic_offloaded
219 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
222 if (zrouter
.asic_offloaded
223 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
226 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
235 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
236 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
242 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
249 * Show backup nexthop info, in the 'detailed' output path
251 static void show_nh_backup_helper(struct vty
*vty
,
252 const struct route_entry
*re
,
253 const struct nexthop
*nexthop
)
255 const struct nexthop
*start
, *backup
, *temp
;
258 /* Double-check that there _is_ a backup */
259 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
260 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
261 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
264 /* Locate the backup nexthop(s) */
265 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
266 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
267 /* Format the backup(s) (indented) */
269 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
270 backup
= backup
->next
;
275 /* It's possible for backups to be recursive too,
276 * so walk the recursive resolution list if present.
281 show_nexthop_detail_helper(vty
, re
, backup
,
285 if (backup
->resolved
&& temp
== backup
)
286 backup
= backup
->resolved
;
288 backup
= nexthop_next(backup
);
290 if (backup
== temp
->next
)
298 * Helper api to format output for a nexthop, used in the 'detailed'
301 static void show_nexthop_detail_helper(struct vty
*vty
,
302 const struct route_entry
*re
,
303 const struct nexthop
*nexthop
,
307 char buf
[MPLS_LABEL_STRLEN
];
312 nexthop
->rparent
? " " : "");
314 vty_out(vty
, " %c%s",
315 re_status_output_char(re
, nexthop
, false),
316 nexthop
->rparent
? " " : "");
318 switch (nexthop
->type
) {
319 case NEXTHOP_TYPE_IPV4
:
320 case NEXTHOP_TYPE_IPV4_IFINDEX
:
321 vty_out(vty
, " %pI4",
322 &nexthop
->gate
.ipv4
);
323 if (nexthop
->ifindex
)
324 vty_out(vty
, ", via %s",
329 case NEXTHOP_TYPE_IPV6
:
330 case NEXTHOP_TYPE_IPV6_IFINDEX
:
332 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
334 if (nexthop
->ifindex
)
335 vty_out(vty
, ", via %s",
341 case NEXTHOP_TYPE_IFINDEX
:
342 vty_out(vty
, " directly connected, %s",
343 ifindex2ifname(nexthop
->ifindex
,
346 case NEXTHOP_TYPE_BLACKHOLE
:
347 vty_out(vty
, " unreachable");
348 switch (nexthop
->bh_type
) {
349 case BLACKHOLE_REJECT
:
350 vty_out(vty
, " (ICMP unreachable)");
352 case BLACKHOLE_ADMINPROHIB
:
354 " (ICMP admin-prohibited)");
357 vty_out(vty
, " (blackhole)");
359 case BLACKHOLE_UNSPEC
:
365 if (re
->vrf_id
!= nexthop
->vrf_id
) {
366 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
368 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
371 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
372 vty_out(vty
, " (duplicate nexthop removed)");
374 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
375 vty_out(vty
, " inactive");
377 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
378 vty_out(vty
, " onlink");
380 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
381 vty_out(vty
, " linkdown");
383 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
384 vty_out(vty
, " (recursive)");
386 /* Source specified? */
387 switch (nexthop
->type
) {
388 case NEXTHOP_TYPE_IPV4
:
389 case NEXTHOP_TYPE_IPV4_IFINDEX
:
390 if (nexthop
->src
.ipv4
.s_addr
) {
391 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
392 addrstr
, sizeof(addrstr
)))
393 vty_out(vty
, ", src %s",
398 case NEXTHOP_TYPE_IPV6
:
399 case NEXTHOP_TYPE_IPV6_IFINDEX
:
400 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
402 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
403 addrstr
, sizeof(addrstr
)))
404 vty_out(vty
, ", src %s",
409 case NEXTHOP_TYPE_IFINDEX
:
410 case NEXTHOP_TYPE_BLACKHOLE
:
415 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
417 /* Label information */
418 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
419 vty_out(vty
, ", label %s",
420 mpls_label2str(nexthop
->nh_label
->num_labels
,
421 nexthop
->nh_label
->label
, buf
,
422 sizeof(buf
), 1 /*pretty*/));
426 vty_out(vty
, ", weight %u", nexthop
->weight
);
428 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
429 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
431 for (i
= 1; i
< nexthop
->backup_num
; i
++)
432 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
436 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
437 struct json_object
*json
)
439 struct bgp_zebra_opaque bzo
= {};
440 struct ospf_zebra_opaque ozo
= {};
446 case ZEBRA_ROUTE_SHARP
:
448 json_object_string_add(json
, "opaque",
449 (char *)re
->opaque
->data
);
451 vty_out(vty
, " Opaque Data: %s",
452 (char *)re
->opaque
->data
);
455 case ZEBRA_ROUTE_BGP
:
456 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
459 json_object_string_add(json
, "asPath", bzo
.aspath
);
460 json_object_string_add(json
, "communities",
462 json_object_string_add(json
, "largeCommunities",
464 json_object_string_add(json
, "selectionReason",
465 bzo
.selection_reason
);
467 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
469 if (bzo
.community
[0] != '\0')
470 vty_out(vty
, " Communities : %s\n",
473 if (bzo
.lcommunity
[0] != '\0')
474 vty_out(vty
, " Large-Communities: %s\n",
477 vty_out(vty
, " Selection reason : %s\n",
478 bzo
.selection_reason
);
481 case ZEBRA_ROUTE_OSPF
:
482 case ZEBRA_ROUTE_OSPF6
:
483 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
486 json_object_string_add(json
, "ospfPathType",
488 if (ozo
.area_id
[0] != '\0')
489 json_object_string_add(json
, "ospfAreaId",
491 if (ozo
.tag
[0] != '\0')
492 json_object_string_add(json
, "ospfTag",
495 vty_out(vty
, " OSPF path type : %s\n",
497 if (ozo
.area_id
[0] != '\0')
498 vty_out(vty
, " OSPF area ID : %s\n",
500 if (ozo
.tag
[0] != '\0')
501 vty_out(vty
, " OSPF tag : %s\n",
510 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
514 cur
= monotime(NULL
);
517 frrtime_to_interval(cur
, buf
, bufsize
);
520 /* New RIB. Detailed information for IPv4 route. */
521 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
522 int mcast
, bool use_fib
, bool show_ng
)
524 struct route_entry
*re
;
525 struct nexthop
*nexthop
;
526 char buf
[SRCDEST2STR_BUFFER
];
527 struct zebra_vrf
*zvrf
;
530 dest
= rib_dest_from_rnode(rn
);
532 RNODE_FOREACH_RE (rn
, re
) {
534 * If re not selected for forwarding, skip re
535 * for "show ip/ipv6 fib <prefix>"
537 if (use_fib
&& re
!= dest
->selected_fib
)
540 const char *mcast_info
= "";
542 struct rib_table_info
*info
=
543 srcdest_rnode_table_info(rn
);
544 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
545 ? " using Multicast RIB"
546 : " using Unicast RIB";
549 vty_out(vty
, "Routing entry for %s%s\n",
550 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
551 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
553 vty_out(vty
, "[%d]", re
->instance
);
555 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
558 vty_out(vty
, ", tag %u", re
->tag
);
559 #if defined(SUPPORT_REALMS)
560 if (re
->tag
> 0 && re
->tag
<= 255)
561 vty_out(vty
, "(realm)");
565 vty_out(vty
, ", mtu %u", re
->mtu
);
566 if (re
->vrf_id
!= VRF_DEFAULT
) {
567 zvrf
= vrf_info_lookup(re
->vrf_id
);
568 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
570 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
571 vty_out(vty
, ", best");
574 uptime2str(re
->uptime
, buf
, sizeof(buf
));
576 vty_out(vty
, " Last update %s ago\n", buf
);
579 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
580 if (re
->nhe_installed_id
!= 0
581 && re
->nhe_id
!= re
->nhe_installed_id
)
583 " Installed Nexthop Group ID: %u\n",
584 re
->nhe_installed_id
);
587 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
588 /* Use helper to format each nexthop */
589 show_nexthop_detail_helper(vty
, re
, nexthop
,
590 false /*not backup*/);
593 /* Include backup(s), if present */
594 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
595 show_nh_backup_helper(vty
, re
, nexthop
);
597 zebra_show_ip_route_opaque(vty
, re
, NULL
);
603 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
604 struct route_entry
*re
, json_object
*json
,
605 bool is_fib
, bool show_ng
)
607 const struct nexthop
*nexthop
;
609 char buf
[SRCDEST2STR_BUFFER
];
610 json_object
*json_nexthops
= NULL
;
611 json_object
*json_nexthop
= NULL
;
612 json_object
*json_route
= NULL
;
613 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
614 const struct nexthop_group
*nhg
;
615 char up_str
[MONOTIME_STRLEN
];
617 bool nhg_from_backup
= false;
619 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
621 /* If showing fib information, use the fib view of the
625 nhg
= rib_get_fib_nhg(re
);
627 nhg
= &(re
->nhe
->nhg
);
630 json_route
= json_object_new_object();
631 json_nexthops
= json_object_new_array();
633 json_object_string_add(json_route
, "prefix",
634 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
635 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
636 json_object_string_add(json_route
, "protocol",
637 zebra_route_string(re
->type
));
640 json_object_int_add(json_route
, "instance",
643 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
644 json_object_string_add(json_route
, "vrfName",
645 vrf_id_to_name(re
->vrf_id
));
647 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
648 json_object_boolean_true_add(json_route
, "selected");
650 if (dest
->selected_fib
== re
)
651 json_object_boolean_true_add(json_route
,
654 json_object_int_add(json_route
, "distance",
656 json_object_int_add(json_route
, "metric", re
->metric
);
658 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
659 json_object_boolean_true_add(json_route
, "installed");
661 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
662 json_object_boolean_true_add(json_route
, "failed");
664 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
665 json_object_boolean_true_add(json_route
, "queued");
667 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
668 json_object_boolean_true_add(json_route
, "trapped");
670 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
671 json_object_boolean_true_add(json_route
, "offloaded");
673 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
674 json_object_boolean_false_add(json_route
, "offloaded");
677 json_object_int_add(json_route
, "tag", re
->tag
);
680 json_object_int_add(json_route
, "table", re
->table
);
682 json_object_int_add(json_route
, "internalStatus",
684 json_object_int_add(json_route
, "internalFlags",
686 json_object_int_add(json_route
, "internalNextHopNum",
687 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
688 json_object_int_add(json_route
, "internalNextHopActiveNum",
689 nexthop_group_active_nexthop_num(
691 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
693 if (re
->nhe_installed_id
!= 0)
694 json_object_int_add(json_route
,
695 "installedNexthopGroupId",
696 re
->nhe_installed_id
);
698 json_object_string_add(json_route
, "uptime", up_str
);
700 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
701 json_nexthop
= json_object_new_object();
702 show_nexthop_json_helper(json_nexthop
,
705 json_object_array_add(json_nexthops
,
709 json_object_object_add(json_route
, "nexthops", json_nexthops
);
711 /* If there are backup nexthops, include them */
713 nhg
= rib_get_fib_backup_nhg(re
);
715 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
717 if (nhg
&& nhg
->nexthop
) {
718 json_nexthops
= json_object_new_array();
720 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
721 json_nexthop
= json_object_new_object();
723 show_nexthop_json_helper(json_nexthop
,
725 json_object_array_add(json_nexthops
,
729 json_object_object_add(json_route
, "backupNexthops",
732 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
734 json_object_array_add(json
, json_route
);
738 /* Prefix information, and first nexthop. If we're showing 'fib',
739 * and there are no installed primary nexthops, see if there are any
740 * backup nexthops and start with those.
742 if (is_fib
&& nhg
->nexthop
== NULL
) {
743 nhg
= rib_get_fib_backup_nhg(re
);
744 nhg_from_backup
= true;
747 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
749 len
+= vty_out(vty
, "[%d]", re
->instance
);
750 if (nhg_from_backup
&& nhg
->nexthop
) {
753 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
754 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
755 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
759 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
760 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
761 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
764 /* Distance and metric display. */
765 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
766 (re
->distance
|| re
->metric
)) ||
767 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
768 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
772 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
774 /* Nexthop information. */
775 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
778 } else if (nhg_from_backup
) {
779 vty_out(vty
, " b%c%*c",
780 re_status_output_char(re
, nexthop
, is_fib
),
781 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
783 vty_out(vty
, " %c%*c",
784 re_status_output_char(re
, nexthop
, is_fib
),
785 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
788 show_route_nexthop_helper(vty
, re
, nexthop
);
789 vty_out(vty
, ", %s\n", up_str
);
792 /* If we only had backup nexthops, we're done */
796 /* Check for backup nexthop info if present */
798 nhg
= rib_get_fib_backup_nhg(re
);
800 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
805 /* Print backup info */
806 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
810 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
812 /* TODO -- it'd be nice to be able to include
813 * the entire list of backups, *and* include the
814 * real installation state.
816 vty_out(vty
, " b%c %*c",
817 (star_p
? '*' : ' '),
818 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
819 show_route_nexthop_helper(vty
, re
, nexthop
);
825 static void vty_show_ip_route_detail_json(struct vty
*vty
,
826 struct route_node
*rn
, bool use_fib
)
828 json_object
*json
= NULL
;
829 json_object
*json_prefix
= NULL
;
830 struct route_entry
*re
;
834 dest
= rib_dest_from_rnode(rn
);
836 json
= json_object_new_object();
837 json_prefix
= json_object_new_array();
839 RNODE_FOREACH_RE (rn
, re
) {
841 * If re not selected for forwarding, skip re
842 * for "show ip/ipv6 fib <prefix> json"
844 if (use_fib
&& re
!= dest
->selected_fib
)
846 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
849 prefix2str(&rn
->p
, buf
, sizeof(buf
));
850 json_object_object_add(json
, buf
, json_prefix
);
854 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
855 struct route_table
*table
, afi_t afi
,
856 bool use_fib
, route_tag_t tag
,
857 const struct prefix
*longer_prefix_p
,
858 bool supernets_only
, int type
,
859 unsigned short ospf_instance_id
, bool use_json
,
860 uint32_t tableid
, bool show_ng
,
861 struct route_show_ctx
*ctx
)
863 struct route_node
*rn
;
864 struct route_entry
*re
;
867 json_object
*json
= NULL
;
868 json_object
*json_prefix
= NULL
;
873 * ctx->multi indicates if we are dumping multiple tables or vrfs.
875 * => display the common header at most once
876 * => add newline at each call except first
877 * => always display the VRF and table
879 * => display the common header if at least one entry is found
880 * => display the VRF and table if specific
884 json
= json_object_new_object();
886 /* Show all routes. */
887 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
888 dest
= rib_dest_from_rnode(rn
);
890 RNODE_FOREACH_RE (rn
, re
) {
891 if (use_fib
&& re
!= dest
->selected_fib
)
894 if (tag
&& re
->tag
!= tag
)
898 && !prefix_match(longer_prefix_p
, &rn
->p
))
901 /* This can only be true when the afi is IPv4 */
902 if (supernets_only
) {
903 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
905 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
908 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
911 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
915 if (type
&& re
->type
!= type
)
919 && (re
->type
!= ZEBRA_ROUTE_OSPF
920 || re
->instance
!= ospf_instance_id
))
925 json_prefix
= json_object_new_array();
927 if (!ctx
->header_done
) {
930 SHOW_ROUTE_V4_HEADER
);
933 SHOW_ROUTE_V6_HEADER
);
935 if (ctx
->multi
&& ctx
->header_done
)
937 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
940 vty_out(vty
, "VRF %s:\n",
944 "VRF %s table %u:\n",
948 ctx
->header_done
= true;
952 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
957 prefix2str(&rn
->p
, buf
, sizeof(buf
));
958 json_object_object_add(json
, buf
, json_prefix
);
967 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
968 afi_t afi
, bool use_fib
, bool use_json
,
970 const struct prefix
*longer_prefix_p
,
971 bool supernets_only
, int type
,
972 unsigned short ospf_instance_id
, bool show_ng
,
973 struct route_show_ctx
*ctx
)
975 struct zebra_router_table
*zrt
;
976 struct rib_table_info
*info
;
978 RB_FOREACH (zrt
, zebra_router_table_head
,
980 info
= route_table_get_info(zrt
->table
);
982 if (zvrf
!= info
->zvrf
)
984 if (zrt
->afi
!= afi
||
985 zrt
->safi
!= SAFI_UNICAST
)
988 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
989 use_fib
, use_json
, tag
, longer_prefix_p
,
990 supernets_only
, type
, ospf_instance_id
,
991 zrt
->tableid
, show_ng
, ctx
);
995 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
996 safi_t safi
, bool use_fib
, bool use_json
,
998 const struct prefix
*longer_prefix_p
,
999 bool supernets_only
, int type
,
1000 unsigned short ospf_instance_id
, uint32_t tableid
,
1001 bool show_ng
, struct route_show_ctx
*ctx
)
1003 struct route_table
*table
;
1004 struct zebra_vrf
*zvrf
= NULL
;
1006 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1008 vty_out(vty
, "{}\n");
1010 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1014 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1016 vty_out(vty
, "{}\n");
1018 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1023 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1025 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1028 vty_out(vty
, "{}\n");
1032 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1033 longer_prefix_p
, supernets_only
, type
,
1034 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1041 "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]",
1045 "IP nexthop tracking table\n"
1046 "IP import check tracking table\n"
1052 VRF_ALL_CMD_HELP_STR
1053 "Show Multicast (MRIB) NHT state\n"
1056 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1057 vrf_id_t vrf_id
= VRF_DEFAULT
;
1058 struct prefix prefix
, *p
= NULL
;
1059 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1060 bool uj
= use_json(argc
, argv
);
1061 json_object
*json
= NULL
;
1062 json_object
*json_vrf
= NULL
;
1063 json_object
*json_nexthop
= NULL
;
1066 json
= json_object_new_object();
1070 struct zebra_vrf
*zvrf
;
1072 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1073 if ((zvrf
= vrf
->info
) != NULL
) {
1075 json_vrf
= json_object_new_object();
1076 json_nexthop
= json_object_new_object();
1077 json_object_object_add(json
,
1080 json_object_object_add(json_vrf
,
1086 vty_out(vty
, "\nVRF %s:\n",
1089 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1090 vty
, NULL
, json_nexthop
);
1095 vty_json(vty
, json
);
1100 VRF_GET_ID(vrf_id
, vrf_name
, false);
1102 memset(&prefix
, 0, sizeof(prefix
));
1104 p
= sockunion2hostprefix(addr
, &prefix
);
1107 json_object_free(json
);
1113 json_vrf
= json_object_new_object();
1114 json_nexthop
= json_object_new_object();
1116 json_object_object_add(json
, vrf_name
, json_vrf
);
1118 json_object_object_add(json
, "default", json_vrf
);
1120 json_object_object_add(json_vrf
,
1121 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1125 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1128 vty_json(vty
, json
);
1133 DEFUN (ip_nht_default_route
,
1134 ip_nht_default_route_cmd
,
1135 "ip nht resolve-via-default",
1137 "Filter Next Hop tracking route resolution\n"
1138 "Resolve via default route\n")
1140 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1145 if (zvrf
->zebra_rnh_ip_default_route
)
1148 zvrf
->zebra_rnh_ip_default_route
= true;
1150 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1154 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1155 json_object
*json_nhe_hdr
)
1157 struct nexthop
*nexthop
= NULL
;
1158 struct nhg_connected
*rb_node_dep
= NULL
;
1159 struct nexthop_group
*backup_nhg
;
1160 char up_str
[MONOTIME_STRLEN
];
1161 char time_left
[MONOTIME_STRLEN
];
1162 json_object
*json_dependants
= NULL
;
1163 json_object
*json_depends
= NULL
;
1164 json_object
*json_nexthop_array
= NULL
;
1165 json_object
*json_nexthops
= NULL
;
1166 json_object
*json
= NULL
;
1167 json_object
*json_backup_nexthop_array
= NULL
;
1168 json_object
*json_backup_nexthops
= NULL
;
1171 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1174 json
= json_object_new_object();
1177 json_object_string_add(json
, "type",
1178 zebra_route_string(nhe
->type
));
1179 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1180 if (thread_is_scheduled(nhe
->timer
))
1181 json_object_string_add(
1182 json
, "timeToDeletion",
1183 thread_timer_to_hhmmss(time_left
,
1186 json_object_string_add(json
, "uptime", up_str
);
1187 json_object_string_add(json
, "vrf",
1188 vrf_id_to_name(nhe
->vrf_id
));
1191 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1192 zebra_route_string(nhe
->type
));
1193 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1194 if (thread_is_scheduled(nhe
->timer
))
1195 vty_out(vty
, " Time to Deletion: %s",
1196 thread_timer_to_hhmmss(time_left
,
1201 vty_out(vty
, " Uptime: %s\n", up_str
);
1202 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1205 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1207 json_object_boolean_true_add(json
, "valid");
1209 vty_out(vty
, " Valid");
1211 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1213 json_object_boolean_true_add(json
, "installed");
1215 vty_out(vty
, ", Installed");
1222 json_object_int_add(json
, "interfaceIndex",
1225 vty_out(vty
, " Interface Index: %d\n",
1229 if (!zebra_nhg_depends_is_empty(nhe
)) {
1231 json_depends
= json_object_new_array();
1233 vty_out(vty
, " Depends:");
1234 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1236 json_object_array_add(
1238 json_object_new_int(
1239 rb_node_dep
->nhe
->id
));
1241 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1246 json_object_object_add(json
, "depends", json_depends
);
1249 /* Output nexthops */
1251 json_nexthop_array
= json_object_new_array();
1254 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1255 if (json_nexthop_array
) {
1256 json_nexthops
= json_object_new_object();
1257 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1259 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1262 /* Make recursive nexthops a bit more clear */
1264 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1267 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1268 if (CHECK_FLAG(nexthop
->flags
,
1269 NEXTHOP_FLAG_HAS_BACKUP
)) {
1271 json_object_int_add(
1272 json_nexthops
, "backup",
1273 nexthop
->backup_idx
[0]);
1275 vty_out(vty
, " [backup %d]",
1276 nexthop
->backup_idx
[0]);
1282 json_object_array_add(json_nexthop_array
,
1289 /* TODO -- print more useful backup info */
1290 if (CHECK_FLAG(nexthop
->flags
,
1291 NEXTHOP_FLAG_HAS_BACKUP
)) {
1294 vty_out(vty
, "[backup");
1295 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1297 nexthop
->backup_idx
[i
]);
1302 json_object_array_add(json_nexthop_array
,
1308 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1310 /* Output backup nexthops (if any) */
1311 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1314 json_backup_nexthop_array
= json_object_new_array();
1316 vty_out(vty
, " Backups:\n");
1318 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1319 if (json_backup_nexthop_array
) {
1320 json_backup_nexthops
= json_object_new_object();
1321 show_nexthop_json_helper(json_backup_nexthops
,
1323 json_object_array_add(json_backup_nexthop_array
,
1324 json_backup_nexthops
);
1327 if (!CHECK_FLAG(nexthop
->flags
,
1328 NEXTHOP_FLAG_RECURSIVE
))
1331 /* Make recursive nexthops a bit more
1335 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1341 json_object_object_add(json
, "backupNexthops",
1342 json_backup_nexthop_array
);
1345 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1347 json_dependants
= json_object_new_array();
1349 vty_out(vty
, " Dependents:");
1350 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1353 json_object_array_add(
1355 json_object_new_int(
1356 rb_node_dep
->nhe
->id
));
1358 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1361 json_object_object_add(json
, "dependents",
1367 if (nhe
->nhg
.nhgr
.buckets
) {
1369 json_object_int_add(json
, "buckets",
1370 nhe
->nhg
.nhgr
.buckets
);
1371 json_object_int_add(json
, "idleTimer",
1372 nhe
->nhg
.nhgr
.idle_timer
);
1373 json_object_int_add(json
, "unbalancedTimer",
1374 nhe
->nhg
.nhgr
.unbalanced_timer
);
1375 json_object_int_add(json
, "unbalancedTime",
1376 nhe
->nhg
.nhgr
.unbalanced_time
);
1379 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1381 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1382 nhe
->nhg
.nhgr
.unbalanced_timer
,
1383 nhe
->nhg
.nhgr
.unbalanced_time
);
1388 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1391 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1394 struct nhg_hash_entry
*nhe
= NULL
;
1396 nhe
= zebra_nhg_lookup_id(id
);
1399 show_nexthop_group_out(vty
, nhe
, json
);
1402 vty_json(vty
, json
);
1404 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1410 vty_json(vty
, json
);
1415 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1417 struct nhe_show_context
{
1425 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1427 struct nhe_show_context
*ctx
= arg
;
1428 struct nhg_hash_entry
*nhe
;
1430 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1432 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1435 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1438 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1441 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1444 return HASHWALK_CONTINUE
;
1447 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1448 struct zebra_vrf
*zvrf
, afi_t afi
,
1449 int type
, json_object
*json
)
1451 struct nhe_show_context ctx
;
1455 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1459 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1462 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1464 struct zebra_if
*zebra_if
= NULL
;
1465 struct nhg_connected
*rb_node_dep
= NULL
;
1467 zebra_if
= ifp
->info
;
1469 if (!if_nhg_dependents_is_empty(ifp
)) {
1470 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1472 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1475 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1480 DEFPY (show_interface_nexthop_group
,
1481 show_interface_nexthop_group_cmd
,
1482 "show interface [IFNAME$if_name] nexthop-group",
1484 "Interface status and configuration\n"
1486 "Show Nexthop Groups\n")
1488 struct vrf
*vrf
= NULL
;
1489 struct interface
*ifp
= NULL
;
1492 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1494 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1496 if_nexthop_group_dump_vty(vty
, ifp
);
1500 FOR_ALL_INTERFACES (vrf
, ifp
)
1501 if_nexthop_group_dump_vty(vty
, ifp
);
1507 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1514 DEFPY(show_nexthop_group
,
1515 show_nexthop_group_cmd
,
1516 "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]",
1518 "Show Nexthop Groups\n"
1520 "Nexthop Group ID\n"
1521 "Show Singleton Nexthop-Groups\n"
1524 "Kernel (not installed via the zebra RIB)\n"
1525 "Zebra (implicitly created by zebra)\n"
1526 "Border Gateway Protocol (BGP)\n"
1527 "Super Happy Advanced Routing Protocol (SHARP)\n"
1528 VRF_FULL_CMD_HELP_STR
1532 struct zebra_vrf
*zvrf
= NULL
;
1533 afi_t afi
= AFI_UNSPEC
;
1535 bool uj
= use_json(argc
, argv
);
1536 json_object
*json
= NULL
;
1537 json_object
*json_vrf
= NULL
;
1540 json
= json_object_new_object();
1543 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1551 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1554 type
= ZEBRA_ROUTE_NHG
;
1558 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1560 vty_json(vty
, json
);
1563 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1570 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1571 struct zebra_vrf
*zvrf
;
1577 json_vrf
= json_object_new_object();
1579 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1581 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1584 json_object_object_add(json
, vrf
->name
,
1589 vty_json(vty
, json
);
1595 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1597 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1601 vty_json(vty
, json
);
1603 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1608 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1611 vty_json(vty
, json
);
1616 DEFPY_HIDDEN(nexthop_group_use_enable
,
1617 nexthop_group_use_enable_cmd
,
1618 "[no] zebra nexthop kernel enable",
1621 "Nexthop configuration \n"
1622 "Configure use of kernel nexthops\n"
1623 "Enable kernel nexthops\n")
1625 zebra_nhg_enable_kernel_nexthops(!no
);
1629 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1630 "[no] zebra nexthop proto only",
1632 "Nexthop configuration\n"
1633 "Configure exclusive use of proto nexthops\n"
1634 "Only use proto nexthops\n")
1636 zebra_nhg_set_proto_nexthops_only(!no
);
1640 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1641 backup_nexthop_recursive_use_enable_cmd
,
1642 "[no] zebra nexthop resolve-via-backup",
1645 "Nexthop configuration \n"
1646 "Configure use of backup nexthops in recursive resolution\n")
1648 zebra_nhg_set_recursive_use_backups(!no
);
1652 DEFUN (no_ip_nht_default_route
,
1653 no_ip_nht_default_route_cmd
,
1654 "no ip nht resolve-via-default",
1657 "Filter Next Hop tracking route resolution\n"
1658 "Resolve via default route\n")
1660 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1665 if (!zvrf
->zebra_rnh_ip_default_route
)
1668 zvrf
->zebra_rnh_ip_default_route
= false;
1669 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1673 DEFUN (ipv6_nht_default_route
,
1674 ipv6_nht_default_route_cmd
,
1675 "ipv6 nht resolve-via-default",
1677 "Filter Next Hop tracking route resolution\n"
1678 "Resolve via default route\n")
1680 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1685 if (zvrf
->zebra_rnh_ipv6_default_route
)
1688 zvrf
->zebra_rnh_ipv6_default_route
= true;
1689 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1693 DEFUN (no_ipv6_nht_default_route
,
1694 no_ipv6_nht_default_route_cmd
,
1695 "no ipv6 nht resolve-via-default",
1698 "Filter Next Hop tracking route resolution\n"
1699 "Resolve via default route\n")
1701 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1706 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1709 zvrf
->zebra_rnh_ipv6_default_route
= false;
1710 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1714 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1715 "[no] ip nht hide-backup-events",
1718 "Nexthop-tracking configuration\n"
1719 "Hide notification about backup nexthops\n")
1721 rnh_set_hide_backups(!no
);
1729 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1730 [vrf <NAME$vrf_name|all$vrf_all>]\
1733 |A.B.C.D/M$prefix longer-prefixes\
1734 |supernets-only$supernets_only\
1737 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1738 |ospf$type_str (1-65535)$ospf_instance_id\
1740 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1741 [vrf <NAME$vrf_name|all$vrf_all>]\
1744 |X:X::X:X/M$prefix longer-prefixes\
1746 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1748 [<json$json|nexthop-group$ng>]",
1751 "IP forwarding table\n"
1752 "IP routing table\n"
1753 "Table to display\n"
1754 "The table number to display\n"
1756 VRF_FULL_CMD_HELP_STR
1757 "Show only routes with tag\n"
1759 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1760 "Show route matching the specified Network/Mask pair only\n"
1761 "Show supernet entries only\n"
1762 FRR_IP_REDIST_HELP_STR_ZEBRA
1763 "Open Shortest Path First (OSPFv2)\n"
1766 "IP forwarding table\n"
1767 "IP routing table\n"
1768 "Table to display\n"
1769 "The table number to display\n"
1771 VRF_FULL_CMD_HELP_STR
1772 "Show only routes with tag\n"
1775 "Show route matching the specified Network/Mask pair only\n"
1776 FRR_IP6_REDIST_HELP_STR_ZEBRA
1778 "Nexthop Group Information\n")
1780 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1783 struct zebra_vrf
*zvrf
;
1784 struct route_show_ctx ctx
= {
1785 .multi
= vrf_all
|| table_all
,
1788 if (!vrf_is_backend_netns()) {
1789 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1791 vty_out(vty
, "{}\n");
1793 vty_out(vty
, "Linux vrf backend already points to table id\n");
1794 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1800 type
= proto_redistnum(afi
, type_str
);
1802 vty_out(vty
, "Unknown route type\n");
1808 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1809 if ((zvrf
= vrf
->info
) == NULL
1810 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1814 do_show_ip_route_all(
1815 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1816 prefix_str
? prefix
: NULL
,
1817 !!supernets_only
, type
,
1818 ospf_instance_id
, !!ng
, &ctx
);
1821 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1823 prefix_str
? prefix
: NULL
,
1824 !!supernets_only
, type
,
1825 ospf_instance_id
, table
, !!ng
, &ctx
);
1828 vrf_id_t vrf_id
= VRF_DEFAULT
;
1831 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1832 vrf
= vrf_lookup_by_id(vrf_id
);
1841 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1842 prefix_str
? prefix
: NULL
,
1843 !!supernets_only
, type
,
1844 ospf_instance_id
, !!ng
, &ctx
);
1846 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1848 prefix_str
? prefix
: NULL
,
1849 !!supernets_only
, type
,
1850 ospf_instance_id
, table
, !!ng
, &ctx
);
1856 ALIAS_HIDDEN (show_route
,
1858 "show <ip$ipv4|ipv6$ipv6> ro",
1862 "IP routing table\n");
1865 DEFPY (show_route_detail
,
1866 show_route_detail_cmd
,
1869 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1874 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1880 [json$json] [nexthop-group$ng]",
1883 "IP forwarding table\n"
1884 "IP routing table\n"
1885 VRF_FULL_CMD_HELP_STR
1886 "Network in the IP routing table to display\n"
1887 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1889 "IPv6 forwarding table\n"
1890 "IPv6 routing table\n"
1891 VRF_FULL_CMD_HELP_STR
1895 "Nexthop Group Information\n")
1897 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1898 struct route_table
*table
;
1900 struct route_node
*rn
;
1901 bool use_fib
= !!fib
;
1903 bool network_found
= false;
1904 bool show_ng
= !!ng
;
1907 prefix_str
= address_str
;
1908 if (str2prefix(prefix_str
, &p
) < 0) {
1909 vty_out(vty
, "%% Malformed address\n");
1915 struct zebra_vrf
*zvrf
;
1917 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1918 if ((zvrf
= vrf
->info
) == NULL
1919 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1922 rn
= route_node_match(table
, &p
);
1925 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1926 route_unlock_node(rn
);
1930 dest
= rib_dest_from_rnode(rn
);
1931 if (use_fib
&& !dest
->selected_fib
) {
1932 route_unlock_node(rn
);
1936 network_found
= true;
1938 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1940 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1943 route_unlock_node(rn
);
1946 if (!network_found
) {
1948 vty_out(vty
, "{}\n");
1952 "%% Network not in FIB\n");
1955 "%% Network not in RIB\n");
1960 vrf_id_t vrf_id
= VRF_DEFAULT
;
1963 VRF_GET_ID(vrf_id
, vrf_name
, false);
1965 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1969 rn
= route_node_match(table
, &p
);
1971 dest
= rib_dest_from_rnode(rn
);
1973 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1974 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1976 vty_out(vty
, "{}\n");
1980 "%% Network not in FIB\n");
1983 "%% Network not in table\n");
1986 route_unlock_node(rn
);
1991 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1993 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1995 route_unlock_node(rn
);
2001 DEFPY (show_route_summary
,
2002 show_route_summary_cmd
,
2003 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2004 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2008 "IP routing table\n"
2009 VRF_FULL_CMD_HELP_STR
2010 "Summary of all routes\n"
2011 "Table to display summary for\n"
2012 "The table number\n"
2016 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2017 struct route_table
*table
;
2018 bool uj
= use_json(argc
, argv
);
2022 struct zebra_vrf
*zvrf
;
2024 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2025 if ((zvrf
= vrf
->info
) == NULL
)
2029 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2032 table
= zebra_vrf_lookup_table_with_table_id(
2033 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2040 vty_show_ip_route_summary_prefix(vty
, table
,
2043 vty_show_ip_route_summary(vty
, table
, uj
);
2046 vrf_id_t vrf_id
= VRF_DEFAULT
;
2049 VRF_GET_ID(vrf_id
, vrf_name
, false);
2052 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2054 table
= zebra_vrf_lookup_table_with_table_id(
2055 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2060 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2062 vty_show_ip_route_summary(vty
, table
, uj
);
2068 DEFUN_HIDDEN (show_route_zebra_dump
,
2069 show_route_zebra_dump_cmd
,
2070 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2080 struct route_table
*table
;
2081 const char *vrf_name
= NULL
;
2084 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2086 if (argv_find(argv
, argc
, "vrf", &idx
))
2087 vrf_name
= argv
[++idx
]->arg
;
2091 struct zebra_vrf
*zvrf
;
2093 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2096 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2099 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2100 show_ip_route_dump_vty(vty
, table
);
2103 vrf_id_t vrf_id
= VRF_DEFAULT
;
2105 VRF_GET_ID(vrf_id
, vrf_name
, true);
2107 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2111 show_ip_route_dump_vty(vty
, table
);
2117 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2118 struct route_entry
*re
, unsigned int num
)
2121 char buf
[SRCDEST2STR_BUFFER
];
2123 vty_out(vty
, " Nexthop %u:\n", num
);
2124 vty_out(vty
, " type: %u\n", nexthop
->type
);
2125 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2126 switch (nexthop
->type
) {
2127 case NEXTHOP_TYPE_IPV4
:
2128 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2129 vty_out(vty
, " ip address: %s\n",
2130 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2132 vty_out(vty
, " afi: ipv4\n");
2134 if (nexthop
->ifindex
) {
2135 vty_out(vty
, " interface index: %d\n",
2137 vty_out(vty
, " interface name: %s\n",
2138 ifindex2ifname(nexthop
->ifindex
,
2142 if (nexthop
->src
.ipv4
.s_addr
2143 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2145 vty_out(vty
, " source: %s\n", buf
);
2147 case NEXTHOP_TYPE_IPV6
:
2148 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2149 vty_out(vty
, " ip: %s\n",
2150 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2152 vty_out(vty
, " afi: ipv6\n");
2154 if (nexthop
->ifindex
) {
2155 vty_out(vty
, " interface index: %d\n",
2157 vty_out(vty
, " interface name: %s\n",
2158 ifindex2ifname(nexthop
->ifindex
,
2162 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2163 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2165 vty_out(vty
, " source: %s\n", buf
);
2168 case NEXTHOP_TYPE_IFINDEX
:
2170 " Nexthop is an interface (directly connected).\n");
2171 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2172 vty_out(vty
, " interface name: %s\n",
2173 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2175 case NEXTHOP_TYPE_BLACKHOLE
:
2176 vty_out(vty
, " Nexthop type is blackhole.\n");
2178 switch (nexthop
->bh_type
) {
2179 case BLACKHOLE_REJECT
:
2180 vty_out(vty
, " Blackhole type: reject\n");
2182 case BLACKHOLE_ADMINPROHIB
:
2184 " Blackhole type: admin-prohibited\n");
2186 case BLACKHOLE_NULL
:
2187 vty_out(vty
, " Blackhole type: NULL0\n");
2189 case BLACKHOLE_UNSPEC
:
2196 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2198 struct route_node
*rn
;
2199 struct route_entry
*re
;
2200 char buf
[SRCDEST2STR_BUFFER
];
2205 struct nexthop
*nexthop
= NULL
;
2206 int nexthop_num
= 0;
2208 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2209 vty_out(vty
, "----------------------------\n");
2211 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2212 RNODE_FOREACH_RE (rn
, re
) {
2213 vty_out(vty
, "Route: %s\n",
2214 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2215 vty_out(vty
, " protocol: %s\n",
2216 zebra_route_string(re
->type
));
2217 vty_out(vty
, " instance: %u\n", re
->instance
);
2218 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2219 vty_out(vty
, " VRF name: %s\n",
2220 vrf_id_to_name(re
->vrf_id
));
2221 vty_out(vty
, " flags: %u\n", re
->flags
);
2223 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2224 vty_out(vty
, " distance: %u\n", re
->distance
);
2225 vty_out(vty
, " metric: %u\n", re
->metric
);
2228 vty_out(vty
, " tag: %u\n", re
->tag
);
2230 uptime
= monotime(&tv
);
2231 uptime
-= re
->uptime
;
2232 gmtime_r(&uptime
, &tm
);
2234 if (uptime
< ONE_DAY_SECOND
)
2235 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2236 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2237 else if (uptime
< ONE_WEEK_SECOND
)
2238 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2239 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2241 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2243 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2246 vty_out(vty
, " status: %u\n", re
->status
);
2247 vty_out(vty
, " nexthop_num: %u\n",
2248 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2249 vty_out(vty
, " nexthop_active_num: %u\n",
2250 nexthop_group_active_nexthop_num(
2252 vty_out(vty
, " table: %u\n", re
->table
);
2253 vty_out(vty
, " uptime: %s\n", time
);
2255 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2257 show_ip_route_nht_dump(vty
, nexthop
, re
,
2267 static void vty_show_ip_route_summary(struct vty
*vty
,
2268 struct route_table
*table
, bool use_json
)
2270 struct route_node
*rn
;
2271 struct route_entry
*re
;
2272 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2273 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2274 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2275 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2276 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2277 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2280 json_object
*json_route_summary
= NULL
;
2281 json_object
*json_route_routes
= NULL
;
2283 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2284 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2285 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2286 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2289 json_route_summary
= json_object_new_object();
2290 json_route_routes
= json_object_new_array();
2291 json_object_object_add(json_route_summary
, "routes",
2295 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2296 RNODE_FOREACH_RE (rn
, re
) {
2297 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2298 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2300 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2302 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2304 rib_cnt
[re
->type
]++;
2306 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2307 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2310 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2312 fib_cnt
[re
->type
]++;
2315 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2317 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2319 trap_cnt
[re
->type
]++;
2322 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2324 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2326 offload_cnt
[re
->type
]++;
2331 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2333 zvrf_name(((struct rib_table_info
*)
2334 route_table_get_info(table
))
2337 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2338 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2339 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2340 if (i
== ZEBRA_ROUTE_BGP
) {
2342 json_object
*json_route_ebgp
=
2343 json_object_new_object();
2345 json_object_int_add(
2346 json_route_ebgp
, "fib",
2347 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2348 json_object_int_add(
2349 json_route_ebgp
, "rib",
2350 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2351 json_object_int_add(
2352 json_route_ebgp
, "fibOffLoaded",
2353 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2354 json_object_int_add(
2355 json_route_ebgp
, "fibTrapped",
2356 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2358 json_object_string_add(json_route_ebgp
,
2360 json_object_array_add(json_route_routes
,
2363 json_object
*json_route_ibgp
=
2364 json_object_new_object();
2366 json_object_int_add(
2367 json_route_ibgp
, "fib",
2368 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2369 json_object_int_add(
2370 json_route_ibgp
, "rib",
2371 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2372 json_object_int_add(
2373 json_route_ibgp
, "fibOffLoaded",
2374 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2375 json_object_int_add(
2376 json_route_ibgp
, "fibTrapped",
2377 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2378 json_object_string_add(json_route_ibgp
,
2380 json_object_array_add(json_route_routes
,
2383 vty_out(vty
, "%-20s %-20d %-20d \n",
2385 rib_cnt
[ZEBRA_ROUTE_BGP
],
2386 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2387 vty_out(vty
, "%-20s %-20d %-20d \n",
2389 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2390 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2394 json_object
*json_route_type
=
2395 json_object_new_object();
2397 json_object_int_add(json_route_type
,
2399 json_object_int_add(json_route_type
,
2402 json_object_int_add(json_route_type
,
2405 json_object_int_add(json_route_type
,
2408 json_object_string_add(
2409 json_route_type
, "type",
2410 zebra_route_string(i
));
2411 json_object_array_add(json_route_routes
,
2414 vty_out(vty
, "%-20s %-20d %-20d \n",
2415 zebra_route_string(i
),
2416 rib_cnt
[i
], fib_cnt
[i
]);
2422 json_object_int_add(json_route_summary
, "routesTotal",
2423 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2424 json_object_int_add(json_route_summary
, "routesTotalFib",
2425 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2427 vty_json(vty
, json_route_summary
);
2429 vty_out(vty
, "------\n");
2430 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2431 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2437 * Implementation of the ip route summary prefix command.
2439 * This command prints the primary prefixes that have been installed by various
2440 * protocols on the box.
2443 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2444 struct route_table
*table
,
2447 struct route_node
*rn
;
2448 struct route_entry
*re
;
2449 struct nexthop
*nexthop
;
2450 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2451 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2452 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2453 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2456 json_object
*json_route_summary
= NULL
;
2457 json_object
*json_route_routes
= NULL
;
2459 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2460 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2463 json_route_summary
= json_object_new_object();
2464 json_route_routes
= json_object_new_array();
2465 json_object_object_add(json_route_summary
, "prefixRoutes",
2469 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2470 RNODE_FOREACH_RE (rn
, re
) {
2473 * In case of ECMP, count only once.
2476 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2477 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2478 fib_cnt
[re
->type
]++;
2480 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2481 nexthop
= nexthop
->next
) {
2483 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2484 rib_cnt
[re
->type
]++;
2485 if (re
->type
== ZEBRA_ROUTE_BGP
2486 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2487 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2488 if (CHECK_FLAG(re
->status
,
2489 ROUTE_ENTRY_INSTALLED
))
2490 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2496 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2497 "Prefix Routes", "FIB",
2498 zvrf_name(((struct rib_table_info
*)
2499 route_table_get_info(table
))
2502 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2503 if (rib_cnt
[i
] > 0) {
2504 if (i
== ZEBRA_ROUTE_BGP
) {
2506 json_object
*json_route_ebgp
=
2507 json_object_new_object();
2509 json_object_int_add(
2510 json_route_ebgp
, "fib",
2511 fib_cnt
[ZEBRA_ROUTE_BGP
]
2512 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2513 json_object_int_add(
2514 json_route_ebgp
, "rib",
2515 rib_cnt
[ZEBRA_ROUTE_BGP
]
2516 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2517 json_object_string_add(json_route_ebgp
,
2519 json_object_array_add(json_route_routes
,
2522 json_object
*json_route_ibgp
=
2523 json_object_new_object();
2525 json_object_int_add(
2526 json_route_ibgp
, "fib",
2527 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2528 json_object_int_add(
2529 json_route_ibgp
, "rib",
2530 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2531 json_object_string_add(json_route_ibgp
,
2533 json_object_array_add(json_route_routes
,
2536 vty_out(vty
, "%-20s %-20d %-20d \n",
2538 rib_cnt
[ZEBRA_ROUTE_BGP
]
2539 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2540 fib_cnt
[ZEBRA_ROUTE_BGP
]
2541 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2542 vty_out(vty
, "%-20s %-20d %-20d \n",
2544 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2545 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2549 json_object
*json_route_type
=
2550 json_object_new_object();
2552 json_object_int_add(json_route_type
,
2554 json_object_int_add(json_route_type
,
2556 json_object_string_add(
2557 json_route_type
, "type",
2558 zebra_route_string(i
));
2559 json_object_array_add(json_route_routes
,
2562 vty_out(vty
, "%-20s %-20d %-20d \n",
2563 zebra_route_string(i
),
2564 rib_cnt
[i
], fib_cnt
[i
]);
2570 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2571 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2572 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2573 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2575 vty_json(vty
, json_route_summary
);
2577 vty_out(vty
, "------\n");
2578 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2579 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2584 DEFUN (allow_external_route_update
,
2585 allow_external_route_update_cmd
,
2586 "allow-external-route-update",
2587 "Allow FRR routes to be overwritten by external processes\n")
2589 zrouter
.allow_delete
= true;
2594 DEFUN (no_allow_external_route_update
,
2595 no_allow_external_route_update_cmd
,
2596 "no allow-external-route-update",
2598 "Allow FRR routes to be overwritten by external processes\n")
2600 zrouter
.allow_delete
= false;
2613 struct zebra_vrf
*zvrf
;
2615 if (vrf_is_backend_netns())
2616 vty_out(vty
, "netns-based vrfs\n");
2618 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2619 if (!(zvrf
= vrf
->info
))
2621 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2624 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2625 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2626 vty_out(vty
, "inactive");
2627 else if (zvrf_ns_name(zvrf
))
2628 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2629 zvrf_ns_name(zvrf
));
2631 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2633 if (vrf_is_user_cfged(vrf
))
2634 vty_out(vty
, " (configured)");
2641 DEFPY (evpn_mh_mac_holdtime
,
2642 evpn_mh_mac_holdtime_cmd
,
2643 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2648 "Duration in seconds\n")
2650 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2654 DEFPY (evpn_mh_neigh_holdtime
,
2655 evpn_mh_neigh_holdtime_cmd
,
2656 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2660 "Neighbor entry hold time\n"
2661 "Duration in seconds\n")
2664 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2668 DEFPY (evpn_mh_startup_delay
,
2669 evpn_mh_startup_delay_cmd
,
2670 "[no] evpn mh startup-delay(0-3600)$duration",
2675 "duration in seconds\n")
2678 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2682 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2683 "[no$no] evpn mh redirect-off",
2687 "ES bond redirect for fast-failover off\n")
2691 redirect_off
= no
? false : true;
2693 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2696 DEFUN (default_vrf_vni_mapping
,
2697 default_vrf_vni_mapping_cmd
,
2698 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2699 "VNI corresponding to the DEFAULT VRF\n"
2701 "Prefix routes only \n")
2703 char xpath
[XPATH_MAXLEN
];
2704 struct zebra_vrf
*zvrf
= NULL
;
2707 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2714 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2716 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2718 snprintf(xpath
, sizeof(xpath
),
2719 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2721 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2724 snprintf(xpath
, sizeof(xpath
),
2725 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2727 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2730 return nb_cli_apply_changes(vty
, NULL
);
2733 DEFUN (no_default_vrf_vni_mapping
,
2734 no_default_vrf_vni_mapping_cmd
,
2735 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2737 "VNI corresponding to DEFAULT VRF\n"
2739 "Prefix routes only \n")
2741 char xpath
[XPATH_MAXLEN
];
2743 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2744 struct zebra_vrf
*zvrf
= NULL
;
2746 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2753 if (zvrf
->l3vni
!= vni
) {
2754 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2759 snprintf(xpath
, sizeof(xpath
),
2760 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2762 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2765 snprintf(xpath
, sizeof(xpath
),
2766 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2768 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2771 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2773 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2775 return nb_cli_apply_changes(vty
, NULL
);
2778 DEFUN (vrf_vni_mapping
,
2779 vrf_vni_mapping_cmd
,
2780 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2781 "VNI corresponding to tenant VRF\n"
2783 "prefix-routes-only\n")
2787 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2795 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2796 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2800 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2801 NB_OP_MODIFY
, "true");
2803 return nb_cli_apply_changes(vty
, NULL
);
2806 DEFUN (no_vrf_vni_mapping
,
2807 no_vrf_vni_mapping_cmd
,
2808 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2810 "VNI corresponding to tenant VRF\n"
2812 "prefix-routes-only\n")
2816 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2817 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2825 if (zvrf
->l3vni
!= vni
) {
2826 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2831 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2835 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2836 NB_OP_DESTROY
, "true");
2838 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2840 return nb_cli_apply_changes(vty
, NULL
);
2844 DEFPY (show_vrf_vni
,
2846 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2848 VRF_FULL_CMD_HELP_STR
2853 struct zebra_vrf
*zvrf
;
2854 json_object
*json
= NULL
;
2855 json_object
*json_vrfs
= NULL
;
2856 bool uj
= use_json(argc
, argv
);
2857 bool use_vrf
= false;
2860 json
= json_object_new_object();
2862 /* show vrf vni used to display across all vrfs
2863 * This is enhanced to support only for specific
2866 if (vrf_all
|| !vrf_name
) {
2867 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2878 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2879 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2882 json_vrfs
= json_object_new_array();
2885 vty_json(vty
, json
);
2887 vty_out(vty
, "%% VRF does not exist\n");
2894 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2899 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2901 } else if (vrf_name
) {
2902 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2905 vty_json(vty
, json
);
2908 "%% VRF '%s' specified does not exist\n",
2915 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2916 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2919 json_vrfs
= json_object_new_array();
2921 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2925 json_object_object_add(json
, "vrfs", json_vrfs
);
2926 vty_json(vty
, json
);
2932 DEFUN (show_evpn_global
,
2933 show_evpn_global_cmd
,
2939 bool uj
= use_json(argc
, argv
);
2941 zebra_vxlan_print_evpn(vty
, uj
);
2945 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2946 SHOW_STR IP_STR
"neighbors\n")
2949 zebra_neigh_show(vty
);
2954 DEFPY(show_evpn_l2_nh
,
2955 show_evpn_l2_nh_cmd
,
2956 "show evpn l2-nh [json$json]",
2964 zebra_evpn_l2_nh_show(vty
, uj
);
2971 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2974 "Ethernet Segment\n"
2976 "Detailed information\n"
2983 if (!str_to_esi(esi_str
, &esi
)) {
2984 vty_out(vty
, "%% Malformed ESI\n");
2987 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2990 zebra_evpn_es_show_detail(vty
, uj
);
2992 zebra_evpn_es_show(vty
, uj
);
2998 DEFPY(show_evpn_es_evi
,
2999 show_evpn_es_evi_cmd
,
3000 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3003 "Ethernet Segment per EVI\n"
3004 "VxLAN Network Identifier\n"
3006 "Detailed information\n"
3013 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3015 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3020 DEFPY(show_evpn_access_vlan
,
3021 show_evpn_access_vlan_cmd
,
3022 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3027 "Detailed information\n"
3033 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3036 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3038 zebra_evpn_acc_vl_show(vty
, uj
);
3044 DEFUN (show_evpn_vni
,
3046 "show evpn vni [json]",
3049 "VxLAN Network Identifier\n"
3052 struct zebra_vrf
*zvrf
;
3053 bool uj
= use_json(argc
, argv
);
3055 zvrf
= zebra_vrf_get_evpn();
3056 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3060 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3061 "show evpn vni detail [json]",
3064 "VxLAN Network Identifier\n"
3065 "Detailed Information On Each VNI\n"
3068 struct zebra_vrf
*zvrf
;
3069 bool uj
= use_json(argc
, argv
);
3071 zvrf
= zebra_vrf_get_evpn();
3072 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3076 DEFUN (show_evpn_vni_vni
,
3077 show_evpn_vni_vni_cmd
,
3078 "show evpn vni " CMD_VNI_RANGE
"[json]",
3081 "VxLAN Network Identifier\n"
3085 struct zebra_vrf
*zvrf
;
3087 bool uj
= use_json(argc
, argv
);
3089 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3090 zvrf
= zebra_vrf_get_evpn();
3091 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3095 DEFUN (show_evpn_rmac_vni_mac
,
3096 show_evpn_rmac_vni_mac_cmd
,
3097 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3104 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3109 bool uj
= use_json(argc
, argv
);
3111 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3112 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3113 vty_out(vty
, "%% Malformed MAC address\n");
3116 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3120 DEFUN (show_evpn_rmac_vni
,
3121 show_evpn_rmac_vni_cmd
,
3122 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3131 bool uj
= use_json(argc
, argv
);
3133 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3134 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3139 DEFUN (show_evpn_rmac_vni_all
,
3140 show_evpn_rmac_vni_all_cmd
,
3141 "show evpn rmac vni all [json]",
3149 bool uj
= use_json(argc
, argv
);
3151 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3156 DEFUN (show_evpn_nh_vni_ip
,
3157 show_evpn_nh_vni_ip_cmd
,
3158 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3165 "Host address (ipv4 or ipv6)\n"
3170 bool uj
= use_json(argc
, argv
);
3172 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3173 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3175 vty_out(vty
, "%% Malformed Neighbor address\n");
3178 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3183 DEFUN (show_evpn_nh_vni
,
3184 show_evpn_nh_vni_cmd
,
3185 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3194 bool uj
= use_json(argc
, argv
);
3196 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3197 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3202 DEFUN (show_evpn_nh_vni_all
,
3203 show_evpn_nh_vni_all_cmd
,
3204 "show evpn next-hops vni all [json]",
3212 bool uj
= use_json(argc
, argv
);
3214 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3219 DEFUN (show_evpn_mac_vni
,
3220 show_evpn_mac_vni_cmd
,
3221 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3225 "VxLAN Network Identifier\n"
3229 struct zebra_vrf
*zvrf
;
3231 bool uj
= use_json(argc
, argv
);
3233 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3234 zvrf
= zebra_vrf_get_evpn();
3235 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3239 DEFPY (show_evpn_mac_vni_detail
,
3240 show_evpn_mac_vni_detail_cmd
,
3241 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3245 "VXLAN Network Identifier\n"
3247 "Detailed Information On Each VNI MAC\n"
3250 struct zebra_vrf
*zvrf
;
3251 bool uj
= use_json(argc
, argv
);
3253 zvrf
= zebra_vrf_get_evpn();
3254 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3258 DEFUN (show_evpn_mac_vni_all
,
3259 show_evpn_mac_vni_all_cmd
,
3260 "show evpn mac vni all [json]",
3264 "VxLAN Network Identifier\n"
3268 struct zebra_vrf
*zvrf
;
3269 bool uj
= use_json(argc
, argv
);
3271 zvrf
= zebra_vrf_get_evpn();
3272 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3276 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3277 "show evpn mac vni all detail [json]",
3281 "VxLAN Network Identifier\n"
3283 "Detailed Information On Each VNI MAC\n"
3286 struct zebra_vrf
*zvrf
;
3287 bool uj
= use_json(argc
, argv
);
3289 zvrf
= zebra_vrf_get_evpn();
3290 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3294 DEFUN (show_evpn_mac_vni_all_vtep
,
3295 show_evpn_mac_vni_all_vtep_cmd
,
3296 "show evpn mac vni all vtep A.B.C.D [json]",
3300 "VxLAN Network Identifier\n"
3303 "Remote VTEP IP address\n"
3306 struct zebra_vrf
*zvrf
;
3307 struct in_addr vtep_ip
;
3308 bool uj
= use_json(argc
, argv
);
3310 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3312 vty_out(vty
, "%% Malformed VTEP IP address\n");
3315 zvrf
= zebra_vrf_get_evpn();
3316 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3322 DEFUN (show_evpn_mac_vni_mac
,
3323 show_evpn_mac_vni_mac_cmd
,
3324 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3328 "VxLAN Network Identifier\n"
3331 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3335 struct zebra_vrf
*zvrf
;
3338 bool uj
= use_json(argc
, argv
);
3340 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3341 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3342 vty_out(vty
, "%% Malformed MAC address\n");
3345 zvrf
= zebra_vrf_get_evpn();
3346 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3350 DEFUN (show_evpn_mac_vni_vtep
,
3351 show_evpn_mac_vni_vtep_cmd
,
3352 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3356 "VxLAN Network Identifier\n"
3359 "Remote VTEP IP address\n"
3362 struct zebra_vrf
*zvrf
;
3364 struct in_addr vtep_ip
;
3365 bool uj
= use_json(argc
, argv
);
3367 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3368 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3370 vty_out(vty
, "%% Malformed VTEP IP address\n");
3374 zvrf
= zebra_vrf_get_evpn();
3375 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3379 DEFPY (show_evpn_mac_vni_all_dad
,
3380 show_evpn_mac_vni_all_dad_cmd
,
3381 "show evpn mac vni all duplicate [json]",
3385 "VxLAN Network Identifier\n"
3387 "Duplicate address list\n"
3390 struct zebra_vrf
*zvrf
;
3391 bool uj
= use_json(argc
, argv
);
3393 zvrf
= zebra_vrf_get_evpn();
3394 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3399 DEFPY (show_evpn_mac_vni_dad
,
3400 show_evpn_mac_vni_dad_cmd
,
3401 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3405 "VxLAN Network Identifier\n"
3407 "Duplicate address list\n"
3410 struct zebra_vrf
*zvrf
;
3411 bool uj
= use_json(argc
, argv
);
3413 zvrf
= zebra_vrf_get_evpn();
3415 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3420 DEFPY (show_evpn_neigh_vni_dad
,
3421 show_evpn_neigh_vni_dad_cmd
,
3422 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3425 "ARP and ND cache\n"
3426 "VxLAN Network Identifier\n"
3428 "Duplicate address list\n"
3431 struct zebra_vrf
*zvrf
;
3432 bool uj
= use_json(argc
, argv
);
3434 zvrf
= zebra_vrf_get_evpn();
3435 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3439 DEFPY (show_evpn_neigh_vni_all_dad
,
3440 show_evpn_neigh_vni_all_dad_cmd
,
3441 "show evpn arp-cache vni all duplicate [json]",
3444 "ARP and ND cache\n"
3445 "VxLAN Network Identifier\n"
3447 "Duplicate address list\n"
3450 struct zebra_vrf
*zvrf
;
3451 bool uj
= use_json(argc
, argv
);
3453 zvrf
= zebra_vrf_get_evpn();
3454 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3459 DEFUN (show_evpn_neigh_vni
,
3460 show_evpn_neigh_vni_cmd
,
3461 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3464 "ARP and ND cache\n"
3465 "VxLAN Network Identifier\n"
3469 struct zebra_vrf
*zvrf
;
3471 bool uj
= use_json(argc
, argv
);
3473 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3474 zvrf
= zebra_vrf_get_evpn();
3475 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3479 DEFUN (show_evpn_neigh_vni_all
,
3480 show_evpn_neigh_vni_all_cmd
,
3481 "show evpn arp-cache vni all [json]",
3484 "ARP and ND cache\n"
3485 "VxLAN Network Identifier\n"
3489 struct zebra_vrf
*zvrf
;
3490 bool uj
= use_json(argc
, argv
);
3492 zvrf
= zebra_vrf_get_evpn();
3493 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3497 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3498 "show evpn arp-cache vni all detail [json]",
3501 "ARP and ND cache\n"
3502 "VxLAN Network Identifier\n"
3504 "Neighbor details for all vnis in detail\n" JSON_STR
)
3506 struct zebra_vrf
*zvrf
;
3507 bool uj
= use_json(argc
, argv
);
3509 zvrf
= zebra_vrf_get_evpn();
3510 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3514 DEFUN (show_evpn_neigh_vni_neigh
,
3515 show_evpn_neigh_vni_neigh_cmd
,
3516 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3519 "ARP and ND cache\n"
3520 "VxLAN Network Identifier\n"
3523 "Neighbor address (IPv4 or IPv6 address)\n"
3526 struct zebra_vrf
*zvrf
;
3529 bool uj
= use_json(argc
, argv
);
3531 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3532 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3534 vty_out(vty
, "%% Malformed Neighbor address\n");
3537 zvrf
= zebra_vrf_get_evpn();
3538 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3542 DEFUN (show_evpn_neigh_vni_vtep
,
3543 show_evpn_neigh_vni_vtep_cmd
,
3544 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3547 "ARP and ND cache\n"
3548 "VxLAN Network Identifier\n"
3551 "Remote VTEP IP address\n"
3554 struct zebra_vrf
*zvrf
;
3556 struct in_addr vtep_ip
;
3557 bool uj
= use_json(argc
, argv
);
3559 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3560 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3562 vty_out(vty
, "%% Malformed VTEP IP address\n");
3566 zvrf
= zebra_vrf_get_evpn();
3567 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3571 /* policy routing contexts */
3572 DEFUN (show_pbr_ipset
,
3574 "show pbr ipset [WORD]",
3576 "Policy-Based Routing\n"
3577 "IPset Context information\n"
3578 "IPset Name information\n")
3582 found
= argv_find(argv
, argc
, "WORD", &idx
);
3584 zebra_pbr_show_ipset_list(vty
, NULL
);
3586 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3590 /* policy routing contexts */
3591 DEFUN (show_pbr_iptable
,
3592 show_pbr_iptable_cmd
,
3593 "show pbr iptable [WORD]",
3595 "Policy-Based Routing\n"
3596 "IPtable Context information\n"
3597 "IPtable Name information\n")
3602 found
= argv_find(argv
, argc
, "WORD", &idx
);
3604 zebra_pbr_show_iptable(vty
, NULL
);
3606 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3610 /* policy routing contexts */
3611 DEFPY (show_pbr_rule
,
3615 "Policy-Based Routing\n"
3618 zebra_pbr_show_rule(vty
);
3622 DEFPY (pbr_nexthop_resolve
,
3623 pbr_nexthop_resolve_cmd
,
3624 "[no$no] pbr nexthop-resolve",
3626 "Policy Based Routing\n"
3627 "Resolve nexthop for dataplane programming\n")
3629 zebra_pbr_expand_action_update(!no
);
3633 DEFPY (clear_evpn_dup_addr
,
3634 clear_evpn_dup_addr_cmd
,
3635 "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>]>",
3638 "Duplicate address \n"
3639 "VxLAN Network Identifier\n"
3643 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3648 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3649 int ret
= CMD_SUCCESS
;
3651 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3652 *yang_dup_mac
= NULL
;
3657 yang_dup
= yang_data_new(
3658 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3661 yang_dup
= yang_data_new_uint32(
3662 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3664 if (!is_zero_mac(&mac
->eth_addr
)) {
3665 yang_dup_mac
= yang_data_new_mac(
3666 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3669 listnode_add(input
, yang_dup_mac
);
3671 if (sockunion_family(ip
) == AF_INET
) {
3672 host_ip
.ipa_type
= IPADDR_V4
;
3673 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3675 host_ip
.ipa_type
= IPADDR_V6
;
3676 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3677 sizeof(struct in6_addr
));
3680 yang_dup_ip
= yang_data_new_ip(
3681 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3685 listnode_add(input
, yang_dup_ip
);
3690 listnode_add(input
, yang_dup
);
3691 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3695 list_delete(&input
);
3700 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3701 evpn_accept_bgp_seq_cmd
,
3702 "evpn accept-bgp-seq",
3704 "Accept all sequence numbers from BGP\n")
3706 zebra_vxlan_set_accept_bgp_seq(true);
3710 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3711 no_evpn_accept_bgp_seq_cmd
,
3712 "no evpn accept-bgp-seq",
3715 "Accept all sequence numbers from BGP\n")
3717 zebra_vxlan_set_accept_bgp_seq(false);
3721 /* Static ip route configuration write function. */
3722 static int zebra_ip_config(struct vty
*vty
)
3726 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3731 DEFUN (ip_zebra_import_table_distance
,
3732 ip_zebra_import_table_distance_cmd
,
3733 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3735 "import routes from non-main kernel table\n"
3736 "kernel routing table id\n"
3737 "Distance for imported routes\n"
3738 "Default distance value\n"
3739 "route-map for filtering\n"
3742 uint32_t table_id
= 0;
3744 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3745 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3747 strmatch(argv
[argc
- 2]->text
, "route-map")
3748 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3752 if (argc
== 7 || (argc
== 5 && !rmap
))
3753 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3755 if (!is_zebra_valid_kernel_table(table_id
)) {
3757 "Invalid routing table ID, %d. Must be in range 1-252\n",
3760 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3764 if (is_zebra_main_routing_table(table_id
)) {
3766 "Invalid routing table ID, %d. Must be non-default table\n",
3769 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3773 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3776 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3781 DEFUN_HIDDEN (zebra_packet_process
,
3782 zebra_packet_process_cmd
,
3783 "zebra zapi-packets (1-10000)",
3786 "Number of packets to process before relinquishing thread\n")
3788 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3790 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3791 memory_order_relaxed
);
3796 DEFUN_HIDDEN (no_zebra_packet_process
,
3797 no_zebra_packet_process_cmd
,
3798 "no zebra zapi-packets [(1-10000)]",
3802 "Number of packets to process before relinquishing thread\n")
3804 atomic_store_explicit(&zrouter
.packets_to_process
,
3805 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3806 memory_order_relaxed
);
3811 DEFUN_HIDDEN (zebra_workqueue_timer
,
3812 zebra_workqueue_timer_cmd
,
3813 "zebra work-queue (0-10000)",
3816 "Time in milliseconds\n")
3818 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3819 zrouter
.ribq
->spec
.hold
= timer
;
3824 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3825 no_zebra_workqueue_timer_cmd
,
3826 "no zebra work-queue [(0-10000)]",
3830 "Time in milliseconds\n")
3832 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3837 DEFUN (no_ip_zebra_import_table
,
3838 no_ip_zebra_import_table_cmd
,
3839 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3842 "import routes from non-main kernel table\n"
3843 "kernel routing table id\n"
3844 "Distance for imported routes\n"
3845 "Default distance value\n"
3846 "route-map for filtering\n"
3849 uint32_t table_id
= 0;
3850 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3852 if (!is_zebra_valid_kernel_table(table_id
)) {
3854 "Invalid routing table ID. Must be in range 1-252\n");
3858 if (is_zebra_main_routing_table(table_id
)) {
3860 "Invalid routing table ID, %d. Must be non-default table\n",
3865 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3868 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3871 DEFPY (zebra_nexthop_group_keep
,
3872 zebra_nexthop_group_keep_cmd
,
3873 "[no] zebra nexthop-group keep (1-3600)",
3877 "How long to keep\n"
3878 "Time in seconds from 1-3600\n")
3881 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3883 zrouter
.nhg_keep
= keep
;
3888 static int config_write_protocol(struct vty
*vty
)
3890 if (zrouter
.allow_delete
)
3891 vty_out(vty
, "allow-external-route-update\n");
3893 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3894 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3896 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3897 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3899 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3900 vty_out(vty
, "zebra zapi-packets %u\n",
3901 zrouter
.packets_to_process
);
3903 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3905 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3906 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3907 ipv4_multicast_mode
== MCAST_URIB_ONLY
3909 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3911 : ipv4_multicast_mode
3912 == MCAST_MIX_MRIB_FIRST
3914 : ipv4_multicast_mode
3915 == MCAST_MIX_DISTANCE
3919 /* Include dataplane info */
3920 dplane_config_write_helper(vty
);
3922 zebra_evpn_mh_config_write(vty
);
3924 zebra_pbr_config_write(vty
);
3926 if (!zebra_vxlan_get_accept_bgp_seq())
3927 vty_out(vty
, "no evpn accept-bgp-seq\n");
3929 /* Include nexthop-group config */
3930 if (!zebra_nhg_kernel_nexthops_enabled())
3931 vty_out(vty
, "no zebra nexthop kernel enable\n");
3933 if (zebra_nhg_proto_nexthops_only())
3934 vty_out(vty
, "zebra nexthop proto only\n");
3936 if (!zebra_nhg_recursive_use_backups())
3937 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3939 if (rnh_get_hide_backups())
3940 vty_out(vty
, "ip nht hide-backup-events\n");
3943 /* Include netlink info */
3944 netlink_config_write_helper(vty
);
3945 #endif /* HAVE_NETLINK */
3957 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3960 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3961 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3962 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3963 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3964 ttable_add_row(table
, "v6 Forwarding|%s",
3965 ipforward_ipv6() ? "On" : "Off");
3966 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3967 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3968 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3972 if (!vrf_is_backend_netns())
3973 ttable_add_row(table
, "VRF|l3mdev Available");
3975 ttable_add_row(table
, "VRF|Namespaces");
3977 ttable_add_row(table
, "VRF|Not Available");
3980 ttable_add_row(table
, "ASIC offload|%s",
3981 zrouter
.asic_offloaded
? "Used" : "Unavailable");
3984 * Do not display this unless someone is actually using it
3986 * Why this distinction? I think this is effectively dead code
3987 * and should not be exposed. Maybe someone proves me wrong.
3989 if (zrouter
.asic_notification_nexthop_control
)
3990 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
3992 ttable_add_row(table
, "RA|%s",
3993 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
3994 ttable_add_row(table
, "RFC 5549|%s",
3995 rtadv_get_interfaces_configured_from_bgp()
3997 : "BGP is not using");
3999 ttable_add_row(table
, "Kernel NHG|%s",
4000 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4002 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4003 zrouter
.allow_delete
? "Yes" : "No");
4004 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4005 zrouter
.all_linkdownv4
? "On" : "Off");
4006 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4007 zrouter
.default_linkdownv4
? "On" : "Off");
4008 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4009 zrouter
.all_linkdownv6
? "On" : "Off");
4010 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4011 zrouter
.default_linkdownv6
? "On" : "Off");
4013 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4014 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4015 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4016 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4017 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4018 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4019 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4020 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4022 out
= ttable_dump(table
, "\n");
4023 vty_out(vty
, "%s\n", out
);
4024 XFREE(MTYPE_TMP
, out
);
4028 " Route Route Neighbor LSP LSP\n");
4030 "VRF Installs Removals Updates Installs Removals\n");
4032 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4033 struct zebra_vrf
*zvrf
= vrf
->info
;
4035 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4036 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4037 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4038 zvrf
->lsp_removals
);
4044 DEFUN (ip_forwarding
,
4048 "Turn on IP forwarding\n")
4054 ret
= ipforward_on();
4057 vty_out(vty
, "Can't turn on IP forwarding\n");
4058 return CMD_WARNING_CONFIG_FAILED
;
4064 DEFUN (no_ip_forwarding
,
4065 no_ip_forwarding_cmd
,
4069 "Turn off IP forwarding\n")
4075 ret
= ipforward_off();
4078 vty_out(vty
, "Can't turn off IP forwarding\n");
4079 return CMD_WARNING_CONFIG_FAILED
;
4085 /* Only display ip forwarding is enabled or not. */
4086 DEFUN (show_ip_forwarding
,
4087 show_ip_forwarding_cmd
,
4088 "show ip forwarding",
4091 "IP forwarding status\n")
4098 vty_out(vty
, "IP forwarding is off\n");
4100 vty_out(vty
, "IP forwarding is on\n");
4104 /* Only display ipv6 forwarding is enabled or not. */
4105 DEFUN (show_ipv6_forwarding
,
4106 show_ipv6_forwarding_cmd
,
4107 "show ipv6 forwarding",
4109 "IPv6 information\n"
4110 "Forwarding status\n")
4114 ret
= ipforward_ipv6();
4118 vty_out(vty
, "ipv6 forwarding is unknown\n");
4121 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4124 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4127 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4133 DEFUN (ipv6_forwarding
,
4134 ipv6_forwarding_cmd
,
4137 "Turn on IPv6 forwarding\n")
4141 ret
= ipforward_ipv6();
4143 ret
= ipforward_ipv6_on();
4146 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4147 return CMD_WARNING_CONFIG_FAILED
;
4153 DEFUN (no_ipv6_forwarding
,
4154 no_ipv6_forwarding_cmd
,
4155 "no ipv6 forwarding",
4158 "Turn off IPv6 forwarding\n")
4162 ret
= ipforward_ipv6();
4164 ret
= ipforward_ipv6_off();
4167 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4168 return CMD_WARNING_CONFIG_FAILED
;
4174 /* Display dataplane info */
4175 DEFUN (show_dataplane
,
4177 "show zebra dplane [detailed]",
4180 "Zebra dataplane information\n"
4181 "Detailed output\n")
4184 bool detailed
= false;
4186 if (argv_find(argv
, argc
, "detailed", &idx
))
4189 return dplane_show_helper(vty
, detailed
);
4192 /* Display dataplane providers info */
4193 DEFUN (show_dataplane_providers
,
4194 show_dataplane_providers_cmd
,
4195 "show zebra dplane providers [detailed]",
4198 "Zebra dataplane information\n"
4199 "Zebra dataplane provider information\n"
4200 "Detailed output\n")
4203 bool detailed
= false;
4205 if (argv_find(argv
, argc
, "detailed", &idx
))
4208 return dplane_show_provs_helper(vty
, detailed
);
4211 /* Configure dataplane incoming queue limit */
4212 DEFUN (zebra_dplane_queue_limit
,
4213 zebra_dplane_queue_limit_cmd
,
4214 "zebra dplane limit (0-10000)",
4217 "Limit incoming queued updates\n"
4218 "Number of queued updates\n")
4222 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4224 dplane_set_in_queue_limit(limit
, true);
4229 /* Reset dataplane queue limit to default value */
4230 DEFUN (no_zebra_dplane_queue_limit
,
4231 no_zebra_dplane_queue_limit_cmd
,
4232 "no zebra dplane limit [(0-10000)]",
4236 "Limit incoming queued updates\n"
4237 "Number of queued updates\n")
4239 dplane_set_in_queue_limit(0, false);
4244 DEFUN (zebra_show_routing_tables_summary
,
4245 zebra_show_routing_tables_summary_cmd
,
4246 "show zebra router table summary",
4249 "The Zebra Router Information\n"
4250 "Table Information about this Zebra Router\n"
4251 "Summary Information\n")
4253 zebra_router_show_table_summary(vty
);
4258 /* Table configuration write function. */
4259 static int config_write_table(struct vty
*vty
)
4264 /* IPForwarding configuration write function. */
4265 static int config_write_forwarding(struct vty
*vty
)
4268 vty_out(vty
, "no ip forwarding\n");
4269 if (!ipforward_ipv6())
4270 vty_out(vty
, "no ipv6 forwarding\n");
4271 vty_out(vty
, "!\n");
4275 DEFUN_HIDDEN (show_frr
,
4281 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4282 vty_out(vty
, ".............................7777:..............................................\n");
4283 vty_out(vty
, ".............................777777,............................................\n");
4284 vty_out(vty
, "... .........................77777777,..........................................\n");
4285 vty_out(vty
, "............................=7777777777:........................................\n");
4286 vty_out(vty
, "........................:7777777777777777,......................................\n");
4287 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4288 vty_out(vty
, "...................I7777777777+.................................................\n");
4289 vty_out(vty
, "................,777777777?............ .......................................\n");
4290 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4291 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4292 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4293 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4294 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4295 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4296 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4297 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4298 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4299 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4300 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4301 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4302 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4303 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4304 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4305 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4306 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4307 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4308 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4309 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4310 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4311 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4312 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4313 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4314 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4315 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4316 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4317 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4318 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4319 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4320 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4321 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4322 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4323 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4324 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4325 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4326 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4327 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4328 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4329 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4330 vty_out(vty
, "................................~77777777...............=777777.................\n");
4331 vty_out(vty
, ".....................................:=?I................~777777................\n");
4332 vty_out(vty
, "..........................................................:777777,..............\n");
4333 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4339 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4340 zebra_kernel_netlink_batch_tx_buf_cmd
,
4341 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4343 "Zebra kernel interface\n"
4344 "Set Netlink parameters\n"
4345 "Set batch buffer size and send threshold\n"
4346 "Size of the buffer\n"
4349 uint32_t bufsize
= 0, threshold
= 0;
4351 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4352 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4354 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4359 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4360 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4361 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4363 "Zebra kernel interface\n"
4364 "Set Netlink parameters\n"
4365 "Set batch buffer size and send threshold\n"
4366 "Size of the buffer\n"
4369 netlink_set_batch_buffer_size(0, 0, false);
4374 DEFPY (zebra_protodown_bit
,
4375 zebra_protodown_bit_cmd
,
4376 "zebra protodown reason-bit (0-31)$bit",
4378 "Protodown Configuration\n"
4379 "Reason Bit used in the kernel for application\n"
4380 "Reason Bit range\n")
4382 if_netlink_set_frr_protodown_r_bit(bit
);
4386 DEFPY (no_zebra_protodown_bit
,
4387 no_zebra_protodown_bit_cmd
,
4388 "no zebra protodown reason-bit [(0-31)$bit]",
4391 "Protodown Configuration\n"
4392 "Reason Bit used in the kernel for setting protodown\n"
4393 "Reason Bit Range\n")
4395 if_netlink_unset_frr_protodown_r_bit();
4399 #endif /* HAVE_NETLINK */
4401 DEFUN(ip_table_range
, ip_table_range_cmd
,
4402 "[no] ip table range (1-4294967295) (1-4294967295)",
4404 "table configuration\n"
4405 "Configure table range\n"
4406 "Start Routing Table\n"
4407 "End Routing Table\n")
4409 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4414 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4416 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4420 if (strmatch(argv
[0]->text
, "no"))
4421 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4423 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4426 #ifdef HAVE_SCRIPTING
4428 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4429 "zebra on-rib-process script SCRIPT",
4431 "on_rib_process_dplane_results hook call\n"
4433 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4436 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4439 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4440 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4442 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4443 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4448 #endif /* HAVE_SCRIPTING */
4450 /* IP node for static routes. */
4451 static int zebra_ip_config(struct vty
*vty
);
4452 static struct cmd_node ip_node
= {
4453 .name
= "static ip",
4456 .config_write
= zebra_ip_config
,
4458 static int config_write_protocol(struct vty
*vty
);
4459 static struct cmd_node protocol_node
= {
4461 .node
= PROTOCOL_NODE
,
4463 .config_write
= config_write_protocol
,
4465 /* table node for routing tables. */
4466 static int config_write_table(struct vty
*vty
);
4467 static struct cmd_node table_node
= {
4471 .config_write
= config_write_table
,
4473 static int config_write_forwarding(struct vty
*vty
);
4474 static struct cmd_node forwarding_node
= {
4475 .name
= "forwarding",
4476 .node
= FORWARDING_NODE
,
4478 .config_write
= config_write_forwarding
,
4482 void zebra_vty_init(void)
4484 /* Install configuration write function. */
4485 install_node(&table_node
);
4486 install_node(&forwarding_node
);
4488 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4489 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4490 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4491 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4493 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4494 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4495 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4498 zebra_route_map_init();
4500 affinity_map_init();
4502 install_node(&ip_node
);
4503 install_node(&protocol_node
);
4505 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4506 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4508 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4509 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4511 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4512 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4513 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4514 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4515 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4516 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4517 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4518 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4519 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4520 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4522 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4523 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4525 install_element(VIEW_NODE
, &show_vrf_cmd
);
4526 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4527 install_element(VIEW_NODE
, &show_route_cmd
);
4528 install_element(VIEW_NODE
, &show_ro_cmd
);
4529 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4530 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4531 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4533 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4534 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4536 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4537 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4538 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4539 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4540 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4541 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4542 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4543 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4544 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4546 install_element(VIEW_NODE
, &show_frr_cmd
);
4547 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4548 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4549 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4550 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4551 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4552 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4553 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4554 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4555 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4556 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4557 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4558 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4573 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4574 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4575 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4576 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4577 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4578 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4579 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4581 install_element(VIEW_NODE
, &show_neigh_cmd
);
4583 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4584 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4585 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4586 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4587 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4589 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4590 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4591 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4592 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4593 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4594 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4595 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4596 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4598 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4599 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4600 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4601 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4603 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4604 install_element(VRF_NODE
, &ip_table_range_cmd
);
4607 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4608 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4609 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4610 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4611 #endif /* HAVE_NETLINK */
4613 #ifdef HAVE_SCRIPTING
4614 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4615 #endif /* HAVE_SCRIPTING */
4617 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);