2 * Copyright (C) 2002 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "srcdest_table.h"
36 #include "termtable.h"
38 #include "zebra/zebra_router.h"
39 #include "zebra/zserv.h"
40 #include "zebra/zebra_vrf.h"
41 #include "zebra/zebra_mpls.h"
42 #include "zebra/zebra_rnh.h"
43 #include "zebra/redistribute.h"
44 #include "zebra/zebra_routemap.h"
46 #include "lib/route_opaque.h"
47 #include "zebra/zebra_vxlan.h"
48 #include "zebra/zebra_evpn_mh.h"
49 #include "zebra/zebra_vty_clippy.c"
50 #include "zebra/zserv.h"
51 #include "zebra/router-id.h"
52 #include "zebra/ipforward.h"
53 #include "zebra/zebra_vxlan_private.h"
54 #include "zebra/zebra_pbr.h"
55 #include "zebra/zebra_nhg.h"
56 #include "zebra/zebra_evpn_mh.h"
57 #include "zebra/interface.h"
58 #include "northbound_cli.h"
59 #include "zebra/zebra_nb.h"
60 #include "zebra/kernel_netlink.h"
61 #include "zebra/if_netlink.h"
62 #include "zebra/table_manager.h"
63 #include "zebra/zebra_script.h"
64 #include "zebra/rtadv.h"
65 #include "zebra/zebra_neigh.h"
67 /* context to manage dumps in multiple tables or vrfs */
68 struct route_show_ctx
{
69 bool multi
; /* dump multiple tables or vrf */
70 bool header_done
; /* common header already displayed */
73 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
74 safi_t safi
, bool use_fib
, bool use_json
,
76 const struct prefix
*longer_prefix_p
,
77 bool supernets_only
, int type
,
78 unsigned short ospf_instance_id
, uint32_t tableid
,
79 bool show_ng
, struct route_show_ctx
*ctx
);
80 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
81 int mcast
, bool use_fib
, bool show_ng
);
82 static void vty_show_ip_route_summary(struct vty
*vty
,
83 struct route_table
*table
, bool use_json
);
84 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
85 struct route_table
*table
,
87 /* Helper api to format a nexthop in the 'detailed' output path. */
88 static void show_nexthop_detail_helper(struct vty
*vty
,
89 const struct route_entry
*re
,
90 const struct nexthop
*nexthop
,
93 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
);
94 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
95 struct route_entry
*re
, unsigned int num
);
97 DEFUN (ip_multicast_mode
,
98 ip_multicast_mode_cmd
,
99 "ip multicast rpf-lookup-mode <urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>",
101 "Multicast options\n"
102 "RPF lookup behavior\n"
103 "Lookup in unicast RIB only\n"
104 "Lookup in multicast RIB only\n"
105 "Try multicast RIB first, fall back to unicast RIB\n"
106 "Lookup both, use entry with lower distance\n"
107 "Lookup both, use entry with longer prefix\n")
109 char *mode
= argv
[3]->text
;
111 if (strmatch(mode
, "urib-only"))
112 multicast_mode_ipv4_set(MCAST_URIB_ONLY
);
113 else if (strmatch(mode
, "mrib-only"))
114 multicast_mode_ipv4_set(MCAST_MRIB_ONLY
);
115 else if (strmatch(mode
, "mrib-then-urib"))
116 multicast_mode_ipv4_set(MCAST_MIX_MRIB_FIRST
);
117 else if (strmatch(mode
, "lower-distance"))
118 multicast_mode_ipv4_set(MCAST_MIX_DISTANCE
);
119 else if (strmatch(mode
, "longer-prefix"))
120 multicast_mode_ipv4_set(MCAST_MIX_PFXLEN
);
122 vty_out(vty
, "Invalid mode specified\n");
123 return CMD_WARNING_CONFIG_FAILED
;
129 DEFUN (no_ip_multicast_mode
,
130 no_ip_multicast_mode_cmd
,
131 "no ip multicast rpf-lookup-mode [<urib-only|mrib-only|mrib-then-urib|lower-distance|longer-prefix>]",
134 "Multicast options\n"
135 "RPF lookup behavior\n"
136 "Lookup in unicast RIB only\n"
137 "Lookup in multicast RIB only\n"
138 "Try multicast RIB first, fall back to unicast RIB\n"
139 "Lookup both, use entry with lower distance\n"
140 "Lookup both, use entry with longer prefix\n")
142 multicast_mode_ipv4_set(MCAST_NO_CONFIG
);
149 "show ip rpf [json]",
152 "Display RPF information for multicast source\n"
155 bool uj
= use_json(argc
, argv
);
156 struct route_show_ctx ctx
= {
160 return do_show_ip_route(vty
, VRF_DEFAULT_NAME
, AFI_IP
, SAFI_MULTICAST
,
161 false, uj
, 0, NULL
, false, 0, 0, 0, false,
165 DEFUN (show_ip_rpf_addr
,
166 show_ip_rpf_addr_cmd
,
167 "show ip rpf A.B.C.D",
170 "Display RPF information for multicast source\n"
171 "IP multicast source address (e.g. 10.0.0.0)\n")
175 struct route_node
*rn
;
176 struct route_entry
*re
;
179 ret
= inet_aton(argv
[idx_ipv4
]->arg
, &addr
);
181 vty_out(vty
, "%% Malformed address\n");
185 re
= rib_match_ipv4_multicast(VRF_DEFAULT
, addr
, &rn
);
188 vty_show_ip_route_detail(vty
, rn
, 1, false, false);
190 vty_out(vty
, "%% No match for RPF lookup\n");
195 static char re_status_output_char(const struct route_entry
*re
,
196 const struct nexthop
*nhop
,
199 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
203 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_DUPLICATE
) &&
204 !CHECK_FLAG(nhop
->flags
, NEXTHOP_FLAG_RECURSIVE
)) {
205 /* More-specific test for 'fib' output */
207 star_p
= !!CHECK_FLAG(nhop
->flags
,
213 if (zrouter
.asic_offloaded
&&
214 CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
217 if (zrouter
.asic_offloaded
218 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
221 if (zrouter
.asic_offloaded
222 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
225 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OUTOFSYNC
))
234 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
)) {
235 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
241 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
248 * Show backup nexthop info, in the 'detailed' output path
250 static void show_nh_backup_helper(struct vty
*vty
,
251 const struct route_entry
*re
,
252 const struct nexthop
*nexthop
)
254 const struct nexthop
*start
, *backup
, *temp
;
257 /* Double-check that there _is_ a backup */
258 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
) ||
259 re
->nhe
->backup_info
== NULL
|| re
->nhe
->backup_info
->nhe
== NULL
||
260 re
->nhe
->backup_info
->nhe
->nhg
.nexthop
== NULL
)
263 /* Locate the backup nexthop(s) */
264 start
= re
->nhe
->backup_info
->nhe
->nhg
.nexthop
;
265 for (i
= 0; i
< nexthop
->backup_num
; i
++) {
266 /* Format the backup(s) (indented) */
268 for (idx
= 0; idx
< nexthop
->backup_idx
[i
]; idx
++) {
269 backup
= backup
->next
;
274 /* It's possible for backups to be recursive too,
275 * so walk the recursive resolution list if present.
280 show_nexthop_detail_helper(vty
, re
, backup
,
284 if (backup
->resolved
&& temp
== backup
)
285 backup
= backup
->resolved
;
287 backup
= nexthop_next(backup
);
289 if (backup
== temp
->next
)
297 * Helper api to format output for a nexthop, used in the 'detailed'
300 static void show_nexthop_detail_helper(struct vty
*vty
,
301 const struct route_entry
*re
,
302 const struct nexthop
*nexthop
,
306 char buf
[MPLS_LABEL_STRLEN
];
311 nexthop
->rparent
? " " : "");
313 vty_out(vty
, " %c%s",
314 re_status_output_char(re
, nexthop
, false),
315 nexthop
->rparent
? " " : "");
317 switch (nexthop
->type
) {
318 case NEXTHOP_TYPE_IPV4
:
319 case NEXTHOP_TYPE_IPV4_IFINDEX
:
320 vty_out(vty
, " %pI4",
321 &nexthop
->gate
.ipv4
);
322 if (nexthop
->ifindex
)
323 vty_out(vty
, ", via %s",
328 case NEXTHOP_TYPE_IPV6
:
329 case NEXTHOP_TYPE_IPV6_IFINDEX
:
331 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
,
333 if (nexthop
->ifindex
)
334 vty_out(vty
, ", via %s",
340 case NEXTHOP_TYPE_IFINDEX
:
341 vty_out(vty
, " directly connected, %s",
342 ifindex2ifname(nexthop
->ifindex
,
345 case NEXTHOP_TYPE_BLACKHOLE
:
346 vty_out(vty
, " unreachable");
347 switch (nexthop
->bh_type
) {
348 case BLACKHOLE_REJECT
:
349 vty_out(vty
, " (ICMP unreachable)");
351 case BLACKHOLE_ADMINPROHIB
:
353 " (ICMP admin-prohibited)");
356 vty_out(vty
, " (blackhole)");
358 case BLACKHOLE_UNSPEC
:
364 if (re
->vrf_id
!= nexthop
->vrf_id
) {
365 struct vrf
*vrf
= vrf_lookup_by_id(nexthop
->vrf_id
);
367 vty_out(vty
, "(vrf %s)", VRF_LOGNAME(vrf
));
370 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_DUPLICATE
))
371 vty_out(vty
, " (duplicate nexthop removed)");
373 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
374 vty_out(vty
, " inactive");
376 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_ONLINK
))
377 vty_out(vty
, " onlink");
379 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_LINKDOWN
))
380 vty_out(vty
, " linkdown");
382 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
383 vty_out(vty
, " (recursive)");
385 /* Source specified? */
386 switch (nexthop
->type
) {
387 case NEXTHOP_TYPE_IPV4
:
388 case NEXTHOP_TYPE_IPV4_IFINDEX
:
389 if (nexthop
->src
.ipv4
.s_addr
) {
390 if (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
,
391 addrstr
, sizeof(addrstr
)))
392 vty_out(vty
, ", src %s",
397 case NEXTHOP_TYPE_IPV6
:
398 case NEXTHOP_TYPE_IPV6_IFINDEX
:
399 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
,
401 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
,
402 addrstr
, sizeof(addrstr
)))
403 vty_out(vty
, ", src %s",
413 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
415 /* Label information */
416 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
417 vty_out(vty
, ", label %s",
418 mpls_label2str(nexthop
->nh_label
->num_labels
,
419 nexthop
->nh_label
->label
, buf
,
420 sizeof(buf
), 1 /*pretty*/));
424 vty_out(vty
, ", weight %u", nexthop
->weight
);
426 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
427 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
429 for (i
= 1; i
< nexthop
->backup_num
; i
++)
430 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
434 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
435 struct json_object
*json
)
437 struct bgp_zebra_opaque bzo
= {};
438 struct ospf_zebra_opaque ozo
= {};
444 case ZEBRA_ROUTE_SHARP
:
446 json_object_string_add(json
, "opaque",
447 (char *)re
->opaque
->data
);
449 vty_out(vty
, " Opaque Data: %s",
450 (char *)re
->opaque
->data
);
453 case ZEBRA_ROUTE_BGP
:
454 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
457 json_object_string_add(json
, "asPath", bzo
.aspath
);
458 json_object_string_add(json
, "communities",
460 json_object_string_add(json
, "largeCommunities",
462 json_object_string_add(json
, "selectionReason",
463 bzo
.selection_reason
);
465 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
467 if (bzo
.community
[0] != '\0')
468 vty_out(vty
, " Communities : %s\n",
471 if (bzo
.lcommunity
[0] != '\0')
472 vty_out(vty
, " Large-Communities: %s\n",
475 vty_out(vty
, " Selection reason : %s\n",
476 bzo
.selection_reason
);
479 case ZEBRA_ROUTE_OSPF
:
480 case ZEBRA_ROUTE_OSPF6
:
481 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
484 json_object_string_add(json
, "ospfPathType",
486 if (ozo
.area_id
[0] != '\0')
487 json_object_string_add(json
, "ospfAreaId",
489 if (ozo
.tag
[0] != '\0')
490 json_object_string_add(json
, "ospfTag",
493 vty_out(vty
, " OSPF path type : %s\n",
495 if (ozo
.area_id
[0] != '\0')
496 vty_out(vty
, " OSPF area ID : %s\n",
498 if (ozo
.tag
[0] != '\0')
499 vty_out(vty
, " OSPF tag : %s\n",
508 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
512 cur
= monotime(NULL
);
515 frrtime_to_interval(cur
, buf
, bufsize
);
518 /* New RIB. Detailed information for IPv4 route. */
519 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
520 int mcast
, bool use_fib
, bool show_ng
)
522 struct route_entry
*re
;
523 struct nexthop
*nexthop
;
524 char buf
[SRCDEST2STR_BUFFER
];
525 struct zebra_vrf
*zvrf
;
528 dest
= rib_dest_from_rnode(rn
);
530 RNODE_FOREACH_RE (rn
, re
) {
532 * If re not selected for forwarding, skip re
533 * for "show ip/ipv6 fib <prefix>"
535 if (use_fib
&& re
!= dest
->selected_fib
)
538 const char *mcast_info
= "";
540 struct rib_table_info
*info
=
541 srcdest_rnode_table_info(rn
);
542 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
543 ? " using Multicast RIB"
544 : " using Unicast RIB";
547 vty_out(vty
, "Routing entry for %s%s\n",
548 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
549 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
551 vty_out(vty
, "[%d]", re
->instance
);
553 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
556 vty_out(vty
, ", tag %u", re
->tag
);
557 #if defined(SUPPORT_REALMS)
558 if (re
->tag
> 0 && re
->tag
<= 255)
559 vty_out(vty
, "(realm)");
563 vty_out(vty
, ", mtu %u", re
->mtu
);
564 if (re
->vrf_id
!= VRF_DEFAULT
) {
565 zvrf
= vrf_info_lookup(re
->vrf_id
);
566 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
568 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
569 vty_out(vty
, ", best");
572 uptime2str(re
->uptime
, buf
, sizeof(buf
));
574 vty_out(vty
, " Last update %s ago\n", buf
);
577 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
578 if (re
->nhe_installed_id
!= 0
579 && re
->nhe_id
!= re
->nhe_installed_id
)
581 " Installed Nexthop Group ID: %u\n",
582 re
->nhe_installed_id
);
585 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
586 /* Use helper to format each nexthop */
587 show_nexthop_detail_helper(vty
, re
, nexthop
,
588 false /*not backup*/);
591 /* Include backup(s), if present */
592 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
593 show_nh_backup_helper(vty
, re
, nexthop
);
595 zebra_show_ip_route_opaque(vty
, re
, NULL
);
601 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
602 struct route_entry
*re
, json_object
*json
,
603 bool is_fib
, bool show_ng
)
605 const struct nexthop
*nexthop
;
607 char buf
[SRCDEST2STR_BUFFER
];
608 json_object
*json_nexthops
= NULL
;
609 json_object
*json_nexthop
= NULL
;
610 json_object
*json_route
= NULL
;
611 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
612 const struct nexthop_group
*nhg
;
613 char up_str
[MONOTIME_STRLEN
];
615 bool nhg_from_backup
= false;
617 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
619 /* If showing fib information, use the fib view of the
623 nhg
= rib_get_fib_nhg(re
);
625 nhg
= &(re
->nhe
->nhg
);
628 json_route
= json_object_new_object();
629 json_nexthops
= json_object_new_array();
631 json_object_string_add(json_route
, "prefix",
632 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
633 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
634 json_object_string_add(json_route
, "protocol",
635 zebra_route_string(re
->type
));
638 json_object_int_add(json_route
, "instance",
641 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
642 json_object_string_add(json_route
, "vrfName",
643 vrf_id_to_name(re
->vrf_id
));
645 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
646 json_object_boolean_true_add(json_route
, "selected");
648 if (dest
->selected_fib
== re
)
649 json_object_boolean_true_add(json_route
,
652 json_object_int_add(json_route
, "distance",
654 json_object_int_add(json_route
, "metric", re
->metric
);
656 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
657 json_object_boolean_true_add(json_route
, "installed");
659 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
660 json_object_boolean_true_add(json_route
, "failed");
662 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
663 json_object_boolean_true_add(json_route
, "queued");
665 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
666 json_object_boolean_true_add(json_route
, "trapped");
668 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
669 json_object_boolean_true_add(json_route
, "offloaded");
671 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
672 json_object_boolean_false_add(json_route
, "offloaded");
675 json_object_int_add(json_route
, "tag", re
->tag
);
678 json_object_int_add(json_route
, "table", re
->table
);
680 json_object_int_add(json_route
, "internalStatus",
682 json_object_int_add(json_route
, "internalFlags",
684 json_object_int_add(json_route
, "internalNextHopNum",
685 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
686 json_object_int_add(json_route
, "internalNextHopActiveNum",
687 nexthop_group_active_nexthop_num(
689 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
691 if (re
->nhe_installed_id
!= 0)
692 json_object_int_add(json_route
,
693 "installedNexthopGroupId",
694 re
->nhe_installed_id
);
696 json_object_string_add(json_route
, "uptime", up_str
);
698 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
699 json_nexthop
= json_object_new_object();
700 show_nexthop_json_helper(json_nexthop
,
703 json_object_array_add(json_nexthops
,
707 json_object_object_add(json_route
, "nexthops", json_nexthops
);
709 /* If there are backup nexthops, include them */
711 nhg
= rib_get_fib_backup_nhg(re
);
713 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
715 if (nhg
&& nhg
->nexthop
) {
716 json_nexthops
= json_object_new_array();
718 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
719 json_nexthop
= json_object_new_object();
721 show_nexthop_json_helper(json_nexthop
,
723 json_object_array_add(json_nexthops
,
727 json_object_object_add(json_route
, "backupNexthops",
730 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
732 json_object_array_add(json
, json_route
);
736 /* Prefix information, and first nexthop. If we're showing 'fib',
737 * and there are no installed primary nexthops, see if there are any
738 * backup nexthops and start with those.
740 if (is_fib
&& nhg
->nexthop
== NULL
) {
741 nhg
= rib_get_fib_backup_nhg(re
);
742 nhg_from_backup
= true;
745 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
747 len
+= vty_out(vty
, "[%d]", re
->instance
);
748 if (nhg_from_backup
&& nhg
->nexthop
) {
751 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
752 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
753 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
757 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
758 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
759 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
762 /* Distance and metric display. */
763 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
764 (re
->distance
|| re
->metric
)) ||
765 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
766 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
770 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
772 /* Nexthop information. */
773 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
776 } else if (nhg_from_backup
) {
777 vty_out(vty
, " b%c%*c",
778 re_status_output_char(re
, nexthop
, is_fib
),
779 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
781 vty_out(vty
, " %c%*c",
782 re_status_output_char(re
, nexthop
, is_fib
),
783 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
786 show_route_nexthop_helper(vty
, re
, nexthop
);
787 vty_out(vty
, ", %s\n", up_str
);
790 /* If we only had backup nexthops, we're done */
794 /* Check for backup nexthop info if present */
796 nhg
= rib_get_fib_backup_nhg(re
);
798 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
803 /* Print backup info */
804 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
808 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
810 /* TODO -- it'd be nice to be able to include
811 * the entire list of backups, *and* include the
812 * real installation state.
814 vty_out(vty
, " b%c %*c",
815 (star_p
? '*' : ' '),
816 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
817 show_route_nexthop_helper(vty
, re
, nexthop
);
823 static void vty_show_ip_route_detail_json(struct vty
*vty
,
824 struct route_node
*rn
, bool use_fib
)
826 json_object
*json
= NULL
;
827 json_object
*json_prefix
= NULL
;
828 struct route_entry
*re
;
832 dest
= rib_dest_from_rnode(rn
);
834 json
= json_object_new_object();
835 json_prefix
= json_object_new_array();
837 RNODE_FOREACH_RE (rn
, re
) {
839 * If re not selected for forwarding, skip re
840 * for "show ip/ipv6 fib <prefix> json"
842 if (use_fib
&& re
!= dest
->selected_fib
)
844 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
847 prefix2str(&rn
->p
, buf
, sizeof(buf
));
848 json_object_object_add(json
, buf
, json_prefix
);
852 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
853 struct route_table
*table
, afi_t afi
,
854 bool use_fib
, route_tag_t tag
,
855 const struct prefix
*longer_prefix_p
,
856 bool supernets_only
, int type
,
857 unsigned short ospf_instance_id
, bool use_json
,
858 uint32_t tableid
, bool show_ng
,
859 struct route_show_ctx
*ctx
)
861 struct route_node
*rn
;
862 struct route_entry
*re
;
865 json_object
*json
= NULL
;
866 json_object
*json_prefix
= NULL
;
871 * ctx->multi indicates if we are dumping multiple tables or vrfs.
873 * => display the common header at most once
874 * => add newline at each call except first
875 * => always display the VRF and table
877 * => display the common header if at least one entry is found
878 * => display the VRF and table if specific
882 json
= json_object_new_object();
884 /* Show all routes. */
885 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
886 dest
= rib_dest_from_rnode(rn
);
888 RNODE_FOREACH_RE (rn
, re
) {
889 if (use_fib
&& re
!= dest
->selected_fib
)
892 if (tag
&& re
->tag
!= tag
)
896 && !prefix_match(longer_prefix_p
, &rn
->p
))
899 /* This can only be true when the afi is IPv4 */
900 if (supernets_only
) {
901 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
903 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
906 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
909 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
913 if (type
&& re
->type
!= type
)
917 && (re
->type
!= ZEBRA_ROUTE_OSPF
918 || re
->instance
!= ospf_instance_id
))
923 json_prefix
= json_object_new_array();
925 if (!ctx
->header_done
) {
928 SHOW_ROUTE_V4_HEADER
);
931 SHOW_ROUTE_V6_HEADER
);
933 if (ctx
->multi
&& ctx
->header_done
)
935 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
938 vty_out(vty
, "VRF %s:\n",
942 "VRF %s table %u:\n",
946 ctx
->header_done
= true;
950 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
955 prefix2str(&rn
->p
, buf
, sizeof(buf
));
956 json_object_object_add(json
, buf
, json_prefix
);
965 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
966 afi_t afi
, bool use_fib
, bool use_json
,
968 const struct prefix
*longer_prefix_p
,
969 bool supernets_only
, int type
,
970 unsigned short ospf_instance_id
, bool show_ng
,
971 struct route_show_ctx
*ctx
)
973 struct zebra_router_table
*zrt
;
974 struct rib_table_info
*info
;
976 RB_FOREACH (zrt
, zebra_router_table_head
,
978 info
= route_table_get_info(zrt
->table
);
980 if (zvrf
!= info
->zvrf
)
982 if (zrt
->afi
!= afi
||
983 zrt
->safi
!= SAFI_UNICAST
)
986 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
987 use_fib
, use_json
, tag
, longer_prefix_p
,
988 supernets_only
, type
, ospf_instance_id
,
989 zrt
->tableid
, show_ng
, ctx
);
993 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
994 safi_t safi
, bool use_fib
, bool use_json
,
996 const struct prefix
*longer_prefix_p
,
997 bool supernets_only
, int type
,
998 unsigned short ospf_instance_id
, uint32_t tableid
,
999 bool show_ng
, struct route_show_ctx
*ctx
)
1001 struct route_table
*table
;
1002 struct zebra_vrf
*zvrf
= NULL
;
1004 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1006 vty_out(vty
, "{}\n");
1008 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1012 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1014 vty_out(vty
, "{}\n");
1016 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1021 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1023 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1026 vty_out(vty
, "{}\n");
1030 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1031 longer_prefix_p
, supernets_only
, type
,
1032 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1039 "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]",
1043 "IP nexthop tracking table\n"
1044 "IP import check tracking table\n"
1050 VRF_ALL_CMD_HELP_STR
1051 "Show Multicast (MRIB) NHT state\n"
1054 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1055 vrf_id_t vrf_id
= VRF_DEFAULT
;
1056 struct prefix prefix
, *p
= NULL
;
1057 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1058 bool uj
= use_json(argc
, argv
);
1059 json_object
*json
= NULL
;
1060 json_object
*json_vrf
= NULL
;
1061 json_object
*json_nexthop
= NULL
;
1064 json
= json_object_new_object();
1068 struct zebra_vrf
*zvrf
;
1070 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1071 if ((zvrf
= vrf
->info
) != NULL
) {
1073 json_vrf
= json_object_new_object();
1074 json_nexthop
= json_object_new_object();
1075 json_object_object_add(json
,
1078 json_object_object_add(json_vrf
,
1084 vty_out(vty
, "\nVRF %s:\n",
1087 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1088 vty
, NULL
, json_nexthop
);
1093 vty_json(vty
, json
);
1098 VRF_GET_ID(vrf_id
, vrf_name
, false);
1100 memset(&prefix
, 0, sizeof(prefix
));
1102 p
= sockunion2hostprefix(addr
, &prefix
);
1105 json_object_free(json
);
1111 json_vrf
= json_object_new_object();
1112 json_nexthop
= json_object_new_object();
1114 json_object_object_add(json
, vrf_name
, json_vrf
);
1116 json_object_object_add(json
, "default", json_vrf
);
1118 json_object_object_add(json_vrf
,
1119 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1123 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1126 vty_json(vty
, json
);
1131 DEFUN (ip_nht_default_route
,
1132 ip_nht_default_route_cmd
,
1133 "ip nht resolve-via-default",
1135 "Filter Next Hop tracking route resolution\n"
1136 "Resolve via default route\n")
1138 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1143 if (zvrf
->zebra_rnh_ip_default_route
)
1146 zvrf
->zebra_rnh_ip_default_route
= true;
1148 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1152 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1153 json_object
*json_nhe_hdr
)
1155 struct nexthop
*nexthop
= NULL
;
1156 struct nhg_connected
*rb_node_dep
= NULL
;
1157 struct nexthop_group
*backup_nhg
;
1158 char up_str
[MONOTIME_STRLEN
];
1159 char time_left
[MONOTIME_STRLEN
];
1160 json_object
*json_dependants
= NULL
;
1161 json_object
*json_depends
= NULL
;
1162 json_object
*json_nexthop_array
= NULL
;
1163 json_object
*json_nexthops
= NULL
;
1164 json_object
*json
= NULL
;
1165 json_object
*json_backup_nexthop_array
= NULL
;
1166 json_object
*json_backup_nexthops
= NULL
;
1169 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1172 json
= json_object_new_object();
1175 json_object_string_add(json
, "type",
1176 zebra_route_string(nhe
->type
));
1177 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1178 if (thread_is_scheduled(nhe
->timer
))
1179 json_object_string_add(
1180 json
, "timeToDeletion",
1181 thread_timer_to_hhmmss(time_left
,
1184 json_object_string_add(json
, "uptime", up_str
);
1185 json_object_string_add(json
, "vrf",
1186 vrf_id_to_name(nhe
->vrf_id
));
1189 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1190 zebra_route_string(nhe
->type
));
1191 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1192 if (thread_is_scheduled(nhe
->timer
))
1193 vty_out(vty
, " Time to Deletion: %s",
1194 thread_timer_to_hhmmss(time_left
,
1199 vty_out(vty
, " Uptime: %s\n", up_str
);
1200 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1203 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1205 json_object_boolean_true_add(json
, "valid");
1207 vty_out(vty
, " Valid");
1209 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1211 json_object_boolean_true_add(json
, "installed");
1213 vty_out(vty
, ", Installed");
1220 json_object_int_add(json
, "interfaceIndex",
1223 vty_out(vty
, " Interface Index: %d\n",
1227 if (!zebra_nhg_depends_is_empty(nhe
)) {
1229 json_depends
= json_object_new_array();
1231 vty_out(vty
, " Depends:");
1232 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1234 json_object_array_add(
1236 json_object_new_int(
1237 rb_node_dep
->nhe
->id
));
1239 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1244 json_object_object_add(json
, "depends", json_depends
);
1247 /* Output nexthops */
1249 json_nexthop_array
= json_object_new_array();
1252 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1253 if (json_nexthop_array
) {
1254 json_nexthops
= json_object_new_object();
1255 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1257 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1260 /* Make recursive nexthops a bit more clear */
1262 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1265 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1266 if (CHECK_FLAG(nexthop
->flags
,
1267 NEXTHOP_FLAG_HAS_BACKUP
)) {
1269 json_object_int_add(
1270 json_nexthops
, "backup",
1271 nexthop
->backup_idx
[0]);
1273 vty_out(vty
, " [backup %d]",
1274 nexthop
->backup_idx
[0]);
1280 json_object_array_add(json_nexthop_array
,
1287 /* TODO -- print more useful backup info */
1288 if (CHECK_FLAG(nexthop
->flags
,
1289 NEXTHOP_FLAG_HAS_BACKUP
)) {
1292 vty_out(vty
, "[backup");
1293 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1295 nexthop
->backup_idx
[i
]);
1300 json_object_array_add(json_nexthop_array
,
1306 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1308 /* Output backup nexthops (if any) */
1309 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1312 json_backup_nexthop_array
= json_object_new_array();
1314 vty_out(vty
, " Backups:\n");
1316 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1317 if (json_backup_nexthop_array
) {
1318 json_backup_nexthops
= json_object_new_object();
1319 show_nexthop_json_helper(json_backup_nexthops
,
1321 json_object_array_add(json_backup_nexthop_array
,
1322 json_backup_nexthops
);
1325 if (!CHECK_FLAG(nexthop
->flags
,
1326 NEXTHOP_FLAG_RECURSIVE
))
1329 /* Make recursive nexthops a bit more
1333 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1339 json_object_object_add(json
, "backupNexthops",
1340 json_backup_nexthop_array
);
1343 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1345 json_dependants
= json_object_new_array();
1347 vty_out(vty
, " Dependents:");
1348 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1351 json_object_array_add(
1353 json_object_new_int(
1354 rb_node_dep
->nhe
->id
));
1356 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1359 json_object_object_add(json
, "dependents",
1365 if (nhe
->nhg
.nhgr
.buckets
) {
1367 json_object_int_add(json
, "buckets",
1368 nhe
->nhg
.nhgr
.buckets
);
1369 json_object_int_add(json
, "idleTimer",
1370 nhe
->nhg
.nhgr
.idle_timer
);
1371 json_object_int_add(json
, "unbalancedTimer",
1372 nhe
->nhg
.nhgr
.unbalanced_timer
);
1373 json_object_int_add(json
, "unbalancedTime",
1374 nhe
->nhg
.nhgr
.unbalanced_time
);
1377 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1379 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1380 nhe
->nhg
.nhgr
.unbalanced_timer
,
1381 nhe
->nhg
.nhgr
.unbalanced_time
);
1386 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1389 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1392 struct nhg_hash_entry
*nhe
= NULL
;
1394 nhe
= zebra_nhg_lookup_id(id
);
1397 show_nexthop_group_out(vty
, nhe
, json
);
1400 vty_json(vty
, json
);
1402 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1408 vty_json(vty
, json
);
1413 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1415 struct nhe_show_context
{
1423 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1425 struct nhe_show_context
*ctx
= arg
;
1426 struct nhg_hash_entry
*nhe
;
1428 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1430 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1433 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1436 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1439 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1442 return HASHWALK_CONTINUE
;
1445 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1446 struct zebra_vrf
*zvrf
, afi_t afi
,
1447 int type
, json_object
*json
)
1449 struct nhe_show_context ctx
;
1453 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1457 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1460 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1462 struct zebra_if
*zebra_if
= NULL
;
1463 struct nhg_connected
*rb_node_dep
= NULL
;
1465 zebra_if
= ifp
->info
;
1467 if (!if_nhg_dependents_is_empty(ifp
)) {
1468 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1470 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1473 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1478 DEFPY (show_interface_nexthop_group
,
1479 show_interface_nexthop_group_cmd
,
1480 "show interface [IFNAME$if_name] nexthop-group",
1482 "Interface status and configuration\n"
1484 "Show Nexthop Groups\n")
1486 struct vrf
*vrf
= NULL
;
1487 struct interface
*ifp
= NULL
;
1490 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1492 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1494 if_nexthop_group_dump_vty(vty
, ifp
);
1498 FOR_ALL_INTERFACES (vrf
, ifp
)
1499 if_nexthop_group_dump_vty(vty
, ifp
);
1505 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1512 DEFPY(show_nexthop_group
,
1513 show_nexthop_group_cmd
,
1514 "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]",
1516 "Show Nexthop Groups\n"
1518 "Nexthop Group ID\n"
1519 "Show Singleton Nexthop-Groups\n"
1522 "Kernel (not installed via the zebra RIB)\n"
1523 "Zebra (implicitly created by zebra)\n"
1524 "Border Gateway Protocol (BGP)\n"
1525 "Super Happy Advanced Routing Protocol (SHARP)\n"
1526 VRF_FULL_CMD_HELP_STR
1530 struct zebra_vrf
*zvrf
= NULL
;
1531 afi_t afi
= AFI_UNSPEC
;
1533 bool uj
= use_json(argc
, argv
);
1534 json_object
*json
= NULL
;
1535 json_object
*json_vrf
= NULL
;
1538 json
= json_object_new_object();
1541 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1549 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1552 type
= ZEBRA_ROUTE_NHG
;
1556 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1558 vty_json(vty
, json
);
1561 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1568 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1569 struct zebra_vrf
*zvrf
;
1575 json_vrf
= json_object_new_object();
1577 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1579 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1582 json_object_object_add(json
, vrf
->name
,
1587 vty_json(vty
, json
);
1593 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1595 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1599 vty_json(vty
, json
);
1601 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1606 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1609 vty_json(vty
, json
);
1614 DEFPY_HIDDEN(nexthop_group_use_enable
,
1615 nexthop_group_use_enable_cmd
,
1616 "[no] zebra nexthop kernel enable",
1619 "Nexthop configuration \n"
1620 "Configure use of kernel nexthops\n"
1621 "Enable kernel nexthops\n")
1623 zebra_nhg_enable_kernel_nexthops(!no
);
1627 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1628 "[no] zebra nexthop proto only",
1630 "Nexthop configuration\n"
1631 "Configure exclusive use of proto nexthops\n"
1632 "Only use proto nexthops\n")
1634 zebra_nhg_set_proto_nexthops_only(!no
);
1638 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1639 backup_nexthop_recursive_use_enable_cmd
,
1640 "[no] zebra nexthop resolve-via-backup",
1643 "Nexthop configuration \n"
1644 "Configure use of backup nexthops in recursive resolution\n")
1646 zebra_nhg_set_recursive_use_backups(!no
);
1650 DEFUN (no_ip_nht_default_route
,
1651 no_ip_nht_default_route_cmd
,
1652 "no ip nht resolve-via-default",
1655 "Filter Next Hop tracking route resolution\n"
1656 "Resolve via default route\n")
1658 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1663 if (!zvrf
->zebra_rnh_ip_default_route
)
1666 zvrf
->zebra_rnh_ip_default_route
= false;
1667 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1671 DEFUN (ipv6_nht_default_route
,
1672 ipv6_nht_default_route_cmd
,
1673 "ipv6 nht resolve-via-default",
1675 "Filter Next Hop tracking route resolution\n"
1676 "Resolve via default route\n")
1678 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1683 if (zvrf
->zebra_rnh_ipv6_default_route
)
1686 zvrf
->zebra_rnh_ipv6_default_route
= true;
1687 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1691 DEFUN (no_ipv6_nht_default_route
,
1692 no_ipv6_nht_default_route_cmd
,
1693 "no ipv6 nht resolve-via-default",
1696 "Filter Next Hop tracking route resolution\n"
1697 "Resolve via default route\n")
1699 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1704 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1707 zvrf
->zebra_rnh_ipv6_default_route
= false;
1708 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1712 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1713 "[no] ip nht hide-backup-events",
1716 "Nexthop-tracking configuration\n"
1717 "Hide notification about backup nexthops\n")
1719 rnh_set_hide_backups(!no
);
1727 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1728 [vrf <NAME$vrf_name|all$vrf_all>]\
1731 |A.B.C.D/M$prefix longer-prefixes\
1732 |supernets-only$supernets_only\
1735 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1736 |ospf$type_str (1-65535)$ospf_instance_id\
1738 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1739 [vrf <NAME$vrf_name|all$vrf_all>]\
1742 |X:X::X:X/M$prefix longer-prefixes\
1744 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1746 [<json$json|nexthop-group$ng>]",
1749 "IP forwarding table\n"
1750 "IP routing table\n"
1751 "Table to display\n"
1752 "The table number to display\n"
1754 VRF_FULL_CMD_HELP_STR
1755 "Show only routes with tag\n"
1757 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1758 "Show route matching the specified Network/Mask pair only\n"
1759 "Show supernet entries only\n"
1760 FRR_IP_REDIST_HELP_STR_ZEBRA
1761 "Open Shortest Path First (OSPFv2)\n"
1764 "IP forwarding table\n"
1765 "IP routing table\n"
1766 "Table to display\n"
1767 "The table number to display\n"
1769 VRF_FULL_CMD_HELP_STR
1770 "Show only routes with tag\n"
1773 "Show route matching the specified Network/Mask pair only\n"
1774 FRR_IP6_REDIST_HELP_STR_ZEBRA
1776 "Nexthop Group Information\n")
1778 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1781 struct zebra_vrf
*zvrf
;
1782 struct route_show_ctx ctx
= {
1783 .multi
= vrf_all
|| table_all
,
1786 if (!vrf_is_backend_netns()) {
1787 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1789 vty_out(vty
, "{}\n");
1791 vty_out(vty
, "Linux vrf backend already points to table id\n");
1792 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1798 type
= proto_redistnum(afi
, type_str
);
1800 vty_out(vty
, "Unknown route type\n");
1806 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1807 if ((zvrf
= vrf
->info
) == NULL
1808 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1812 do_show_ip_route_all(
1813 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1814 prefix_str
? prefix
: NULL
,
1815 !!supernets_only
, type
,
1816 ospf_instance_id
, !!ng
, &ctx
);
1819 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1821 prefix_str
? prefix
: NULL
,
1822 !!supernets_only
, type
,
1823 ospf_instance_id
, table
, !!ng
, &ctx
);
1826 vrf_id_t vrf_id
= VRF_DEFAULT
;
1829 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1830 vrf
= vrf_lookup_by_id(vrf_id
);
1839 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1840 prefix_str
? prefix
: NULL
,
1841 !!supernets_only
, type
,
1842 ospf_instance_id
, !!ng
, &ctx
);
1844 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1846 prefix_str
? prefix
: NULL
,
1847 !!supernets_only
, type
,
1848 ospf_instance_id
, table
, !!ng
, &ctx
);
1854 ALIAS_HIDDEN (show_route
,
1856 "show <ip$ipv4|ipv6$ipv6> ro",
1860 "IP routing table\n");
1863 DEFPY (show_route_detail
,
1864 show_route_detail_cmd
,
1867 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1872 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1878 [json$json] [nexthop-group$ng]",
1881 "IP forwarding table\n"
1882 "IP routing table\n"
1883 VRF_FULL_CMD_HELP_STR
1884 "Network in the IP routing table to display\n"
1885 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1887 "IPv6 forwarding table\n"
1888 "IPv6 routing table\n"
1889 VRF_FULL_CMD_HELP_STR
1893 "Nexthop Group Information\n")
1895 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1896 struct route_table
*table
;
1898 struct route_node
*rn
;
1899 bool use_fib
= !!fib
;
1901 bool network_found
= false;
1902 bool show_ng
= !!ng
;
1905 prefix_str
= address_str
;
1906 if (str2prefix(prefix_str
, &p
) < 0) {
1907 vty_out(vty
, "%% Malformed address\n");
1913 struct zebra_vrf
*zvrf
;
1915 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1916 if ((zvrf
= vrf
->info
) == NULL
1917 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1920 rn
= route_node_match(table
, &p
);
1923 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1924 route_unlock_node(rn
);
1928 dest
= rib_dest_from_rnode(rn
);
1929 if (use_fib
&& !dest
->selected_fib
) {
1930 route_unlock_node(rn
);
1934 network_found
= true;
1936 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1938 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1941 route_unlock_node(rn
);
1944 if (!network_found
) {
1946 vty_out(vty
, "{}\n");
1950 "%% Network not in FIB\n");
1953 "%% Network not in RIB\n");
1958 vrf_id_t vrf_id
= VRF_DEFAULT
;
1961 VRF_GET_ID(vrf_id
, vrf_name
, false);
1963 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1967 rn
= route_node_match(table
, &p
);
1969 dest
= rib_dest_from_rnode(rn
);
1971 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1972 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1974 vty_out(vty
, "{}\n");
1978 "%% Network not in FIB\n");
1981 "%% Network not in table\n");
1984 route_unlock_node(rn
);
1989 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1991 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1993 route_unlock_node(rn
);
1999 DEFPY (show_route_summary
,
2000 show_route_summary_cmd
,
2001 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2002 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2006 "IP routing table\n"
2007 VRF_FULL_CMD_HELP_STR
2008 "Summary of all routes\n"
2009 "Table to display summary for\n"
2010 "The table number\n"
2014 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2015 struct route_table
*table
;
2016 bool uj
= use_json(argc
, argv
);
2020 struct zebra_vrf
*zvrf
;
2022 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2023 if ((zvrf
= vrf
->info
) == NULL
)
2027 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2030 table
= zebra_vrf_lookup_table_with_table_id(
2031 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2038 vty_show_ip_route_summary_prefix(vty
, table
,
2041 vty_show_ip_route_summary(vty
, table
, uj
);
2044 vrf_id_t vrf_id
= VRF_DEFAULT
;
2047 VRF_GET_ID(vrf_id
, vrf_name
, false);
2050 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2052 table
= zebra_vrf_lookup_table_with_table_id(
2053 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2058 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2060 vty_show_ip_route_summary(vty
, table
, uj
);
2066 DEFUN_HIDDEN (show_route_zebra_dump
,
2067 show_route_zebra_dump_cmd
,
2068 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2078 struct route_table
*table
;
2079 const char *vrf_name
= NULL
;
2082 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2084 if (argv_find(argv
, argc
, "vrf", &idx
))
2085 vrf_name
= argv
[++idx
]->arg
;
2089 struct zebra_vrf
*zvrf
;
2091 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2094 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2097 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2098 show_ip_route_dump_vty(vty
, table
);
2101 vrf_id_t vrf_id
= VRF_DEFAULT
;
2103 VRF_GET_ID(vrf_id
, vrf_name
, true);
2105 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2109 show_ip_route_dump_vty(vty
, table
);
2115 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2116 struct route_entry
*re
, unsigned int num
)
2119 char buf
[SRCDEST2STR_BUFFER
];
2121 vty_out(vty
, " Nexthop %u:\n", num
);
2122 vty_out(vty
, " type: %u\n", nexthop
->type
);
2123 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2124 switch (nexthop
->type
) {
2125 case NEXTHOP_TYPE_IPV4
:
2126 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2127 vty_out(vty
, " ip address: %s\n",
2128 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2130 vty_out(vty
, " afi: ipv4\n");
2132 if (nexthop
->ifindex
) {
2133 vty_out(vty
, " interface index: %d\n",
2135 vty_out(vty
, " interface name: %s\n",
2136 ifindex2ifname(nexthop
->ifindex
,
2140 if (nexthop
->src
.ipv4
.s_addr
2141 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2143 vty_out(vty
, " source: %s\n", buf
);
2145 case NEXTHOP_TYPE_IPV6
:
2146 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2147 vty_out(vty
, " ip: %s\n",
2148 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2150 vty_out(vty
, " afi: ipv6\n");
2152 if (nexthop
->ifindex
) {
2153 vty_out(vty
, " interface index: %d\n",
2155 vty_out(vty
, " interface name: %s\n",
2156 ifindex2ifname(nexthop
->ifindex
,
2160 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2161 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2163 vty_out(vty
, " source: %s\n", buf
);
2166 case NEXTHOP_TYPE_IFINDEX
:
2168 " Nexthop is an interface (directly connected).\n");
2169 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2170 vty_out(vty
, " interface name: %s\n",
2171 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2173 case NEXTHOP_TYPE_BLACKHOLE
:
2174 vty_out(vty
, " Nexthop type is blackhole.\n");
2176 switch (nexthop
->bh_type
) {
2177 case BLACKHOLE_REJECT
:
2178 vty_out(vty
, " Blackhole type: reject\n");
2180 case BLACKHOLE_ADMINPROHIB
:
2182 " Blackhole type: admin-prohibited\n");
2184 case BLACKHOLE_NULL
:
2185 vty_out(vty
, " Blackhole type: NULL0\n");
2187 case BLACKHOLE_UNSPEC
:
2194 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2196 struct route_node
*rn
;
2197 struct route_entry
*re
;
2198 char buf
[SRCDEST2STR_BUFFER
];
2203 struct nexthop
*nexthop
= NULL
;
2204 int nexthop_num
= 0;
2206 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2207 vty_out(vty
, "----------------------------\n");
2209 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2210 RNODE_FOREACH_RE (rn
, re
) {
2211 vty_out(vty
, "Route: %s\n",
2212 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2213 vty_out(vty
, " protocol: %s\n",
2214 zebra_route_string(re
->type
));
2215 vty_out(vty
, " instance: %u\n", re
->instance
);
2216 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2217 vty_out(vty
, " VRF name: %s\n",
2218 vrf_id_to_name(re
->vrf_id
));
2219 vty_out(vty
, " flags: %u\n", re
->flags
);
2221 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2222 vty_out(vty
, " distance: %u\n", re
->distance
);
2223 vty_out(vty
, " metric: %u\n", re
->metric
);
2226 vty_out(vty
, " tag: %u\n", re
->tag
);
2228 uptime
= monotime(&tv
);
2229 uptime
-= re
->uptime
;
2230 gmtime_r(&uptime
, &tm
);
2232 if (uptime
< ONE_DAY_SECOND
)
2233 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2234 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2235 else if (uptime
< ONE_WEEK_SECOND
)
2236 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2237 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2239 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2241 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2244 vty_out(vty
, " status: %u\n", re
->status
);
2245 vty_out(vty
, " nexthop_num: %u\n",
2246 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2247 vty_out(vty
, " nexthop_active_num: %u\n",
2248 nexthop_group_active_nexthop_num(
2250 vty_out(vty
, " table: %u\n", re
->table
);
2251 vty_out(vty
, " uptime: %s\n", time
);
2253 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2255 show_ip_route_nht_dump(vty
, nexthop
, re
,
2265 static void vty_show_ip_route_summary(struct vty
*vty
,
2266 struct route_table
*table
, bool use_json
)
2268 struct route_node
*rn
;
2269 struct route_entry
*re
;
2270 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2271 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2272 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2273 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2274 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2275 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2278 json_object
*json_route_summary
= NULL
;
2279 json_object
*json_route_routes
= NULL
;
2281 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2282 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2283 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2284 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2287 json_route_summary
= json_object_new_object();
2288 json_route_routes
= json_object_new_array();
2289 json_object_object_add(json_route_summary
, "routes",
2293 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2294 RNODE_FOREACH_RE (rn
, re
) {
2295 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2296 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2298 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2300 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2302 rib_cnt
[re
->type
]++;
2304 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2305 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2308 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2310 fib_cnt
[re
->type
]++;
2313 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2315 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2317 trap_cnt
[re
->type
]++;
2320 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2322 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2324 offload_cnt
[re
->type
]++;
2329 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2331 zvrf_name(((struct rib_table_info
*)
2332 route_table_get_info(table
))
2335 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2336 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2337 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2338 if (i
== ZEBRA_ROUTE_BGP
) {
2340 json_object
*json_route_ebgp
=
2341 json_object_new_object();
2343 json_object_int_add(
2344 json_route_ebgp
, "fib",
2345 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2346 json_object_int_add(
2347 json_route_ebgp
, "rib",
2348 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2349 json_object_int_add(
2350 json_route_ebgp
, "fibOffLoaded",
2351 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2352 json_object_int_add(
2353 json_route_ebgp
, "fibTrapped",
2354 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2356 json_object_string_add(json_route_ebgp
,
2358 json_object_array_add(json_route_routes
,
2361 json_object
*json_route_ibgp
=
2362 json_object_new_object();
2364 json_object_int_add(
2365 json_route_ibgp
, "fib",
2366 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2367 json_object_int_add(
2368 json_route_ibgp
, "rib",
2369 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2370 json_object_int_add(
2371 json_route_ibgp
, "fibOffLoaded",
2372 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2373 json_object_int_add(
2374 json_route_ibgp
, "fibTrapped",
2375 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2376 json_object_string_add(json_route_ibgp
,
2378 json_object_array_add(json_route_routes
,
2381 vty_out(vty
, "%-20s %-20d %-20d \n",
2383 rib_cnt
[ZEBRA_ROUTE_BGP
],
2384 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2385 vty_out(vty
, "%-20s %-20d %-20d \n",
2387 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2388 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2392 json_object
*json_route_type
=
2393 json_object_new_object();
2395 json_object_int_add(json_route_type
,
2397 json_object_int_add(json_route_type
,
2400 json_object_int_add(json_route_type
,
2403 json_object_int_add(json_route_type
,
2406 json_object_string_add(
2407 json_route_type
, "type",
2408 zebra_route_string(i
));
2409 json_object_array_add(json_route_routes
,
2412 vty_out(vty
, "%-20s %-20d %-20d \n",
2413 zebra_route_string(i
),
2414 rib_cnt
[i
], fib_cnt
[i
]);
2420 json_object_int_add(json_route_summary
, "routesTotal",
2421 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2422 json_object_int_add(json_route_summary
, "routesTotalFib",
2423 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2425 vty_json(vty
, json_route_summary
);
2427 vty_out(vty
, "------\n");
2428 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2429 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2435 * Implementation of the ip route summary prefix command.
2437 * This command prints the primary prefixes that have been installed by various
2438 * protocols on the box.
2441 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2442 struct route_table
*table
,
2445 struct route_node
*rn
;
2446 struct route_entry
*re
;
2447 struct nexthop
*nexthop
;
2448 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2449 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2450 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2451 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2454 json_object
*json_route_summary
= NULL
;
2455 json_object
*json_route_routes
= NULL
;
2457 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2458 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2461 json_route_summary
= json_object_new_object();
2462 json_route_routes
= json_object_new_array();
2463 json_object_object_add(json_route_summary
, "prefixRoutes",
2467 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2468 RNODE_FOREACH_RE (rn
, re
) {
2471 * In case of ECMP, count only once.
2474 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2475 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2476 fib_cnt
[re
->type
]++;
2478 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2479 nexthop
= nexthop
->next
) {
2481 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2482 rib_cnt
[re
->type
]++;
2483 if (re
->type
== ZEBRA_ROUTE_BGP
2484 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2485 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2486 if (CHECK_FLAG(re
->status
,
2487 ROUTE_ENTRY_INSTALLED
))
2488 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2494 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2495 "Prefix Routes", "FIB",
2496 zvrf_name(((struct rib_table_info
*)
2497 route_table_get_info(table
))
2500 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2501 if (rib_cnt
[i
] > 0) {
2502 if (i
== ZEBRA_ROUTE_BGP
) {
2504 json_object
*json_route_ebgp
=
2505 json_object_new_object();
2507 json_object_int_add(
2508 json_route_ebgp
, "fib",
2509 fib_cnt
[ZEBRA_ROUTE_BGP
]
2510 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2511 json_object_int_add(
2512 json_route_ebgp
, "rib",
2513 rib_cnt
[ZEBRA_ROUTE_BGP
]
2514 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2515 json_object_string_add(json_route_ebgp
,
2517 json_object_array_add(json_route_routes
,
2520 json_object
*json_route_ibgp
=
2521 json_object_new_object();
2523 json_object_int_add(
2524 json_route_ibgp
, "fib",
2525 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2526 json_object_int_add(
2527 json_route_ibgp
, "rib",
2528 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2529 json_object_string_add(json_route_ibgp
,
2531 json_object_array_add(json_route_routes
,
2534 vty_out(vty
, "%-20s %-20d %-20d \n",
2536 rib_cnt
[ZEBRA_ROUTE_BGP
]
2537 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2538 fib_cnt
[ZEBRA_ROUTE_BGP
]
2539 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2540 vty_out(vty
, "%-20s %-20d %-20d \n",
2542 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2543 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2547 json_object
*json_route_type
=
2548 json_object_new_object();
2550 json_object_int_add(json_route_type
,
2552 json_object_int_add(json_route_type
,
2554 json_object_string_add(
2555 json_route_type
, "type",
2556 zebra_route_string(i
));
2557 json_object_array_add(json_route_routes
,
2560 vty_out(vty
, "%-20s %-20d %-20d \n",
2561 zebra_route_string(i
),
2562 rib_cnt
[i
], fib_cnt
[i
]);
2568 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2569 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2570 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2571 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2573 vty_json(vty
, json_route_summary
);
2575 vty_out(vty
, "------\n");
2576 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2577 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2582 DEFUN (allow_external_route_update
,
2583 allow_external_route_update_cmd
,
2584 "allow-external-route-update",
2585 "Allow FRR routes to be overwritten by external processes\n")
2587 zrouter
.allow_delete
= true;
2592 DEFUN (no_allow_external_route_update
,
2593 no_allow_external_route_update_cmd
,
2594 "no allow-external-route-update",
2596 "Allow FRR routes to be overwritten by external processes\n")
2598 zrouter
.allow_delete
= false;
2611 struct zebra_vrf
*zvrf
;
2613 if (vrf_is_backend_netns())
2614 vty_out(vty
, "netns-based vrfs\n");
2616 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2617 if (!(zvrf
= vrf
->info
))
2619 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2622 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2623 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2624 vty_out(vty
, "inactive");
2625 else if (zvrf_ns_name(zvrf
))
2626 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2627 zvrf_ns_name(zvrf
));
2629 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2631 if (vrf_is_user_cfged(vrf
))
2632 vty_out(vty
, " (configured)");
2639 DEFPY (evpn_mh_mac_holdtime
,
2640 evpn_mh_mac_holdtime_cmd
,
2641 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2646 "Duration in seconds\n")
2648 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2652 DEFPY (evpn_mh_neigh_holdtime
,
2653 evpn_mh_neigh_holdtime_cmd
,
2654 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2658 "Neighbor entry hold time\n"
2659 "Duration in seconds\n")
2662 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2666 DEFPY (evpn_mh_startup_delay
,
2667 evpn_mh_startup_delay_cmd
,
2668 "[no] evpn mh startup-delay(0-3600)$duration",
2673 "duration in seconds\n")
2676 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2680 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2681 "[no$no] evpn mh redirect-off",
2685 "ES bond redirect for fast-failover off\n")
2689 redirect_off
= no
? false : true;
2691 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2694 DEFUN (default_vrf_vni_mapping
,
2695 default_vrf_vni_mapping_cmd
,
2696 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2697 "VNI corresponding to the DEFAULT VRF\n"
2699 "Prefix routes only \n")
2701 char xpath
[XPATH_MAXLEN
];
2702 struct zebra_vrf
*zvrf
= NULL
;
2705 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2712 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2714 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2716 snprintf(xpath
, sizeof(xpath
),
2717 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2719 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2722 snprintf(xpath
, sizeof(xpath
),
2723 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2725 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2728 return nb_cli_apply_changes(vty
, NULL
);
2731 DEFUN (no_default_vrf_vni_mapping
,
2732 no_default_vrf_vni_mapping_cmd
,
2733 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2735 "VNI corresponding to DEFAULT VRF\n"
2737 "Prefix routes only \n")
2739 char xpath
[XPATH_MAXLEN
];
2741 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2742 struct zebra_vrf
*zvrf
= NULL
;
2744 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2751 if (zvrf
->l3vni
!= vni
) {
2752 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2757 snprintf(xpath
, sizeof(xpath
),
2758 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2760 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2763 snprintf(xpath
, sizeof(xpath
),
2764 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2766 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2769 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2771 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2773 return nb_cli_apply_changes(vty
, NULL
);
2776 DEFUN (vrf_vni_mapping
,
2777 vrf_vni_mapping_cmd
,
2778 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2779 "VNI corresponding to tenant VRF\n"
2781 "prefix-routes-only\n")
2785 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2793 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2794 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2798 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2799 NB_OP_MODIFY
, "true");
2801 return nb_cli_apply_changes(vty
, NULL
);
2804 DEFUN (no_vrf_vni_mapping
,
2805 no_vrf_vni_mapping_cmd
,
2806 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2808 "VNI corresponding to tenant VRF\n"
2810 "prefix-routes-only\n")
2814 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2815 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2823 if (zvrf
->l3vni
!= vni
) {
2824 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2829 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2833 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2834 NB_OP_DESTROY
, "true");
2836 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2838 return nb_cli_apply_changes(vty
, NULL
);
2842 DEFPY (show_vrf_vni
,
2844 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2846 VRF_FULL_CMD_HELP_STR
2851 struct zebra_vrf
*zvrf
;
2852 json_object
*json
= NULL
;
2853 json_object
*json_vrfs
= NULL
;
2854 bool uj
= use_json(argc
, argv
);
2855 bool use_vrf
= false;
2858 json
= json_object_new_object();
2860 /* show vrf vni used to display across all vrfs
2861 * This is enhanced to support only for specific
2864 if (vrf_all
|| !vrf_name
) {
2865 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2876 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2877 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2880 json_vrfs
= json_object_new_array();
2883 vty_json(vty
, json
);
2885 vty_out(vty
, "%% VRF does not exist\n");
2892 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2897 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2899 } else if (vrf_name
) {
2900 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2903 vty_json(vty
, json
);
2906 "%% VRF '%s' specified does not exist\n",
2913 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2914 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2917 json_vrfs
= json_object_new_array();
2919 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2923 json_object_object_add(json
, "vrfs", json_vrfs
);
2924 vty_json(vty
, json
);
2930 DEFUN (show_evpn_global
,
2931 show_evpn_global_cmd
,
2937 bool uj
= use_json(argc
, argv
);
2939 zebra_vxlan_print_evpn(vty
, uj
);
2943 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2944 SHOW_STR IP_STR
"neighbors\n")
2947 zebra_neigh_show(vty
);
2952 DEFPY(show_evpn_l2_nh
,
2953 show_evpn_l2_nh_cmd
,
2954 "show evpn l2-nh [json$json]",
2962 zebra_evpn_l2_nh_show(vty
, uj
);
2969 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2972 "Ethernet Segment\n"
2974 "Detailed information\n"
2981 if (!str_to_esi(esi_str
, &esi
)) {
2982 vty_out(vty
, "%% Malformed ESI\n");
2985 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2988 zebra_evpn_es_show_detail(vty
, uj
);
2990 zebra_evpn_es_show(vty
, uj
);
2996 DEFPY(show_evpn_es_evi
,
2997 show_evpn_es_evi_cmd
,
2998 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3001 "Ethernet Segment per EVI\n"
3002 "VxLAN Network Identifier\n"
3004 "Detailed information\n"
3011 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3013 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3018 DEFPY(show_evpn_access_vlan
,
3019 show_evpn_access_vlan_cmd
,
3020 "show evpn access-vlan [(1-4094)$vid | detail$detail] [json$json]",
3025 "Detailed information\n"
3031 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
);
3034 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3036 zebra_evpn_acc_vl_show(vty
, uj
);
3042 DEFUN (show_evpn_vni
,
3044 "show evpn vni [json]",
3047 "VxLAN Network Identifier\n"
3050 struct zebra_vrf
*zvrf
;
3051 bool uj
= use_json(argc
, argv
);
3053 zvrf
= zebra_vrf_get_evpn();
3054 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3058 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3059 "show evpn vni detail [json]",
3062 "VxLAN Network Identifier\n"
3063 "Detailed Information On Each VNI\n"
3066 struct zebra_vrf
*zvrf
;
3067 bool uj
= use_json(argc
, argv
);
3069 zvrf
= zebra_vrf_get_evpn();
3070 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3074 DEFUN (show_evpn_vni_vni
,
3075 show_evpn_vni_vni_cmd
,
3076 "show evpn vni " CMD_VNI_RANGE
"[json]",
3079 "VxLAN Network Identifier\n"
3083 struct zebra_vrf
*zvrf
;
3085 bool uj
= use_json(argc
, argv
);
3087 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3088 zvrf
= zebra_vrf_get_evpn();
3089 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3093 DEFUN (show_evpn_rmac_vni_mac
,
3094 show_evpn_rmac_vni_mac_cmd
,
3095 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3102 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3107 bool uj
= use_json(argc
, argv
);
3109 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3110 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3111 vty_out(vty
, "%% Malformed MAC address\n");
3114 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3118 DEFUN (show_evpn_rmac_vni
,
3119 show_evpn_rmac_vni_cmd
,
3120 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3129 bool uj
= use_json(argc
, argv
);
3131 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3132 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3137 DEFUN (show_evpn_rmac_vni_all
,
3138 show_evpn_rmac_vni_all_cmd
,
3139 "show evpn rmac vni all [json]",
3147 bool uj
= use_json(argc
, argv
);
3149 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3154 DEFUN (show_evpn_nh_vni_ip
,
3155 show_evpn_nh_vni_ip_cmd
,
3156 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3163 "Host address (ipv4 or ipv6)\n"
3168 bool uj
= use_json(argc
, argv
);
3170 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3171 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3173 vty_out(vty
, "%% Malformed Neighbor address\n");
3176 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3181 DEFUN (show_evpn_nh_vni
,
3182 show_evpn_nh_vni_cmd
,
3183 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3192 bool uj
= use_json(argc
, argv
);
3194 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3195 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3200 DEFUN (show_evpn_nh_vni_all
,
3201 show_evpn_nh_vni_all_cmd
,
3202 "show evpn next-hops vni all [json]",
3210 bool uj
= use_json(argc
, argv
);
3212 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3217 DEFUN (show_evpn_mac_vni
,
3218 show_evpn_mac_vni_cmd
,
3219 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3223 "VxLAN Network Identifier\n"
3227 struct zebra_vrf
*zvrf
;
3229 bool uj
= use_json(argc
, argv
);
3231 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3232 zvrf
= zebra_vrf_get_evpn();
3233 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3237 DEFPY (show_evpn_mac_vni_detail
,
3238 show_evpn_mac_vni_detail_cmd
,
3239 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3243 "VXLAN Network Identifier\n"
3245 "Detailed Information On Each VNI MAC\n"
3248 struct zebra_vrf
*zvrf
;
3249 bool uj
= use_json(argc
, argv
);
3251 zvrf
= zebra_vrf_get_evpn();
3252 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3256 DEFUN (show_evpn_mac_vni_all
,
3257 show_evpn_mac_vni_all_cmd
,
3258 "show evpn mac vni all [json]",
3262 "VxLAN Network Identifier\n"
3266 struct zebra_vrf
*zvrf
;
3267 bool uj
= use_json(argc
, argv
);
3269 zvrf
= zebra_vrf_get_evpn();
3270 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3274 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3275 "show evpn mac vni all detail [json]",
3279 "VxLAN Network Identifier\n"
3281 "Detailed Information On Each VNI MAC\n"
3284 struct zebra_vrf
*zvrf
;
3285 bool uj
= use_json(argc
, argv
);
3287 zvrf
= zebra_vrf_get_evpn();
3288 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3292 DEFUN (show_evpn_mac_vni_all_vtep
,
3293 show_evpn_mac_vni_all_vtep_cmd
,
3294 "show evpn mac vni all vtep A.B.C.D [json]",
3298 "VxLAN Network Identifier\n"
3301 "Remote VTEP IP address\n"
3304 struct zebra_vrf
*zvrf
;
3305 struct in_addr vtep_ip
;
3306 bool uj
= use_json(argc
, argv
);
3308 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3310 vty_out(vty
, "%% Malformed VTEP IP address\n");
3313 zvrf
= zebra_vrf_get_evpn();
3314 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3320 DEFUN (show_evpn_mac_vni_mac
,
3321 show_evpn_mac_vni_mac_cmd
,
3322 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3326 "VxLAN Network Identifier\n"
3329 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3333 struct zebra_vrf
*zvrf
;
3336 bool uj
= use_json(argc
, argv
);
3338 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3339 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3340 vty_out(vty
, "%% Malformed MAC address\n");
3343 zvrf
= zebra_vrf_get_evpn();
3344 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3348 DEFUN (show_evpn_mac_vni_vtep
,
3349 show_evpn_mac_vni_vtep_cmd
,
3350 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3354 "VxLAN Network Identifier\n"
3357 "Remote VTEP IP address\n"
3360 struct zebra_vrf
*zvrf
;
3362 struct in_addr vtep_ip
;
3363 bool uj
= use_json(argc
, argv
);
3365 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3366 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3368 vty_out(vty
, "%% Malformed VTEP IP address\n");
3372 zvrf
= zebra_vrf_get_evpn();
3373 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3377 DEFPY (show_evpn_mac_vni_all_dad
,
3378 show_evpn_mac_vni_all_dad_cmd
,
3379 "show evpn mac vni all duplicate [json]",
3383 "VxLAN Network Identifier\n"
3385 "Duplicate address list\n"
3388 struct zebra_vrf
*zvrf
;
3389 bool uj
= use_json(argc
, argv
);
3391 zvrf
= zebra_vrf_get_evpn();
3392 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3397 DEFPY (show_evpn_mac_vni_dad
,
3398 show_evpn_mac_vni_dad_cmd
,
3399 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3403 "VxLAN Network Identifier\n"
3405 "Duplicate address list\n"
3408 struct zebra_vrf
*zvrf
;
3409 bool uj
= use_json(argc
, argv
);
3411 zvrf
= zebra_vrf_get_evpn();
3413 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3418 DEFPY (show_evpn_neigh_vni_dad
,
3419 show_evpn_neigh_vni_dad_cmd
,
3420 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3423 "ARP and ND cache\n"
3424 "VxLAN Network Identifier\n"
3426 "Duplicate address list\n"
3429 struct zebra_vrf
*zvrf
;
3430 bool uj
= use_json(argc
, argv
);
3432 zvrf
= zebra_vrf_get_evpn();
3433 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3437 DEFPY (show_evpn_neigh_vni_all_dad
,
3438 show_evpn_neigh_vni_all_dad_cmd
,
3439 "show evpn arp-cache vni all duplicate [json]",
3442 "ARP and ND cache\n"
3443 "VxLAN Network Identifier\n"
3445 "Duplicate address list\n"
3448 struct zebra_vrf
*zvrf
;
3449 bool uj
= use_json(argc
, argv
);
3451 zvrf
= zebra_vrf_get_evpn();
3452 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3457 DEFUN (show_evpn_neigh_vni
,
3458 show_evpn_neigh_vni_cmd
,
3459 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3462 "ARP and ND cache\n"
3463 "VxLAN Network Identifier\n"
3467 struct zebra_vrf
*zvrf
;
3469 bool uj
= use_json(argc
, argv
);
3471 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3472 zvrf
= zebra_vrf_get_evpn();
3473 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3477 DEFUN (show_evpn_neigh_vni_all
,
3478 show_evpn_neigh_vni_all_cmd
,
3479 "show evpn arp-cache vni all [json]",
3482 "ARP and ND cache\n"
3483 "VxLAN Network Identifier\n"
3487 struct zebra_vrf
*zvrf
;
3488 bool uj
= use_json(argc
, argv
);
3490 zvrf
= zebra_vrf_get_evpn();
3491 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3495 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3496 "show evpn arp-cache vni all detail [json]",
3499 "ARP and ND cache\n"
3500 "VxLAN Network Identifier\n"
3502 "Neighbor details for all vnis in detail\n" JSON_STR
)
3504 struct zebra_vrf
*zvrf
;
3505 bool uj
= use_json(argc
, argv
);
3507 zvrf
= zebra_vrf_get_evpn();
3508 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3512 DEFUN (show_evpn_neigh_vni_neigh
,
3513 show_evpn_neigh_vni_neigh_cmd
,
3514 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3517 "ARP and ND cache\n"
3518 "VxLAN Network Identifier\n"
3521 "Neighbor address (IPv4 or IPv6 address)\n"
3524 struct zebra_vrf
*zvrf
;
3527 bool uj
= use_json(argc
, argv
);
3529 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3530 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3532 vty_out(vty
, "%% Malformed Neighbor address\n");
3535 zvrf
= zebra_vrf_get_evpn();
3536 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3540 DEFUN (show_evpn_neigh_vni_vtep
,
3541 show_evpn_neigh_vni_vtep_cmd
,
3542 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3545 "ARP and ND cache\n"
3546 "VxLAN Network Identifier\n"
3549 "Remote VTEP IP address\n"
3552 struct zebra_vrf
*zvrf
;
3554 struct in_addr vtep_ip
;
3555 bool uj
= use_json(argc
, argv
);
3557 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3558 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3560 vty_out(vty
, "%% Malformed VTEP IP address\n");
3564 zvrf
= zebra_vrf_get_evpn();
3565 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3569 /* policy routing contexts */
3570 DEFUN (show_pbr_ipset
,
3572 "show pbr ipset [WORD]",
3574 "Policy-Based Routing\n"
3575 "IPset Context information\n"
3576 "IPset Name information\n")
3580 found
= argv_find(argv
, argc
, "WORD", &idx
);
3582 zebra_pbr_show_ipset_list(vty
, NULL
);
3584 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3588 /* policy routing contexts */
3589 DEFUN (show_pbr_iptable
,
3590 show_pbr_iptable_cmd
,
3591 "show pbr iptable [WORD]",
3593 "Policy-Based Routing\n"
3594 "IPtable Context information\n"
3595 "IPtable Name information\n")
3600 found
= argv_find(argv
, argc
, "WORD", &idx
);
3602 zebra_pbr_show_iptable(vty
, NULL
);
3604 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3608 /* policy routing contexts */
3609 DEFPY (show_pbr_rule
,
3613 "Policy-Based Routing\n"
3616 zebra_pbr_show_rule(vty
);
3620 DEFPY (pbr_nexthop_resolve
,
3621 pbr_nexthop_resolve_cmd
,
3622 "[no$no] pbr nexthop-resolve",
3624 "Policy Based Routing\n"
3625 "Resolve nexthop for dataplane programming\n")
3627 zebra_pbr_expand_action_update(!no
);
3631 DEFPY (clear_evpn_dup_addr
,
3632 clear_evpn_dup_addr_cmd
,
3633 "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>]>",
3636 "Duplicate address \n"
3637 "VxLAN Network Identifier\n"
3641 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3646 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3647 int ret
= CMD_SUCCESS
;
3649 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3650 *yang_dup_mac
= NULL
;
3655 yang_dup
= yang_data_new(
3656 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3659 yang_dup
= yang_data_new_uint32(
3660 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3662 if (!is_zero_mac(&mac
->eth_addr
)) {
3663 yang_dup_mac
= yang_data_new_mac(
3664 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3667 listnode_add(input
, yang_dup_mac
);
3669 if (sockunion_family(ip
) == AF_INET
) {
3670 host_ip
.ipa_type
= IPADDR_V4
;
3671 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3673 host_ip
.ipa_type
= IPADDR_V6
;
3674 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3675 sizeof(struct in6_addr
));
3678 yang_dup_ip
= yang_data_new_ip(
3679 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3683 listnode_add(input
, yang_dup_ip
);
3688 listnode_add(input
, yang_dup
);
3689 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3693 list_delete(&input
);
3698 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3699 evpn_accept_bgp_seq_cmd
,
3700 "evpn accept-bgp-seq",
3702 "Accept all sequence numbers from BGP\n")
3704 zebra_vxlan_set_accept_bgp_seq(true);
3708 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3709 no_evpn_accept_bgp_seq_cmd
,
3710 "no evpn accept-bgp-seq",
3713 "Accept all sequence numbers from BGP\n")
3715 zebra_vxlan_set_accept_bgp_seq(false);
3719 /* Static ip route configuration write function. */
3720 static int zebra_ip_config(struct vty
*vty
)
3724 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3729 DEFUN (ip_zebra_import_table_distance
,
3730 ip_zebra_import_table_distance_cmd
,
3731 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3733 "import routes from non-main kernel table\n"
3734 "kernel routing table id\n"
3735 "Distance for imported routes\n"
3736 "Default distance value\n"
3737 "route-map for filtering\n"
3740 uint32_t table_id
= 0;
3742 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3743 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3745 strmatch(argv
[argc
- 2]->text
, "route-map")
3746 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3750 if (argc
== 7 || (argc
== 5 && !rmap
))
3751 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3753 if (!is_zebra_valid_kernel_table(table_id
)) {
3755 "Invalid routing table ID, %d. Must be in range 1-252\n",
3758 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3762 if (is_zebra_main_routing_table(table_id
)) {
3764 "Invalid routing table ID, %d. Must be non-default table\n",
3767 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3771 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3774 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3779 DEFUN_HIDDEN (zebra_packet_process
,
3780 zebra_packet_process_cmd
,
3781 "zebra zapi-packets (1-10000)",
3784 "Number of packets to process before relinquishing thread\n")
3786 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3788 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3789 memory_order_relaxed
);
3794 DEFUN_HIDDEN (no_zebra_packet_process
,
3795 no_zebra_packet_process_cmd
,
3796 "no zebra zapi-packets [(1-10000)]",
3800 "Number of packets to process before relinquishing thread\n")
3802 atomic_store_explicit(&zrouter
.packets_to_process
,
3803 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3804 memory_order_relaxed
);
3809 DEFUN_HIDDEN (zebra_workqueue_timer
,
3810 zebra_workqueue_timer_cmd
,
3811 "zebra work-queue (0-10000)",
3814 "Time in milliseconds\n")
3816 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3817 zrouter
.ribq
->spec
.hold
= timer
;
3822 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3823 no_zebra_workqueue_timer_cmd
,
3824 "no zebra work-queue [(0-10000)]",
3828 "Time in milliseconds\n")
3830 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3835 DEFUN (no_ip_zebra_import_table
,
3836 no_ip_zebra_import_table_cmd
,
3837 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3840 "import routes from non-main kernel table\n"
3841 "kernel routing table id\n"
3842 "Distance for imported routes\n"
3843 "Default distance value\n"
3844 "route-map for filtering\n"
3847 uint32_t table_id
= 0;
3848 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3850 if (!is_zebra_valid_kernel_table(table_id
)) {
3852 "Invalid routing table ID. Must be in range 1-252\n");
3856 if (is_zebra_main_routing_table(table_id
)) {
3858 "Invalid routing table ID, %d. Must be non-default table\n",
3863 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3866 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3869 DEFPY (zebra_nexthop_group_keep
,
3870 zebra_nexthop_group_keep_cmd
,
3871 "[no] zebra nexthop-group keep (1-3600)",
3875 "How long to keep\n"
3876 "Time in seconds from 1-3600\n")
3879 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3881 zrouter
.nhg_keep
= keep
;
3886 static int config_write_protocol(struct vty
*vty
)
3888 if (zrouter
.allow_delete
)
3889 vty_out(vty
, "allow-external-route-update\n");
3891 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3892 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3894 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3895 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3897 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3898 vty_out(vty
, "zebra zapi-packets %u\n",
3899 zrouter
.packets_to_process
);
3901 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3903 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3904 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3905 ipv4_multicast_mode
== MCAST_URIB_ONLY
3907 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3909 : ipv4_multicast_mode
3910 == MCAST_MIX_MRIB_FIRST
3912 : ipv4_multicast_mode
3913 == MCAST_MIX_DISTANCE
3917 /* Include dataplane info */
3918 dplane_config_write_helper(vty
);
3920 zebra_evpn_mh_config_write(vty
);
3922 zebra_pbr_config_write(vty
);
3924 if (!zebra_vxlan_get_accept_bgp_seq())
3925 vty_out(vty
, "no evpn accept-bgp-seq\n");
3927 /* Include nexthop-group config */
3928 if (!zebra_nhg_kernel_nexthops_enabled())
3929 vty_out(vty
, "no zebra nexthop kernel enable\n");
3931 if (zebra_nhg_proto_nexthops_only())
3932 vty_out(vty
, "zebra nexthop proto only\n");
3934 if (!zebra_nhg_recursive_use_backups())
3935 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3937 if (rnh_get_hide_backups())
3938 vty_out(vty
, "ip nht hide-backup-events\n");
3941 /* Include netlink info */
3942 netlink_config_write_helper(vty
);
3943 #endif /* HAVE_NETLINK */
3955 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
3958 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
3959 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
3960 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
3961 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
3962 ttable_add_row(table
, "v6 Forwarding|%s",
3963 ipforward_ipv6() ? "On" : "Off");
3964 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
3965 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
3966 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
3970 if (!vrf_is_backend_netns())
3971 ttable_add_row(table
, "VRF|l3mdev Available");
3973 ttable_add_row(table
, "VRF|Namespaces");
3975 ttable_add_row(table
, "VRF|Not Available");
3978 ttable_add_row(table
, "ASIC offload|%s",
3979 zrouter
.asic_offloaded
? "Used" : "Unavailable");
3982 * Do not display this unless someone is actually using it
3984 * Why this distinction? I think this is effectively dead code
3985 * and should not be exposed. Maybe someone proves me wrong.
3987 if (zrouter
.asic_notification_nexthop_control
)
3988 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
3990 ttable_add_row(table
, "RA|%s",
3991 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
3992 ttable_add_row(table
, "RFC 5549|%s",
3993 rtadv_get_interfaces_configured_from_bgp()
3995 : "BGP is not using");
3997 ttable_add_row(table
, "Kernel NHG|%s",
3998 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4000 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4001 zrouter
.allow_delete
? "Yes" : "No");
4002 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4003 zrouter
.all_linkdownv4
? "On" : "Off");
4004 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4005 zrouter
.default_linkdownv4
? "On" : "Off");
4006 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4007 zrouter
.all_linkdownv6
? "On" : "Off");
4008 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4009 zrouter
.default_linkdownv6
? "On" : "Off");
4011 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4012 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4013 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4014 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4015 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4016 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4017 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4018 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4020 out
= ttable_dump(table
, "\n");
4021 vty_out(vty
, "%s\n", out
);
4022 XFREE(MTYPE_TMP
, out
);
4026 " Route Route Neighbor LSP LSP\n");
4028 "VRF Installs Removals Updates Installs Removals\n");
4030 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4031 struct zebra_vrf
*zvrf
= vrf
->info
;
4033 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4034 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4035 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4036 zvrf
->lsp_removals
);
4042 DEFUN (ip_forwarding
,
4046 "Turn on IP forwarding\n")
4052 ret
= ipforward_on();
4055 vty_out(vty
, "Can't turn on IP forwarding\n");
4056 return CMD_WARNING_CONFIG_FAILED
;
4062 DEFUN (no_ip_forwarding
,
4063 no_ip_forwarding_cmd
,
4067 "Turn off IP forwarding\n")
4073 ret
= ipforward_off();
4076 vty_out(vty
, "Can't turn off IP forwarding\n");
4077 return CMD_WARNING_CONFIG_FAILED
;
4083 /* Only display ip forwarding is enabled or not. */
4084 DEFUN (show_ip_forwarding
,
4085 show_ip_forwarding_cmd
,
4086 "show ip forwarding",
4089 "IP forwarding status\n")
4096 vty_out(vty
, "IP forwarding is off\n");
4098 vty_out(vty
, "IP forwarding is on\n");
4102 /* Only display ipv6 forwarding is enabled or not. */
4103 DEFUN (show_ipv6_forwarding
,
4104 show_ipv6_forwarding_cmd
,
4105 "show ipv6 forwarding",
4107 "IPv6 information\n"
4108 "Forwarding status\n")
4112 ret
= ipforward_ipv6();
4116 vty_out(vty
, "ipv6 forwarding is unknown\n");
4119 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4122 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4125 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4131 DEFUN (ipv6_forwarding
,
4132 ipv6_forwarding_cmd
,
4135 "Turn on IPv6 forwarding\n")
4139 ret
= ipforward_ipv6();
4141 ret
= ipforward_ipv6_on();
4144 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4145 return CMD_WARNING_CONFIG_FAILED
;
4151 DEFUN (no_ipv6_forwarding
,
4152 no_ipv6_forwarding_cmd
,
4153 "no ipv6 forwarding",
4156 "Turn off IPv6 forwarding\n")
4160 ret
= ipforward_ipv6();
4162 ret
= ipforward_ipv6_off();
4165 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4166 return CMD_WARNING_CONFIG_FAILED
;
4172 /* Display dataplane info */
4173 DEFUN (show_dataplane
,
4175 "show zebra dplane [detailed]",
4178 "Zebra dataplane information\n"
4179 "Detailed output\n")
4182 bool detailed
= false;
4184 if (argv_find(argv
, argc
, "detailed", &idx
))
4187 return dplane_show_helper(vty
, detailed
);
4190 /* Display dataplane providers info */
4191 DEFUN (show_dataplane_providers
,
4192 show_dataplane_providers_cmd
,
4193 "show zebra dplane providers [detailed]",
4196 "Zebra dataplane information\n"
4197 "Zebra dataplane provider information\n"
4198 "Detailed output\n")
4201 bool detailed
= false;
4203 if (argv_find(argv
, argc
, "detailed", &idx
))
4206 return dplane_show_provs_helper(vty
, detailed
);
4209 /* Configure dataplane incoming queue limit */
4210 DEFUN (zebra_dplane_queue_limit
,
4211 zebra_dplane_queue_limit_cmd
,
4212 "zebra dplane limit (0-10000)",
4215 "Limit incoming queued updates\n"
4216 "Number of queued updates\n")
4220 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4222 dplane_set_in_queue_limit(limit
, true);
4227 /* Reset dataplane queue limit to default value */
4228 DEFUN (no_zebra_dplane_queue_limit
,
4229 no_zebra_dplane_queue_limit_cmd
,
4230 "no zebra dplane limit [(0-10000)]",
4234 "Limit incoming queued updates\n"
4235 "Number of queued updates\n")
4237 dplane_set_in_queue_limit(0, false);
4242 DEFUN (zebra_show_routing_tables_summary
,
4243 zebra_show_routing_tables_summary_cmd
,
4244 "show zebra router table summary",
4247 "The Zebra Router Information\n"
4248 "Table Information about this Zebra Router\n"
4249 "Summary Information\n")
4251 zebra_router_show_table_summary(vty
);
4256 /* Table configuration write function. */
4257 static int config_write_table(struct vty
*vty
)
4262 /* IPForwarding configuration write function. */
4263 static int config_write_forwarding(struct vty
*vty
)
4266 vty_out(vty
, "no ip forwarding\n");
4267 if (!ipforward_ipv6())
4268 vty_out(vty
, "no ipv6 forwarding\n");
4269 vty_out(vty
, "!\n");
4273 DEFUN_HIDDEN (show_frr
,
4279 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4280 vty_out(vty
, ".............................7777:..............................................\n");
4281 vty_out(vty
, ".............................777777,............................................\n");
4282 vty_out(vty
, "... .........................77777777,..........................................\n");
4283 vty_out(vty
, "............................=7777777777:........................................\n");
4284 vty_out(vty
, "........................:7777777777777777,......................................\n");
4285 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4286 vty_out(vty
, "...................I7777777777+.................................................\n");
4287 vty_out(vty
, "................,777777777?............ .......................................\n");
4288 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4289 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4290 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4291 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4292 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4293 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4294 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4295 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4296 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4297 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4298 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4299 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4300 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4301 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4302 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4303 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4304 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4305 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4306 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4307 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4308 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4309 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4310 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4311 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4312 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4313 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4314 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4315 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4316 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4317 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4318 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4319 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4320 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4321 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4322 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4323 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4324 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4325 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4326 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4327 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4328 vty_out(vty
, "................................~77777777...............=777777.................\n");
4329 vty_out(vty
, ".....................................:=?I................~777777................\n");
4330 vty_out(vty
, "..........................................................:777777,..............\n");
4331 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4337 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4338 zebra_kernel_netlink_batch_tx_buf_cmd
,
4339 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4341 "Zebra kernel interface\n"
4342 "Set Netlink parameters\n"
4343 "Set batch buffer size and send threshold\n"
4344 "Size of the buffer\n"
4347 uint32_t bufsize
= 0, threshold
= 0;
4349 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4350 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4352 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4357 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4358 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4359 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4361 "Zebra kernel interface\n"
4362 "Set Netlink parameters\n"
4363 "Set batch buffer size and send threshold\n"
4364 "Size of the buffer\n"
4367 netlink_set_batch_buffer_size(0, 0, false);
4372 DEFPY (zebra_protodown_bit
,
4373 zebra_protodown_bit_cmd
,
4374 "zebra protodown reason-bit (0-31)$bit",
4376 "Protodown Configuration\n"
4377 "Reason Bit used in the kernel for application\n"
4378 "Reason Bit range\n")
4380 if_netlink_set_frr_protodown_r_bit(bit
);
4384 DEFPY (no_zebra_protodown_bit
,
4385 no_zebra_protodown_bit_cmd
,
4386 "no zebra protodown reason-bit [(0-31)$bit]",
4389 "Protodown Configuration\n"
4390 "Reason Bit used in the kernel for setting protodown\n"
4391 "Reason Bit Range\n")
4393 if_netlink_unset_frr_protodown_r_bit();
4397 #endif /* HAVE_NETLINK */
4399 DEFUN(ip_table_range
, ip_table_range_cmd
,
4400 "[no] ip table range (1-4294967295) (1-4294967295)",
4402 "table configuration\n"
4403 "Configure table range\n"
4404 "Start Routing Table\n"
4405 "End Routing Table\n")
4407 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4412 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4414 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4418 if (strmatch(argv
[0]->text
, "no"))
4419 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4421 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4424 #ifdef HAVE_SCRIPTING
4426 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4427 "zebra on-rib-process script SCRIPT",
4429 "on_rib_process_dplane_results hook call\n"
4431 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4434 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4437 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4438 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4440 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4441 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4446 #endif /* HAVE_SCRIPTING */
4448 /* IP node for static routes. */
4449 static int zebra_ip_config(struct vty
*vty
);
4450 static struct cmd_node ip_node
= {
4451 .name
= "static ip",
4454 .config_write
= zebra_ip_config
,
4456 static int config_write_protocol(struct vty
*vty
);
4457 static struct cmd_node protocol_node
= {
4459 .node
= PROTOCOL_NODE
,
4461 .config_write
= config_write_protocol
,
4463 /* table node for routing tables. */
4464 static int config_write_table(struct vty
*vty
);
4465 static struct cmd_node table_node
= {
4469 .config_write
= config_write_table
,
4471 static int config_write_forwarding(struct vty
*vty
);
4472 static struct cmd_node forwarding_node
= {
4473 .name
= "forwarding",
4474 .node
= FORWARDING_NODE
,
4476 .config_write
= config_write_forwarding
,
4480 void zebra_vty_init(void)
4482 /* Install configuration write function. */
4483 install_node(&table_node
);
4484 install_node(&forwarding_node
);
4486 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4487 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4488 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4489 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4491 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4492 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4493 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4496 zebra_route_map_init();
4498 install_node(&ip_node
);
4499 install_node(&protocol_node
);
4501 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4502 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4504 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4505 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4507 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4508 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4509 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4510 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4511 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4512 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4513 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4514 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4515 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4516 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4518 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4519 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4521 install_element(VIEW_NODE
, &show_vrf_cmd
);
4522 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4523 install_element(VIEW_NODE
, &show_route_cmd
);
4524 install_element(VIEW_NODE
, &show_ro_cmd
);
4525 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4526 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4527 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4529 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4530 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4532 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4533 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4534 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4535 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4536 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4537 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4538 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4539 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4540 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4542 install_element(VIEW_NODE
, &show_frr_cmd
);
4543 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4544 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4545 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4546 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4547 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4548 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4549 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4550 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4551 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4552 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4553 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4554 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4555 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4556 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4557 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4558 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4559 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4560 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4561 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4562 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4563 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4564 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4565 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4566 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4567 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4568 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4569 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4570 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4571 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4572 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4573 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4574 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4575 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4577 install_element(VIEW_NODE
, &show_neigh_cmd
);
4579 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4580 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4581 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4582 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4583 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4585 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4586 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4587 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4588 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4589 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4590 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4591 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4592 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4594 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4595 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4596 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4597 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4599 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4600 install_element(VRF_NODE
, &ip_table_range_cmd
);
4603 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4604 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4605 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4606 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4607 #endif /* HAVE_NETLINK */
4609 #ifdef HAVE_SCRIPTING
4610 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4611 #endif /* HAVE_SCRIPTING */
4613 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);