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",
408 case NEXTHOP_TYPE_IFINDEX
:
409 case NEXTHOP_TYPE_BLACKHOLE
:
414 vty_out(vty
, ", mtu %u", re
->nexthop_mtu
);
416 /* Label information */
417 if (nexthop
->nh_label
&& nexthop
->nh_label
->num_labels
) {
418 vty_out(vty
, ", label %s",
419 mpls_label2str(nexthop
->nh_label
->num_labels
,
420 nexthop
->nh_label
->label
, buf
,
421 sizeof(buf
), nexthop
->nh_label_type
,
426 vty_out(vty
, ", weight %u", nexthop
->weight
);
428 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
)) {
429 vty_out(vty
, ", backup %d", nexthop
->backup_idx
[0]);
431 for (i
= 1; i
< nexthop
->backup_num
; i
++)
432 vty_out(vty
, ",%d", nexthop
->backup_idx
[i
]);
436 static void zebra_show_ip_route_opaque(struct vty
*vty
, struct route_entry
*re
,
437 struct json_object
*json
)
439 struct bgp_zebra_opaque bzo
= {};
440 struct ospf_zebra_opaque ozo
= {};
446 case ZEBRA_ROUTE_SHARP
:
448 json_object_string_add(json
, "opaque",
449 (char *)re
->opaque
->data
);
451 vty_out(vty
, " Opaque Data: %s",
452 (char *)re
->opaque
->data
);
455 case ZEBRA_ROUTE_BGP
:
456 memcpy(&bzo
, re
->opaque
->data
, re
->opaque
->length
);
459 json_object_string_add(json
, "asPath", bzo
.aspath
);
460 json_object_string_add(json
, "communities",
462 json_object_string_add(json
, "largeCommunities",
464 json_object_string_add(json
, "selectionReason",
465 bzo
.selection_reason
);
467 vty_out(vty
, " AS-Path : %s\n", bzo
.aspath
);
469 if (bzo
.community
[0] != '\0')
470 vty_out(vty
, " Communities : %s\n",
473 if (bzo
.lcommunity
[0] != '\0')
474 vty_out(vty
, " Large-Communities: %s\n",
477 vty_out(vty
, " Selection reason : %s\n",
478 bzo
.selection_reason
);
481 case ZEBRA_ROUTE_OSPF
:
482 case ZEBRA_ROUTE_OSPF6
:
483 memcpy(&ozo
, re
->opaque
->data
, re
->opaque
->length
);
486 json_object_string_add(json
, "ospfPathType",
488 if (ozo
.area_id
[0] != '\0')
489 json_object_string_add(json
, "ospfAreaId",
491 if (ozo
.tag
[0] != '\0')
492 json_object_string_add(json
, "ospfTag",
495 vty_out(vty
, " OSPF path type : %s\n",
497 if (ozo
.area_id
[0] != '\0')
498 vty_out(vty
, " OSPF area ID : %s\n",
500 if (ozo
.tag
[0] != '\0')
501 vty_out(vty
, " OSPF tag : %s\n",
510 static void uptime2str(time_t uptime
, char *buf
, size_t bufsize
)
514 cur
= monotime(NULL
);
517 frrtime_to_interval(cur
, buf
, bufsize
);
520 /* New RIB. Detailed information for IPv4 route. */
521 static void vty_show_ip_route_detail(struct vty
*vty
, struct route_node
*rn
,
522 int mcast
, bool use_fib
, bool show_ng
)
524 struct route_entry
*re
;
525 struct nexthop
*nexthop
;
526 char buf
[SRCDEST2STR_BUFFER
];
527 struct zebra_vrf
*zvrf
;
530 dest
= rib_dest_from_rnode(rn
);
532 RNODE_FOREACH_RE (rn
, re
) {
534 * If re not selected for forwarding, skip re
535 * for "show ip/ipv6 fib <prefix>"
537 if (use_fib
&& re
!= dest
->selected_fib
)
540 const char *mcast_info
= "";
542 struct rib_table_info
*info
=
543 srcdest_rnode_table_info(rn
);
544 mcast_info
= (info
->safi
== SAFI_MULTICAST
)
545 ? " using Multicast RIB"
546 : " using Unicast RIB";
549 vty_out(vty
, "Routing entry for %s%s\n",
550 srcdest_rnode2str(rn
, buf
, sizeof(buf
)), mcast_info
);
551 vty_out(vty
, " Known via \"%s", zebra_route_string(re
->type
));
553 vty_out(vty
, "[%d]", re
->instance
);
555 vty_out(vty
, ", distance %u, metric %u", re
->distance
,
558 vty_out(vty
, ", tag %u", re
->tag
);
559 #if defined(SUPPORT_REALMS)
560 if (re
->tag
> 0 && re
->tag
<= 255)
561 vty_out(vty
, "(realm)");
565 vty_out(vty
, ", mtu %u", re
->mtu
);
566 if (re
->vrf_id
!= VRF_DEFAULT
) {
567 zvrf
= vrf_info_lookup(re
->vrf_id
);
568 vty_out(vty
, ", vrf %s", zvrf_name(zvrf
));
570 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
571 vty_out(vty
, ", best");
574 uptime2str(re
->uptime
, buf
, sizeof(buf
));
576 vty_out(vty
, " Last update %s ago\n", buf
);
579 vty_out(vty
, " Nexthop Group ID: %u\n", re
->nhe_id
);
580 if (re
->nhe_installed_id
!= 0
581 && re
->nhe_id
!= re
->nhe_installed_id
)
583 " Installed Nexthop Group ID: %u\n",
584 re
->nhe_installed_id
);
587 for (ALL_NEXTHOPS(re
->nhe
->nhg
, nexthop
)) {
588 /* Use helper to format each nexthop */
589 show_nexthop_detail_helper(vty
, re
, nexthop
,
590 false /*not backup*/);
593 /* Include backup(s), if present */
594 if (CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_HAS_BACKUP
))
595 show_nh_backup_helper(vty
, re
, nexthop
);
597 zebra_show_ip_route_opaque(vty
, re
, NULL
);
603 static void vty_show_ip_route(struct vty
*vty
, struct route_node
*rn
,
604 struct route_entry
*re
, json_object
*json
,
605 bool is_fib
, bool show_ng
)
607 const struct nexthop
*nexthop
;
609 char buf
[SRCDEST2STR_BUFFER
];
610 json_object
*json_nexthops
= NULL
;
611 json_object
*json_nexthop
= NULL
;
612 json_object
*json_route
= NULL
;
613 const rib_dest_t
*dest
= rib_dest_from_rnode(rn
);
614 const struct nexthop_group
*nhg
;
615 char up_str
[MONOTIME_STRLEN
];
617 bool nhg_from_backup
= false;
619 uptime2str(re
->uptime
, up_str
, sizeof(up_str
));
621 /* If showing fib information, use the fib view of the
625 nhg
= rib_get_fib_nhg(re
);
627 nhg
= &(re
->nhe
->nhg
);
630 json_route
= json_object_new_object();
631 json_nexthops
= json_object_new_array();
633 json_object_string_add(json_route
, "prefix",
634 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
635 json_object_int_add(json_route
, "prefixLen", rn
->p
.prefixlen
);
636 json_object_string_add(json_route
, "protocol",
637 zebra_route_string(re
->type
));
640 json_object_int_add(json_route
, "instance",
643 json_object_int_add(json_route
, "vrfId", re
->vrf_id
);
644 json_object_string_add(json_route
, "vrfName",
645 vrf_id_to_name(re
->vrf_id
));
647 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
))
648 json_object_boolean_true_add(json_route
, "selected");
650 if (dest
->selected_fib
== re
)
651 json_object_boolean_true_add(json_route
,
654 json_object_int_add(json_route
, "distance",
656 json_object_int_add(json_route
, "metric", re
->metric
);
658 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
))
659 json_object_boolean_true_add(json_route
, "installed");
661 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_FAILED
))
662 json_object_boolean_true_add(json_route
, "failed");
664 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_QUEUED
))
665 json_object_boolean_true_add(json_route
, "queued");
667 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
))
668 json_object_boolean_true_add(json_route
, "trapped");
670 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
))
671 json_object_boolean_true_add(json_route
, "offloaded");
673 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOAD_FAILED
))
674 json_object_boolean_false_add(json_route
, "offloaded");
677 json_object_int_add(json_route
, "tag", re
->tag
);
680 json_object_int_add(json_route
, "table", re
->table
);
682 json_object_int_add(json_route
, "internalStatus",
684 json_object_int_add(json_route
, "internalFlags",
686 json_object_int_add(json_route
, "internalNextHopNum",
687 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
688 json_object_int_add(json_route
, "internalNextHopActiveNum",
689 nexthop_group_active_nexthop_num(
691 json_object_int_add(json_route
, "nexthopGroupId", re
->nhe_id
);
693 if (re
->nhe_installed_id
!= 0)
694 json_object_int_add(json_route
,
695 "installedNexthopGroupId",
696 re
->nhe_installed_id
);
698 json_object_string_add(json_route
, "uptime", up_str
);
700 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
701 json_nexthop
= json_object_new_object();
702 show_nexthop_json_helper(json_nexthop
,
705 json_object_array_add(json_nexthops
,
709 json_object_object_add(json_route
, "nexthops", json_nexthops
);
711 /* If there are backup nexthops, include them */
713 nhg
= rib_get_fib_backup_nhg(re
);
715 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
717 if (nhg
&& nhg
->nexthop
) {
718 json_nexthops
= json_object_new_array();
720 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
721 json_nexthop
= json_object_new_object();
723 show_nexthop_json_helper(json_nexthop
,
725 json_object_array_add(json_nexthops
,
729 json_object_object_add(json_route
, "backupNexthops",
732 zebra_show_ip_route_opaque(NULL
, re
, json_route
);
734 json_object_array_add(json
, json_route
);
738 /* Prefix information, and first nexthop. If we're showing 'fib',
739 * and there are no installed primary nexthops, see if there are any
740 * backup nexthops and start with those.
742 if (is_fib
&& nhg
->nexthop
== NULL
) {
743 nhg
= rib_get_fib_backup_nhg(re
);
744 nhg_from_backup
= true;
747 len
= vty_out(vty
, "%c", zebra_route_char(re
->type
));
749 len
+= vty_out(vty
, "[%d]", re
->instance
);
750 if (nhg_from_backup
&& nhg
->nexthop
) {
753 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
754 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
755 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
759 CHECK_FLAG(re
->flags
, ZEBRA_FLAG_SELECTED
) ? '>' : ' ',
760 re_status_output_char(re
, nhg
->nexthop
, is_fib
),
761 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
764 /* Distance and metric display. */
765 if (((re
->type
== ZEBRA_ROUTE_CONNECT
) &&
766 (re
->distance
|| re
->metric
)) ||
767 (re
->type
!= ZEBRA_ROUTE_CONNECT
))
768 len
+= vty_out(vty
, " [%u/%u]", re
->distance
,
772 len
+= vty_out(vty
, " (%u)", re
->nhe_id
);
774 /* Nexthop information. */
775 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
778 } else if (nhg_from_backup
) {
779 vty_out(vty
, " b%c%*c",
780 re_status_output_char(re
, nexthop
, is_fib
),
781 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
783 vty_out(vty
, " %c%*c",
784 re_status_output_char(re
, nexthop
, is_fib
),
785 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
788 show_route_nexthop_helper(vty
, re
, nexthop
);
789 vty_out(vty
, ", %s\n", up_str
);
792 /* If we only had backup nexthops, we're done */
796 /* Check for backup nexthop info if present */
798 nhg
= rib_get_fib_backup_nhg(re
);
800 nhg
= zebra_nhg_get_backup_nhg(re
->nhe
);
805 /* Print backup info */
806 for (ALL_NEXTHOPS_PTR(nhg
, nexthop
)) {
810 star_p
= CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_FIB
);
812 /* TODO -- it'd be nice to be able to include
813 * the entire list of backups, *and* include the
814 * real installation state.
816 vty_out(vty
, " b%c %*c",
817 (star_p
? '*' : ' '),
818 len
- 3 + (2 * nexthop_level(nexthop
)), ' ');
819 show_route_nexthop_helper(vty
, re
, nexthop
);
825 static void vty_show_ip_route_detail_json(struct vty
*vty
,
826 struct route_node
*rn
, bool use_fib
)
828 json_object
*json
= NULL
;
829 json_object
*json_prefix
= NULL
;
830 struct route_entry
*re
;
834 dest
= rib_dest_from_rnode(rn
);
836 json
= json_object_new_object();
837 json_prefix
= json_object_new_array();
839 RNODE_FOREACH_RE (rn
, re
) {
841 * If re not selected for forwarding, skip re
842 * for "show ip/ipv6 fib <prefix> json"
844 if (use_fib
&& re
!= dest
->selected_fib
)
846 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
, false);
849 prefix2str(&rn
->p
, buf
, sizeof(buf
));
850 json_object_object_add(json
, buf
, json_prefix
);
854 static void do_show_route_helper(struct vty
*vty
, struct zebra_vrf
*zvrf
,
855 struct route_table
*table
, afi_t afi
,
856 bool use_fib
, route_tag_t tag
,
857 const struct prefix
*longer_prefix_p
,
858 bool supernets_only
, int type
,
859 unsigned short ospf_instance_id
, bool use_json
,
860 uint32_t tableid
, bool show_ng
,
861 struct route_show_ctx
*ctx
)
863 struct route_node
*rn
;
864 struct route_entry
*re
;
867 json_object
*json
= NULL
;
868 json_object
*json_prefix
= NULL
;
873 * ctx->multi indicates if we are dumping multiple tables or vrfs.
875 * => display the common header at most once
876 * => add newline at each call except first
877 * => always display the VRF and table
879 * => display the common header if at least one entry is found
880 * => display the VRF and table if specific
884 json
= json_object_new_object();
886 /* Show all routes. */
887 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
)) {
888 dest
= rib_dest_from_rnode(rn
);
890 RNODE_FOREACH_RE (rn
, re
) {
891 if (use_fib
&& re
!= dest
->selected_fib
)
894 if (tag
&& re
->tag
!= tag
)
898 && !prefix_match(longer_prefix_p
, &rn
->p
))
901 /* This can only be true when the afi is IPv4 */
902 if (supernets_only
) {
903 addr
= ntohl(rn
->p
.u
.prefix4
.s_addr
);
905 if (IN_CLASSC(addr
) && rn
->p
.prefixlen
>= 24)
908 if (IN_CLASSB(addr
) && rn
->p
.prefixlen
>= 16)
911 if (IN_CLASSA(addr
) && rn
->p
.prefixlen
>= 8)
915 if (type
&& re
->type
!= type
)
919 && (re
->type
!= ZEBRA_ROUTE_OSPF
920 || re
->instance
!= ospf_instance_id
))
925 json_prefix
= json_object_new_array();
927 if (!ctx
->header_done
) {
930 SHOW_ROUTE_V4_HEADER
);
933 SHOW_ROUTE_V6_HEADER
);
935 if (ctx
->multi
&& ctx
->header_done
)
937 if (ctx
->multi
|| zvrf_id(zvrf
) != VRF_DEFAULT
940 vty_out(vty
, "VRF %s:\n",
944 "VRF %s table %u:\n",
948 ctx
->header_done
= true;
952 vty_show_ip_route(vty
, rn
, re
, json_prefix
, use_fib
,
957 prefix2str(&rn
->p
, buf
, sizeof(buf
));
958 json_object_object_add(json
, buf
, json_prefix
);
967 static void do_show_ip_route_all(struct vty
*vty
, struct zebra_vrf
*zvrf
,
968 afi_t afi
, bool use_fib
, bool use_json
,
970 const struct prefix
*longer_prefix_p
,
971 bool supernets_only
, int type
,
972 unsigned short ospf_instance_id
, bool show_ng
,
973 struct route_show_ctx
*ctx
)
975 struct zebra_router_table
*zrt
;
976 struct rib_table_info
*info
;
978 RB_FOREACH (zrt
, zebra_router_table_head
,
980 info
= route_table_get_info(zrt
->table
);
982 if (zvrf
!= info
->zvrf
)
984 if (zrt
->afi
!= afi
||
985 zrt
->safi
!= SAFI_UNICAST
)
988 do_show_ip_route(vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
989 use_fib
, use_json
, tag
, longer_prefix_p
,
990 supernets_only
, type
, ospf_instance_id
,
991 zrt
->tableid
, show_ng
, ctx
);
995 static int do_show_ip_route(struct vty
*vty
, const char *vrf_name
, afi_t afi
,
996 safi_t safi
, bool use_fib
, bool use_json
,
998 const struct prefix
*longer_prefix_p
,
999 bool supernets_only
, int type
,
1000 unsigned short ospf_instance_id
, uint32_t tableid
,
1001 bool show_ng
, struct route_show_ctx
*ctx
)
1003 struct route_table
*table
;
1004 struct zebra_vrf
*zvrf
= NULL
;
1006 if (!(zvrf
= zebra_vrf_lookup_by_name(vrf_name
))) {
1008 vty_out(vty
, "{}\n");
1010 vty_out(vty
, "vrf %s not defined\n", vrf_name
);
1014 if (zvrf_id(zvrf
) == VRF_UNKNOWN
) {
1016 vty_out(vty
, "{}\n");
1018 vty_out(vty
, "vrf %s inactive\n", vrf_name
);
1023 table
= zebra_router_find_table(zvrf
, tableid
, afi
, SAFI_UNICAST
);
1025 table
= zebra_vrf_table(afi
, safi
, zvrf_id(zvrf
));
1028 vty_out(vty
, "{}\n");
1032 do_show_route_helper(vty
, zvrf
, table
, afi
, use_fib
, tag
,
1033 longer_prefix_p
, supernets_only
, type
,
1034 ospf_instance_id
, use_json
, tableid
, show_ng
, ctx
);
1041 "show <ip$ipv4|ipv6$ipv6> <nht|import-check>$type [<A.B.C.D|X:X::X:X>$addr|vrf NAME$vrf_name [<A.B.C.D|X:X::X:X>$addr]|vrf all$vrf_all] [mrib$mrib] [json]",
1045 "IP nexthop tracking table\n"
1046 "IP import check tracking table\n"
1052 VRF_ALL_CMD_HELP_STR
1053 "Show Multicast (MRIB) NHT state\n"
1056 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1057 vrf_id_t vrf_id
= VRF_DEFAULT
;
1058 struct prefix prefix
, *p
= NULL
;
1059 safi_t safi
= mrib
? SAFI_MULTICAST
: SAFI_UNICAST
;
1060 bool uj
= use_json(argc
, argv
);
1061 json_object
*json
= NULL
;
1062 json_object
*json_vrf
= NULL
;
1063 json_object
*json_nexthop
= NULL
;
1066 json
= json_object_new_object();
1070 struct zebra_vrf
*zvrf
;
1072 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1073 if ((zvrf
= vrf
->info
) != NULL
) {
1075 json_vrf
= json_object_new_object();
1076 json_nexthop
= json_object_new_object();
1077 json_object_object_add(json
,
1080 json_object_object_add(json_vrf
,
1086 vty_out(vty
, "\nVRF %s:\n",
1089 zebra_print_rnh_table(zvrf_id(zvrf
), afi
, safi
,
1090 vty
, NULL
, json_nexthop
);
1095 vty_json(vty
, json
);
1100 VRF_GET_ID(vrf_id
, vrf_name
, false);
1102 memset(&prefix
, 0, sizeof(prefix
));
1104 p
= sockunion2hostprefix(addr
, &prefix
);
1107 json_object_free(json
);
1113 json_vrf
= json_object_new_object();
1114 json_nexthop
= json_object_new_object();
1116 json_object_object_add(json
, vrf_name
, json_vrf
);
1118 json_object_object_add(json
, "default", json_vrf
);
1120 json_object_object_add(json_vrf
,
1121 (afi
== AFI_IP
) ? "ipv4" : "ipv6",
1125 zebra_print_rnh_table(vrf_id
, afi
, safi
, vty
, p
, json_nexthop
);
1128 vty_json(vty
, json
);
1133 DEFUN (ip_nht_default_route
,
1134 ip_nht_default_route_cmd
,
1135 "ip nht resolve-via-default",
1137 "Filter Next Hop tracking route resolution\n"
1138 "Resolve via default route\n")
1140 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1145 if (zvrf
->zebra_rnh_ip_default_route
)
1148 zvrf
->zebra_rnh_ip_default_route
= true;
1150 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1154 static void show_nexthop_group_out(struct vty
*vty
, struct nhg_hash_entry
*nhe
,
1155 json_object
*json_nhe_hdr
)
1157 struct nexthop
*nexthop
= NULL
;
1158 struct nhg_connected
*rb_node_dep
= NULL
;
1159 struct nexthop_group
*backup_nhg
;
1160 char up_str
[MONOTIME_STRLEN
];
1161 char time_left
[MONOTIME_STRLEN
];
1162 json_object
*json_dependants
= NULL
;
1163 json_object
*json_depends
= NULL
;
1164 json_object
*json_nexthop_array
= NULL
;
1165 json_object
*json_nexthops
= NULL
;
1166 json_object
*json
= NULL
;
1167 json_object
*json_backup_nexthop_array
= NULL
;
1168 json_object
*json_backup_nexthops
= NULL
;
1171 uptime2str(nhe
->uptime
, up_str
, sizeof(up_str
));
1174 json
= json_object_new_object();
1177 json_object_string_add(json
, "type",
1178 zebra_route_string(nhe
->type
));
1179 json_object_int_add(json
, "refCount", nhe
->refcnt
);
1180 if (thread_is_scheduled(nhe
->timer
))
1181 json_object_string_add(
1182 json
, "timeToDeletion",
1183 thread_timer_to_hhmmss(time_left
,
1186 json_object_string_add(json
, "uptime", up_str
);
1187 json_object_string_add(json
, "vrf",
1188 vrf_id_to_name(nhe
->vrf_id
));
1191 vty_out(vty
, "ID: %u (%s)\n", nhe
->id
,
1192 zebra_route_string(nhe
->type
));
1193 vty_out(vty
, " RefCnt: %u", nhe
->refcnt
);
1194 if (thread_is_scheduled(nhe
->timer
))
1195 vty_out(vty
, " Time to Deletion: %s",
1196 thread_timer_to_hhmmss(time_left
,
1201 vty_out(vty
, " Uptime: %s\n", up_str
);
1202 vty_out(vty
, " VRF: %s\n", vrf_id_to_name(nhe
->vrf_id
));
1205 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_VALID
)) {
1207 json_object_boolean_true_add(json
, "valid");
1209 vty_out(vty
, " Valid");
1211 if (CHECK_FLAG(nhe
->flags
, NEXTHOP_GROUP_INSTALLED
)) {
1213 json_object_boolean_true_add(json
, "installed");
1215 vty_out(vty
, ", Installed");
1222 json_object_int_add(json
, "interfaceIndex",
1225 vty_out(vty
, " Interface Index: %d\n",
1229 if (!zebra_nhg_depends_is_empty(nhe
)) {
1231 json_depends
= json_object_new_array();
1233 vty_out(vty
, " Depends:");
1234 frr_each(nhg_connected_tree
, &nhe
->nhg_depends
, rb_node_dep
) {
1236 json_object_array_add(
1238 json_object_new_int(
1239 rb_node_dep
->nhe
->id
));
1241 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1246 json_object_object_add(json
, "depends", json_depends
);
1249 /* Output nexthops */
1251 json_nexthop_array
= json_object_new_array();
1254 for (ALL_NEXTHOPS(nhe
->nhg
, nexthop
)) {
1255 if (json_nexthop_array
) {
1256 json_nexthops
= json_object_new_object();
1257 show_nexthop_json_helper(json_nexthops
, nexthop
, NULL
);
1259 if (!CHECK_FLAG(nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1262 /* Make recursive nexthops a bit more clear */
1264 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1267 if (nhe
->backup_info
== NULL
|| nhe
->backup_info
->nhe
== NULL
) {
1268 if (CHECK_FLAG(nexthop
->flags
,
1269 NEXTHOP_FLAG_HAS_BACKUP
)) {
1271 json_object_int_add(
1272 json_nexthops
, "backup",
1273 nexthop
->backup_idx
[0]);
1275 vty_out(vty
, " [backup %d]",
1276 nexthop
->backup_idx
[0]);
1282 json_object_array_add(json_nexthop_array
,
1289 /* TODO -- print more useful backup info */
1290 if (CHECK_FLAG(nexthop
->flags
,
1291 NEXTHOP_FLAG_HAS_BACKUP
)) {
1294 vty_out(vty
, "[backup");
1295 for (i
= 0; i
< nexthop
->backup_num
; i
++)
1297 nexthop
->backup_idx
[i
]);
1302 json_object_array_add(json_nexthop_array
,
1308 json_object_object_add(json
, "nexthops", json_nexthop_array
);
1310 /* Output backup nexthops (if any) */
1311 backup_nhg
= zebra_nhg_get_backup_nhg(nhe
);
1314 json_backup_nexthop_array
= json_object_new_array();
1316 vty_out(vty
, " Backups:\n");
1318 for (ALL_NEXTHOPS_PTR(backup_nhg
, nexthop
)) {
1319 if (json_backup_nexthop_array
) {
1320 json_backup_nexthops
= json_object_new_object();
1321 show_nexthop_json_helper(json_backup_nexthops
,
1323 json_object_array_add(json_backup_nexthop_array
,
1324 json_backup_nexthops
);
1327 if (!CHECK_FLAG(nexthop
->flags
,
1328 NEXTHOP_FLAG_RECURSIVE
))
1331 /* Make recursive nexthops a bit more
1335 show_route_nexthop_helper(vty
, NULL
, nexthop
);
1341 json_object_object_add(json
, "backupNexthops",
1342 json_backup_nexthop_array
);
1345 if (!zebra_nhg_dependents_is_empty(nhe
)) {
1347 json_dependants
= json_object_new_array();
1349 vty_out(vty
, " Dependents:");
1350 frr_each(nhg_connected_tree
, &nhe
->nhg_dependents
,
1353 json_object_array_add(
1355 json_object_new_int(
1356 rb_node_dep
->nhe
->id
));
1358 vty_out(vty
, " (%u)", rb_node_dep
->nhe
->id
);
1361 json_object_object_add(json
, "dependents",
1367 if (nhe
->nhg
.nhgr
.buckets
) {
1369 json_object_int_add(json
, "buckets",
1370 nhe
->nhg
.nhgr
.buckets
);
1371 json_object_int_add(json
, "idleTimer",
1372 nhe
->nhg
.nhgr
.idle_timer
);
1373 json_object_int_add(json
, "unbalancedTimer",
1374 nhe
->nhg
.nhgr
.unbalanced_timer
);
1375 json_object_int_add(json
, "unbalancedTime",
1376 nhe
->nhg
.nhgr
.unbalanced_time
);
1379 " Buckets: %u Idle Timer: %u Unbalanced Timer: %u Unbalanced time: %" PRIu64
1381 nhe
->nhg
.nhgr
.buckets
, nhe
->nhg
.nhgr
.idle_timer
,
1382 nhe
->nhg
.nhgr
.unbalanced_timer
,
1383 nhe
->nhg
.nhgr
.unbalanced_time
);
1388 json_object_object_addf(json_nhe_hdr
, json
, "%u", nhe
->id
);
1391 static int show_nexthop_group_id_cmd_helper(struct vty
*vty
, uint32_t id
,
1394 struct nhg_hash_entry
*nhe
= NULL
;
1396 nhe
= zebra_nhg_lookup_id(id
);
1399 show_nexthop_group_out(vty
, nhe
, json
);
1402 vty_json(vty
, json
);
1404 vty_out(vty
, "Nexthop Group ID: %u does not exist\n",
1410 vty_json(vty
, json
);
1415 /* Helper function for iteration through the hash of nexthop-groups/nhe-s */
1417 struct nhe_show_context
{
1425 static int nhe_show_walker(struct hash_bucket
*bucket
, void *arg
)
1427 struct nhe_show_context
*ctx
= arg
;
1428 struct nhg_hash_entry
*nhe
;
1430 nhe
= bucket
->data
; /* We won't be offered NULL buckets */
1432 if (ctx
->afi
&& nhe
->afi
!= ctx
->afi
)
1435 if (ctx
->vrf_id
&& nhe
->vrf_id
!= ctx
->vrf_id
)
1438 if (ctx
->type
&& nhe
->type
!= ctx
->type
)
1441 show_nexthop_group_out(ctx
->vty
, nhe
, ctx
->json
);
1444 return HASHWALK_CONTINUE
;
1447 static void show_nexthop_group_cmd_helper(struct vty
*vty
,
1448 struct zebra_vrf
*zvrf
, afi_t afi
,
1449 int type
, json_object
*json
)
1451 struct nhe_show_context ctx
;
1455 ctx
.vrf_id
= zvrf
->vrf
->vrf_id
;
1459 hash_walk(zrouter
.nhgs_id
, nhe_show_walker
, &ctx
);
1462 static void if_nexthop_group_dump_vty(struct vty
*vty
, struct interface
*ifp
)
1464 struct zebra_if
*zebra_if
= NULL
;
1465 struct nhg_connected
*rb_node_dep
= NULL
;
1467 zebra_if
= ifp
->info
;
1469 if (!if_nhg_dependents_is_empty(ifp
)) {
1470 vty_out(vty
, "Interface %s:\n", ifp
->name
);
1472 frr_each(nhg_connected_tree
, &zebra_if
->nhg_dependents
,
1475 show_nexthop_group_out(vty
, rb_node_dep
->nhe
, NULL
);
1480 DEFPY (show_interface_nexthop_group
,
1481 show_interface_nexthop_group_cmd
,
1482 "show interface [IFNAME$if_name] nexthop-group",
1484 "Interface status and configuration\n"
1486 "Show Nexthop Groups\n")
1488 struct vrf
*vrf
= NULL
;
1489 struct interface
*ifp
= NULL
;
1492 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1494 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
1496 if_nexthop_group_dump_vty(vty
, ifp
);
1500 FOR_ALL_INTERFACES (vrf
, ifp
)
1501 if_nexthop_group_dump_vty(vty
, ifp
);
1507 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
1514 DEFPY(show_nexthop_group
,
1515 show_nexthop_group_cmd
,
1516 "show nexthop-group rib <(0-4294967295)$id|[singleton <ip$v4|ipv6$v6>] [<kernel|zebra|bgp|sharp>$type_str] [vrf <NAME$vrf_name|all$vrf_all>]> [json]",
1518 "Show Nexthop Groups\n"
1520 "Nexthop Group ID\n"
1521 "Show Singleton Nexthop-Groups\n"
1524 "Kernel (not installed via the zebra RIB)\n"
1525 "Zebra (implicitly created by zebra)\n"
1526 "Border Gateway Protocol (BGP)\n"
1527 "Super Happy Advanced Routing Protocol (SHARP)\n"
1528 VRF_FULL_CMD_HELP_STR
1532 struct zebra_vrf
*zvrf
= NULL
;
1533 afi_t afi
= AFI_UNSPEC
;
1535 bool uj
= use_json(argc
, argv
);
1536 json_object
*json
= NULL
;
1537 json_object
*json_vrf
= NULL
;
1540 json
= json_object_new_object();
1543 return show_nexthop_group_id_cmd_helper(vty
, id
, json
);
1551 type
= proto_redistnum((afi
? afi
: AFI_IP
), type_str
);
1554 type
= ZEBRA_ROUTE_NHG
;
1558 if (!vrf_is_backend_netns() && (vrf_name
|| vrf_all
)) {
1560 vty_json(vty
, json
);
1563 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
1570 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1571 struct zebra_vrf
*zvrf
;
1577 json_vrf
= json_object_new_object();
1579 vty_out(vty
, "VRF: %s\n", vrf
->name
);
1581 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
,
1584 json_object_object_add(json
, vrf
->name
,
1589 vty_json(vty
, json
);
1595 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
1597 zvrf
= zebra_vrf_lookup_by_name(VRF_DEFAULT_NAME
);
1601 vty_json(vty
, json
);
1603 vty_out(vty
, "%% VRF '%s' specified does not exist\n",
1608 show_nexthop_group_cmd_helper(vty
, zvrf
, afi
, type
, json
);
1611 vty_json(vty
, json
);
1616 DEFPY_HIDDEN(nexthop_group_use_enable
,
1617 nexthop_group_use_enable_cmd
,
1618 "[no] zebra nexthop kernel enable",
1621 "Nexthop configuration \n"
1622 "Configure use of kernel nexthops\n"
1623 "Enable kernel nexthops\n")
1625 zebra_nhg_enable_kernel_nexthops(!no
);
1629 DEFPY_HIDDEN(proto_nexthop_group_only
, proto_nexthop_group_only_cmd
,
1630 "[no] zebra nexthop proto only",
1632 "Nexthop configuration\n"
1633 "Configure exclusive use of proto nexthops\n"
1634 "Only use proto nexthops\n")
1636 zebra_nhg_set_proto_nexthops_only(!no
);
1640 DEFPY_HIDDEN(backup_nexthop_recursive_use_enable
,
1641 backup_nexthop_recursive_use_enable_cmd
,
1642 "[no] zebra nexthop resolve-via-backup",
1645 "Nexthop configuration \n"
1646 "Configure use of backup nexthops in recursive resolution\n")
1648 zebra_nhg_set_recursive_use_backups(!no
);
1652 DEFUN (no_ip_nht_default_route
,
1653 no_ip_nht_default_route_cmd
,
1654 "no ip nht resolve-via-default",
1657 "Filter Next Hop tracking route resolution\n"
1658 "Resolve via default route\n")
1660 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1665 if (!zvrf
->zebra_rnh_ip_default_route
)
1668 zvrf
->zebra_rnh_ip_default_route
= false;
1669 zebra_evaluate_rnh(zvrf
, AFI_IP
, 0, NULL
, SAFI_UNICAST
);
1673 DEFUN (ipv6_nht_default_route
,
1674 ipv6_nht_default_route_cmd
,
1675 "ipv6 nht resolve-via-default",
1677 "Filter Next Hop tracking route resolution\n"
1678 "Resolve via default route\n")
1680 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1685 if (zvrf
->zebra_rnh_ipv6_default_route
)
1688 zvrf
->zebra_rnh_ipv6_default_route
= true;
1689 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1693 DEFUN (no_ipv6_nht_default_route
,
1694 no_ipv6_nht_default_route_cmd
,
1695 "no ipv6 nht resolve-via-default",
1698 "Filter Next Hop tracking route resolution\n"
1699 "Resolve via default route\n")
1701 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
1706 if (!zvrf
->zebra_rnh_ipv6_default_route
)
1709 zvrf
->zebra_rnh_ipv6_default_route
= false;
1710 zebra_evaluate_rnh(zvrf
, AFI_IP6
, 0, NULL
, SAFI_UNICAST
);
1714 DEFPY_HIDDEN(rnh_hide_backups
, rnh_hide_backups_cmd
,
1715 "[no] ip nht hide-backup-events",
1718 "Nexthop-tracking configuration\n"
1719 "Hide notification about backup nexthops\n")
1721 rnh_set_hide_backups(!no
);
1729 ip$ipv4 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1730 [vrf <NAME$vrf_name|all$vrf_all>]\
1733 |A.B.C.D/M$prefix longer-prefixes\
1734 |supernets-only$supernets_only\
1737 " FRR_IP_REDIST_STR_ZEBRA
"$type_str\
1738 |ospf$type_str (1-65535)$ospf_instance_id\
1740 |ipv6$ipv6 <fib$fib|route> [table <(1-4294967295)$table|all$table_all>]\
1741 [vrf <NAME$vrf_name|all$vrf_all>]\
1744 |X:X::X:X/M$prefix longer-prefixes\
1746 [" FRR_IP6_REDIST_STR_ZEBRA
"$type_str]\
1748 [<json$json|nexthop-group$ng>]",
1751 "IP forwarding table\n"
1752 "IP routing table\n"
1753 "Table to display\n"
1754 "The table number to display\n"
1756 VRF_FULL_CMD_HELP_STR
1757 "Show only routes with tag\n"
1759 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1760 "Show route matching the specified Network/Mask pair only\n"
1761 "Show supernet entries only\n"
1762 FRR_IP_REDIST_HELP_STR_ZEBRA
1763 "Open Shortest Path First (OSPFv2)\n"
1766 "IP forwarding table\n"
1767 "IP routing table\n"
1768 "Table to display\n"
1769 "The table number to display\n"
1771 VRF_FULL_CMD_HELP_STR
1772 "Show only routes with tag\n"
1775 "Show route matching the specified Network/Mask pair only\n"
1776 FRR_IP6_REDIST_HELP_STR_ZEBRA
1778 "Nexthop Group Information\n")
1780 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1783 struct zebra_vrf
*zvrf
;
1784 struct route_show_ctx ctx
= {
1785 .multi
= vrf_all
|| table_all
,
1788 if (!vrf_is_backend_netns()) {
1789 if ((vrf_all
|| vrf_name
) && (table
|| table_all
)) {
1791 vty_out(vty
, "{}\n");
1793 vty_out(vty
, "Linux vrf backend already points to table id\n");
1794 vty_out(vty
, "Either remove table parameter or vrf parameter\n");
1800 type
= proto_redistnum(afi
, type_str
);
1802 vty_out(vty
, "Unknown route type\n");
1808 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1809 if ((zvrf
= vrf
->info
) == NULL
1810 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
1814 do_show_ip_route_all(
1815 vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1816 prefix_str
? prefix
: NULL
,
1817 !!supernets_only
, type
,
1818 ospf_instance_id
, !!ng
, &ctx
);
1821 vty
, zvrf_name(zvrf
), afi
, SAFI_UNICAST
,
1823 prefix_str
? prefix
: NULL
,
1824 !!supernets_only
, type
,
1825 ospf_instance_id
, table
, !!ng
, &ctx
);
1828 vrf_id_t vrf_id
= VRF_DEFAULT
;
1831 VRF_GET_ID(vrf_id
, vrf_name
, !!json
);
1832 vrf
= vrf_lookup_by_id(vrf_id
);
1841 do_show_ip_route_all(vty
, zvrf
, afi
, !!fib
, !!json
, tag
,
1842 prefix_str
? prefix
: NULL
,
1843 !!supernets_only
, type
,
1844 ospf_instance_id
, !!ng
, &ctx
);
1846 do_show_ip_route(vty
, vrf
->name
, afi
, SAFI_UNICAST
,
1848 prefix_str
? prefix
: NULL
,
1849 !!supernets_only
, type
,
1850 ospf_instance_id
, table
, !!ng
, &ctx
);
1856 ALIAS_HIDDEN (show_route
,
1858 "show <ip$ipv4|ipv6$ipv6> ro",
1862 "IP routing table\n");
1865 DEFPY (show_route_detail
,
1866 show_route_detail_cmd
,
1869 ip$ipv4 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1874 |ipv6$ipv6 <fib$fib|route> [vrf <NAME$vrf_name|all$vrf_all>]\
1880 [json$json] [nexthop-group$ng]",
1883 "IP forwarding table\n"
1884 "IP routing table\n"
1885 VRF_FULL_CMD_HELP_STR
1886 "Network in the IP routing table to display\n"
1887 "IP prefix <network>/<length>, e.g., 35.0.0.0/8\n"
1889 "IPv6 forwarding table\n"
1890 "IPv6 routing table\n"
1891 VRF_FULL_CMD_HELP_STR
1895 "Nexthop Group Information\n")
1897 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
1898 struct route_table
*table
;
1900 struct route_node
*rn
;
1901 bool use_fib
= !!fib
;
1903 bool network_found
= false;
1904 bool show_ng
= !!ng
;
1907 prefix_str
= address_str
;
1908 if (str2prefix(prefix_str
, &p
) < 0) {
1909 vty_out(vty
, "%% Malformed address\n");
1915 struct zebra_vrf
*zvrf
;
1917 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1918 if ((zvrf
= vrf
->info
) == NULL
1919 || (table
= zvrf
->table
[afi
][SAFI_UNICAST
]) == NULL
)
1922 rn
= route_node_match(table
, &p
);
1925 if (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) {
1926 route_unlock_node(rn
);
1930 dest
= rib_dest_from_rnode(rn
);
1931 if (use_fib
&& !dest
->selected_fib
) {
1932 route_unlock_node(rn
);
1936 network_found
= true;
1938 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1940 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
,
1943 route_unlock_node(rn
);
1946 if (!network_found
) {
1948 vty_out(vty
, "{}\n");
1952 "%% Network not in FIB\n");
1955 "%% Network not in RIB\n");
1960 vrf_id_t vrf_id
= VRF_DEFAULT
;
1963 VRF_GET_ID(vrf_id
, vrf_name
, false);
1965 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
1969 rn
= route_node_match(table
, &p
);
1971 dest
= rib_dest_from_rnode(rn
);
1973 if (!rn
|| (!address_str
&& rn
->p
.prefixlen
!= p
.prefixlen
) ||
1974 (use_fib
&& dest
&& !dest
->selected_fib
)) {
1976 vty_out(vty
, "{}\n");
1980 "%% Network not in FIB\n");
1983 "%% Network not in table\n");
1986 route_unlock_node(rn
);
1991 vty_show_ip_route_detail_json(vty
, rn
, use_fib
);
1993 vty_show_ip_route_detail(vty
, rn
, 0, use_fib
, show_ng
);
1995 route_unlock_node(rn
);
2001 DEFPY (show_route_summary
,
2002 show_route_summary_cmd
,
2003 "show <ip$ipv4|ipv6$ipv6> route [vrf <NAME$vrf_name|all$vrf_all>] \
2004 summary [table (1-4294967295)$table_id] [prefix$prefix] [json]",
2008 "IP routing table\n"
2009 VRF_FULL_CMD_HELP_STR
2010 "Summary of all routes\n"
2011 "Table to display summary for\n"
2012 "The table number\n"
2016 afi_t afi
= ipv4
? AFI_IP
: AFI_IP6
;
2017 struct route_table
*table
;
2018 bool uj
= use_json(argc
, argv
);
2022 struct zebra_vrf
*zvrf
;
2024 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2025 if ((zvrf
= vrf
->info
) == NULL
)
2029 table
= zebra_vrf_table(afi
, SAFI_UNICAST
,
2032 table
= zebra_vrf_lookup_table_with_table_id(
2033 afi
, SAFI_UNICAST
, zvrf
->vrf
->vrf_id
,
2040 vty_show_ip_route_summary_prefix(vty
, table
,
2043 vty_show_ip_route_summary(vty
, table
, uj
);
2046 vrf_id_t vrf_id
= VRF_DEFAULT
;
2049 VRF_GET_ID(vrf_id
, vrf_name
, false);
2052 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2054 table
= zebra_vrf_lookup_table_with_table_id(
2055 afi
, SAFI_UNICAST
, vrf_id
, table_id
);
2060 vty_show_ip_route_summary_prefix(vty
, table
, uj
);
2062 vty_show_ip_route_summary(vty
, table
, uj
);
2068 DEFUN_HIDDEN (show_route_zebra_dump
,
2069 show_route_zebra_dump_cmd
,
2070 "show <ip|ipv6> zebra route dump [vrf VRFNAME]",
2080 struct route_table
*table
;
2081 const char *vrf_name
= NULL
;
2084 afi
= strmatch(argv
[1]->text
, "ipv6") ? AFI_IP6
: AFI_IP
;
2086 if (argv_find(argv
, argc
, "vrf", &idx
))
2087 vrf_name
= argv
[++idx
]->arg
;
2091 struct zebra_vrf
*zvrf
;
2093 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2096 || (zvrf
->table
[afi
][SAFI_UNICAST
] == NULL
))
2099 table
= zvrf
->table
[afi
][SAFI_UNICAST
];
2100 show_ip_route_dump_vty(vty
, table
);
2103 vrf_id_t vrf_id
= VRF_DEFAULT
;
2105 VRF_GET_ID(vrf_id
, vrf_name
, true);
2107 table
= zebra_vrf_table(afi
, SAFI_UNICAST
, vrf_id
);
2111 show_ip_route_dump_vty(vty
, table
);
2117 static void show_ip_route_nht_dump(struct vty
*vty
, struct nexthop
*nexthop
,
2118 struct route_entry
*re
, unsigned int num
)
2121 char buf
[SRCDEST2STR_BUFFER
];
2123 vty_out(vty
, " Nexthop %u:\n", num
);
2124 vty_out(vty
, " type: %u\n", nexthop
->type
);
2125 vty_out(vty
, " flags: %u\n", nexthop
->flags
);
2126 switch (nexthop
->type
) {
2127 case NEXTHOP_TYPE_IPV4
:
2128 case NEXTHOP_TYPE_IPV4_IFINDEX
:
2129 vty_out(vty
, " ip address: %s\n",
2130 inet_ntop(AF_INET
, &nexthop
->gate
.ipv4
, buf
,
2132 vty_out(vty
, " afi: ipv4\n");
2134 if (nexthop
->ifindex
) {
2135 vty_out(vty
, " interface index: %d\n",
2137 vty_out(vty
, " interface name: %s\n",
2138 ifindex2ifname(nexthop
->ifindex
,
2142 if (nexthop
->src
.ipv4
.s_addr
2143 && (inet_ntop(AF_INET
, &nexthop
->src
.ipv4
, buf
,
2145 vty_out(vty
, " source: %s\n", buf
);
2147 case NEXTHOP_TYPE_IPV6
:
2148 case NEXTHOP_TYPE_IPV6_IFINDEX
:
2149 vty_out(vty
, " ip: %s\n",
2150 inet_ntop(AF_INET6
, &nexthop
->gate
.ipv6
, buf
,
2152 vty_out(vty
, " afi: ipv6\n");
2154 if (nexthop
->ifindex
) {
2155 vty_out(vty
, " interface index: %d\n",
2157 vty_out(vty
, " interface name: %s\n",
2158 ifindex2ifname(nexthop
->ifindex
,
2162 if (!IPV6_ADDR_SAME(&nexthop
->src
.ipv6
, &in6addr_any
)) {
2163 if (inet_ntop(AF_INET6
, &nexthop
->src
.ipv6
, buf
,
2165 vty_out(vty
, " source: %s\n", buf
);
2168 case NEXTHOP_TYPE_IFINDEX
:
2170 " Nexthop is an interface (directly connected).\n");
2171 vty_out(vty
, " interface index: %d\n", nexthop
->ifindex
);
2172 vty_out(vty
, " interface name: %s\n",
2173 ifindex2ifname(nexthop
->ifindex
, nexthop
->vrf_id
));
2175 case NEXTHOP_TYPE_BLACKHOLE
:
2176 vty_out(vty
, " Nexthop type is blackhole.\n");
2178 switch (nexthop
->bh_type
) {
2179 case BLACKHOLE_REJECT
:
2180 vty_out(vty
, " Blackhole type: reject\n");
2182 case BLACKHOLE_ADMINPROHIB
:
2184 " Blackhole type: admin-prohibited\n");
2186 case BLACKHOLE_NULL
:
2187 vty_out(vty
, " Blackhole type: NULL0\n");
2189 case BLACKHOLE_UNSPEC
:
2196 static void show_ip_route_dump_vty(struct vty
*vty
, struct route_table
*table
)
2198 struct route_node
*rn
;
2199 struct route_entry
*re
;
2200 char buf
[SRCDEST2STR_BUFFER
];
2205 struct nexthop
*nexthop
= NULL
;
2206 int nexthop_num
= 0;
2208 vty_out(vty
, "\nIPv4/IPv6 Routing table dump\n");
2209 vty_out(vty
, "----------------------------\n");
2211 for (rn
= route_top(table
); rn
; rn
= route_next(rn
)) {
2212 RNODE_FOREACH_RE (rn
, re
) {
2213 vty_out(vty
, "Route: %s\n",
2214 srcdest_rnode2str(rn
, buf
, sizeof(buf
)));
2215 vty_out(vty
, " protocol: %s\n",
2216 zebra_route_string(re
->type
));
2217 vty_out(vty
, " instance: %u\n", re
->instance
);
2218 vty_out(vty
, " VRF ID: %u\n", re
->vrf_id
);
2219 vty_out(vty
, " VRF name: %s\n",
2220 vrf_id_to_name(re
->vrf_id
));
2221 vty_out(vty
, " flags: %u\n", re
->flags
);
2223 if (re
->type
!= ZEBRA_ROUTE_CONNECT
) {
2224 vty_out(vty
, " distance: %u\n", re
->distance
);
2225 vty_out(vty
, " metric: %u\n", re
->metric
);
2228 vty_out(vty
, " tag: %u\n", re
->tag
);
2230 uptime
= monotime(&tv
);
2231 uptime
-= re
->uptime
;
2232 gmtime_r(&uptime
, &tm
);
2234 if (uptime
< ONE_DAY_SECOND
)
2235 snprintf(time
, sizeof(time
), "%02d:%02d:%02d",
2236 tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);
2237 else if (uptime
< ONE_WEEK_SECOND
)
2238 snprintf(time
, sizeof(time
), "%dd%02dh%02dm",
2239 tm
.tm_yday
, tm
.tm_hour
, tm
.tm_min
);
2241 snprintf(time
, sizeof(time
), "%02dw%dd%02dh",
2243 tm
.tm_yday
- ((tm
.tm_yday
/ 7) * 7),
2246 vty_out(vty
, " status: %u\n", re
->status
);
2247 vty_out(vty
, " nexthop_num: %u\n",
2248 nexthop_group_nexthop_num(&(re
->nhe
->nhg
)));
2249 vty_out(vty
, " nexthop_active_num: %u\n",
2250 nexthop_group_active_nexthop_num(
2252 vty_out(vty
, " table: %u\n", re
->table
);
2253 vty_out(vty
, " uptime: %s\n", time
);
2255 for (ALL_NEXTHOPS_PTR(&(re
->nhe
->nhg
), nexthop
)) {
2257 show_ip_route_nht_dump(vty
, nexthop
, re
,
2267 static void vty_show_ip_route_summary(struct vty
*vty
,
2268 struct route_table
*table
, bool use_json
)
2270 struct route_node
*rn
;
2271 struct route_entry
*re
;
2272 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2273 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2274 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2275 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2276 uint32_t offload_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2277 uint32_t trap_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2280 json_object
*json_route_summary
= NULL
;
2281 json_object
*json_route_routes
= NULL
;
2283 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2284 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2285 memset(&offload_cnt
, 0, sizeof(offload_cnt
));
2286 memset(&trap_cnt
, 0, sizeof(trap_cnt
));
2289 json_route_summary
= json_object_new_object();
2290 json_route_routes
= json_object_new_array();
2291 json_object_object_add(json_route_summary
, "routes",
2295 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2296 RNODE_FOREACH_RE (rn
, re
) {
2297 is_ibgp
= (re
->type
== ZEBRA_ROUTE_BGP
2298 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
));
2300 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2302 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2304 rib_cnt
[re
->type
]++;
2306 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2307 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2310 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2312 fib_cnt
[re
->type
]++;
2315 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_TRAPPED
)) {
2317 trap_cnt
[ZEBRA_ROUTE_IBGP
]++;
2319 trap_cnt
[re
->type
]++;
2322 if (CHECK_FLAG(re
->flags
, ZEBRA_FLAG_OFFLOADED
)) {
2324 offload_cnt
[ZEBRA_ROUTE_IBGP
]++;
2326 offload_cnt
[re
->type
]++;
2331 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2333 zvrf_name(((struct rib_table_info
*)
2334 route_table_get_info(table
))
2337 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2338 if ((rib_cnt
[i
] > 0) || (i
== ZEBRA_ROUTE_BGP
2339 && rib_cnt
[ZEBRA_ROUTE_IBGP
] > 0)) {
2340 if (i
== ZEBRA_ROUTE_BGP
) {
2342 json_object
*json_route_ebgp
=
2343 json_object_new_object();
2345 json_object_int_add(
2346 json_route_ebgp
, "fib",
2347 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2348 json_object_int_add(
2349 json_route_ebgp
, "rib",
2350 rib_cnt
[ZEBRA_ROUTE_BGP
]);
2351 json_object_int_add(
2352 json_route_ebgp
, "fibOffLoaded",
2353 offload_cnt
[ZEBRA_ROUTE_BGP
]);
2354 json_object_int_add(
2355 json_route_ebgp
, "fibTrapped",
2356 trap_cnt
[ZEBRA_ROUTE_BGP
]);
2358 json_object_string_add(json_route_ebgp
,
2360 json_object_array_add(json_route_routes
,
2363 json_object
*json_route_ibgp
=
2364 json_object_new_object();
2366 json_object_int_add(
2367 json_route_ibgp
, "fib",
2368 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2369 json_object_int_add(
2370 json_route_ibgp
, "rib",
2371 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2372 json_object_int_add(
2373 json_route_ibgp
, "fibOffLoaded",
2374 offload_cnt
[ZEBRA_ROUTE_IBGP
]);
2375 json_object_int_add(
2376 json_route_ibgp
, "fibTrapped",
2377 trap_cnt
[ZEBRA_ROUTE_IBGP
]);
2378 json_object_string_add(json_route_ibgp
,
2380 json_object_array_add(json_route_routes
,
2383 vty_out(vty
, "%-20s %-20d %-20d \n",
2385 rib_cnt
[ZEBRA_ROUTE_BGP
],
2386 fib_cnt
[ZEBRA_ROUTE_BGP
]);
2387 vty_out(vty
, "%-20s %-20d %-20d \n",
2389 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2390 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2394 json_object
*json_route_type
=
2395 json_object_new_object();
2397 json_object_int_add(json_route_type
,
2399 json_object_int_add(json_route_type
,
2402 json_object_int_add(json_route_type
,
2405 json_object_int_add(json_route_type
,
2408 json_object_string_add(
2409 json_route_type
, "type",
2410 zebra_route_string(i
));
2411 json_object_array_add(json_route_routes
,
2414 vty_out(vty
, "%-20s %-20d %-20d \n",
2415 zebra_route_string(i
),
2416 rib_cnt
[i
], fib_cnt
[i
]);
2422 json_object_int_add(json_route_summary
, "routesTotal",
2423 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2424 json_object_int_add(json_route_summary
, "routesTotalFib",
2425 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2427 vty_json(vty
, json_route_summary
);
2429 vty_out(vty
, "------\n");
2430 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2431 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2437 * Implementation of the ip route summary prefix command.
2439 * This command prints the primary prefixes that have been installed by various
2440 * protocols on the box.
2443 static void vty_show_ip_route_summary_prefix(struct vty
*vty
,
2444 struct route_table
*table
,
2447 struct route_node
*rn
;
2448 struct route_entry
*re
;
2449 struct nexthop
*nexthop
;
2450 #define ZEBRA_ROUTE_IBGP ZEBRA_ROUTE_MAX
2451 #define ZEBRA_ROUTE_TOTAL (ZEBRA_ROUTE_IBGP + 1)
2452 uint32_t rib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2453 uint32_t fib_cnt
[ZEBRA_ROUTE_TOTAL
+ 1];
2456 json_object
*json_route_summary
= NULL
;
2457 json_object
*json_route_routes
= NULL
;
2459 memset(&rib_cnt
, 0, sizeof(rib_cnt
));
2460 memset(&fib_cnt
, 0, sizeof(fib_cnt
));
2463 json_route_summary
= json_object_new_object();
2464 json_route_routes
= json_object_new_array();
2465 json_object_object_add(json_route_summary
, "prefixRoutes",
2469 for (rn
= route_top(table
); rn
; rn
= srcdest_route_next(rn
))
2470 RNODE_FOREACH_RE (rn
, re
) {
2473 * In case of ECMP, count only once.
2476 if (CHECK_FLAG(re
->status
, ROUTE_ENTRY_INSTALLED
)) {
2477 fib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2478 fib_cnt
[re
->type
]++;
2480 for (nexthop
= re
->nhe
->nhg
.nexthop
; (!cnt
&& nexthop
);
2481 nexthop
= nexthop
->next
) {
2483 rib_cnt
[ZEBRA_ROUTE_TOTAL
]++;
2484 rib_cnt
[re
->type
]++;
2485 if (re
->type
== ZEBRA_ROUTE_BGP
2486 && CHECK_FLAG(re
->flags
, ZEBRA_FLAG_IBGP
)) {
2487 rib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2488 if (CHECK_FLAG(re
->status
,
2489 ROUTE_ENTRY_INSTALLED
))
2490 fib_cnt
[ZEBRA_ROUTE_IBGP
]++;
2496 vty_out(vty
, "%-20s %-20s %s (vrf %s)\n", "Route Source",
2497 "Prefix Routes", "FIB",
2498 zvrf_name(((struct rib_table_info
*)
2499 route_table_get_info(table
))
2502 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
2503 if (rib_cnt
[i
] > 0) {
2504 if (i
== ZEBRA_ROUTE_BGP
) {
2506 json_object
*json_route_ebgp
=
2507 json_object_new_object();
2509 json_object_int_add(
2510 json_route_ebgp
, "fib",
2511 fib_cnt
[ZEBRA_ROUTE_BGP
]
2512 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2513 json_object_int_add(
2514 json_route_ebgp
, "rib",
2515 rib_cnt
[ZEBRA_ROUTE_BGP
]
2516 - rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2517 json_object_string_add(json_route_ebgp
,
2519 json_object_array_add(json_route_routes
,
2522 json_object
*json_route_ibgp
=
2523 json_object_new_object();
2525 json_object_int_add(
2526 json_route_ibgp
, "fib",
2527 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2528 json_object_int_add(
2529 json_route_ibgp
, "rib",
2530 rib_cnt
[ZEBRA_ROUTE_IBGP
]);
2531 json_object_string_add(json_route_ibgp
,
2533 json_object_array_add(json_route_routes
,
2536 vty_out(vty
, "%-20s %-20d %-20d \n",
2538 rib_cnt
[ZEBRA_ROUTE_BGP
]
2539 - rib_cnt
[ZEBRA_ROUTE_IBGP
],
2540 fib_cnt
[ZEBRA_ROUTE_BGP
]
2541 - fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2542 vty_out(vty
, "%-20s %-20d %-20d \n",
2544 rib_cnt
[ZEBRA_ROUTE_IBGP
],
2545 fib_cnt
[ZEBRA_ROUTE_IBGP
]);
2549 json_object
*json_route_type
=
2550 json_object_new_object();
2552 json_object_int_add(json_route_type
,
2554 json_object_int_add(json_route_type
,
2556 json_object_string_add(
2557 json_route_type
, "type",
2558 zebra_route_string(i
));
2559 json_object_array_add(json_route_routes
,
2562 vty_out(vty
, "%-20s %-20d %-20d \n",
2563 zebra_route_string(i
),
2564 rib_cnt
[i
], fib_cnt
[i
]);
2570 json_object_int_add(json_route_summary
, "prefixRoutesTotal",
2571 rib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2572 json_object_int_add(json_route_summary
, "prefixRoutesTotalFib",
2573 fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2575 vty_json(vty
, json_route_summary
);
2577 vty_out(vty
, "------\n");
2578 vty_out(vty
, "%-20s %-20d %-20d \n", "Totals",
2579 rib_cnt
[ZEBRA_ROUTE_TOTAL
], fib_cnt
[ZEBRA_ROUTE_TOTAL
]);
2584 DEFUN (allow_external_route_update
,
2585 allow_external_route_update_cmd
,
2586 "allow-external-route-update",
2587 "Allow FRR routes to be overwritten by external processes\n")
2589 zrouter
.allow_delete
= true;
2594 DEFUN (no_allow_external_route_update
,
2595 no_allow_external_route_update_cmd
,
2596 "no allow-external-route-update",
2598 "Allow FRR routes to be overwritten by external processes\n")
2600 zrouter
.allow_delete
= false;
2613 struct zebra_vrf
*zvrf
;
2615 if (vrf_is_backend_netns())
2616 vty_out(vty
, "netns-based vrfs\n");
2618 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2619 if (!(zvrf
= vrf
->info
))
2621 if (zvrf_id(zvrf
) == VRF_DEFAULT
)
2624 vty_out(vty
, "vrf %s ", zvrf_name(zvrf
));
2625 if (zvrf_id(zvrf
) == VRF_UNKNOWN
|| !zvrf_is_active(zvrf
))
2626 vty_out(vty
, "inactive");
2627 else if (zvrf_ns_name(zvrf
))
2628 vty_out(vty
, "id %u netns %s", zvrf_id(zvrf
),
2629 zvrf_ns_name(zvrf
));
2631 vty_out(vty
, "id %u table %u", zvrf_id(zvrf
),
2633 if (vrf_is_user_cfged(vrf
))
2634 vty_out(vty
, " (configured)");
2641 DEFPY (evpn_mh_mac_holdtime
,
2642 evpn_mh_mac_holdtime_cmd
,
2643 "[no$no] evpn mh mac-holdtime (0-86400)$duration",
2648 "Duration in seconds\n")
2650 return zebra_evpn_mh_mac_holdtime_update(vty
, duration
,
2654 DEFPY (evpn_mh_neigh_holdtime
,
2655 evpn_mh_neigh_holdtime_cmd
,
2656 "[no$no] evpn mh neigh-holdtime (0-86400)$duration",
2660 "Neighbor entry hold time\n"
2661 "Duration in seconds\n")
2664 return zebra_evpn_mh_neigh_holdtime_update(vty
, duration
,
2668 DEFPY (evpn_mh_startup_delay
,
2669 evpn_mh_startup_delay_cmd
,
2670 "[no] evpn mh startup-delay(0-3600)$duration",
2675 "duration in seconds\n")
2678 return zebra_evpn_mh_startup_delay_update(vty
, duration
,
2682 DEFPY(evpn_mh_redirect_off
, evpn_mh_redirect_off_cmd
,
2683 "[no$no] evpn mh redirect-off",
2687 "ES bond redirect for fast-failover off\n")
2691 redirect_off
= no
? false : true;
2693 return zebra_evpn_mh_redirect_off(vty
, redirect_off
);
2696 DEFUN (default_vrf_vni_mapping
,
2697 default_vrf_vni_mapping_cmd
,
2698 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2699 "VNI corresponding to the DEFAULT VRF\n"
2701 "Prefix routes only \n")
2703 char xpath
[XPATH_MAXLEN
];
2704 struct zebra_vrf
*zvrf
= NULL
;
2707 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2714 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2716 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
2718 snprintf(xpath
, sizeof(xpath
),
2719 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2721 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, argv
[1]->arg
);
2724 snprintf(xpath
, sizeof(xpath
),
2725 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2727 nb_cli_enqueue_change(vty
, xpath
, NB_OP_MODIFY
, "true");
2730 return nb_cli_apply_changes(vty
, NULL
);
2733 DEFUN (no_default_vrf_vni_mapping
,
2734 no_default_vrf_vni_mapping_cmd
,
2735 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2737 "VNI corresponding to DEFAULT VRF\n"
2739 "Prefix routes only \n")
2741 char xpath
[XPATH_MAXLEN
];
2743 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2744 struct zebra_vrf
*zvrf
= NULL
;
2746 zvrf
= vrf_info_lookup(VRF_DEFAULT
);
2753 if (zvrf
->l3vni
!= vni
) {
2754 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2759 snprintf(xpath
, sizeof(xpath
),
2760 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/l3vni-id",
2762 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, argv
[2]->arg
);
2765 snprintf(xpath
, sizeof(xpath
),
2766 FRR_VRF_KEY_XPATH
"/frr-zebra:zebra/prefix-only",
2768 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, "true");
2771 snprintf(xpath
, sizeof(xpath
), FRR_VRF_KEY_XPATH
"/frr-zebra:zebra",
2773 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
2775 return nb_cli_apply_changes(vty
, NULL
);
2778 DEFUN (vrf_vni_mapping
,
2779 vrf_vni_mapping_cmd
,
2780 "vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2781 "VNI corresponding to tenant VRF\n"
2783 "prefix-routes-only\n")
2787 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2795 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_CREATE
, NULL
);
2796 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_MODIFY
,
2800 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2801 NB_OP_MODIFY
, "true");
2803 return nb_cli_apply_changes(vty
, NULL
);
2806 DEFUN (no_vrf_vni_mapping
,
2807 no_vrf_vni_mapping_cmd
,
2808 "no vni " CMD_VNI_RANGE
"[prefix-routes-only]",
2810 "VNI corresponding to tenant VRF\n"
2812 "prefix-routes-only\n")
2816 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
2817 vni_t vni
= strtoul(argv
[2]->arg
, NULL
, 10);
2825 if (zvrf
->l3vni
!= vni
) {
2826 vty_out(vty
, "VNI %d doesn't exist in VRF: %s \n", vni
,
2831 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/l3vni-id", NB_OP_DESTROY
,
2835 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra/prefix-only",
2836 NB_OP_DESTROY
, "true");
2838 nb_cli_enqueue_change(vty
, "./frr-zebra:zebra", NB_OP_DESTROY
, NULL
);
2840 return nb_cli_apply_changes(vty
, NULL
);
2844 DEFPY (show_vrf_vni
,
2846 "show vrf [<NAME$vrf_name|all$vrf_all>] vni [json]",
2848 VRF_FULL_CMD_HELP_STR
2853 struct zebra_vrf
*zvrf
;
2854 json_object
*json
= NULL
;
2855 json_object
*json_vrfs
= NULL
;
2856 bool uj
= use_json(argc
, argv
);
2857 bool use_vrf
= false;
2860 json
= json_object_new_object();
2862 /* show vrf vni used to display across all vrfs
2863 * This is enhanced to support only for specific
2866 if (vrf_all
|| !vrf_name
) {
2867 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2878 "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2879 "VRF", "VNI", "VxLAN IF", "L3-SVI",
2882 json_vrfs
= json_object_new_array();
2885 vty_json(vty
, json
);
2887 vty_out(vty
, "%% VRF does not exist\n");
2894 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
2899 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2901 } else if (vrf_name
) {
2902 zvrf
= zebra_vrf_lookup_by_name(vrf_name
);
2905 vty_json(vty
, json
);
2908 "%% VRF '%s' specified does not exist\n",
2915 vty_out(vty
, "%-37s %-10s %-20s %-20s %-5s %-18s\n",
2916 "VRF", "VNI", "VxLAN IF", "L3-SVI", "State",
2919 json_vrfs
= json_object_new_array();
2921 zebra_vxlan_print_vrf_vni(vty
, zvrf
, json_vrfs
);
2925 json_object_object_add(json
, "vrfs", json_vrfs
);
2926 vty_json(vty
, json
);
2932 DEFUN (show_evpn_global
,
2933 show_evpn_global_cmd
,
2939 bool uj
= use_json(argc
, argv
);
2941 zebra_vxlan_print_evpn(vty
, uj
);
2945 DEFPY(show_evpn_neigh
, show_neigh_cmd
, "show ip neigh",
2946 SHOW_STR IP_STR
"neighbors\n")
2949 zebra_neigh_show(vty
);
2954 DEFPY(show_evpn_l2_nh
,
2955 show_evpn_l2_nh_cmd
,
2956 "show evpn l2-nh [json$json]",
2964 zebra_evpn_l2_nh_show(vty
, uj
);
2971 "show evpn es [NAME$esi_str|detail$detail] [json$json]",
2974 "Ethernet Segment\n"
2976 "Detailed information\n"
2983 if (!str_to_esi(esi_str
, &esi
)) {
2984 vty_out(vty
, "%% Malformed ESI\n");
2987 zebra_evpn_es_show_esi(vty
, uj
, &esi
);
2990 zebra_evpn_es_show_detail(vty
, uj
);
2992 zebra_evpn_es_show(vty
, uj
);
2998 DEFPY(show_evpn_es_evi
,
2999 show_evpn_es_evi_cmd
,
3000 "show evpn es-evi [vni (1-16777215)$vni] [detail$detail] [json$json]",
3003 "Ethernet Segment per EVI\n"
3004 "VxLAN Network Identifier\n"
3006 "Detailed information\n"
3013 zebra_evpn_es_evi_show_vni(vty
, uj
, vni
, ud
);
3015 zebra_evpn_es_evi_show(vty
, uj
, ud
);
3020 DEFPY(show_evpn_access_vlan
, show_evpn_access_vlan_cmd
,
3021 "show evpn access-vlan [IFNAME$if_name (1-4094)$vid | detail$detail] [json$json]",
3027 "Detailed information\n" JSON_STR
)
3031 if (if_name
&& vid
) {
3034 struct interface
*ifp
;
3036 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
3038 ifp
= if_lookup_by_name(if_name
, vrf
->vrf_id
);
3040 zebra_evpn_acc_vl_show_vid(vty
, uj
, vid
,
3048 vty_out(vty
, "%% Can't find interface %s\n", if_name
);
3053 zebra_evpn_acc_vl_show_detail(vty
, uj
);
3055 zebra_evpn_acc_vl_show(vty
, uj
);
3061 DEFUN (show_evpn_vni
,
3063 "show evpn vni [json]",
3066 "VxLAN Network Identifier\n"
3069 struct zebra_vrf
*zvrf
;
3070 bool uj
= use_json(argc
, argv
);
3072 zvrf
= zebra_vrf_get_evpn();
3073 zebra_vxlan_print_vnis(vty
, zvrf
, uj
);
3077 DEFUN (show_evpn_vni_detail
, show_evpn_vni_detail_cmd
,
3078 "show evpn vni detail [json]",
3081 "VxLAN Network Identifier\n"
3082 "Detailed Information On Each VNI\n"
3085 struct zebra_vrf
*zvrf
;
3086 bool uj
= use_json(argc
, argv
);
3088 zvrf
= zebra_vrf_get_evpn();
3089 zebra_vxlan_print_vnis_detail(vty
, zvrf
, uj
);
3093 DEFUN (show_evpn_vni_vni
,
3094 show_evpn_vni_vni_cmd
,
3095 "show evpn vni " CMD_VNI_RANGE
"[json]",
3098 "VxLAN Network Identifier\n"
3102 struct zebra_vrf
*zvrf
;
3104 bool uj
= use_json(argc
, argv
);
3106 vni
= strtoul(argv
[3]->arg
, NULL
, 10);
3107 zvrf
= zebra_vrf_get_evpn();
3108 zebra_vxlan_print_vni(vty
, zvrf
, vni
, uj
, NULL
);
3112 DEFUN (show_evpn_rmac_vni_mac
,
3113 show_evpn_rmac_vni_mac_cmd
,
3114 "show evpn rmac vni " CMD_VNI_RANGE
" mac WORD [json]",
3121 "mac-address (e.g. 0a:0a:0a:0a:0a:0a)\n"
3126 bool uj
= use_json(argc
, argv
);
3128 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3129 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3130 vty_out(vty
, "%% Malformed MAC address\n");
3133 zebra_vxlan_print_specific_rmac_l3vni(vty
, l3vni
, &mac
, uj
);
3137 DEFUN (show_evpn_rmac_vni
,
3138 show_evpn_rmac_vni_cmd
,
3139 "show evpn rmac vni " CMD_VNI_RANGE
"[json]",
3148 bool uj
= use_json(argc
, argv
);
3150 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3151 zebra_vxlan_print_rmacs_l3vni(vty
, l3vni
, uj
);
3156 DEFUN (show_evpn_rmac_vni_all
,
3157 show_evpn_rmac_vni_all_cmd
,
3158 "show evpn rmac vni all [json]",
3166 bool uj
= use_json(argc
, argv
);
3168 zebra_vxlan_print_rmacs_all_l3vni(vty
, uj
);
3173 DEFUN (show_evpn_nh_vni_ip
,
3174 show_evpn_nh_vni_ip_cmd
,
3175 "show evpn next-hops vni " CMD_VNI_RANGE
" ip WORD [json]",
3182 "Host address (ipv4 or ipv6)\n"
3187 bool uj
= use_json(argc
, argv
);
3189 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3190 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3192 vty_out(vty
, "%% Malformed Neighbor address\n");
3195 zebra_vxlan_print_specific_nh_l3vni(vty
, l3vni
, &ip
, uj
);
3200 DEFUN_HIDDEN (show_evpn_nh_svd_ip
,
3201 show_evpn_nh_svd_ip_cmd
,
3202 "show evpn next-hops svd ip WORD [json]",
3206 "Single Vxlan Device\n"
3208 "Host address (ipv4 or ipv6)\n"
3212 bool uj
= use_json(argc
, argv
);
3214 if (str2ipaddr(argv
[5]->arg
, &ip
) != 0) {
3216 vty_out(vty
, "%% Malformed Neighbor address\n");
3219 zebra_vxlan_print_specific_nh_l3vni(vty
, 0, &ip
, uj
);
3224 DEFUN (show_evpn_nh_vni
,
3225 show_evpn_nh_vni_cmd
,
3226 "show evpn next-hops vni " CMD_VNI_RANGE
"[json]",
3235 bool uj
= use_json(argc
, argv
);
3237 l3vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3238 zebra_vxlan_print_nh_l3vni(vty
, l3vni
, uj
);
3243 DEFUN_HIDDEN (show_evpn_nh_svd
,
3244 show_evpn_nh_svd_cmd
,
3245 "show evpn next-hops svd [json]",
3249 "Single Vxlan Device\n"
3252 bool uj
= use_json(argc
, argv
);
3254 zebra_vxlan_print_nh_svd(vty
, uj
);
3259 DEFUN (show_evpn_nh_vni_all
,
3260 show_evpn_nh_vni_all_cmd
,
3261 "show evpn next-hops vni all [json]",
3269 bool uj
= use_json(argc
, argv
);
3271 zebra_vxlan_print_nh_all_l3vni(vty
, uj
);
3276 DEFUN (show_evpn_mac_vni
,
3277 show_evpn_mac_vni_cmd
,
3278 "show evpn mac vni " CMD_VNI_RANGE
"[json]",
3282 "VxLAN Network Identifier\n"
3286 struct zebra_vrf
*zvrf
;
3288 bool uj
= use_json(argc
, argv
);
3290 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3291 zvrf
= zebra_vrf_get_evpn();
3292 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, false);
3296 DEFPY (show_evpn_mac_vni_detail
,
3297 show_evpn_mac_vni_detail_cmd
,
3298 "show evpn mac vni " CMD_VNI_RANGE
" detail [json]",
3302 "VXLAN Network Identifier\n"
3304 "Detailed Information On Each VNI MAC\n"
3307 struct zebra_vrf
*zvrf
;
3308 bool uj
= use_json(argc
, argv
);
3310 zvrf
= zebra_vrf_get_evpn();
3311 zebra_vxlan_print_macs_vni(vty
, zvrf
, vni
, uj
, true);
3315 DEFUN (show_evpn_mac_vni_all
,
3316 show_evpn_mac_vni_all_cmd
,
3317 "show evpn mac vni all [json]",
3321 "VxLAN Network Identifier\n"
3325 struct zebra_vrf
*zvrf
;
3326 bool uj
= use_json(argc
, argv
);
3328 zvrf
= zebra_vrf_get_evpn();
3329 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, false, uj
);
3333 DEFUN (show_evpn_mac_vni_all_detail
, show_evpn_mac_vni_all_detail_cmd
,
3334 "show evpn mac vni all detail [json]",
3338 "VxLAN Network Identifier\n"
3340 "Detailed Information On Each VNI MAC\n"
3343 struct zebra_vrf
*zvrf
;
3344 bool uj
= use_json(argc
, argv
);
3346 zvrf
= zebra_vrf_get_evpn();
3347 zebra_vxlan_print_macs_all_vni_detail(vty
, zvrf
, false, uj
);
3351 DEFUN (show_evpn_mac_vni_all_vtep
,
3352 show_evpn_mac_vni_all_vtep_cmd
,
3353 "show evpn mac vni all vtep A.B.C.D [json]",
3357 "VxLAN Network Identifier\n"
3360 "Remote VTEP IP address\n"
3363 struct zebra_vrf
*zvrf
;
3364 struct in_addr vtep_ip
;
3365 bool uj
= use_json(argc
, argv
);
3367 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3369 vty_out(vty
, "%% Malformed VTEP IP address\n");
3372 zvrf
= zebra_vrf_get_evpn();
3373 zebra_vxlan_print_macs_all_vni_vtep(vty
, zvrf
, vtep_ip
, uj
);
3379 DEFUN (show_evpn_mac_vni_mac
,
3380 show_evpn_mac_vni_mac_cmd
,
3381 "show evpn mac vni " CMD_VNI_RANGE
" mac WORD [json]",
3385 "VxLAN Network Identifier\n"
3388 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3392 struct zebra_vrf
*zvrf
;
3395 bool uj
= use_json(argc
, argv
);
3397 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3398 if (!prefix_str2mac(argv
[6]->arg
, &mac
)) {
3399 vty_out(vty
, "%% Malformed MAC address\n");
3402 zvrf
= zebra_vrf_get_evpn();
3403 zebra_vxlan_print_specific_mac_vni(vty
, zvrf
, vni
, &mac
, uj
);
3407 DEFUN (show_evpn_mac_vni_vtep
,
3408 show_evpn_mac_vni_vtep_cmd
,
3409 "show evpn mac vni " CMD_VNI_RANGE
" vtep A.B.C.D" "[json]",
3413 "VxLAN Network Identifier\n"
3416 "Remote VTEP IP address\n"
3419 struct zebra_vrf
*zvrf
;
3421 struct in_addr vtep_ip
;
3422 bool uj
= use_json(argc
, argv
);
3424 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3425 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3427 vty_out(vty
, "%% Malformed VTEP IP address\n");
3431 zvrf
= zebra_vrf_get_evpn();
3432 zebra_vxlan_print_macs_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3436 DEFPY (show_evpn_mac_vni_all_dad
,
3437 show_evpn_mac_vni_all_dad_cmd
,
3438 "show evpn mac vni all duplicate [json]",
3442 "VxLAN Network Identifier\n"
3444 "Duplicate address list\n"
3447 struct zebra_vrf
*zvrf
;
3448 bool uj
= use_json(argc
, argv
);
3450 zvrf
= zebra_vrf_get_evpn();
3451 zebra_vxlan_print_macs_all_vni(vty
, zvrf
, true, uj
);
3456 DEFPY (show_evpn_mac_vni_dad
,
3457 show_evpn_mac_vni_dad_cmd
,
3458 "show evpn mac vni " CMD_VNI_RANGE
" duplicate [json]",
3462 "VxLAN Network Identifier\n"
3464 "Duplicate address list\n"
3467 struct zebra_vrf
*zvrf
;
3468 bool uj
= use_json(argc
, argv
);
3470 zvrf
= zebra_vrf_get_evpn();
3472 zebra_vxlan_print_macs_vni_dad(vty
, zvrf
, vni
, uj
);
3477 DEFPY (show_evpn_neigh_vni_dad
,
3478 show_evpn_neigh_vni_dad_cmd
,
3479 "show evpn arp-cache vni " CMD_VNI_RANGE
"duplicate [json]",
3482 "ARP and ND cache\n"
3483 "VxLAN Network Identifier\n"
3485 "Duplicate address list\n"
3488 struct zebra_vrf
*zvrf
;
3489 bool uj
= use_json(argc
, argv
);
3491 zvrf
= zebra_vrf_get_evpn();
3492 zebra_vxlan_print_neigh_vni_dad(vty
, zvrf
, vni
, uj
);
3496 DEFPY (show_evpn_neigh_vni_all_dad
,
3497 show_evpn_neigh_vni_all_dad_cmd
,
3498 "show evpn arp-cache vni all duplicate [json]",
3501 "ARP and ND cache\n"
3502 "VxLAN Network Identifier\n"
3504 "Duplicate address list\n"
3507 struct zebra_vrf
*zvrf
;
3508 bool uj
= use_json(argc
, argv
);
3510 zvrf
= zebra_vrf_get_evpn();
3511 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, true, uj
);
3516 DEFUN (show_evpn_neigh_vni
,
3517 show_evpn_neigh_vni_cmd
,
3518 "show evpn arp-cache vni " CMD_VNI_RANGE
"[json]",
3521 "ARP and ND cache\n"
3522 "VxLAN Network Identifier\n"
3526 struct zebra_vrf
*zvrf
;
3528 bool uj
= use_json(argc
, argv
);
3530 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3531 zvrf
= zebra_vrf_get_evpn();
3532 zebra_vxlan_print_neigh_vni(vty
, zvrf
, vni
, uj
);
3536 DEFUN (show_evpn_neigh_vni_all
,
3537 show_evpn_neigh_vni_all_cmd
,
3538 "show evpn arp-cache vni all [json]",
3541 "ARP and ND cache\n"
3542 "VxLAN Network Identifier\n"
3546 struct zebra_vrf
*zvrf
;
3547 bool uj
= use_json(argc
, argv
);
3549 zvrf
= zebra_vrf_get_evpn();
3550 zebra_vxlan_print_neigh_all_vni(vty
, zvrf
, false, uj
);
3554 DEFUN (show_evpn_neigh_vni_all_detail
, show_evpn_neigh_vni_all_detail_cmd
,
3555 "show evpn arp-cache vni all detail [json]",
3558 "ARP and ND cache\n"
3559 "VxLAN Network Identifier\n"
3561 "Neighbor details for all vnis in detail\n" JSON_STR
)
3563 struct zebra_vrf
*zvrf
;
3564 bool uj
= use_json(argc
, argv
);
3566 zvrf
= zebra_vrf_get_evpn();
3567 zebra_vxlan_print_neigh_all_vni_detail(vty
, zvrf
, false, uj
);
3571 DEFUN (show_evpn_neigh_vni_neigh
,
3572 show_evpn_neigh_vni_neigh_cmd
,
3573 "show evpn arp-cache vni " CMD_VNI_RANGE
" ip WORD [json]",
3576 "ARP and ND cache\n"
3577 "VxLAN Network Identifier\n"
3580 "Neighbor address (IPv4 or IPv6 address)\n"
3583 struct zebra_vrf
*zvrf
;
3586 bool uj
= use_json(argc
, argv
);
3588 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3589 if (str2ipaddr(argv
[6]->arg
, &ip
) != 0) {
3591 vty_out(vty
, "%% Malformed Neighbor address\n");
3594 zvrf
= zebra_vrf_get_evpn();
3595 zebra_vxlan_print_specific_neigh_vni(vty
, zvrf
, vni
, &ip
, uj
);
3599 DEFUN (show_evpn_neigh_vni_vtep
,
3600 show_evpn_neigh_vni_vtep_cmd
,
3601 "show evpn arp-cache vni " CMD_VNI_RANGE
" vtep A.B.C.D [json]",
3604 "ARP and ND cache\n"
3605 "VxLAN Network Identifier\n"
3608 "Remote VTEP IP address\n"
3611 struct zebra_vrf
*zvrf
;
3613 struct in_addr vtep_ip
;
3614 bool uj
= use_json(argc
, argv
);
3616 vni
= strtoul(argv
[4]->arg
, NULL
, 10);
3617 if (!inet_aton(argv
[6]->arg
, &vtep_ip
)) {
3619 vty_out(vty
, "%% Malformed VTEP IP address\n");
3623 zvrf
= zebra_vrf_get_evpn();
3624 zebra_vxlan_print_neigh_vni_vtep(vty
, zvrf
, vni
, vtep_ip
, uj
);
3628 /* policy routing contexts */
3629 DEFUN (show_pbr_ipset
,
3631 "show pbr ipset [WORD]",
3633 "Policy-Based Routing\n"
3634 "IPset Context information\n"
3635 "IPset Name information\n")
3639 found
= argv_find(argv
, argc
, "WORD", &idx
);
3641 zebra_pbr_show_ipset_list(vty
, NULL
);
3643 zebra_pbr_show_ipset_list(vty
, argv
[idx
]->arg
);
3647 /* policy routing contexts */
3648 DEFUN (show_pbr_iptable
,
3649 show_pbr_iptable_cmd
,
3650 "show pbr iptable [WORD]",
3652 "Policy-Based Routing\n"
3653 "IPtable Context information\n"
3654 "IPtable Name information\n")
3659 found
= argv_find(argv
, argc
, "WORD", &idx
);
3661 zebra_pbr_show_iptable(vty
, NULL
);
3663 zebra_pbr_show_iptable(vty
, argv
[idx
]->arg
);
3667 /* policy routing contexts */
3668 DEFPY (show_pbr_rule
,
3672 "Policy-Based Routing\n"
3675 zebra_pbr_show_rule(vty
);
3679 DEFPY (pbr_nexthop_resolve
,
3680 pbr_nexthop_resolve_cmd
,
3681 "[no$no] pbr nexthop-resolve",
3683 "Policy Based Routing\n"
3684 "Resolve nexthop for dataplane programming\n")
3686 zebra_pbr_expand_action_update(!no
);
3690 DEFPY (clear_evpn_dup_addr
,
3691 clear_evpn_dup_addr_cmd
,
3692 "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>]>",
3695 "Duplicate address \n"
3696 "VxLAN Network Identifier\n"
3700 "MAC address (e.g., 00:e0:ec:20:12:62)\n"
3705 struct ipaddr host_ip
= {.ipa_type
= IPADDR_NONE
};
3706 int ret
= CMD_SUCCESS
;
3708 struct yang_data
*yang_dup
= NULL
, *yang_dup_ip
= NULL
,
3709 *yang_dup_mac
= NULL
;
3714 yang_dup
= yang_data_new(
3715 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
3718 yang_dup
= yang_data_new_uint32(
3719 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
3721 if (!is_zero_mac(&mac
->eth_addr
)) {
3722 yang_dup_mac
= yang_data_new_mac(
3723 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
3726 listnode_add(input
, yang_dup_mac
);
3728 if (sockunion_family(ip
) == AF_INET
) {
3729 host_ip
.ipa_type
= IPADDR_V4
;
3730 host_ip
.ipaddr_v4
.s_addr
= sockunion2ip(ip
);
3732 host_ip
.ipa_type
= IPADDR_V6
;
3733 memcpy(&host_ip
.ipaddr_v6
, &ip
->sin6
.sin6_addr
,
3734 sizeof(struct in6_addr
));
3737 yang_dup_ip
= yang_data_new_ip(
3738 "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
3742 listnode_add(input
, yang_dup_ip
);
3747 listnode_add(input
, yang_dup
);
3748 ret
= nb_cli_rpc(vty
, "/frr-zebra:clear-evpn-dup-addr", input
,
3752 list_delete(&input
);
3757 DEFPY_HIDDEN (evpn_accept_bgp_seq
,
3758 evpn_accept_bgp_seq_cmd
,
3759 "evpn accept-bgp-seq",
3761 "Accept all sequence numbers from BGP\n")
3763 zebra_vxlan_set_accept_bgp_seq(true);
3767 DEFPY_HIDDEN (no_evpn_accept_bgp_seq
,
3768 no_evpn_accept_bgp_seq_cmd
,
3769 "no evpn accept-bgp-seq",
3772 "Accept all sequence numbers from BGP\n")
3774 zebra_vxlan_set_accept_bgp_seq(false);
3778 /* Static ip route configuration write function. */
3779 static int zebra_ip_config(struct vty
*vty
)
3783 write
+= zebra_import_table_config(vty
, VRF_DEFAULT
);
3788 DEFUN (ip_zebra_import_table_distance
,
3789 ip_zebra_import_table_distance_cmd
,
3790 "ip import-table (1-252) [distance (1-255)] [route-map RMAP_NAME]",
3792 "import routes from non-main kernel table\n"
3793 "kernel routing table id\n"
3794 "Distance for imported routes\n"
3795 "Default distance value\n"
3796 "route-map for filtering\n"
3799 uint32_t table_id
= 0;
3801 table_id
= strtoul(argv
[2]->arg
, NULL
, 10);
3802 int distance
= ZEBRA_TABLE_DISTANCE_DEFAULT
;
3804 strmatch(argv
[argc
- 2]->text
, "route-map")
3805 ? XSTRDUP(MTYPE_ROUTE_MAP_NAME
, argv
[argc
- 1]->arg
)
3809 if (argc
== 7 || (argc
== 5 && !rmap
))
3810 distance
= strtoul(argv
[4]->arg
, NULL
, 10);
3812 if (!is_zebra_valid_kernel_table(table_id
)) {
3814 "Invalid routing table ID, %d. Must be in range 1-252\n",
3817 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3821 if (is_zebra_main_routing_table(table_id
)) {
3823 "Invalid routing table ID, %d. Must be non-default table\n",
3826 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3830 ret
= zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
,
3833 XFREE(MTYPE_ROUTE_MAP_NAME
, rmap
);
3838 DEFUN_HIDDEN (zebra_packet_process
,
3839 zebra_packet_process_cmd
,
3840 "zebra zapi-packets (1-10000)",
3843 "Number of packets to process before relinquishing thread\n")
3845 uint32_t packets
= strtoul(argv
[2]->arg
, NULL
, 10);
3847 atomic_store_explicit(&zrouter
.packets_to_process
, packets
,
3848 memory_order_relaxed
);
3853 DEFUN_HIDDEN (no_zebra_packet_process
,
3854 no_zebra_packet_process_cmd
,
3855 "no zebra zapi-packets [(1-10000)]",
3859 "Number of packets to process before relinquishing thread\n")
3861 atomic_store_explicit(&zrouter
.packets_to_process
,
3862 ZEBRA_ZAPI_PACKETS_TO_PROCESS
,
3863 memory_order_relaxed
);
3868 DEFUN_HIDDEN (zebra_workqueue_timer
,
3869 zebra_workqueue_timer_cmd
,
3870 "zebra work-queue (0-10000)",
3873 "Time in milliseconds\n")
3875 uint32_t timer
= strtoul(argv
[2]->arg
, NULL
, 10);
3876 zrouter
.ribq
->spec
.hold
= timer
;
3881 DEFUN_HIDDEN (no_zebra_workqueue_timer
,
3882 no_zebra_workqueue_timer_cmd
,
3883 "no zebra work-queue [(0-10000)]",
3887 "Time in milliseconds\n")
3889 zrouter
.ribq
->spec
.hold
= ZEBRA_RIB_PROCESS_HOLD_TIME
;
3894 DEFUN (no_ip_zebra_import_table
,
3895 no_ip_zebra_import_table_cmd
,
3896 "no ip import-table (1-252) [distance (1-255)] [route-map NAME]",
3899 "import routes from non-main kernel table\n"
3900 "kernel routing table id\n"
3901 "Distance for imported routes\n"
3902 "Default distance value\n"
3903 "route-map for filtering\n"
3906 uint32_t table_id
= 0;
3907 table_id
= strtoul(argv
[3]->arg
, NULL
, 10);
3909 if (!is_zebra_valid_kernel_table(table_id
)) {
3911 "Invalid routing table ID. Must be in range 1-252\n");
3915 if (is_zebra_main_routing_table(table_id
)) {
3917 "Invalid routing table ID, %d. Must be non-default table\n",
3922 if (!is_zebra_import_table_enabled(AFI_IP
, VRF_DEFAULT
, table_id
))
3925 return (zebra_import_table(AFI_IP
, VRF_DEFAULT
, table_id
, 0, NULL
, 0));
3928 DEFPY (zebra_nexthop_group_keep
,
3929 zebra_nexthop_group_keep_cmd
,
3930 "[no] zebra nexthop-group keep (1-3600)",
3934 "How long to keep\n"
3935 "Time in seconds from 1-3600\n")
3938 zrouter
.nhg_keep
= ZEBRA_DEFAULT_NHG_KEEP_TIMER
;
3940 zrouter
.nhg_keep
= keep
;
3945 static int config_write_protocol(struct vty
*vty
)
3947 if (zrouter
.allow_delete
)
3948 vty_out(vty
, "allow-external-route-update\n");
3950 if (zrouter
.nhg_keep
!= ZEBRA_DEFAULT_NHG_KEEP_TIMER
)
3951 vty_out(vty
, "zebra nexthop-group keep %u\n", zrouter
.nhg_keep
);
3953 if (zrouter
.ribq
->spec
.hold
!= ZEBRA_RIB_PROCESS_HOLD_TIME
)
3954 vty_out(vty
, "zebra work-queue %u\n", zrouter
.ribq
->spec
.hold
);
3956 if (zrouter
.packets_to_process
!= ZEBRA_ZAPI_PACKETS_TO_PROCESS
)
3957 vty_out(vty
, "zebra zapi-packets %u\n",
3958 zrouter
.packets_to_process
);
3960 enum multicast_mode ipv4_multicast_mode
= multicast_mode_ipv4_get();
3962 if (ipv4_multicast_mode
!= MCAST_NO_CONFIG
)
3963 vty_out(vty
, "ip multicast rpf-lookup-mode %s\n",
3964 ipv4_multicast_mode
== MCAST_URIB_ONLY
3966 : ipv4_multicast_mode
== MCAST_MRIB_ONLY
3968 : ipv4_multicast_mode
3969 == MCAST_MIX_MRIB_FIRST
3971 : ipv4_multicast_mode
3972 == MCAST_MIX_DISTANCE
3976 /* Include dataplane info */
3977 dplane_config_write_helper(vty
);
3979 zebra_evpn_mh_config_write(vty
);
3981 zebra_pbr_config_write(vty
);
3983 if (!zebra_vxlan_get_accept_bgp_seq())
3984 vty_out(vty
, "no evpn accept-bgp-seq\n");
3986 /* Include nexthop-group config */
3987 if (!zebra_nhg_kernel_nexthops_enabled())
3988 vty_out(vty
, "no zebra nexthop kernel enable\n");
3990 if (zebra_nhg_proto_nexthops_only())
3991 vty_out(vty
, "zebra nexthop proto only\n");
3993 if (!zebra_nhg_recursive_use_backups())
3994 vty_out(vty
, "no zebra nexthop resolve-via-backup\n");
3996 if (rnh_get_hide_backups())
3997 vty_out(vty
, "ip nht hide-backup-events\n");
4000 /* Include netlink info */
4001 netlink_config_write_helper(vty
);
4002 #endif /* HAVE_NETLINK */
4014 struct ttable
*table
= ttable_new(&ttable_styles
[TTSTYLE_BLANK
]);
4017 ttable_rowseps(table
, 0, BOTTOM
, true, '-');
4018 ttable_add_row(table
, "OS|%s(%s)", cmd_system_get(), cmd_release_get());
4019 ttable_add_row(table
, "ECMP Maximum|%d", zrouter
.multipath_num
);
4020 ttable_add_row(table
, "v4 Forwarding|%s", ipforward() ? "On" : "Off");
4021 ttable_add_row(table
, "v6 Forwarding|%s",
4022 ipforward_ipv6() ? "On" : "Off");
4023 ttable_add_row(table
, "MPLS|%s", mpls_enabled
? "On" : "Off");
4024 ttable_add_row(table
, "EVPN|%s", is_evpn_enabled() ? "On" : "Off");
4025 ttable_add_row(table
, "Kernel socket buffer size|%d", rcvbufsize
);
4029 if (!vrf_is_backend_netns())
4030 ttable_add_row(table
, "VRF|l3mdev Available");
4032 ttable_add_row(table
, "VRF|Namespaces");
4034 ttable_add_row(table
, "VRF|Not Available");
4037 ttable_add_row(table
, "ASIC offload|%s",
4038 zrouter
.asic_offloaded
? "Used" : "Unavailable");
4041 * Do not display this unless someone is actually using it
4043 * Why this distinction? I think this is effectively dead code
4044 * and should not be exposed. Maybe someone proves me wrong.
4046 if (zrouter
.asic_notification_nexthop_control
)
4047 ttable_add_row(table
, "ASIC offload and nexthop control|Used");
4049 ttable_add_row(table
, "RA|%s",
4050 rtadv_compiled_in() ? "Compiled in" : "Not Compiled in");
4051 ttable_add_row(table
, "RFC 5549|%s",
4052 rtadv_get_interfaces_configured_from_bgp()
4054 : "BGP is not using");
4056 ttable_add_row(table
, "Kernel NHG|%s",
4057 zrouter
.supports_nhgs
? "Available" : "Unavailable");
4059 ttable_add_row(table
, "Allow Non FRR route deletion|%s",
4060 zrouter
.allow_delete
? "Yes" : "No");
4061 ttable_add_row(table
, "v4 All LinkDown Routes|%s",
4062 zrouter
.all_linkdownv4
? "On" : "Off");
4063 ttable_add_row(table
, "v4 Default LinkDown Routes|%s",
4064 zrouter
.default_linkdownv4
? "On" : "Off");
4065 ttable_add_row(table
, "v6 All LinkDown Routes|%s",
4066 zrouter
.all_linkdownv6
? "On" : "Off");
4067 ttable_add_row(table
, "v6 Default LinkDown Routes|%s",
4068 zrouter
.default_linkdownv6
? "On" : "Off");
4070 ttable_add_row(table
, "v4 All MC Forwarding|%s",
4071 zrouter
.all_mc_forwardingv4
? "On" : "Off");
4072 ttable_add_row(table
, "v4 Default MC Forwarding|%s",
4073 zrouter
.default_mc_forwardingv4
? "On" : "Off");
4074 ttable_add_row(table
, "v6 All MC Forwarding|%s",
4075 zrouter
.all_mc_forwardingv6
? "On" : "Off");
4076 ttable_add_row(table
, "v6 Default MC Forwarding|%s",
4077 zrouter
.default_mc_forwardingv6
? "On" : "Off");
4079 out
= ttable_dump(table
, "\n");
4080 vty_out(vty
, "%s\n", out
);
4081 XFREE(MTYPE_TMP
, out
);
4085 " Route Route Neighbor LSP LSP\n");
4087 "VRF Installs Removals Updates Installs Removals\n");
4089 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
4090 struct zebra_vrf
*zvrf
= vrf
->info
;
4092 vty_out(vty
, "%-25s %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
" %10" PRIu64
"\n",
4093 vrf
->name
, zvrf
->installs
, zvrf
->removals
,
4094 zvrf
->neigh_updates
, zvrf
->lsp_installs
,
4095 zvrf
->lsp_removals
);
4101 DEFUN (ip_forwarding
,
4105 "Turn on IP forwarding\n")
4111 ret
= ipforward_on();
4114 vty_out(vty
, "Can't turn on IP forwarding\n");
4115 return CMD_WARNING_CONFIG_FAILED
;
4121 DEFUN (no_ip_forwarding
,
4122 no_ip_forwarding_cmd
,
4126 "Turn off IP forwarding\n")
4132 ret
= ipforward_off();
4135 vty_out(vty
, "Can't turn off IP forwarding\n");
4136 return CMD_WARNING_CONFIG_FAILED
;
4142 /* Only display ip forwarding is enabled or not. */
4143 DEFUN (show_ip_forwarding
,
4144 show_ip_forwarding_cmd
,
4145 "show ip forwarding",
4148 "IP forwarding status\n")
4155 vty_out(vty
, "IP forwarding is off\n");
4157 vty_out(vty
, "IP forwarding is on\n");
4161 /* Only display ipv6 forwarding is enabled or not. */
4162 DEFUN (show_ipv6_forwarding
,
4163 show_ipv6_forwarding_cmd
,
4164 "show ipv6 forwarding",
4166 "IPv6 information\n"
4167 "Forwarding status\n")
4171 ret
= ipforward_ipv6();
4175 vty_out(vty
, "ipv6 forwarding is unknown\n");
4178 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4181 vty_out(vty
, "ipv6 forwarding is %s\n", "on");
4184 vty_out(vty
, "ipv6 forwarding is %s\n", "off");
4190 DEFUN (ipv6_forwarding
,
4191 ipv6_forwarding_cmd
,
4194 "Turn on IPv6 forwarding\n")
4198 ret
= ipforward_ipv6();
4200 ret
= ipforward_ipv6_on();
4203 vty_out(vty
, "Can't turn on IPv6 forwarding\n");
4204 return CMD_WARNING_CONFIG_FAILED
;
4210 DEFUN (no_ipv6_forwarding
,
4211 no_ipv6_forwarding_cmd
,
4212 "no ipv6 forwarding",
4215 "Turn off IPv6 forwarding\n")
4219 ret
= ipforward_ipv6();
4221 ret
= ipforward_ipv6_off();
4224 vty_out(vty
, "Can't turn off IPv6 forwarding\n");
4225 return CMD_WARNING_CONFIG_FAILED
;
4231 /* Display dataplane info */
4232 DEFUN (show_dataplane
,
4234 "show zebra dplane [detailed]",
4237 "Zebra dataplane information\n"
4238 "Detailed output\n")
4241 bool detailed
= false;
4243 if (argv_find(argv
, argc
, "detailed", &idx
))
4246 return dplane_show_helper(vty
, detailed
);
4249 /* Display dataplane providers info */
4250 DEFUN (show_dataplane_providers
,
4251 show_dataplane_providers_cmd
,
4252 "show zebra dplane providers [detailed]",
4255 "Zebra dataplane information\n"
4256 "Zebra dataplane provider information\n"
4257 "Detailed output\n")
4260 bool detailed
= false;
4262 if (argv_find(argv
, argc
, "detailed", &idx
))
4265 return dplane_show_provs_helper(vty
, detailed
);
4268 /* Configure dataplane incoming queue limit */
4269 DEFUN (zebra_dplane_queue_limit
,
4270 zebra_dplane_queue_limit_cmd
,
4271 "zebra dplane limit (0-10000)",
4274 "Limit incoming queued updates\n"
4275 "Number of queued updates\n")
4279 limit
= strtoul(argv
[3]->arg
, NULL
, 10);
4281 dplane_set_in_queue_limit(limit
, true);
4286 /* Reset dataplane queue limit to default value */
4287 DEFUN (no_zebra_dplane_queue_limit
,
4288 no_zebra_dplane_queue_limit_cmd
,
4289 "no zebra dplane limit [(0-10000)]",
4293 "Limit incoming queued updates\n"
4294 "Number of queued updates\n")
4296 dplane_set_in_queue_limit(0, false);
4301 DEFUN (zebra_show_routing_tables_summary
,
4302 zebra_show_routing_tables_summary_cmd
,
4303 "show zebra router table summary",
4306 "The Zebra Router Information\n"
4307 "Table Information about this Zebra Router\n"
4308 "Summary Information\n")
4310 zebra_router_show_table_summary(vty
);
4315 /* Table configuration write function. */
4316 static int config_write_table(struct vty
*vty
)
4321 /* IPForwarding configuration write function. */
4322 static int config_write_forwarding(struct vty
*vty
)
4325 vty_out(vty
, "no ip forwarding\n");
4326 if (!ipforward_ipv6())
4327 vty_out(vty
, "no ipv6 forwarding\n");
4328 vty_out(vty
, "!\n");
4332 DEFUN_HIDDEN (show_frr
,
4338 vty_out(vty
, "........ .. . .. . ..... ...77:................................................\n");
4339 vty_out(vty
, ".............................7777:..............................................\n");
4340 vty_out(vty
, ".............................777777,............................................\n");
4341 vty_out(vty
, "... .........................77777777,..........................................\n");
4342 vty_out(vty
, "............................=7777777777:........................................\n");
4343 vty_out(vty
, "........................:7777777777777777,......................................\n");
4344 vty_out(vty
, ".................... ~7777777777777?~,..........................................\n");
4345 vty_out(vty
, "...................I7777777777+.................................................\n");
4346 vty_out(vty
, "................,777777777?............ .......................................\n");
4347 vty_out(vty
, "..............:77777777?..........~?77777.......................................\n");
4348 vty_out(vty
, ".............77777777~........=7777777777.......................................\n");
4349 vty_out(vty
, ".......... +7777777,.......?7777777777777.......................................\n");
4350 vty_out(vty
, "..........7777777~......:7777777777777777......77?,.............................\n");
4351 vty_out(vty
, "........:777777?......+777777777777777777......777777I,.........................\n");
4352 vty_out(vty
, ".......?777777,.....+77777777777777777777......777777777?.......................\n");
4353 vty_out(vty
, "......?777777......7777777777777777777777......,?777777777?.....................\n");
4354 vty_out(vty
, ".....?77777?.....=7777777777777777777I~............,I7777777~...................\n");
4355 vty_out(vty
, "....+77777+.....I77777777777777777:...................+777777I..................\n");
4356 vty_out(vty
, "...~77777+.....7777777777777777=........................?777777...... .......\n");
4357 vty_out(vty
, "...77777I.....I77777777777777~.........:?................,777777.....I777.......\n");
4358 vty_out(vty
, "..777777.....I7777777777777I .......?7777..................777777.....777?......\n");
4359 vty_out(vty
, ".~77777,....=7777777777777:......,7777777..................,77777+....+777......\n");
4360 vty_out(vty
, ".77777I.....7777777777777,......777777777.......ONNNN.......=77777.....777~.....\n");
4361 vty_out(vty
, ",77777.....I777777777777,.....:7777777777......DNNNNNN.......77777+ ...7777.....\n");
4362 vty_out(vty
, "I7777I.....777777777777=.....~77777777777......NNNNNNN~......=7777I....=777.....\n");
4363 vty_out(vty
, "77777:....=777777777777.....,777777777777......$NNNNND ......:77777....:777.....\n");
4364 vty_out(vty
, "77777. ...777777777777~.....7777777777777........7DZ,........:77777.....777.....\n");
4365 vty_out(vty
, "????? . ..777777777777.....,7777777777777....................:77777I....777.....\n");
4366 vty_out(vty
, "....... ..777777777777.....+7777777777777....................=7777777+...?7.....\n");
4367 vty_out(vty
, "..........77777777777I.....I7777777777777....................7777777777:........\n");
4368 vty_out(vty
, "..........77777777777I.....?7777777777777...................~777777777777.......\n");
4369 vty_out(vty
, "..........777777777777.....~7777777777777..................,77777777777777+.....\n");
4370 vty_out(vty
, "..........777777777777......7777777777777..................77777777777777777,...\n");
4371 vty_out(vty
, "..... ....?77777777777I.....~777777777777................,777777.....,:+77777I..\n");
4372 vty_out(vty
, "........ .:777777777777,.....?77777777777...............?777777..............,:=\n");
4373 vty_out(vty
, ".......... 7777777777777..... ?7777777777.............=7777777.....~777I........\n");
4374 vty_out(vty
, "...........:777777777777I......~777777777...........I7777777~.....+777I.........\n");
4375 vty_out(vty
, "..... ......7777777777777I.......I7777777.......+777777777I......7777I..........\n");
4376 vty_out(vty
, ".............77777777777777........?77777......777777777?......=7777=...........\n");
4377 vty_out(vty
, ".............,77777777777777+.........~77......777777I,......:77777.............\n");
4378 vty_out(vty
, "..............~777777777777777~................777777......:77777=..............\n");
4379 vty_out(vty
, "...............:7777777777777777?..............:777777,.....=77=................\n");
4380 vty_out(vty
, "................,777777777777777777?,...........,777777:.....,..................\n");
4381 vty_out(vty
, "........... ......I777777777777777777777I.........777777~.......................\n");
4382 vty_out(vty
, "...................,777777777777777777777..........777777+......................\n");
4383 vty_out(vty
, ".....................+7777777777777777777...........777777?.....................\n");
4384 vty_out(vty
, ".......................=77777777777777777............777777I....................\n");
4385 vty_out(vty
, ".........................:777777777777777.............I77777I...................\n");
4386 vty_out(vty
, "............................~777777777777..............+777777..................\n");
4387 vty_out(vty
, "................................~77777777...............=777777.................\n");
4388 vty_out(vty
, ".....................................:=?I................~777777................\n");
4389 vty_out(vty
, "..........................................................:777777,..............\n");
4390 vty_out(vty
, ".... ... ... . . .... ....... ....... ....................:777777..............\n");
4396 DEFUN_HIDDEN(zebra_kernel_netlink_batch_tx_buf
,
4397 zebra_kernel_netlink_batch_tx_buf_cmd
,
4398 "zebra kernel netlink batch-tx-buf (1-1048576) (1-1048576)",
4400 "Zebra kernel interface\n"
4401 "Set Netlink parameters\n"
4402 "Set batch buffer size and send threshold\n"
4403 "Size of the buffer\n"
4406 uint32_t bufsize
= 0, threshold
= 0;
4408 bufsize
= strtoul(argv
[4]->arg
, NULL
, 10);
4409 threshold
= strtoul(argv
[5]->arg
, NULL
, 10);
4411 netlink_set_batch_buffer_size(bufsize
, threshold
, true);
4416 DEFUN_HIDDEN(no_zebra_kernel_netlink_batch_tx_buf
,
4417 no_zebra_kernel_netlink_batch_tx_buf_cmd
,
4418 "no zebra kernel netlink batch-tx-buf [(0-1048576)] [(0-1048576)]",
4420 "Zebra kernel interface\n"
4421 "Set Netlink parameters\n"
4422 "Set batch buffer size and send threshold\n"
4423 "Size of the buffer\n"
4426 netlink_set_batch_buffer_size(0, 0, false);
4431 DEFPY (zebra_protodown_bit
,
4432 zebra_protodown_bit_cmd
,
4433 "zebra protodown reason-bit (0-31)$bit",
4435 "Protodown Configuration\n"
4436 "Reason Bit used in the kernel for application\n"
4437 "Reason Bit range\n")
4439 if_netlink_set_frr_protodown_r_bit(bit
);
4443 DEFPY (no_zebra_protodown_bit
,
4444 no_zebra_protodown_bit_cmd
,
4445 "no zebra protodown reason-bit [(0-31)$bit]",
4448 "Protodown Configuration\n"
4449 "Reason Bit used in the kernel for setting protodown\n"
4450 "Reason Bit Range\n")
4452 if_netlink_unset_frr_protodown_r_bit();
4456 #endif /* HAVE_NETLINK */
4458 DEFUN(ip_table_range
, ip_table_range_cmd
,
4459 "[no] ip table range (1-4294967295) (1-4294967295)",
4461 "table configuration\n"
4462 "Configure table range\n"
4463 "Start Routing Table\n"
4464 "End Routing Table\n")
4466 ZEBRA_DECLVAR_CONTEXT_VRF(vrf
, zvrf
);
4471 if (zvrf_id(zvrf
) != VRF_DEFAULT
&& !vrf_is_backend_netns()) {
4473 "VRF subcommand does not make any sense in l3mdev based vrf's\n");
4477 if (strmatch(argv
[0]->text
, "no"))
4478 return table_manager_range(vty
, false, zvrf
, NULL
, NULL
);
4480 return table_manager_range(vty
, true, zvrf
, argv
[3]->arg
, argv
[4]->arg
);
4483 #ifdef HAVE_SCRIPTING
4485 DEFUN(zebra_on_rib_process_script
, zebra_on_rib_process_script_cmd
,
4486 "zebra on-rib-process script SCRIPT",
4488 "on_rib_process_dplane_results hook call\n"
4490 "Script name (same as filename in /etc/frr/scripts/, without .lua)\n")
4493 if (frrscript_names_set_script_name(ZEBRA_ON_RIB_PROCESS_HOOK_CALL
,
4496 vty_out(vty
, "Successfully added script %s for hook call %s\n",
4497 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4499 vty_out(vty
, "Failed to add script %s for hook call %s\n",
4500 argv
[3]->arg
, ZEBRA_ON_RIB_PROCESS_HOOK_CALL
);
4505 #endif /* HAVE_SCRIPTING */
4507 /* IP node for static routes. */
4508 static int zebra_ip_config(struct vty
*vty
);
4509 static struct cmd_node ip_node
= {
4510 .name
= "static ip",
4513 .config_write
= zebra_ip_config
,
4515 static int config_write_protocol(struct vty
*vty
);
4516 static struct cmd_node protocol_node
= {
4518 .node
= PROTOCOL_NODE
,
4520 .config_write
= config_write_protocol
,
4522 /* table node for routing tables. */
4523 static int config_write_table(struct vty
*vty
);
4524 static struct cmd_node table_node
= {
4528 .config_write
= config_write_table
,
4530 static int config_write_forwarding(struct vty
*vty
);
4531 static struct cmd_node forwarding_node
= {
4532 .name
= "forwarding",
4533 .node
= FORWARDING_NODE
,
4535 .config_write
= config_write_forwarding
,
4539 void zebra_vty_init(void)
4541 /* Install configuration write function. */
4542 install_node(&table_node
);
4543 install_node(&forwarding_node
);
4545 install_element(VIEW_NODE
, &show_ip_forwarding_cmd
);
4546 install_element(CONFIG_NODE
, &ip_forwarding_cmd
);
4547 install_element(CONFIG_NODE
, &no_ip_forwarding_cmd
);
4548 install_element(ENABLE_NODE
, &show_zebra_cmd
);
4550 install_element(VIEW_NODE
, &show_ipv6_forwarding_cmd
);
4551 install_element(CONFIG_NODE
, &ipv6_forwarding_cmd
);
4552 install_element(CONFIG_NODE
, &no_ipv6_forwarding_cmd
);
4555 zebra_route_map_init();
4557 install_node(&ip_node
);
4558 install_node(&protocol_node
);
4560 install_element(CONFIG_NODE
, &allow_external_route_update_cmd
);
4561 install_element(CONFIG_NODE
, &no_allow_external_route_update_cmd
);
4563 install_element(CONFIG_NODE
, &ip_multicast_mode_cmd
);
4564 install_element(CONFIG_NODE
, &no_ip_multicast_mode_cmd
);
4566 install_element(CONFIG_NODE
, &zebra_nexthop_group_keep_cmd
);
4567 install_element(CONFIG_NODE
, &ip_zebra_import_table_distance_cmd
);
4568 install_element(CONFIG_NODE
, &no_ip_zebra_import_table_cmd
);
4569 install_element(CONFIG_NODE
, &zebra_workqueue_timer_cmd
);
4570 install_element(CONFIG_NODE
, &no_zebra_workqueue_timer_cmd
);
4571 install_element(CONFIG_NODE
, &zebra_packet_process_cmd
);
4572 install_element(CONFIG_NODE
, &no_zebra_packet_process_cmd
);
4573 install_element(CONFIG_NODE
, &nexthop_group_use_enable_cmd
);
4574 install_element(CONFIG_NODE
, &proto_nexthop_group_only_cmd
);
4575 install_element(CONFIG_NODE
, &backup_nexthop_recursive_use_enable_cmd
);
4577 install_element(VIEW_NODE
, &show_nexthop_group_cmd
);
4578 install_element(VIEW_NODE
, &show_interface_nexthop_group_cmd
);
4580 install_element(VIEW_NODE
, &show_vrf_cmd
);
4581 install_element(VIEW_NODE
, &show_vrf_vni_cmd
);
4582 install_element(VIEW_NODE
, &show_route_cmd
);
4583 install_element(VIEW_NODE
, &show_ro_cmd
);
4584 install_element(VIEW_NODE
, &show_route_detail_cmd
);
4585 install_element(VIEW_NODE
, &show_route_summary_cmd
);
4586 install_element(VIEW_NODE
, &show_ip_nht_cmd
);
4588 install_element(VIEW_NODE
, &show_ip_rpf_cmd
);
4589 install_element(VIEW_NODE
, &show_ip_rpf_addr_cmd
);
4591 install_element(CONFIG_NODE
, &ip_nht_default_route_cmd
);
4592 install_element(CONFIG_NODE
, &no_ip_nht_default_route_cmd
);
4593 install_element(CONFIG_NODE
, &ipv6_nht_default_route_cmd
);
4594 install_element(CONFIG_NODE
, &no_ipv6_nht_default_route_cmd
);
4595 install_element(VRF_NODE
, &ip_nht_default_route_cmd
);
4596 install_element(VRF_NODE
, &no_ip_nht_default_route_cmd
);
4597 install_element(VRF_NODE
, &ipv6_nht_default_route_cmd
);
4598 install_element(VRF_NODE
, &no_ipv6_nht_default_route_cmd
);
4599 install_element(CONFIG_NODE
, &rnh_hide_backups_cmd
);
4601 install_element(VIEW_NODE
, &show_frr_cmd
);
4602 install_element(VIEW_NODE
, &show_evpn_global_cmd
);
4603 install_element(VIEW_NODE
, &show_evpn_vni_cmd
);
4604 install_element(VIEW_NODE
, &show_evpn_vni_detail_cmd
);
4605 install_element(VIEW_NODE
, &show_evpn_vni_vni_cmd
);
4606 install_element(VIEW_NODE
, &show_evpn_l2_nh_cmd
);
4607 install_element(VIEW_NODE
, &show_evpn_es_cmd
);
4608 install_element(VIEW_NODE
, &show_evpn_es_evi_cmd
);
4609 install_element(VIEW_NODE
, &show_evpn_access_vlan_cmd
);
4610 install_element(VIEW_NODE
, &show_evpn_rmac_vni_mac_cmd
);
4611 install_element(VIEW_NODE
, &show_evpn_rmac_vni_cmd
);
4612 install_element(VIEW_NODE
, &show_evpn_rmac_vni_all_cmd
);
4613 install_element(VIEW_NODE
, &show_evpn_nh_vni_ip_cmd
);
4614 install_element(VIEW_NODE
, &show_evpn_nh_svd_ip_cmd
);
4615 install_element(VIEW_NODE
, &show_evpn_nh_vni_cmd
);
4616 install_element(VIEW_NODE
, &show_evpn_nh_svd_cmd
);
4617 install_element(VIEW_NODE
, &show_evpn_nh_vni_all_cmd
);
4618 install_element(VIEW_NODE
, &show_evpn_mac_vni_cmd
);
4619 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_cmd
);
4620 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_detail_cmd
);
4621 install_element(VIEW_NODE
, &show_evpn_mac_vni_detail_cmd
);
4622 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_vtep_cmd
);
4623 install_element(VIEW_NODE
, &show_evpn_mac_vni_mac_cmd
);
4624 install_element(VIEW_NODE
, &show_evpn_mac_vni_vtep_cmd
);
4625 install_element(VIEW_NODE
, &show_evpn_mac_vni_dad_cmd
);
4626 install_element(VIEW_NODE
, &show_evpn_mac_vni_all_dad_cmd
);
4627 install_element(VIEW_NODE
, &show_evpn_neigh_vni_cmd
);
4628 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_cmd
);
4629 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_detail_cmd
);
4630 install_element(VIEW_NODE
, &show_evpn_neigh_vni_neigh_cmd
);
4631 install_element(VIEW_NODE
, &show_evpn_neigh_vni_vtep_cmd
);
4632 install_element(VIEW_NODE
, &show_evpn_neigh_vni_dad_cmd
);
4633 install_element(VIEW_NODE
, &show_evpn_neigh_vni_all_dad_cmd
);
4634 install_element(ENABLE_NODE
, &clear_evpn_dup_addr_cmd
);
4635 install_element(CONFIG_NODE
, &evpn_accept_bgp_seq_cmd
);
4636 install_element(CONFIG_NODE
, &no_evpn_accept_bgp_seq_cmd
);
4638 install_element(VIEW_NODE
, &show_neigh_cmd
);
4640 install_element(VIEW_NODE
, &show_pbr_ipset_cmd
);
4641 install_element(VIEW_NODE
, &show_pbr_iptable_cmd
);
4642 install_element(VIEW_NODE
, &show_pbr_rule_cmd
);
4643 install_element(CONFIG_NODE
, &pbr_nexthop_resolve_cmd
);
4644 install_element(VIEW_NODE
, &show_route_zebra_dump_cmd
);
4646 install_element(CONFIG_NODE
, &evpn_mh_mac_holdtime_cmd
);
4647 install_element(CONFIG_NODE
, &evpn_mh_neigh_holdtime_cmd
);
4648 install_element(CONFIG_NODE
, &evpn_mh_startup_delay_cmd
);
4649 install_element(CONFIG_NODE
, &evpn_mh_redirect_off_cmd
);
4650 install_element(CONFIG_NODE
, &default_vrf_vni_mapping_cmd
);
4651 install_element(CONFIG_NODE
, &no_default_vrf_vni_mapping_cmd
);
4652 install_element(VRF_NODE
, &vrf_vni_mapping_cmd
);
4653 install_element(VRF_NODE
, &no_vrf_vni_mapping_cmd
);
4655 install_element(VIEW_NODE
, &show_dataplane_cmd
);
4656 install_element(VIEW_NODE
, &show_dataplane_providers_cmd
);
4657 install_element(CONFIG_NODE
, &zebra_dplane_queue_limit_cmd
);
4658 install_element(CONFIG_NODE
, &no_zebra_dplane_queue_limit_cmd
);
4660 install_element(CONFIG_NODE
, &ip_table_range_cmd
);
4661 install_element(VRF_NODE
, &ip_table_range_cmd
);
4664 install_element(CONFIG_NODE
, &zebra_kernel_netlink_batch_tx_buf_cmd
);
4665 install_element(CONFIG_NODE
, &no_zebra_kernel_netlink_batch_tx_buf_cmd
);
4666 install_element(CONFIG_NODE
, &zebra_protodown_bit_cmd
);
4667 install_element(CONFIG_NODE
, &no_zebra_protodown_bit_cmd
);
4668 #endif /* HAVE_NETLINK */
4670 #ifdef HAVE_SCRIPTING
4671 install_element(CONFIG_NODE
, &zebra_on_rib_process_script_cmd
);
4672 #endif /* HAVE_SCRIPTING */
4674 install_element(VIEW_NODE
, &zebra_show_routing_tables_summary_cmd
);